diff options
author | Mark Brown <broonie@kernel.org> | 2019-09-09 09:55:20 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-09-09 09:55:20 -0400 |
commit | bb831786117519fc16dfd3eaa7b84e4f6bbb8d99 (patch) | |
tree | 18f8333bbaf6918a0246113eeb0f056011e436f2 | |
parent | 6652ddbb5d83ecfc2591b92be063519714e40ebf (diff) | |
parent | 6fa5963c37a2e3335eba0b7455e35a01318ebc15 (diff) |
Merge branch 'asoc-5.4' into asoc-next
272 files changed, 12088 insertions, 6831 deletions
diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml new file mode 100644 index 000000000000..3248595dc93c --- /dev/null +++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml | |||
@@ -0,0 +1,88 @@ | |||
1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
2 | %YAML 1.2 | ||
3 | --- | ||
4 | $id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml# | ||
5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
6 | |||
7 | title: NXP i.MX8 DSP core | ||
8 | |||
9 | maintainers: | ||
10 | - Daniel Baluta <daniel.baluta@nxp.com> | ||
11 | |||
12 | description: | | ||
13 | Some boards from i.MX8 family contain a DSP core used for | ||
14 | advanced pre- and post- audio processing. | ||
15 | |||
16 | properties: | ||
17 | compatible: | ||
18 | enum: | ||
19 | - fsl,imx8qxp-dsp | ||
20 | |||
21 | reg: | ||
22 | description: Should contain register location and length | ||
23 | |||
24 | clocks: | ||
25 | items: | ||
26 | - description: ipg clock | ||
27 | - description: ocram clock | ||
28 | - description: core clock | ||
29 | |||
30 | clock-names: | ||
31 | items: | ||
32 | - const: ipg | ||
33 | - const: ocram | ||
34 | - const: core | ||
35 | |||
36 | power-domains: | ||
37 | description: | ||
38 | List of phandle and PM domain specifier as documented in | ||
39 | Documentation/devicetree/bindings/power/power_domain.txt | ||
40 | maxItems: 4 | ||
41 | |||
42 | mboxes: | ||
43 | description: | ||
44 | List of <&phandle type channel> - 2 channels for TXDB, 2 channels for RXDB | ||
45 | (see mailbox/fsl,mu.txt) | ||
46 | maxItems: 4 | ||
47 | |||
48 | mbox-names: | ||
49 | items: | ||
50 | - const: txdb0 | ||
51 | - const: txdb1 | ||
52 | - const: rxdb0 | ||
53 | - const: rxdb1 | ||
54 | |||
55 | memory-region: | ||
56 | description: | ||
57 | phandle to a node describing reserved memory (System RAM memory) | ||
58 | used by DSP (see bindings/reserved-memory/reserved-memory.txt) | ||
59 | maxItems: 1 | ||
60 | |||
61 | required: | ||
62 | - compatible | ||
63 | - reg | ||
64 | - clocks | ||
65 | - clock-names | ||
66 | - power-domains | ||
67 | - mboxes | ||
68 | - mbox-names | ||
69 | - memory-region | ||
70 | |||
71 | examples: | ||
72 | - | | ||
73 | #include <dt-bindings/firmware/imx/rsrc.h> | ||
74 | #include <dt-bindings/clock/imx8-clock.h> | ||
75 | dsp@596e8000 { | ||
76 | compatible = "fsl,imx8qxp-dsp"; | ||
77 | reg = <0x596e8000 0x88000>; | ||
78 | clocks = <&adma_lpcg IMX_ADMA_LPCG_DSP_IPG_CLK>, | ||
79 | <&adma_lpcg IMX_ADMA_LPCG_OCRAM_IPG_CLK>, | ||
80 | <&adma_lpcg IMX_ADMA_LPCG_DSP_CORE_CLK>; | ||
81 | clock-names = "ipg", "ocram", "core"; | ||
82 | power-domains = <&pd IMX_SC_R_MU_13A>, | ||
83 | <&pd IMX_SC_R_MU_13B>, | ||
84 | <&pd IMX_SC_R_DSP>, | ||
85 | <&pd IMX_SC_R_DSP_RAM>; | ||
86 | mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1"; | ||
87 | mboxes = <&lsio_mu13 2 0>, <&lsio_mu13 2 1>, <&lsio_mu13 3 0>, <&lsio_mu13 3 1>; | ||
88 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml index e0284d8c3b63..38d4cede0860 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml | |||
@@ -70,7 +70,9 @@ allOf: | |||
70 | properties: | 70 | properties: |
71 | compatible: | 71 | compatible: |
72 | contains: | 72 | contains: |
73 | const: allwinner,sun8i-h3-spdif | 73 | enum: |
74 | - allwinner,sun8i-h3-spdif | ||
75 | - allwinner,sun50i-h6-spdif | ||
74 | 76 | ||
75 | then: | 77 | then: |
76 | properties: | 78 | properties: |
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun50i-a64-codec-analog.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun50i-a64-codec-analog.yaml new file mode 100644 index 000000000000..f290eb72a878 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/allwinner,sun50i-a64-codec-analog.yaml | |||
@@ -0,0 +1,39 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | %YAML 1.2 | ||
3 | --- | ||
4 | $id: http://devicetree.org/schemas/sound/allwinner,sun50i-a64-codec-analog.yaml# | ||
5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
6 | |||
7 | title: Allwinner A64 Analog Codec Device Tree Bindings | ||
8 | |||
9 | maintainers: | ||
10 | - Chen-Yu Tsai <wens@csie.org> | ||
11 | - Maxime Ripard <maxime.ripard@bootlin.com> | ||
12 | |||
13 | properties: | ||
14 | compatible: | ||
15 | const: allwinner,sun50i-a64-codec-analog | ||
16 | |||
17 | reg: | ||
18 | maxItems: 1 | ||
19 | |||
20 | cpvdd-supply: | ||
21 | description: | ||
22 | Regulator for the headphone amplifier | ||
23 | |||
24 | required: | ||
25 | - compatible | ||
26 | - reg | ||
27 | - cpvdd-supply | ||
28 | |||
29 | additionalProperties: false | ||
30 | |||
31 | examples: | ||
32 | - | | ||
33 | codec_analog: codec-analog@1f015c0 { | ||
34 | compatible = "allwinner,sun50i-a64-codec-analog"; | ||
35 | reg = <0x01f015c0 0x4>; | ||
36 | cpvdd-supply = <®_eldo1>; | ||
37 | }; | ||
38 | |||
39 | ... | ||
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml new file mode 100644 index 000000000000..5e7cc05bbff1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml | |||
@@ -0,0 +1,57 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | %YAML 1.2 | ||
3 | --- | ||
4 | $id: http://devicetree.org/schemas/sound/allwinner,sun8i-a33-codec.yaml# | ||
5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
6 | |||
7 | title: Allwinner A33 Codec Device Tree Bindings | ||
8 | |||
9 | maintainers: | ||
10 | - Chen-Yu Tsai <wens@csie.org> | ||
11 | - Maxime Ripard <maxime.ripard@bootlin.com> | ||
12 | |||
13 | properties: | ||
14 | "#sound-dai-cells": | ||
15 | const: 0 | ||
16 | |||
17 | compatible: | ||
18 | const: allwinner,sun8i-a33-codec | ||
19 | |||
20 | reg: | ||
21 | maxItems: 1 | ||
22 | |||
23 | interrupts: | ||
24 | maxItems: 1 | ||
25 | |||
26 | clocks: | ||
27 | items: | ||
28 | - description: Bus Clock | ||
29 | - description: Module Clock | ||
30 | |||
31 | clock-names: | ||
32 | items: | ||
33 | - const: bus | ||
34 | - const: mod | ||
35 | |||
36 | required: | ||
37 | - "#sound-dai-cells" | ||
38 | - compatible | ||
39 | - reg | ||
40 | - interrupts | ||
41 | - clocks | ||
42 | - clock-names | ||
43 | |||
44 | additionalProperties: false | ||
45 | |||
46 | examples: | ||
47 | - | | ||
48 | audio-codec@1c22e00 { | ||
49 | #sound-dai-cells = <0>; | ||
50 | compatible = "allwinner,sun8i-a33-codec"; | ||
51 | reg = <0x01c22e00 0x400>; | ||
52 | interrupts = <0 29 4>; | ||
53 | clocks = <&ccu 47>, <&ccu 92>; | ||
54 | clock-names = "bus", "mod"; | ||
55 | }; | ||
56 | |||
57 | ... | ||
diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt index 4330fc9dca6d..3080979350a0 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt | |||
@@ -4,13 +4,18 @@ Required properties: | |||
4 | - compatible: 'amlogic,axg-toddr' or | 4 | - compatible: 'amlogic,axg-toddr' or |
5 | 'amlogic,axg-toddr' or | 5 | 'amlogic,axg-toddr' or |
6 | 'amlogic,g12a-frddr' or | 6 | 'amlogic,g12a-frddr' or |
7 | 'amlogic,g12a-toddr' | 7 | 'amlogic,g12a-toddr' or |
8 | 'amlogic,sm1-frddr' or | ||
9 | 'amlogic,sm1-toddr' | ||
8 | - reg: physical base address of the controller and length of memory | 10 | - reg: physical base address of the controller and length of memory |
9 | mapped region. | 11 | mapped region. |
10 | - interrupts: interrupt specifier for the fifo. | 12 | - interrupts: interrupt specifier for the fifo. |
11 | - clocks: phandle to the fifo peripheral clock provided by the audio | 13 | - clocks: phandle to the fifo peripheral clock provided by the audio |
12 | clock controller. | 14 | clock controller. |
13 | - resets: phandle to memory ARB line provided by the arb reset controller. | 15 | - resets: list of reset phandle, one for each entry reset-names. |
16 | - reset-names: should contain the following: | ||
17 | * "arb" : memory ARB line (required) | ||
18 | * "rst" : dedicated device reset line (optional) | ||
14 | - #sound-dai-cells: must be 0. | 19 | - #sound-dai-cells: must be 0. |
15 | 20 | ||
16 | Example of FRDDR A on the A113 SoC: | 21 | Example of FRDDR A on the A113 SoC: |
diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.txt index 73f473a9365f..716878107a24 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.txt | |||
@@ -2,7 +2,8 @@ | |||
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: 'amlogic,axg-pdm' or | 4 | - compatible: 'amlogic,axg-pdm' or |
5 | 'amlogic,g12a-pdm' | 5 | 'amlogic,g12a-pdm' or |
6 | 'amlogic,sm1-pdm' | ||
6 | - reg: physical base address of the controller and length of memory | 7 | - reg: physical base address of the controller and length of memory |
7 | mapped region. | 8 | mapped region. |
8 | - clocks: list of clock phandle, one for each entry clock-names. | 9 | - clocks: list of clock phandle, one for each entry clock-names. |
@@ -12,6 +13,9 @@ Required properties: | |||
12 | * "sysclk" : dsp system clock | 13 | * "sysclk" : dsp system clock |
13 | - #sound-dai-cells: must be 0. | 14 | - #sound-dai-cells: must be 0. |
14 | 15 | ||
16 | Optional property: | ||
17 | - resets: phandle to the dedicated reset line of the pdm input. | ||
18 | |||
15 | Example of PDM on the A113 SoC: | 19 | Example of PDM on the A113 SoC: |
16 | 20 | ||
17 | pdm: audio-controller@ff632000 { | 21 | pdm: audio-controller@ff632000 { |
diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-spdifin.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-spdifin.txt index 0b82504fa419..df92a4ecf288 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-spdifin.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-spdifin.txt | |||
@@ -2,7 +2,8 @@ | |||
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: 'amlogic,axg-spdifin' or | 4 | - compatible: 'amlogic,axg-spdifin' or |
5 | 'amlogic,g12a-spdifin' | 5 | 'amlogic,g12a-spdifin' or |
6 | 'amlogic,sm1-spdifin' | ||
6 | - interrupts: interrupt specifier for the spdif input. | 7 | - interrupts: interrupt specifier for the spdif input. |
7 | - clocks: list of clock phandle, one for each entry clock-names. | 8 | - clocks: list of clock phandle, one for each entry clock-names. |
8 | - clock-names: should contain the following: | 9 | - clock-names: should contain the following: |
@@ -10,6 +11,9 @@ Required properties: | |||
10 | * "refclk" : spdif input reference clock | 11 | * "refclk" : spdif input reference clock |
11 | - #sound-dai-cells: must be 0. | 12 | - #sound-dai-cells: must be 0. |
12 | 13 | ||
14 | Optional property: | ||
15 | - resets: phandle to the dedicated reset line of the spdif input. | ||
16 | |||
13 | Example on the A113 SoC: | 17 | Example on the A113 SoC: |
14 | 18 | ||
15 | spdifin: audio-controller@400 { | 19 | spdifin: audio-controller@400 { |
diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-spdifout.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-spdifout.txt index 826152730508..28381dd1f633 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-spdifout.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-spdifout.txt | |||
@@ -2,13 +2,17 @@ | |||
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: 'amlogic,axg-spdifout' or | 4 | - compatible: 'amlogic,axg-spdifout' or |
5 | 'amlogic,g12a-spdifout' | 5 | 'amlogic,g12a-spdifout' or |
6 | 'amlogic,sm1-spdifout' | ||
6 | - clocks: list of clock phandle, one for each entry clock-names. | 7 | - clocks: list of clock phandle, one for each entry clock-names. |
7 | - clock-names: should contain the following: | 8 | - clock-names: should contain the following: |
8 | * "pclk" : peripheral clock. | 9 | * "pclk" : peripheral clock. |
9 | * "mclk" : master clock | 10 | * "mclk" : master clock |
10 | - #sound-dai-cells: must be 0. | 11 | - #sound-dai-cells: must be 0. |
11 | 12 | ||
13 | Optional property: | ||
14 | - resets: phandle to the dedicated reset line of the spdif output. | ||
15 | |||
12 | Example on the A113 SoC: | 16 | Example on the A113 SoC: |
13 | 17 | ||
14 | spdifout: audio-controller@480 { | 18 | spdifout: audio-controller@480 { |
diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt index 8835a43edfbb..5996c0cd89c2 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-tdm-formatters.txt | |||
@@ -4,7 +4,9 @@ Required properties: | |||
4 | - compatible: 'amlogic,axg-tdmin' or | 4 | - compatible: 'amlogic,axg-tdmin' or |
5 | 'amlogic,axg-tdmout' or | 5 | 'amlogic,axg-tdmout' or |
6 | 'amlogic,g12a-tdmin' or | 6 | 'amlogic,g12a-tdmin' or |
7 | 'amlogic,g12a-tdmout' | 7 | 'amlogic,g12a-tdmout' or |
8 | 'amlogic,sm1-tdmin' or | ||
9 | 'amlogic,sm1-tdmout | ||
8 | - reg: physical base address of the controller and length of memory | 10 | - reg: physical base address of the controller and length of memory |
9 | mapped region. | 11 | mapped region. |
10 | - clocks: list of clock phandle, one for each entry clock-names. | 12 | - clocks: list of clock phandle, one for each entry clock-names. |
diff --git a/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt b/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt index aa6c35570d31..4e8cd7eb7cec 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt | |||
@@ -1,10 +1,12 @@ | |||
1 | * Amlogic HDMI Tx control glue | 1 | * Amlogic HDMI Tx control glue |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: "amlogic,g12a-tohdmitx" | 4 | - compatible: "amlogic,g12a-tohdmitx" or |
5 | "amlogic,sm1-tohdmitx" | ||
5 | - reg: physical base address of the controller and length of memory | 6 | - reg: physical base address of the controller and length of memory |
6 | mapped region. | 7 | mapped region. |
7 | - #sound-dai-cells: should be 1. | 8 | - #sound-dai-cells: should be 1. |
9 | - resets: phandle to the dedicated reset line of the hdmitx glue. | ||
8 | 10 | ||
9 | Example on the S905X2 SoC: | 11 | Example on the S905X2 SoC: |
10 | 12 | ||
@@ -12,6 +14,7 @@ tohdmitx: audio-controller@744 { | |||
12 | compatible = "amlogic,g12a-tohdmitx"; | 14 | compatible = "amlogic,g12a-tohdmitx"; |
13 | reg = <0x0 0x744 0x0 0x4>; | 15 | reg = <0x0 0x744 0x0 0x4>; |
14 | #sound-dai-cells = <1>; | 16 | #sound-dai-cells = <1>; |
17 | resets = <&clkc_audio AUD_RESET_TOHDMITX>; | ||
15 | }; | 18 | }; |
16 | 19 | ||
17 | Example of an 'amlogic,axg-sound-card': | 20 | Example of an 'amlogic,axg-sound-card': |
diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.txt b/Documentation/devicetree/bindings/sound/everest,es8316.txt new file mode 100644 index 000000000000..1bf03c5f2af4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/everest,es8316.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | Everest ES8316 audio CODEC | ||
2 | |||
3 | This device supports both I2C and SPI. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : should be "everest,es8316" | ||
8 | - reg : the I2C address of the device for I2C | ||
9 | |||
10 | Optional properties: | ||
11 | |||
12 | - clocks : a list of phandle, should contain entries for clock-names | ||
13 | - clock-names : should include as follows: | ||
14 | "mclk" : master clock (MCLK) of the device | ||
15 | |||
16 | Example: | ||
17 | |||
18 | es8316: codec@11 { | ||
19 | compatible = "everest,es8316"; | ||
20 | reg = <0x11>; | ||
21 | clocks = <&clks 10>; | ||
22 | clock-names = "mclk"; | ||
23 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index 5b9914367610..0e6e2166f76c 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt | |||
@@ -7,8 +7,11 @@ other DSPs. It has up to six transmitters and four receivers. | |||
7 | 7 | ||
8 | Required properties: | 8 | Required properties: |
9 | 9 | ||
10 | - compatible : Compatible list, must contain "fsl,imx35-esai" or | 10 | - compatible : Compatible list, should contain one of the following |
11 | "fsl,vf610-esai" | 11 | compatibles: |
12 | "fsl,imx35-esai", | ||
13 | "fsl,vf610-esai", | ||
14 | "fsl,imx6ull-esai", | ||
12 | 15 | ||
13 | - reg : Offset and length of the register set for the device. | 16 | - reg : Offset and length of the register set for the device. |
14 | 17 | ||
diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt index 2e726b983845..0dc83cc4a236 100644 --- a/Documentation/devicetree/bindings/sound/fsl-sai.txt +++ b/Documentation/devicetree/bindings/sound/fsl-sai.txt | |||
@@ -8,7 +8,9 @@ codec/DSP interfaces. | |||
8 | Required properties: | 8 | Required properties: |
9 | 9 | ||
10 | - compatible : Compatible list, contains "fsl,vf610-sai", | 10 | - compatible : Compatible list, contains "fsl,vf610-sai", |
11 | "fsl,imx6sx-sai" or "fsl,imx6ul-sai" | 11 | "fsl,imx6sx-sai", "fsl,imx6ul-sai", |
12 | "fsl,imx7ulp-sai", "fsl,imx8mq-sai" or | ||
13 | "fsl,imx8qm-sai". | ||
12 | 14 | ||
13 | - reg : Offset and length of the register set for the device. | 15 | - reg : Offset and length of the register set for the device. |
14 | 16 | ||
diff --git a/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt b/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt deleted file mode 100644 index 056a098495cc..000000000000 --- a/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | * Allwinner A64 Codec Analog Controls | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: must be one of the following compatibles: | ||
5 | - "allwinner,sun50i-a64-codec-analog" | ||
6 | - reg: must contain the registers location and length | ||
7 | - cpvdd-supply: Regulator supply for the headphone amplifier | ||
8 | |||
9 | Example: | ||
10 | codec_analog: codec-analog@1f015c0 { | ||
11 | compatible = "allwinner,sun50i-a64-codec-analog"; | ||
12 | reg = <0x01f015c0 0x4>; | ||
13 | cpvdd-supply = <®_eldo1>; | ||
14 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt b/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt deleted file mode 100644 index 2ca3d138528e..000000000000 --- a/Documentation/devicetree/bindings/sound/sun8i-a33-codec.txt +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | Allwinner SUN8I audio codec | ||
2 | ------------------------------------ | ||
3 | |||
4 | On Sun8i-A33 SoCs, the audio is separated in different parts: | ||
5 | - A DAI driver. It uses the "sun4i-i2s" driver which is | ||
6 | documented here: | ||
7 | Documentation/devicetree/bindings/sound/sun4i-i2s.txt | ||
8 | - An analog part of the codec which is handled as PRCM registers. | ||
9 | See Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt | ||
10 | - An digital part of the codec which is documented in this current | ||
11 | binding documentation. | ||
12 | - And finally, an audio card which links all the above components. | ||
13 | The simple-audio card will be used. | ||
14 | See Documentation/devicetree/bindings/sound/simple-card.txt | ||
15 | |||
16 | This bindings documentation exposes Sun8i codec (digital part). | ||
17 | |||
18 | Required properties: | ||
19 | - compatible: must be "allwinner,sun8i-a33-codec" | ||
20 | - reg: must contain the registers location and length | ||
21 | - interrupts: must contain the codec interrupt | ||
22 | - clocks: a list of phandle + clock-specifer pairs, one for each entry | ||
23 | in clock-names. | ||
24 | - clock-names: should contain followings: | ||
25 | - "bus": the parent APB clock for this controller | ||
26 | - "mod": the parent module clock | ||
27 | |||
28 | Here is an example to add a sound card and the codec binding on sun8i SoCs that | ||
29 | are similar to A33 using simple-card: | ||
30 | |||
31 | sound { | ||
32 | compatible = "simple-audio-card"; | ||
33 | simple-audio-card,name = "sun8i-a33-audio"; | ||
34 | simple-audio-card,format = "i2s"; | ||
35 | simple-audio-card,frame-master = <&link_codec>; | ||
36 | simple-audio-card,bitclock-master = <&link_codec>; | ||
37 | simple-audio-card,mclk-fs = <512>; | ||
38 | simple-audio-card,aux-devs = <&codec_analog>; | ||
39 | simple-audio-card,routing = | ||
40 | "Left DAC", "Digital Left DAC", | ||
41 | "Right DAC", "Digital Right DAC"; | ||
42 | |||
43 | simple-audio-card,cpu { | ||
44 | sound-dai = <&dai>; | ||
45 | }; | ||
46 | |||
47 | link_codec: simple-audio-card,codec { | ||
48 | sound-dai = <&codec>; | ||
49 | }; | ||
50 | |||
51 | soc@1c00000 { | ||
52 | [...] | ||
53 | |||
54 | audio-codec@1c22e00 { | ||
55 | #sound-dai-cells = <0>; | ||
56 | compatible = "allwinner,sun8i-a33-codec"; | ||
57 | reg = <0x01c22e00 0x400>; | ||
58 | interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; | ||
59 | clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>; | ||
60 | clock-names = "bus", "mod"; | ||
61 | }; | ||
62 | }; | ||
63 | |||
diff --git a/Documentation/devicetree/bindings/sound/uda1334.txt b/Documentation/devicetree/bindings/sound/uda1334.txt new file mode 100644 index 000000000000..f64071b25e8d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/uda1334.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | UDA1334 audio CODEC | ||
2 | |||
3 | This device uses simple GPIO pins for controlling codec settings. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "nxp,uda1334" | ||
8 | - nxp,mute-gpios: a GPIO spec for the MUTE pin. | ||
9 | - nxp,deemph-gpios: a GPIO spec for the De-emphasis pin | ||
10 | |||
11 | Example: | ||
12 | |||
13 | uda1334: audio-codec { | ||
14 | compatible = "nxp,uda1334"; | ||
15 | nxp,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; | ||
16 | nxp,deemph-gpios = <&gpio3 3 GPIO_ACTIVE_LOW>; | ||
17 | }; | ||
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 612a17e375d0..4af4af55e854 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h | |||
@@ -253,24 +253,6 @@ struct hdac_ext_bus_ops { | |||
253 | int (*hdev_detach)(struct hdac_device *hdev); | 253 | int (*hdev_detach)(struct hdac_device *hdev); |
254 | }; | 254 | }; |
255 | 255 | ||
256 | /* | ||
257 | * Lowlevel I/O operators | ||
258 | */ | ||
259 | struct hdac_io_ops { | ||
260 | /* mapped register accesses */ | ||
261 | void (*reg_writel)(u32 value, u32 __iomem *addr); | ||
262 | u32 (*reg_readl)(u32 __iomem *addr); | ||
263 | void (*reg_writew)(u16 value, u16 __iomem *addr); | ||
264 | u16 (*reg_readw)(u16 __iomem *addr); | ||
265 | void (*reg_writeb)(u8 value, u8 __iomem *addr); | ||
266 | u8 (*reg_readb)(u8 __iomem *addr); | ||
267 | /* Allocation ops */ | ||
268 | int (*dma_alloc_pages)(struct hdac_bus *bus, int type, size_t size, | ||
269 | struct snd_dma_buffer *buf); | ||
270 | void (*dma_free_pages)(struct hdac_bus *bus, | ||
271 | struct snd_dma_buffer *buf); | ||
272 | }; | ||
273 | |||
274 | #define HDA_UNSOL_QUEUE_SIZE 64 | 256 | #define HDA_UNSOL_QUEUE_SIZE 64 |
275 | #define HDA_MAX_CODECS 8 /* limit by controller side */ | 257 | #define HDA_MAX_CODECS 8 /* limit by controller side */ |
276 | 258 | ||
@@ -304,7 +286,6 @@ struct hdac_rb { | |||
304 | struct hdac_bus { | 286 | struct hdac_bus { |
305 | struct device *dev; | 287 | struct device *dev; |
306 | const struct hdac_bus_ops *ops; | 288 | const struct hdac_bus_ops *ops; |
307 | const struct hdac_io_ops *io_ops; | ||
308 | const struct hdac_ext_bus_ops *ext_ops; | 289 | const struct hdac_ext_bus_ops *ext_ops; |
309 | 290 | ||
310 | /* h/w resources */ | 291 | /* h/w resources */ |
@@ -344,6 +325,7 @@ struct hdac_bus { | |||
344 | /* CORB/RIRB and position buffers */ | 325 | /* CORB/RIRB and position buffers */ |
345 | struct snd_dma_buffer rb; | 326 | struct snd_dma_buffer rb; |
346 | struct snd_dma_buffer posbuf; | 327 | struct snd_dma_buffer posbuf; |
328 | int dma_type; /* SNDRV_DMA_TYPE_XXX for CORB/RIRB */ | ||
347 | 329 | ||
348 | /* hdac_stream linked list */ | 330 | /* hdac_stream linked list */ |
349 | struct list_head stream_list; | 331 | struct list_head stream_list; |
@@ -384,8 +366,7 @@ struct hdac_bus { | |||
384 | }; | 366 | }; |
385 | 367 | ||
386 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | 368 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, |
387 | const struct hdac_bus_ops *ops, | 369 | const struct hdac_bus_ops *ops); |
388 | const struct hdac_io_ops *io_ops); | ||
389 | void snd_hdac_bus_exit(struct hdac_bus *bus); | 370 | void snd_hdac_bus_exit(struct hdac_bus *bus); |
390 | int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, | 371 | int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, |
391 | unsigned int cmd, unsigned int *res); | 372 | unsigned int cmd, unsigned int *res); |
@@ -429,21 +410,38 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, | |||
429 | int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus); | 410 | int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus); |
430 | void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus); | 411 | void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus); |
431 | 412 | ||
413 | #ifdef CONFIG_SND_HDA_ALIGNED_MMIO | ||
414 | unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask); | ||
415 | void snd_hdac_aligned_write(unsigned int val, void __iomem *addr, | ||
416 | unsigned int mask); | ||
417 | #define snd_hdac_reg_writeb(v, addr) snd_hdac_aligned_write(v, addr, 0xff) | ||
418 | #define snd_hdac_reg_writew(v, addr) snd_hdac_aligned_write(v, addr, 0xffff) | ||
419 | #define snd_hdac_reg_readb(addr) snd_hdac_aligned_read(addr, 0xff) | ||
420 | #define snd_hdac_reg_readw(addr) snd_hdac_aligned_read(addr, 0xffff) | ||
421 | #else /* CONFIG_SND_HDA_ALIGNED_MMIO */ | ||
422 | #define snd_hdac_reg_writeb(val, addr) writeb(val, addr) | ||
423 | #define snd_hdac_reg_writew(val, addr) writew(val, addr) | ||
424 | #define snd_hdac_reg_readb(addr) readb(addr) | ||
425 | #define snd_hdac_reg_readw(addr) readw(addr) | ||
426 | #endif /* CONFIG_SND_HDA_ALIGNED_MMIO */ | ||
427 | #define snd_hdac_reg_writel(val, addr) writel(val, addr) | ||
428 | #define snd_hdac_reg_readl(addr) readl(addr) | ||
429 | |||
432 | /* | 430 | /* |
433 | * macros for easy use | 431 | * macros for easy use |
434 | */ | 432 | */ |
435 | #define _snd_hdac_chip_writeb(chip, reg, value) \ | 433 | #define _snd_hdac_chip_writeb(chip, reg, value) \ |
436 | ((chip)->io_ops->reg_writeb(value, (chip)->remap_addr + (reg))) | 434 | snd_hdac_reg_writeb(value, (chip)->remap_addr + (reg)) |
437 | #define _snd_hdac_chip_readb(chip, reg) \ | 435 | #define _snd_hdac_chip_readb(chip, reg) \ |
438 | ((chip)->io_ops->reg_readb((chip)->remap_addr + (reg))) | 436 | snd_hdac_reg_readb((chip)->remap_addr + (reg)) |
439 | #define _snd_hdac_chip_writew(chip, reg, value) \ | 437 | #define _snd_hdac_chip_writew(chip, reg, value) \ |
440 | ((chip)->io_ops->reg_writew(value, (chip)->remap_addr + (reg))) | 438 | snd_hdac_reg_writew(value, (chip)->remap_addr + (reg)) |
441 | #define _snd_hdac_chip_readw(chip, reg) \ | 439 | #define _snd_hdac_chip_readw(chip, reg) \ |
442 | ((chip)->io_ops->reg_readw((chip)->remap_addr + (reg))) | 440 | snd_hdac_reg_readw((chip)->remap_addr + (reg)) |
443 | #define _snd_hdac_chip_writel(chip, reg, value) \ | 441 | #define _snd_hdac_chip_writel(chip, reg, value) \ |
444 | ((chip)->io_ops->reg_writel(value, (chip)->remap_addr + (reg))) | 442 | snd_hdac_reg_writel(value, (chip)->remap_addr + (reg)) |
445 | #define _snd_hdac_chip_readl(chip, reg) \ | 443 | #define _snd_hdac_chip_readl(chip, reg) \ |
446 | ((chip)->io_ops->reg_readl((chip)->remap_addr + (reg))) | 444 | snd_hdac_reg_readl((chip)->remap_addr + (reg)) |
447 | 445 | ||
448 | /* read/write a register, pass without AZX_REG_ prefix */ | 446 | /* read/write a register, pass without AZX_REG_ prefix */ |
449 | #define snd_hdac_chip_writel(chip, reg, value) \ | 447 | #define snd_hdac_chip_writel(chip, reg, value) \ |
@@ -548,24 +546,19 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, | |||
548 | /* | 546 | /* |
549 | * macros for easy use | 547 | * macros for easy use |
550 | */ | 548 | */ |
551 | #define _snd_hdac_stream_write(type, dev, reg, value) \ | ||
552 | ((dev)->bus->io_ops->reg_write ## type(value, (dev)->sd_addr + (reg))) | ||
553 | #define _snd_hdac_stream_read(type, dev, reg) \ | ||
554 | ((dev)->bus->io_ops->reg_read ## type((dev)->sd_addr + (reg))) | ||
555 | |||
556 | /* read/write a register, pass without AZX_REG_ prefix */ | 549 | /* read/write a register, pass without AZX_REG_ prefix */ |
557 | #define snd_hdac_stream_writel(dev, reg, value) \ | 550 | #define snd_hdac_stream_writel(dev, reg, value) \ |
558 | _snd_hdac_stream_write(l, dev, AZX_REG_ ## reg, value) | 551 | snd_hdac_reg_writel(value, (dev)->sd_addr + AZX_REG_ ## reg) |
559 | #define snd_hdac_stream_writew(dev, reg, value) \ | 552 | #define snd_hdac_stream_writew(dev, reg, value) \ |
560 | _snd_hdac_stream_write(w, dev, AZX_REG_ ## reg, value) | 553 | snd_hdac_reg_writew(value, (dev)->sd_addr + AZX_REG_ ## reg) |
561 | #define snd_hdac_stream_writeb(dev, reg, value) \ | 554 | #define snd_hdac_stream_writeb(dev, reg, value) \ |
562 | _snd_hdac_stream_write(b, dev, AZX_REG_ ## reg, value) | 555 | snd_hdac_reg_writeb(value, (dev)->sd_addr + AZX_REG_ ## reg) |
563 | #define snd_hdac_stream_readl(dev, reg) \ | 556 | #define snd_hdac_stream_readl(dev, reg) \ |
564 | _snd_hdac_stream_read(l, dev, AZX_REG_ ## reg) | 557 | snd_hdac_reg_readl((dev)->sd_addr + AZX_REG_ ## reg) |
565 | #define snd_hdac_stream_readw(dev, reg) \ | 558 | #define snd_hdac_stream_readw(dev, reg) \ |
566 | _snd_hdac_stream_read(w, dev, AZX_REG_ ## reg) | 559 | snd_hdac_reg_readw((dev)->sd_addr + AZX_REG_ ## reg) |
567 | #define snd_hdac_stream_readb(dev, reg) \ | 560 | #define snd_hdac_stream_readb(dev, reg) \ |
568 | _snd_hdac_stream_read(b, dev, AZX_REG_ ## reg) | 561 | snd_hdac_reg_readb((dev)->sd_addr + AZX_REG_ ## reg) |
569 | 562 | ||
570 | /* update a register, pass without AZX_REG_ prefix */ | 563 | /* update a register, pass without AZX_REG_ prefix */ |
571 | #define snd_hdac_stream_updatel(dev, reg, mask, val) \ | 564 | #define snd_hdac_stream_updatel(dev, reg, mask, val) \ |
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index f34aced69ca8..ef88b20c7b0a 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h | |||
@@ -6,7 +6,6 @@ | |||
6 | 6 | ||
7 | int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, | 7 | int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, |
8 | const struct hdac_bus_ops *ops, | 8 | const struct hdac_bus_ops *ops, |
9 | const struct hdac_io_ops *io_ops, | ||
10 | const struct hdac_ext_bus_ops *ext_ops); | 9 | const struct hdac_ext_bus_ops *ext_ops); |
11 | 10 | ||
12 | void snd_hdac_ext_bus_exit(struct hdac_bus *bus); | 11 | void snd_hdac_ext_bus_exit(struct hdac_bus *bus); |
diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h index 7fea496f1f34..83b17682e01c 100644 --- a/include/sound/hdmi-codec.h +++ b/include/sound/hdmi-codec.h | |||
@@ -47,6 +47,9 @@ struct hdmi_codec_params { | |||
47 | int channels; | 47 | int channels; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | typedef void (*hdmi_codec_plugged_cb)(struct device *dev, | ||
51 | bool plugged); | ||
52 | |||
50 | struct hdmi_codec_pdata; | 53 | struct hdmi_codec_pdata; |
51 | struct hdmi_codec_ops { | 54 | struct hdmi_codec_ops { |
52 | /* | 55 | /* |
@@ -88,6 +91,14 @@ struct hdmi_codec_ops { | |||
88 | */ | 91 | */ |
89 | int (*get_dai_id)(struct snd_soc_component *comment, | 92 | int (*get_dai_id)(struct snd_soc_component *comment, |
90 | struct device_node *endpoint); | 93 | struct device_node *endpoint); |
94 | |||
95 | /* | ||
96 | * Hook callback function to handle connector plug event. | ||
97 | * Optional | ||
98 | */ | ||
99 | int (*hook_plugged_cb)(struct device *dev, void *data, | ||
100 | hdmi_codec_plugged_cb fn, | ||
101 | struct device *codec_dev); | ||
91 | }; | 102 | }; |
92 | 103 | ||
93 | /* HDMI codec initalization data */ | 104 | /* HDMI codec initalization data */ |
@@ -99,6 +110,12 @@ struct hdmi_codec_pdata { | |||
99 | void *data; | 110 | void *data; |
100 | }; | 111 | }; |
101 | 112 | ||
113 | struct snd_soc_component; | ||
114 | struct snd_soc_jack; | ||
115 | |||
116 | int hdmi_codec_set_jack_detect(struct snd_soc_component *component, | ||
117 | struct snd_soc_jack *jack); | ||
118 | |||
102 | #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" | 119 | #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" |
103 | 120 | ||
104 | #endif /* __HDMI_CODEC_H__ */ | 121 | #endif /* __HDMI_CODEC_H__ */ |
diff --git a/sound/soc/intel/skylake/skl-nhlt.h b/include/sound/intel-nhlt.h index f85fbf9c7ce4..f657fd8fc0ad 100644 --- a/sound/soc/intel/skylake/skl-nhlt.h +++ b/include/sound/intel-nhlt.h | |||
@@ -1,18 +1,17 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0-only */ | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* | 2 | /* |
3 | * skl-nhlt.h - Intel HDA Platform NHLT header | 3 | * intel-nhlt.h - Intel HDA Platform NHLT header |
4 | * | 4 | * |
5 | * Copyright (C) 2015 Intel Corp | 5 | * Copyright (c) 2015-2019 Intel Corporation |
6 | * Author: Sanjiv Kumar <sanjiv.kumar@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
10 | */ | 6 | */ |
11 | #ifndef __SKL_NHLT_H__ | 7 | |
12 | #define __SKL_NHLT_H__ | 8 | #ifndef __INTEL_NHLT_H__ |
9 | #define __INTEL_NHLT_H__ | ||
13 | 10 | ||
14 | #include <linux/acpi.h> | 11 | #include <linux/acpi.h> |
15 | 12 | ||
13 | #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) | ||
14 | |||
16 | struct wav_fmt { | 15 | struct wav_fmt { |
17 | u16 fmt_tag; | 16 | u16 fmt_tag; |
18 | u16 channels; | 17 | u16 channels; |
@@ -97,16 +96,22 @@ struct nhlt_resource_desc { | |||
97 | #define MIC_ARRAY_2CH 2 | 96 | #define MIC_ARRAY_2CH 2 |
98 | #define MIC_ARRAY_4CH 4 | 97 | #define MIC_ARRAY_4CH 4 |
99 | 98 | ||
100 | struct nhlt_tdm_config { | 99 | struct nhlt_device_specific_config { |
101 | u8 virtual_slot; | 100 | u8 virtual_slot; |
102 | u8 config_type; | 101 | u8 config_type; |
103 | } __packed; | 102 | } __packed; |
104 | 103 | ||
105 | struct nhlt_dmic_array_config { | 104 | struct nhlt_dmic_array_config { |
106 | struct nhlt_tdm_config tdm_config; | 105 | struct nhlt_device_specific_config device_config; |
107 | u8 array_type; | 106 | u8 array_type; |
108 | } __packed; | 107 | } __packed; |
109 | 108 | ||
109 | struct nhlt_vendor_dmic_array_config { | ||
110 | struct nhlt_dmic_array_config dmic_config; | ||
111 | u8 nb_mics; | ||
112 | /* TODO add vendor mic config */ | ||
113 | } __packed; | ||
114 | |||
110 | enum { | 115 | enum { |
111 | NHLT_MIC_ARRAY_2CH_SMALL = 0xa, | 116 | NHLT_MIC_ARRAY_2CH_SMALL = 0xa, |
112 | NHLT_MIC_ARRAY_2CH_BIG = 0xb, | 117 | NHLT_MIC_ARRAY_2CH_BIG = 0xb, |
@@ -116,4 +121,30 @@ enum { | |||
116 | NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, | 121 | NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, |
117 | }; | 122 | }; |
118 | 123 | ||
124 | struct nhlt_acpi_table *intel_nhlt_init(struct device *dev); | ||
125 | |||
126 | void intel_nhlt_free(struct nhlt_acpi_table *addr); | ||
127 | |||
128 | int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt); | ||
129 | |||
130 | #else | ||
131 | |||
132 | struct nhlt_acpi_table; | ||
133 | |||
134 | static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) | ||
135 | { | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | static inline void intel_nhlt_free(struct nhlt_acpi_table *addr) | ||
140 | { | ||
141 | } | ||
142 | |||
143 | static inline int intel_nhlt_get_dmic_geo(struct device *dev, | ||
144 | struct nhlt_acpi_table *nhlt) | ||
145 | { | ||
146 | return 0; | ||
147 | } | ||
148 | #endif | ||
149 | |||
119 | #endif | 150 | #endif |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 1e9bb1c91770..bbe6eb1ff5d2 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -117,6 +117,8 @@ struct snd_pcm_ops { | |||
117 | #define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ | 117 | #define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ |
118 | #define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ | 118 | #define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ |
119 | #define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ | 119 | #define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ |
120 | #define SNDRV_PCM_RATE_352800 (1<<13) /* 352800Hz */ | ||
121 | #define SNDRV_PCM_RATE_384000 (1<<14) /* 384000Hz */ | ||
120 | 122 | ||
121 | #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ | 123 | #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ |
122 | #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ | 124 | #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ |
@@ -129,6 +131,9 @@ struct snd_pcm_ops { | |||
129 | SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) | 131 | SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) |
130 | #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ | 132 | #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ |
131 | SNDRV_PCM_RATE_192000) | 133 | SNDRV_PCM_RATE_192000) |
134 | #define SNDRV_PCM_RATE_8000_384000 (SNDRV_PCM_RATE_8000_192000|\ | ||
135 | SNDRV_PCM_RATE_352800|\ | ||
136 | SNDRV_PCM_RATE_384000) | ||
132 | #define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt) | 137 | #define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt) |
133 | #define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8) | 138 | #define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8) |
134 | #define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8) | 139 | #define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8) |
diff --git a/include/sound/soc-acpi-intel-match.h b/include/sound/soc-acpi-intel-match.h index bb5e1e4ce8bf..6c9929abd90b 100644 --- a/include/sound/soc-acpi-intel-match.h +++ b/include/sound/soc-acpi-intel-match.h | |||
@@ -25,6 +25,8 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[]; | |||
25 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[]; | 25 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[]; |
26 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[]; | 26 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[]; |
27 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[]; | 27 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[]; |
28 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[]; | ||
29 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[]; | ||
28 | 30 | ||
29 | /* | 31 | /* |
30 | * generic table used for HDA codec-based platforms, possibly with | 32 | * generic table used for HDA codec-based platforms, possibly with |
diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h new file mode 100644 index 000000000000..5d80b2eef525 --- /dev/null +++ b/include/sound/soc-component.h | |||
@@ -0,0 +1,387 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 | ||
2 | * | ||
3 | * soc-component.h | ||
4 | * | ||
5 | * Copyright (c) 2019 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #ifndef __SOC_COMPONENT_H | ||
12 | #define __SOC_COMPONENT_H | ||
13 | |||
14 | #include <sound/soc.h> | ||
15 | |||
16 | /* | ||
17 | * Component probe and remove ordering levels for components with runtime | ||
18 | * dependencies. | ||
19 | */ | ||
20 | #define SND_SOC_COMP_ORDER_FIRST -2 | ||
21 | #define SND_SOC_COMP_ORDER_EARLY -1 | ||
22 | #define SND_SOC_COMP_ORDER_NORMAL 0 | ||
23 | #define SND_SOC_COMP_ORDER_LATE 1 | ||
24 | #define SND_SOC_COMP_ORDER_LAST 2 | ||
25 | |||
26 | #define for_each_comp_order(order) \ | ||
27 | for (order = SND_SOC_COMP_ORDER_FIRST; \ | ||
28 | order <= SND_SOC_COMP_ORDER_LAST; \ | ||
29 | order++) | ||
30 | |||
31 | /* component interface */ | ||
32 | struct snd_soc_component_driver { | ||
33 | const char *name; | ||
34 | |||
35 | /* Default control and setup, added after probe() is run */ | ||
36 | const struct snd_kcontrol_new *controls; | ||
37 | unsigned int num_controls; | ||
38 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
39 | unsigned int num_dapm_widgets; | ||
40 | const struct snd_soc_dapm_route *dapm_routes; | ||
41 | unsigned int num_dapm_routes; | ||
42 | |||
43 | int (*probe)(struct snd_soc_component *component); | ||
44 | void (*remove)(struct snd_soc_component *component); | ||
45 | int (*suspend)(struct snd_soc_component *component); | ||
46 | int (*resume)(struct snd_soc_component *component); | ||
47 | |||
48 | unsigned int (*read)(struct snd_soc_component *component, | ||
49 | unsigned int reg); | ||
50 | int (*write)(struct snd_soc_component *component, | ||
51 | unsigned int reg, unsigned int val); | ||
52 | |||
53 | /* pcm creation and destruction */ | ||
54 | int (*pcm_new)(struct snd_soc_pcm_runtime *rtd); | ||
55 | void (*pcm_free)(struct snd_pcm *pcm); | ||
56 | |||
57 | /* component wide operations */ | ||
58 | int (*set_sysclk)(struct snd_soc_component *component, | ||
59 | int clk_id, int source, unsigned int freq, int dir); | ||
60 | int (*set_pll)(struct snd_soc_component *component, int pll_id, | ||
61 | int source, unsigned int freq_in, unsigned int freq_out); | ||
62 | int (*set_jack)(struct snd_soc_component *component, | ||
63 | struct snd_soc_jack *jack, void *data); | ||
64 | |||
65 | /* DT */ | ||
66 | int (*of_xlate_dai_name)(struct snd_soc_component *component, | ||
67 | struct of_phandle_args *args, | ||
68 | const char **dai_name); | ||
69 | int (*of_xlate_dai_id)(struct snd_soc_component *comment, | ||
70 | struct device_node *endpoint); | ||
71 | void (*seq_notifier)(struct snd_soc_component *component, | ||
72 | enum snd_soc_dapm_type type, int subseq); | ||
73 | int (*stream_event)(struct snd_soc_component *component, int event); | ||
74 | int (*set_bias_level)(struct snd_soc_component *component, | ||
75 | enum snd_soc_bias_level level); | ||
76 | |||
77 | const struct snd_pcm_ops *ops; | ||
78 | const struct snd_compr_ops *compr_ops; | ||
79 | |||
80 | /* probe ordering - for components with runtime dependencies */ | ||
81 | int probe_order; | ||
82 | int remove_order; | ||
83 | |||
84 | /* | ||
85 | * signal if the module handling the component should not be removed | ||
86 | * if a pcm is open. Setting this would prevent the module | ||
87 | * refcount being incremented in probe() but allow it be incremented | ||
88 | * when a pcm is opened and decremented when it is closed. | ||
89 | */ | ||
90 | unsigned int module_get_upon_open:1; | ||
91 | |||
92 | /* bits */ | ||
93 | unsigned int idle_bias_on:1; | ||
94 | unsigned int suspend_bias_off:1; | ||
95 | unsigned int use_pmdown_time:1; /* care pmdown_time at stop */ | ||
96 | unsigned int endianness:1; | ||
97 | unsigned int non_legacy_dai_naming:1; | ||
98 | |||
99 | /* this component uses topology and ignore machine driver FEs */ | ||
100 | const char *ignore_machine; | ||
101 | const char *topology_name_prefix; | ||
102 | int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, | ||
103 | struct snd_pcm_hw_params *params); | ||
104 | bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */ | ||
105 | int be_pcm_base; /* base device ID for all BE PCMs */ | ||
106 | }; | ||
107 | |||
108 | struct snd_soc_component { | ||
109 | const char *name; | ||
110 | int id; | ||
111 | const char *name_prefix; | ||
112 | struct device *dev; | ||
113 | struct snd_soc_card *card; | ||
114 | |||
115 | unsigned int active; | ||
116 | |||
117 | unsigned int suspended:1; /* is in suspend PM state */ | ||
118 | |||
119 | struct list_head list; | ||
120 | struct list_head card_aux_list; /* for auxiliary bound components */ | ||
121 | struct list_head card_list; | ||
122 | |||
123 | const struct snd_soc_component_driver *driver; | ||
124 | |||
125 | struct list_head dai_list; | ||
126 | int num_dai; | ||
127 | |||
128 | struct regmap *regmap; | ||
129 | int val_bytes; | ||
130 | |||
131 | struct mutex io_mutex; | ||
132 | |||
133 | /* attached dynamic objects */ | ||
134 | struct list_head dobj_list; | ||
135 | |||
136 | /* | ||
137 | * DO NOT use any of the fields below in drivers, they are temporary and | ||
138 | * are going to be removed again soon. If you use them in driver code | ||
139 | * the driver will be marked as BROKEN when these fields are removed. | ||
140 | */ | ||
141 | |||
142 | /* Don't use these, use snd_soc_component_get_dapm() */ | ||
143 | struct snd_soc_dapm_context dapm; | ||
144 | |||
145 | /* machine specific init */ | ||
146 | int (*init)(struct snd_soc_component *component); | ||
147 | |||
148 | #ifdef CONFIG_DEBUG_FS | ||
149 | struct dentry *debugfs_root; | ||
150 | const char *debugfs_prefix; | ||
151 | #endif | ||
152 | }; | ||
153 | |||
154 | #define for_each_component_dais(component, dai)\ | ||
155 | list_for_each_entry(dai, &(component)->dai_list, list) | ||
156 | #define for_each_component_dais_safe(component, dai, _dai)\ | ||
157 | list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list) | ||
158 | |||
159 | /** | ||
160 | * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is | ||
161 | * embedded in | ||
162 | * @dapm: The DAPM context to cast to the component | ||
163 | * | ||
164 | * This function must only be used on DAPM contexts that are known to be part of | ||
165 | * a component (e.g. in a component driver). Otherwise the behavior is | ||
166 | * undefined. | ||
167 | */ | ||
168 | static inline struct snd_soc_component *snd_soc_dapm_to_component( | ||
169 | struct snd_soc_dapm_context *dapm) | ||
170 | { | ||
171 | return container_of(dapm, struct snd_soc_component, dapm); | ||
172 | } | ||
173 | |||
174 | /** | ||
175 | * snd_soc_component_get_dapm() - Returns the DAPM context associated with a | ||
176 | * component | ||
177 | * @component: The component for which to get the DAPM context | ||
178 | */ | ||
179 | static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( | ||
180 | struct snd_soc_component *component) | ||
181 | { | ||
182 | return &component->dapm; | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level | ||
187 | * @component: The COMPONENT for which to initialize the DAPM bias level | ||
188 | * @level: The DAPM level to initialize to | ||
189 | * | ||
190 | * Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level() | ||
191 | */ | ||
192 | static inline void | ||
193 | snd_soc_component_init_bias_level(struct snd_soc_component *component, | ||
194 | enum snd_soc_bias_level level) | ||
195 | { | ||
196 | snd_soc_dapm_init_bias_level( | ||
197 | snd_soc_component_get_dapm(component), level); | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level | ||
202 | * @component: The COMPONENT for which to get the DAPM bias level | ||
203 | * | ||
204 | * Returns: The current DAPM bias level of the COMPONENT. | ||
205 | */ | ||
206 | static inline enum snd_soc_bias_level | ||
207 | snd_soc_component_get_bias_level(struct snd_soc_component *component) | ||
208 | { | ||
209 | return snd_soc_dapm_get_bias_level( | ||
210 | snd_soc_component_get_dapm(component)); | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level | ||
215 | * @component: The COMPONENT for which to set the level | ||
216 | * @level: The level to set to | ||
217 | * | ||
218 | * Forces the COMPONENT bias level to a specific state. See | ||
219 | * snd_soc_dapm_force_bias_level(). | ||
220 | */ | ||
221 | static inline int | ||
222 | snd_soc_component_force_bias_level(struct snd_soc_component *component, | ||
223 | enum snd_soc_bias_level level) | ||
224 | { | ||
225 | return snd_soc_dapm_force_bias_level( | ||
226 | snd_soc_component_get_dapm(component), | ||
227 | level); | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * snd_soc_dapm_kcontrol_component() - Returns the component associated to a | ||
232 | * kcontrol | ||
233 | * @kcontrol: The kcontrol | ||
234 | * | ||
235 | * This function must only be used on DAPM contexts that are known to be part of | ||
236 | * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined | ||
237 | */ | ||
238 | static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component( | ||
239 | struct snd_kcontrol *kcontrol) | ||
240 | { | ||
241 | return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol)); | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * snd_soc_component_cache_sync() - Sync the register cache with the hardware | ||
246 | * @component: COMPONENT to sync | ||
247 | * | ||
248 | * Note: This function will call regcache_sync() | ||
249 | */ | ||
250 | static inline int snd_soc_component_cache_sync( | ||
251 | struct snd_soc_component *component) | ||
252 | { | ||
253 | return regcache_sync(component->regmap); | ||
254 | } | ||
255 | |||
256 | /* component IO */ | ||
257 | int snd_soc_component_read(struct snd_soc_component *component, | ||
258 | unsigned int reg, unsigned int *val); | ||
259 | unsigned int snd_soc_component_read32(struct snd_soc_component *component, | ||
260 | unsigned int reg); | ||
261 | int snd_soc_component_write(struct snd_soc_component *component, | ||
262 | unsigned int reg, unsigned int val); | ||
263 | int snd_soc_component_update_bits(struct snd_soc_component *component, | ||
264 | unsigned int reg, unsigned int mask, | ||
265 | unsigned int val); | ||
266 | int snd_soc_component_update_bits_async(struct snd_soc_component *component, | ||
267 | unsigned int reg, unsigned int mask, | ||
268 | unsigned int val); | ||
269 | void snd_soc_component_async_complete(struct snd_soc_component *component); | ||
270 | int snd_soc_component_test_bits(struct snd_soc_component *component, | ||
271 | unsigned int reg, unsigned int mask, | ||
272 | unsigned int value); | ||
273 | |||
274 | /* component wide operations */ | ||
275 | int snd_soc_component_set_sysclk(struct snd_soc_component *component, | ||
276 | int clk_id, int source, | ||
277 | unsigned int freq, int dir); | ||
278 | int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, | ||
279 | int source, unsigned int freq_in, | ||
280 | unsigned int freq_out); | ||
281 | int snd_soc_component_set_jack(struct snd_soc_component *component, | ||
282 | struct snd_soc_jack *jack, void *data); | ||
283 | |||
284 | void snd_soc_component_seq_notifier(struct snd_soc_component *component, | ||
285 | enum snd_soc_dapm_type type, int subseq); | ||
286 | int snd_soc_component_stream_event(struct snd_soc_component *component, | ||
287 | int event); | ||
288 | int snd_soc_component_set_bias_level(struct snd_soc_component *component, | ||
289 | enum snd_soc_bias_level level); | ||
290 | |||
291 | #ifdef CONFIG_REGMAP | ||
292 | void snd_soc_component_init_regmap(struct snd_soc_component *component, | ||
293 | struct regmap *regmap); | ||
294 | void snd_soc_component_exit_regmap(struct snd_soc_component *component); | ||
295 | #endif | ||
296 | |||
297 | #define snd_soc_component_module_get_when_probe(component)\ | ||
298 | snd_soc_component_module_get(component, 0) | ||
299 | #define snd_soc_component_module_get_when_open(component) \ | ||
300 | snd_soc_component_module_get(component, 1) | ||
301 | int snd_soc_component_module_get(struct snd_soc_component *component, | ||
302 | int upon_open); | ||
303 | #define snd_soc_component_module_put_when_remove(component) \ | ||
304 | snd_soc_component_module_put(component, 0) | ||
305 | #define snd_soc_component_module_put_when_close(component) \ | ||
306 | snd_soc_component_module_put(component, 1) | ||
307 | void snd_soc_component_module_put(struct snd_soc_component *component, | ||
308 | int upon_open); | ||
309 | |||
310 | static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c, | ||
311 | void *data) | ||
312 | { | ||
313 | dev_set_drvdata(c->dev, data); | ||
314 | } | ||
315 | |||
316 | static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c) | ||
317 | { | ||
318 | return dev_get_drvdata(c->dev); | ||
319 | } | ||
320 | |||
321 | static inline bool snd_soc_component_is_active( | ||
322 | struct snd_soc_component *component) | ||
323 | { | ||
324 | return component->active != 0; | ||
325 | } | ||
326 | |||
327 | /* component pin */ | ||
328 | int snd_soc_component_enable_pin(struct snd_soc_component *component, | ||
329 | const char *pin); | ||
330 | int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, | ||
331 | const char *pin); | ||
332 | int snd_soc_component_disable_pin(struct snd_soc_component *component, | ||
333 | const char *pin); | ||
334 | int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, | ||
335 | const char *pin); | ||
336 | int snd_soc_component_nc_pin(struct snd_soc_component *component, | ||
337 | const char *pin); | ||
338 | int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, | ||
339 | const char *pin); | ||
340 | int snd_soc_component_get_pin_status(struct snd_soc_component *component, | ||
341 | const char *pin); | ||
342 | int snd_soc_component_force_enable_pin(struct snd_soc_component *component, | ||
343 | const char *pin); | ||
344 | int snd_soc_component_force_enable_pin_unlocked( | ||
345 | struct snd_soc_component *component, | ||
346 | const char *pin); | ||
347 | |||
348 | /* component driver ops */ | ||
349 | int snd_soc_component_open(struct snd_soc_component *component, | ||
350 | struct snd_pcm_substream *substream); | ||
351 | int snd_soc_component_close(struct snd_soc_component *component, | ||
352 | struct snd_pcm_substream *substream); | ||
353 | int snd_soc_component_prepare(struct snd_soc_component *component, | ||
354 | struct snd_pcm_substream *substream); | ||
355 | int snd_soc_component_hw_params(struct snd_soc_component *component, | ||
356 | struct snd_pcm_substream *substream, | ||
357 | struct snd_pcm_hw_params *params); | ||
358 | int snd_soc_component_hw_free(struct snd_soc_component *component, | ||
359 | struct snd_pcm_substream *substream); | ||
360 | int snd_soc_component_trigger(struct snd_soc_component *component, | ||
361 | struct snd_pcm_substream *substream, | ||
362 | int cmd); | ||
363 | void snd_soc_component_suspend(struct snd_soc_component *component); | ||
364 | void snd_soc_component_resume(struct snd_soc_component *component); | ||
365 | int snd_soc_component_is_suspended(struct snd_soc_component *component); | ||
366 | int snd_soc_component_probe(struct snd_soc_component *component); | ||
367 | void snd_soc_component_remove(struct snd_soc_component *component); | ||
368 | int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, | ||
369 | struct device_node *ep); | ||
370 | int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, | ||
371 | struct of_phandle_args *args, | ||
372 | const char **dai_name); | ||
373 | |||
374 | int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream); | ||
375 | int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, | ||
376 | unsigned int cmd, void *arg); | ||
377 | int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, | ||
378 | int channel, unsigned long pos, | ||
379 | void __user *buf, unsigned long bytes); | ||
380 | struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, | ||
381 | unsigned long offset); | ||
382 | int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, | ||
383 | struct vm_area_struct *vma); | ||
384 | int snd_soc_pcm_component_new(struct snd_pcm *pcm); | ||
385 | void snd_soc_pcm_component_free(struct snd_pcm *pcm); | ||
386 | |||
387 | #endif /* __SOC_COMPONENT_H */ | ||
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index f5d70041108f..939c73db6a03 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
@@ -145,6 +145,31 @@ int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, | |||
145 | 145 | ||
146 | int snd_soc_dai_is_dummy(struct snd_soc_dai *dai); | 146 | int snd_soc_dai_is_dummy(struct snd_soc_dai *dai); |
147 | 147 | ||
148 | int snd_soc_dai_hw_params(struct snd_soc_dai *dai, | ||
149 | struct snd_pcm_substream *substream, | ||
150 | struct snd_pcm_hw_params *params); | ||
151 | void snd_soc_dai_hw_free(struct snd_soc_dai *dai, | ||
152 | struct snd_pcm_substream *substream); | ||
153 | int snd_soc_dai_startup(struct snd_soc_dai *dai, | ||
154 | struct snd_pcm_substream *substream); | ||
155 | void snd_soc_dai_shutdown(struct snd_soc_dai *dai, | ||
156 | struct snd_pcm_substream *substream); | ||
157 | int snd_soc_dai_prepare(struct snd_soc_dai *dai, | ||
158 | struct snd_pcm_substream *substream); | ||
159 | int snd_soc_dai_trigger(struct snd_soc_dai *dai, | ||
160 | struct snd_pcm_substream *substream, int cmd); | ||
161 | int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, | ||
162 | struct snd_pcm_substream *substream, int cmd); | ||
163 | snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, | ||
164 | struct snd_pcm_substream *substream); | ||
165 | void snd_soc_dai_suspend(struct snd_soc_dai *dai); | ||
166 | void snd_soc_dai_resume(struct snd_soc_dai *dai); | ||
167 | int snd_soc_dai_probe(struct snd_soc_dai *dai); | ||
168 | int snd_soc_dai_remove(struct snd_soc_dai *dai); | ||
169 | int snd_soc_dai_compress_new(struct snd_soc_dai *dai, | ||
170 | struct snd_soc_pcm_runtime *rtd, int num); | ||
171 | bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); | ||
172 | |||
148 | struct snd_soc_dai_ops { | 173 | struct snd_soc_dai_ops { |
149 | /* | 174 | /* |
150 | * DAI clocking configuration, all optional. | 175 | * DAI clocking configuration, all optional. |
@@ -268,8 +293,6 @@ struct snd_soc_dai_driver { | |||
268 | /* Optional Callback used at pcm creation*/ | 293 | /* Optional Callback used at pcm creation*/ |
269 | int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, | 294 | int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, |
270 | struct snd_soc_dai *dai); | 295 | struct snd_soc_dai *dai); |
271 | /* DAI is also used for the control bus */ | ||
272 | bool bus_control; | ||
273 | 296 | ||
274 | /* ops */ | 297 | /* ops */ |
275 | const struct snd_soc_dai_ops *ops; | 298 | const struct snd_soc_dai_ops *ops; |
@@ -281,6 +304,7 @@ struct snd_soc_dai_driver { | |||
281 | unsigned int symmetric_rates:1; | 304 | unsigned int symmetric_rates:1; |
282 | unsigned int symmetric_channels:1; | 305 | unsigned int symmetric_channels:1; |
283 | unsigned int symmetric_samplebits:1; | 306 | unsigned int symmetric_samplebits:1; |
307 | unsigned int bus_control:1; /* DAI is also used for the control bus */ | ||
284 | 308 | ||
285 | /* probe ordering - for components with runtime dependencies */ | 309 | /* probe ordering - for components with runtime dependencies */ |
286 | int probe_order; | 310 | int probe_order; |
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 8a90816a6eb5..6e8a31225383 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -353,6 +353,8 @@ struct device; | |||
353 | #define SND_SOC_DAPM_WILL_PMD 0x80 /* called at start of sequence */ | 353 | #define SND_SOC_DAPM_WILL_PMD 0x80 /* called at start of sequence */ |
354 | #define SND_SOC_DAPM_PRE_POST_PMD \ | 354 | #define SND_SOC_DAPM_PRE_POST_PMD \ |
355 | (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD) | 355 | (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD) |
356 | #define SND_SOC_DAPM_PRE_POST_PMU \ | ||
357 | (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU) | ||
356 | 358 | ||
357 | /* convenience event type detection */ | 359 | /* convenience event type detection */ |
358 | #define SND_SOC_DAPM_EVENT_ON(e) \ | 360 | #define SND_SOC_DAPM_EVENT_ON(e) \ |
@@ -417,6 +419,9 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, | |||
417 | /* dapm path setup */ | 419 | /* dapm path setup */ |
418 | int snd_soc_dapm_new_widgets(struct snd_soc_card *card); | 420 | int snd_soc_dapm_new_widgets(struct snd_soc_card *card); |
419 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); | 421 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); |
422 | void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, | ||
423 | struct snd_soc_card *card, | ||
424 | struct snd_soc_component *component); | ||
420 | int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, | 425 | int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, |
421 | const struct snd_soc_dapm_route *route, int num); | 426 | const struct snd_soc_dapm_route *route, int num); |
422 | int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, | 427 | int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, |
@@ -662,8 +667,6 @@ struct snd_soc_dapm_context { | |||
662 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ | 667 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ |
663 | /* Go to BIAS_OFF in suspend if the DAPM context is idle */ | 668 | /* Go to BIAS_OFF in suspend if the DAPM context is idle */ |
664 | unsigned int suspend_bias_off:1; | 669 | unsigned int suspend_bias_off:1; |
665 | void (*seq_notifier)(struct snd_soc_dapm_context *, | ||
666 | enum snd_soc_dapm_type, int); | ||
667 | 670 | ||
668 | struct device *dev; /* from parent - for debug */ | 671 | struct device *dev; /* from parent - for debug */ |
669 | struct snd_soc_component *component; /* parent component */ | 672 | struct snd_soc_component *component; /* parent component */ |
@@ -673,10 +676,6 @@ struct snd_soc_dapm_context { | |||
673 | enum snd_soc_bias_level target_bias_level; | 676 | enum snd_soc_bias_level target_bias_level; |
674 | struct list_head list; | 677 | struct list_head list; |
675 | 678 | ||
676 | int (*stream_event)(struct snd_soc_dapm_context *dapm, int event); | ||
677 | int (*set_bias_level)(struct snd_soc_dapm_context *dapm, | ||
678 | enum snd_soc_bias_level level); | ||
679 | |||
680 | struct snd_soc_dapm_wcache path_sink_cache; | 679 | struct snd_soc_dapm_wcache path_sink_cache; |
681 | struct snd_soc_dapm_wcache path_source_cache; | 680 | struct snd_soc_dapm_wcache path_source_cache; |
682 | 681 | ||
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 4be3a2b7c106..e55aeb00ce2d 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h | |||
@@ -142,9 +142,16 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, | |||
142 | 142 | ||
143 | /* internal use only */ | 143 | /* internal use only */ |
144 | int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); | 144 | int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); |
145 | void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); | ||
146 | int soc_dpcm_runtime_update(struct snd_soc_card *); | 145 | int soc_dpcm_runtime_update(struct snd_soc_card *); |
147 | 146 | ||
147 | #ifdef CONFIG_DEBUG_FS | ||
148 | void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); | ||
149 | #else | ||
150 | static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) | ||
151 | { | ||
152 | } | ||
153 | #endif | ||
154 | |||
148 | int dpcm_path_get(struct snd_soc_pcm_runtime *fe, | 155 | int dpcm_path_get(struct snd_soc_pcm_runtime *fe, |
149 | int stream, struct snd_soc_dapm_widget_list **list_); | 156 | int stream, struct snd_soc_dapm_widget_list **list_); |
150 | int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, | 157 | int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 4e8071269639..f264c6509f00 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -363,21 +363,6 @@ | |||
363 | const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) | 363 | const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) |
364 | 364 | ||
365 | /* | 365 | /* |
366 | * Component probe and remove ordering levels for components with runtime | ||
367 | * dependencies. | ||
368 | */ | ||
369 | #define SND_SOC_COMP_ORDER_FIRST -2 | ||
370 | #define SND_SOC_COMP_ORDER_EARLY -1 | ||
371 | #define SND_SOC_COMP_ORDER_NORMAL 0 | ||
372 | #define SND_SOC_COMP_ORDER_LATE 1 | ||
373 | #define SND_SOC_COMP_ORDER_LAST 2 | ||
374 | |||
375 | #define for_each_comp_order(order) \ | ||
376 | for (order = SND_SOC_COMP_ORDER_FIRST; \ | ||
377 | order <= SND_SOC_COMP_ORDER_LAST; \ | ||
378 | order++) | ||
379 | |||
380 | /* | ||
381 | * Bias levels | 366 | * Bias levels |
382 | * | 367 | * |
383 | * @ON: Bias is fully on for audio playback and capture operations. | 368 | * @ON: Bias is fully on for audio playback and capture operations. |
@@ -505,10 +490,6 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms); | |||
505 | int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, | 490 | int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, |
506 | const struct snd_pcm_hardware *hw); | 491 | const struct snd_pcm_hardware *hw); |
507 | 492 | ||
508 | int soc_dai_hw_params(struct snd_pcm_substream *substream, | ||
509 | struct snd_pcm_hw_params *params, | ||
510 | struct snd_soc_dai *dai); | ||
511 | |||
512 | /* Jack reporting */ | 493 | /* Jack reporting */ |
513 | int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, | 494 | int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, |
514 | struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, | 495 | struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, |
@@ -751,132 +732,6 @@ struct snd_soc_compr_ops { | |||
751 | int (*trigger)(struct snd_compr_stream *); | 732 | int (*trigger)(struct snd_compr_stream *); |
752 | }; | 733 | }; |
753 | 734 | ||
754 | /* component interface */ | ||
755 | struct snd_soc_component_driver { | ||
756 | const char *name; | ||
757 | |||
758 | /* Default control and setup, added after probe() is run */ | ||
759 | const struct snd_kcontrol_new *controls; | ||
760 | unsigned int num_controls; | ||
761 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
762 | unsigned int num_dapm_widgets; | ||
763 | const struct snd_soc_dapm_route *dapm_routes; | ||
764 | unsigned int num_dapm_routes; | ||
765 | |||
766 | int (*probe)(struct snd_soc_component *); | ||
767 | void (*remove)(struct snd_soc_component *); | ||
768 | int (*suspend)(struct snd_soc_component *); | ||
769 | int (*resume)(struct snd_soc_component *); | ||
770 | |||
771 | unsigned int (*read)(struct snd_soc_component *, unsigned int); | ||
772 | int (*write)(struct snd_soc_component *, unsigned int, unsigned int); | ||
773 | |||
774 | /* pcm creation and destruction */ | ||
775 | int (*pcm_new)(struct snd_soc_pcm_runtime *); | ||
776 | void (*pcm_free)(struct snd_pcm *); | ||
777 | |||
778 | /* component wide operations */ | ||
779 | int (*set_sysclk)(struct snd_soc_component *component, | ||
780 | int clk_id, int source, unsigned int freq, int dir); | ||
781 | int (*set_pll)(struct snd_soc_component *component, int pll_id, | ||
782 | int source, unsigned int freq_in, unsigned int freq_out); | ||
783 | int (*set_jack)(struct snd_soc_component *component, | ||
784 | struct snd_soc_jack *jack, void *data); | ||
785 | |||
786 | /* DT */ | ||
787 | int (*of_xlate_dai_name)(struct snd_soc_component *component, | ||
788 | struct of_phandle_args *args, | ||
789 | const char **dai_name); | ||
790 | int (*of_xlate_dai_id)(struct snd_soc_component *comment, | ||
791 | struct device_node *endpoint); | ||
792 | void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, | ||
793 | int subseq); | ||
794 | int (*stream_event)(struct snd_soc_component *, int event); | ||
795 | int (*set_bias_level)(struct snd_soc_component *component, | ||
796 | enum snd_soc_bias_level level); | ||
797 | |||
798 | const struct snd_pcm_ops *ops; | ||
799 | const struct snd_compr_ops *compr_ops; | ||
800 | |||
801 | /* probe ordering - for components with runtime dependencies */ | ||
802 | int probe_order; | ||
803 | int remove_order; | ||
804 | |||
805 | /* | ||
806 | * signal if the module handling the component should not be removed | ||
807 | * if a pcm is open. Setting this would prevent the module | ||
808 | * refcount being incremented in probe() but allow it be incremented | ||
809 | * when a pcm is opened and decremented when it is closed. | ||
810 | */ | ||
811 | unsigned int module_get_upon_open:1; | ||
812 | |||
813 | /* bits */ | ||
814 | unsigned int idle_bias_on:1; | ||
815 | unsigned int suspend_bias_off:1; | ||
816 | unsigned int use_pmdown_time:1; /* care pmdown_time at stop */ | ||
817 | unsigned int endianness:1; | ||
818 | unsigned int non_legacy_dai_naming:1; | ||
819 | |||
820 | /* this component uses topology and ignore machine driver FEs */ | ||
821 | const char *ignore_machine; | ||
822 | const char *topology_name_prefix; | ||
823 | int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, | ||
824 | struct snd_pcm_hw_params *params); | ||
825 | bool use_dai_pcm_id; /* use the DAI link PCM ID as PCM device number */ | ||
826 | int be_pcm_base; /* base device ID for all BE PCMs */ | ||
827 | }; | ||
828 | |||
829 | struct snd_soc_component { | ||
830 | const char *name; | ||
831 | int id; | ||
832 | const char *name_prefix; | ||
833 | struct device *dev; | ||
834 | struct snd_soc_card *card; | ||
835 | |||
836 | unsigned int active; | ||
837 | |||
838 | unsigned int suspended:1; /* is in suspend PM state */ | ||
839 | |||
840 | struct list_head list; | ||
841 | struct list_head card_aux_list; /* for auxiliary bound components */ | ||
842 | struct list_head card_list; | ||
843 | |||
844 | const struct snd_soc_component_driver *driver; | ||
845 | |||
846 | struct list_head dai_list; | ||
847 | int num_dai; | ||
848 | |||
849 | struct regmap *regmap; | ||
850 | int val_bytes; | ||
851 | |||
852 | struct mutex io_mutex; | ||
853 | |||
854 | /* attached dynamic objects */ | ||
855 | struct list_head dobj_list; | ||
856 | |||
857 | /* | ||
858 | * DO NOT use any of the fields below in drivers, they are temporary and | ||
859 | * are going to be removed again soon. If you use them in driver code the | ||
860 | * driver will be marked as BROKEN when these fields are removed. | ||
861 | */ | ||
862 | |||
863 | /* Don't use these, use snd_soc_component_get_dapm() */ | ||
864 | struct snd_soc_dapm_context dapm; | ||
865 | |||
866 | /* machine specific init */ | ||
867 | int (*init)(struct snd_soc_component *component); | ||
868 | |||
869 | #ifdef CONFIG_DEBUG_FS | ||
870 | struct dentry *debugfs_root; | ||
871 | const char *debugfs_prefix; | ||
872 | #endif | ||
873 | }; | ||
874 | |||
875 | #define for_each_component_dais(component, dai)\ | ||
876 | list_for_each_entry(dai, &(component)->dai_list, list) | ||
877 | #define for_each_component_dais_safe(component, dai, _dai)\ | ||
878 | list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list) | ||
879 | |||
880 | struct snd_soc_rtdcom_list { | 735 | struct snd_soc_rtdcom_list { |
881 | struct snd_soc_component *component; | 736 | struct snd_soc_component *component; |
882 | struct list_head list; /* rtd::component_list */ | 737 | struct list_head list; /* rtd::component_list */ |
@@ -1086,6 +941,7 @@ struct snd_soc_dai_link { | |||
1086 | #define COMP_CPU(_dai) { .dai_name = _dai, } | 941 | #define COMP_CPU(_dai) { .dai_name = _dai, } |
1087 | #define COMP_CODEC(_name, _dai) { .name = _name, .dai_name = _dai, } | 942 | #define COMP_CODEC(_name, _dai) { .name = _name, .dai_name = _dai, } |
1088 | #define COMP_PLATFORM(_name) { .name = _name } | 943 | #define COMP_PLATFORM(_name) { .name = _name } |
944 | #define COMP_AUX(_name) { .name = _name } | ||
1089 | #define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", } | 945 | #define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", } |
1090 | 946 | ||
1091 | extern struct snd_soc_dai_link_component null_dailink_component[0]; | 947 | extern struct snd_soc_dai_link_component null_dailink_component[0]; |
@@ -1107,14 +963,11 @@ struct snd_soc_codec_conf { | |||
1107 | }; | 963 | }; |
1108 | 964 | ||
1109 | struct snd_soc_aux_dev { | 965 | struct snd_soc_aux_dev { |
1110 | const char *name; /* Codec name */ | ||
1111 | |||
1112 | /* | 966 | /* |
1113 | * specify multi-codec either by device name, or by | 967 | * specify multi-codec either by device name, or by |
1114 | * DT/OF node, but not both. | 968 | * DT/OF node, but not both. |
1115 | */ | 969 | */ |
1116 | const char *codec_name; | 970 | struct snd_soc_dai_link_component dlc; |
1117 | struct device_node *codec_of_node; | ||
1118 | 971 | ||
1119 | /* codec/machine specific init - e.g. add machine controls */ | 972 | /* codec/machine specific init - e.g. add machine controls */ |
1120 | int (*init)(struct snd_soc_component *component); | 973 | int (*init)(struct snd_soc_component *component); |
@@ -1135,6 +988,10 @@ struct snd_soc_card { | |||
1135 | struct mutex mutex; | 988 | struct mutex mutex; |
1136 | struct mutex dapm_mutex; | 989 | struct mutex dapm_mutex; |
1137 | 990 | ||
991 | /* Mutex for PCM operations */ | ||
992 | struct mutex pcm_mutex; | ||
993 | enum snd_soc_pcm_subclass pcm_subclass; | ||
994 | |||
1138 | spinlock_t dpcm_lock; | 995 | spinlock_t dpcm_lock; |
1139 | 996 | ||
1140 | bool instantiated; | 997 | bool instantiated; |
@@ -1203,8 +1060,6 @@ struct snd_soc_card { | |||
1203 | int num_of_dapm_routes; | 1060 | int num_of_dapm_routes; |
1204 | bool fully_routed; | 1061 | bool fully_routed; |
1205 | 1062 | ||
1206 | struct work_struct deferred_resume_work; | ||
1207 | |||
1208 | /* lists of probed devices belonging to this card */ | 1063 | /* lists of probed devices belonging to this card */ |
1209 | struct list_head component_dev_list; | 1064 | struct list_head component_dev_list; |
1210 | struct list_head list; | 1065 | struct list_head list; |
@@ -1224,7 +1079,9 @@ struct snd_soc_card { | |||
1224 | 1079 | ||
1225 | #ifdef CONFIG_DEBUG_FS | 1080 | #ifdef CONFIG_DEBUG_FS |
1226 | struct dentry *debugfs_card_root; | 1081 | struct dentry *debugfs_card_root; |
1227 | struct dentry *debugfs_pop_time; | 1082 | #endif |
1083 | #ifdef CONFIG_PM_SLEEP | ||
1084 | struct work_struct deferred_resume_work; | ||
1228 | #endif | 1085 | #endif |
1229 | u32 pop_time; | 1086 | u32 pop_time; |
1230 | 1087 | ||
@@ -1234,6 +1091,10 @@ struct snd_soc_card { | |||
1234 | for ((i) = 0; \ | 1091 | for ((i) = 0; \ |
1235 | ((i) < (card)->num_links) && ((link) = &(card)->dai_link[i]); \ | 1092 | ((i) < (card)->num_links) && ((link) = &(card)->dai_link[i]); \ |
1236 | (i)++) | 1093 | (i)++) |
1094 | #define for_each_card_pre_auxs(card, i, aux) \ | ||
1095 | for ((i) = 0; \ | ||
1096 | ((i) < (card)->num_aux_devs) && ((aux) = &(card)->aux_dev[i]); \ | ||
1097 | (i)++) | ||
1237 | 1098 | ||
1238 | #define for_each_card_links(card, link) \ | 1099 | #define for_each_card_links(card, link) \ |
1239 | list_for_each_entry(link, &(card)->dai_link_list, list) | 1100 | list_for_each_entry(link, &(card)->dai_link_list, list) |
@@ -1245,6 +1106,12 @@ struct snd_soc_card { | |||
1245 | #define for_each_card_rtds_safe(card, rtd, _rtd) \ | 1106 | #define for_each_card_rtds_safe(card, rtd, _rtd) \ |
1246 | list_for_each_entry_safe(rtd, _rtd, &(card)->rtd_list, list) | 1107 | list_for_each_entry_safe(rtd, _rtd, &(card)->rtd_list, list) |
1247 | 1108 | ||
1109 | #define for_each_card_auxs(card, component) \ | ||
1110 | list_for_each_entry(component, &card->aux_comp_list, card_aux_list) | ||
1111 | #define for_each_card_auxs_safe(card, component, _comp) \ | ||
1112 | list_for_each_entry_safe(component, _comp, \ | ||
1113 | &card->aux_comp_list, card_aux_list) | ||
1114 | |||
1248 | #define for_each_card_components(card, component) \ | 1115 | #define for_each_card_components(card, component) \ |
1249 | list_for_each_entry(component, &(card)->component_dev_list, card_list) | 1116 | list_for_each_entry(component, &(card)->component_dev_list, card_list) |
1250 | 1117 | ||
@@ -1253,8 +1120,6 @@ struct snd_soc_pcm_runtime { | |||
1253 | struct device *dev; | 1120 | struct device *dev; |
1254 | struct snd_soc_card *card; | 1121 | struct snd_soc_card *card; |
1255 | struct snd_soc_dai_link *dai_link; | 1122 | struct snd_soc_dai_link *dai_link; |
1256 | struct mutex pcm_mutex; | ||
1257 | enum snd_soc_pcm_subclass pcm_subclass; | ||
1258 | struct snd_pcm_ops ops; | 1123 | struct snd_pcm_ops ops; |
1259 | 1124 | ||
1260 | unsigned int params_select; /* currently selected param for dai link */ | 1125 | unsigned int params_select; /* currently selected param for dai link */ |
@@ -1342,134 +1207,6 @@ struct soc_enum { | |||
1342 | struct snd_soc_dobj dobj; | 1207 | struct snd_soc_dobj dobj; |
1343 | }; | 1208 | }; |
1344 | 1209 | ||
1345 | /** | ||
1346 | * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is | ||
1347 | * embedded in | ||
1348 | * @dapm: The DAPM context to cast to the component | ||
1349 | * | ||
1350 | * This function must only be used on DAPM contexts that are known to be part of | ||
1351 | * a component (e.g. in a component driver). Otherwise the behavior is | ||
1352 | * undefined. | ||
1353 | */ | ||
1354 | static inline struct snd_soc_component *snd_soc_dapm_to_component( | ||
1355 | struct snd_soc_dapm_context *dapm) | ||
1356 | { | ||
1357 | return container_of(dapm, struct snd_soc_component, dapm); | ||
1358 | } | ||
1359 | |||
1360 | /** | ||
1361 | * snd_soc_component_get_dapm() - Returns the DAPM context associated with a | ||
1362 | * component | ||
1363 | * @component: The component for which to get the DAPM context | ||
1364 | */ | ||
1365 | static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( | ||
1366 | struct snd_soc_component *component) | ||
1367 | { | ||
1368 | return &component->dapm; | ||
1369 | } | ||
1370 | |||
1371 | /** | ||
1372 | * snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level | ||
1373 | * @component: The COMPONENT for which to initialize the DAPM bias level | ||
1374 | * @level: The DAPM level to initialize to | ||
1375 | * | ||
1376 | * Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level(). | ||
1377 | */ | ||
1378 | static inline void | ||
1379 | snd_soc_component_init_bias_level(struct snd_soc_component *component, | ||
1380 | enum snd_soc_bias_level level) | ||
1381 | { | ||
1382 | snd_soc_dapm_init_bias_level( | ||
1383 | snd_soc_component_get_dapm(component), level); | ||
1384 | } | ||
1385 | |||
1386 | /** | ||
1387 | * snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level | ||
1388 | * @component: The COMPONENT for which to get the DAPM bias level | ||
1389 | * | ||
1390 | * Returns: The current DAPM bias level of the COMPONENT. | ||
1391 | */ | ||
1392 | static inline enum snd_soc_bias_level | ||
1393 | snd_soc_component_get_bias_level(struct snd_soc_component *component) | ||
1394 | { | ||
1395 | return snd_soc_dapm_get_bias_level( | ||
1396 | snd_soc_component_get_dapm(component)); | ||
1397 | } | ||
1398 | |||
1399 | /** | ||
1400 | * snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level | ||
1401 | * @component: The COMPONENT for which to set the level | ||
1402 | * @level: The level to set to | ||
1403 | * | ||
1404 | * Forces the COMPONENT bias level to a specific state. See | ||
1405 | * snd_soc_dapm_force_bias_level(). | ||
1406 | */ | ||
1407 | static inline int | ||
1408 | snd_soc_component_force_bias_level(struct snd_soc_component *component, | ||
1409 | enum snd_soc_bias_level level) | ||
1410 | { | ||
1411 | return snd_soc_dapm_force_bias_level( | ||
1412 | snd_soc_component_get_dapm(component), | ||
1413 | level); | ||
1414 | } | ||
1415 | |||
1416 | /** | ||
1417 | * snd_soc_dapm_kcontrol_component() - Returns the component associated to a kcontrol | ||
1418 | * @kcontrol: The kcontrol | ||
1419 | * | ||
1420 | * This function must only be used on DAPM contexts that are known to be part of | ||
1421 | * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined. | ||
1422 | */ | ||
1423 | static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component( | ||
1424 | struct snd_kcontrol *kcontrol) | ||
1425 | { | ||
1426 | return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol)); | ||
1427 | } | ||
1428 | |||
1429 | /** | ||
1430 | * snd_soc_component_cache_sync() - Sync the register cache with the hardware | ||
1431 | * @component: COMPONENT to sync | ||
1432 | * | ||
1433 | * Note: This function will call regcache_sync() | ||
1434 | */ | ||
1435 | static inline int snd_soc_component_cache_sync( | ||
1436 | struct snd_soc_component *component) | ||
1437 | { | ||
1438 | return regcache_sync(component->regmap); | ||
1439 | } | ||
1440 | |||
1441 | /* component IO */ | ||
1442 | int snd_soc_component_read(struct snd_soc_component *component, | ||
1443 | unsigned int reg, unsigned int *val); | ||
1444 | unsigned int snd_soc_component_read32(struct snd_soc_component *component, | ||
1445 | unsigned int reg); | ||
1446 | int snd_soc_component_write(struct snd_soc_component *component, | ||
1447 | unsigned int reg, unsigned int val); | ||
1448 | int snd_soc_component_update_bits(struct snd_soc_component *component, | ||
1449 | unsigned int reg, unsigned int mask, unsigned int val); | ||
1450 | int snd_soc_component_update_bits_async(struct snd_soc_component *component, | ||
1451 | unsigned int reg, unsigned int mask, unsigned int val); | ||
1452 | void snd_soc_component_async_complete(struct snd_soc_component *component); | ||
1453 | int snd_soc_component_test_bits(struct snd_soc_component *component, | ||
1454 | unsigned int reg, unsigned int mask, unsigned int value); | ||
1455 | |||
1456 | /* component wide operations */ | ||
1457 | int snd_soc_component_set_sysclk(struct snd_soc_component *component, | ||
1458 | int clk_id, int source, unsigned int freq, int dir); | ||
1459 | int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, | ||
1460 | int source, unsigned int freq_in, | ||
1461 | unsigned int freq_out); | ||
1462 | int snd_soc_component_set_jack(struct snd_soc_component *component, | ||
1463 | struct snd_soc_jack *jack, void *data); | ||
1464 | |||
1465 | #ifdef CONFIG_REGMAP | ||
1466 | |||
1467 | void snd_soc_component_init_regmap(struct snd_soc_component *component, | ||
1468 | struct regmap *regmap); | ||
1469 | void snd_soc_component_exit_regmap(struct snd_soc_component *component); | ||
1470 | |||
1471 | #endif | ||
1472 | |||
1473 | /* device driver data */ | 1210 | /* device driver data */ |
1474 | 1211 | ||
1475 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, | 1212 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, |
@@ -1483,27 +1220,6 @@ static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) | |||
1483 | return card->drvdata; | 1220 | return card->drvdata; |
1484 | } | 1221 | } |
1485 | 1222 | ||
1486 | static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c, | ||
1487 | void *data) | ||
1488 | { | ||
1489 | dev_set_drvdata(c->dev, data); | ||
1490 | } | ||
1491 | |||
1492 | static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c) | ||
1493 | { | ||
1494 | return dev_get_drvdata(c->dev); | ||
1495 | } | ||
1496 | |||
1497 | static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) | ||
1498 | { | ||
1499 | INIT_LIST_HEAD(&card->widgets); | ||
1500 | INIT_LIST_HEAD(&card->paths); | ||
1501 | INIT_LIST_HEAD(&card->dapm_list); | ||
1502 | INIT_LIST_HEAD(&card->aux_comp_list); | ||
1503 | INIT_LIST_HEAD(&card->component_dev_list); | ||
1504 | INIT_LIST_HEAD(&card->list); | ||
1505 | } | ||
1506 | |||
1507 | static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) | 1223 | static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) |
1508 | { | 1224 | { |
1509 | if (mc->reg == mc->rreg && mc->shift == mc->rshift) | 1225 | if (mc->reg == mc->rreg && mc->shift == mc->rshift) |
@@ -1540,12 +1256,6 @@ static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, | |||
1540 | return e->values[item]; | 1256 | return e->values[item]; |
1541 | } | 1257 | } |
1542 | 1258 | ||
1543 | static inline bool snd_soc_component_is_active( | ||
1544 | struct snd_soc_component *component) | ||
1545 | { | ||
1546 | return component->active != 0; | ||
1547 | } | ||
1548 | |||
1549 | /** | 1259 | /** |
1550 | * snd_soc_kcontrol_component() - Returns the component that registered the | 1260 | * snd_soc_kcontrol_component() - Returns the component that registered the |
1551 | * control | 1261 | * control |
@@ -1681,24 +1391,6 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) | |||
1681 | mutex_unlock(&dapm->card->dapm_mutex); | 1391 | mutex_unlock(&dapm->card->dapm_mutex); |
1682 | } | 1392 | } |
1683 | 1393 | ||
1684 | int snd_soc_component_enable_pin(struct snd_soc_component *component, | 1394 | #include <sound/soc-component.h> |
1685 | const char *pin); | ||
1686 | int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, | ||
1687 | const char *pin); | ||
1688 | int snd_soc_component_disable_pin(struct snd_soc_component *component, | ||
1689 | const char *pin); | ||
1690 | int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, | ||
1691 | const char *pin); | ||
1692 | int snd_soc_component_nc_pin(struct snd_soc_component *component, | ||
1693 | const char *pin); | ||
1694 | int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, | ||
1695 | const char *pin); | ||
1696 | int snd_soc_component_get_pin_status(struct snd_soc_component *component, | ||
1697 | const char *pin); | ||
1698 | int snd_soc_component_force_enable_pin(struct snd_soc_component *component, | ||
1699 | const char *pin); | ||
1700 | int snd_soc_component_force_enable_pin_unlocked( | ||
1701 | struct snd_soc_component *component, | ||
1702 | const char *pin); | ||
1703 | 1395 | ||
1704 | #endif | 1396 | #endif |
diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 65e4c20e567c..5f1ef5565be6 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h | |||
@@ -76,6 +76,9 @@ struct sof_ipc_dai_ssp_params { | |||
76 | uint16_t tdm_per_slot_padding_flag; | 76 | uint16_t tdm_per_slot_padding_flag; |
77 | uint32_t clks_control; | 77 | uint32_t clks_control; |
78 | uint32_t quirks; | 78 | uint32_t quirks; |
79 | uint32_t bclk_delay; /* guaranteed time (ms) for which BCLK | ||
80 | * will be driven, before sending data | ||
81 | */ | ||
79 | } __packed; | 82 | } __packed; |
80 | 83 | ||
81 | /* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */ | 84 | /* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */ |
@@ -176,4 +179,13 @@ struct sof_ipc_dai_dmic_params { | |||
176 | struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; | 179 | struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; |
177 | } __packed; | 180 | } __packed; |
178 | 181 | ||
182 | /* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */ | ||
183 | struct sof_ipc_dai_alh_params { | ||
184 | struct sof_ipc_hdr hdr; | ||
185 | uint32_t stream_id; | ||
186 | |||
187 | /* reserved for future use */ | ||
188 | uint32_t reserved[15]; | ||
189 | } __packed; | ||
190 | |||
179 | #endif | 191 | #endif |
diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h index 5b8de1b1983c..0f1235022146 100644 --- a/include/sound/sof/dai.h +++ b/include/sound/sof/dai.h | |||
@@ -49,7 +49,9 @@ enum sof_ipc_dai_type { | |||
49 | SOF_DAI_INTEL_SSP, /**< Intel SSP */ | 49 | SOF_DAI_INTEL_SSP, /**< Intel SSP */ |
50 | SOF_DAI_INTEL_DMIC, /**< Intel DMIC */ | 50 | SOF_DAI_INTEL_DMIC, /**< Intel DMIC */ |
51 | SOF_DAI_INTEL_HDA, /**< Intel HD/A */ | 51 | SOF_DAI_INTEL_HDA, /**< Intel HD/A */ |
52 | SOF_DAI_INTEL_SOUNDWIRE, /**< Intel SoundWire */ | 52 | SOF_DAI_INTEL_ALH, /**< Intel ALH */ |
53 | SOF_DAI_IMX_SAI, /**< i.MX SAI */ | ||
54 | SOF_DAI_IMX_ESAI, /**< i.MX ESAI */ | ||
53 | }; | 55 | }; |
54 | 56 | ||
55 | /* general purpose DAI configuration */ | 57 | /* general purpose DAI configuration */ |
@@ -70,6 +72,7 @@ struct sof_ipc_dai_config { | |||
70 | struct sof_ipc_dai_ssp_params ssp; | 72 | struct sof_ipc_dai_ssp_params ssp; |
71 | struct sof_ipc_dai_dmic_params dmic; | 73 | struct sof_ipc_dai_dmic_params dmic; |
72 | struct sof_ipc_dai_hda_params hda; | 74 | struct sof_ipc_dai_hda_params hda; |
75 | struct sof_ipc_dai_alh_params alh; | ||
73 | }; | 76 | }; |
74 | } __packed; | 77 | } __packed; |
75 | 78 | ||
diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index 4a9c24434f42..a0fe0d4c4b66 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | /* SOF ABI version major, minor and patch numbers */ | 27 | /* SOF ABI version major, minor and patch numbers */ |
28 | #define SOF_ABI_MAJOR 3 | 28 | #define SOF_ABI_MAJOR 3 |
29 | #define SOF_ABI_MINOR 8 | 29 | #define SOF_ABI_MINOR 10 |
30 | #define SOF_ABI_PATCH 0 | 30 | #define SOF_ABI_PATCH 0 |
31 | 31 | ||
32 | /* SOF ABI version number. Format within 32bit word is MMmmmppp */ | 32 | /* SOF ABI version number. Format within 32bit word is MMmmmppp */ |
diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h index dc1b27daaac6..8f996857fb24 100644 --- a/include/uapi/sound/sof/tokens.h +++ b/include/uapi/sound/sof/tokens.h | |||
@@ -75,6 +75,7 @@ | |||
75 | #define SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH 503 | 75 | #define SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH 503 |
76 | #define SOF_TKN_INTEL_SSP_QUIRKS 504 | 76 | #define SOF_TKN_INTEL_SSP_QUIRKS 504 |
77 | #define SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT 505 | 77 | #define SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT 505 |
78 | #define SOF_TKN_INTEL_SSP_BCLK_DELAY 506 | ||
78 | 79 | ||
79 | /* DMIC */ | 80 | /* DMIC */ |
80 | #define SOF_TKN_INTEL_DMIC_DRIVER_VERSION 600 | 81 | #define SOF_TKN_INTEL_DMIC_DRIVER_VERSION 600 |
@@ -105,4 +106,12 @@ | |||
105 | /* for backward compatibility */ | 106 | /* for backward compatibility */ |
106 | #define SOF_TKN_EFFECT_TYPE SOF_TKN_PROCESS_TYPE | 107 | #define SOF_TKN_EFFECT_TYPE SOF_TKN_PROCESS_TYPE |
107 | 108 | ||
109 | /* SAI */ | ||
110 | #define SOF_TKN_IMX_SAI_FIRST_TOKEN 1000 | ||
111 | /* TODO: Add SAI tokens */ | ||
112 | |||
113 | /* ESAI */ | ||
114 | #define SOF_TKN_IMX_ESAI_FIRST_TOKEN 1100 | ||
115 | /* TODO: Add ESAI tokens */ | ||
116 | |||
108 | #endif | 117 | #endif |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 703857aab00f..11e653c8aa0e 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -2170,7 +2170,7 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, | |||
2170 | 2170 | ||
2171 | static const unsigned int rates[] = { | 2171 | static const unsigned int rates[] = { |
2172 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, | 2172 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, |
2173 | 48000, 64000, 88200, 96000, 176400, 192000 | 2173 | 48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000 |
2174 | }; | 2174 | }; |
2175 | 2175 | ||
2176 | const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { | 2176 | const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { |
diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index f6feced15f17..3d33fc1757ba 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig | |||
@@ -6,6 +6,9 @@ config SND_HDA_CORE | |||
6 | config SND_HDA_DSP_LOADER | 6 | config SND_HDA_DSP_LOADER |
7 | bool | 7 | bool |
8 | 8 | ||
9 | config SND_HDA_ALIGNED_MMIO | ||
10 | bool | ||
11 | |||
9 | config SND_HDA_COMPONENT | 12 | config SND_HDA_COMPONENT |
10 | bool | 13 | bool |
11 | 14 | ||
@@ -29,3 +32,8 @@ config SND_HDA_PREALLOC_SIZE | |||
29 | 32 | ||
30 | Note that the pre-allocation size can be changed dynamically | 33 | Note that the pre-allocation size can be changed dynamically |
31 | via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. | 34 | via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. |
35 | |||
36 | config SND_INTEL_NHLT | ||
37 | tristate | ||
38 | # this config should be selected only for Intel ACPI platforms. | ||
39 | # A fallback is provided so that the code compiles in all cases. \ No newline at end of file | ||
diff --git a/sound/hda/Makefile b/sound/hda/Makefile index 2160202e2dc1..8560f6ef1b19 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile | |||
@@ -13,3 +13,6 @@ obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o | |||
13 | 13 | ||
14 | #extended hda | 14 | #extended hda |
15 | obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ | 15 | obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ |
16 | |||
17 | snd-intel-nhlt-objs := intel-nhlt.o | ||
18 | obj-$(CONFIG_SND_INTEL_NHLT) += snd-intel-nhlt.o | ||
diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 4f9f1d2a2ec5..242306d820ec 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c | |||
@@ -17,80 +17,22 @@ | |||
17 | MODULE_DESCRIPTION("HDA extended core"); | 17 | MODULE_DESCRIPTION("HDA extended core"); |
18 | MODULE_LICENSE("GPL v2"); | 18 | MODULE_LICENSE("GPL v2"); |
19 | 19 | ||
20 | static void hdac_ext_writel(u32 value, u32 __iomem *addr) | ||
21 | { | ||
22 | writel(value, addr); | ||
23 | } | ||
24 | |||
25 | static u32 hdac_ext_readl(u32 __iomem *addr) | ||
26 | { | ||
27 | return readl(addr); | ||
28 | } | ||
29 | |||
30 | static void hdac_ext_writew(u16 value, u16 __iomem *addr) | ||
31 | { | ||
32 | writew(value, addr); | ||
33 | } | ||
34 | |||
35 | static u16 hdac_ext_readw(u16 __iomem *addr) | ||
36 | { | ||
37 | return readw(addr); | ||
38 | } | ||
39 | |||
40 | static void hdac_ext_writeb(u8 value, u8 __iomem *addr) | ||
41 | { | ||
42 | writeb(value, addr); | ||
43 | } | ||
44 | |||
45 | static u8 hdac_ext_readb(u8 __iomem *addr) | ||
46 | { | ||
47 | return readb(addr); | ||
48 | } | ||
49 | |||
50 | static int hdac_ext_dma_alloc_pages(struct hdac_bus *bus, int type, | ||
51 | size_t size, struct snd_dma_buffer *buf) | ||
52 | { | ||
53 | return snd_dma_alloc_pages(type, bus->dev, size, buf); | ||
54 | } | ||
55 | |||
56 | static void hdac_ext_dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) | ||
57 | { | ||
58 | snd_dma_free_pages(buf); | ||
59 | } | ||
60 | |||
61 | static const struct hdac_io_ops hdac_ext_default_io = { | ||
62 | .reg_writel = hdac_ext_writel, | ||
63 | .reg_readl = hdac_ext_readl, | ||
64 | .reg_writew = hdac_ext_writew, | ||
65 | .reg_readw = hdac_ext_readw, | ||
66 | .reg_writeb = hdac_ext_writeb, | ||
67 | .reg_readb = hdac_ext_readb, | ||
68 | .dma_alloc_pages = hdac_ext_dma_alloc_pages, | ||
69 | .dma_free_pages = hdac_ext_dma_free_pages, | ||
70 | }; | ||
71 | |||
72 | /** | 20 | /** |
73 | * snd_hdac_ext_bus_init - initialize a HD-audio extended bus | 21 | * snd_hdac_ext_bus_init - initialize a HD-audio extended bus |
74 | * @ebus: the pointer to extended bus object | 22 | * @ebus: the pointer to extended bus object |
75 | * @dev: device pointer | 23 | * @dev: device pointer |
76 | * @ops: bus verb operators | 24 | * @ops: bus verb operators |
77 | * @io_ops: lowlevel I/O operators, can be NULL. If NULL core will use | ||
78 | * default ops | 25 | * default ops |
79 | * | 26 | * |
80 | * Returns 0 if successful, or a negative error code. | 27 | * Returns 0 if successful, or a negative error code. |
81 | */ | 28 | */ |
82 | int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, | 29 | int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, |
83 | const struct hdac_bus_ops *ops, | 30 | const struct hdac_bus_ops *ops, |
84 | const struct hdac_io_ops *io_ops, | ||
85 | const struct hdac_ext_bus_ops *ext_ops) | 31 | const struct hdac_ext_bus_ops *ext_ops) |
86 | { | 32 | { |
87 | int ret; | 33 | int ret; |
88 | 34 | ||
89 | /* check if io ops are provided, if not load the defaults */ | 35 | ret = snd_hdac_bus_init(bus, dev, ops); |
90 | if (io_ops == NULL) | ||
91 | io_ops = &hdac_ext_default_io; | ||
92 | |||
93 | ret = snd_hdac_bus_init(bus, dev, ops, io_ops); | ||
94 | if (ret < 0) | 36 | if (ret < 0) |
95 | return ret; | 37 | return ret; |
96 | 38 | ||
diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 14e57ffd5bc1..cd25e2b3f7f2 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c | |||
@@ -4,6 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
7 | #include <linux/io.h> | ||
7 | #include <linux/device.h> | 8 | #include <linux/device.h> |
8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
9 | #include <linux/export.h> | 10 | #include <linux/export.h> |
@@ -19,13 +20,11 @@ static const struct hdac_bus_ops default_ops = { | |||
19 | * snd_hdac_bus_init - initialize a HD-audio bas bus | 20 | * snd_hdac_bus_init - initialize a HD-audio bas bus |
20 | * @bus: the pointer to bus object | 21 | * @bus: the pointer to bus object |
21 | * @ops: bus verb operators | 22 | * @ops: bus verb operators |
22 | * @io_ops: lowlevel I/O operators | ||
23 | * | 23 | * |
24 | * Returns 0 if successful, or a negative error code. | 24 | * Returns 0 if successful, or a negative error code. |
25 | */ | 25 | */ |
26 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | 26 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, |
27 | const struct hdac_bus_ops *ops, | 27 | const struct hdac_bus_ops *ops) |
28 | const struct hdac_io_ops *io_ops) | ||
29 | { | 28 | { |
30 | memset(bus, 0, sizeof(*bus)); | 29 | memset(bus, 0, sizeof(*bus)); |
31 | bus->dev = dev; | 30 | bus->dev = dev; |
@@ -33,7 +32,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, | |||
33 | bus->ops = ops; | 32 | bus->ops = ops; |
34 | else | 33 | else |
35 | bus->ops = &default_ops; | 34 | bus->ops = &default_ops; |
36 | bus->io_ops = io_ops; | 35 | bus->dma_type = SNDRV_DMA_TYPE_DEV; |
37 | INIT_LIST_HEAD(&bus->stream_list); | 36 | INIT_LIST_HEAD(&bus->stream_list); |
38 | INIT_LIST_HEAD(&bus->codec_list); | 37 | INIT_LIST_HEAD(&bus->codec_list); |
39 | INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); | 38 | INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); |
@@ -217,3 +216,33 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus, | |||
217 | flush_work(&bus->unsol_work); | 216 | flush_work(&bus->unsol_work); |
218 | } | 217 | } |
219 | EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); | 218 | EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); |
219 | |||
220 | #ifdef CONFIG_SND_HDA_ALIGNED_MMIO | ||
221 | /* Helpers for aligned read/write of mmio space, for Tegra */ | ||
222 | unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask) | ||
223 | { | ||
224 | void __iomem *aligned_addr = | ||
225 | (void __iomem *)((unsigned long)(addr) & ~0x3); | ||
226 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
227 | unsigned int v; | ||
228 | |||
229 | v = readl(aligned_addr); | ||
230 | return (v >> shift) & mask; | ||
231 | } | ||
232 | EXPORT_SYMBOL_GPL(snd_hdac_aligned_read); | ||
233 | |||
234 | void snd_hdac_aligned_write(unsigned int val, void __iomem *addr, | ||
235 | unsigned int mask) | ||
236 | { | ||
237 | void __iomem *aligned_addr = | ||
238 | (void __iomem *)((unsigned long)(addr) & ~0x3); | ||
239 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
240 | unsigned int v; | ||
241 | |||
242 | v = readl(aligned_addr); | ||
243 | v &= ~(mask << shift); | ||
244 | v |= val << shift; | ||
245 | writel(v, aligned_addr); | ||
246 | } | ||
247 | EXPORT_SYMBOL_GPL(snd_hdac_aligned_write); | ||
248 | #endif /* CONFIG_SND_HDA_ALIGNED_MMIO */ | ||
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 3b0110545070..7e7be8e4dcf9 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c | |||
@@ -575,12 +575,13 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) | |||
575 | { | 575 | { |
576 | struct hdac_stream *s; | 576 | struct hdac_stream *s; |
577 | int num_streams = 0; | 577 | int num_streams = 0; |
578 | int dma_type = bus->dma_type ? bus->dma_type : SNDRV_DMA_TYPE_DEV; | ||
578 | int err; | 579 | int err; |
579 | 580 | ||
580 | list_for_each_entry(s, &bus->stream_list, list) { | 581 | list_for_each_entry(s, &bus->stream_list, list) { |
581 | /* allocate memory for the BDL for each stream */ | 582 | /* allocate memory for the BDL for each stream */ |
582 | err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, | 583 | err = snd_dma_alloc_pages(dma_type, bus->dev, |
583 | BDL_SIZE, &s->bdl); | 584 | BDL_SIZE, &s->bdl); |
584 | num_streams++; | 585 | num_streams++; |
585 | if (err < 0) | 586 | if (err < 0) |
586 | return -ENOMEM; | 587 | return -ENOMEM; |
@@ -589,16 +590,15 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus) | |||
589 | if (WARN_ON(!num_streams)) | 590 | if (WARN_ON(!num_streams)) |
590 | return -EINVAL; | 591 | return -EINVAL; |
591 | /* allocate memory for the position buffer */ | 592 | /* allocate memory for the position buffer */ |
592 | err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, | 593 | err = snd_dma_alloc_pages(dma_type, bus->dev, |
593 | num_streams * 8, &bus->posbuf); | 594 | num_streams * 8, &bus->posbuf); |
594 | if (err < 0) | 595 | if (err < 0) |
595 | return -ENOMEM; | 596 | return -ENOMEM; |
596 | list_for_each_entry(s, &bus->stream_list, list) | 597 | list_for_each_entry(s, &bus->stream_list, list) |
597 | s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8); | 598 | s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8); |
598 | 599 | ||
599 | /* single page (at least 4096 bytes) must suffice for both ringbuffes */ | 600 | /* single page (at least 4096 bytes) must suffice for both ringbuffes */ |
600 | return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, | 601 | return snd_dma_alloc_pages(dma_type, bus->dev, PAGE_SIZE, &bus->rb); |
601 | PAGE_SIZE, &bus->rb); | ||
602 | } | 602 | } |
603 | EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages); | 603 | EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages); |
604 | 604 | ||
@@ -612,12 +612,12 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus) | |||
612 | 612 | ||
613 | list_for_each_entry(s, &bus->stream_list, list) { | 613 | list_for_each_entry(s, &bus->stream_list, list) { |
614 | if (s->bdl.area) | 614 | if (s->bdl.area) |
615 | bus->io_ops->dma_free_pages(bus, &s->bdl); | 615 | snd_dma_free_pages(&s->bdl); |
616 | } | 616 | } |
617 | 617 | ||
618 | if (bus->rb.area) | 618 | if (bus->rb.area) |
619 | bus->io_ops->dma_free_pages(bus, &bus->rb); | 619 | snd_dma_free_pages(&bus->rb); |
620 | if (bus->posbuf.area) | 620 | if (bus->posbuf.area) |
621 | bus->io_ops->dma_free_pages(bus, &bus->posbuf); | 621 | snd_dma_free_pages(&bus->posbuf); |
622 | } | 622 | } |
623 | EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages); | 623 | EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages); |
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 55d53b89ac21..fc68d4ce0a37 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c | |||
@@ -680,8 +680,8 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, | |||
680 | azx_dev->locked = true; | 680 | azx_dev->locked = true; |
681 | spin_unlock_irq(&bus->reg_lock); | 681 | spin_unlock_irq(&bus->reg_lock); |
682 | 682 | ||
683 | err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG, | 683 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, |
684 | byte_size, bufp); | 684 | byte_size, bufp); |
685 | if (err < 0) | 685 | if (err < 0) |
686 | goto err_alloc; | 686 | goto err_alloc; |
687 | 687 | ||
@@ -707,7 +707,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, | |||
707 | return azx_dev->stream_tag; | 707 | return azx_dev->stream_tag; |
708 | 708 | ||
709 | error: | 709 | error: |
710 | bus->io_ops->dma_free_pages(bus, bufp); | 710 | snd_dma_free_pages(bufp); |
711 | err_alloc: | 711 | err_alloc: |
712 | spin_lock_irq(&bus->reg_lock); | 712 | spin_lock_irq(&bus->reg_lock); |
713 | azx_dev->locked = false; | 713 | azx_dev->locked = false; |
@@ -754,7 +754,7 @@ void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, | |||
754 | azx_dev->period_bytes = 0; | 754 | azx_dev->period_bytes = 0; |
755 | azx_dev->format_val = 0; | 755 | azx_dev->format_val = 0; |
756 | 756 | ||
757 | bus->io_ops->dma_free_pages(bus, dmab); | 757 | snd_dma_free_pages(dmab); |
758 | dmab->area = NULL; | 758 | dmab->area = NULL; |
759 | 759 | ||
760 | spin_lock_irq(&bus->reg_lock); | 760 | spin_lock_irq(&bus->reg_lock); |
diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c new file mode 100644 index 000000000000..daede96f28ee --- /dev/null +++ b/sound/hda/intel-nhlt.c | |||
@@ -0,0 +1,107 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright (c) 2015-2019 Intel Corporation | ||
3 | |||
4 | #include <linux/acpi.h> | ||
5 | #include <sound/intel-nhlt.h> | ||
6 | |||
7 | #define NHLT_ACPI_HEADER_SIG "NHLT" | ||
8 | |||
9 | /* Unique identification for getting NHLT blobs */ | ||
10 | static guid_t osc_guid = | ||
11 | GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, | ||
12 | 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); | ||
13 | |||
14 | struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) | ||
15 | { | ||
16 | acpi_handle handle; | ||
17 | union acpi_object *obj; | ||
18 | struct nhlt_resource_desc *nhlt_ptr; | ||
19 | struct nhlt_acpi_table *nhlt_table = NULL; | ||
20 | |||
21 | handle = ACPI_HANDLE(dev); | ||
22 | if (!handle) { | ||
23 | dev_err(dev, "Didn't find ACPI_HANDLE\n"); | ||
24 | return NULL; | ||
25 | } | ||
26 | |||
27 | obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); | ||
28 | |||
29 | if (!obj) | ||
30 | return NULL; | ||
31 | |||
32 | if (obj->type != ACPI_TYPE_BUFFER) { | ||
33 | dev_dbg(dev, "No NHLT table found\n"); | ||
34 | ACPI_FREE(obj); | ||
35 | return NULL; | ||
36 | } | ||
37 | |||
38 | nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; | ||
39 | if (nhlt_ptr->length) | ||
40 | nhlt_table = (struct nhlt_acpi_table *) | ||
41 | memremap(nhlt_ptr->min_addr, nhlt_ptr->length, | ||
42 | MEMREMAP_WB); | ||
43 | ACPI_FREE(obj); | ||
44 | if (nhlt_table && | ||
45 | (strncmp(nhlt_table->header.signature, | ||
46 | NHLT_ACPI_HEADER_SIG, | ||
47 | strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { | ||
48 | memunmap(nhlt_table); | ||
49 | dev_err(dev, "NHLT ACPI header signature incorrect\n"); | ||
50 | return NULL; | ||
51 | } | ||
52 | return nhlt_table; | ||
53 | } | ||
54 | EXPORT_SYMBOL_GPL(intel_nhlt_init); | ||
55 | |||
56 | void intel_nhlt_free(struct nhlt_acpi_table *nhlt) | ||
57 | { | ||
58 | memunmap((void *)nhlt); | ||
59 | } | ||
60 | EXPORT_SYMBOL_GPL(intel_nhlt_free); | ||
61 | |||
62 | int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) | ||
63 | { | ||
64 | struct nhlt_endpoint *epnt; | ||
65 | struct nhlt_dmic_array_config *cfg; | ||
66 | struct nhlt_vendor_dmic_array_config *cfg_vendor; | ||
67 | unsigned int dmic_geo = 0; | ||
68 | u8 j; | ||
69 | |||
70 | if (!nhlt) | ||
71 | return 0; | ||
72 | |||
73 | epnt = (struct nhlt_endpoint *)nhlt->desc; | ||
74 | |||
75 | for (j = 0; j < nhlt->endpoint_count; j++) { | ||
76 | if (epnt->linktype == NHLT_LINK_DMIC) { | ||
77 | cfg = (struct nhlt_dmic_array_config *) | ||
78 | (epnt->config.caps); | ||
79 | switch (cfg->array_type) { | ||
80 | case NHLT_MIC_ARRAY_2CH_SMALL: | ||
81 | case NHLT_MIC_ARRAY_2CH_BIG: | ||
82 | dmic_geo = MIC_ARRAY_2CH; | ||
83 | break; | ||
84 | |||
85 | case NHLT_MIC_ARRAY_4CH_1ST_GEOM: | ||
86 | case NHLT_MIC_ARRAY_4CH_L_SHAPED: | ||
87 | case NHLT_MIC_ARRAY_4CH_2ND_GEOM: | ||
88 | dmic_geo = MIC_ARRAY_4CH; | ||
89 | break; | ||
90 | case NHLT_MIC_ARRAY_VENDOR_DEFINED: | ||
91 | cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg; | ||
92 | dmic_geo = cfg_vendor->nb_mics; | ||
93 | break; | ||
94 | default: | ||
95 | dev_warn(dev, "undefined DMIC array_type 0x%0x\n", | ||
96 | cfg->array_type); | ||
97 | } | ||
98 | } | ||
99 | epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); | ||
100 | } | ||
101 | |||
102 | return dmic_geo; | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo); | ||
105 | |||
106 | MODULE_LICENSE("GPL v2"); | ||
107 | MODULE_DESCRIPTION("Intel NHLT driver"); | ||
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 35d934309cb2..dae47a45b2b8 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -12,6 +12,7 @@ config SND_HDA_INTEL | |||
12 | tristate "HD Audio PCI" | 12 | tristate "HD Audio PCI" |
13 | depends on SND_PCI | 13 | depends on SND_PCI |
14 | select SND_HDA | 14 | select SND_HDA |
15 | select SND_INTEL_NHLT if ACPI | ||
15 | help | 16 | help |
16 | Say Y here to include support for Intel "High Definition | 17 | Say Y here to include support for Intel "High Definition |
17 | Audio" (Azalia) and its compatible devices. | 18 | Audio" (Azalia) and its compatible devices. |
@@ -22,10 +23,20 @@ config SND_HDA_INTEL | |||
22 | To compile this driver as a module, choose M here: the module | 23 | To compile this driver as a module, choose M here: the module |
23 | will be called snd-hda-intel. | 24 | will be called snd-hda-intel. |
24 | 25 | ||
26 | config SND_HDA_INTEL_DETECT_DMIC | ||
27 | bool "DMIC detection and probe abort" | ||
28 | depends on SND_HDA_INTEL | ||
29 | help | ||
30 | Say Y to detect digital microphones on SKL+ devices. DMICs | ||
31 | cannot be handled by the HDaudio legacy driver and are | ||
32 | currently only supported by the SOF driver. | ||
33 | If unsure say N. | ||
34 | |||
25 | config SND_HDA_TEGRA | 35 | config SND_HDA_TEGRA |
26 | tristate "NVIDIA Tegra HD Audio" | 36 | tristate "NVIDIA Tegra HD Audio" |
27 | depends on ARCH_TEGRA | 37 | depends on ARCH_TEGRA |
28 | select SND_HDA | 38 | select SND_HDA |
39 | select SND_HDA_ALIGNED_MMIO | ||
29 | help | 40 | help |
30 | Say Y here to support the HDA controller present in NVIDIA | 41 | Say Y here to support the HDA controller present in NVIDIA |
31 | Tegra SoCs | 42 | Tegra SoCs |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 51f10ed9bc43..a2fb19129219 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -846,7 +846,13 @@ static void snd_hda_codec_dev_release(struct device *dev) | |||
846 | snd_hda_sysfs_clear(codec); | 846 | snd_hda_sysfs_clear(codec); |
847 | kfree(codec->modelname); | 847 | kfree(codec->modelname); |
848 | kfree(codec->wcaps); | 848 | kfree(codec->wcaps); |
849 | kfree(codec); | 849 | |
850 | /* | ||
851 | * In the case of ASoC HD-audio, hda_codec is device managed. | ||
852 | * It will be freed when the ASoC device is removed. | ||
853 | */ | ||
854 | if (codec->core.type == HDA_DEV_LEGACY) | ||
855 | kfree(codec); | ||
850 | } | 856 | } |
851 | 857 | ||
852 | #define DEV_NAME_LEN 31 | 858 | #define DEV_NAME_LEN 31 |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 48d863736b3c..97a43a28b9e4 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -1207,14 +1207,12 @@ void snd_hda_bus_reset(struct hda_bus *bus) | |||
1207 | } | 1207 | } |
1208 | 1208 | ||
1209 | /* HD-audio bus initialization */ | 1209 | /* HD-audio bus initialization */ |
1210 | int azx_bus_init(struct azx *chip, const char *model, | 1210 | int azx_bus_init(struct azx *chip, const char *model) |
1211 | const struct hdac_io_ops *io_ops) | ||
1212 | { | 1211 | { |
1213 | struct hda_bus *bus = &chip->bus; | 1212 | struct hda_bus *bus = &chip->bus; |
1214 | int err; | 1213 | int err; |
1215 | 1214 | ||
1216 | err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops, | 1215 | err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops); |
1217 | io_ops); | ||
1218 | if (err < 0) | 1216 | if (err < 0) |
1219 | return err; | 1217 | return err; |
1220 | 1218 | ||
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index f2a6df5e6bcb..82e26442724b 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -206,8 +206,7 @@ void azx_stop_chip(struct azx *chip); | |||
206 | irqreturn_t azx_interrupt(int irq, void *dev_id); | 206 | irqreturn_t azx_interrupt(int irq, void *dev_id); |
207 | 207 | ||
208 | /* Codec interface */ | 208 | /* Codec interface */ |
209 | int azx_bus_init(struct azx *chip, const char *model, | 209 | int azx_bus_init(struct azx *chip, const char *model); |
210 | const struct hdac_io_ops *io_ops); | ||
211 | int azx_probe_codecs(struct azx *chip, unsigned int max_slots); | 210 | int azx_probe_codecs(struct azx *chip, unsigned int max_slots); |
212 | int azx_codec_configure(struct azx *chip); | 211 | int azx_codec_configure(struct azx *chip); |
213 | int azx_init_streams(struct azx *chip); | 212 | int azx_init_streams(struct azx *chip); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 99fc0917339b..2d0db3c9f335 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <sound/initval.h> | 46 | #include <sound/initval.h> |
47 | #include <sound/hdaudio.h> | 47 | #include <sound/hdaudio.h> |
48 | #include <sound/hda_i915.h> | 48 | #include <sound/hda_i915.h> |
49 | #include <sound/intel-nhlt.h> | ||
49 | #include <linux/vgaarb.h> | 50 | #include <linux/vgaarb.h> |
50 | #include <linux/vga_switcheroo.h> | 51 | #include <linux/vga_switcheroo.h> |
51 | #include <linux/firmware.h> | 52 | #include <linux/firmware.h> |
@@ -125,6 +126,7 @@ static char *patch[SNDRV_CARDS]; | |||
125 | static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = | 126 | static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = |
126 | CONFIG_SND_HDA_INPUT_BEEP_MODE}; | 127 | CONFIG_SND_HDA_INPUT_BEEP_MODE}; |
127 | #endif | 128 | #endif |
129 | static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC); | ||
128 | 130 | ||
129 | module_param_array(index, int, NULL, 0444); | 131 | module_param_array(index, int, NULL, 0444); |
130 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); | 132 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); |
@@ -159,6 +161,8 @@ module_param_array(beep_mode, bool, NULL, 0444); | |||
159 | MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " | 161 | MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " |
160 | "(0=off, 1=on) (default=1)."); | 162 | "(0=off, 1=on) (default=1)."); |
161 | #endif | 163 | #endif |
164 | module_param(dmic_detect, bool, 0444); | ||
165 | MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms"); | ||
162 | 166 | ||
163 | #ifdef CONFIG_PM | 167 | #ifdef CONFIG_PM |
164 | static int param_set_xint(const char *val, const struct kernel_param *kp); | 168 | static int param_set_xint(const char *val, const struct kernel_param *kp); |
@@ -1684,7 +1688,6 @@ static int default_bdl_pos_adj(struct azx *chip) | |||
1684 | /* | 1688 | /* |
1685 | * constructor | 1689 | * constructor |
1686 | */ | 1690 | */ |
1687 | static const struct hdac_io_ops pci_hda_io_ops; | ||
1688 | static const struct hda_controller_ops pci_hda_ops; | 1691 | static const struct hda_controller_ops pci_hda_ops; |
1689 | 1692 | ||
1690 | static int azx_create(struct snd_card *card, struct pci_dev *pci, | 1693 | static int azx_create(struct snd_card *card, struct pci_dev *pci, |
@@ -1744,13 +1747,17 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1744 | else | 1747 | else |
1745 | chip->bdl_pos_adj = bdl_pos_adj[dev]; | 1748 | chip->bdl_pos_adj = bdl_pos_adj[dev]; |
1746 | 1749 | ||
1747 | err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); | 1750 | err = azx_bus_init(chip, model[dev]); |
1748 | if (err < 0) { | 1751 | if (err < 0) { |
1749 | kfree(hda); | 1752 | kfree(hda); |
1750 | pci_disable_device(pci); | 1753 | pci_disable_device(pci); |
1751 | return err; | 1754 | return err; |
1752 | } | 1755 | } |
1753 | 1756 | ||
1757 | /* use the non-cached pages in non-snoop mode */ | ||
1758 | if (!azx_snoop(chip)) | ||
1759 | azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC; | ||
1760 | |||
1754 | /* Workaround for a communication error on CFL (bko#199007) and CNL */ | 1761 | /* Workaround for a communication error on CFL (bko#199007) and CNL */ |
1755 | if (IS_CFL(pci) || IS_CNL(pci)) | 1762 | if (IS_CFL(pci) || IS_CNL(pci)) |
1756 | azx_bus(chip)->polling_mode = 1; | 1763 | azx_bus(chip)->polling_mode = 1; |
@@ -1985,41 +1992,6 @@ static void azx_firmware_cb(const struct firmware *fw, void *context) | |||
1985 | } | 1992 | } |
1986 | #endif | 1993 | #endif |
1987 | 1994 | ||
1988 | /* | ||
1989 | * HDA controller ops. | ||
1990 | */ | ||
1991 | |||
1992 | /* PCI register access. */ | ||
1993 | static void pci_azx_writel(u32 value, u32 __iomem *addr) | ||
1994 | { | ||
1995 | writel(value, addr); | ||
1996 | } | ||
1997 | |||
1998 | static u32 pci_azx_readl(u32 __iomem *addr) | ||
1999 | { | ||
2000 | return readl(addr); | ||
2001 | } | ||
2002 | |||
2003 | static void pci_azx_writew(u16 value, u16 __iomem *addr) | ||
2004 | { | ||
2005 | writew(value, addr); | ||
2006 | } | ||
2007 | |||
2008 | static u16 pci_azx_readw(u16 __iomem *addr) | ||
2009 | { | ||
2010 | return readw(addr); | ||
2011 | } | ||
2012 | |||
2013 | static void pci_azx_writeb(u8 value, u8 __iomem *addr) | ||
2014 | { | ||
2015 | writeb(value, addr); | ||
2016 | } | ||
2017 | |||
2018 | static u8 pci_azx_readb(u8 __iomem *addr) | ||
2019 | { | ||
2020 | return readb(addr); | ||
2021 | } | ||
2022 | |||
2023 | static int disable_msi_reset_irq(struct azx *chip) | 1995 | static int disable_msi_reset_irq(struct azx *chip) |
2024 | { | 1996 | { |
2025 | struct hdac_bus *bus = azx_bus(chip); | 1997 | struct hdac_bus *bus = azx_bus(chip); |
@@ -2036,24 +2008,6 @@ static int disable_msi_reset_irq(struct azx *chip) | |||
2036 | return 0; | 2008 | return 0; |
2037 | } | 2009 | } |
2038 | 2010 | ||
2039 | /* DMA page allocation helpers. */ | ||
2040 | static int dma_alloc_pages(struct hdac_bus *bus, | ||
2041 | int type, | ||
2042 | size_t size, | ||
2043 | struct snd_dma_buffer *buf) | ||
2044 | { | ||
2045 | struct azx *chip = bus_to_azx(bus); | ||
2046 | |||
2047 | if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV) | ||
2048 | type = SNDRV_DMA_TYPE_DEV_UC; | ||
2049 | return snd_dma_alloc_pages(type, bus->dev, size, buf); | ||
2050 | } | ||
2051 | |||
2052 | static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) | ||
2053 | { | ||
2054 | snd_dma_free_pages(buf); | ||
2055 | } | ||
2056 | |||
2057 | static void pcm_mmap_prepare(struct snd_pcm_substream *substream, | 2011 | static void pcm_mmap_prepare(struct snd_pcm_substream *substream, |
2058 | struct vm_area_struct *area) | 2012 | struct vm_area_struct *area) |
2059 | { | 2013 | { |
@@ -2065,23 +2019,31 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, | |||
2065 | #endif | 2019 | #endif |
2066 | } | 2020 | } |
2067 | 2021 | ||
2068 | static const struct hdac_io_ops pci_hda_io_ops = { | ||
2069 | .reg_writel = pci_azx_writel, | ||
2070 | .reg_readl = pci_azx_readl, | ||
2071 | .reg_writew = pci_azx_writew, | ||
2072 | .reg_readw = pci_azx_readw, | ||
2073 | .reg_writeb = pci_azx_writeb, | ||
2074 | .reg_readb = pci_azx_readb, | ||
2075 | .dma_alloc_pages = dma_alloc_pages, | ||
2076 | .dma_free_pages = dma_free_pages, | ||
2077 | }; | ||
2078 | |||
2079 | static const struct hda_controller_ops pci_hda_ops = { | 2022 | static const struct hda_controller_ops pci_hda_ops = { |
2080 | .disable_msi_reset_irq = disable_msi_reset_irq, | 2023 | .disable_msi_reset_irq = disable_msi_reset_irq, |
2081 | .pcm_mmap_prepare = pcm_mmap_prepare, | 2024 | .pcm_mmap_prepare = pcm_mmap_prepare, |
2082 | .position_check = azx_position_check, | 2025 | .position_check = azx_position_check, |
2083 | }; | 2026 | }; |
2084 | 2027 | ||
2028 | static int azx_check_dmic(struct pci_dev *pci, struct azx *chip) | ||
2029 | { | ||
2030 | struct nhlt_acpi_table *nhlt; | ||
2031 | int ret = 0; | ||
2032 | |||
2033 | if (chip->driver_type == AZX_DRIVER_SKL && | ||
2034 | pci->class != 0x040300) { | ||
2035 | nhlt = intel_nhlt_init(&pci->dev); | ||
2036 | if (nhlt) { | ||
2037 | if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) { | ||
2038 | ret = -ENODEV; | ||
2039 | dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n"); | ||
2040 | } | ||
2041 | intel_nhlt_free(nhlt); | ||
2042 | } | ||
2043 | } | ||
2044 | return ret; | ||
2045 | } | ||
2046 | |||
2085 | static int azx_probe(struct pci_dev *pci, | 2047 | static int azx_probe(struct pci_dev *pci, |
2086 | const struct pci_device_id *pci_id) | 2048 | const struct pci_device_id *pci_id) |
2087 | { | 2049 | { |
@@ -2112,6 +2074,17 @@ static int azx_probe(struct pci_dev *pci, | |||
2112 | card->private_data = chip; | 2074 | card->private_data = chip; |
2113 | hda = container_of(chip, struct hda_intel, chip); | 2075 | hda = container_of(chip, struct hda_intel, chip); |
2114 | 2076 | ||
2077 | /* | ||
2078 | * stop probe if digital microphones detected on Skylake+ platform | ||
2079 | * with the DSP enabled. This is an opt-in behavior defined at build | ||
2080 | * time or at run-time with a module parameter | ||
2081 | */ | ||
2082 | if (dmic_detect) { | ||
2083 | err = azx_check_dmic(pci, chip); | ||
2084 | if (err < 0) | ||
2085 | goto out_free; | ||
2086 | } | ||
2087 | |||
2115 | pci_set_drvdata(pci, card); | 2088 | pci_set_drvdata(pci, card); |
2116 | 2089 | ||
2117 | err = register_vga_switcheroo(chip); | 2090 | err = register_vga_switcheroo(chip); |
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 7dbe9f39fc79..8350954b7986 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -75,88 +75,6 @@ MODULE_PARM_DESC(power_save, | |||
75 | #define power_save 0 | 75 | #define power_save 0 |
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | /* | ||
79 | * DMA page allocation ops. | ||
80 | */ | ||
81 | static int dma_alloc_pages(struct hdac_bus *bus, int type, size_t size, | ||
82 | struct snd_dma_buffer *buf) | ||
83 | { | ||
84 | return snd_dma_alloc_pages(type, bus->dev, size, buf); | ||
85 | } | ||
86 | |||
87 | static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) | ||
88 | { | ||
89 | snd_dma_free_pages(buf); | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Register access ops. Tegra HDA register access is DWORD only. | ||
94 | */ | ||
95 | static void hda_tegra_writel(u32 value, u32 __iomem *addr) | ||
96 | { | ||
97 | writel(value, addr); | ||
98 | } | ||
99 | |||
100 | static u32 hda_tegra_readl(u32 __iomem *addr) | ||
101 | { | ||
102 | return readl(addr); | ||
103 | } | ||
104 | |||
105 | static void hda_tegra_writew(u16 value, u16 __iomem *addr) | ||
106 | { | ||
107 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
108 | void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); | ||
109 | u32 v; | ||
110 | |||
111 | v = readl(dword_addr); | ||
112 | v &= ~(0xffff << shift); | ||
113 | v |= value << shift; | ||
114 | writel(v, dword_addr); | ||
115 | } | ||
116 | |||
117 | static u16 hda_tegra_readw(u16 __iomem *addr) | ||
118 | { | ||
119 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
120 | void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); | ||
121 | u32 v; | ||
122 | |||
123 | v = readl(dword_addr); | ||
124 | return (v >> shift) & 0xffff; | ||
125 | } | ||
126 | |||
127 | static void hda_tegra_writeb(u8 value, u8 __iomem *addr) | ||
128 | { | ||
129 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
130 | void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); | ||
131 | u32 v; | ||
132 | |||
133 | v = readl(dword_addr); | ||
134 | v &= ~(0xff << shift); | ||
135 | v |= value << shift; | ||
136 | writel(v, dword_addr); | ||
137 | } | ||
138 | |||
139 | static u8 hda_tegra_readb(u8 __iomem *addr) | ||
140 | { | ||
141 | unsigned int shift = ((unsigned long)(addr) & 0x3) << 3; | ||
142 | void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3); | ||
143 | u32 v; | ||
144 | |||
145 | v = readl(dword_addr); | ||
146 | return (v >> shift) & 0xff; | ||
147 | } | ||
148 | |||
149 | static const struct hdac_io_ops hda_tegra_io_ops = { | ||
150 | .reg_writel = hda_tegra_writel, | ||
151 | .reg_readl = hda_tegra_readl, | ||
152 | .reg_writew = hda_tegra_writew, | ||
153 | .reg_readw = hda_tegra_readw, | ||
154 | .reg_writeb = hda_tegra_writeb, | ||
155 | .reg_readb = hda_tegra_readb, | ||
156 | .dma_alloc_pages = dma_alloc_pages, | ||
157 | .dma_free_pages = dma_free_pages, | ||
158 | }; | ||
159 | |||
160 | static const struct hda_controller_ops hda_tegra_ops; /* nothing special */ | 78 | static const struct hda_controller_ops hda_tegra_ops; /* nothing special */ |
161 | 79 | ||
162 | static void hda_tegra_init(struct hda_tegra *hda) | 80 | static void hda_tegra_init(struct hda_tegra *hda) |
@@ -475,7 +393,7 @@ static int hda_tegra_create(struct snd_card *card, | |||
475 | 393 | ||
476 | INIT_WORK(&hda->probe_work, hda_tegra_probe_work); | 394 | INIT_WORK(&hda->probe_work, hda_tegra_probe_work); |
477 | 395 | ||
478 | err = azx_bus_init(chip, NULL, &hda_tegra_io_ops); | 396 | err = azx_bus_init(chip, NULL); |
479 | if (err < 0) | 397 | if (err < 0) |
480 | return err; | 398 | return err; |
481 | 399 | ||
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index dc86e4073001..bdc305cece6e 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -51,7 +51,6 @@ source "sound/soc/dwc/Kconfig" | |||
51 | source "sound/soc/fsl/Kconfig" | 51 | source "sound/soc/fsl/Kconfig" |
52 | source "sound/soc/hisilicon/Kconfig" | 52 | source "sound/soc/hisilicon/Kconfig" |
53 | source "sound/soc/jz4740/Kconfig" | 53 | source "sound/soc/jz4740/Kconfig" |
54 | source "sound/soc/nuc900/Kconfig" | ||
55 | source "sound/soc/kirkwood/Kconfig" | 54 | source "sound/soc/kirkwood/Kconfig" |
56 | source "sound/soc/img/Kconfig" | 55 | source "sound/soc/img/Kconfig" |
57 | source "sound/soc/intel/Kconfig" | 56 | source "sound/soc/intel/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index d90ce8a32887..861a21b79484 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o | 2 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o |
3 | snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o | 3 | snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o |
4 | snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o | 4 | snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o |
5 | 5 | ||
@@ -39,7 +39,6 @@ obj-$(CONFIG_SND_SOC) += intel/ | |||
39 | obj-$(CONFIG_SND_SOC) += mediatek/ | 39 | obj-$(CONFIG_SND_SOC) += mediatek/ |
40 | obj-$(CONFIG_SND_SOC) += meson/ | 40 | obj-$(CONFIG_SND_SOC) += meson/ |
41 | obj-$(CONFIG_SND_SOC) += mxs/ | 41 | obj-$(CONFIG_SND_SOC) += mxs/ |
42 | obj-$(CONFIG_SND_SOC) += nuc900/ | ||
43 | obj-$(CONFIG_SND_SOC) += kirkwood/ | 42 | obj-$(CONFIG_SND_SOC) += kirkwood/ |
44 | obj-$(CONFIG_SND_SOC) += pxa/ | 43 | obj-$(CONFIG_SND_SOC) += pxa/ |
45 | obj-$(CONFIG_SND_SOC) += qcom/ | 44 | obj-$(CONFIG_SND_SOC) += qcom/ |
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index d26653f81416..52225b4b6382 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c | |||
@@ -1251,8 +1251,7 @@ static int acp_audio_probe(struct platform_device *pdev) | |||
1251 | if (!audio_drv_data) | 1251 | if (!audio_drv_data) |
1252 | return -ENOMEM; | 1252 | return -ENOMEM; |
1253 | 1253 | ||
1254 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1254 | audio_drv_data->acp_mmio = devm_platform_ioremap_resource(pdev, 0); |
1255 | audio_drv_data->acp_mmio = devm_ioremap_resource(&pdev->dev, res); | ||
1256 | if (IS_ERR(audio_drv_data->acp_mmio)) | 1255 | if (IS_ERR(audio_drv_data->acp_mmio)) |
1257 | return PTR_ERR(audio_drv_data->acp_mmio); | 1256 | return PTR_ERR(audio_drv_data->acp_mmio); |
1258 | 1257 | ||
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 06c1d5ce642c..f118c229ed82 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig | |||
@@ -12,25 +12,31 @@ if SND_ATMEL_SOC | |||
12 | config SND_ATMEL_SOC_PDC | 12 | config SND_ATMEL_SOC_PDC |
13 | tristate | 13 | tristate |
14 | depends on HAS_DMA | 14 | depends on HAS_DMA |
15 | default m if SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=m | ||
16 | default y if SND_ATMEL_SOC_SSC_PDC=y || (SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=y) | ||
17 | |||
18 | config SND_ATMEL_SOC_SSC_PDC | ||
19 | tristate | ||
20 | 15 | ||
21 | config SND_ATMEL_SOC_DMA | 16 | config SND_ATMEL_SOC_DMA |
22 | tristate | 17 | tristate |
23 | select SND_SOC_GENERIC_DMAENGINE_PCM | 18 | select SND_SOC_GENERIC_DMAENGINE_PCM |
24 | default m if SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=m | ||
25 | default y if SND_ATMEL_SOC_SSC_DMA=y || (SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=y) | ||
26 | |||
27 | config SND_ATMEL_SOC_SSC_DMA | ||
28 | tristate | ||
29 | 19 | ||
30 | config SND_ATMEL_SOC_SSC | 20 | config SND_ATMEL_SOC_SSC |
31 | tristate | 21 | tristate |
32 | default y if SND_ATMEL_SOC_SSC_DMA=y || SND_ATMEL_SOC_SSC_PDC=y | 22 | |
33 | default m if SND_ATMEL_SOC_SSC_DMA=m || SND_ATMEL_SOC_SSC_PDC=m | 23 | config SND_ATMEL_SOC_SSC_PDC |
24 | tristate "SoC PCM DAI support for AT91 SSC controller using PDC" | ||
25 | depends on ATMEL_SSC | ||
26 | select SND_ATMEL_SOC_PDC | ||
27 | select SND_ATMEL_SOC_SSC | ||
28 | help | ||
29 | Say Y or M if you want to add support for Atmel SSC interface | ||
30 | in PDC mode configured using audio-graph-card in device-tree. | ||
31 | |||
32 | config SND_ATMEL_SOC_SSC_DMA | ||
33 | tristate "SoC PCM DAI support for AT91 SSC controller using DMA" | ||
34 | depends on ATMEL_SSC | ||
35 | select SND_ATMEL_SOC_DMA | ||
36 | select SND_ATMEL_SOC_SSC | ||
37 | help | ||
38 | Say Y or M if you want to add support for Atmel SSC interface | ||
39 | in DMA mode configured using audio-graph-card in device-tree. | ||
34 | 40 | ||
35 | config SND_AT91_SOC_SAM9G20_WM8731 | 41 | config SND_AT91_SOC_SAM9G20_WM8731 |
36 | tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" | 42 | tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" |
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 0f2c574f27f1..e98601eccfa3 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c | |||
@@ -571,11 +571,8 @@ static int atmel_classd_probe(struct platform_device *pdev) | |||
571 | dd->pdata = pdata; | 571 | dd->pdata = pdata; |
572 | 572 | ||
573 | dd->irq = platform_get_irq(pdev, 0); | 573 | dd->irq = platform_get_irq(pdev, 0); |
574 | if (dd->irq < 0) { | 574 | if (dd->irq < 0) |
575 | ret = dd->irq; | 575 | return dd->irq; |
576 | dev_err(dev, "failed to could not get irq: %d\n", ret); | ||
577 | return ret; | ||
578 | } | ||
579 | 576 | ||
580 | dd->pclk = devm_clk_get(dev, "pclk"); | 577 | dd->pclk = devm_clk_get(dev, "pclk"); |
581 | if (IS_ERR(dd->pclk)) { | 578 | if (IS_ERR(dd->pclk)) { |
diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index e09c28349e0d..04ec6f0af179 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c | |||
@@ -612,11 +612,8 @@ static int atmel_pdmic_probe(struct platform_device *pdev) | |||
612 | dd->dev = dev; | 612 | dd->dev = dev; |
613 | 613 | ||
614 | dd->irq = platform_get_irq(pdev, 0); | 614 | dd->irq = platform_get_irq(pdev, 0); |
615 | if (dd->irq < 0) { | 615 | if (dd->irq < 0) |
616 | ret = dd->irq; | 616 | return dd->irq; |
617 | dev_err(dev, "failed to get irq: %d\n", ret); | ||
618 | return ret; | ||
619 | } | ||
620 | 617 | ||
621 | dd->pclk = devm_clk_get(dev, "pclk"); | 618 | dd->pclk = devm_clk_get(dev, "pclk"); |
622 | if (IS_ERR(dd->pclk)) { | 619 | if (IS_ERR(dd->pclk)) { |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 6f89483ac88c..48e9eef34c0f 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -471,7 +471,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
471 | int dir, channels, bits; | 471 | int dir, channels, bits; |
472 | u32 tfmr, rfmr, tcmr, rcmr; | 472 | u32 tfmr, rfmr, tcmr, rcmr; |
473 | int ret; | 473 | int ret; |
474 | int fslen, fslen_ext; | 474 | int fslen, fslen_ext, fs_osync, fs_edge; |
475 | u32 cmr_div; | 475 | u32 cmr_div; |
476 | u32 tcmr_period; | 476 | u32 tcmr_period; |
477 | u32 rcmr_period; | 477 | u32 rcmr_period; |
@@ -558,226 +558,45 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
558 | /* | 558 | /* |
559 | * Compute SSC register settings. | 559 | * Compute SSC register settings. |
560 | */ | 560 | */ |
561 | switch (ssc_p->daifmt | ||
562 | & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { | ||
563 | 561 | ||
564 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: | 562 | fslen_ext = (bits - 1) / 16; |
565 | /* | 563 | fslen = (bits - 1) % 16; |
566 | * I2S format, SSC provides BCLK and LRC clocks. | ||
567 | * | ||
568 | * The SSC transmit and receive clocks are generated | ||
569 | * from the MCK divider, and the BCLK signal | ||
570 | * is output on the SSC TK line. | ||
571 | */ | ||
572 | 564 | ||
573 | if (bits > 16 && !ssc->pdata->has_fslen_ext) { | 565 | switch (ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
574 | dev_err(dai->dev, | ||
575 | "sample size %d is too large for SSC device\n", | ||
576 | bits); | ||
577 | return -EINVAL; | ||
578 | } | ||
579 | 566 | ||
580 | fslen_ext = (bits - 1) / 16; | 567 | case SND_SOC_DAIFMT_LEFT_J: |
581 | fslen = (bits - 1) % 16; | 568 | fs_osync = SSC_FSOS_POSITIVE; |
582 | 569 | fs_edge = SSC_START_RISING_RF; | |
583 | rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | 570 | |
584 | | SSC_BF(RCMR_STTDLY, START_DELAY) | 571 | rcmr = SSC_BF(RCMR_STTDLY, 0); |
585 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | 572 | tcmr = SSC_BF(TCMR_STTDLY, 0); |
586 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
587 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
588 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | ||
589 | |||
590 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) | ||
591 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
592 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
593 | | SSC_BF(RFMR_FSLEN, fslen) | ||
594 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
595 | | SSC_BIT(RFMR_MSBF) | ||
596 | | SSC_BF(RFMR_LOOP, 0) | ||
597 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
598 | |||
599 | tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | ||
600 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
601 | | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | ||
602 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
603 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | ||
604 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | ||
605 | |||
606 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) | ||
607 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
608 | | SSC_BF(TFMR_FSDEN, 0) | ||
609 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
610 | | SSC_BF(TFMR_FSLEN, fslen) | ||
611 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
612 | | SSC_BIT(TFMR_MSBF) | ||
613 | | SSC_BF(TFMR_DATDEF, 0) | ||
614 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
615 | break; | ||
616 | 573 | ||
617 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: | ||
618 | /* I2S format, CODEC supplies BCLK and LRC clocks. */ | ||
619 | rcmr = SSC_BF(RCMR_PERIOD, 0) | ||
620 | | SSC_BF(RCMR_STTDLY, START_DELAY) | ||
621 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | ||
622 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
623 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
624 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
625 | SSC_CKS_PIN : SSC_CKS_CLOCK); | ||
626 | |||
627 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
628 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | ||
629 | | SSC_BF(RFMR_FSLEN, 0) | ||
630 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
631 | | SSC_BIT(RFMR_MSBF) | ||
632 | | SSC_BF(RFMR_LOOP, 0) | ||
633 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
634 | |||
635 | tcmr = SSC_BF(TCMR_PERIOD, 0) | ||
636 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
637 | | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | ||
638 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
639 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | ||
640 | | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? | ||
641 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
642 | |||
643 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
644 | | SSC_BF(TFMR_FSDEN, 0) | ||
645 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | ||
646 | | SSC_BF(TFMR_FSLEN, 0) | ||
647 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
648 | | SSC_BIT(TFMR_MSBF) | ||
649 | | SSC_BF(TFMR_DATDEF, 0) | ||
650 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
651 | break; | 574 | break; |
652 | 575 | ||
653 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFS: | 576 | case SND_SOC_DAIFMT_I2S: |
654 | /* I2S format, CODEC supplies BCLK, SSC supplies LRCLK. */ | 577 | fs_osync = SSC_FSOS_NEGATIVE; |
655 | if (bits > 16 && !ssc->pdata->has_fslen_ext) { | 578 | fs_edge = SSC_START_FALLING_RF; |
656 | dev_err(dai->dev, | ||
657 | "sample size %d is too large for SSC device\n", | ||
658 | bits); | ||
659 | return -EINVAL; | ||
660 | } | ||
661 | 579 | ||
662 | fslen_ext = (bits - 1) / 16; | 580 | rcmr = SSC_BF(RCMR_STTDLY, 1); |
663 | fslen = (bits - 1) % 16; | 581 | tcmr = SSC_BF(TCMR_STTDLY, 1); |
664 | |||
665 | rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | ||
666 | | SSC_BF(RCMR_STTDLY, START_DELAY) | ||
667 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | ||
668 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
669 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
670 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
671 | SSC_CKS_PIN : SSC_CKS_CLOCK); | ||
672 | |||
673 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) | ||
674 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
675 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
676 | | SSC_BF(RFMR_FSLEN, fslen) | ||
677 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
678 | | SSC_BIT(RFMR_MSBF) | ||
679 | | SSC_BF(RFMR_LOOP, 0) | ||
680 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
681 | |||
682 | tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | ||
683 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
684 | | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | ||
685 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
686 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | ||
687 | | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? | ||
688 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
689 | |||
690 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) | ||
691 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_NEGATIVE) | ||
692 | | SSC_BF(TFMR_FSDEN, 0) | ||
693 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
694 | | SSC_BF(TFMR_FSLEN, fslen) | ||
695 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
696 | | SSC_BIT(TFMR_MSBF) | ||
697 | | SSC_BF(TFMR_DATDEF, 0) | ||
698 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
699 | break; | ||
700 | 582 | ||
701 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: | ||
702 | /* | ||
703 | * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. | ||
704 | * | ||
705 | * The SSC transmit and receive clocks are generated from the | ||
706 | * MCK divider, and the BCLK signal is output | ||
707 | * on the SSC TK line. | ||
708 | */ | ||
709 | rcmr = SSC_BF(RCMR_PERIOD, rcmr_period) | ||
710 | | SSC_BF(RCMR_STTDLY, 1) | ||
711 | | SSC_BF(RCMR_START, SSC_START_RISING_RF) | ||
712 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
713 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
714 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | ||
715 | |||
716 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
717 | | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) | ||
718 | | SSC_BF(RFMR_FSLEN, 0) | ||
719 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
720 | | SSC_BIT(RFMR_MSBF) | ||
721 | | SSC_BF(RFMR_LOOP, 0) | ||
722 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
723 | |||
724 | tcmr = SSC_BF(TCMR_PERIOD, tcmr_period) | ||
725 | | SSC_BF(TCMR_STTDLY, 1) | ||
726 | | SSC_BF(TCMR_START, SSC_START_RISING_RF) | ||
727 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
728 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | ||
729 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | ||
730 | |||
731 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
732 | | SSC_BF(TFMR_FSDEN, 0) | ||
733 | | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) | ||
734 | | SSC_BF(TFMR_FSLEN, 0) | ||
735 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
736 | | SSC_BIT(TFMR_MSBF) | ||
737 | | SSC_BF(TFMR_DATDEF, 0) | ||
738 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
739 | break; | 583 | break; |
740 | 584 | ||
741 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: | 585 | case SND_SOC_DAIFMT_DSP_A: |
742 | /* | 586 | /* |
743 | * DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks. | 587 | * DSP/PCM Mode A format |
744 | * | 588 | * |
745 | * Data is transferred on first BCLK after LRC pulse rising | 589 | * Data is transferred on first BCLK after LRC pulse rising |
746 | * edge.If stereo, the right channel data is contiguous with | 590 | * edge.If stereo, the right channel data is contiguous with |
747 | * the left channel data. | 591 | * the left channel data. |
748 | */ | 592 | */ |
749 | rcmr = SSC_BF(RCMR_PERIOD, 0) | 593 | fs_osync = SSC_FSOS_POSITIVE; |
750 | | SSC_BF(RCMR_STTDLY, START_DELAY) | 594 | fs_edge = SSC_START_RISING_RF; |
751 | | SSC_BF(RCMR_START, SSC_START_RISING_RF) | 595 | fslen = fslen_ext = 0; |
752 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | 596 | |
753 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | 597 | rcmr = SSC_BF(RCMR_STTDLY, 1); |
754 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | 598 | tcmr = SSC_BF(TCMR_STTDLY, 1); |
755 | SSC_CKS_PIN : SSC_CKS_CLOCK); | 599 | |
756 | |||
757 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
758 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | ||
759 | | SSC_BF(RFMR_FSLEN, 0) | ||
760 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
761 | | SSC_BIT(RFMR_MSBF) | ||
762 | | SSC_BF(RFMR_LOOP, 0) | ||
763 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
764 | |||
765 | tcmr = SSC_BF(TCMR_PERIOD, 0) | ||
766 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
767 | | SSC_BF(TCMR_START, SSC_START_RISING_RF) | ||
768 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
769 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | ||
770 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
771 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
772 | |||
773 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
774 | | SSC_BF(TFMR_FSDEN, 0) | ||
775 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | ||
776 | | SSC_BF(TFMR_FSLEN, 0) | ||
777 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
778 | | SSC_BIT(TFMR_MSBF) | ||
779 | | SSC_BF(TFMR_DATDEF, 0) | ||
780 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
781 | break; | 600 | break; |
782 | 601 | ||
783 | default: | 602 | default: |
@@ -785,6 +604,70 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
785 | ssc_p->daifmt); | 604 | ssc_p->daifmt); |
786 | return -EINVAL; | 605 | return -EINVAL; |
787 | } | 606 | } |
607 | |||
608 | if (!atmel_ssc_cfs(ssc_p)) { | ||
609 | fslen = fslen_ext = 0; | ||
610 | rcmr_period = tcmr_period = 0; | ||
611 | fs_osync = SSC_FSOS_NONE; | ||
612 | } | ||
613 | |||
614 | rcmr |= SSC_BF(RCMR_START, fs_edge); | ||
615 | tcmr |= SSC_BF(TCMR_START, fs_edge); | ||
616 | |||
617 | if (atmel_ssc_cbs(ssc_p)) { | ||
618 | /* | ||
619 | * SSC provides BCLK | ||
620 | * | ||
621 | * The SSC transmit and receive clocks are generated from the | ||
622 | * MCK divider, and the BCLK signal is output | ||
623 | * on the SSC TK line. | ||
624 | */ | ||
625 | rcmr |= SSC_BF(RCMR_CKS, SSC_CKS_DIV) | ||
626 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE); | ||
627 | |||
628 | tcmr |= SSC_BF(TCMR_CKS, SSC_CKS_DIV) | ||
629 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS); | ||
630 | } else { | ||
631 | rcmr |= SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
632 | SSC_CKS_PIN : SSC_CKS_CLOCK) | ||
633 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE); | ||
634 | |||
635 | tcmr |= SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? | ||
636 | SSC_CKS_CLOCK : SSC_CKS_PIN) | ||
637 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE); | ||
638 | } | ||
639 | |||
640 | rcmr |= SSC_BF(RCMR_PERIOD, rcmr_period) | ||
641 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING); | ||
642 | |||
643 | tcmr |= SSC_BF(TCMR_PERIOD, tcmr_period) | ||
644 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING); | ||
645 | |||
646 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) | ||
647 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
648 | | SSC_BF(RFMR_FSOS, fs_osync) | ||
649 | | SSC_BF(RFMR_FSLEN, fslen) | ||
650 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
651 | | SSC_BIT(RFMR_MSBF) | ||
652 | | SSC_BF(RFMR_LOOP, 0) | ||
653 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
654 | |||
655 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) | ||
656 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
657 | | SSC_BF(TFMR_FSDEN, 0) | ||
658 | | SSC_BF(TFMR_FSOS, fs_osync) | ||
659 | | SSC_BF(TFMR_FSLEN, fslen) | ||
660 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
661 | | SSC_BIT(TFMR_MSBF) | ||
662 | | SSC_BF(TFMR_DATDEF, 0) | ||
663 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
664 | |||
665 | if (fslen_ext && !ssc->pdata->has_fslen_ext) { | ||
666 | dev_err(dai->dev, "sample size %d is too large for SSC device\n", | ||
667 | bits); | ||
668 | return -EINVAL; | ||
669 | } | ||
670 | |||
788 | pr_debug("atmel_ssc_hw_params: " | 671 | pr_debug("atmel_ssc_hw_params: " |
789 | "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", | 672 | "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", |
790 | rcmr, rfmr, tcmr, tfmr); | 673 | rcmr, rfmr, tcmr, tfmr); |
diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index ab7d5f98e759..befc2a3a05b0 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c | |||
@@ -392,11 +392,11 @@ static int mchp_i2s_mcc_clk_get_rate_diff(struct clk *clk, | |||
392 | } | 392 | } |
393 | 393 | ||
394 | static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, | 394 | static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, |
395 | unsigned int bclk, unsigned int *mra) | 395 | unsigned int bclk, unsigned int *mra, |
396 | unsigned long *best_rate) | ||
396 | { | 397 | { |
397 | unsigned long clk_rate; | 398 | unsigned long clk_rate; |
398 | unsigned long lcm_rate; | 399 | unsigned long lcm_rate; |
399 | unsigned long best_rate = 0; | ||
400 | unsigned long best_diff_rate = ~0; | 400 | unsigned long best_diff_rate = ~0; |
401 | unsigned int sysclk; | 401 | unsigned int sysclk; |
402 | struct clk *best_clk = NULL; | 402 | struct clk *best_clk = NULL; |
@@ -423,7 +423,7 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, | |||
423 | (clk_rate == bclk || clk_rate / (bclk * 2) <= GENMASK(5, 0)); | 423 | (clk_rate == bclk || clk_rate / (bclk * 2) <= GENMASK(5, 0)); |
424 | clk_rate += lcm_rate) { | 424 | clk_rate += lcm_rate) { |
425 | ret = mchp_i2s_mcc_clk_get_rate_diff(dev->gclk, clk_rate, | 425 | ret = mchp_i2s_mcc_clk_get_rate_diff(dev->gclk, clk_rate, |
426 | &best_clk, &best_rate, | 426 | &best_clk, best_rate, |
427 | &best_diff_rate); | 427 | &best_diff_rate); |
428 | if (ret) { | 428 | if (ret) { |
429 | dev_err(dev->dev, "gclk error for rate %lu: %d", | 429 | dev_err(dev->dev, "gclk error for rate %lu: %d", |
@@ -437,7 +437,7 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, | |||
437 | } | 437 | } |
438 | 438 | ||
439 | ret = mchp_i2s_mcc_clk_get_rate_diff(dev->pclk, clk_rate, | 439 | ret = mchp_i2s_mcc_clk_get_rate_diff(dev->pclk, clk_rate, |
440 | &best_clk, &best_rate, | 440 | &best_clk, best_rate, |
441 | &best_diff_rate); | 441 | &best_diff_rate); |
442 | if (ret) { | 442 | if (ret) { |
443 | dev_err(dev->dev, "pclk error for rate %lu: %d", | 443 | dev_err(dev->dev, "pclk error for rate %lu: %d", |
@@ -459,33 +459,17 @@ static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev, | |||
459 | 459 | ||
460 | dev_dbg(dev->dev, "source CLK is %s with rate %lu, diff %lu\n", | 460 | dev_dbg(dev->dev, "source CLK is %s with rate %lu, diff %lu\n", |
461 | best_clk == dev->pclk ? "pclk" : "gclk", | 461 | best_clk == dev->pclk ? "pclk" : "gclk", |
462 | best_rate, best_diff_rate); | 462 | *best_rate, best_diff_rate); |
463 | |||
464 | /* set the rate */ | ||
465 | ret = clk_set_rate(best_clk, best_rate); | ||
466 | if (ret) { | ||
467 | dev_err(dev->dev, "unable to set rate %lu to %s: %d\n", | ||
468 | best_rate, best_clk == dev->pclk ? "PCLK" : "GCLK", | ||
469 | ret); | ||
470 | return ret; | ||
471 | } | ||
472 | 463 | ||
473 | /* Configure divisors */ | 464 | /* Configure divisors */ |
474 | if (dev->sysclk) | 465 | if (dev->sysclk) |
475 | *mra |= MCHP_I2SMCC_MRA_IMCKDIV(best_rate / (2 * sysclk)); | 466 | *mra |= MCHP_I2SMCC_MRA_IMCKDIV(*best_rate / (2 * sysclk)); |
476 | *mra |= MCHP_I2SMCC_MRA_ISCKDIV(best_rate / (2 * bclk)); | 467 | *mra |= MCHP_I2SMCC_MRA_ISCKDIV(*best_rate / (2 * bclk)); |
477 | 468 | ||
478 | if (best_clk == dev->gclk) { | 469 | if (best_clk == dev->gclk) |
479 | *mra |= MCHP_I2SMCC_MRA_SRCCLK_GCLK; | 470 | *mra |= MCHP_I2SMCC_MRA_SRCCLK_GCLK; |
480 | ret = clk_prepare(dev->gclk); | 471 | else |
481 | if (ret < 0) | ||
482 | dev_err(dev->dev, "unable to prepare GCLK: %d\n", ret); | ||
483 | else | ||
484 | dev->gclk_use = 1; | ||
485 | } else { | ||
486 | *mra |= MCHP_I2SMCC_MRA_SRCCLK_PCLK; | 472 | *mra |= MCHP_I2SMCC_MRA_SRCCLK_PCLK; |
487 | dev->gclk_use = 0; | ||
488 | } | ||
489 | 473 | ||
490 | return 0; | 474 | return 0; |
491 | } | 475 | } |
@@ -502,6 +486,7 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, | |||
502 | struct snd_pcm_hw_params *params, | 486 | struct snd_pcm_hw_params *params, |
503 | struct snd_soc_dai *dai) | 487 | struct snd_soc_dai *dai) |
504 | { | 488 | { |
489 | unsigned long rate = 0; | ||
505 | struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai); | 490 | struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai); |
506 | u32 mra = 0; | 491 | u32 mra = 0; |
507 | u32 mrb = 0; | 492 | u32 mrb = 0; |
@@ -640,6 +625,17 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, | |||
640 | return -EINVAL; | 625 | return -EINVAL; |
641 | } | 626 | } |
642 | 627 | ||
628 | if (set_divs) { | ||
629 | bclk_rate = frame_length * params_rate(params); | ||
630 | ret = mchp_i2s_mcc_config_divs(dev, bclk_rate, &mra, | ||
631 | &rate); | ||
632 | if (ret) { | ||
633 | dev_err(dev->dev, | ||
634 | "unable to configure the divisors: %d\n", ret); | ||
635 | return ret; | ||
636 | } | ||
637 | } | ||
638 | |||
643 | /* | 639 | /* |
644 | * If we are already running, the wanted setup must be | 640 | * If we are already running, the wanted setup must be |
645 | * the same with the one that's currently ongoing | 641 | * the same with the one that's currently ongoing |
@@ -656,19 +652,27 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, | |||
656 | return 0; | 652 | return 0; |
657 | } | 653 | } |
658 | 654 | ||
659 | /* Save the number of channels to know what interrupts to enable */ | 655 | if (mra & MCHP_I2SMCC_MRA_SRCCLK_GCLK && !dev->gclk_use) { |
660 | dev->channels = channels; | 656 | /* set the rate */ |
661 | 657 | ret = clk_set_rate(dev->gclk, rate); | |
662 | if (set_divs) { | ||
663 | bclk_rate = frame_length * params_rate(params); | ||
664 | ret = mchp_i2s_mcc_config_divs(dev, bclk_rate, &mra); | ||
665 | if (ret) { | 658 | if (ret) { |
666 | dev_err(dev->dev, "unable to configure the divisors: %d\n", | 659 | dev_err(dev->dev, |
667 | ret); | 660 | "unable to set rate %lu to GCLK: %d\n", |
661 | rate, ret); | ||
662 | return ret; | ||
663 | } | ||
664 | |||
665 | ret = clk_prepare(dev->gclk); | ||
666 | if (ret < 0) { | ||
667 | dev_err(dev->dev, "unable to prepare GCLK: %d\n", ret); | ||
668 | return ret; | 668 | return ret; |
669 | } | 669 | } |
670 | dev->gclk_use = 1; | ||
670 | } | 671 | } |
671 | 672 | ||
673 | /* Save the number of channels to know what interrupts to enable */ | ||
674 | dev->channels = channels; | ||
675 | |||
672 | ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra); | 676 | ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra); |
673 | if (ret < 0) { | 677 | if (ret < 0) { |
674 | if (dev->gclk_use) { | 678 | if (dev->gclk_use) { |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 21e5f6aed7f3..08bc04e2da2a 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -363,7 +363,7 @@ static const struct snd_soc_component_driver au1xpsc_ac97_component = { | |||
363 | static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | 363 | static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) |
364 | { | 364 | { |
365 | int ret; | 365 | int ret; |
366 | struct resource *iores, *dmares; | 366 | struct resource *dmares; |
367 | unsigned long sel; | 367 | unsigned long sel; |
368 | struct au1xpsc_audio_data *wd; | 368 | struct au1xpsc_audio_data *wd; |
369 | 369 | ||
@@ -374,8 +374,7 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
374 | 374 | ||
375 | mutex_init(&wd->lock); | 375 | mutex_init(&wd->lock); |
376 | 376 | ||
377 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 377 | wd->mmio = devm_platform_ioremap_resource(pdev, 0); |
378 | wd->mmio = devm_ioremap_resource(&pdev->dev, iores); | ||
379 | if (IS_ERR(wd->mmio)) | 378 | if (IS_ERR(wd->mmio)) |
380 | return PTR_ERR(wd->mmio); | 379 | return PTR_ERR(wd->mmio); |
381 | 380 | ||
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 076303f96b8c..767ce950d0da 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c | |||
@@ -291,7 +291,7 @@ static const struct snd_soc_component_driver au1xpsc_i2s_component = { | |||
291 | 291 | ||
292 | static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) | 292 | static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) |
293 | { | 293 | { |
294 | struct resource *iores, *dmares; | 294 | struct resource *dmares; |
295 | unsigned long sel; | 295 | unsigned long sel; |
296 | struct au1xpsc_audio_data *wd; | 296 | struct au1xpsc_audio_data *wd; |
297 | 297 | ||
@@ -300,8 +300,7 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
300 | if (!wd) | 300 | if (!wd) |
301 | return -ENOMEM; | 301 | return -ENOMEM; |
302 | 302 | ||
303 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 303 | wd->mmio = devm_platform_ioremap_resource(pdev, 0); |
304 | wd->mmio = devm_ioremap_resource(&pdev->dev, iores); | ||
305 | if (IS_ERR(wd->mmio)) | 304 | if (IS_ERR(wd->mmio)) |
306 | return PTR_ERR(wd->mmio); | 305 | return PTR_ERR(wd->mmio); |
307 | 306 | ||
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index 5ef80f3d446a..e6a12e271b07 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c | |||
@@ -828,7 +828,6 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) | |||
828 | { | 828 | { |
829 | struct bcm2835_i2s_dev *dev; | 829 | struct bcm2835_i2s_dev *dev; |
830 | int ret; | 830 | int ret; |
831 | struct resource *mem; | ||
832 | void __iomem *base; | 831 | void __iomem *base; |
833 | const __be32 *addr; | 832 | const __be32 *addr; |
834 | dma_addr_t dma_base; | 833 | dma_addr_t dma_base; |
@@ -848,8 +847,7 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) | |||
848 | } | 847 | } |
849 | 848 | ||
850 | /* Request ioarea */ | 849 | /* Request ioarea */ |
851 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 850 | base = devm_platform_ioremap_resource(pdev, 0); |
852 | base = devm_ioremap_resource(&pdev->dev, mem); | ||
853 | if (IS_ERR(base)) | 851 | if (IS_ERR(base)) |
854 | return PTR_ERR(base); | 852 | return PTR_ERR(base); |
855 | 853 | ||
diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index 123ecf5479d7..8966b02844dc 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c | |||
@@ -639,7 +639,6 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, | |||
639 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 639 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
640 | struct snd_pcm_runtime *runtime = substream->runtime; | 640 | struct snd_pcm_runtime *runtime = substream->runtime; |
641 | struct cygnus_aio_port *aio; | 641 | struct cygnus_aio_port *aio; |
642 | int ret = 0; | ||
643 | 642 | ||
644 | aio = cygnus_dai_get_dma_data(substream); | 643 | aio = cygnus_dai_get_dma_data(substream); |
645 | dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum); | 644 | dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum); |
@@ -647,7 +646,7 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream, | |||
647 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 646 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
648 | runtime->dma_bytes = params_buffer_bytes(params); | 647 | runtime->dma_bytes = params_buffer_bytes(params); |
649 | 648 | ||
650 | return ret; | 649 | return 0; |
651 | } | 650 | } |
652 | 651 | ||
653 | static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream) | 652 | static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream) |
@@ -668,7 +667,6 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) | |||
668 | struct snd_pcm_runtime *runtime = substream->runtime; | 667 | struct snd_pcm_runtime *runtime = substream->runtime; |
669 | struct cygnus_aio_port *aio; | 668 | struct cygnus_aio_port *aio; |
670 | unsigned long bufsize, periodsize; | 669 | unsigned long bufsize, periodsize; |
671 | int ret = 0; | ||
672 | bool is_play; | 670 | bool is_play; |
673 | u32 start; | 671 | u32 start; |
674 | struct ringbuf_regs *p_rbuf = NULL; | 672 | struct ringbuf_regs *p_rbuf = NULL; |
@@ -693,7 +691,7 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream) | |||
693 | ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start, | 691 | ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start, |
694 | periodsize, bufsize); | 692 | periodsize, bufsize); |
695 | 693 | ||
696 | return ret; | 694 | return 0; |
697 | } | 695 | } |
698 | 696 | ||
699 | static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream) | 697 | static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream) |
diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index b7c358b48d8d..2f9357d7da96 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c | |||
@@ -1342,11 +1342,8 @@ static int cygnus_ssp_probe(struct platform_device *pdev) | |||
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | cygaud->irq_num = platform_get_irq(pdev, 0); | 1344 | cygaud->irq_num = platform_get_irq(pdev, 0); |
1345 | if (cygaud->irq_num <= 0) { | 1345 | if (cygaud->irq_num <= 0) |
1346 | dev_err(dev, "platform_get_irq failed\n"); | 1346 | return cygaud->irq_num; |
1347 | err = cygaud->irq_num; | ||
1348 | return err; | ||
1349 | } | ||
1350 | 1347 | ||
1351 | err = audio_clk_init(pdev, cygaud); | 1348 | err = audio_clk_init(pdev, cygaud); |
1352 | if (err) { | 1349 | if (err) { |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index 84c967fcab6b..e21eaa1893d1 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
@@ -362,7 +362,6 @@ static const struct snd_soc_component_driver ep93xx_ac97_component = { | |||
362 | static int ep93xx_ac97_probe(struct platform_device *pdev) | 362 | static int ep93xx_ac97_probe(struct platform_device *pdev) |
363 | { | 363 | { |
364 | struct ep93xx_ac97_info *info; | 364 | struct ep93xx_ac97_info *info; |
365 | struct resource *res; | ||
366 | int irq; | 365 | int irq; |
367 | int ret; | 366 | int ret; |
368 | 367 | ||
@@ -370,8 +369,7 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
370 | if (!info) | 369 | if (!info) |
371 | return -ENOMEM; | 370 | return -ENOMEM; |
372 | 371 | ||
373 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 372 | info->regs = devm_platform_ioremap_resource(pdev, 0); |
374 | info->regs = devm_ioremap_resource(&pdev->dev, res); | ||
375 | if (IS_ERR(info->regs)) | 373 | if (IS_ERR(info->regs)) |
376 | return PTR_ERR(info->regs); | 374 | return PTR_ERR(info->regs); |
377 | 375 | ||
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 0b4355e95f84..7d9cf67129d4 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c | |||
@@ -430,15 +430,13 @@ static const struct snd_soc_component_driver ep93xx_i2s_component = { | |||
430 | static int ep93xx_i2s_probe(struct platform_device *pdev) | 430 | static int ep93xx_i2s_probe(struct platform_device *pdev) |
431 | { | 431 | { |
432 | struct ep93xx_i2s_info *info; | 432 | struct ep93xx_i2s_info *info; |
433 | struct resource *res; | ||
434 | int err; | 433 | int err; |
435 | 434 | ||
436 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | 435 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); |
437 | if (!info) | 436 | if (!info) |
438 | return -ENOMEM; | 437 | return -ENOMEM; |
439 | 438 | ||
440 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 439 | info->regs = devm_platform_ioremap_resource(pdev, 0); |
441 | info->regs = devm_ioremap_resource(&pdev->dev, res); | ||
442 | if (IS_ERR(info->regs)) | 440 | if (IS_ERR(info->regs)) |
443 | return PTR_ERR(info->regs); | 441 | return PTR_ERR(info->regs); |
444 | 442 | ||
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index e982722b448e..00b2c43d28a1 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -529,10 +529,6 @@ static const struct snd_kcontrol_new pm860x_snd_controls[] = { | |||
529 | * DAPM Controls | 529 | * DAPM Controls |
530 | */ | 530 | */ |
531 | 531 | ||
532 | /* PCM Switch / PCM Interface */ | ||
533 | static const struct snd_kcontrol_new pcm_switch_controls = | ||
534 | SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0); | ||
535 | |||
536 | /* AUX1 Switch */ | 532 | /* AUX1 Switch */ |
537 | static const struct snd_kcontrol_new aux1_switch_controls = | 533 | static const struct snd_kcontrol_new aux1_switch_controls = |
538 | SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0); | 534 | SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0); |
@@ -549,17 +545,6 @@ static const struct snd_kcontrol_new lepa_switch_controls = | |||
549 | static const struct snd_kcontrol_new repa_switch_controls = | 545 | static const struct snd_kcontrol_new repa_switch_controls = |
550 | SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0); | 546 | SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0); |
551 | 547 | ||
552 | /* PCM Mux / Mux7 */ | ||
553 | static const char *aif1_text[] = { | ||
554 | "PCM L", "PCM R", | ||
555 | }; | ||
556 | |||
557 | static SOC_ENUM_SINGLE_DECL(aif1_enum, | ||
558 | PM860X_PCM_IFACE_3, 6, aif1_text); | ||
559 | |||
560 | static const struct snd_kcontrol_new aif1_mux = | ||
561 | SOC_DAPM_ENUM("PCM Mux", aif1_enum); | ||
562 | |||
563 | /* I2S Mux / Mux9 */ | 548 | /* I2S Mux / Mux9 */ |
564 | static const char *i2s_din_text[] = { | 549 | static const char *i2s_din_text[] = { |
565 | "DIN", "DIN1", | 550 | "DIN", "DIN1", |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f89a5346299..89238343e34d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -70,10 +70,12 @@ config SND_SOC_ALL_CODECS | |||
70 | select SND_SOC_CS43130 if I2C | 70 | select SND_SOC_CS43130 if I2C |
71 | select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI | 71 | select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI |
72 | select SND_SOC_CS4349 if I2C | 72 | select SND_SOC_CS4349 if I2C |
73 | select SND_SOC_CS47L15 if MFD_CS47L15 | ||
73 | select SND_SOC_CS47L24 if MFD_CS47L24 | 74 | select SND_SOC_CS47L24 if MFD_CS47L24 |
74 | select SND_SOC_CS47L35 if MFD_CS47L35 | 75 | select SND_SOC_CS47L35 if MFD_CS47L35 |
75 | select SND_SOC_CS47L85 if MFD_CS47L85 | 76 | select SND_SOC_CS47L85 if MFD_CS47L85 |
76 | select SND_SOC_CS47L90 if MFD_CS47L90 | 77 | select SND_SOC_CS47L90 if MFD_CS47L90 |
78 | select SND_SOC_CS47L92 if MFD_CS47L92 | ||
77 | select SND_SOC_CS53L30 if I2C | 79 | select SND_SOC_CS53L30 if I2C |
78 | select SND_SOC_CX20442 if TTY | 80 | select SND_SOC_CX20442 if TTY |
79 | select SND_SOC_CX2072X if I2C | 81 | select SND_SOC_CX2072X if I2C |
@@ -197,6 +199,7 @@ config SND_SOC_ALL_CODECS | |||
197 | select SND_SOC_TS3A227E if I2C | 199 | select SND_SOC_TS3A227E if I2C |
198 | select SND_SOC_TWL4030 if TWL4030_CORE | 200 | select SND_SOC_TWL4030 if TWL4030_CORE |
199 | select SND_SOC_TWL6040 if TWL6040_CORE | 201 | select SND_SOC_TWL6040 if TWL6040_CORE |
202 | select SND_SOC_UDA1334 if GPIOLIB | ||
200 | select SND_SOC_UDA134X | 203 | select SND_SOC_UDA134X |
201 | select SND_SOC_UDA1380 if I2C | 204 | select SND_SOC_UDA1380 if I2C |
202 | select SND_SOC_WCD9335 if SLIMBUS | 205 | select SND_SOC_WCD9335 if SLIMBUS |
@@ -581,6 +584,9 @@ config SND_SOC_CS4349 | |||
581 | tristate "Cirrus Logic CS4349 CODEC" | 584 | tristate "Cirrus Logic CS4349 CODEC" |
582 | depends on I2C | 585 | depends on I2C |
583 | 586 | ||
587 | config SND_SOC_CS47L15 | ||
588 | tristate | ||
589 | |||
584 | config SND_SOC_CS47L24 | 590 | config SND_SOC_CS47L24 |
585 | tristate | 591 | tristate |
586 | 592 | ||
@@ -593,6 +599,9 @@ config SND_SOC_CS47L85 | |||
593 | config SND_SOC_CS47L90 | 599 | config SND_SOC_CS47L90 |
594 | tristate | 600 | tristate |
595 | 601 | ||
602 | config SND_SOC_CS47L92 | ||
603 | tristate | ||
604 | |||
596 | # Cirrus Logic Quad-Channel ADC | 605 | # Cirrus Logic Quad-Channel ADC |
597 | config SND_SOC_CS53L30 | 606 | config SND_SOC_CS53L30 |
598 | tristate "Cirrus Logic CS53L30 CODEC" | 607 | tristate "Cirrus Logic CS53L30 CODEC" |
@@ -722,12 +731,16 @@ config SND_SOC_LOCHNAGAR_SC | |||
722 | 731 | ||
723 | config SND_SOC_MADERA | 732 | config SND_SOC_MADERA |
724 | tristate | 733 | tristate |
734 | default y if SND_SOC_CS47L15=y | ||
725 | default y if SND_SOC_CS47L35=y | 735 | default y if SND_SOC_CS47L35=y |
726 | default y if SND_SOC_CS47L85=y | 736 | default y if SND_SOC_CS47L85=y |
727 | default y if SND_SOC_CS47L90=y | 737 | default y if SND_SOC_CS47L90=y |
738 | default y if SND_SOC_CS47L92=y | ||
739 | default m if SND_SOC_CS47L15=m | ||
728 | default m if SND_SOC_CS47L35=m | 740 | default m if SND_SOC_CS47L35=m |
729 | default m if SND_SOC_CS47L85=m | 741 | default m if SND_SOC_CS47L85=m |
730 | default m if SND_SOC_CS47L90=m | 742 | default m if SND_SOC_CS47L90=m |
743 | default m if SND_SOC_CS47L92=m | ||
731 | 744 | ||
732 | config SND_SOC_MAX98088 | 745 | config SND_SOC_MAX98088 |
733 | tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" | 746 | tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" |
@@ -1195,6 +1208,14 @@ config SND_SOC_TWL4030 | |||
1195 | config SND_SOC_TWL6040 | 1208 | config SND_SOC_TWL6040 |
1196 | tristate | 1209 | tristate |
1197 | 1210 | ||
1211 | config SND_SOC_UDA1334 | ||
1212 | tristate "NXP UDA1334 DAC" | ||
1213 | depends on GPIOLIB | ||
1214 | help | ||
1215 | The UDA1334 is an NXP audio codec, supports the I2S-bus data format | ||
1216 | and has basic features such as de-emphasis (at 44.1 kHz sampling | ||
1217 | rate) and mute. | ||
1218 | |||
1198 | config SND_SOC_UDA134X | 1219 | config SND_SOC_UDA134X |
1199 | tristate | 1220 | tristate |
1200 | 1221 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5b4bb8cf4325..c498373dcc5f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -64,10 +64,12 @@ snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o | |||
64 | snd-soc-cs43130-objs := cs43130.o | 64 | snd-soc-cs43130-objs := cs43130.o |
65 | snd-soc-cs4341-objs := cs4341.o | 65 | snd-soc-cs4341-objs := cs4341.o |
66 | snd-soc-cs4349-objs := cs4349.o | 66 | snd-soc-cs4349-objs := cs4349.o |
67 | snd-soc-cs47l15-objs := cs47l15.o | ||
67 | snd-soc-cs47l24-objs := cs47l24.o | 68 | snd-soc-cs47l24-objs := cs47l24.o |
68 | snd-soc-cs47l35-objs := cs47l35.o | 69 | snd-soc-cs47l35-objs := cs47l35.o |
69 | snd-soc-cs47l85-objs := cs47l85.o | 70 | snd-soc-cs47l85-objs := cs47l85.o |
70 | snd-soc-cs47l90-objs := cs47l90.o | 71 | snd-soc-cs47l90-objs := cs47l90.o |
72 | snd-soc-cs47l92-objs := cs47l92.o | ||
71 | snd-soc-cs53l30-objs := cs53l30.o | 73 | snd-soc-cs53l30-objs := cs53l30.o |
72 | snd-soc-cx20442-objs := cx20442.o | 74 | snd-soc-cx20442-objs := cx20442.o |
73 | snd-soc-cx2072x-objs := cx2072x.o | 75 | snd-soc-cx2072x-objs := cx2072x.o |
@@ -210,6 +212,7 @@ snd-soc-tscs454-objs := tscs454.o | |||
210 | snd-soc-ts3a227e-objs := ts3a227e.o | 212 | snd-soc-ts3a227e-objs := ts3a227e.o |
211 | snd-soc-twl4030-objs := twl4030.o | 213 | snd-soc-twl4030-objs := twl4030.o |
212 | snd-soc-twl6040-objs := twl6040.o | 214 | snd-soc-twl6040-objs := twl6040.o |
215 | snd-soc-uda1334-objs := uda1334.o | ||
213 | snd-soc-uda134x-objs := uda134x.o | 216 | snd-soc-uda134x-objs := uda134x.o |
214 | snd-soc-uda1380-objs := uda1380.o | 217 | snd-soc-uda1380-objs := uda1380.o |
215 | snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o | 218 | snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o |
@@ -346,9 +349,11 @@ obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o | |||
346 | obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o | 349 | obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o |
347 | obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o | 350 | obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o |
348 | obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o | 351 | obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o |
352 | obj-$(CONFIG_SND_SOC_CS47L15) += snd-soc-cs47l15.o | ||
349 | obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o | 353 | obj-$(CONFIG_SND_SOC_CS47L35) += snd-soc-cs47l35.o |
350 | obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o | 354 | obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o |
351 | obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o | 355 | obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o |
356 | obj-$(CONFIG_SND_SOC_CS47L92) += snd-soc-cs47l92.o | ||
352 | obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o | 357 | obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o |
353 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 358 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
354 | obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o | 359 | obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o |
@@ -490,6 +495,7 @@ obj-$(CONFIG_SND_SOC_TSCS454) += snd-soc-tscs454.o | |||
490 | obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o | 495 | obj-$(CONFIG_SND_SOC_TS3A227E) += snd-soc-ts3a227e.o |
491 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o | 496 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o |
492 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | 497 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o |
498 | obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o | ||
493 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | 499 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o |
494 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o | 500 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
495 | obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o | 501 | obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 80dab5df9633..980e024a5720 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -413,15 +413,10 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = { | |||
413 | .ops = &ad193x_dai_ops, | 413 | .ops = &ad193x_dai_ops, |
414 | }; | 414 | }; |
415 | 415 | ||
416 | struct ad193x_reg_default { | ||
417 | unsigned int reg; | ||
418 | unsigned int val; | ||
419 | }; | ||
420 | |||
421 | /* codec register values to set after reset */ | 416 | /* codec register values to set after reset */ |
422 | static void ad193x_reg_default_init(struct ad193x_priv *ad193x) | 417 | static void ad193x_reg_default_init(struct ad193x_priv *ad193x) |
423 | { | 418 | { |
424 | const struct ad193x_reg_default reg_init[] = { | 419 | static const struct reg_sequence reg_init[] = { |
425 | { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ | 420 | { 0, 0x99 }, /* PLL_CLK_CTRL0: pll input: mclki/xi 12.288Mhz */ |
426 | { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ | 421 | { 1, 0x04 }, /* PLL_CLK_CTRL1: no on-chip Vref */ |
427 | { 2, 0x40 }, /* DAC_CTRL0: TDM mode */ | 422 | { 2, 0x40 }, /* DAC_CTRL0: TDM mode */ |
@@ -437,21 +432,17 @@ static void ad193x_reg_default_init(struct ad193x_priv *ad193x) | |||
437 | { 12, 0x00 }, /* DAC_L4_VOL: no attenuation */ | 432 | { 12, 0x00 }, /* DAC_L4_VOL: no attenuation */ |
438 | { 13, 0x00 }, /* DAC_R4_VOL: no attenuation */ | 433 | { 13, 0x00 }, /* DAC_R4_VOL: no attenuation */ |
439 | }; | 434 | }; |
440 | const struct ad193x_reg_default reg_adc_init[] = { | 435 | static const struct reg_sequence reg_adc_init[] = { |
441 | { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ | 436 | { 14, 0x03 }, /* ADC_CTRL0: high-pass filter enable */ |
442 | { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ | 437 | { 15, 0x43 }, /* ADC_CTRL1: sata delay=1, adc aux mode */ |
443 | { 16, 0x00 }, /* ADC_CTRL2: reset */ | 438 | { 16, 0x00 }, /* ADC_CTRL2: reset */ |
444 | }; | 439 | }; |
445 | int i; | ||
446 | 440 | ||
447 | for (i = 0; i < ARRAY_SIZE(reg_init); i++) | 441 | regmap_multi_reg_write(ad193x->regmap, reg_init, ARRAY_SIZE(reg_init)); |
448 | regmap_write(ad193x->regmap, reg_init[i].reg, reg_init[i].val); | ||
449 | 442 | ||
450 | if (ad193x_has_adc(ad193x)) { | 443 | if (ad193x_has_adc(ad193x)) { |
451 | for (i = 0; i < ARRAY_SIZE(reg_adc_init); i++) { | 444 | regmap_multi_reg_write(ad193x->regmap, reg_adc_init, |
452 | regmap_write(ad193x->regmap, reg_adc_init[i].reg, | 445 | ARRAY_SIZE(reg_adc_init)); |
453 | reg_adc_init[i].val); | ||
454 | } | ||
455 | } | 446 | } |
456 | } | 447 | } |
457 | 448 | ||
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 1d03a1348162..04b86a51e055 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
@@ -334,7 +334,7 @@ static struct cs4271_clk_cfg cs4271_clk_tab[] = { | |||
334 | {0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2}, | 334 | {0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2}, |
335 | }; | 335 | }; |
336 | 336 | ||
337 | #define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab) | 337 | #define CS4271_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab) |
338 | 338 | ||
339 | static int cs4271_hw_params(struct snd_pcm_substream *substream, | 339 | static int cs4271_hw_params(struct snd_pcm_substream *substream, |
340 | struct snd_pcm_hw_params *params, | 340 | struct snd_pcm_hw_params *params, |
@@ -383,13 +383,13 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, | |||
383 | val = CS4271_MODE1_MODE_4X; | 383 | val = CS4271_MODE1_MODE_4X; |
384 | 384 | ||
385 | ratio = cs4271->mclk / cs4271->rate; | 385 | ratio = cs4271->mclk / cs4271->rate; |
386 | for (i = 0; i < CS4171_NR_RATIOS; i++) | 386 | for (i = 0; i < CS4271_NR_RATIOS; i++) |
387 | if ((cs4271_clk_tab[i].master == cs4271->master) && | 387 | if ((cs4271_clk_tab[i].master == cs4271->master) && |
388 | (cs4271_clk_tab[i].speed_mode == val) && | 388 | (cs4271_clk_tab[i].speed_mode == val) && |
389 | (cs4271_clk_tab[i].ratio == ratio)) | 389 | (cs4271_clk_tab[i].ratio == ratio)) |
390 | break; | 390 | break; |
391 | 391 | ||
392 | if (i == CS4171_NR_RATIOS) { | 392 | if (i == CS4271_NR_RATIOS) { |
393 | dev_err(component->dev, "Invalid sample rate\n"); | 393 | dev_err(component->dev, "Invalid sample rate\n"); |
394 | return -EINVAL; | 394 | return -EINVAL; |
395 | } | 395 | } |
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index b4d7627525f9..ac569ab3d30f 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c | |||
@@ -199,14 +199,6 @@ static const struct soc_enum beep_bass_enum = | |||
199 | SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 1, | 199 | SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 1, |
200 | ARRAY_SIZE(beep_bass_text), beep_bass_text); | 200 | ARRAY_SIZE(beep_bass_text), beep_bass_text); |
201 | 201 | ||
202 | static const char * const adc_swap_text[] = { | ||
203 | "None", "A+B/2", "A-B/2", "Swap" | ||
204 | }; | ||
205 | |||
206 | static const struct soc_enum adc_swap_enum = | ||
207 | SOC_ENUM_SINGLE(CS42L56_MISC_ADC_CTL, 3, | ||
208 | ARRAY_SIZE(adc_swap_text), adc_swap_text); | ||
209 | |||
210 | static const char * const pgaa_mux_text[] = { | 202 | static const char * const pgaa_mux_text[] = { |
211 | "AIN1A", "AIN2A", "AIN3A"}; | 203 | "AIN1A", "AIN2A", "AIN3A"}; |
212 | 204 | ||
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index a81739367109..36089f8bcf0a 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -273,12 +273,6 @@ static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum, | |||
273 | CS42L73_MIXERCTL, 4, | 273 | CS42L73_MIXERCTL, 4, |
274 | cs42l73_spo_mixer_text); | 274 | cs42l73_spo_mixer_text); |
275 | 275 | ||
276 | static const struct snd_kcontrol_new vsp_output_mux = | ||
277 | SOC_DAPM_ENUM("Route", vsp_output_mux_enum); | ||
278 | |||
279 | static const struct snd_kcontrol_new xsp_output_mux = | ||
280 | SOC_DAPM_ENUM("Route", xsp_output_mux_enum); | ||
281 | |||
282 | static const struct snd_kcontrol_new hp_amp_ctl = | 276 | static const struct snd_kcontrol_new hp_amp_ctl = |
283 | SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1); | 277 | SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1); |
284 | 278 | ||
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 5b049fcdba20..94b1adb088fd 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c | |||
@@ -684,6 +684,8 @@ static int cs42xx8_runtime_suspend(struct device *dev) | |||
684 | #endif | 684 | #endif |
685 | 685 | ||
686 | const struct dev_pm_ops cs42xx8_pm = { | 686 | const struct dev_pm_ops cs42xx8_pm = { |
687 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | ||
688 | pm_runtime_force_resume) | ||
687 | SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) | 689 | SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) |
688 | }; | 690 | }; |
689 | EXPORT_SYMBOL_GPL(cs42xx8_pm); | 691 | EXPORT_SYMBOL_GPL(cs42xx8_pm); |
diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c new file mode 100644 index 000000000000..ece1276f38eb --- /dev/null +++ b/sound/soc/codecs/cs47l15.c | |||
@@ -0,0 +1,1490 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | // | ||
3 | // ALSA SoC Audio driver for CS47L15 codec | ||
4 | // | ||
5 | // Copyright (C) 2016-2019 Cirrus Logic, Inc. and | ||
6 | // Cirrus Logic International Semiconductor Ltd. | ||
7 | // | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/moduleparam.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/pm.h> | ||
15 | #include <linux/pm_runtime.h> | ||
16 | #include <linux/regmap.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/tlv.h> | ||
22 | |||
23 | #include <linux/irqchip/irq-madera.h> | ||
24 | #include <linux/mfd/madera/core.h> | ||
25 | #include <linux/mfd/madera/registers.h> | ||
26 | |||
27 | #include "madera.h" | ||
28 | #include "wm_adsp.h" | ||
29 | |||
30 | #define CS47L15_NUM_ADSP 1 | ||
31 | #define CS47L15_MONO_OUTPUTS 1 | ||
32 | |||
33 | /* Mid-mode registers */ | ||
34 | #define CS47L15_ADC_INT_BIAS_MASK 0x3800 | ||
35 | #define CS47L15_ADC_INT_BIAS_SHIFT 11 | ||
36 | #define CS47L15_PGA_BIAS_SEL_MASK 0x03 | ||
37 | #define CS47L15_PGA_BIAS_SEL_SHIFT 0 | ||
38 | |||
39 | #define DRV_NAME "cs47l15-codec" | ||
40 | |||
41 | struct cs47l15 { | ||
42 | struct madera_priv core; | ||
43 | struct madera_fll fll[2]; | ||
44 | |||
45 | bool in1_lp_mode; | ||
46 | }; | ||
47 | |||
48 | static const struct wm_adsp_region cs47l15_dsp1_regions[] = { | ||
49 | { .type = WMFW_ADSP2_PM, .base = 0x080000 }, | ||
50 | { .type = WMFW_ADSP2_ZM, .base = 0x0e0000 }, | ||
51 | { .type = WMFW_ADSP2_XM, .base = 0x0a0000 }, | ||
52 | { .type = WMFW_ADSP2_YM, .base = 0x0c0000 }, | ||
53 | }; | ||
54 | |||
55 | static const char * const cs47l15_outdemux_texts[] = { | ||
56 | "HPOUT", | ||
57 | "EPOUT", | ||
58 | }; | ||
59 | |||
60 | static SOC_ENUM_SINGLE_DECL(cs47l15_outdemux_enum, SND_SOC_NOPM, 0, | ||
61 | cs47l15_outdemux_texts); | ||
62 | |||
63 | static const struct snd_kcontrol_new cs47l15_outdemux = | ||
64 | SOC_DAPM_ENUM_EXT("HPOUT1 Demux", cs47l15_outdemux_enum, | ||
65 | madera_out1_demux_get, madera_out1_demux_put); | ||
66 | |||
67 | static int cs47l15_adsp_power_ev(struct snd_soc_dapm_widget *w, | ||
68 | struct snd_kcontrol *kcontrol, | ||
69 | int event) | ||
70 | { | ||
71 | struct snd_soc_component *component = | ||
72 | snd_soc_dapm_to_component(w->dapm); | ||
73 | struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); | ||
74 | struct madera_priv *priv = &cs47l15->core; | ||
75 | struct madera *madera = priv->madera; | ||
76 | unsigned int freq; | ||
77 | int ret; | ||
78 | |||
79 | ret = regmap_read(madera->regmap, MADERA_DSP_CLOCK_2, &freq); | ||
80 | if (ret != 0) { | ||
81 | dev_err(madera->dev, | ||
82 | "Failed to read MADERA_DSP_CLOCK_2: %d\n", ret); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | switch (event) { | ||
87 | case SND_SOC_DAPM_PRE_PMU: | ||
88 | ret = madera_set_adsp_clk(&cs47l15->core, w->shift, freq); | ||
89 | if (ret) | ||
90 | return ret; | ||
91 | break; | ||
92 | default: | ||
93 | break; | ||
94 | } | ||
95 | |||
96 | return wm_adsp_early_event(w, kcontrol, event); | ||
97 | } | ||
98 | |||
99 | #define CS47L15_NG_SRC(name, base) \ | ||
100 | SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ | ||
101 | SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ | ||
102 | SOC_SINGLE(name " NG SPKOUTL Switch", base, 6, 1, 0), \ | ||
103 | SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ | ||
104 | SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0) | ||
105 | |||
106 | static int cs47l15_in1_adc_get(struct snd_kcontrol *kcontrol, | ||
107 | struct snd_ctl_elem_value *ucontrol) | ||
108 | { | ||
109 | struct snd_soc_component *component = | ||
110 | snd_soc_kcontrol_component(kcontrol); | ||
111 | struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); | ||
112 | |||
113 | ucontrol->value.integer.value[0] = !!cs47l15->in1_lp_mode; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol, | ||
119 | struct snd_ctl_elem_value *ucontrol) | ||
120 | { | ||
121 | struct snd_soc_component *component = | ||
122 | snd_soc_kcontrol_component(kcontrol); | ||
123 | struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); | ||
124 | |||
125 | switch (ucontrol->value.integer.value[0]) { | ||
126 | case 0: | ||
127 | /* Set IN1 to normal mode */ | ||
128 | snd_soc_component_update_bits(component, MADERA_DMIC1L_CONTROL, | ||
129 | MADERA_IN1_OSR_MASK, | ||
130 | 5 << MADERA_IN1_OSR_SHIFT); | ||
131 | snd_soc_component_update_bits(component, CS47L15_ADC_INT_BIAS, | ||
132 | CS47L15_ADC_INT_BIAS_MASK, | ||
133 | 4 << CS47L15_ADC_INT_BIAS_SHIFT); | ||
134 | snd_soc_component_update_bits(component, CS47L15_PGA_BIAS_SEL, | ||
135 | CS47L15_PGA_BIAS_SEL_MASK, 0); | ||
136 | cs47l15->in1_lp_mode = false; | ||
137 | break; | ||
138 | default: | ||
139 | /* Set IN1 to LP mode */ | ||
140 | snd_soc_component_update_bits(component, MADERA_DMIC1L_CONTROL, | ||
141 | MADERA_IN1_OSR_MASK, | ||
142 | 4 << MADERA_IN1_OSR_SHIFT); | ||
143 | snd_soc_component_update_bits(component, CS47L15_ADC_INT_BIAS, | ||
144 | CS47L15_ADC_INT_BIAS_MASK, | ||
145 | 1 << CS47L15_ADC_INT_BIAS_SHIFT); | ||
146 | snd_soc_component_update_bits(component, CS47L15_PGA_BIAS_SEL, | ||
147 | CS47L15_PGA_BIAS_SEL_MASK, | ||
148 | 3 << CS47L15_PGA_BIAS_SEL_SHIFT); | ||
149 | cs47l15->in1_lp_mode = true; | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static const struct snd_kcontrol_new cs47l15_snd_controls[] = { | ||
157 | SOC_ENUM("IN1 OSR", madera_in_dmic_osr[0]), | ||
158 | SOC_ENUM("IN2 OSR", madera_in_dmic_osr[1]), | ||
159 | |||
160 | SOC_SINGLE_RANGE_TLV("IN1L Volume", MADERA_IN1L_CONTROL, | ||
161 | MADERA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), | ||
162 | SOC_SINGLE_RANGE_TLV("IN1R Volume", MADERA_IN1R_CONTROL, | ||
163 | MADERA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), | ||
164 | |||
165 | SOC_ENUM("IN HPF Cutoff Frequency", madera_in_hpf_cut_enum), | ||
166 | |||
167 | SOC_SINGLE("IN1L HPF Switch", MADERA_IN1L_CONTROL, MADERA_IN1L_HPF_SHIFT, 1, 0), | ||
168 | SOC_SINGLE("IN1R HPF Switch", MADERA_IN1R_CONTROL, MADERA_IN1R_HPF_SHIFT, 1, 0), | ||
169 | SOC_SINGLE("IN2L HPF Switch", MADERA_IN2L_CONTROL, MADERA_IN2L_HPF_SHIFT, 1, 0), | ||
170 | SOC_SINGLE("IN2R HPF Switch", MADERA_IN2R_CONTROL, MADERA_IN2R_HPF_SHIFT, 1, 0), | ||
171 | |||
172 | SOC_SINGLE_TLV("IN1L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1L, | ||
173 | MADERA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
174 | SOC_SINGLE_TLV("IN1R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1R, | ||
175 | MADERA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
176 | SOC_SINGLE_TLV("IN2L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2L, | ||
177 | MADERA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
178 | SOC_SINGLE_TLV("IN2R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2R, | ||
179 | MADERA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
180 | |||
181 | SOC_ENUM("Input Ramp Up", madera_in_vi_ramp), | ||
182 | SOC_ENUM("Input Ramp Down", madera_in_vd_ramp), | ||
183 | |||
184 | MADERA_MIXER_CONTROLS("EQ1", MADERA_EQ1MIX_INPUT_1_SOURCE), | ||
185 | MADERA_MIXER_CONTROLS("EQ2", MADERA_EQ2MIX_INPUT_1_SOURCE), | ||
186 | MADERA_MIXER_CONTROLS("EQ3", MADERA_EQ3MIX_INPUT_1_SOURCE), | ||
187 | MADERA_MIXER_CONTROLS("EQ4", MADERA_EQ4MIX_INPUT_1_SOURCE), | ||
188 | |||
189 | MADERA_EQ_CONTROL("EQ1 Coefficients", MADERA_EQ1_2), | ||
190 | SOC_SINGLE_TLV("EQ1 B1 Volume", MADERA_EQ1_1, MADERA_EQ1_B1_GAIN_SHIFT, | ||
191 | 24, 0, madera_eq_tlv), | ||
192 | SOC_SINGLE_TLV("EQ1 B2 Volume", MADERA_EQ1_1, MADERA_EQ1_B2_GAIN_SHIFT, | ||
193 | 24, 0, madera_eq_tlv), | ||
194 | SOC_SINGLE_TLV("EQ1 B3 Volume", MADERA_EQ1_1, MADERA_EQ1_B3_GAIN_SHIFT, | ||
195 | 24, 0, madera_eq_tlv), | ||
196 | SOC_SINGLE_TLV("EQ1 B4 Volume", MADERA_EQ1_2, MADERA_EQ1_B4_GAIN_SHIFT, | ||
197 | 24, 0, madera_eq_tlv), | ||
198 | SOC_SINGLE_TLV("EQ1 B5 Volume", MADERA_EQ1_2, MADERA_EQ1_B5_GAIN_SHIFT, | ||
199 | 24, 0, madera_eq_tlv), | ||
200 | |||
201 | MADERA_EQ_CONTROL("EQ2 Coefficients", MADERA_EQ2_2), | ||
202 | SOC_SINGLE_TLV("EQ2 B1 Volume", MADERA_EQ2_1, MADERA_EQ2_B1_GAIN_SHIFT, | ||
203 | 24, 0, madera_eq_tlv), | ||
204 | SOC_SINGLE_TLV("EQ2 B2 Volume", MADERA_EQ2_1, MADERA_EQ2_B2_GAIN_SHIFT, | ||
205 | 24, 0, madera_eq_tlv), | ||
206 | SOC_SINGLE_TLV("EQ2 B3 Volume", MADERA_EQ2_1, MADERA_EQ2_B3_GAIN_SHIFT, | ||
207 | 24, 0, madera_eq_tlv), | ||
208 | SOC_SINGLE_TLV("EQ2 B4 Volume", MADERA_EQ2_2, MADERA_EQ2_B4_GAIN_SHIFT, | ||
209 | 24, 0, madera_eq_tlv), | ||
210 | SOC_SINGLE_TLV("EQ2 B5 Volume", MADERA_EQ2_2, MADERA_EQ2_B5_GAIN_SHIFT, | ||
211 | 24, 0, madera_eq_tlv), | ||
212 | |||
213 | MADERA_EQ_CONTROL("EQ3 Coefficients", MADERA_EQ3_2), | ||
214 | SOC_SINGLE_TLV("EQ3 B1 Volume", MADERA_EQ3_1, MADERA_EQ3_B1_GAIN_SHIFT, | ||
215 | 24, 0, madera_eq_tlv), | ||
216 | SOC_SINGLE_TLV("EQ3 B2 Volume", MADERA_EQ3_1, MADERA_EQ3_B2_GAIN_SHIFT, | ||
217 | 24, 0, madera_eq_tlv), | ||
218 | SOC_SINGLE_TLV("EQ3 B3 Volume", MADERA_EQ3_1, MADERA_EQ3_B3_GAIN_SHIFT, | ||
219 | 24, 0, madera_eq_tlv), | ||
220 | SOC_SINGLE_TLV("EQ3 B4 Volume", MADERA_EQ3_2, MADERA_EQ3_B4_GAIN_SHIFT, | ||
221 | 24, 0, madera_eq_tlv), | ||
222 | SOC_SINGLE_TLV("EQ3 B5 Volume", MADERA_EQ3_2, MADERA_EQ3_B5_GAIN_SHIFT, | ||
223 | 24, 0, madera_eq_tlv), | ||
224 | |||
225 | MADERA_EQ_CONTROL("EQ4 Coefficients", MADERA_EQ4_2), | ||
226 | SOC_SINGLE_TLV("EQ4 B1 Volume", MADERA_EQ4_1, MADERA_EQ4_B1_GAIN_SHIFT, | ||
227 | 24, 0, madera_eq_tlv), | ||
228 | SOC_SINGLE_TLV("EQ4 B2 Volume", MADERA_EQ4_1, MADERA_EQ4_B2_GAIN_SHIFT, | ||
229 | 24, 0, madera_eq_tlv), | ||
230 | SOC_SINGLE_TLV("EQ4 B3 Volume", MADERA_EQ4_1, MADERA_EQ4_B3_GAIN_SHIFT, | ||
231 | 24, 0, madera_eq_tlv), | ||
232 | SOC_SINGLE_TLV("EQ4 B4 Volume", MADERA_EQ4_2, MADERA_EQ4_B4_GAIN_SHIFT, | ||
233 | 24, 0, madera_eq_tlv), | ||
234 | SOC_SINGLE_TLV("EQ4 B5 Volume", MADERA_EQ4_2, MADERA_EQ4_B5_GAIN_SHIFT, | ||
235 | 24, 0, madera_eq_tlv), | ||
236 | |||
237 | MADERA_MIXER_CONTROLS("DRC1L", MADERA_DRC1LMIX_INPUT_1_SOURCE), | ||
238 | MADERA_MIXER_CONTROLS("DRC1R", MADERA_DRC1RMIX_INPUT_1_SOURCE), | ||
239 | MADERA_MIXER_CONTROLS("DRC2L", MADERA_DRC2LMIX_INPUT_1_SOURCE), | ||
240 | MADERA_MIXER_CONTROLS("DRC2R", MADERA_DRC2RMIX_INPUT_1_SOURCE), | ||
241 | |||
242 | SND_SOC_BYTES_MASK("DRC1", MADERA_DRC1_CTRL1, 5, | ||
243 | MADERA_DRC1R_ENA | MADERA_DRC1L_ENA), | ||
244 | SND_SOC_BYTES_MASK("DRC2", MADERA_DRC2_CTRL1, 5, | ||
245 | MADERA_DRC2R_ENA | MADERA_DRC2L_ENA), | ||
246 | |||
247 | MADERA_MIXER_CONTROLS("LHPF1", MADERA_HPLP1MIX_INPUT_1_SOURCE), | ||
248 | MADERA_MIXER_CONTROLS("LHPF2", MADERA_HPLP2MIX_INPUT_1_SOURCE), | ||
249 | MADERA_MIXER_CONTROLS("LHPF3", MADERA_HPLP3MIX_INPUT_1_SOURCE), | ||
250 | MADERA_MIXER_CONTROLS("LHPF4", MADERA_HPLP4MIX_INPUT_1_SOURCE), | ||
251 | |||
252 | MADERA_LHPF_CONTROL("LHPF1 Coefficients", MADERA_HPLPF1_2), | ||
253 | MADERA_LHPF_CONTROL("LHPF2 Coefficients", MADERA_HPLPF2_2), | ||
254 | MADERA_LHPF_CONTROL("LHPF3 Coefficients", MADERA_HPLPF3_2), | ||
255 | MADERA_LHPF_CONTROL("LHPF4 Coefficients", MADERA_HPLPF4_2), | ||
256 | |||
257 | SOC_ENUM("LHPF1 Mode", madera_lhpf1_mode), | ||
258 | SOC_ENUM("LHPF2 Mode", madera_lhpf2_mode), | ||
259 | SOC_ENUM("LHPF3 Mode", madera_lhpf3_mode), | ||
260 | SOC_ENUM("LHPF4 Mode", madera_lhpf4_mode), | ||
261 | |||
262 | MADERA_RATE_ENUM("ISRC1 FSL", madera_isrc_fsl[0]), | ||
263 | MADERA_RATE_ENUM("ISRC2 FSL", madera_isrc_fsl[1]), | ||
264 | MADERA_RATE_ENUM("ISRC1 FSH", madera_isrc_fsh[0]), | ||
265 | MADERA_RATE_ENUM("ISRC2 FSH", madera_isrc_fsh[1]), | ||
266 | |||
267 | WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), | ||
268 | |||
269 | MADERA_MIXER_CONTROLS("DSP1L", MADERA_DSP1LMIX_INPUT_1_SOURCE), | ||
270 | MADERA_MIXER_CONTROLS("DSP1R", MADERA_DSP1RMIX_INPUT_1_SOURCE), | ||
271 | |||
272 | SOC_SINGLE_TLV("Noise Generator Volume", MADERA_COMFORT_NOISE_GENERATOR, | ||
273 | MADERA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, madera_noise_tlv), | ||
274 | |||
275 | MADERA_MIXER_CONTROLS("HPOUT1L", MADERA_OUT1LMIX_INPUT_1_SOURCE), | ||
276 | MADERA_MIXER_CONTROLS("HPOUT1R", MADERA_OUT1RMIX_INPUT_1_SOURCE), | ||
277 | MADERA_MIXER_CONTROLS("SPKOUTL", MADERA_OUT4LMIX_INPUT_1_SOURCE), | ||
278 | MADERA_MIXER_CONTROLS("SPKDAT1L", MADERA_OUT5LMIX_INPUT_1_SOURCE), | ||
279 | MADERA_MIXER_CONTROLS("SPKDAT1R", MADERA_OUT5RMIX_INPUT_1_SOURCE), | ||
280 | |||
281 | SOC_SINGLE("HPOUT1 SC Protect Switch", MADERA_HP1_SHORT_CIRCUIT_CTRL, | ||
282 | MADERA_HP1_SC_ENA_SHIFT, 1, 0), | ||
283 | |||
284 | SOC_SINGLE("SPKDAT1 High Performance Switch", MADERA_OUTPUT_PATH_CONFIG_5L, | ||
285 | MADERA_OUT5_OSR_SHIFT, 1, 0), | ||
286 | |||
287 | SOC_DOUBLE_R("HPOUT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_1L, | ||
288 | MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_MUTE_SHIFT, 1, 1), | ||
289 | SOC_SINGLE("Speaker Digital Switch", MADERA_DAC_DIGITAL_VOLUME_4L, | ||
290 | MADERA_OUT4L_MUTE_SHIFT, 1, 1), | ||
291 | SOC_DOUBLE_R("SPKDAT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_5L, | ||
292 | MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_MUTE_SHIFT, 1, 1), | ||
293 | |||
294 | SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_1L, | ||
295 | MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_VOL_SHIFT, | ||
296 | 0xbf, 0, madera_digital_tlv), | ||
297 | SOC_SINGLE_TLV("Speaker Digital Volume", MADERA_DAC_DIGITAL_VOLUME_4L, | ||
298 | MADERA_OUT4L_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
299 | SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_5L, | ||
300 | MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_VOL_SHIFT, | ||
301 | 0xbf, 0, madera_digital_tlv), | ||
302 | |||
303 | SOC_DOUBLE("SPKDAT1 Switch", MADERA_PDM_SPK1_CTRL_1, MADERA_SPK1L_MUTE_SHIFT, | ||
304 | MADERA_SPK1R_MUTE_SHIFT, 1, 1), | ||
305 | |||
306 | SOC_ENUM("Output Ramp Up", madera_out_vi_ramp), | ||
307 | SOC_ENUM("Output Ramp Down", madera_out_vd_ramp), | ||
308 | |||
309 | SOC_SINGLE("Noise Gate Switch", MADERA_NOISE_GATE_CONTROL, | ||
310 | MADERA_NGATE_ENA_SHIFT, 1, 0), | ||
311 | SOC_SINGLE_TLV("Noise Gate Threshold Volume", MADERA_NOISE_GATE_CONTROL, | ||
312 | MADERA_NGATE_THR_SHIFT, 7, 1, madera_ng_tlv), | ||
313 | SOC_ENUM("Noise Gate Hold", madera_ng_hold), | ||
314 | |||
315 | SOC_SINGLE_BOOL_EXT("IN1 LP Mode Switch", 0, | ||
316 | cs47l15_in1_adc_get, cs47l15_in1_adc_put), | ||
317 | |||
318 | CS47L15_NG_SRC("HPOUT1L", MADERA_NOISE_GATE_SELECT_1L), | ||
319 | CS47L15_NG_SRC("HPOUT1R", MADERA_NOISE_GATE_SELECT_1R), | ||
320 | CS47L15_NG_SRC("SPKOUTL", MADERA_NOISE_GATE_SELECT_4L), | ||
321 | CS47L15_NG_SRC("SPKDAT1L", MADERA_NOISE_GATE_SELECT_5L), | ||
322 | CS47L15_NG_SRC("SPKDAT1R", MADERA_NOISE_GATE_SELECT_5R), | ||
323 | |||
324 | MADERA_MIXER_CONTROLS("AIF1TX1", MADERA_AIF1TX1MIX_INPUT_1_SOURCE), | ||
325 | MADERA_MIXER_CONTROLS("AIF1TX2", MADERA_AIF1TX2MIX_INPUT_1_SOURCE), | ||
326 | MADERA_MIXER_CONTROLS("AIF1TX3", MADERA_AIF1TX3MIX_INPUT_1_SOURCE), | ||
327 | MADERA_MIXER_CONTROLS("AIF1TX4", MADERA_AIF1TX4MIX_INPUT_1_SOURCE), | ||
328 | MADERA_MIXER_CONTROLS("AIF1TX5", MADERA_AIF1TX5MIX_INPUT_1_SOURCE), | ||
329 | MADERA_MIXER_CONTROLS("AIF1TX6", MADERA_AIF1TX6MIX_INPUT_1_SOURCE), | ||
330 | |||
331 | MADERA_MIXER_CONTROLS("AIF2TX1", MADERA_AIF2TX1MIX_INPUT_1_SOURCE), | ||
332 | MADERA_MIXER_CONTROLS("AIF2TX2", MADERA_AIF2TX2MIX_INPUT_1_SOURCE), | ||
333 | MADERA_MIXER_CONTROLS("AIF2TX3", MADERA_AIF2TX3MIX_INPUT_1_SOURCE), | ||
334 | MADERA_MIXER_CONTROLS("AIF2TX4", MADERA_AIF2TX4MIX_INPUT_1_SOURCE), | ||
335 | |||
336 | MADERA_MIXER_CONTROLS("AIF3TX1", MADERA_AIF3TX1MIX_INPUT_1_SOURCE), | ||
337 | MADERA_MIXER_CONTROLS("AIF3TX2", MADERA_AIF3TX2MIX_INPUT_1_SOURCE), | ||
338 | |||
339 | MADERA_GAINMUX_CONTROLS("SPDIF1TX1", MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE), | ||
340 | MADERA_GAINMUX_CONTROLS("SPDIF1TX2", MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE), | ||
341 | |||
342 | WM_ADSP_FW_CONTROL("DSP1", 0), | ||
343 | }; | ||
344 | |||
345 | MADERA_MIXER_ENUMS(EQ1, MADERA_EQ1MIX_INPUT_1_SOURCE); | ||
346 | MADERA_MIXER_ENUMS(EQ2, MADERA_EQ2MIX_INPUT_1_SOURCE); | ||
347 | MADERA_MIXER_ENUMS(EQ3, MADERA_EQ3MIX_INPUT_1_SOURCE); | ||
348 | MADERA_MIXER_ENUMS(EQ4, MADERA_EQ4MIX_INPUT_1_SOURCE); | ||
349 | |||
350 | MADERA_MIXER_ENUMS(DRC1L, MADERA_DRC1LMIX_INPUT_1_SOURCE); | ||
351 | MADERA_MIXER_ENUMS(DRC1R, MADERA_DRC1RMIX_INPUT_1_SOURCE); | ||
352 | MADERA_MIXER_ENUMS(DRC2L, MADERA_DRC2LMIX_INPUT_1_SOURCE); | ||
353 | MADERA_MIXER_ENUMS(DRC2R, MADERA_DRC2RMIX_INPUT_1_SOURCE); | ||
354 | |||
355 | MADERA_MIXER_ENUMS(LHPF1, MADERA_HPLP1MIX_INPUT_1_SOURCE); | ||
356 | MADERA_MIXER_ENUMS(LHPF2, MADERA_HPLP2MIX_INPUT_1_SOURCE); | ||
357 | MADERA_MIXER_ENUMS(LHPF3, MADERA_HPLP3MIX_INPUT_1_SOURCE); | ||
358 | MADERA_MIXER_ENUMS(LHPF4, MADERA_HPLP4MIX_INPUT_1_SOURCE); | ||
359 | |||
360 | MADERA_MIXER_ENUMS(DSP1L, MADERA_DSP1LMIX_INPUT_1_SOURCE); | ||
361 | MADERA_MIXER_ENUMS(DSP1R, MADERA_DSP1RMIX_INPUT_1_SOURCE); | ||
362 | MADERA_DSP_AUX_ENUMS(DSP1, MADERA_DSP1AUX1MIX_INPUT_1_SOURCE); | ||
363 | |||
364 | MADERA_MIXER_ENUMS(PWM1, MADERA_PWM1MIX_INPUT_1_SOURCE); | ||
365 | MADERA_MIXER_ENUMS(PWM2, MADERA_PWM2MIX_INPUT_1_SOURCE); | ||
366 | |||
367 | MADERA_MIXER_ENUMS(OUT1L, MADERA_OUT1LMIX_INPUT_1_SOURCE); | ||
368 | MADERA_MIXER_ENUMS(OUT1R, MADERA_OUT1RMIX_INPUT_1_SOURCE); | ||
369 | MADERA_MIXER_ENUMS(SPKOUTL, MADERA_OUT4LMIX_INPUT_1_SOURCE); | ||
370 | MADERA_MIXER_ENUMS(SPKDAT1L, MADERA_OUT5LMIX_INPUT_1_SOURCE); | ||
371 | MADERA_MIXER_ENUMS(SPKDAT1R, MADERA_OUT5RMIX_INPUT_1_SOURCE); | ||
372 | |||
373 | MADERA_MIXER_ENUMS(AIF1TX1, MADERA_AIF1TX1MIX_INPUT_1_SOURCE); | ||
374 | MADERA_MIXER_ENUMS(AIF1TX2, MADERA_AIF1TX2MIX_INPUT_1_SOURCE); | ||
375 | MADERA_MIXER_ENUMS(AIF1TX3, MADERA_AIF1TX3MIX_INPUT_1_SOURCE); | ||
376 | MADERA_MIXER_ENUMS(AIF1TX4, MADERA_AIF1TX4MIX_INPUT_1_SOURCE); | ||
377 | MADERA_MIXER_ENUMS(AIF1TX5, MADERA_AIF1TX5MIX_INPUT_1_SOURCE); | ||
378 | MADERA_MIXER_ENUMS(AIF1TX6, MADERA_AIF1TX6MIX_INPUT_1_SOURCE); | ||
379 | |||
380 | MADERA_MIXER_ENUMS(AIF2TX1, MADERA_AIF2TX1MIX_INPUT_1_SOURCE); | ||
381 | MADERA_MIXER_ENUMS(AIF2TX2, MADERA_AIF2TX2MIX_INPUT_1_SOURCE); | ||
382 | MADERA_MIXER_ENUMS(AIF2TX3, MADERA_AIF2TX3MIX_INPUT_1_SOURCE); | ||
383 | MADERA_MIXER_ENUMS(AIF2TX4, MADERA_AIF2TX4MIX_INPUT_1_SOURCE); | ||
384 | |||
385 | MADERA_MIXER_ENUMS(AIF3TX1, MADERA_AIF3TX1MIX_INPUT_1_SOURCE); | ||
386 | MADERA_MIXER_ENUMS(AIF3TX2, MADERA_AIF3TX2MIX_INPUT_1_SOURCE); | ||
387 | |||
388 | MADERA_MUX_ENUMS(SPD1TX1, MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE); | ||
389 | MADERA_MUX_ENUMS(SPD1TX2, MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE); | ||
390 | |||
391 | MADERA_MUX_ENUMS(ISRC1INT1, MADERA_ISRC1INT1MIX_INPUT_1_SOURCE); | ||
392 | MADERA_MUX_ENUMS(ISRC1INT2, MADERA_ISRC1INT2MIX_INPUT_1_SOURCE); | ||
393 | MADERA_MUX_ENUMS(ISRC1INT3, MADERA_ISRC1INT3MIX_INPUT_1_SOURCE); | ||
394 | MADERA_MUX_ENUMS(ISRC1INT4, MADERA_ISRC1INT4MIX_INPUT_1_SOURCE); | ||
395 | |||
396 | MADERA_MUX_ENUMS(ISRC1DEC1, MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE); | ||
397 | MADERA_MUX_ENUMS(ISRC1DEC2, MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE); | ||
398 | MADERA_MUX_ENUMS(ISRC1DEC3, MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE); | ||
399 | MADERA_MUX_ENUMS(ISRC1DEC4, MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE); | ||
400 | |||
401 | MADERA_MUX_ENUMS(ISRC2INT1, MADERA_ISRC2INT1MIX_INPUT_1_SOURCE); | ||
402 | MADERA_MUX_ENUMS(ISRC2INT2, MADERA_ISRC2INT2MIX_INPUT_1_SOURCE); | ||
403 | MADERA_MUX_ENUMS(ISRC2INT3, MADERA_ISRC2INT3MIX_INPUT_1_SOURCE); | ||
404 | MADERA_MUX_ENUMS(ISRC2INT4, MADERA_ISRC2INT4MIX_INPUT_1_SOURCE); | ||
405 | |||
406 | MADERA_MUX_ENUMS(ISRC2DEC1, MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE); | ||
407 | MADERA_MUX_ENUMS(ISRC2DEC2, MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE); | ||
408 | MADERA_MUX_ENUMS(ISRC2DEC3, MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE); | ||
409 | MADERA_MUX_ENUMS(ISRC2DEC4, MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE); | ||
410 | |||
411 | static const char * const cs47l15_aec_loopback_texts[] = { | ||
412 | "HPOUT1L", "HPOUT1R", "SPKOUTL", "SPKDAT1L", "SPKDAT1R", | ||
413 | }; | ||
414 | |||
415 | static const unsigned int cs47l15_aec_loopback_values[] = { | ||
416 | 0, 1, 6, 8, 9, | ||
417 | }; | ||
418 | |||
419 | static const struct soc_enum cs47l15_aec1_loopback = | ||
420 | SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_1, | ||
421 | MADERA_AEC1_LOOPBACK_SRC_SHIFT, 0xf, | ||
422 | ARRAY_SIZE(cs47l15_aec_loopback_texts), | ||
423 | cs47l15_aec_loopback_texts, | ||
424 | cs47l15_aec_loopback_values); | ||
425 | |||
426 | static const struct soc_enum cs47l15_aec2_loopback = | ||
427 | SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_2, | ||
428 | MADERA_AEC2_LOOPBACK_SRC_SHIFT, 0xf, | ||
429 | ARRAY_SIZE(cs47l15_aec_loopback_texts), | ||
430 | cs47l15_aec_loopback_texts, | ||
431 | cs47l15_aec_loopback_values); | ||
432 | |||
433 | static const struct snd_kcontrol_new cs47l15_aec_loopback_mux[] = { | ||
434 | SOC_DAPM_ENUM("AEC1 Loopback", cs47l15_aec1_loopback), | ||
435 | SOC_DAPM_ENUM("AEC2 Loopback", cs47l15_aec2_loopback), | ||
436 | }; | ||
437 | |||
438 | static const struct snd_soc_dapm_widget cs47l15_dapm_widgets[] = { | ||
439 | SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, | ||
440 | 0, madera_sysclk_ev, | ||
441 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
442 | SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, | ||
443 | MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), | ||
444 | SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, | ||
445 | MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), | ||
446 | |||
447 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), | ||
448 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), | ||
449 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDD", 0, 0), | ||
450 | |||
451 | SND_SOC_DAPM_SUPPLY("MICBIAS1", MADERA_MIC_BIAS_CTRL_1, | ||
452 | MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
453 | |||
454 | SND_SOC_DAPM_SUPPLY("MICBIAS1A", MADERA_MIC_BIAS_CTRL_5, | ||
455 | MADERA_MICB1A_ENA_SHIFT, 0, NULL, 0), | ||
456 | SND_SOC_DAPM_SUPPLY("MICBIAS1B", MADERA_MIC_BIAS_CTRL_5, | ||
457 | MADERA_MICB1B_ENA_SHIFT, 0, NULL, 0), | ||
458 | SND_SOC_DAPM_SUPPLY("MICBIAS1C", MADERA_MIC_BIAS_CTRL_5, | ||
459 | MADERA_MICB1C_ENA_SHIFT, 0, NULL, 0), | ||
460 | |||
461 | SND_SOC_DAPM_SUPPLY("FXCLK", SND_SOC_NOPM, | ||
462 | MADERA_DOM_GRP_FX, 0, | ||
463 | madera_domain_clk_ev, | ||
464 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
465 | SND_SOC_DAPM_SUPPLY("ISRC1CLK", SND_SOC_NOPM, | ||
466 | MADERA_DOM_GRP_ISRC1, 0, | ||
467 | madera_domain_clk_ev, | ||
468 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
469 | SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, | ||
470 | MADERA_DOM_GRP_ISRC2, 0, | ||
471 | madera_domain_clk_ev, | ||
472 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
473 | SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, | ||
474 | MADERA_DOM_GRP_OUT, 0, | ||
475 | madera_domain_clk_ev, | ||
476 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
477 | SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, | ||
478 | MADERA_DOM_GRP_SPD, 0, | ||
479 | madera_domain_clk_ev, | ||
480 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
481 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, | ||
482 | MADERA_DOM_GRP_DSP1, 0, | ||
483 | madera_domain_clk_ev, | ||
484 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
485 | SND_SOC_DAPM_SUPPLY("AIF1TXCLK", SND_SOC_NOPM, | ||
486 | MADERA_DOM_GRP_AIF1, 0, | ||
487 | madera_domain_clk_ev, | ||
488 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
489 | SND_SOC_DAPM_SUPPLY("AIF2TXCLK", SND_SOC_NOPM, | ||
490 | MADERA_DOM_GRP_AIF2, 0, | ||
491 | madera_domain_clk_ev, | ||
492 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
493 | SND_SOC_DAPM_SUPPLY("AIF3TXCLK", SND_SOC_NOPM, | ||
494 | MADERA_DOM_GRP_AIF3, 0, | ||
495 | madera_domain_clk_ev, | ||
496 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
497 | SND_SOC_DAPM_SUPPLY("PWMCLK", SND_SOC_NOPM, | ||
498 | MADERA_DOM_GRP_PWM, 0, | ||
499 | madera_domain_clk_ev, | ||
500 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
501 | |||
502 | SND_SOC_DAPM_SIGGEN("TONE"), | ||
503 | SND_SOC_DAPM_SIGGEN("NOISE"), | ||
504 | |||
505 | SND_SOC_DAPM_INPUT("IN1ALN"), | ||
506 | SND_SOC_DAPM_INPUT("IN1ALP"), | ||
507 | SND_SOC_DAPM_INPUT("IN1BLN"), | ||
508 | SND_SOC_DAPM_INPUT("IN1BLP"), | ||
509 | SND_SOC_DAPM_INPUT("IN1ARN"), | ||
510 | SND_SOC_DAPM_INPUT("IN1ARP"), | ||
511 | SND_SOC_DAPM_INPUT("IN1BRN"), | ||
512 | SND_SOC_DAPM_INPUT("IN1BRP"), | ||
513 | SND_SOC_DAPM_INPUT("IN2N"), | ||
514 | SND_SOC_DAPM_INPUT("IN2P"), | ||
515 | SND_SOC_DAPM_INPUT("SPKRXDAT"), | ||
516 | |||
517 | SND_SOC_DAPM_MUX("IN1L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[0]), | ||
518 | SND_SOC_DAPM_MUX("IN1R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[1]), | ||
519 | |||
520 | SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), | ||
521 | SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), | ||
522 | |||
523 | SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), | ||
524 | SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), | ||
525 | |||
526 | SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), | ||
527 | SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), | ||
528 | |||
529 | SND_SOC_DAPM_OUTPUT("DSP Trigger Out"), | ||
530 | |||
531 | SND_SOC_DAPM_DEMUX("HPOUT1 Demux", SND_SOC_NOPM, 0, 0, &cs47l15_outdemux), | ||
532 | |||
533 | SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT, | ||
534 | 0, NULL, 0), | ||
535 | SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, | ||
536 | 0, NULL, 0), | ||
537 | |||
538 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | ||
539 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), | ||
540 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | ||
541 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), | ||
542 | SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, | ||
543 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), | ||
544 | SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, | ||
545 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), | ||
546 | SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, | ||
547 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), | ||
548 | SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, | ||
549 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), | ||
550 | |||
551 | SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | ||
552 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), | ||
553 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | ||
554 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), | ||
555 | SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, | ||
556 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), | ||
557 | SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, | ||
558 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), | ||
559 | |||
560 | SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, | ||
561 | MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), | ||
562 | SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, | ||
563 | MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), | ||
564 | |||
565 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, | ||
566 | MADERA_OUT1L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, | ||
567 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
568 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
569 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, | ||
570 | MADERA_OUT1R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, | ||
571 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
572 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
573 | SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM, | ||
574 | MADERA_OUT4L_ENA_SHIFT, 0, NULL, 0, madera_spk_ev, | ||
575 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
576 | SND_SOC_DAPM_PGA_E("OUT5L", MADERA_OUTPUT_ENABLES_1, | ||
577 | MADERA_OUT5L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, | ||
578 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
579 | SND_SOC_DAPM_PGA_E("OUT5R", MADERA_OUTPUT_ENABLES_1, | ||
580 | MADERA_OUT5R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, | ||
581 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
582 | |||
583 | SND_SOC_DAPM_PGA("SPD1TX1", MADERA_SPD1_TX_CONTROL, | ||
584 | MADERA_SPD1_VAL1_SHIFT, 0, NULL, 0), | ||
585 | SND_SOC_DAPM_PGA("SPD1TX2", MADERA_SPD1_TX_CONTROL, | ||
586 | MADERA_SPD1_VAL2_SHIFT, 0, NULL, 0), | ||
587 | SND_SOC_DAPM_OUT_DRV("SPD1", MADERA_SPD1_TX_CONTROL, | ||
588 | MADERA_SPD1_ENA_SHIFT, 0, NULL, 0), | ||
589 | |||
590 | /* | ||
591 | * mux_in widgets : arranged in the order of sources | ||
592 | * specified in MADERA_MIXER_INPUT_ROUTES | ||
593 | */ | ||
594 | |||
595 | SND_SOC_DAPM_PGA("Noise Generator", MADERA_COMFORT_NOISE_GENERATOR, | ||
596 | MADERA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), | ||
597 | |||
598 | SND_SOC_DAPM_PGA("Tone Generator 1", MADERA_TONE_GENERATOR_1, | ||
599 | MADERA_TONE1_ENA_SHIFT, 0, NULL, 0), | ||
600 | SND_SOC_DAPM_PGA("Tone Generator 2", MADERA_TONE_GENERATOR_1, | ||
601 | MADERA_TONE2_ENA_SHIFT, 0, NULL, 0), | ||
602 | |||
603 | SND_SOC_DAPM_SIGGEN("HAPTICS"), | ||
604 | |||
605 | SND_SOC_DAPM_MUX("AEC1 Loopback", MADERA_DAC_AEC_CONTROL_1, | ||
606 | MADERA_AEC1_LOOPBACK_ENA_SHIFT, 0, | ||
607 | &cs47l15_aec_loopback_mux[0]), | ||
608 | SND_SOC_DAPM_MUX("AEC2 Loopback", MADERA_DAC_AEC_CONTROL_2, | ||
609 | MADERA_AEC2_LOOPBACK_ENA_SHIFT, 0, | ||
610 | &cs47l15_aec_loopback_mux[1]), | ||
611 | |||
612 | SND_SOC_DAPM_PGA_E("IN1L", MADERA_INPUT_ENABLES, MADERA_IN1L_ENA_SHIFT, | ||
613 | 0, NULL, 0, madera_in_ev, | ||
614 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
615 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
616 | SND_SOC_DAPM_PGA_E("IN1R", MADERA_INPUT_ENABLES, MADERA_IN1R_ENA_SHIFT, | ||
617 | 0, NULL, 0, madera_in_ev, | ||
618 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
619 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
620 | SND_SOC_DAPM_PGA_E("IN2L", MADERA_INPUT_ENABLES, MADERA_IN2L_ENA_SHIFT, | ||
621 | 0, NULL, 0, madera_in_ev, | ||
622 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
623 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
624 | SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, | ||
625 | 0, NULL, 0, madera_in_ev, | ||
626 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
627 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
628 | |||
629 | SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, | ||
630 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), | ||
631 | SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, | ||
632 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), | ||
633 | SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, | ||
634 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), | ||
635 | SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, | ||
636 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), | ||
637 | SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, | ||
638 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), | ||
639 | SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, | ||
640 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), | ||
641 | |||
642 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | ||
643 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), | ||
644 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | ||
645 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), | ||
646 | SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, | ||
647 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), | ||
648 | SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, | ||
649 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), | ||
650 | |||
651 | SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | ||
652 | MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), | ||
653 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | ||
654 | MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), | ||
655 | |||
656 | SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), | ||
657 | SND_SOC_DAPM_PGA("EQ2", MADERA_EQ2_1, MADERA_EQ2_ENA_SHIFT, 0, NULL, 0), | ||
658 | SND_SOC_DAPM_PGA("EQ3", MADERA_EQ3_1, MADERA_EQ3_ENA_SHIFT, 0, NULL, 0), | ||
659 | SND_SOC_DAPM_PGA("EQ4", MADERA_EQ4_1, MADERA_EQ4_ENA_SHIFT, 0, NULL, 0), | ||
660 | |||
661 | SND_SOC_DAPM_PGA("DRC1L", MADERA_DRC1_CTRL1, MADERA_DRC1L_ENA_SHIFT, 0, | ||
662 | NULL, 0), | ||
663 | SND_SOC_DAPM_PGA("DRC1R", MADERA_DRC1_CTRL1, MADERA_DRC1R_ENA_SHIFT, 0, | ||
664 | NULL, 0), | ||
665 | SND_SOC_DAPM_PGA("DRC2L", MADERA_DRC2_CTRL1, MADERA_DRC2L_ENA_SHIFT, 0, | ||
666 | NULL, 0), | ||
667 | SND_SOC_DAPM_PGA("DRC2R", MADERA_DRC2_CTRL1, MADERA_DRC2R_ENA_SHIFT, 0, | ||
668 | NULL, 0), | ||
669 | |||
670 | SND_SOC_DAPM_PGA("LHPF1", MADERA_HPLPF1_1, MADERA_LHPF1_ENA_SHIFT, 0, NULL, 0), | ||
671 | SND_SOC_DAPM_PGA("LHPF2", MADERA_HPLPF2_1, MADERA_LHPF2_ENA_SHIFT, 0, NULL, 0), | ||
672 | SND_SOC_DAPM_PGA("LHPF3", MADERA_HPLPF3_1, MADERA_LHPF3_ENA_SHIFT, 0, NULL, 0), | ||
673 | SND_SOC_DAPM_PGA("LHPF4", MADERA_HPLPF4_1, MADERA_LHPF4_ENA_SHIFT, 0, NULL, 0), | ||
674 | |||
675 | SND_SOC_DAPM_PGA("ISRC1DEC1", MADERA_ISRC_1_CTRL_3, | ||
676 | MADERA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
677 | SND_SOC_DAPM_PGA("ISRC1DEC2", MADERA_ISRC_1_CTRL_3, | ||
678 | MADERA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
679 | SND_SOC_DAPM_PGA("ISRC1DEC3", MADERA_ISRC_1_CTRL_3, | ||
680 | MADERA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0), | ||
681 | SND_SOC_DAPM_PGA("ISRC1DEC4", MADERA_ISRC_1_CTRL_3, | ||
682 | MADERA_ISRC1_DEC4_ENA_SHIFT, 0, NULL, 0), | ||
683 | |||
684 | SND_SOC_DAPM_PGA("ISRC1INT1", MADERA_ISRC_1_CTRL_3, | ||
685 | MADERA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), | ||
686 | SND_SOC_DAPM_PGA("ISRC1INT2", MADERA_ISRC_1_CTRL_3, | ||
687 | MADERA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), | ||
688 | SND_SOC_DAPM_PGA("ISRC1INT3", MADERA_ISRC_1_CTRL_3, | ||
689 | MADERA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0), | ||
690 | SND_SOC_DAPM_PGA("ISRC1INT4", MADERA_ISRC_1_CTRL_3, | ||
691 | MADERA_ISRC1_INT4_ENA_SHIFT, 0, NULL, 0), | ||
692 | |||
693 | SND_SOC_DAPM_PGA("ISRC2DEC1", MADERA_ISRC_2_CTRL_3, | ||
694 | MADERA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
695 | SND_SOC_DAPM_PGA("ISRC2DEC2", MADERA_ISRC_2_CTRL_3, | ||
696 | MADERA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
697 | SND_SOC_DAPM_PGA("ISRC2DEC3", MADERA_ISRC_2_CTRL_3, | ||
698 | MADERA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0), | ||
699 | SND_SOC_DAPM_PGA("ISRC2DEC4", MADERA_ISRC_2_CTRL_3, | ||
700 | MADERA_ISRC2_DEC4_ENA_SHIFT, 0, NULL, 0), | ||
701 | |||
702 | SND_SOC_DAPM_PGA("ISRC2INT1", MADERA_ISRC_2_CTRL_3, | ||
703 | MADERA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), | ||
704 | SND_SOC_DAPM_PGA("ISRC2INT2", MADERA_ISRC_2_CTRL_3, | ||
705 | MADERA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), | ||
706 | SND_SOC_DAPM_PGA("ISRC2INT3", MADERA_ISRC_2_CTRL_3, | ||
707 | MADERA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0), | ||
708 | SND_SOC_DAPM_PGA("ISRC2INT4", MADERA_ISRC_2_CTRL_3, | ||
709 | MADERA_ISRC2_INT4_ENA_SHIFT, 0, NULL, 0), | ||
710 | |||
711 | WM_ADSP2("DSP1", 0, cs47l15_adsp_power_ev), | ||
712 | |||
713 | /* end of ordered widget list */ | ||
714 | |||
715 | MADERA_MIXER_WIDGETS(EQ1, "EQ1"), | ||
716 | MADERA_MIXER_WIDGETS(EQ2, "EQ2"), | ||
717 | MADERA_MIXER_WIDGETS(EQ3, "EQ3"), | ||
718 | MADERA_MIXER_WIDGETS(EQ4, "EQ4"), | ||
719 | |||
720 | MADERA_MIXER_WIDGETS(DRC1L, "DRC1L"), | ||
721 | MADERA_MIXER_WIDGETS(DRC1R, "DRC1R"), | ||
722 | MADERA_MIXER_WIDGETS(DRC2L, "DRC2L"), | ||
723 | MADERA_MIXER_WIDGETS(DRC2R, "DRC2R"), | ||
724 | |||
725 | SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0, | ||
726 | &madera_drc_activity_output_mux[0]), | ||
727 | SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0, | ||
728 | &madera_drc_activity_output_mux[1]), | ||
729 | |||
730 | MADERA_MIXER_WIDGETS(LHPF1, "LHPF1"), | ||
731 | MADERA_MIXER_WIDGETS(LHPF2, "LHPF2"), | ||
732 | MADERA_MIXER_WIDGETS(LHPF3, "LHPF3"), | ||
733 | MADERA_MIXER_WIDGETS(LHPF4, "LHPF4"), | ||
734 | |||
735 | MADERA_MIXER_WIDGETS(PWM1, "PWM1"), | ||
736 | MADERA_MIXER_WIDGETS(PWM2, "PWM2"), | ||
737 | |||
738 | MADERA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | ||
739 | MADERA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | ||
740 | MADERA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), | ||
741 | MADERA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | ||
742 | MADERA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), | ||
743 | |||
744 | MADERA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), | ||
745 | MADERA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), | ||
746 | MADERA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), | ||
747 | MADERA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), | ||
748 | MADERA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), | ||
749 | MADERA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), | ||
750 | |||
751 | MADERA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | ||
752 | MADERA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | ||
753 | MADERA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), | ||
754 | MADERA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), | ||
755 | |||
756 | MADERA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | ||
757 | MADERA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | ||
758 | |||
759 | MADERA_MUX_WIDGETS(SPD1TX1, "SPDIF1TX1"), | ||
760 | MADERA_MUX_WIDGETS(SPD1TX2, "SPDIF1TX2"), | ||
761 | |||
762 | MADERA_DSP_WIDGETS(DSP1, "DSP1"), | ||
763 | |||
764 | SND_SOC_DAPM_SWITCH("DSP1 Trigger Output", SND_SOC_NOPM, 0, 0, | ||
765 | &madera_dsp_trigger_output_mux[0]), | ||
766 | |||
767 | MADERA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), | ||
768 | MADERA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), | ||
769 | MADERA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), | ||
770 | MADERA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), | ||
771 | |||
772 | MADERA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), | ||
773 | MADERA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), | ||
774 | MADERA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), | ||
775 | MADERA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), | ||
776 | |||
777 | MADERA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), | ||
778 | MADERA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), | ||
779 | MADERA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"), | ||
780 | MADERA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"), | ||
781 | |||
782 | MADERA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), | ||
783 | MADERA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), | ||
784 | MADERA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"), | ||
785 | MADERA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"), | ||
786 | |||
787 | SND_SOC_DAPM_OUTPUT("HPOUTL"), | ||
788 | SND_SOC_DAPM_OUTPUT("HPOUTR"), | ||
789 | SND_SOC_DAPM_OUTPUT("EPOUTP"), | ||
790 | SND_SOC_DAPM_OUTPUT("EPOUTN"), | ||
791 | SND_SOC_DAPM_OUTPUT("SPKOUTN"), | ||
792 | SND_SOC_DAPM_OUTPUT("SPKOUTP"), | ||
793 | SND_SOC_DAPM_OUTPUT("SPKDAT1L"), | ||
794 | SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | ||
795 | SND_SOC_DAPM_OUTPUT("SPDIF1"), | ||
796 | |||
797 | SND_SOC_DAPM_OUTPUT("MICSUPP"), | ||
798 | }; | ||
799 | |||
800 | #define MADERA_MIXER_INPUT_ROUTES(name) \ | ||
801 | { name, "Noise Generator", "Noise Generator" }, \ | ||
802 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | ||
803 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | ||
804 | { name, "Haptics", "HAPTICS" }, \ | ||
805 | { name, "AEC1", "AEC1 Loopback" }, \ | ||
806 | { name, "AEC2", "AEC2 Loopback" }, \ | ||
807 | { name, "IN1L", "IN1L" }, \ | ||
808 | { name, "IN1R", "IN1R" }, \ | ||
809 | { name, "IN2L", "IN2L" }, \ | ||
810 | { name, "IN2R", "IN2R" }, \ | ||
811 | { name, "AIF1RX1", "AIF1RX1" }, \ | ||
812 | { name, "AIF1RX2", "AIF1RX2" }, \ | ||
813 | { name, "AIF1RX3", "AIF1RX3" }, \ | ||
814 | { name, "AIF1RX4", "AIF1RX4" }, \ | ||
815 | { name, "AIF1RX5", "AIF1RX5" }, \ | ||
816 | { name, "AIF1RX6", "AIF1RX6" }, \ | ||
817 | { name, "AIF2RX1", "AIF2RX1" }, \ | ||
818 | { name, "AIF2RX2", "AIF2RX2" }, \ | ||
819 | { name, "AIF2RX3", "AIF2RX3" }, \ | ||
820 | { name, "AIF2RX4", "AIF2RX4" }, \ | ||
821 | { name, "AIF3RX1", "AIF3RX1" }, \ | ||
822 | { name, "AIF3RX2", "AIF3RX2" }, \ | ||
823 | { name, "EQ1", "EQ1" }, \ | ||
824 | { name, "EQ2", "EQ2" }, \ | ||
825 | { name, "EQ3", "EQ3" }, \ | ||
826 | { name, "EQ4", "EQ4" }, \ | ||
827 | { name, "DRC1L", "DRC1L" }, \ | ||
828 | { name, "DRC1R", "DRC1R" }, \ | ||
829 | { name, "DRC2L", "DRC2L" }, \ | ||
830 | { name, "DRC2R", "DRC2R" }, \ | ||
831 | { name, "LHPF1", "LHPF1" }, \ | ||
832 | { name, "LHPF2", "LHPF2" }, \ | ||
833 | { name, "LHPF3", "LHPF3" }, \ | ||
834 | { name, "LHPF4", "LHPF4" }, \ | ||
835 | { name, "ISRC1DEC1", "ISRC1DEC1" }, \ | ||
836 | { name, "ISRC1DEC2", "ISRC1DEC2" }, \ | ||
837 | { name, "ISRC1DEC3", "ISRC1DEC3" }, \ | ||
838 | { name, "ISRC1DEC4", "ISRC1DEC4" }, \ | ||
839 | { name, "ISRC1INT1", "ISRC1INT1" }, \ | ||
840 | { name, "ISRC1INT2", "ISRC1INT2" }, \ | ||
841 | { name, "ISRC1INT3", "ISRC1INT3" }, \ | ||
842 | { name, "ISRC1INT4", "ISRC1INT4" }, \ | ||
843 | { name, "ISRC2DEC1", "ISRC2DEC1" }, \ | ||
844 | { name, "ISRC2DEC2", "ISRC2DEC2" }, \ | ||
845 | { name, "ISRC2DEC3", "ISRC2DEC3" }, \ | ||
846 | { name, "ISRC2DEC4", "ISRC2DEC4" }, \ | ||
847 | { name, "ISRC2INT1", "ISRC2INT1" }, \ | ||
848 | { name, "ISRC2INT2", "ISRC2INT2" }, \ | ||
849 | { name, "ISRC2INT3", "ISRC2INT3" }, \ | ||
850 | { name, "ISRC2INT4", "ISRC2INT4" }, \ | ||
851 | { name, "DSP1.1", "DSP1" }, \ | ||
852 | { name, "DSP1.2", "DSP1" }, \ | ||
853 | { name, "DSP1.3", "DSP1" }, \ | ||
854 | { name, "DSP1.4", "DSP1" }, \ | ||
855 | { name, "DSP1.5", "DSP1" }, \ | ||
856 | { name, "DSP1.6", "DSP1" } | ||
857 | |||
858 | static const struct snd_soc_dapm_route cs47l15_dapm_routes[] = { | ||
859 | /* Internal clock domains */ | ||
860 | { "EQ1", NULL, "FXCLK" }, | ||
861 | { "EQ2", NULL, "FXCLK" }, | ||
862 | { "EQ3", NULL, "FXCLK" }, | ||
863 | { "EQ4", NULL, "FXCLK" }, | ||
864 | { "DRC1L", NULL, "FXCLK" }, | ||
865 | { "DRC1R", NULL, "FXCLK" }, | ||
866 | { "DRC2L", NULL, "FXCLK" }, | ||
867 | { "DRC2R", NULL, "FXCLK" }, | ||
868 | { "LHPF1", NULL, "FXCLK" }, | ||
869 | { "LHPF2", NULL, "FXCLK" }, | ||
870 | { "LHPF3", NULL, "FXCLK" }, | ||
871 | { "LHPF4", NULL, "FXCLK" }, | ||
872 | { "PWM1 Mixer", NULL, "PWMCLK" }, | ||
873 | { "PWM2 Mixer", NULL, "PWMCLK" }, | ||
874 | { "OUT1L", NULL, "OUTCLK" }, | ||
875 | { "OUT1R", NULL, "OUTCLK" }, | ||
876 | { "OUT4L", NULL, "OUTCLK" }, | ||
877 | { "OUT5L", NULL, "OUTCLK" }, | ||
878 | { "OUT5R", NULL, "OUTCLK" }, | ||
879 | { "AIF1TX1", NULL, "AIF1TXCLK" }, | ||
880 | { "AIF1TX2", NULL, "AIF1TXCLK" }, | ||
881 | { "AIF1TX3", NULL, "AIF1TXCLK" }, | ||
882 | { "AIF1TX4", NULL, "AIF1TXCLK" }, | ||
883 | { "AIF1TX5", NULL, "AIF1TXCLK" }, | ||
884 | { "AIF1TX6", NULL, "AIF1TXCLK" }, | ||
885 | { "AIF2TX1", NULL, "AIF2TXCLK" }, | ||
886 | { "AIF2TX2", NULL, "AIF2TXCLK" }, | ||
887 | { "AIF2TX3", NULL, "AIF2TXCLK" }, | ||
888 | { "AIF2TX4", NULL, "AIF2TXCLK" }, | ||
889 | { "AIF3TX1", NULL, "AIF3TXCLK" }, | ||
890 | { "AIF3TX2", NULL, "AIF3TXCLK" }, | ||
891 | { "SPD1TX1", NULL, "SPDCLK" }, | ||
892 | { "SPD1TX2", NULL, "SPDCLK" }, | ||
893 | { "DSP1", NULL, "DSP1CLK" }, | ||
894 | { "ISRC1DEC1", NULL, "ISRC1CLK" }, | ||
895 | { "ISRC1DEC2", NULL, "ISRC1CLK" }, | ||
896 | { "ISRC1DEC3", NULL, "ISRC1CLK" }, | ||
897 | { "ISRC1DEC4", NULL, "ISRC1CLK" }, | ||
898 | { "ISRC1INT1", NULL, "ISRC1CLK" }, | ||
899 | { "ISRC1INT2", NULL, "ISRC1CLK" }, | ||
900 | { "ISRC1INT3", NULL, "ISRC1CLK" }, | ||
901 | { "ISRC1INT4", NULL, "ISRC1CLK" }, | ||
902 | { "ISRC2DEC1", NULL, "ISRC2CLK" }, | ||
903 | { "ISRC2DEC2", NULL, "ISRC2CLK" }, | ||
904 | { "ISRC2DEC3", NULL, "ISRC2CLK" }, | ||
905 | { "ISRC2DEC4", NULL, "ISRC2CLK" }, | ||
906 | { "ISRC2INT1", NULL, "ISRC2CLK" }, | ||
907 | { "ISRC2INT2", NULL, "ISRC2CLK" }, | ||
908 | { "ISRC2INT3", NULL, "ISRC2CLK" }, | ||
909 | { "ISRC2INT4", NULL, "ISRC2CLK" }, | ||
910 | |||
911 | { "OUT1L", NULL, "CPVDD1" }, | ||
912 | { "OUT1R", NULL, "CPVDD1" }, | ||
913 | { "OUT4L", NULL, "SPKVDD" }, | ||
914 | |||
915 | { "OUT1L", NULL, "SYSCLK" }, | ||
916 | { "OUT1R", NULL, "SYSCLK" }, | ||
917 | { "OUT4L", NULL, "SYSCLK" }, | ||
918 | { "OUT5L", NULL, "SYSCLK" }, | ||
919 | { "OUT5R", NULL, "SYSCLK" }, | ||
920 | |||
921 | { "SPD1", NULL, "SYSCLK" }, | ||
922 | { "SPD1", NULL, "SPD1TX1" }, | ||
923 | { "SPD1", NULL, "SPD1TX2" }, | ||
924 | |||
925 | { "IN1L", NULL, "SYSCLK" }, | ||
926 | { "IN1R", NULL, "SYSCLK" }, | ||
927 | { "IN2L", NULL, "SYSCLK" }, | ||
928 | { "IN2R", NULL, "SYSCLK" }, | ||
929 | |||
930 | { "MICBIAS1", NULL, "MICVDD" }, | ||
931 | |||
932 | { "MICBIAS1A", NULL, "MICBIAS1" }, | ||
933 | { "MICBIAS1B", NULL, "MICBIAS1" }, | ||
934 | { "MICBIAS1C", NULL, "MICBIAS1" }, | ||
935 | |||
936 | { "Noise Generator", NULL, "SYSCLK" }, | ||
937 | { "Tone Generator 1", NULL, "SYSCLK" }, | ||
938 | { "Tone Generator 2", NULL, "SYSCLK" }, | ||
939 | |||
940 | { "Noise Generator", NULL, "NOISE" }, | ||
941 | { "Tone Generator 1", NULL, "TONE" }, | ||
942 | { "Tone Generator 2", NULL, "TONE" }, | ||
943 | |||
944 | { "AIF1 Capture", NULL, "AIF1TX1" }, | ||
945 | { "AIF1 Capture", NULL, "AIF1TX2" }, | ||
946 | { "AIF1 Capture", NULL, "AIF1TX3" }, | ||
947 | { "AIF1 Capture", NULL, "AIF1TX4" }, | ||
948 | { "AIF1 Capture", NULL, "AIF1TX5" }, | ||
949 | { "AIF1 Capture", NULL, "AIF1TX6" }, | ||
950 | |||
951 | { "AIF1RX1", NULL, "AIF1 Playback" }, | ||
952 | { "AIF1RX2", NULL, "AIF1 Playback" }, | ||
953 | { "AIF1RX3", NULL, "AIF1 Playback" }, | ||
954 | { "AIF1RX4", NULL, "AIF1 Playback" }, | ||
955 | { "AIF1RX5", NULL, "AIF1 Playback" }, | ||
956 | { "AIF1RX6", NULL, "AIF1 Playback" }, | ||
957 | |||
958 | { "AIF2 Capture", NULL, "AIF2TX1" }, | ||
959 | { "AIF2 Capture", NULL, "AIF2TX2" }, | ||
960 | { "AIF2 Capture", NULL, "AIF2TX3" }, | ||
961 | { "AIF2 Capture", NULL, "AIF2TX4" }, | ||
962 | |||
963 | { "AIF2RX1", NULL, "AIF2 Playback" }, | ||
964 | { "AIF2RX2", NULL, "AIF2 Playback" }, | ||
965 | { "AIF2RX3", NULL, "AIF2 Playback" }, | ||
966 | { "AIF2RX4", NULL, "AIF2 Playback" }, | ||
967 | |||
968 | { "AIF3 Capture", NULL, "AIF3TX1" }, | ||
969 | { "AIF3 Capture", NULL, "AIF3TX2" }, | ||
970 | |||
971 | { "AIF3RX1", NULL, "AIF3 Playback" }, | ||
972 | { "AIF3RX2", NULL, "AIF3 Playback" }, | ||
973 | |||
974 | { "AIF1 Playback", NULL, "SYSCLK" }, | ||
975 | { "AIF2 Playback", NULL, "SYSCLK" }, | ||
976 | { "AIF3 Playback", NULL, "SYSCLK" }, | ||
977 | |||
978 | { "AIF1 Capture", NULL, "SYSCLK" }, | ||
979 | { "AIF2 Capture", NULL, "SYSCLK" }, | ||
980 | { "AIF3 Capture", NULL, "SYSCLK" }, | ||
981 | |||
982 | { "Audio Trace DSP", NULL, "DSP1" }, | ||
983 | |||
984 | { "IN1L Analog Mux", "A", "IN1ALN" }, | ||
985 | { "IN1L Analog Mux", "A", "IN1ALP" }, | ||
986 | { "IN1L Analog Mux", "B", "IN1BLN" }, | ||
987 | { "IN1L Analog Mux", "B", "IN1BLP" }, | ||
988 | { "IN1R Analog Mux", "A", "IN1ARN" }, | ||
989 | { "IN1R Analog Mux", "A", "IN1ARP" }, | ||
990 | { "IN1R Analog Mux", "B", "IN1BRN" }, | ||
991 | { "IN1R Analog Mux", "B", "IN1BRP" }, | ||
992 | |||
993 | { "IN1L Mode", "Analog", "IN1L Analog Mux" }, | ||
994 | { "IN1R Mode", "Analog", "IN1R Analog Mux" }, | ||
995 | |||
996 | { "IN1L Mode", "Digital", "IN1ALN" }, | ||
997 | { "IN1L Mode", "Digital", "IN1ALP" }, | ||
998 | { "IN1R Mode", "Digital", "IN1ALN" }, | ||
999 | { "IN1R Mode", "Digital", "IN1ALP" }, | ||
1000 | |||
1001 | { "IN1L", NULL, "IN1L Mode" }, | ||
1002 | { "IN1R", NULL, "IN1R Mode" }, | ||
1003 | |||
1004 | { "IN2L Mode", "Analog", "IN2N" }, | ||
1005 | { "IN2L Mode", "Analog", "IN2P" }, | ||
1006 | |||
1007 | { "IN2L Mode", "Digital", "SPKRXDAT" }, | ||
1008 | { "IN2R Mode", "Digital", "SPKRXDAT" }, | ||
1009 | |||
1010 | { "IN2L", NULL, "IN2L Mode" }, | ||
1011 | { "IN2R", NULL, "IN2R Mode" }, | ||
1012 | |||
1013 | MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | ||
1014 | MADERA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | ||
1015 | MADERA_MIXER_ROUTES("OUT4L", "SPKOUTL"), | ||
1016 | MADERA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), | ||
1017 | MADERA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), | ||
1018 | |||
1019 | MADERA_MIXER_ROUTES("PWM1 Driver", "PWM1"), | ||
1020 | MADERA_MIXER_ROUTES("PWM2 Driver", "PWM2"), | ||
1021 | |||
1022 | MADERA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), | ||
1023 | MADERA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), | ||
1024 | MADERA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), | ||
1025 | MADERA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), | ||
1026 | MADERA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), | ||
1027 | MADERA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), | ||
1028 | |||
1029 | MADERA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | ||
1030 | MADERA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | ||
1031 | MADERA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), | ||
1032 | MADERA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), | ||
1033 | |||
1034 | MADERA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | ||
1035 | MADERA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | ||
1036 | |||
1037 | MADERA_MUX_ROUTES("SPD1TX1", "SPDIF1TX1"), | ||
1038 | MADERA_MUX_ROUTES("SPD1TX2", "SPDIF1TX2"), | ||
1039 | |||
1040 | MADERA_MIXER_ROUTES("EQ1", "EQ1"), | ||
1041 | MADERA_MIXER_ROUTES("EQ2", "EQ2"), | ||
1042 | MADERA_MIXER_ROUTES("EQ3", "EQ3"), | ||
1043 | MADERA_MIXER_ROUTES("EQ4", "EQ4"), | ||
1044 | |||
1045 | MADERA_MIXER_ROUTES("DRC1L", "DRC1L"), | ||
1046 | MADERA_MIXER_ROUTES("DRC1R", "DRC1R"), | ||
1047 | MADERA_MIXER_ROUTES("DRC2L", "DRC2L"), | ||
1048 | MADERA_MIXER_ROUTES("DRC2R", "DRC2R"), | ||
1049 | |||
1050 | MADERA_MIXER_ROUTES("LHPF1", "LHPF1"), | ||
1051 | MADERA_MIXER_ROUTES("LHPF2", "LHPF2"), | ||
1052 | MADERA_MIXER_ROUTES("LHPF3", "LHPF3"), | ||
1053 | MADERA_MIXER_ROUTES("LHPF4", "LHPF4"), | ||
1054 | |||
1055 | MADERA_DSP_ROUTES("DSP1"), | ||
1056 | |||
1057 | { "DSP Trigger Out", NULL, "DSP1 Trigger Output" }, | ||
1058 | |||
1059 | { "DSP1 Trigger Output", "Switch", "DSP1" }, | ||
1060 | |||
1061 | MADERA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), | ||
1062 | MADERA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), | ||
1063 | MADERA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), | ||
1064 | MADERA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), | ||
1065 | |||
1066 | MADERA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), | ||
1067 | MADERA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), | ||
1068 | MADERA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), | ||
1069 | MADERA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), | ||
1070 | |||
1071 | MADERA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), | ||
1072 | MADERA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), | ||
1073 | MADERA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"), | ||
1074 | MADERA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"), | ||
1075 | |||
1076 | MADERA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), | ||
1077 | MADERA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), | ||
1078 | MADERA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"), | ||
1079 | MADERA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"), | ||
1080 | |||
1081 | { "AEC1 Loopback", "HPOUT1L", "OUT1L" }, | ||
1082 | { "AEC1 Loopback", "HPOUT1R", "OUT1R" }, | ||
1083 | { "AEC2 Loopback", "HPOUT1L", "OUT1L" }, | ||
1084 | { "AEC2 Loopback", "HPOUT1R", "OUT1R" }, | ||
1085 | { "HPOUT1 Demux", NULL, "OUT1L" }, | ||
1086 | { "HPOUT1 Demux", NULL, "OUT1R" }, | ||
1087 | { "HPOUTL", "HPOUT", "HPOUT1 Demux" }, | ||
1088 | { "HPOUTR", "HPOUT", "HPOUT1 Demux" }, | ||
1089 | { "EPOUTP", "EPOUT", "HPOUT1 Demux" }, | ||
1090 | { "EPOUTN", "EPOUT", "HPOUT1 Demux" }, | ||
1091 | |||
1092 | { "AEC1 Loopback", "SPKOUTL", "OUT4L" }, | ||
1093 | { "AEC2 Loopback", "SPKOUTL", "OUT4L" }, | ||
1094 | { "SPKOUTN", NULL, "OUT4L" }, | ||
1095 | { "SPKOUTP", NULL, "OUT4L" }, | ||
1096 | |||
1097 | { "AEC1 Loopback", "SPKDAT1L", "OUT5L" }, | ||
1098 | { "AEC1 Loopback", "SPKDAT1R", "OUT5R" }, | ||
1099 | { "AEC2 Loopback", "SPKDAT1L", "OUT5L" }, | ||
1100 | { "AEC2 Loopback", "SPKDAT1R", "OUT5R" }, | ||
1101 | { "SPKDAT1L", NULL, "OUT5L" }, | ||
1102 | { "SPKDAT1R", NULL, "OUT5R" }, | ||
1103 | |||
1104 | { "SPDIF1", NULL, "SPD1" }, | ||
1105 | |||
1106 | { "MICSUPP", NULL, "SYSCLK" }, | ||
1107 | |||
1108 | { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" }, | ||
1109 | { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" }, | ||
1110 | { "DRC1 Activity Output", "Switch", "DRC1L" }, | ||
1111 | { "DRC1 Activity Output", "Switch", "DRC1R" }, | ||
1112 | { "DRC2 Activity Output", "Switch", "DRC2L" }, | ||
1113 | { "DRC2 Activity Output", "Switch", "DRC2R" }, | ||
1114 | }; | ||
1115 | |||
1116 | static int cs47l15_set_fll(struct snd_soc_component *component, int fll_id, | ||
1117 | int source, unsigned int fref, unsigned int fout) | ||
1118 | { | ||
1119 | struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); | ||
1120 | |||
1121 | switch (fll_id) { | ||
1122 | case MADERA_FLL1_REFCLK: | ||
1123 | return madera_set_fll_refclk(&cs47l15->fll[0], source, fref, | ||
1124 | fout); | ||
1125 | case MADERA_FLLAO_REFCLK: | ||
1126 | return madera_set_fll_ao_refclk(&cs47l15->fll[1], source, fref, | ||
1127 | fout); | ||
1128 | case MADERA_FLL1_SYNCCLK: | ||
1129 | return madera_set_fll_syncclk(&cs47l15->fll[0], source, fref, | ||
1130 | fout); | ||
1131 | default: | ||
1132 | return -EINVAL; | ||
1133 | } | ||
1134 | } | ||
1135 | |||
1136 | static struct snd_soc_dai_driver cs47l15_dai[] = { | ||
1137 | { | ||
1138 | .name = "cs47l15-aif1", | ||
1139 | .id = 1, | ||
1140 | .base = MADERA_AIF1_BCLK_CTRL, | ||
1141 | .playback = { | ||
1142 | .stream_name = "AIF1 Playback", | ||
1143 | .channels_min = 1, | ||
1144 | .channels_max = 6, | ||
1145 | .rates = MADERA_RATES, | ||
1146 | .formats = MADERA_FORMATS, | ||
1147 | }, | ||
1148 | .capture = { | ||
1149 | .stream_name = "AIF1 Capture", | ||
1150 | .channels_min = 1, | ||
1151 | .channels_max = 6, | ||
1152 | .rates = MADERA_RATES, | ||
1153 | .formats = MADERA_FORMATS, | ||
1154 | }, | ||
1155 | .ops = &madera_dai_ops, | ||
1156 | .symmetric_rates = 1, | ||
1157 | .symmetric_samplebits = 1, | ||
1158 | }, | ||
1159 | { | ||
1160 | .name = "cs47l15-aif2", | ||
1161 | .id = 2, | ||
1162 | .base = MADERA_AIF2_BCLK_CTRL, | ||
1163 | .playback = { | ||
1164 | .stream_name = "AIF2 Playback", | ||
1165 | .channels_min = 1, | ||
1166 | .channels_max = 4, | ||
1167 | .rates = MADERA_RATES, | ||
1168 | .formats = MADERA_FORMATS, | ||
1169 | }, | ||
1170 | .capture = { | ||
1171 | .stream_name = "AIF2 Capture", | ||
1172 | .channels_min = 1, | ||
1173 | .channels_max = 4, | ||
1174 | .rates = MADERA_RATES, | ||
1175 | .formats = MADERA_FORMATS, | ||
1176 | }, | ||
1177 | .ops = &madera_dai_ops, | ||
1178 | .symmetric_rates = 1, | ||
1179 | .symmetric_samplebits = 1, | ||
1180 | }, | ||
1181 | { | ||
1182 | .name = "cs47l15-aif3", | ||
1183 | .id = 3, | ||
1184 | .base = MADERA_AIF3_BCLK_CTRL, | ||
1185 | .playback = { | ||
1186 | .stream_name = "AIF3 Playback", | ||
1187 | .channels_min = 1, | ||
1188 | .channels_max = 2, | ||
1189 | .rates = MADERA_RATES, | ||
1190 | .formats = MADERA_FORMATS, | ||
1191 | }, | ||
1192 | .capture = { | ||
1193 | .stream_name = "AIF3 Capture", | ||
1194 | .channels_min = 1, | ||
1195 | .channels_max = 2, | ||
1196 | .rates = MADERA_RATES, | ||
1197 | .formats = MADERA_FORMATS, | ||
1198 | }, | ||
1199 | .ops = &madera_dai_ops, | ||
1200 | .symmetric_rates = 1, | ||
1201 | .symmetric_samplebits = 1, | ||
1202 | }, | ||
1203 | { | ||
1204 | .name = "cs47l15-cpu-trace", | ||
1205 | .capture = { | ||
1206 | .stream_name = "Audio Trace CPU", | ||
1207 | .channels_min = 1, | ||
1208 | .channels_max = 6, | ||
1209 | .rates = MADERA_RATES, | ||
1210 | .formats = MADERA_FORMATS, | ||
1211 | }, | ||
1212 | .compress_new = snd_soc_new_compress, | ||
1213 | }, | ||
1214 | { | ||
1215 | .name = "cs47l15-dsp-trace", | ||
1216 | .capture = { | ||
1217 | .stream_name = "Audio Trace DSP", | ||
1218 | .channels_min = 1, | ||
1219 | .channels_max = 6, | ||
1220 | .rates = MADERA_RATES, | ||
1221 | .formats = MADERA_FORMATS, | ||
1222 | }, | ||
1223 | }, | ||
1224 | }; | ||
1225 | |||
1226 | static int cs47l15_open(struct snd_compr_stream *stream) | ||
1227 | { | ||
1228 | struct snd_soc_pcm_runtime *rtd = stream->private_data; | ||
1229 | struct snd_soc_component *component = | ||
1230 | snd_soc_rtdcom_lookup(rtd, DRV_NAME); | ||
1231 | struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); | ||
1232 | struct madera_priv *priv = &cs47l15->core; | ||
1233 | struct madera *madera = priv->madera; | ||
1234 | int n_adsp; | ||
1235 | |||
1236 | if (strcmp(rtd->codec_dai->name, "cs47l15-dsp-trace") == 0) { | ||
1237 | n_adsp = 0; | ||
1238 | } else { | ||
1239 | dev_err(madera->dev, | ||
1240 | "No suitable compressed stream for DAI '%s'\n", | ||
1241 | rtd->codec_dai->name); | ||
1242 | return -EINVAL; | ||
1243 | } | ||
1244 | |||
1245 | return wm_adsp_compr_open(&priv->adsp[n_adsp], stream); | ||
1246 | } | ||
1247 | |||
1248 | static irqreturn_t cs47l15_adsp2_irq(int irq, void *data) | ||
1249 | { | ||
1250 | struct cs47l15 *cs47l15 = data; | ||
1251 | struct madera_priv *priv = &cs47l15->core; | ||
1252 | struct madera *madera = priv->madera; | ||
1253 | int ret; | ||
1254 | |||
1255 | ret = wm_adsp_compr_handle_irq(&priv->adsp[0]); | ||
1256 | if (ret == -ENODEV) { | ||
1257 | dev_err(madera->dev, "Spurious compressed data IRQ\n"); | ||
1258 | return IRQ_NONE; | ||
1259 | } | ||
1260 | |||
1261 | return IRQ_HANDLED; | ||
1262 | } | ||
1263 | |||
1264 | static int cs47l15_component_probe(struct snd_soc_component *component) | ||
1265 | { | ||
1266 | struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); | ||
1267 | struct madera *madera = cs47l15->core.madera; | ||
1268 | int ret; | ||
1269 | |||
1270 | snd_soc_component_init_regmap(component, madera->regmap); | ||
1271 | |||
1272 | mutex_lock(&madera->dapm_ptr_lock); | ||
1273 | madera->dapm = snd_soc_component_get_dapm(component); | ||
1274 | mutex_unlock(&madera->dapm_ptr_lock); | ||
1275 | |||
1276 | ret = madera_init_inputs(component); | ||
1277 | if (ret) | ||
1278 | return ret; | ||
1279 | |||
1280 | ret = madera_init_outputs(component, CS47L15_MONO_OUTPUTS); | ||
1281 | if (ret) | ||
1282 | return ret; | ||
1283 | |||
1284 | snd_soc_component_disable_pin(component, "HAPTICS"); | ||
1285 | |||
1286 | ret = snd_soc_add_component_controls(component, | ||
1287 | madera_adsp_rate_controls, | ||
1288 | CS47L15_NUM_ADSP); | ||
1289 | if (ret) | ||
1290 | return ret; | ||
1291 | |||
1292 | wm_adsp2_component_probe(&cs47l15->core.adsp[0], component); | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1297 | static void cs47l15_component_remove(struct snd_soc_component *component) | ||
1298 | { | ||
1299 | struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); | ||
1300 | struct madera *madera = cs47l15->core.madera; | ||
1301 | |||
1302 | mutex_lock(&madera->dapm_ptr_lock); | ||
1303 | madera->dapm = NULL; | ||
1304 | mutex_unlock(&madera->dapm_ptr_lock); | ||
1305 | |||
1306 | wm_adsp2_component_remove(&cs47l15->core.adsp[0], component); | ||
1307 | } | ||
1308 | |||
1309 | #define CS47L15_DIG_VU 0x0200 | ||
1310 | |||
1311 | static unsigned int cs47l15_digital_vu[] = { | ||
1312 | MADERA_DAC_DIGITAL_VOLUME_1L, | ||
1313 | MADERA_DAC_DIGITAL_VOLUME_1R, | ||
1314 | MADERA_DAC_DIGITAL_VOLUME_4L, | ||
1315 | MADERA_DAC_DIGITAL_VOLUME_5L, | ||
1316 | MADERA_DAC_DIGITAL_VOLUME_5R, | ||
1317 | }; | ||
1318 | |||
1319 | static const struct snd_compr_ops cs47l15_compr_ops = { | ||
1320 | .open = &cs47l15_open, | ||
1321 | .free = &wm_adsp_compr_free, | ||
1322 | .set_params = &wm_adsp_compr_set_params, | ||
1323 | .get_caps = &wm_adsp_compr_get_caps, | ||
1324 | .trigger = &wm_adsp_compr_trigger, | ||
1325 | .pointer = &wm_adsp_compr_pointer, | ||
1326 | .copy = &wm_adsp_compr_copy, | ||
1327 | }; | ||
1328 | |||
1329 | static const struct snd_soc_component_driver soc_component_dev_cs47l15 = { | ||
1330 | .probe = &cs47l15_component_probe, | ||
1331 | .remove = &cs47l15_component_remove, | ||
1332 | .set_sysclk = &madera_set_sysclk, | ||
1333 | .set_pll = &cs47l15_set_fll, | ||
1334 | .name = DRV_NAME, | ||
1335 | .compr_ops = &cs47l15_compr_ops, | ||
1336 | .controls = cs47l15_snd_controls, | ||
1337 | .num_controls = ARRAY_SIZE(cs47l15_snd_controls), | ||
1338 | .dapm_widgets = cs47l15_dapm_widgets, | ||
1339 | .num_dapm_widgets = ARRAY_SIZE(cs47l15_dapm_widgets), | ||
1340 | .dapm_routes = cs47l15_dapm_routes, | ||
1341 | .num_dapm_routes = ARRAY_SIZE(cs47l15_dapm_routes), | ||
1342 | .use_pmdown_time = 1, | ||
1343 | .endianness = 1, | ||
1344 | .non_legacy_dai_naming = 1, | ||
1345 | }; | ||
1346 | |||
1347 | static int cs47l15_probe(struct platform_device *pdev) | ||
1348 | { | ||
1349 | struct madera *madera = dev_get_drvdata(pdev->dev.parent); | ||
1350 | struct cs47l15 *cs47l15; | ||
1351 | int i, ret; | ||
1352 | |||
1353 | BUILD_BUG_ON(ARRAY_SIZE(cs47l15_dai) > MADERA_MAX_DAI); | ||
1354 | |||
1355 | /* quick exit if Madera irqchip driver hasn't completed probe */ | ||
1356 | if (!madera->irq_dev) { | ||
1357 | dev_dbg(&pdev->dev, "irqchip driver not ready\n"); | ||
1358 | return -EPROBE_DEFER; | ||
1359 | } | ||
1360 | |||
1361 | cs47l15 = devm_kzalloc(&pdev->dev, sizeof(struct cs47l15), | ||
1362 | GFP_KERNEL); | ||
1363 | if (!cs47l15) | ||
1364 | return -ENOMEM; | ||
1365 | |||
1366 | platform_set_drvdata(pdev, cs47l15); | ||
1367 | |||
1368 | cs47l15->core.madera = madera; | ||
1369 | cs47l15->core.dev = &pdev->dev; | ||
1370 | cs47l15->core.num_inputs = 4; | ||
1371 | |||
1372 | ret = madera_core_init(&cs47l15->core); | ||
1373 | if (ret) | ||
1374 | return ret; | ||
1375 | |||
1376 | ret = madera_init_overheat(&cs47l15->core); | ||
1377 | if (ret) | ||
1378 | goto error_core; | ||
1379 | |||
1380 | ret = madera_request_irq(madera, MADERA_IRQ_DSP_IRQ1, | ||
1381 | "ADSP2 Compressed IRQ", cs47l15_adsp2_irq, | ||
1382 | cs47l15); | ||
1383 | if (ret != 0) { | ||
1384 | dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); | ||
1385 | goto error_overheat; | ||
1386 | } | ||
1387 | |||
1388 | ret = madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 1); | ||
1389 | if (ret) | ||
1390 | dev_warn(&pdev->dev, "Failed to set DSP IRQ wake: %d\n", ret); | ||
1391 | |||
1392 | cs47l15->core.adsp[0].part = "cs47l15"; | ||
1393 | cs47l15->core.adsp[0].num = 1; | ||
1394 | cs47l15->core.adsp[0].type = WMFW_ADSP2; | ||
1395 | cs47l15->core.adsp[0].rev = 2; | ||
1396 | cs47l15->core.adsp[0].dev = madera->dev; | ||
1397 | cs47l15->core.adsp[0].regmap = madera->regmap_32bit; | ||
1398 | |||
1399 | cs47l15->core.adsp[0].base = MADERA_DSP1_CONFIG_1; | ||
1400 | cs47l15->core.adsp[0].mem = cs47l15_dsp1_regions; | ||
1401 | cs47l15->core.adsp[0].num_mems = ARRAY_SIZE(cs47l15_dsp1_regions); | ||
1402 | |||
1403 | cs47l15->core.adsp[0].lock_regions = | ||
1404 | WM_ADSP2_REGION_1 | WM_ADSP2_REGION_2 | WM_ADSP2_REGION_3; | ||
1405 | |||
1406 | ret = wm_adsp2_init(&cs47l15->core.adsp[0]); | ||
1407 | if (ret != 0) | ||
1408 | goto error_dsp_irq; | ||
1409 | |||
1410 | ret = madera_init_bus_error_irq(&cs47l15->core, 0, wm_adsp2_bus_error); | ||
1411 | if (ret) | ||
1412 | goto error_adsp; | ||
1413 | |||
1414 | madera_init_fll(madera, 1, MADERA_FLL1_CONTROL_1 - 1, | ||
1415 | &cs47l15->fll[0]); | ||
1416 | madera_init_fll(madera, 4, MADERA_FLLAO_CONTROL_1 - 1, | ||
1417 | &cs47l15->fll[1]); | ||
1418 | |||
1419 | for (i = 0; i < ARRAY_SIZE(cs47l15_dai); i++) | ||
1420 | madera_init_dai(&cs47l15->core, i); | ||
1421 | |||
1422 | /* Latch volume update bits */ | ||
1423 | for (i = 0; i < ARRAY_SIZE(cs47l15_digital_vu); i++) | ||
1424 | regmap_update_bits(madera->regmap, cs47l15_digital_vu[i], | ||
1425 | CS47L15_DIG_VU, CS47L15_DIG_VU); | ||
1426 | |||
1427 | pm_runtime_enable(&pdev->dev); | ||
1428 | pm_runtime_idle(&pdev->dev); | ||
1429 | |||
1430 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
1431 | &soc_component_dev_cs47l15, | ||
1432 | cs47l15_dai, | ||
1433 | ARRAY_SIZE(cs47l15_dai)); | ||
1434 | if (ret < 0) { | ||
1435 | dev_err(&pdev->dev, "Failed to register component: %d\n", ret); | ||
1436 | goto error_pm_runtime; | ||
1437 | } | ||
1438 | |||
1439 | return ret; | ||
1440 | |||
1441 | error_pm_runtime: | ||
1442 | pm_runtime_disable(&pdev->dev); | ||
1443 | madera_free_bus_error_irq(&cs47l15->core, 0); | ||
1444 | error_adsp: | ||
1445 | wm_adsp2_remove(&cs47l15->core.adsp[0]); | ||
1446 | error_dsp_irq: | ||
1447 | madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 0); | ||
1448 | madera_free_irq(madera, MADERA_IRQ_DSP_IRQ1, cs47l15); | ||
1449 | error_overheat: | ||
1450 | madera_free_overheat(&cs47l15->core); | ||
1451 | error_core: | ||
1452 | madera_core_free(&cs47l15->core); | ||
1453 | |||
1454 | return ret; | ||
1455 | } | ||
1456 | |||
1457 | static int cs47l15_remove(struct platform_device *pdev) | ||
1458 | { | ||
1459 | struct cs47l15 *cs47l15 = platform_get_drvdata(pdev); | ||
1460 | |||
1461 | pm_runtime_disable(&pdev->dev); | ||
1462 | |||
1463 | madera_free_bus_error_irq(&cs47l15->core, 0); | ||
1464 | |||
1465 | wm_adsp2_remove(&cs47l15->core.adsp[0]); | ||
1466 | |||
1467 | madera_set_irq_wake(cs47l15->core.madera, MADERA_IRQ_DSP_IRQ1, 0); | ||
1468 | madera_free_irq(cs47l15->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l15); | ||
1469 | madera_free_overheat(&cs47l15->core); | ||
1470 | madera_core_free(&cs47l15->core); | ||
1471 | |||
1472 | return 0; | ||
1473 | } | ||
1474 | |||
1475 | static struct platform_driver cs47l15_codec_driver = { | ||
1476 | .driver = { | ||
1477 | .name = "cs47l15-codec", | ||
1478 | }, | ||
1479 | .probe = &cs47l15_probe, | ||
1480 | .remove = &cs47l15_remove, | ||
1481 | }; | ||
1482 | |||
1483 | module_platform_driver(cs47l15_codec_driver); | ||
1484 | |||
1485 | MODULE_SOFTDEP("pre: madera irq-madera arizona-micsupp"); | ||
1486 | MODULE_DESCRIPTION("ASoC CS47L15 driver"); | ||
1487 | MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | ||
1488 | MODULE_AUTHOR("Jaswinder Jassal <jjassal@opensource.cirrus.com>"); | ||
1489 | MODULE_LICENSE("GPL v2"); | ||
1490 | MODULE_ALIAS("platform:cs47l15-codec"); | ||
diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index e3585c1dab3d..d396a8545d51 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c | |||
@@ -524,7 +524,7 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, | |||
524 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 524 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
525 | SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, | 525 | SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, |
526 | MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), | 526 | MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), |
527 | SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, 6, | 527 | SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, |
528 | 0, NULL, 0), | 528 | 0, NULL, 0), |
529 | 529 | ||
530 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), | 530 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index c4ecb0e6911a..67cac60a859d 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c | |||
@@ -2402,13 +2402,6 @@ static irqreturn_t cs47l90_adsp2_irq(int irq, void *data) | |||
2402 | return IRQ_HANDLED; | 2402 | return IRQ_HANDLED; |
2403 | } | 2403 | } |
2404 | 2404 | ||
2405 | static irqreturn_t cs47l90_dsp_bus_error(int irq, void *data) | ||
2406 | { | ||
2407 | struct wm_adsp *dsp = (struct wm_adsp *)data; | ||
2408 | |||
2409 | return wm_adsp2_bus_error(dsp); | ||
2410 | } | ||
2411 | |||
2412 | static int cs47l90_component_probe(struct snd_soc_component *component) | 2405 | static int cs47l90_component_probe(struct snd_soc_component *component) |
2413 | { | 2406 | { |
2414 | struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); | 2407 | struct cs47l90 *cs47l90 = snd_soc_component_get_drvdata(component); |
@@ -2558,7 +2551,7 @@ static int cs47l90_probe(struct platform_device *pdev) | |||
2558 | 2551 | ||
2559 | if (ret == 0) { | 2552 | if (ret == 0) { |
2560 | ret = madera_init_bus_error_irq(&cs47l90->core, i, | 2553 | ret = madera_init_bus_error_irq(&cs47l90->core, i, |
2561 | cs47l90_dsp_bus_error); | 2554 | wm_adsp2_bus_error); |
2562 | if (ret != 0) | 2555 | if (ret != 0) |
2563 | wm_adsp2_remove(&cs47l90->core.adsp[i]); | 2556 | wm_adsp2_remove(&cs47l90->core.adsp[i]); |
2564 | } | 2557 | } |
diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c new file mode 100644 index 000000000000..d50f75f3b3e4 --- /dev/null +++ b/sound/soc/codecs/cs47l92.c | |||
@@ -0,0 +1,2039 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | // | ||
3 | // ALSA SoC Audio driver for CS47L92 codec | ||
4 | // | ||
5 | // Copyright (C) 2016-2019 Cirrus Logic, Inc. and | ||
6 | // Cirrus Logic International Semiconductor Ltd. | ||
7 | // | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/moduleparam.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/pm.h> | ||
15 | #include <linux/pm_runtime.h> | ||
16 | #include <linux/regmap.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/tlv.h> | ||
22 | |||
23 | #include <linux/irqchip/irq-madera.h> | ||
24 | #include <linux/mfd/madera/core.h> | ||
25 | #include <linux/mfd/madera/registers.h> | ||
26 | |||
27 | #include "madera.h" | ||
28 | #include "wm_adsp.h" | ||
29 | |||
30 | #define CS47L92_NUM_ADSP 1 | ||
31 | #define CS47L92_MONO_OUTPUTS 3 | ||
32 | |||
33 | #define DRV_NAME "cs47l92-codec" | ||
34 | |||
35 | struct cs47l92 { | ||
36 | struct madera_priv core; | ||
37 | struct madera_fll fll[2]; | ||
38 | }; | ||
39 | |||
40 | static const struct wm_adsp_region cs47l92_dsp1_regions[] = { | ||
41 | { .type = WMFW_ADSP2_PM, .base = 0x080000 }, | ||
42 | { .type = WMFW_ADSP2_ZM, .base = 0x0e0000 }, | ||
43 | { .type = WMFW_ADSP2_XM, .base = 0x0a0000 }, | ||
44 | { .type = WMFW_ADSP2_YM, .base = 0x0c0000 }, | ||
45 | }; | ||
46 | |||
47 | static const char * const cs47l92_outdemux_texts[] = { | ||
48 | "HPOUT3", | ||
49 | "HPOUT4", | ||
50 | }; | ||
51 | |||
52 | static int cs47l92_put_demux(struct snd_kcontrol *kcontrol, | ||
53 | struct snd_ctl_elem_value *ucontrol) | ||
54 | { | ||
55 | struct snd_soc_component *component = | ||
56 | snd_soc_dapm_kcontrol_component(kcontrol); | ||
57 | struct snd_soc_dapm_context *dapm = | ||
58 | snd_soc_component_get_dapm(component); | ||
59 | struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); | ||
60 | struct madera_priv *priv = &cs47l92->core; | ||
61 | struct madera *madera = priv->madera; | ||
62 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
63 | unsigned int ep_sel, mux, change, cur; | ||
64 | bool out_mono; | ||
65 | int ret; | ||
66 | |||
67 | if (ucontrol->value.enumerated.item[0] > e->items - 1) | ||
68 | return -EINVAL; | ||
69 | |||
70 | mux = ucontrol->value.enumerated.item[0]; | ||
71 | |||
72 | snd_soc_dapm_mutex_lock(dapm); | ||
73 | |||
74 | ep_sel = mux << e->shift_l; | ||
75 | |||
76 | change = snd_soc_component_test_bits(component, MADERA_OUTPUT_ENABLES_1, | ||
77 | MADERA_EP_SEL_MASK, | ||
78 | ep_sel); | ||
79 | if (!change) | ||
80 | goto end; | ||
81 | |||
82 | ret = regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &cur); | ||
83 | if (ret != 0) | ||
84 | dev_warn(madera->dev, "Failed to read outputs: %d\n", ret); | ||
85 | |||
86 | /* EP_SEL should not be modified while HPOUT3 or 4 is enabled */ | ||
87 | ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, | ||
88 | MADERA_OUT3L_ENA | MADERA_OUT3R_ENA, 0); | ||
89 | if (ret) | ||
90 | dev_warn(madera->dev, "Failed to disable outputs: %d\n", ret); | ||
91 | |||
92 | usleep_range(2000, 3000); /* wait for wseq to complete */ | ||
93 | |||
94 | ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, | ||
95 | MADERA_EP_SEL, ep_sel); | ||
96 | if (ret) { | ||
97 | dev_err(madera->dev, "Failed to set OUT3 demux: %d\n", ret); | ||
98 | } else { | ||
99 | out_mono = madera->pdata.codec.out_mono[2 + mux]; | ||
100 | |||
101 | ret = madera_set_output_mode(component, 3, out_mono); | ||
102 | if (ret < 0) | ||
103 | dev_warn(madera->dev, | ||
104 | "Failed to set output mode: %d\n", ret); | ||
105 | } | ||
106 | |||
107 | ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, | ||
108 | MADERA_OUT3L_ENA | MADERA_OUT3R_ENA, cur); | ||
109 | if (ret) { | ||
110 | dev_warn(madera->dev, "Failed to restore outputs: %d\n", ret); | ||
111 | } else { | ||
112 | /* wait for wseq */ | ||
113 | if (cur & (MADERA_OUT3L_ENA | MADERA_OUT3R_ENA)) | ||
114 | msleep(34); /* enable delay */ | ||
115 | else | ||
116 | usleep_range(2000, 3000); /* disable delay */ | ||
117 | } | ||
118 | |||
119 | end: | ||
120 | snd_soc_dapm_mutex_unlock(dapm); | ||
121 | |||
122 | return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); | ||
123 | } | ||
124 | |||
125 | static SOC_ENUM_SINGLE_DECL(cs47l92_outdemux_enum, | ||
126 | MADERA_OUTPUT_ENABLES_1, | ||
127 | MADERA_EP_SEL_SHIFT, | ||
128 | cs47l92_outdemux_texts); | ||
129 | |||
130 | static const struct snd_kcontrol_new cs47l92_outdemux = | ||
131 | SOC_DAPM_ENUM_EXT("OUT3 Demux", cs47l92_outdemux_enum, | ||
132 | snd_soc_dapm_get_enum_double, cs47l92_put_demux); | ||
133 | |||
134 | static int cs47l92_adsp_power_ev(struct snd_soc_dapm_widget *w, | ||
135 | struct snd_kcontrol *kcontrol, | ||
136 | int event) | ||
137 | { | ||
138 | struct snd_soc_component *component = | ||
139 | snd_soc_dapm_to_component(w->dapm); | ||
140 | struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); | ||
141 | struct madera_priv *priv = &cs47l92->core; | ||
142 | struct madera *madera = priv->madera; | ||
143 | unsigned int freq; | ||
144 | int ret; | ||
145 | |||
146 | ret = regmap_read(madera->regmap, MADERA_DSP_CLOCK_2, &freq); | ||
147 | if (ret != 0) { | ||
148 | dev_err(madera->dev, | ||
149 | "Failed to read MADERA_DSP_CLOCK_2: %d\n", ret); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | switch (event) { | ||
154 | case SND_SOC_DAPM_PRE_PMU: | ||
155 | ret = madera_set_adsp_clk(&cs47l92->core, w->shift, freq); | ||
156 | if (ret) | ||
157 | return ret; | ||
158 | break; | ||
159 | default: | ||
160 | break; | ||
161 | } | ||
162 | |||
163 | return wm_adsp_early_event(w, kcontrol, event); | ||
164 | } | ||
165 | |||
166 | #define CS47L92_NG_SRC(name, base) \ | ||
167 | SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ | ||
168 | SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ | ||
169 | SOC_SINGLE(name " NG HPOUT2L Switch", base, 2, 1, 0), \ | ||
170 | SOC_SINGLE(name " NG HPOUT2R Switch", base, 3, 1, 0), \ | ||
171 | SOC_SINGLE(name " NG HPOUT3L Switch", base, 4, 1, 0), \ | ||
172 | SOC_SINGLE(name " NG HPOUT3R Switch", base, 5, 1, 0), \ | ||
173 | SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \ | ||
174 | SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0) | ||
175 | |||
176 | static const struct snd_kcontrol_new cs47l92_snd_controls[] = { | ||
177 | SOC_ENUM("IN1 OSR", madera_in_dmic_osr[0]), | ||
178 | SOC_ENUM("IN2 OSR", madera_in_dmic_osr[1]), | ||
179 | SOC_ENUM("IN3 OSR", madera_in_dmic_osr[2]), | ||
180 | SOC_ENUM("IN4 OSR", madera_in_dmic_osr[3]), | ||
181 | |||
182 | SOC_SINGLE_RANGE_TLV("IN1L Volume", MADERA_IN1L_CONTROL, | ||
183 | MADERA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), | ||
184 | SOC_SINGLE_RANGE_TLV("IN1R Volume", MADERA_IN1R_CONTROL, | ||
185 | MADERA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), | ||
186 | SOC_SINGLE_RANGE_TLV("IN2L Volume", MADERA_IN2L_CONTROL, | ||
187 | MADERA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), | ||
188 | SOC_SINGLE_RANGE_TLV("IN2R Volume", MADERA_IN2R_CONTROL, | ||
189 | MADERA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, madera_ana_tlv), | ||
190 | |||
191 | SOC_ENUM("IN HPF Cutoff Frequency", madera_in_hpf_cut_enum), | ||
192 | |||
193 | SOC_SINGLE_EXT("IN1L LP Switch", MADERA_ADC_DIGITAL_VOLUME_1L, | ||
194 | MADERA_IN1L_LP_MODE_SHIFT, 1, 0, | ||
195 | snd_soc_get_volsw, madera_lp_mode_put), | ||
196 | SOC_SINGLE_EXT("IN1R LP Switch", MADERA_ADC_DIGITAL_VOLUME_1R, | ||
197 | MADERA_IN1L_LP_MODE_SHIFT, 1, 0, | ||
198 | snd_soc_get_volsw, madera_lp_mode_put), | ||
199 | SOC_SINGLE_EXT("IN2L LP Switch", MADERA_ADC_DIGITAL_VOLUME_2L, | ||
200 | MADERA_IN1L_LP_MODE_SHIFT, 1, 0, | ||
201 | snd_soc_get_volsw, madera_lp_mode_put), | ||
202 | SOC_SINGLE_EXT("IN2R LP Switch", MADERA_ADC_DIGITAL_VOLUME_2R, | ||
203 | MADERA_IN1L_LP_MODE_SHIFT, 1, 0, | ||
204 | snd_soc_get_volsw, madera_lp_mode_put), | ||
205 | |||
206 | SOC_SINGLE("IN1L HPF Switch", MADERA_IN1L_CONTROL, | ||
207 | MADERA_IN1L_HPF_SHIFT, 1, 0), | ||
208 | SOC_SINGLE("IN1R HPF Switch", MADERA_IN1R_CONTROL, | ||
209 | MADERA_IN1R_HPF_SHIFT, 1, 0), | ||
210 | SOC_SINGLE("IN2L HPF Switch", MADERA_IN2L_CONTROL, | ||
211 | MADERA_IN2L_HPF_SHIFT, 1, 0), | ||
212 | SOC_SINGLE("IN2R HPF Switch", MADERA_IN2R_CONTROL, | ||
213 | MADERA_IN2R_HPF_SHIFT, 1, 0), | ||
214 | SOC_SINGLE("IN3L HPF Switch", MADERA_IN3L_CONTROL, | ||
215 | MADERA_IN3L_HPF_SHIFT, 1, 0), | ||
216 | SOC_SINGLE("IN3R HPF Switch", MADERA_IN3R_CONTROL, | ||
217 | MADERA_IN3R_HPF_SHIFT, 1, 0), | ||
218 | SOC_SINGLE("IN4L HPF Switch", MADERA_IN4L_CONTROL, | ||
219 | MADERA_IN4L_HPF_SHIFT, 1, 0), | ||
220 | SOC_SINGLE("IN4R HPF Switch", MADERA_IN4R_CONTROL, | ||
221 | MADERA_IN4R_HPF_SHIFT, 1, 0), | ||
222 | |||
223 | SOC_SINGLE_TLV("IN1L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1L, | ||
224 | MADERA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
225 | SOC_SINGLE_TLV("IN1R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_1R, | ||
226 | MADERA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
227 | SOC_SINGLE_TLV("IN2L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2L, | ||
228 | MADERA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
229 | SOC_SINGLE_TLV("IN2R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_2R, | ||
230 | MADERA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
231 | SOC_SINGLE_TLV("IN3L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_3L, | ||
232 | MADERA_IN3L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
233 | SOC_SINGLE_TLV("IN3R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_3R, | ||
234 | MADERA_IN3R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
235 | SOC_SINGLE_TLV("IN4L Digital Volume", MADERA_ADC_DIGITAL_VOLUME_4L, | ||
236 | MADERA_IN4L_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
237 | SOC_SINGLE_TLV("IN4R Digital Volume", MADERA_ADC_DIGITAL_VOLUME_4R, | ||
238 | MADERA_IN4R_DIG_VOL_SHIFT, 0xbf, 0, madera_digital_tlv), | ||
239 | |||
240 | SOC_ENUM("Input Ramp Up", madera_in_vi_ramp), | ||
241 | SOC_ENUM("Input Ramp Down", madera_in_vd_ramp), | ||
242 | |||
243 | MADERA_MIXER_CONTROLS("EQ1", MADERA_EQ1MIX_INPUT_1_SOURCE), | ||
244 | MADERA_MIXER_CONTROLS("EQ2", MADERA_EQ2MIX_INPUT_1_SOURCE), | ||
245 | MADERA_MIXER_CONTROLS("EQ3", MADERA_EQ3MIX_INPUT_1_SOURCE), | ||
246 | MADERA_MIXER_CONTROLS("EQ4", MADERA_EQ4MIX_INPUT_1_SOURCE), | ||
247 | |||
248 | MADERA_EQ_CONTROL("EQ1 Coefficients", MADERA_EQ1_2), | ||
249 | SOC_SINGLE_TLV("EQ1 B1 Volume", MADERA_EQ1_1, MADERA_EQ1_B1_GAIN_SHIFT, | ||
250 | 24, 0, madera_eq_tlv), | ||
251 | SOC_SINGLE_TLV("EQ1 B2 Volume", MADERA_EQ1_1, MADERA_EQ1_B2_GAIN_SHIFT, | ||
252 | 24, 0, madera_eq_tlv), | ||
253 | SOC_SINGLE_TLV("EQ1 B3 Volume", MADERA_EQ1_1, MADERA_EQ1_B3_GAIN_SHIFT, | ||
254 | 24, 0, madera_eq_tlv), | ||
255 | SOC_SINGLE_TLV("EQ1 B4 Volume", MADERA_EQ1_2, MADERA_EQ1_B4_GAIN_SHIFT, | ||
256 | 24, 0, madera_eq_tlv), | ||
257 | SOC_SINGLE_TLV("EQ1 B5 Volume", MADERA_EQ1_2, MADERA_EQ1_B5_GAIN_SHIFT, | ||
258 | 24, 0, madera_eq_tlv), | ||
259 | |||
260 | MADERA_EQ_CONTROL("EQ2 Coefficients", MADERA_EQ2_2), | ||
261 | SOC_SINGLE_TLV("EQ2 B1 Volume", MADERA_EQ2_1, MADERA_EQ2_B1_GAIN_SHIFT, | ||
262 | 24, 0, madera_eq_tlv), | ||
263 | SOC_SINGLE_TLV("EQ2 B2 Volume", MADERA_EQ2_1, MADERA_EQ2_B2_GAIN_SHIFT, | ||
264 | 24, 0, madera_eq_tlv), | ||
265 | SOC_SINGLE_TLV("EQ2 B3 Volume", MADERA_EQ2_1, MADERA_EQ2_B3_GAIN_SHIFT, | ||
266 | 24, 0, madera_eq_tlv), | ||
267 | SOC_SINGLE_TLV("EQ2 B4 Volume", MADERA_EQ2_2, MADERA_EQ2_B4_GAIN_SHIFT, | ||
268 | 24, 0, madera_eq_tlv), | ||
269 | SOC_SINGLE_TLV("EQ2 B5 Volume", MADERA_EQ2_2, MADERA_EQ2_B5_GAIN_SHIFT, | ||
270 | 24, 0, madera_eq_tlv), | ||
271 | |||
272 | MADERA_EQ_CONTROL("EQ3 Coefficients", MADERA_EQ3_2), | ||
273 | SOC_SINGLE_TLV("EQ3 B1 Volume", MADERA_EQ3_1, MADERA_EQ3_B1_GAIN_SHIFT, | ||
274 | 24, 0, madera_eq_tlv), | ||
275 | SOC_SINGLE_TLV("EQ3 B2 Volume", MADERA_EQ3_1, MADERA_EQ3_B2_GAIN_SHIFT, | ||
276 | 24, 0, madera_eq_tlv), | ||
277 | SOC_SINGLE_TLV("EQ3 B3 Volume", MADERA_EQ3_1, MADERA_EQ3_B3_GAIN_SHIFT, | ||
278 | 24, 0, madera_eq_tlv), | ||
279 | SOC_SINGLE_TLV("EQ3 B4 Volume", MADERA_EQ3_2, MADERA_EQ3_B4_GAIN_SHIFT, | ||
280 | 24, 0, madera_eq_tlv), | ||
281 | SOC_SINGLE_TLV("EQ3 B5 Volume", MADERA_EQ3_2, MADERA_EQ3_B5_GAIN_SHIFT, | ||
282 | 24, 0, madera_eq_tlv), | ||
283 | |||
284 | MADERA_EQ_CONTROL("EQ4 Coefficients", MADERA_EQ4_2), | ||
285 | SOC_SINGLE_TLV("EQ4 B1 Volume", MADERA_EQ4_1, MADERA_EQ4_B1_GAIN_SHIFT, | ||
286 | 24, 0, madera_eq_tlv), | ||
287 | SOC_SINGLE_TLV("EQ4 B2 Volume", MADERA_EQ4_1, MADERA_EQ4_B2_GAIN_SHIFT, | ||
288 | 24, 0, madera_eq_tlv), | ||
289 | SOC_SINGLE_TLV("EQ4 B3 Volume", MADERA_EQ4_1, MADERA_EQ4_B3_GAIN_SHIFT, | ||
290 | 24, 0, madera_eq_tlv), | ||
291 | SOC_SINGLE_TLV("EQ4 B4 Volume", MADERA_EQ4_2, MADERA_EQ4_B4_GAIN_SHIFT, | ||
292 | 24, 0, madera_eq_tlv), | ||
293 | SOC_SINGLE_TLV("EQ4 B5 Volume", MADERA_EQ4_2, MADERA_EQ4_B5_GAIN_SHIFT, | ||
294 | 24, 0, madera_eq_tlv), | ||
295 | |||
296 | SOC_SINGLE("DAC High Performance Mode Switch", MADERA_OUTPUT_RATE_1, | ||
297 | MADERA_CP_DAC_MODE_SHIFT, 1, 0), | ||
298 | |||
299 | MADERA_MIXER_CONTROLS("DRC1L", MADERA_DRC1LMIX_INPUT_1_SOURCE), | ||
300 | MADERA_MIXER_CONTROLS("DRC1R", MADERA_DRC1RMIX_INPUT_1_SOURCE), | ||
301 | MADERA_MIXER_CONTROLS("DRC2L", MADERA_DRC2LMIX_INPUT_1_SOURCE), | ||
302 | MADERA_MIXER_CONTROLS("DRC2R", MADERA_DRC2RMIX_INPUT_1_SOURCE), | ||
303 | |||
304 | SND_SOC_BYTES_MASK("DRC1", MADERA_DRC1_CTRL1, 5, | ||
305 | MADERA_DRC1R_ENA | MADERA_DRC1L_ENA), | ||
306 | SND_SOC_BYTES_MASK("DRC2", MADERA_DRC2_CTRL1, 5, | ||
307 | MADERA_DRC2R_ENA | MADERA_DRC2L_ENA), | ||
308 | |||
309 | MADERA_MIXER_CONTROLS("LHPF1", MADERA_HPLP1MIX_INPUT_1_SOURCE), | ||
310 | MADERA_MIXER_CONTROLS("LHPF2", MADERA_HPLP2MIX_INPUT_1_SOURCE), | ||
311 | MADERA_MIXER_CONTROLS("LHPF3", MADERA_HPLP3MIX_INPUT_1_SOURCE), | ||
312 | MADERA_MIXER_CONTROLS("LHPF4", MADERA_HPLP4MIX_INPUT_1_SOURCE), | ||
313 | |||
314 | MADERA_LHPF_CONTROL("LHPF1 Coefficients", MADERA_HPLPF1_2), | ||
315 | MADERA_LHPF_CONTROL("LHPF2 Coefficients", MADERA_HPLPF2_2), | ||
316 | MADERA_LHPF_CONTROL("LHPF3 Coefficients", MADERA_HPLPF3_2), | ||
317 | MADERA_LHPF_CONTROL("LHPF4 Coefficients", MADERA_HPLPF4_2), | ||
318 | |||
319 | SOC_ENUM("LHPF1 Mode", madera_lhpf1_mode), | ||
320 | SOC_ENUM("LHPF2 Mode", madera_lhpf2_mode), | ||
321 | SOC_ENUM("LHPF3 Mode", madera_lhpf3_mode), | ||
322 | SOC_ENUM("LHPF4 Mode", madera_lhpf4_mode), | ||
323 | |||
324 | MADERA_RATE_ENUM("ISRC1 FSL", madera_isrc_fsl[0]), | ||
325 | MADERA_RATE_ENUM("ISRC2 FSL", madera_isrc_fsl[1]), | ||
326 | MADERA_RATE_ENUM("ISRC1 FSH", madera_isrc_fsh[0]), | ||
327 | MADERA_RATE_ENUM("ISRC2 FSH", madera_isrc_fsh[1]), | ||
328 | MADERA_RATE_ENUM("ASRC1 Rate 1", madera_asrc1_bidir_rate[0]), | ||
329 | MADERA_RATE_ENUM("ASRC1 Rate 2", madera_asrc1_bidir_rate[1]), | ||
330 | |||
331 | WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), | ||
332 | |||
333 | MADERA_MIXER_CONTROLS("DSP1L", MADERA_DSP1LMIX_INPUT_1_SOURCE), | ||
334 | MADERA_MIXER_CONTROLS("DSP1R", MADERA_DSP1RMIX_INPUT_1_SOURCE), | ||
335 | |||
336 | SOC_SINGLE_TLV("Noise Generator Volume", MADERA_COMFORT_NOISE_GENERATOR, | ||
337 | MADERA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, madera_noise_tlv), | ||
338 | |||
339 | MADERA_MIXER_CONTROLS("HPOUT1L", MADERA_OUT1LMIX_INPUT_1_SOURCE), | ||
340 | MADERA_MIXER_CONTROLS("HPOUT1R", MADERA_OUT1RMIX_INPUT_1_SOURCE), | ||
341 | MADERA_MIXER_CONTROLS("HPOUT2L", MADERA_OUT2LMIX_INPUT_1_SOURCE), | ||
342 | MADERA_MIXER_CONTROLS("HPOUT2R", MADERA_OUT2RMIX_INPUT_1_SOURCE), | ||
343 | MADERA_MIXER_CONTROLS("HPOUT3L", MADERA_OUT3LMIX_INPUT_1_SOURCE), | ||
344 | MADERA_MIXER_CONTROLS("HPOUT3R", MADERA_OUT3RMIX_INPUT_1_SOURCE), | ||
345 | MADERA_MIXER_CONTROLS("SPKDAT1L", MADERA_OUT5LMIX_INPUT_1_SOURCE), | ||
346 | MADERA_MIXER_CONTROLS("SPKDAT1R", MADERA_OUT5RMIX_INPUT_1_SOURCE), | ||
347 | |||
348 | SOC_SINGLE("HPOUT1 SC Protect Switch", MADERA_HP1_SHORT_CIRCUIT_CTRL, | ||
349 | MADERA_HP1_SC_ENA_SHIFT, 1, 0), | ||
350 | SOC_SINGLE("HPOUT2 SC Protect Switch", MADERA_HP2_SHORT_CIRCUIT_CTRL, | ||
351 | MADERA_HP2_SC_ENA_SHIFT, 1, 0), | ||
352 | SOC_SINGLE("HPOUT3 SC Protect Switch", MADERA_HP3_SHORT_CIRCUIT_CTRL, | ||
353 | MADERA_HP3_SC_ENA_SHIFT, 1, 0), | ||
354 | |||
355 | SOC_SINGLE("SPKDAT1 High Performance Switch", MADERA_OUTPUT_PATH_CONFIG_5L, | ||
356 | MADERA_OUT5_OSR_SHIFT, 1, 0), | ||
357 | |||
358 | SOC_DOUBLE_R("HPOUT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_1L, | ||
359 | MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_MUTE_SHIFT, 1, 1), | ||
360 | SOC_DOUBLE_R("HPOUT2 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_2L, | ||
361 | MADERA_DAC_DIGITAL_VOLUME_2R, MADERA_OUT2L_MUTE_SHIFT, 1, 1), | ||
362 | SOC_DOUBLE_R("HPOUT3 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_3L, | ||
363 | MADERA_DAC_DIGITAL_VOLUME_3R, MADERA_OUT3L_MUTE_SHIFT, 1, 1), | ||
364 | SOC_DOUBLE_R("SPKDAT1 Digital Switch", MADERA_DAC_DIGITAL_VOLUME_5L, | ||
365 | MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_MUTE_SHIFT, 1, 1), | ||
366 | |||
367 | SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_1L, | ||
368 | MADERA_DAC_DIGITAL_VOLUME_1R, MADERA_OUT1L_VOL_SHIFT, | ||
369 | 0xbf, 0, madera_digital_tlv), | ||
370 | SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_2L, | ||
371 | MADERA_DAC_DIGITAL_VOLUME_2R, MADERA_OUT2L_VOL_SHIFT, | ||
372 | 0xbf, 0, madera_digital_tlv), | ||
373 | SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_3L, | ||
374 | MADERA_DAC_DIGITAL_VOLUME_3R, MADERA_OUT3L_VOL_SHIFT, | ||
375 | 0xbf, 0, madera_digital_tlv), | ||
376 | SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", MADERA_DAC_DIGITAL_VOLUME_5L, | ||
377 | MADERA_DAC_DIGITAL_VOLUME_5R, MADERA_OUT5L_VOL_SHIFT, | ||
378 | 0xbf, 0, madera_digital_tlv), | ||
379 | |||
380 | SOC_DOUBLE("SPKDAT1 Switch", MADERA_PDM_SPK1_CTRL_1, MADERA_SPK1L_MUTE_SHIFT, | ||
381 | MADERA_SPK1R_MUTE_SHIFT, 1, 1), | ||
382 | |||
383 | SOC_ENUM("Output Ramp Up", madera_out_vi_ramp), | ||
384 | SOC_ENUM("Output Ramp Down", madera_out_vd_ramp), | ||
385 | |||
386 | SOC_SINGLE("Noise Gate Switch", MADERA_NOISE_GATE_CONTROL, | ||
387 | MADERA_NGATE_ENA_SHIFT, 1, 0), | ||
388 | SOC_SINGLE_TLV("Noise Gate Threshold Volume", MADERA_NOISE_GATE_CONTROL, | ||
389 | MADERA_NGATE_THR_SHIFT, 7, 1, madera_ng_tlv), | ||
390 | SOC_ENUM("Noise Gate Hold", madera_ng_hold), | ||
391 | |||
392 | SOC_ENUM_EXT("DFC1RX Width", madera_dfc_width[0], | ||
393 | snd_soc_get_enum_double, madera_dfc_put), | ||
394 | SOC_ENUM_EXT("DFC1RX Type", madera_dfc_type[0], | ||
395 | snd_soc_get_enum_double, madera_dfc_put), | ||
396 | SOC_ENUM_EXT("DFC1TX Width", madera_dfc_width[1], | ||
397 | snd_soc_get_enum_double, madera_dfc_put), | ||
398 | SOC_ENUM_EXT("DFC1TX Type", madera_dfc_type[1], | ||
399 | snd_soc_get_enum_double, madera_dfc_put), | ||
400 | SOC_ENUM_EXT("DFC2RX Width", madera_dfc_width[2], | ||
401 | snd_soc_get_enum_double, madera_dfc_put), | ||
402 | SOC_ENUM_EXT("DFC2RX Type", madera_dfc_type[2], | ||
403 | snd_soc_get_enum_double, madera_dfc_put), | ||
404 | SOC_ENUM_EXT("DFC2TX Width", madera_dfc_width[3], | ||
405 | snd_soc_get_enum_double, madera_dfc_put), | ||
406 | SOC_ENUM_EXT("DFC2TX Type", madera_dfc_type[3], | ||
407 | snd_soc_get_enum_double, madera_dfc_put), | ||
408 | SOC_ENUM_EXT("DFC3RX Width", madera_dfc_width[4], | ||
409 | snd_soc_get_enum_double, madera_dfc_put), | ||
410 | SOC_ENUM_EXT("DFC3RX Type", madera_dfc_type[4], | ||
411 | snd_soc_get_enum_double, madera_dfc_put), | ||
412 | SOC_ENUM_EXT("DFC3TX Width", madera_dfc_width[5], | ||
413 | snd_soc_get_enum_double, madera_dfc_put), | ||
414 | SOC_ENUM_EXT("DFC3TX Type", madera_dfc_type[5], | ||
415 | snd_soc_get_enum_double, madera_dfc_put), | ||
416 | SOC_ENUM_EXT("DFC4RX Width", madera_dfc_width[6], | ||
417 | snd_soc_get_enum_double, madera_dfc_put), | ||
418 | SOC_ENUM_EXT("DFC4RX Type", madera_dfc_type[6], | ||
419 | snd_soc_get_enum_double, madera_dfc_put), | ||
420 | SOC_ENUM_EXT("DFC4TX Width", madera_dfc_width[7], | ||
421 | snd_soc_get_enum_double, madera_dfc_put), | ||
422 | SOC_ENUM_EXT("DFC4TX Type", madera_dfc_type[7], | ||
423 | snd_soc_get_enum_double, madera_dfc_put), | ||
424 | SOC_ENUM_EXT("DFC5RX Width", madera_dfc_width[8], | ||
425 | snd_soc_get_enum_double, madera_dfc_put), | ||
426 | SOC_ENUM_EXT("DFC5RX Type", madera_dfc_type[8], | ||
427 | snd_soc_get_enum_double, madera_dfc_put), | ||
428 | SOC_ENUM_EXT("DFC5TX Width", madera_dfc_width[9], | ||
429 | snd_soc_get_enum_double, madera_dfc_put), | ||
430 | SOC_ENUM_EXT("DFC5TX Type", madera_dfc_type[9], | ||
431 | snd_soc_get_enum_double, madera_dfc_put), | ||
432 | SOC_ENUM_EXT("DFC6RX Width", madera_dfc_width[10], | ||
433 | snd_soc_get_enum_double, madera_dfc_put), | ||
434 | SOC_ENUM_EXT("DFC6RX Type", madera_dfc_type[10], | ||
435 | snd_soc_get_enum_double, madera_dfc_put), | ||
436 | SOC_ENUM_EXT("DFC6TX Width", madera_dfc_width[11], | ||
437 | snd_soc_get_enum_double, madera_dfc_put), | ||
438 | SOC_ENUM_EXT("DFC6TX Type", madera_dfc_type[11], | ||
439 | snd_soc_get_enum_double, madera_dfc_put), | ||
440 | SOC_ENUM_EXT("DFC7RX Width", madera_dfc_width[12], | ||
441 | snd_soc_get_enum_double, madera_dfc_put), | ||
442 | SOC_ENUM_EXT("DFC7RX Type", madera_dfc_type[12], | ||
443 | snd_soc_get_enum_double, madera_dfc_put), | ||
444 | SOC_ENUM_EXT("DFC7TX Width", madera_dfc_width[13], | ||
445 | snd_soc_get_enum_double, madera_dfc_put), | ||
446 | SOC_ENUM_EXT("DFC7TX Type", madera_dfc_type[13], | ||
447 | snd_soc_get_enum_double, madera_dfc_put), | ||
448 | SOC_ENUM_EXT("DFC8RX Width", madera_dfc_width[14], | ||
449 | snd_soc_get_enum_double, madera_dfc_put), | ||
450 | SOC_ENUM_EXT("DFC8RX Type", madera_dfc_type[14], | ||
451 | snd_soc_get_enum_double, madera_dfc_put), | ||
452 | SOC_ENUM_EXT("DFC8TX Width", madera_dfc_width[15], | ||
453 | snd_soc_get_enum_double, madera_dfc_put), | ||
454 | SOC_ENUM_EXT("DFC8TX Type", madera_dfc_type[15], | ||
455 | snd_soc_get_enum_double, madera_dfc_put), | ||
456 | |||
457 | CS47L92_NG_SRC("HPOUT1L", MADERA_NOISE_GATE_SELECT_1L), | ||
458 | CS47L92_NG_SRC("HPOUT1R", MADERA_NOISE_GATE_SELECT_1R), | ||
459 | CS47L92_NG_SRC("HPOUT2L", MADERA_NOISE_GATE_SELECT_2L), | ||
460 | CS47L92_NG_SRC("HPOUT2R", MADERA_NOISE_GATE_SELECT_2R), | ||
461 | CS47L92_NG_SRC("HPOUT3L", MADERA_NOISE_GATE_SELECT_3L), | ||
462 | CS47L92_NG_SRC("HPOUT3R", MADERA_NOISE_GATE_SELECT_3R), | ||
463 | CS47L92_NG_SRC("SPKDAT1L", MADERA_NOISE_GATE_SELECT_5L), | ||
464 | CS47L92_NG_SRC("SPKDAT1R", MADERA_NOISE_GATE_SELECT_5R), | ||
465 | |||
466 | MADERA_MIXER_CONTROLS("AIF1TX1", MADERA_AIF1TX1MIX_INPUT_1_SOURCE), | ||
467 | MADERA_MIXER_CONTROLS("AIF1TX2", MADERA_AIF1TX2MIX_INPUT_1_SOURCE), | ||
468 | MADERA_MIXER_CONTROLS("AIF1TX3", MADERA_AIF1TX3MIX_INPUT_1_SOURCE), | ||
469 | MADERA_MIXER_CONTROLS("AIF1TX4", MADERA_AIF1TX4MIX_INPUT_1_SOURCE), | ||
470 | MADERA_MIXER_CONTROLS("AIF1TX5", MADERA_AIF1TX5MIX_INPUT_1_SOURCE), | ||
471 | MADERA_MIXER_CONTROLS("AIF1TX6", MADERA_AIF1TX6MIX_INPUT_1_SOURCE), | ||
472 | MADERA_MIXER_CONTROLS("AIF1TX7", MADERA_AIF1TX7MIX_INPUT_1_SOURCE), | ||
473 | MADERA_MIXER_CONTROLS("AIF1TX8", MADERA_AIF1TX8MIX_INPUT_1_SOURCE), | ||
474 | |||
475 | MADERA_MIXER_CONTROLS("AIF2TX1", MADERA_AIF2TX1MIX_INPUT_1_SOURCE), | ||
476 | MADERA_MIXER_CONTROLS("AIF2TX2", MADERA_AIF2TX2MIX_INPUT_1_SOURCE), | ||
477 | MADERA_MIXER_CONTROLS("AIF2TX3", MADERA_AIF2TX3MIX_INPUT_1_SOURCE), | ||
478 | MADERA_MIXER_CONTROLS("AIF2TX4", MADERA_AIF2TX4MIX_INPUT_1_SOURCE), | ||
479 | MADERA_MIXER_CONTROLS("AIF2TX5", MADERA_AIF2TX5MIX_INPUT_1_SOURCE), | ||
480 | MADERA_MIXER_CONTROLS("AIF2TX6", MADERA_AIF2TX6MIX_INPUT_1_SOURCE), | ||
481 | MADERA_MIXER_CONTROLS("AIF2TX7", MADERA_AIF2TX7MIX_INPUT_1_SOURCE), | ||
482 | MADERA_MIXER_CONTROLS("AIF2TX8", MADERA_AIF2TX8MIX_INPUT_1_SOURCE), | ||
483 | |||
484 | MADERA_MIXER_CONTROLS("AIF3TX1", MADERA_AIF3TX1MIX_INPUT_1_SOURCE), | ||
485 | MADERA_MIXER_CONTROLS("AIF3TX2", MADERA_AIF3TX2MIX_INPUT_1_SOURCE), | ||
486 | MADERA_MIXER_CONTROLS("AIF3TX3", MADERA_AIF3TX3MIX_INPUT_1_SOURCE), | ||
487 | MADERA_MIXER_CONTROLS("AIF3TX4", MADERA_AIF3TX4MIX_INPUT_1_SOURCE), | ||
488 | |||
489 | MADERA_MIXER_CONTROLS("SLIMTX1", MADERA_SLIMTX1MIX_INPUT_1_SOURCE), | ||
490 | MADERA_MIXER_CONTROLS("SLIMTX2", MADERA_SLIMTX2MIX_INPUT_1_SOURCE), | ||
491 | MADERA_MIXER_CONTROLS("SLIMTX3", MADERA_SLIMTX3MIX_INPUT_1_SOURCE), | ||
492 | MADERA_MIXER_CONTROLS("SLIMTX4", MADERA_SLIMTX4MIX_INPUT_1_SOURCE), | ||
493 | MADERA_MIXER_CONTROLS("SLIMTX5", MADERA_SLIMTX5MIX_INPUT_1_SOURCE), | ||
494 | MADERA_MIXER_CONTROLS("SLIMTX6", MADERA_SLIMTX6MIX_INPUT_1_SOURCE), | ||
495 | MADERA_MIXER_CONTROLS("SLIMTX7", MADERA_SLIMTX7MIX_INPUT_1_SOURCE), | ||
496 | MADERA_MIXER_CONTROLS("SLIMTX8", MADERA_SLIMTX8MIX_INPUT_1_SOURCE), | ||
497 | |||
498 | MADERA_GAINMUX_CONTROLS("SPDIFTX1", MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE), | ||
499 | MADERA_GAINMUX_CONTROLS("SPDIFTX2", MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE), | ||
500 | |||
501 | WM_ADSP_FW_CONTROL("DSP1", 0), | ||
502 | }; | ||
503 | |||
504 | MADERA_MIXER_ENUMS(EQ1, MADERA_EQ1MIX_INPUT_1_SOURCE); | ||
505 | MADERA_MIXER_ENUMS(EQ2, MADERA_EQ2MIX_INPUT_1_SOURCE); | ||
506 | MADERA_MIXER_ENUMS(EQ3, MADERA_EQ3MIX_INPUT_1_SOURCE); | ||
507 | MADERA_MIXER_ENUMS(EQ4, MADERA_EQ4MIX_INPUT_1_SOURCE); | ||
508 | |||
509 | MADERA_MIXER_ENUMS(DRC1L, MADERA_DRC1LMIX_INPUT_1_SOURCE); | ||
510 | MADERA_MIXER_ENUMS(DRC1R, MADERA_DRC1RMIX_INPUT_1_SOURCE); | ||
511 | MADERA_MIXER_ENUMS(DRC2L, MADERA_DRC2LMIX_INPUT_1_SOURCE); | ||
512 | MADERA_MIXER_ENUMS(DRC2R, MADERA_DRC2RMIX_INPUT_1_SOURCE); | ||
513 | |||
514 | MADERA_MIXER_ENUMS(LHPF1, MADERA_HPLP1MIX_INPUT_1_SOURCE); | ||
515 | MADERA_MIXER_ENUMS(LHPF2, MADERA_HPLP2MIX_INPUT_1_SOURCE); | ||
516 | MADERA_MIXER_ENUMS(LHPF3, MADERA_HPLP3MIX_INPUT_1_SOURCE); | ||
517 | MADERA_MIXER_ENUMS(LHPF4, MADERA_HPLP4MIX_INPUT_1_SOURCE); | ||
518 | |||
519 | MADERA_MIXER_ENUMS(DSP1L, MADERA_DSP1LMIX_INPUT_1_SOURCE); | ||
520 | MADERA_MIXER_ENUMS(DSP1R, MADERA_DSP1RMIX_INPUT_1_SOURCE); | ||
521 | MADERA_DSP_AUX_ENUMS(DSP1, MADERA_DSP1AUX1MIX_INPUT_1_SOURCE); | ||
522 | |||
523 | MADERA_MIXER_ENUMS(PWM1, MADERA_PWM1MIX_INPUT_1_SOURCE); | ||
524 | MADERA_MIXER_ENUMS(PWM2, MADERA_PWM2MIX_INPUT_1_SOURCE); | ||
525 | |||
526 | MADERA_MIXER_ENUMS(OUT1L, MADERA_OUT1LMIX_INPUT_1_SOURCE); | ||
527 | MADERA_MIXER_ENUMS(OUT1R, MADERA_OUT1RMIX_INPUT_1_SOURCE); | ||
528 | MADERA_MIXER_ENUMS(OUT2L, MADERA_OUT2LMIX_INPUT_1_SOURCE); | ||
529 | MADERA_MIXER_ENUMS(OUT2R, MADERA_OUT2RMIX_INPUT_1_SOURCE); | ||
530 | MADERA_MIXER_ENUMS(OUT3L, MADERA_OUT3LMIX_INPUT_1_SOURCE); | ||
531 | MADERA_MIXER_ENUMS(OUT3R, MADERA_OUT3RMIX_INPUT_1_SOURCE); | ||
532 | MADERA_MIXER_ENUMS(SPKDAT1L, MADERA_OUT5LMIX_INPUT_1_SOURCE); | ||
533 | MADERA_MIXER_ENUMS(SPKDAT1R, MADERA_OUT5RMIX_INPUT_1_SOURCE); | ||
534 | |||
535 | MADERA_MIXER_ENUMS(AIF1TX1, MADERA_AIF1TX1MIX_INPUT_1_SOURCE); | ||
536 | MADERA_MIXER_ENUMS(AIF1TX2, MADERA_AIF1TX2MIX_INPUT_1_SOURCE); | ||
537 | MADERA_MIXER_ENUMS(AIF1TX3, MADERA_AIF1TX3MIX_INPUT_1_SOURCE); | ||
538 | MADERA_MIXER_ENUMS(AIF1TX4, MADERA_AIF1TX4MIX_INPUT_1_SOURCE); | ||
539 | MADERA_MIXER_ENUMS(AIF1TX5, MADERA_AIF1TX5MIX_INPUT_1_SOURCE); | ||
540 | MADERA_MIXER_ENUMS(AIF1TX6, MADERA_AIF1TX6MIX_INPUT_1_SOURCE); | ||
541 | MADERA_MIXER_ENUMS(AIF1TX7, MADERA_AIF1TX7MIX_INPUT_1_SOURCE); | ||
542 | MADERA_MIXER_ENUMS(AIF1TX8, MADERA_AIF1TX8MIX_INPUT_1_SOURCE); | ||
543 | |||
544 | MADERA_MIXER_ENUMS(AIF2TX1, MADERA_AIF2TX1MIX_INPUT_1_SOURCE); | ||
545 | MADERA_MIXER_ENUMS(AIF2TX2, MADERA_AIF2TX2MIX_INPUT_1_SOURCE); | ||
546 | MADERA_MIXER_ENUMS(AIF2TX3, MADERA_AIF2TX3MIX_INPUT_1_SOURCE); | ||
547 | MADERA_MIXER_ENUMS(AIF2TX4, MADERA_AIF2TX4MIX_INPUT_1_SOURCE); | ||
548 | MADERA_MIXER_ENUMS(AIF2TX5, MADERA_AIF2TX5MIX_INPUT_1_SOURCE); | ||
549 | MADERA_MIXER_ENUMS(AIF2TX6, MADERA_AIF2TX6MIX_INPUT_1_SOURCE); | ||
550 | MADERA_MIXER_ENUMS(AIF2TX7, MADERA_AIF2TX7MIX_INPUT_1_SOURCE); | ||
551 | MADERA_MIXER_ENUMS(AIF2TX8, MADERA_AIF2TX8MIX_INPUT_1_SOURCE); | ||
552 | |||
553 | MADERA_MIXER_ENUMS(AIF3TX1, MADERA_AIF3TX1MIX_INPUT_1_SOURCE); | ||
554 | MADERA_MIXER_ENUMS(AIF3TX2, MADERA_AIF3TX2MIX_INPUT_1_SOURCE); | ||
555 | MADERA_MIXER_ENUMS(AIF3TX3, MADERA_AIF3TX3MIX_INPUT_1_SOURCE); | ||
556 | MADERA_MIXER_ENUMS(AIF3TX4, MADERA_AIF3TX4MIX_INPUT_1_SOURCE); | ||
557 | |||
558 | MADERA_MIXER_ENUMS(SLIMTX1, MADERA_SLIMTX1MIX_INPUT_1_SOURCE); | ||
559 | MADERA_MIXER_ENUMS(SLIMTX2, MADERA_SLIMTX2MIX_INPUT_1_SOURCE); | ||
560 | MADERA_MIXER_ENUMS(SLIMTX3, MADERA_SLIMTX3MIX_INPUT_1_SOURCE); | ||
561 | MADERA_MIXER_ENUMS(SLIMTX4, MADERA_SLIMTX4MIX_INPUT_1_SOURCE); | ||
562 | MADERA_MIXER_ENUMS(SLIMTX5, MADERA_SLIMTX5MIX_INPUT_1_SOURCE); | ||
563 | MADERA_MIXER_ENUMS(SLIMTX6, MADERA_SLIMTX6MIX_INPUT_1_SOURCE); | ||
564 | MADERA_MIXER_ENUMS(SLIMTX7, MADERA_SLIMTX7MIX_INPUT_1_SOURCE); | ||
565 | MADERA_MIXER_ENUMS(SLIMTX8, MADERA_SLIMTX8MIX_INPUT_1_SOURCE); | ||
566 | |||
567 | MADERA_MUX_ENUMS(SPD1TX1, MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE); | ||
568 | MADERA_MUX_ENUMS(SPD1TX2, MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE); | ||
569 | |||
570 | MADERA_MUX_ENUMS(ASRC1IN1L, MADERA_ASRC1_1LMIX_INPUT_1_SOURCE); | ||
571 | MADERA_MUX_ENUMS(ASRC1IN1R, MADERA_ASRC1_1RMIX_INPUT_1_SOURCE); | ||
572 | MADERA_MUX_ENUMS(ASRC1IN2L, MADERA_ASRC1_2LMIX_INPUT_1_SOURCE); | ||
573 | MADERA_MUX_ENUMS(ASRC1IN2R, MADERA_ASRC1_2RMIX_INPUT_1_SOURCE); | ||
574 | |||
575 | MADERA_MUX_ENUMS(ISRC1INT1, MADERA_ISRC1INT1MIX_INPUT_1_SOURCE); | ||
576 | MADERA_MUX_ENUMS(ISRC1INT2, MADERA_ISRC1INT2MIX_INPUT_1_SOURCE); | ||
577 | |||
578 | MADERA_MUX_ENUMS(ISRC1DEC1, MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE); | ||
579 | MADERA_MUX_ENUMS(ISRC1DEC2, MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE); | ||
580 | |||
581 | MADERA_MUX_ENUMS(ISRC2INT1, MADERA_ISRC2INT1MIX_INPUT_1_SOURCE); | ||
582 | MADERA_MUX_ENUMS(ISRC2INT2, MADERA_ISRC2INT2MIX_INPUT_1_SOURCE); | ||
583 | |||
584 | MADERA_MUX_ENUMS(ISRC2DEC1, MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE); | ||
585 | MADERA_MUX_ENUMS(ISRC2DEC2, MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE); | ||
586 | |||
587 | MADERA_MUX_ENUMS(DFC1, MADERA_DFC1MIX_INPUT_1_SOURCE); | ||
588 | MADERA_MUX_ENUMS(DFC2, MADERA_DFC2MIX_INPUT_1_SOURCE); | ||
589 | MADERA_MUX_ENUMS(DFC3, MADERA_DFC3MIX_INPUT_1_SOURCE); | ||
590 | MADERA_MUX_ENUMS(DFC4, MADERA_DFC4MIX_INPUT_1_SOURCE); | ||
591 | MADERA_MUX_ENUMS(DFC5, MADERA_DFC5MIX_INPUT_1_SOURCE); | ||
592 | MADERA_MUX_ENUMS(DFC6, MADERA_DFC6MIX_INPUT_1_SOURCE); | ||
593 | MADERA_MUX_ENUMS(DFC7, MADERA_DFC7MIX_INPUT_1_SOURCE); | ||
594 | MADERA_MUX_ENUMS(DFC8, MADERA_DFC8MIX_INPUT_1_SOURCE); | ||
595 | |||
596 | static const char * const cs47l92_aec_loopback_texts[] = { | ||
597 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", | ||
598 | "SPKDAT1L", "SPKDAT1R", | ||
599 | }; | ||
600 | |||
601 | static const unsigned int cs47l92_aec_loopback_values[] = { | ||
602 | 0, 1, 2, 3, 4, 5, 8, 9 | ||
603 | }; | ||
604 | |||
605 | static const struct soc_enum cs47l92_aec_loopback = | ||
606 | SOC_VALUE_ENUM_SINGLE(MADERA_DAC_AEC_CONTROL_1, | ||
607 | MADERA_AEC1_LOOPBACK_SRC_SHIFT, 0xf, | ||
608 | ARRAY_SIZE(cs47l92_aec_loopback_texts), | ||
609 | cs47l92_aec_loopback_texts, | ||
610 | cs47l92_aec_loopback_values); | ||
611 | |||
612 | static const struct snd_kcontrol_new cs47l92_aec_loopback_mux = | ||
613 | SOC_DAPM_ENUM("AEC1 Loopback", cs47l92_aec_loopback); | ||
614 | |||
615 | static const struct snd_soc_dapm_widget cs47l92_dapm_widgets[] = { | ||
616 | SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, | ||
617 | 0, madera_sysclk_ev, | ||
618 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
619 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, | ||
620 | MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | ||
621 | SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, | ||
622 | MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), | ||
623 | SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, | ||
624 | MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), | ||
625 | SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, | ||
626 | MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), | ||
627 | |||
628 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), | ||
629 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD2", 20, 0), | ||
630 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), | ||
631 | |||
632 | SND_SOC_DAPM_SUPPLY("MICBIAS1", MADERA_MIC_BIAS_CTRL_1, | ||
633 | MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
634 | SND_SOC_DAPM_SUPPLY("MICBIAS2", MADERA_MIC_BIAS_CTRL_2, | ||
635 | MADERA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
636 | |||
637 | SND_SOC_DAPM_SUPPLY("MICBIAS1A", MADERA_MIC_BIAS_CTRL_5, | ||
638 | MADERA_MICB1A_ENA_SHIFT, 0, NULL, 0), | ||
639 | SND_SOC_DAPM_SUPPLY("MICBIAS1B", MADERA_MIC_BIAS_CTRL_5, | ||
640 | MADERA_MICB1B_ENA_SHIFT, 0, NULL, 0), | ||
641 | SND_SOC_DAPM_SUPPLY("MICBIAS1C", MADERA_MIC_BIAS_CTRL_5, | ||
642 | MADERA_MICB1C_ENA_SHIFT, 0, NULL, 0), | ||
643 | SND_SOC_DAPM_SUPPLY("MICBIAS1D", MADERA_MIC_BIAS_CTRL_5, | ||
644 | MADERA_MICB1D_ENA_SHIFT, 0, NULL, 0), | ||
645 | |||
646 | SND_SOC_DAPM_SUPPLY("MICBIAS2A", MADERA_MIC_BIAS_CTRL_6, | ||
647 | MADERA_MICB2A_ENA_SHIFT, 0, NULL, 0), | ||
648 | SND_SOC_DAPM_SUPPLY("MICBIAS2B", MADERA_MIC_BIAS_CTRL_6, | ||
649 | MADERA_MICB2B_ENA_SHIFT, 0, NULL, 0), | ||
650 | |||
651 | SND_SOC_DAPM_SUPPLY("FXCLK", SND_SOC_NOPM, | ||
652 | MADERA_DOM_GRP_FX, 0, | ||
653 | madera_domain_clk_ev, | ||
654 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
655 | SND_SOC_DAPM_SUPPLY("ASRC1CLK", SND_SOC_NOPM, | ||
656 | MADERA_DOM_GRP_ASRC1, 0, | ||
657 | madera_domain_clk_ev, | ||
658 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
659 | SND_SOC_DAPM_SUPPLY("ISRC1CLK", SND_SOC_NOPM, | ||
660 | MADERA_DOM_GRP_ISRC1, 0, | ||
661 | madera_domain_clk_ev, | ||
662 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
663 | SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, | ||
664 | MADERA_DOM_GRP_ISRC2, 0, | ||
665 | madera_domain_clk_ev, | ||
666 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
667 | SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, | ||
668 | MADERA_DOM_GRP_OUT, 0, | ||
669 | madera_domain_clk_ev, | ||
670 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
671 | SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, | ||
672 | MADERA_DOM_GRP_SPD, 0, | ||
673 | madera_domain_clk_ev, | ||
674 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
675 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, | ||
676 | MADERA_DOM_GRP_DSP1, 0, | ||
677 | madera_domain_clk_ev, | ||
678 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
679 | SND_SOC_DAPM_SUPPLY("AIF1TXCLK", SND_SOC_NOPM, | ||
680 | MADERA_DOM_GRP_AIF1, 0, | ||
681 | madera_domain_clk_ev, | ||
682 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
683 | SND_SOC_DAPM_SUPPLY("AIF2TXCLK", SND_SOC_NOPM, | ||
684 | MADERA_DOM_GRP_AIF2, 0, | ||
685 | madera_domain_clk_ev, | ||
686 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
687 | SND_SOC_DAPM_SUPPLY("AIF3TXCLK", SND_SOC_NOPM, | ||
688 | MADERA_DOM_GRP_AIF3, 0, | ||
689 | madera_domain_clk_ev, | ||
690 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
691 | SND_SOC_DAPM_SUPPLY("SLIMBUSCLK", SND_SOC_NOPM, | ||
692 | MADERA_DOM_GRP_SLIMBUS, 0, | ||
693 | madera_domain_clk_ev, | ||
694 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
695 | SND_SOC_DAPM_SUPPLY("PWMCLK", SND_SOC_NOPM, | ||
696 | MADERA_DOM_GRP_PWM, 0, | ||
697 | madera_domain_clk_ev, | ||
698 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
699 | SND_SOC_DAPM_SUPPLY("DFCCLK", SND_SOC_NOPM, | ||
700 | MADERA_DOM_GRP_DFC, 0, | ||
701 | madera_domain_clk_ev, | ||
702 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
703 | |||
704 | SND_SOC_DAPM_SIGGEN("TONE"), | ||
705 | SND_SOC_DAPM_SIGGEN("NOISE"), | ||
706 | |||
707 | SND_SOC_DAPM_INPUT("IN1ALN"), | ||
708 | SND_SOC_DAPM_INPUT("IN1ALP"), | ||
709 | SND_SOC_DAPM_INPUT("IN1BLN"), | ||
710 | SND_SOC_DAPM_INPUT("IN1BLP"), | ||
711 | SND_SOC_DAPM_INPUT("IN1ARN"), | ||
712 | SND_SOC_DAPM_INPUT("IN1ARP"), | ||
713 | SND_SOC_DAPM_INPUT("IN1BR"), | ||
714 | SND_SOC_DAPM_INPUT("IN2ALN"), | ||
715 | SND_SOC_DAPM_INPUT("IN2ALP"), | ||
716 | SND_SOC_DAPM_INPUT("IN2BL"), | ||
717 | SND_SOC_DAPM_INPUT("IN2ARN"), | ||
718 | SND_SOC_DAPM_INPUT("IN2ARP"), | ||
719 | SND_SOC_DAPM_INPUT("IN2BR"), | ||
720 | |||
721 | SND_SOC_DAPM_MUX("IN1L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[0]), | ||
722 | SND_SOC_DAPM_MUX("IN1R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[1]), | ||
723 | SND_SOC_DAPM_MUX("IN2L Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[2]), | ||
724 | SND_SOC_DAPM_MUX("IN2R Analog Mux", SND_SOC_NOPM, 0, 0, &madera_inmux[3]), | ||
725 | |||
726 | SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), | ||
727 | SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[0]), | ||
728 | |||
729 | SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), | ||
730 | SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]), | ||
731 | |||
732 | SND_SOC_DAPM_DEMUX("OUT3 Demux", SND_SOC_NOPM, 0, 0, &cs47l92_outdemux), | ||
733 | |||
734 | SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), | ||
735 | SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), | ||
736 | |||
737 | SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT, | ||
738 | 0, NULL, 0), | ||
739 | SND_SOC_DAPM_PGA("PWM2 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM2_ENA_SHIFT, | ||
740 | 0, NULL, 0), | ||
741 | |||
742 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | ||
743 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX1_ENA_SHIFT, 0), | ||
744 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | ||
745 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX2_ENA_SHIFT, 0), | ||
746 | SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, | ||
747 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX3_ENA_SHIFT, 0), | ||
748 | SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, | ||
749 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX4_ENA_SHIFT, 0), | ||
750 | SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, | ||
751 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX5_ENA_SHIFT, 0), | ||
752 | SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, | ||
753 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX6_ENA_SHIFT, 0), | ||
754 | SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, | ||
755 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX7_ENA_SHIFT, 0), | ||
756 | SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, | ||
757 | MADERA_AIF1_TX_ENABLES, MADERA_AIF1TX8_ENA_SHIFT, 0), | ||
758 | |||
759 | SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | ||
760 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX1_ENA_SHIFT, 0), | ||
761 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | ||
762 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX2_ENA_SHIFT, 0), | ||
763 | SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0, | ||
764 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX3_ENA_SHIFT, 0), | ||
765 | SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0, | ||
766 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX4_ENA_SHIFT, 0), | ||
767 | SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0, | ||
768 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX5_ENA_SHIFT, 0), | ||
769 | SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0, | ||
770 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX6_ENA_SHIFT, 0), | ||
771 | SND_SOC_DAPM_AIF_OUT("AIF2TX7", NULL, 0, | ||
772 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX7_ENA_SHIFT, 0), | ||
773 | SND_SOC_DAPM_AIF_OUT("AIF2TX8", NULL, 0, | ||
774 | MADERA_AIF2_TX_ENABLES, MADERA_AIF2TX8_ENA_SHIFT, 0), | ||
775 | |||
776 | SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, | ||
777 | MADERA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
778 | MADERA_SLIMTX1_ENA_SHIFT, 0), | ||
779 | SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, | ||
780 | MADERA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
781 | MADERA_SLIMTX2_ENA_SHIFT, 0), | ||
782 | SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, | ||
783 | MADERA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
784 | MADERA_SLIMTX3_ENA_SHIFT, 0), | ||
785 | SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, | ||
786 | MADERA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
787 | MADERA_SLIMTX4_ENA_SHIFT, 0), | ||
788 | SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, | ||
789 | MADERA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
790 | MADERA_SLIMTX5_ENA_SHIFT, 0), | ||
791 | SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, | ||
792 | MADERA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
793 | MADERA_SLIMTX6_ENA_SHIFT, 0), | ||
794 | SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, | ||
795 | MADERA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
796 | MADERA_SLIMTX7_ENA_SHIFT, 0), | ||
797 | SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, | ||
798 | MADERA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
799 | MADERA_SLIMTX8_ENA_SHIFT, 0), | ||
800 | |||
801 | SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, | ||
802 | MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX1_ENA_SHIFT, 0), | ||
803 | SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, | ||
804 | MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX2_ENA_SHIFT, 0), | ||
805 | SND_SOC_DAPM_AIF_OUT("AIF3TX3", NULL, 0, | ||
806 | MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX3_ENA_SHIFT, 0), | ||
807 | SND_SOC_DAPM_AIF_OUT("AIF3TX4", NULL, 0, | ||
808 | MADERA_AIF3_TX_ENABLES, MADERA_AIF3TX4_ENA_SHIFT, 0), | ||
809 | |||
810 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, | ||
811 | MADERA_OUT1L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, | ||
812 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
813 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
814 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, | ||
815 | MADERA_OUT1R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, | ||
816 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
817 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
818 | SND_SOC_DAPM_PGA_E("OUT2L", SND_SOC_NOPM, | ||
819 | MADERA_OUT2L_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, | ||
820 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
821 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
822 | SND_SOC_DAPM_PGA_E("OUT2R", SND_SOC_NOPM, | ||
823 | MADERA_OUT2R_ENA_SHIFT, 0, NULL, 0, madera_hp_ev, | ||
824 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
825 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
826 | SND_SOC_DAPM_PGA_E("OUT3L", MADERA_OUTPUT_ENABLES_1, | ||
827 | MADERA_OUT3L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, | ||
828 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
829 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
830 | SND_SOC_DAPM_PGA_E("OUT3R", MADERA_OUTPUT_ENABLES_1, | ||
831 | MADERA_OUT3R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, | ||
832 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
833 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
834 | SND_SOC_DAPM_PGA_E("OUT5L", MADERA_OUTPUT_ENABLES_1, | ||
835 | MADERA_OUT5L_ENA_SHIFT, 0, NULL, 0, madera_out_ev, | ||
836 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
837 | SND_SOC_DAPM_PGA_E("OUT5R", MADERA_OUTPUT_ENABLES_1, | ||
838 | MADERA_OUT5R_ENA_SHIFT, 0, NULL, 0, madera_out_ev, | ||
839 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
840 | |||
841 | SND_SOC_DAPM_PGA("SPD1TX1", MADERA_SPD1_TX_CONTROL, | ||
842 | MADERA_SPD1_VAL1_SHIFT, 0, NULL, 0), | ||
843 | SND_SOC_DAPM_PGA("SPD1TX2", MADERA_SPD1_TX_CONTROL, | ||
844 | MADERA_SPD1_VAL2_SHIFT, 0, NULL, 0), | ||
845 | SND_SOC_DAPM_OUT_DRV("SPD1", MADERA_SPD1_TX_CONTROL, | ||
846 | MADERA_SPD1_ENA_SHIFT, 0, NULL, 0), | ||
847 | |||
848 | /* | ||
849 | * mux_in widgets : arranged in the order of sources | ||
850 | * specified in MADERA_MIXER_INPUT_ROUTES | ||
851 | */ | ||
852 | |||
853 | SND_SOC_DAPM_PGA("Noise Generator", MADERA_COMFORT_NOISE_GENERATOR, | ||
854 | MADERA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), | ||
855 | |||
856 | SND_SOC_DAPM_PGA("Tone Generator 1", MADERA_TONE_GENERATOR_1, | ||
857 | MADERA_TONE1_ENA_SHIFT, 0, NULL, 0), | ||
858 | SND_SOC_DAPM_PGA("Tone Generator 2", MADERA_TONE_GENERATOR_1, | ||
859 | MADERA_TONE2_ENA_SHIFT, 0, NULL, 0), | ||
860 | |||
861 | SND_SOC_DAPM_SIGGEN("HAPTICS"), | ||
862 | |||
863 | SND_SOC_DAPM_MUX("AEC1 Loopback", MADERA_DAC_AEC_CONTROL_1, | ||
864 | MADERA_AEC1_LOOPBACK_ENA_SHIFT, 0, | ||
865 | &cs47l92_aec_loopback_mux), | ||
866 | |||
867 | SND_SOC_DAPM_PGA_E("IN1L", MADERA_INPUT_ENABLES, MADERA_IN1L_ENA_SHIFT, | ||
868 | 0, NULL, 0, madera_in_ev, | ||
869 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
870 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
871 | SND_SOC_DAPM_PGA_E("IN1R", MADERA_INPUT_ENABLES, MADERA_IN1R_ENA_SHIFT, | ||
872 | 0, NULL, 0, madera_in_ev, | ||
873 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
874 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
875 | SND_SOC_DAPM_PGA_E("IN2L", MADERA_INPUT_ENABLES, MADERA_IN2L_ENA_SHIFT, | ||
876 | 0, NULL, 0, madera_in_ev, | ||
877 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
878 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
879 | SND_SOC_DAPM_PGA_E("IN2R", MADERA_INPUT_ENABLES, MADERA_IN2R_ENA_SHIFT, | ||
880 | 0, NULL, 0, madera_in_ev, | ||
881 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
882 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
883 | SND_SOC_DAPM_PGA_E("IN3L", MADERA_INPUT_ENABLES, MADERA_IN3L_ENA_SHIFT, | ||
884 | 0, NULL, 0, madera_in_ev, | ||
885 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
886 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
887 | SND_SOC_DAPM_PGA_E("IN3R", MADERA_INPUT_ENABLES, MADERA_IN3R_ENA_SHIFT, | ||
888 | 0, NULL, 0, madera_in_ev, | ||
889 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
890 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
891 | SND_SOC_DAPM_PGA_E("IN4L", MADERA_INPUT_ENABLES, MADERA_IN4L_ENA_SHIFT, | ||
892 | 0, NULL, 0, madera_in_ev, | ||
893 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
894 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
895 | SND_SOC_DAPM_PGA_E("IN4R", MADERA_INPUT_ENABLES, MADERA_IN4R_ENA_SHIFT, | ||
896 | 0, NULL, 0, madera_in_ev, | ||
897 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | | ||
898 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
899 | |||
900 | SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, | ||
901 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX1_ENA_SHIFT, 0), | ||
902 | SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, | ||
903 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX2_ENA_SHIFT, 0), | ||
904 | SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, | ||
905 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX3_ENA_SHIFT, 0), | ||
906 | SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, | ||
907 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX4_ENA_SHIFT, 0), | ||
908 | SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, | ||
909 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX5_ENA_SHIFT, 0), | ||
910 | SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, | ||
911 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX6_ENA_SHIFT, 0), | ||
912 | SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, | ||
913 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX7_ENA_SHIFT, 0), | ||
914 | SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, | ||
915 | MADERA_AIF1_RX_ENABLES, MADERA_AIF1RX8_ENA_SHIFT, 0), | ||
916 | |||
917 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | ||
918 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX1_ENA_SHIFT, 0), | ||
919 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | ||
920 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX2_ENA_SHIFT, 0), | ||
921 | SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0, | ||
922 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX3_ENA_SHIFT, 0), | ||
923 | SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0, | ||
924 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX4_ENA_SHIFT, 0), | ||
925 | SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0, | ||
926 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX5_ENA_SHIFT, 0), | ||
927 | SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0, | ||
928 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX6_ENA_SHIFT, 0), | ||
929 | SND_SOC_DAPM_AIF_IN("AIF2RX7", NULL, 0, | ||
930 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX7_ENA_SHIFT, 0), | ||
931 | SND_SOC_DAPM_AIF_IN("AIF2RX8", NULL, 0, | ||
932 | MADERA_AIF2_RX_ENABLES, MADERA_AIF2RX8_ENA_SHIFT, 0), | ||
933 | |||
934 | SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | ||
935 | MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX1_ENA_SHIFT, 0), | ||
936 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | ||
937 | MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX2_ENA_SHIFT, 0), | ||
938 | SND_SOC_DAPM_AIF_IN("AIF3RX3", NULL, 0, | ||
939 | MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX3_ENA_SHIFT, 0), | ||
940 | SND_SOC_DAPM_AIF_IN("AIF3RX4", NULL, 0, | ||
941 | MADERA_AIF3_RX_ENABLES, MADERA_AIF3RX4_ENA_SHIFT, 0), | ||
942 | |||
943 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
944 | MADERA_SLIMRX1_ENA_SHIFT, 0), | ||
945 | SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
946 | MADERA_SLIMRX2_ENA_SHIFT, 0), | ||
947 | SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
948 | MADERA_SLIMRX3_ENA_SHIFT, 0), | ||
949 | SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
950 | MADERA_SLIMRX4_ENA_SHIFT, 0), | ||
951 | SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
952 | MADERA_SLIMRX5_ENA_SHIFT, 0), | ||
953 | SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
954 | MADERA_SLIMRX6_ENA_SHIFT, 0), | ||
955 | SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
956 | MADERA_SLIMRX7_ENA_SHIFT, 0), | ||
957 | SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, MADERA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
958 | MADERA_SLIMRX8_ENA_SHIFT, 0), | ||
959 | |||
960 | SND_SOC_DAPM_PGA("EQ1", MADERA_EQ1_1, MADERA_EQ1_ENA_SHIFT, 0, NULL, 0), | ||
961 | SND_SOC_DAPM_PGA("EQ2", MADERA_EQ2_1, MADERA_EQ2_ENA_SHIFT, 0, NULL, 0), | ||
962 | SND_SOC_DAPM_PGA("EQ3", MADERA_EQ3_1, MADERA_EQ3_ENA_SHIFT, 0, NULL, 0), | ||
963 | SND_SOC_DAPM_PGA("EQ4", MADERA_EQ4_1, MADERA_EQ4_ENA_SHIFT, 0, NULL, 0), | ||
964 | |||
965 | SND_SOC_DAPM_PGA("DRC1L", MADERA_DRC1_CTRL1, MADERA_DRC1L_ENA_SHIFT, 0, | ||
966 | NULL, 0), | ||
967 | SND_SOC_DAPM_PGA("DRC1R", MADERA_DRC1_CTRL1, MADERA_DRC1R_ENA_SHIFT, 0, | ||
968 | NULL, 0), | ||
969 | SND_SOC_DAPM_PGA("DRC2L", MADERA_DRC2_CTRL1, MADERA_DRC2L_ENA_SHIFT, 0, | ||
970 | NULL, 0), | ||
971 | SND_SOC_DAPM_PGA("DRC2R", MADERA_DRC2_CTRL1, MADERA_DRC2R_ENA_SHIFT, 0, | ||
972 | NULL, 0), | ||
973 | |||
974 | SND_SOC_DAPM_PGA("LHPF1", MADERA_HPLPF1_1, MADERA_LHPF1_ENA_SHIFT, 0, | ||
975 | NULL, 0), | ||
976 | SND_SOC_DAPM_PGA("LHPF2", MADERA_HPLPF2_1, MADERA_LHPF2_ENA_SHIFT, 0, | ||
977 | NULL, 0), | ||
978 | SND_SOC_DAPM_PGA("LHPF3", MADERA_HPLPF3_1, MADERA_LHPF3_ENA_SHIFT, 0, | ||
979 | NULL, 0), | ||
980 | SND_SOC_DAPM_PGA("LHPF4", MADERA_HPLPF4_1, MADERA_LHPF4_ENA_SHIFT, 0, | ||
981 | NULL, 0), | ||
982 | |||
983 | SND_SOC_DAPM_PGA("ASRC1IN1L", MADERA_ASRC1_ENABLE, | ||
984 | MADERA_ASRC1_IN1L_ENA_SHIFT, 0, NULL, 0), | ||
985 | SND_SOC_DAPM_PGA("ASRC1IN1R", MADERA_ASRC1_ENABLE, | ||
986 | MADERA_ASRC1_IN1R_ENA_SHIFT, 0, NULL, 0), | ||
987 | SND_SOC_DAPM_PGA("ASRC1IN2L", MADERA_ASRC1_ENABLE, | ||
988 | MADERA_ASRC1_IN2L_ENA_SHIFT, 0, NULL, 0), | ||
989 | SND_SOC_DAPM_PGA("ASRC1IN2R", MADERA_ASRC1_ENABLE, | ||
990 | MADERA_ASRC1_IN2R_ENA_SHIFT, 0, NULL, 0), | ||
991 | |||
992 | SND_SOC_DAPM_PGA("ISRC1DEC1", MADERA_ISRC_1_CTRL_3, | ||
993 | MADERA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
994 | SND_SOC_DAPM_PGA("ISRC1DEC2", MADERA_ISRC_1_CTRL_3, | ||
995 | MADERA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
996 | |||
997 | SND_SOC_DAPM_PGA("ISRC1INT1", MADERA_ISRC_1_CTRL_3, | ||
998 | MADERA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0), | ||
999 | SND_SOC_DAPM_PGA("ISRC1INT2", MADERA_ISRC_1_CTRL_3, | ||
1000 | MADERA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0), | ||
1001 | |||
1002 | SND_SOC_DAPM_PGA("ISRC2DEC1", MADERA_ISRC_2_CTRL_3, | ||
1003 | MADERA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0), | ||
1004 | SND_SOC_DAPM_PGA("ISRC2DEC2", MADERA_ISRC_2_CTRL_3, | ||
1005 | MADERA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0), | ||
1006 | |||
1007 | SND_SOC_DAPM_PGA("ISRC2INT1", MADERA_ISRC_2_CTRL_3, | ||
1008 | MADERA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0), | ||
1009 | SND_SOC_DAPM_PGA("ISRC2INT2", MADERA_ISRC_2_CTRL_3, | ||
1010 | MADERA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0), | ||
1011 | |||
1012 | WM_ADSP2("DSP1", 0, cs47l92_adsp_power_ev), | ||
1013 | |||
1014 | /* end of ordered widget list */ | ||
1015 | |||
1016 | SND_SOC_DAPM_PGA("DFC1", MADERA_DFC1_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), | ||
1017 | SND_SOC_DAPM_PGA("DFC2", MADERA_DFC2_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), | ||
1018 | SND_SOC_DAPM_PGA("DFC3", MADERA_DFC3_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), | ||
1019 | SND_SOC_DAPM_PGA("DFC4", MADERA_DFC4_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), | ||
1020 | SND_SOC_DAPM_PGA("DFC5", MADERA_DFC5_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), | ||
1021 | SND_SOC_DAPM_PGA("DFC6", MADERA_DFC6_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), | ||
1022 | SND_SOC_DAPM_PGA("DFC7", MADERA_DFC7_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), | ||
1023 | SND_SOC_DAPM_PGA("DFC8", MADERA_DFC8_CTRL, MADERA_DFC1_ENA_SHIFT, 0, NULL, 0), | ||
1024 | |||
1025 | MADERA_MIXER_WIDGETS(EQ1, "EQ1"), | ||
1026 | MADERA_MIXER_WIDGETS(EQ2, "EQ2"), | ||
1027 | MADERA_MIXER_WIDGETS(EQ3, "EQ3"), | ||
1028 | MADERA_MIXER_WIDGETS(EQ4, "EQ4"), | ||
1029 | |||
1030 | MADERA_MIXER_WIDGETS(DRC1L, "DRC1L"), | ||
1031 | MADERA_MIXER_WIDGETS(DRC1R, "DRC1R"), | ||
1032 | MADERA_MIXER_WIDGETS(DRC2L, "DRC2L"), | ||
1033 | MADERA_MIXER_WIDGETS(DRC2R, "DRC2R"), | ||
1034 | |||
1035 | SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0, | ||
1036 | &madera_drc_activity_output_mux[0]), | ||
1037 | SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0, | ||
1038 | &madera_drc_activity_output_mux[1]), | ||
1039 | |||
1040 | MADERA_MIXER_WIDGETS(LHPF1, "LHPF1"), | ||
1041 | MADERA_MIXER_WIDGETS(LHPF2, "LHPF2"), | ||
1042 | MADERA_MIXER_WIDGETS(LHPF3, "LHPF3"), | ||
1043 | MADERA_MIXER_WIDGETS(LHPF4, "LHPF4"), | ||
1044 | |||
1045 | MADERA_MIXER_WIDGETS(PWM1, "PWM1"), | ||
1046 | MADERA_MIXER_WIDGETS(PWM2, "PWM2"), | ||
1047 | |||
1048 | MADERA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | ||
1049 | MADERA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | ||
1050 | MADERA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), | ||
1051 | MADERA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), | ||
1052 | MADERA_MIXER_WIDGETS(OUT3L, "HPOUT3L"), | ||
1053 | MADERA_MIXER_WIDGETS(OUT3R, "HPOUT3R"), | ||
1054 | MADERA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | ||
1055 | MADERA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), | ||
1056 | |||
1057 | MADERA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), | ||
1058 | MADERA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), | ||
1059 | MADERA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), | ||
1060 | MADERA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), | ||
1061 | MADERA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), | ||
1062 | MADERA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), | ||
1063 | MADERA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), | ||
1064 | MADERA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), | ||
1065 | |||
1066 | MADERA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | ||
1067 | MADERA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | ||
1068 | MADERA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"), | ||
1069 | MADERA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"), | ||
1070 | MADERA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"), | ||
1071 | MADERA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"), | ||
1072 | MADERA_MIXER_WIDGETS(AIF2TX7, "AIF2TX7"), | ||
1073 | MADERA_MIXER_WIDGETS(AIF2TX8, "AIF2TX8"), | ||
1074 | |||
1075 | MADERA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | ||
1076 | MADERA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | ||
1077 | MADERA_MIXER_WIDGETS(AIF3TX3, "AIF3TX3"), | ||
1078 | MADERA_MIXER_WIDGETS(AIF3TX4, "AIF3TX4"), | ||
1079 | |||
1080 | MADERA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), | ||
1081 | MADERA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), | ||
1082 | MADERA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), | ||
1083 | MADERA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), | ||
1084 | MADERA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), | ||
1085 | MADERA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), | ||
1086 | MADERA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), | ||
1087 | MADERA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), | ||
1088 | |||
1089 | MADERA_MUX_WIDGETS(SPD1TX1, "SPDIFTX1"), | ||
1090 | MADERA_MUX_WIDGETS(SPD1TX2, "SPDIFTX2"), | ||
1091 | |||
1092 | MADERA_MUX_WIDGETS(ASRC1IN1L, "ASRC1IN1L"), | ||
1093 | MADERA_MUX_WIDGETS(ASRC1IN1R, "ASRC1IN1R"), | ||
1094 | MADERA_MUX_WIDGETS(ASRC1IN2L, "ASRC1IN2L"), | ||
1095 | MADERA_MUX_WIDGETS(ASRC1IN2R, "ASRC1IN2R"), | ||
1096 | |||
1097 | MADERA_DSP_WIDGETS(DSP1, "DSP1"), | ||
1098 | |||
1099 | MADERA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), | ||
1100 | MADERA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), | ||
1101 | |||
1102 | MADERA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), | ||
1103 | MADERA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), | ||
1104 | |||
1105 | MADERA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), | ||
1106 | MADERA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), | ||
1107 | |||
1108 | MADERA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), | ||
1109 | MADERA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), | ||
1110 | |||
1111 | MADERA_MUX_WIDGETS(DFC1, "DFC1"), | ||
1112 | MADERA_MUX_WIDGETS(DFC2, "DFC2"), | ||
1113 | MADERA_MUX_WIDGETS(DFC3, "DFC3"), | ||
1114 | MADERA_MUX_WIDGETS(DFC4, "DFC4"), | ||
1115 | MADERA_MUX_WIDGETS(DFC5, "DFC5"), | ||
1116 | MADERA_MUX_WIDGETS(DFC6, "DFC6"), | ||
1117 | MADERA_MUX_WIDGETS(DFC7, "DFC7"), | ||
1118 | MADERA_MUX_WIDGETS(DFC8, "DFC8"), | ||
1119 | |||
1120 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | ||
1121 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | ||
1122 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), | ||
1123 | SND_SOC_DAPM_OUTPUT("HPOUT2R"), | ||
1124 | SND_SOC_DAPM_OUTPUT("HPOUT3L"), | ||
1125 | SND_SOC_DAPM_OUTPUT("HPOUT3R"), | ||
1126 | SND_SOC_DAPM_OUTPUT("HPOUT4L"), | ||
1127 | SND_SOC_DAPM_OUTPUT("HPOUT4R"), | ||
1128 | SND_SOC_DAPM_OUTPUT("SPKDAT1L"), | ||
1129 | SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | ||
1130 | SND_SOC_DAPM_OUTPUT("SPDIF1"), | ||
1131 | |||
1132 | SND_SOC_DAPM_OUTPUT("MICSUPP"), | ||
1133 | }; | ||
1134 | |||
1135 | #define MADERA_MIXER_INPUT_ROUTES(name) \ | ||
1136 | { name, "Noise Generator", "Noise Generator" }, \ | ||
1137 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | ||
1138 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | ||
1139 | { name, "Haptics", "HAPTICS" }, \ | ||
1140 | { name, "AEC1", "AEC1 Loopback" }, \ | ||
1141 | { name, "IN1L", "IN1L" }, \ | ||
1142 | { name, "IN1R", "IN1R" }, \ | ||
1143 | { name, "IN2L", "IN2L" }, \ | ||
1144 | { name, "IN2R", "IN2R" }, \ | ||
1145 | { name, "IN3L", "IN3L" }, \ | ||
1146 | { name, "IN3R", "IN3R" }, \ | ||
1147 | { name, "IN4L", "IN4L" }, \ | ||
1148 | { name, "IN4R", "IN4R" }, \ | ||
1149 | { name, "AIF1RX1", "AIF1RX1" }, \ | ||
1150 | { name, "AIF1RX2", "AIF1RX2" }, \ | ||
1151 | { name, "AIF1RX3", "AIF1RX3" }, \ | ||
1152 | { name, "AIF1RX4", "AIF1RX4" }, \ | ||
1153 | { name, "AIF1RX5", "AIF1RX5" }, \ | ||
1154 | { name, "AIF1RX6", "AIF1RX6" }, \ | ||
1155 | { name, "AIF1RX7", "AIF1RX7" }, \ | ||
1156 | { name, "AIF1RX8", "AIF1RX8" }, \ | ||
1157 | { name, "AIF2RX1", "AIF2RX1" }, \ | ||
1158 | { name, "AIF2RX2", "AIF2RX2" }, \ | ||
1159 | { name, "AIF2RX3", "AIF2RX3" }, \ | ||
1160 | { name, "AIF2RX4", "AIF2RX4" }, \ | ||
1161 | { name, "AIF2RX5", "AIF2RX5" }, \ | ||
1162 | { name, "AIF2RX6", "AIF2RX6" }, \ | ||
1163 | { name, "AIF2RX7", "AIF2RX7" }, \ | ||
1164 | { name, "AIF2RX8", "AIF2RX8" }, \ | ||
1165 | { name, "AIF3RX1", "AIF3RX1" }, \ | ||
1166 | { name, "AIF3RX2", "AIF3RX2" }, \ | ||
1167 | { name, "AIF3RX3", "AIF3RX3" }, \ | ||
1168 | { name, "AIF3RX4", "AIF3RX4" }, \ | ||
1169 | { name, "SLIMRX1", "SLIMRX1" }, \ | ||
1170 | { name, "SLIMRX2", "SLIMRX2" }, \ | ||
1171 | { name, "SLIMRX3", "SLIMRX3" }, \ | ||
1172 | { name, "SLIMRX4", "SLIMRX4" }, \ | ||
1173 | { name, "SLIMRX5", "SLIMRX5" }, \ | ||
1174 | { name, "SLIMRX6", "SLIMRX6" }, \ | ||
1175 | { name, "SLIMRX7", "SLIMRX7" }, \ | ||
1176 | { name, "SLIMRX8", "SLIMRX8" }, \ | ||
1177 | { name, "EQ1", "EQ1" }, \ | ||
1178 | { name, "EQ2", "EQ2" }, \ | ||
1179 | { name, "EQ3", "EQ3" }, \ | ||
1180 | { name, "EQ4", "EQ4" }, \ | ||
1181 | { name, "DRC1L", "DRC1L" }, \ | ||
1182 | { name, "DRC1R", "DRC1R" }, \ | ||
1183 | { name, "DRC2L", "DRC2L" }, \ | ||
1184 | { name, "DRC2R", "DRC2R" }, \ | ||
1185 | { name, "LHPF1", "LHPF1" }, \ | ||
1186 | { name, "LHPF2", "LHPF2" }, \ | ||
1187 | { name, "LHPF3", "LHPF3" }, \ | ||
1188 | { name, "LHPF4", "LHPF4" }, \ | ||
1189 | { name, "ASRC1IN1L", "ASRC1IN1L" }, \ | ||
1190 | { name, "ASRC1IN1R", "ASRC1IN1R" }, \ | ||
1191 | { name, "ASRC1IN2L", "ASRC1IN2L" }, \ | ||
1192 | { name, "ASRC1IN2R", "ASRC1IN2R" }, \ | ||
1193 | { name, "ISRC1DEC1", "ISRC1DEC1" }, \ | ||
1194 | { name, "ISRC1DEC2", "ISRC1DEC2" }, \ | ||
1195 | { name, "ISRC1INT1", "ISRC1INT1" }, \ | ||
1196 | { name, "ISRC1INT2", "ISRC1INT2" }, \ | ||
1197 | { name, "ISRC2DEC1", "ISRC2DEC1" }, \ | ||
1198 | { name, "ISRC2DEC2", "ISRC2DEC2" }, \ | ||
1199 | { name, "ISRC2INT1", "ISRC2INT1" }, \ | ||
1200 | { name, "ISRC2INT2", "ISRC2INT2" }, \ | ||
1201 | { name, "DSP1.1", "DSP1" }, \ | ||
1202 | { name, "DSP1.2", "DSP1" }, \ | ||
1203 | { name, "DSP1.3", "DSP1" }, \ | ||
1204 | { name, "DSP1.4", "DSP1" }, \ | ||
1205 | { name, "DSP1.5", "DSP1" }, \ | ||
1206 | { name, "DSP1.6", "DSP1" }, \ | ||
1207 | { name, "DFC1", "DFC1" }, \ | ||
1208 | { name, "DFC2", "DFC2" }, \ | ||
1209 | { name, "DFC3", "DFC3" }, \ | ||
1210 | { name, "DFC4", "DFC4" }, \ | ||
1211 | { name, "DFC5", "DFC5" }, \ | ||
1212 | { name, "DFC6", "DFC6" }, \ | ||
1213 | { name, "DFC7", "DFC7" }, \ | ||
1214 | { name, "DFC8", "DFC8" } | ||
1215 | |||
1216 | static const struct snd_soc_dapm_route cs47l92_dapm_routes[] = { | ||
1217 | /* Internal clock domains */ | ||
1218 | { "EQ1", NULL, "FXCLK" }, | ||
1219 | { "EQ2", NULL, "FXCLK" }, | ||
1220 | { "EQ3", NULL, "FXCLK" }, | ||
1221 | { "EQ4", NULL, "FXCLK" }, | ||
1222 | { "DRC1L", NULL, "FXCLK" }, | ||
1223 | { "DRC1R", NULL, "FXCLK" }, | ||
1224 | { "DRC2L", NULL, "FXCLK" }, | ||
1225 | { "DRC2R", NULL, "FXCLK" }, | ||
1226 | { "LHPF1", NULL, "FXCLK" }, | ||
1227 | { "LHPF2", NULL, "FXCLK" }, | ||
1228 | { "LHPF3", NULL, "FXCLK" }, | ||
1229 | { "LHPF4", NULL, "FXCLK" }, | ||
1230 | { "PWM1 Mixer", NULL, "PWMCLK" }, | ||
1231 | { "PWM2 Mixer", NULL, "PWMCLK" }, | ||
1232 | { "OUT1L", NULL, "OUTCLK" }, | ||
1233 | { "OUT1R", NULL, "OUTCLK" }, | ||
1234 | { "OUT2L", NULL, "OUTCLK" }, | ||
1235 | { "OUT2R", NULL, "OUTCLK" }, | ||
1236 | { "OUT3L", NULL, "OUTCLK" }, | ||
1237 | { "OUT3R", NULL, "OUTCLK" }, | ||
1238 | { "OUT5L", NULL, "OUTCLK" }, | ||
1239 | { "OUT5R", NULL, "OUTCLK" }, | ||
1240 | { "AIF1TX1", NULL, "AIF1TXCLK" }, | ||
1241 | { "AIF1TX2", NULL, "AIF1TXCLK" }, | ||
1242 | { "AIF1TX3", NULL, "AIF1TXCLK" }, | ||
1243 | { "AIF1TX4", NULL, "AIF1TXCLK" }, | ||
1244 | { "AIF1TX5", NULL, "AIF1TXCLK" }, | ||
1245 | { "AIF1TX6", NULL, "AIF1TXCLK" }, | ||
1246 | { "AIF1TX7", NULL, "AIF1TXCLK" }, | ||
1247 | { "AIF1TX8", NULL, "AIF1TXCLK" }, | ||
1248 | { "AIF2TX1", NULL, "AIF2TXCLK" }, | ||
1249 | { "AIF2TX2", NULL, "AIF2TXCLK" }, | ||
1250 | { "AIF2TX3", NULL, "AIF2TXCLK" }, | ||
1251 | { "AIF2TX4", NULL, "AIF2TXCLK" }, | ||
1252 | { "AIF2TX5", NULL, "AIF2TXCLK" }, | ||
1253 | { "AIF2TX6", NULL, "AIF2TXCLK" }, | ||
1254 | { "AIF2TX7", NULL, "AIF2TXCLK" }, | ||
1255 | { "AIF2TX8", NULL, "AIF2TXCLK" }, | ||
1256 | { "AIF3TX1", NULL, "AIF3TXCLK" }, | ||
1257 | { "AIF3TX2", NULL, "AIF3TXCLK" }, | ||
1258 | { "AIF3TX3", NULL, "AIF3TXCLK" }, | ||
1259 | { "AIF3TX4", NULL, "AIF3TXCLK" }, | ||
1260 | { "SLIMTX1", NULL, "SLIMBUSCLK" }, | ||
1261 | { "SLIMTX2", NULL, "SLIMBUSCLK" }, | ||
1262 | { "SLIMTX3", NULL, "SLIMBUSCLK" }, | ||
1263 | { "SLIMTX4", NULL, "SLIMBUSCLK" }, | ||
1264 | { "SLIMTX5", NULL, "SLIMBUSCLK" }, | ||
1265 | { "SLIMTX6", NULL, "SLIMBUSCLK" }, | ||
1266 | { "SLIMTX7", NULL, "SLIMBUSCLK" }, | ||
1267 | { "SLIMTX8", NULL, "SLIMBUSCLK" }, | ||
1268 | { "SPD1TX1", NULL, "SPDCLK" }, | ||
1269 | { "SPD1TX2", NULL, "SPDCLK" }, | ||
1270 | { "DSP1", NULL, "DSP1CLK" }, | ||
1271 | { "ISRC1DEC1", NULL, "ISRC1CLK" }, | ||
1272 | { "ISRC1DEC2", NULL, "ISRC1CLK" }, | ||
1273 | { "ISRC1INT1", NULL, "ISRC1CLK" }, | ||
1274 | { "ISRC1INT2", NULL, "ISRC1CLK" }, | ||
1275 | { "ISRC2DEC1", NULL, "ISRC2CLK" }, | ||
1276 | { "ISRC2DEC2", NULL, "ISRC2CLK" }, | ||
1277 | { "ISRC2INT1", NULL, "ISRC2CLK" }, | ||
1278 | { "ISRC2INT2", NULL, "ISRC2CLK" }, | ||
1279 | { "ASRC1IN1L", NULL, "ASRC1CLK" }, | ||
1280 | { "ASRC1IN1R", NULL, "ASRC1CLK" }, | ||
1281 | { "ASRC1IN2L", NULL, "ASRC1CLK" }, | ||
1282 | { "ASRC1IN2R", NULL, "ASRC1CLK" }, | ||
1283 | { "DFC1", NULL, "DFCCLK" }, | ||
1284 | { "DFC2", NULL, "DFCCLK" }, | ||
1285 | { "DFC3", NULL, "DFCCLK" }, | ||
1286 | { "DFC4", NULL, "DFCCLK" }, | ||
1287 | { "DFC5", NULL, "DFCCLK" }, | ||
1288 | { "DFC6", NULL, "DFCCLK" }, | ||
1289 | { "DFC7", NULL, "DFCCLK" }, | ||
1290 | { "DFC8", NULL, "DFCCLK" }, | ||
1291 | |||
1292 | { "OUT1L", NULL, "CPVDD1" }, | ||
1293 | { "OUT1L", NULL, "CPVDD2" }, | ||
1294 | { "OUT1R", NULL, "CPVDD1" }, | ||
1295 | { "OUT1R", NULL, "CPVDD2" }, | ||
1296 | { "OUT2L", NULL, "CPVDD1" }, | ||
1297 | { "OUT2L", NULL, "CPVDD2" }, | ||
1298 | { "OUT2R", NULL, "CPVDD1" }, | ||
1299 | { "OUT2R", NULL, "CPVDD2" }, | ||
1300 | { "OUT3L", NULL, "CPVDD1" }, | ||
1301 | { "OUT3L", NULL, "CPVDD2" }, | ||
1302 | { "OUT3R", NULL, "CPVDD1" }, | ||
1303 | { "OUT3R", NULL, "CPVDD2" }, | ||
1304 | |||
1305 | { "OUT1L", NULL, "SYSCLK" }, | ||
1306 | { "OUT1R", NULL, "SYSCLK" }, | ||
1307 | { "OUT2L", NULL, "SYSCLK" }, | ||
1308 | { "OUT2R", NULL, "SYSCLK" }, | ||
1309 | { "OUT3L", NULL, "SYSCLK" }, | ||
1310 | { "OUT3R", NULL, "SYSCLK" }, | ||
1311 | { "OUT5L", NULL, "SYSCLK" }, | ||
1312 | { "OUT5R", NULL, "SYSCLK" }, | ||
1313 | |||
1314 | { "SPD1", NULL, "SYSCLK" }, | ||
1315 | { "SPD1", NULL, "SPD1TX1" }, | ||
1316 | { "SPD1", NULL, "SPD1TX2" }, | ||
1317 | |||
1318 | { "IN1L", NULL, "SYSCLK" }, | ||
1319 | { "IN1R", NULL, "SYSCLK" }, | ||
1320 | { "IN2L", NULL, "SYSCLK" }, | ||
1321 | { "IN2R", NULL, "SYSCLK" }, | ||
1322 | { "IN3L", NULL, "SYSCLK" }, | ||
1323 | { "IN3R", NULL, "SYSCLK" }, | ||
1324 | { "IN4L", NULL, "SYSCLK" }, | ||
1325 | { "IN4R", NULL, "SYSCLK" }, | ||
1326 | |||
1327 | { "ASRC1IN1L", NULL, "SYSCLK" }, | ||
1328 | { "ASRC1IN1R", NULL, "SYSCLK" }, | ||
1329 | { "ASRC1IN2L", NULL, "SYSCLK" }, | ||
1330 | { "ASRC1IN2R", NULL, "SYSCLK" }, | ||
1331 | |||
1332 | { "ASRC1IN1L", NULL, "ASYNCCLK" }, | ||
1333 | { "ASRC1IN1R", NULL, "ASYNCCLK" }, | ||
1334 | { "ASRC1IN2L", NULL, "ASYNCCLK" }, | ||
1335 | { "ASRC1IN2R", NULL, "ASYNCCLK" }, | ||
1336 | |||
1337 | { "MICBIAS1", NULL, "MICVDD" }, | ||
1338 | { "MICBIAS2", NULL, "MICVDD" }, | ||
1339 | |||
1340 | { "MICBIAS1A", NULL, "MICBIAS1" }, | ||
1341 | { "MICBIAS1B", NULL, "MICBIAS1" }, | ||
1342 | { "MICBIAS1C", NULL, "MICBIAS1" }, | ||
1343 | { "MICBIAS1D", NULL, "MICBIAS1" }, | ||
1344 | |||
1345 | { "MICBIAS2A", NULL, "MICBIAS2" }, | ||
1346 | { "MICBIAS2B", NULL, "MICBIAS2" }, | ||
1347 | |||
1348 | { "Noise Generator", NULL, "SYSCLK" }, | ||
1349 | { "Tone Generator 1", NULL, "SYSCLK" }, | ||
1350 | { "Tone Generator 2", NULL, "SYSCLK" }, | ||
1351 | |||
1352 | { "Noise Generator", NULL, "NOISE" }, | ||
1353 | { "Tone Generator 1", NULL, "TONE" }, | ||
1354 | { "Tone Generator 2", NULL, "TONE" }, | ||
1355 | |||
1356 | { "AIF1 Capture", NULL, "AIF1TX1" }, | ||
1357 | { "AIF1 Capture", NULL, "AIF1TX2" }, | ||
1358 | { "AIF1 Capture", NULL, "AIF1TX3" }, | ||
1359 | { "AIF1 Capture", NULL, "AIF1TX4" }, | ||
1360 | { "AIF1 Capture", NULL, "AIF1TX5" }, | ||
1361 | { "AIF1 Capture", NULL, "AIF1TX6" }, | ||
1362 | { "AIF1 Capture", NULL, "AIF1TX7" }, | ||
1363 | { "AIF1 Capture", NULL, "AIF1TX8" }, | ||
1364 | |||
1365 | { "AIF1RX1", NULL, "AIF1 Playback" }, | ||
1366 | { "AIF1RX2", NULL, "AIF1 Playback" }, | ||
1367 | { "AIF1RX3", NULL, "AIF1 Playback" }, | ||
1368 | { "AIF1RX4", NULL, "AIF1 Playback" }, | ||
1369 | { "AIF1RX5", NULL, "AIF1 Playback" }, | ||
1370 | { "AIF1RX6", NULL, "AIF1 Playback" }, | ||
1371 | { "AIF1RX7", NULL, "AIF1 Playback" }, | ||
1372 | { "AIF1RX8", NULL, "AIF1 Playback" }, | ||
1373 | |||
1374 | { "AIF2 Capture", NULL, "AIF2TX1" }, | ||
1375 | { "AIF2 Capture", NULL, "AIF2TX2" }, | ||
1376 | { "AIF2 Capture", NULL, "AIF2TX3" }, | ||
1377 | { "AIF2 Capture", NULL, "AIF2TX4" }, | ||
1378 | { "AIF2 Capture", NULL, "AIF2TX5" }, | ||
1379 | { "AIF2 Capture", NULL, "AIF2TX6" }, | ||
1380 | { "AIF2 Capture", NULL, "AIF2TX7" }, | ||
1381 | { "AIF2 Capture", NULL, "AIF2TX8" }, | ||
1382 | |||
1383 | { "AIF2RX1", NULL, "AIF2 Playback" }, | ||
1384 | { "AIF2RX2", NULL, "AIF2 Playback" }, | ||
1385 | { "AIF2RX3", NULL, "AIF2 Playback" }, | ||
1386 | { "AIF2RX4", NULL, "AIF2 Playback" }, | ||
1387 | { "AIF2RX5", NULL, "AIF2 Playback" }, | ||
1388 | { "AIF2RX6", NULL, "AIF2 Playback" }, | ||
1389 | { "AIF2RX7", NULL, "AIF2 Playback" }, | ||
1390 | { "AIF2RX8", NULL, "AIF2 Playback" }, | ||
1391 | |||
1392 | { "AIF3 Capture", NULL, "AIF3TX1" }, | ||
1393 | { "AIF3 Capture", NULL, "AIF3TX2" }, | ||
1394 | { "AIF3 Capture", NULL, "AIF3TX3" }, | ||
1395 | { "AIF3 Capture", NULL, "AIF3TX4" }, | ||
1396 | |||
1397 | { "AIF3RX1", NULL, "AIF3 Playback" }, | ||
1398 | { "AIF3RX2", NULL, "AIF3 Playback" }, | ||
1399 | { "AIF3RX3", NULL, "AIF3 Playback" }, | ||
1400 | { "AIF3RX4", NULL, "AIF3 Playback" }, | ||
1401 | |||
1402 | { "Slim1 Capture", NULL, "SLIMTX1" }, | ||
1403 | { "Slim1 Capture", NULL, "SLIMTX2" }, | ||
1404 | { "Slim1 Capture", NULL, "SLIMTX3" }, | ||
1405 | { "Slim1 Capture", NULL, "SLIMTX4" }, | ||
1406 | |||
1407 | { "SLIMRX1", NULL, "Slim1 Playback" }, | ||
1408 | { "SLIMRX2", NULL, "Slim1 Playback" }, | ||
1409 | { "SLIMRX3", NULL, "Slim1 Playback" }, | ||
1410 | { "SLIMRX4", NULL, "Slim1 Playback" }, | ||
1411 | |||
1412 | { "Slim2 Capture", NULL, "SLIMTX5" }, | ||
1413 | { "Slim2 Capture", NULL, "SLIMTX6" }, | ||
1414 | |||
1415 | { "SLIMRX5", NULL, "Slim2 Playback" }, | ||
1416 | { "SLIMRX6", NULL, "Slim2 Playback" }, | ||
1417 | |||
1418 | { "Slim3 Capture", NULL, "SLIMTX7" }, | ||
1419 | { "Slim3 Capture", NULL, "SLIMTX8" }, | ||
1420 | |||
1421 | { "SLIMRX7", NULL, "Slim3 Playback" }, | ||
1422 | { "SLIMRX8", NULL, "Slim3 Playback" }, | ||
1423 | |||
1424 | { "AIF1 Playback", NULL, "SYSCLK" }, | ||
1425 | { "AIF2 Playback", NULL, "SYSCLK" }, | ||
1426 | { "AIF3 Playback", NULL, "SYSCLK" }, | ||
1427 | { "Slim1 Playback", NULL, "SYSCLK" }, | ||
1428 | { "Slim2 Playback", NULL, "SYSCLK" }, | ||
1429 | { "Slim3 Playback", NULL, "SYSCLK" }, | ||
1430 | |||
1431 | { "AIF1 Capture", NULL, "SYSCLK" }, | ||
1432 | { "AIF2 Capture", NULL, "SYSCLK" }, | ||
1433 | { "AIF3 Capture", NULL, "SYSCLK" }, | ||
1434 | { "Slim1 Capture", NULL, "SYSCLK" }, | ||
1435 | { "Slim2 Capture", NULL, "SYSCLK" }, | ||
1436 | { "Slim3 Capture", NULL, "SYSCLK" }, | ||
1437 | |||
1438 | { "Audio Trace DSP", NULL, "DSP1" }, | ||
1439 | |||
1440 | { "IN1L Analog Mux", "A", "IN1ALN" }, | ||
1441 | { "IN1L Analog Mux", "A", "IN1ALP" }, | ||
1442 | { "IN1L Analog Mux", "B", "IN1BLN" }, | ||
1443 | { "IN1L Analog Mux", "B", "IN1BLP" }, | ||
1444 | { "IN1R Analog Mux", "A", "IN1ARN" }, | ||
1445 | { "IN1R Analog Mux", "A", "IN1ARP" }, | ||
1446 | { "IN1R Analog Mux", "B", "IN1BR" }, | ||
1447 | { "IN1R Analog Mux", "B", "IN1ALN" }, | ||
1448 | |||
1449 | { "IN1L Mode", "Analog", "IN1L Analog Mux" }, | ||
1450 | { "IN1R Mode", "Analog", "IN1R Analog Mux" }, | ||
1451 | |||
1452 | { "IN1L Mode", "Digital", "IN1ALN" }, | ||
1453 | { "IN1L Mode", "Digital", "IN1ALP" }, | ||
1454 | { "IN1R Mode", "Digital", "IN1ALN" }, | ||
1455 | { "IN1R Mode", "Digital", "IN1ALP" }, | ||
1456 | |||
1457 | { "IN1L", NULL, "IN1L Mode" }, | ||
1458 | { "IN1R", NULL, "IN1R Mode" }, | ||
1459 | |||
1460 | { "IN2L Analog Mux", "A", "IN2ALN" }, | ||
1461 | { "IN2L Analog Mux", "A", "IN2ALP" }, | ||
1462 | { "IN2L Analog Mux", "B", "IN2ALN" }, | ||
1463 | { "IN2L Analog Mux", "B", "IN2BL" }, | ||
1464 | { "IN2R Analog Mux", "A", "IN2ARN" }, | ||
1465 | { "IN2R Analog Mux", "A", "IN2ARP" }, | ||
1466 | { "IN2R Analog Mux", "B", "IN2ARN" }, | ||
1467 | { "IN2R Analog Mux", "B", "IN2BR" }, | ||
1468 | |||
1469 | { "IN2L Mode", "Analog", "IN2L Analog Mux" }, | ||
1470 | { "IN2R Mode", "Analog", "IN2R Analog Mux" }, | ||
1471 | |||
1472 | { "IN2L Mode", "Digital", "IN2ALN" }, | ||
1473 | { "IN2L Mode", "Digital", "IN2ALP" }, | ||
1474 | { "IN2R Mode", "Digital", "IN2ALN" }, | ||
1475 | { "IN2R Mode", "Digital", "IN2ALP" }, | ||
1476 | |||
1477 | { "IN2L", NULL, "IN2L Mode" }, | ||
1478 | { "IN2R", NULL, "IN2R Mode" }, | ||
1479 | |||
1480 | { "IN3L", NULL, "IN1ARN" }, | ||
1481 | { "IN3L", NULL, "IN1ARP" }, | ||
1482 | { "IN3R", NULL, "IN1ARN" }, | ||
1483 | { "IN3R", NULL, "IN1ARP" }, | ||
1484 | |||
1485 | { "IN4L", NULL, "IN2ARN" }, | ||
1486 | { "IN4L", NULL, "IN2ARP" }, | ||
1487 | { "IN4R", NULL, "IN2ARN" }, | ||
1488 | { "IN4R", NULL, "IN2ARP" }, | ||
1489 | |||
1490 | MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | ||
1491 | MADERA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | ||
1492 | MADERA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | ||
1493 | MADERA_MIXER_ROUTES("OUT2R", "HPOUT2R"), | ||
1494 | MADERA_MIXER_ROUTES("OUT3L", "HPOUT3L"), | ||
1495 | MADERA_MIXER_ROUTES("OUT3R", "HPOUT3R"), | ||
1496 | |||
1497 | MADERA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), | ||
1498 | MADERA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), | ||
1499 | |||
1500 | MADERA_MIXER_ROUTES("PWM1 Driver", "PWM1"), | ||
1501 | MADERA_MIXER_ROUTES("PWM2 Driver", "PWM2"), | ||
1502 | |||
1503 | MADERA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), | ||
1504 | MADERA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), | ||
1505 | MADERA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), | ||
1506 | MADERA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), | ||
1507 | MADERA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), | ||
1508 | MADERA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), | ||
1509 | MADERA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), | ||
1510 | MADERA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), | ||
1511 | |||
1512 | MADERA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | ||
1513 | MADERA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | ||
1514 | MADERA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"), | ||
1515 | MADERA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"), | ||
1516 | MADERA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"), | ||
1517 | MADERA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"), | ||
1518 | MADERA_MIXER_ROUTES("AIF2TX7", "AIF2TX7"), | ||
1519 | MADERA_MIXER_ROUTES("AIF2TX8", "AIF2TX8"), | ||
1520 | |||
1521 | MADERA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | ||
1522 | MADERA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | ||
1523 | MADERA_MIXER_ROUTES("AIF3TX3", "AIF3TX3"), | ||
1524 | MADERA_MIXER_ROUTES("AIF3TX4", "AIF3TX4"), | ||
1525 | |||
1526 | MADERA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"), | ||
1527 | MADERA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"), | ||
1528 | MADERA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"), | ||
1529 | MADERA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"), | ||
1530 | MADERA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"), | ||
1531 | MADERA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"), | ||
1532 | MADERA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"), | ||
1533 | MADERA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"), | ||
1534 | |||
1535 | MADERA_MUX_ROUTES("SPD1TX1", "SPDIFTX1"), | ||
1536 | MADERA_MUX_ROUTES("SPD1TX2", "SPDIFTX2"), | ||
1537 | |||
1538 | MADERA_MIXER_ROUTES("EQ1", "EQ1"), | ||
1539 | MADERA_MIXER_ROUTES("EQ2", "EQ2"), | ||
1540 | MADERA_MIXER_ROUTES("EQ3", "EQ3"), | ||
1541 | MADERA_MIXER_ROUTES("EQ4", "EQ4"), | ||
1542 | |||
1543 | MADERA_MIXER_ROUTES("DRC1L", "DRC1L"), | ||
1544 | MADERA_MIXER_ROUTES("DRC1R", "DRC1R"), | ||
1545 | MADERA_MIXER_ROUTES("DRC2L", "DRC2L"), | ||
1546 | MADERA_MIXER_ROUTES("DRC2R", "DRC2R"), | ||
1547 | |||
1548 | MADERA_MIXER_ROUTES("LHPF1", "LHPF1"), | ||
1549 | MADERA_MIXER_ROUTES("LHPF2", "LHPF2"), | ||
1550 | MADERA_MIXER_ROUTES("LHPF3", "LHPF3"), | ||
1551 | MADERA_MIXER_ROUTES("LHPF4", "LHPF4"), | ||
1552 | |||
1553 | MADERA_MUX_ROUTES("ASRC1IN1L", "ASRC1IN1L"), | ||
1554 | MADERA_MUX_ROUTES("ASRC1IN1R", "ASRC1IN1R"), | ||
1555 | MADERA_MUX_ROUTES("ASRC1IN2L", "ASRC1IN2L"), | ||
1556 | MADERA_MUX_ROUTES("ASRC1IN2R", "ASRC1IN2R"), | ||
1557 | |||
1558 | MADERA_DSP_ROUTES("DSP1"), | ||
1559 | |||
1560 | MADERA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), | ||
1561 | MADERA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), | ||
1562 | |||
1563 | MADERA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), | ||
1564 | MADERA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), | ||
1565 | |||
1566 | MADERA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), | ||
1567 | MADERA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), | ||
1568 | |||
1569 | MADERA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), | ||
1570 | MADERA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), | ||
1571 | |||
1572 | { "AEC1 Loopback", "HPOUT1L", "OUT1L" }, | ||
1573 | { "AEC1 Loopback", "HPOUT1R", "OUT1R" }, | ||
1574 | { "HPOUT1L", NULL, "OUT1L" }, | ||
1575 | { "HPOUT1R", NULL, "OUT1R" }, | ||
1576 | |||
1577 | { "AEC1 Loopback", "HPOUT2L", "OUT2L" }, | ||
1578 | { "AEC1 Loopback", "HPOUT2R", "OUT2R" }, | ||
1579 | { "HPOUT2L", NULL, "OUT2L" }, | ||
1580 | { "HPOUT2R", NULL, "OUT2R" }, | ||
1581 | |||
1582 | { "AEC1 Loopback", "HPOUT3L", "OUT3L" }, | ||
1583 | { "AEC1 Loopback", "HPOUT3R", "OUT3R" }, | ||
1584 | { "OUT3 Demux", NULL, "OUT3L" }, | ||
1585 | { "OUT3 Demux", NULL, "OUT3R" }, | ||
1586 | |||
1587 | { "HPOUT3L", "HPOUT3", "OUT3 Demux" }, | ||
1588 | { "HPOUT3R", "HPOUT3", "OUT3 Demux" }, | ||
1589 | { "HPOUT4L", "HPOUT4", "OUT3 Demux" }, | ||
1590 | { "HPOUT4R", "HPOUT4", "OUT3 Demux" }, | ||
1591 | |||
1592 | { "AEC1 Loopback", "SPKDAT1L", "OUT5L" }, | ||
1593 | { "AEC1 Loopback", "SPKDAT1R", "OUT5R" }, | ||
1594 | { "SPKDAT1L", NULL, "OUT5L" }, | ||
1595 | { "SPKDAT1R", NULL, "OUT5R" }, | ||
1596 | |||
1597 | { "SPDIF1", NULL, "SPD1" }, | ||
1598 | |||
1599 | { "MICSUPP", NULL, "SYSCLK" }, | ||
1600 | |||
1601 | { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" }, | ||
1602 | { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" }, | ||
1603 | { "DRC1 Activity Output", "Switch", "DRC1L" }, | ||
1604 | { "DRC1 Activity Output", "Switch", "DRC1R" }, | ||
1605 | { "DRC2 Activity Output", "Switch", "DRC2L" }, | ||
1606 | { "DRC2 Activity Output", "Switch", "DRC2R" }, | ||
1607 | |||
1608 | MADERA_MUX_ROUTES("DFC1", "DFC1"), | ||
1609 | MADERA_MUX_ROUTES("DFC2", "DFC2"), | ||
1610 | MADERA_MUX_ROUTES("DFC3", "DFC3"), | ||
1611 | MADERA_MUX_ROUTES("DFC4", "DFC4"), | ||
1612 | MADERA_MUX_ROUTES("DFC5", "DFC5"), | ||
1613 | MADERA_MUX_ROUTES("DFC6", "DFC6"), | ||
1614 | MADERA_MUX_ROUTES("DFC7", "DFC7"), | ||
1615 | MADERA_MUX_ROUTES("DFC8", "DFC8"), | ||
1616 | }; | ||
1617 | |||
1618 | static int cs47l92_set_fll(struct snd_soc_component *component, int fll_id, | ||
1619 | int source, unsigned int fref, unsigned int fout) | ||
1620 | { | ||
1621 | struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); | ||
1622 | |||
1623 | switch (fll_id) { | ||
1624 | case MADERA_FLL1_REFCLK: | ||
1625 | return madera_fllhj_set_refclk(&cs47l92->fll[0], source, fref, | ||
1626 | fout); | ||
1627 | case MADERA_FLL2_REFCLK: | ||
1628 | return madera_fllhj_set_refclk(&cs47l92->fll[1], source, fref, | ||
1629 | fout); | ||
1630 | default: | ||
1631 | return -EINVAL; | ||
1632 | } | ||
1633 | } | ||
1634 | |||
1635 | static struct snd_soc_dai_driver cs47l92_dai[] = { | ||
1636 | { | ||
1637 | .name = "cs47l92-aif1", | ||
1638 | .id = 1, | ||
1639 | .base = MADERA_AIF1_BCLK_CTRL, | ||
1640 | .playback = { | ||
1641 | .stream_name = "AIF1 Playback", | ||
1642 | .channels_min = 1, | ||
1643 | .channels_max = 8, | ||
1644 | .rates = MADERA_RATES, | ||
1645 | .formats = MADERA_FORMATS, | ||
1646 | }, | ||
1647 | .capture = { | ||
1648 | .stream_name = "AIF1 Capture", | ||
1649 | .channels_min = 1, | ||
1650 | .channels_max = 8, | ||
1651 | .rates = MADERA_RATES, | ||
1652 | .formats = MADERA_FORMATS, | ||
1653 | }, | ||
1654 | .ops = &madera_dai_ops, | ||
1655 | .symmetric_rates = 1, | ||
1656 | .symmetric_samplebits = 1, | ||
1657 | }, | ||
1658 | { | ||
1659 | .name = "cs47l92-aif2", | ||
1660 | .id = 2, | ||
1661 | .base = MADERA_AIF2_BCLK_CTRL, | ||
1662 | .playback = { | ||
1663 | .stream_name = "AIF2 Playback", | ||
1664 | .channels_min = 1, | ||
1665 | .channels_max = 8, | ||
1666 | .rates = MADERA_RATES, | ||
1667 | .formats = MADERA_FORMATS, | ||
1668 | }, | ||
1669 | .capture = { | ||
1670 | .stream_name = "AIF2 Capture", | ||
1671 | .channels_min = 1, | ||
1672 | .channels_max = 8, | ||
1673 | .rates = MADERA_RATES, | ||
1674 | .formats = MADERA_FORMATS, | ||
1675 | }, | ||
1676 | .ops = &madera_dai_ops, | ||
1677 | .symmetric_rates = 1, | ||
1678 | .symmetric_samplebits = 1, | ||
1679 | }, | ||
1680 | { | ||
1681 | .name = "cs47l92-aif3", | ||
1682 | .id = 3, | ||
1683 | .base = MADERA_AIF3_BCLK_CTRL, | ||
1684 | .playback = { | ||
1685 | .stream_name = "AIF3 Playback", | ||
1686 | .channels_min = 1, | ||
1687 | .channels_max = 4, | ||
1688 | .rates = MADERA_RATES, | ||
1689 | .formats = MADERA_FORMATS, | ||
1690 | }, | ||
1691 | .capture = { | ||
1692 | .stream_name = "AIF3 Capture", | ||
1693 | .channels_min = 1, | ||
1694 | .channels_max = 4, | ||
1695 | .rates = MADERA_RATES, | ||
1696 | .formats = MADERA_FORMATS, | ||
1697 | }, | ||
1698 | .ops = &madera_dai_ops, | ||
1699 | .symmetric_rates = 1, | ||
1700 | .symmetric_samplebits = 1, | ||
1701 | }, | ||
1702 | { | ||
1703 | .name = "cs47l92-slim1", | ||
1704 | .id = 5, | ||
1705 | .playback = { | ||
1706 | .stream_name = "Slim1 Playback", | ||
1707 | .channels_min = 1, | ||
1708 | .channels_max = 4, | ||
1709 | .rates = MADERA_RATES, | ||
1710 | .formats = MADERA_FORMATS, | ||
1711 | }, | ||
1712 | .capture = { | ||
1713 | .stream_name = "Slim1 Capture", | ||
1714 | .channels_min = 1, | ||
1715 | .channels_max = 4, | ||
1716 | .rates = MADERA_RATES, | ||
1717 | .formats = MADERA_FORMATS, | ||
1718 | }, | ||
1719 | .ops = &madera_simple_dai_ops, | ||
1720 | }, | ||
1721 | { | ||
1722 | .name = "cs47l92-slim2", | ||
1723 | .id = 6, | ||
1724 | .playback = { | ||
1725 | .stream_name = "Slim2 Playback", | ||
1726 | .channels_min = 1, | ||
1727 | .channels_max = 2, | ||
1728 | .rates = MADERA_RATES, | ||
1729 | .formats = MADERA_FORMATS, | ||
1730 | }, | ||
1731 | .capture = { | ||
1732 | .stream_name = "Slim2 Capture", | ||
1733 | .channels_min = 1, | ||
1734 | .channels_max = 2, | ||
1735 | .rates = MADERA_RATES, | ||
1736 | .formats = MADERA_FORMATS, | ||
1737 | }, | ||
1738 | .ops = &madera_simple_dai_ops, | ||
1739 | }, | ||
1740 | { | ||
1741 | .name = "cs47l92-slim3", | ||
1742 | .id = 7, | ||
1743 | .playback = { | ||
1744 | .stream_name = "Slim3 Playback", | ||
1745 | .channels_min = 1, | ||
1746 | .channels_max = 2, | ||
1747 | .rates = MADERA_RATES, | ||
1748 | .formats = MADERA_FORMATS, | ||
1749 | }, | ||
1750 | .capture = { | ||
1751 | .stream_name = "Slim3 Capture", | ||
1752 | .channels_min = 1, | ||
1753 | .channels_max = 2, | ||
1754 | .rates = MADERA_RATES, | ||
1755 | .formats = MADERA_FORMATS, | ||
1756 | }, | ||
1757 | .ops = &madera_simple_dai_ops, | ||
1758 | }, | ||
1759 | { | ||
1760 | .name = "cs47l92-cpu-trace", | ||
1761 | .capture = { | ||
1762 | .stream_name = "Audio Trace CPU", | ||
1763 | .channels_min = 1, | ||
1764 | .channels_max = 2, | ||
1765 | .rates = MADERA_RATES, | ||
1766 | .formats = MADERA_FORMATS, | ||
1767 | }, | ||
1768 | .compress_new = snd_soc_new_compress, | ||
1769 | }, | ||
1770 | { | ||
1771 | .name = "cs47l92-dsp-trace", | ||
1772 | .capture = { | ||
1773 | .stream_name = "Audio Trace DSP", | ||
1774 | .channels_min = 1, | ||
1775 | .channels_max = 2, | ||
1776 | .rates = MADERA_RATES, | ||
1777 | .formats = MADERA_FORMATS, | ||
1778 | }, | ||
1779 | }, | ||
1780 | }; | ||
1781 | |||
1782 | static int cs47l92_open(struct snd_compr_stream *stream) | ||
1783 | { | ||
1784 | struct snd_soc_pcm_runtime *rtd = stream->private_data; | ||
1785 | struct snd_soc_component *component = | ||
1786 | snd_soc_rtdcom_lookup(rtd, DRV_NAME); | ||
1787 | struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); | ||
1788 | struct madera_priv *priv = &cs47l92->core; | ||
1789 | struct madera *madera = priv->madera; | ||
1790 | int n_adsp; | ||
1791 | |||
1792 | if (strcmp(rtd->codec_dai->name, "cs47l92-dsp-trace") == 0) { | ||
1793 | n_adsp = 0; | ||
1794 | } else { | ||
1795 | dev_err(madera->dev, | ||
1796 | "No suitable compressed stream for DAI '%s'\n", | ||
1797 | rtd->codec_dai->name); | ||
1798 | return -EINVAL; | ||
1799 | } | ||
1800 | |||
1801 | return wm_adsp_compr_open(&priv->adsp[n_adsp], stream); | ||
1802 | } | ||
1803 | |||
1804 | static irqreturn_t cs47l92_adsp2_irq(int irq, void *data) | ||
1805 | { | ||
1806 | struct cs47l92 *cs47l92 = data; | ||
1807 | struct madera_priv *priv = &cs47l92->core; | ||
1808 | struct madera *madera = priv->madera; | ||
1809 | int ret; | ||
1810 | |||
1811 | ret = wm_adsp_compr_handle_irq(&priv->adsp[0]); | ||
1812 | if (ret == -ENODEV) { | ||
1813 | dev_err(madera->dev, "Spurious compressed data IRQ\n"); | ||
1814 | return IRQ_NONE; | ||
1815 | } | ||
1816 | |||
1817 | return IRQ_HANDLED; | ||
1818 | } | ||
1819 | |||
1820 | static int cs47l92_component_probe(struct snd_soc_component *component) | ||
1821 | { | ||
1822 | struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); | ||
1823 | struct madera *madera = cs47l92->core.madera; | ||
1824 | int ret; | ||
1825 | |||
1826 | snd_soc_component_init_regmap(component, madera->regmap); | ||
1827 | |||
1828 | mutex_lock(&madera->dapm_ptr_lock); | ||
1829 | madera->dapm = snd_soc_component_get_dapm(component); | ||
1830 | mutex_unlock(&madera->dapm_ptr_lock); | ||
1831 | |||
1832 | ret = madera_init_inputs(component); | ||
1833 | if (ret) | ||
1834 | return ret; | ||
1835 | |||
1836 | ret = madera_init_outputs(component, CS47L92_MONO_OUTPUTS); | ||
1837 | if (ret) | ||
1838 | return ret; | ||
1839 | |||
1840 | snd_soc_component_disable_pin(component, "HAPTICS"); | ||
1841 | |||
1842 | ret = snd_soc_add_component_controls(component, | ||
1843 | madera_adsp_rate_controls, | ||
1844 | CS47L92_NUM_ADSP); | ||
1845 | if (ret) | ||
1846 | return ret; | ||
1847 | |||
1848 | return wm_adsp2_component_probe(&cs47l92->core.adsp[0], component); | ||
1849 | } | ||
1850 | |||
1851 | static void cs47l92_component_remove(struct snd_soc_component *component) | ||
1852 | { | ||
1853 | struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); | ||
1854 | struct madera *madera = cs47l92->core.madera; | ||
1855 | |||
1856 | mutex_lock(&madera->dapm_ptr_lock); | ||
1857 | madera->dapm = NULL; | ||
1858 | mutex_unlock(&madera->dapm_ptr_lock); | ||
1859 | |||
1860 | wm_adsp2_component_remove(&cs47l92->core.adsp[0], component); | ||
1861 | } | ||
1862 | |||
1863 | #define CS47L92_DIG_VU 0x0200 | ||
1864 | |||
1865 | static unsigned int cs47l92_digital_vu[] = { | ||
1866 | MADERA_DAC_DIGITAL_VOLUME_1L, | ||
1867 | MADERA_DAC_DIGITAL_VOLUME_1R, | ||
1868 | MADERA_DAC_DIGITAL_VOLUME_2L, | ||
1869 | MADERA_DAC_DIGITAL_VOLUME_2R, | ||
1870 | MADERA_DAC_DIGITAL_VOLUME_3L, | ||
1871 | MADERA_DAC_DIGITAL_VOLUME_3R, | ||
1872 | MADERA_DAC_DIGITAL_VOLUME_5L, | ||
1873 | MADERA_DAC_DIGITAL_VOLUME_5R, | ||
1874 | }; | ||
1875 | |||
1876 | static const struct snd_compr_ops cs47l92_compr_ops = { | ||
1877 | .open = &cs47l92_open, | ||
1878 | .free = &wm_adsp_compr_free, | ||
1879 | .set_params = &wm_adsp_compr_set_params, | ||
1880 | .get_caps = &wm_adsp_compr_get_caps, | ||
1881 | .trigger = &wm_adsp_compr_trigger, | ||
1882 | .pointer = &wm_adsp_compr_pointer, | ||
1883 | .copy = &wm_adsp_compr_copy, | ||
1884 | }; | ||
1885 | |||
1886 | static const struct snd_soc_component_driver soc_component_dev_cs47l92 = { | ||
1887 | .probe = &cs47l92_component_probe, | ||
1888 | .remove = &cs47l92_component_remove, | ||
1889 | .set_sysclk = &madera_set_sysclk, | ||
1890 | .set_pll = &cs47l92_set_fll, | ||
1891 | .name = DRV_NAME, | ||
1892 | .compr_ops = &cs47l92_compr_ops, | ||
1893 | .controls = cs47l92_snd_controls, | ||
1894 | .num_controls = ARRAY_SIZE(cs47l92_snd_controls), | ||
1895 | .dapm_widgets = cs47l92_dapm_widgets, | ||
1896 | .num_dapm_widgets = ARRAY_SIZE(cs47l92_dapm_widgets), | ||
1897 | .dapm_routes = cs47l92_dapm_routes, | ||
1898 | .num_dapm_routes = ARRAY_SIZE(cs47l92_dapm_routes), | ||
1899 | .use_pmdown_time = 1, | ||
1900 | .endianness = 1, | ||
1901 | .non_legacy_dai_naming = 1, | ||
1902 | }; | ||
1903 | |||
1904 | static int cs47l92_probe(struct platform_device *pdev) | ||
1905 | { | ||
1906 | struct madera *madera = dev_get_drvdata(pdev->dev.parent); | ||
1907 | struct cs47l92 *cs47l92; | ||
1908 | int i, ret; | ||
1909 | |||
1910 | BUILD_BUG_ON(ARRAY_SIZE(cs47l92_dai) > MADERA_MAX_DAI); | ||
1911 | |||
1912 | /* quick exit if Madera irqchip driver hasn't completed probe */ | ||
1913 | if (!madera->irq_dev) { | ||
1914 | dev_dbg(&pdev->dev, "irqchip driver not ready\n"); | ||
1915 | return -EPROBE_DEFER; | ||
1916 | } | ||
1917 | |||
1918 | cs47l92 = devm_kzalloc(&pdev->dev, sizeof(struct cs47l92), GFP_KERNEL); | ||
1919 | if (!cs47l92) | ||
1920 | return -ENOMEM; | ||
1921 | |||
1922 | platform_set_drvdata(pdev, cs47l92); | ||
1923 | |||
1924 | cs47l92->core.madera = madera; | ||
1925 | cs47l92->core.dev = &pdev->dev; | ||
1926 | cs47l92->core.num_inputs = 8; | ||
1927 | |||
1928 | ret = madera_core_init(&cs47l92->core); | ||
1929 | if (ret) | ||
1930 | return ret; | ||
1931 | |||
1932 | ret = madera_request_irq(madera, MADERA_IRQ_DSP_IRQ1, | ||
1933 | "ADSP2 Compressed IRQ", cs47l92_adsp2_irq, | ||
1934 | cs47l92); | ||
1935 | if (ret != 0) { | ||
1936 | dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); | ||
1937 | goto error_core; | ||
1938 | } | ||
1939 | |||
1940 | ret = madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 1); | ||
1941 | if (ret) | ||
1942 | dev_warn(&pdev->dev, "Failed to set DSP IRQ wake: %d\n", ret); | ||
1943 | |||
1944 | cs47l92->core.adsp[0].part = "cs47l92"; | ||
1945 | cs47l92->core.adsp[0].num = 1; | ||
1946 | cs47l92->core.adsp[0].type = WMFW_ADSP2; | ||
1947 | cs47l92->core.adsp[0].rev = 2; | ||
1948 | cs47l92->core.adsp[0].dev = madera->dev; | ||
1949 | cs47l92->core.adsp[0].regmap = madera->regmap_32bit; | ||
1950 | |||
1951 | cs47l92->core.adsp[0].base = MADERA_DSP1_CONFIG_1; | ||
1952 | cs47l92->core.adsp[0].mem = cs47l92_dsp1_regions; | ||
1953 | cs47l92->core.adsp[0].num_mems = ARRAY_SIZE(cs47l92_dsp1_regions); | ||
1954 | |||
1955 | cs47l92->core.adsp[0].lock_regions = WM_ADSP2_REGION_1_9; | ||
1956 | |||
1957 | ret = wm_adsp2_init(&cs47l92->core.adsp[0]); | ||
1958 | if (ret != 0) | ||
1959 | goto error_dsp_irq; | ||
1960 | |||
1961 | ret = madera_init_bus_error_irq(&cs47l92->core, 0, wm_adsp2_bus_error); | ||
1962 | if (ret != 0) { | ||
1963 | wm_adsp2_remove(&cs47l92->core.adsp[0]); | ||
1964 | goto error_adsp; | ||
1965 | } | ||
1966 | |||
1967 | madera_init_fll(madera, 1, MADERA_FLL1_CONTROL_1 - 1, | ||
1968 | &cs47l92->fll[0]); | ||
1969 | madera_init_fll(madera, 2, MADERA_FLL2_CONTROL_1 - 1, | ||
1970 | &cs47l92->fll[1]); | ||
1971 | |||
1972 | for (i = 0; i < ARRAY_SIZE(cs47l92_dai); i++) | ||
1973 | madera_init_dai(&cs47l92->core, i); | ||
1974 | |||
1975 | /* Latch volume update bits */ | ||
1976 | for (i = 0; i < ARRAY_SIZE(cs47l92_digital_vu); i++) | ||
1977 | regmap_update_bits(madera->regmap, cs47l92_digital_vu[i], | ||
1978 | CS47L92_DIG_VU, CS47L92_DIG_VU); | ||
1979 | |||
1980 | pm_runtime_enable(&pdev->dev); | ||
1981 | pm_runtime_idle(&pdev->dev); | ||
1982 | |||
1983 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
1984 | &soc_component_dev_cs47l92, | ||
1985 | cs47l92_dai, | ||
1986 | ARRAY_SIZE(cs47l92_dai)); | ||
1987 | if (ret < 0) { | ||
1988 | dev_err(&pdev->dev, "Failed to register component: %d\n", ret); | ||
1989 | goto error_pm_runtime; | ||
1990 | } | ||
1991 | |||
1992 | return ret; | ||
1993 | |||
1994 | error_pm_runtime: | ||
1995 | pm_runtime_disable(&pdev->dev); | ||
1996 | madera_free_bus_error_irq(&cs47l92->core, 0); | ||
1997 | error_adsp: | ||
1998 | wm_adsp2_remove(&cs47l92->core.adsp[0]); | ||
1999 | error_dsp_irq: | ||
2000 | madera_set_irq_wake(madera, MADERA_IRQ_DSP_IRQ1, 0); | ||
2001 | madera_free_irq(madera, MADERA_IRQ_DSP_IRQ1, cs47l92); | ||
2002 | error_core: | ||
2003 | madera_core_free(&cs47l92->core); | ||
2004 | |||
2005 | return ret; | ||
2006 | } | ||
2007 | |||
2008 | static int cs47l92_remove(struct platform_device *pdev) | ||
2009 | { | ||
2010 | struct cs47l92 *cs47l92 = platform_get_drvdata(pdev); | ||
2011 | |||
2012 | pm_runtime_disable(&pdev->dev); | ||
2013 | |||
2014 | madera_free_bus_error_irq(&cs47l92->core, 0); | ||
2015 | wm_adsp2_remove(&cs47l92->core.adsp[0]); | ||
2016 | |||
2017 | madera_set_irq_wake(cs47l92->core.madera, MADERA_IRQ_DSP_IRQ1, 0); | ||
2018 | madera_free_irq(cs47l92->core.madera, MADERA_IRQ_DSP_IRQ1, cs47l92); | ||
2019 | |||
2020 | madera_core_free(&cs47l92->core); | ||
2021 | |||
2022 | return 0; | ||
2023 | } | ||
2024 | |||
2025 | static struct platform_driver cs47l92_codec_driver = { | ||
2026 | .driver = { | ||
2027 | .name = "cs47l92-codec", | ||
2028 | }, | ||
2029 | .probe = &cs47l92_probe, | ||
2030 | .remove = &cs47l92_remove, | ||
2031 | }; | ||
2032 | |||
2033 | module_platform_driver(cs47l92_codec_driver); | ||
2034 | |||
2035 | MODULE_SOFTDEP("pre: madera irq-madera arizona-micsupp"); | ||
2036 | MODULE_DESCRIPTION("ASoC CS47L92 driver"); | ||
2037 | MODULE_AUTHOR("Stuart Henderson <stuarth@opensource.cirrus.com>"); | ||
2038 | MODULE_LICENSE("GPL v2"); | ||
2039 | MODULE_ALIAS("platform:cs47l92-codec"); | ||
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index ed2959dbe1fb..36eef1fb3d18 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/acpi.h> | 11 | #include <linux/acpi.h> |
12 | #include <linux/clk.h> | ||
12 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
13 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
14 | #include <linux/mod_devicetable.h> | 15 | #include <linux/mod_devicetable.h> |
@@ -33,6 +34,7 @@ static const unsigned int supported_mclk_lrck_ratios[] = { | |||
33 | 34 | ||
34 | struct es8316_priv { | 35 | struct es8316_priv { |
35 | struct mutex lock; | 36 | struct mutex lock; |
37 | struct clk *mclk; | ||
36 | struct regmap *regmap; | 38 | struct regmap *regmap; |
37 | struct snd_soc_component *component; | 39 | struct snd_soc_component *component; |
38 | struct snd_soc_jack *jack; | 40 | struct snd_soc_jack *jack; |
@@ -363,13 +365,21 @@ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
363 | { | 365 | { |
364 | struct snd_soc_component *component = codec_dai->component; | 366 | struct snd_soc_component *component = codec_dai->component; |
365 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); | 367 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); |
366 | int i; | 368 | int i, ret; |
367 | int count = 0; | 369 | int count = 0; |
368 | 370 | ||
369 | es8316->sysclk = freq; | 371 | es8316->sysclk = freq; |
370 | 372 | ||
371 | if (freq == 0) | 373 | if (freq == 0) { |
374 | es8316->sysclk_constraints.list = NULL; | ||
375 | es8316->sysclk_constraints.count = 0; | ||
376 | |||
372 | return 0; | 377 | return 0; |
378 | } | ||
379 | |||
380 | ret = clk_set_rate(es8316->mclk, freq); | ||
381 | if (ret) | ||
382 | return ret; | ||
373 | 383 | ||
374 | /* Limit supported sample rates to ones that can be autodetected | 384 | /* Limit supported sample rates to ones that can be autodetected |
375 | * by the codec running in slave mode. | 385 | * by the codec running in slave mode. |
@@ -444,17 +454,10 @@ static int es8316_pcm_startup(struct snd_pcm_substream *substream, | |||
444 | struct snd_soc_component *component = dai->component; | 454 | struct snd_soc_component *component = dai->component; |
445 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); | 455 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); |
446 | 456 | ||
447 | if (es8316->sysclk == 0) { | 457 | if (es8316->sysclk_constraints.list) |
448 | dev_err(component->dev, "No sysclk provided\n"); | 458 | snd_pcm_hw_constraint_list(substream->runtime, 0, |
449 | return -EINVAL; | 459 | SNDRV_PCM_HW_PARAM_RATE, |
450 | } | 460 | &es8316->sysclk_constraints); |
451 | |||
452 | /* The set of sample rates that can be supported depends on the | ||
453 | * MCLK supplied to the CODEC. | ||
454 | */ | ||
455 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
456 | SNDRV_PCM_HW_PARAM_RATE, | ||
457 | &es8316->sysclk_constraints); | ||
458 | 461 | ||
459 | return 0; | 462 | return 0; |
460 | } | 463 | } |
@@ -466,11 +469,19 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream, | |||
466 | struct snd_soc_component *component = dai->component; | 469 | struct snd_soc_component *component = dai->component; |
467 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); | 470 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); |
468 | u8 wordlen = 0; | 471 | u8 wordlen = 0; |
472 | int i; | ||
469 | 473 | ||
470 | if (!es8316->sysclk) { | 474 | /* Validate supported sample rates that are autodetected from MCLK */ |
471 | dev_err(component->dev, "No MCLK configured\n"); | 475 | for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) { |
472 | return -EINVAL; | 476 | const unsigned int ratio = supported_mclk_lrck_ratios[i]; |
477 | |||
478 | if (es8316->sysclk % ratio != 0) | ||
479 | continue; | ||
480 | if (es8316->sysclk / ratio == params_rate(params)) | ||
481 | break; | ||
473 | } | 482 | } |
483 | if (i == NR_SUPPORTED_MCLK_LRCK_RATIOS) | ||
484 | return -EINVAL; | ||
474 | 485 | ||
475 | switch (params_format(params)) { | 486 | switch (params_format(params)) { |
476 | case SNDRV_PCM_FORMAT_S16_LE: | 487 | case SNDRV_PCM_FORMAT_S16_LE: |
@@ -700,9 +711,24 @@ static int es8316_set_jack(struct snd_soc_component *component, | |||
700 | static int es8316_probe(struct snd_soc_component *component) | 711 | static int es8316_probe(struct snd_soc_component *component) |
701 | { | 712 | { |
702 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); | 713 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); |
714 | int ret; | ||
703 | 715 | ||
704 | es8316->component = component; | 716 | es8316->component = component; |
705 | 717 | ||
718 | es8316->mclk = devm_clk_get_optional(component->dev, "mclk"); | ||
719 | if (IS_ERR(es8316->mclk)) { | ||
720 | dev_err(component->dev, "unable to get mclk\n"); | ||
721 | return PTR_ERR(es8316->mclk); | ||
722 | } | ||
723 | if (!es8316->mclk) | ||
724 | dev_warn(component->dev, "assuming static mclk\n"); | ||
725 | |||
726 | ret = clk_prepare_enable(es8316->mclk); | ||
727 | if (ret) { | ||
728 | dev_err(component->dev, "unable to enable mclk\n"); | ||
729 | return ret; | ||
730 | } | ||
731 | |||
706 | /* Reset codec and enable current state machine */ | 732 | /* Reset codec and enable current state machine */ |
707 | snd_soc_component_write(component, ES8316_RESET, 0x3f); | 733 | snd_soc_component_write(component, ES8316_RESET, 0x3f); |
708 | usleep_range(5000, 5500); | 734 | usleep_range(5000, 5500); |
@@ -725,8 +751,16 @@ static int es8316_probe(struct snd_soc_component *component) | |||
725 | return 0; | 751 | return 0; |
726 | } | 752 | } |
727 | 753 | ||
754 | static void es8316_remove(struct snd_soc_component *component) | ||
755 | { | ||
756 | struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); | ||
757 | |||
758 | clk_disable_unprepare(es8316->mclk); | ||
759 | } | ||
760 | |||
728 | static const struct snd_soc_component_driver soc_component_dev_es8316 = { | 761 | static const struct snd_soc_component_driver soc_component_dev_es8316 = { |
729 | .probe = es8316_probe, | 762 | .probe = es8316_probe, |
763 | .remove = es8316_remove, | ||
730 | .set_jack = es8316_set_jack, | 764 | .set_jack = es8316_set_jack, |
731 | .controls = es8316_snd_controls, | 765 | .controls = es8316_snd_controls, |
732 | .num_controls = ARRAY_SIZE(es8316_snd_controls), | 766 | .num_controls = ARRAY_SIZE(es8316_snd_controls), |
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 69b81e704127..fdf64c29f563 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c | |||
@@ -99,7 +99,6 @@ static SOC_ENUM_SINGLE_DECL(adcpol, | |||
99 | 99 | ||
100 | static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0); | 100 | static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0); |
101 | static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0); | 101 | static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0); |
102 | static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0); | ||
103 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); | 102 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); |
104 | static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0); | 103 | static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0); |
105 | 104 | ||
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 0bf1c8cad108..b5fd8f08726e 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/string.h> | 8 | #include <linux/string.h> |
9 | #include <sound/core.h> | 9 | #include <sound/core.h> |
10 | #include <sound/jack.h> | ||
10 | #include <sound/pcm.h> | 11 | #include <sound/pcm.h> |
11 | #include <sound/pcm_params.h> | 12 | #include <sound/pcm_params.h> |
12 | #include <sound/soc.h> | 13 | #include <sound/soc.h> |
@@ -274,6 +275,8 @@ struct hdmi_codec_priv { | |||
274 | struct snd_pcm_chmap *chmap_info; | 275 | struct snd_pcm_chmap *chmap_info; |
275 | unsigned int chmap_idx; | 276 | unsigned int chmap_idx; |
276 | struct mutex lock; | 277 | struct mutex lock; |
278 | struct snd_soc_jack *jack; | ||
279 | unsigned int jack_status; | ||
277 | }; | 280 | }; |
278 | 281 | ||
279 | static const struct snd_soc_dapm_widget hdmi_widgets[] = { | 282 | static const struct snd_soc_dapm_widget hdmi_widgets[] = { |
@@ -663,6 +666,49 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai) | |||
663 | return 0; | 666 | return 0; |
664 | } | 667 | } |
665 | 668 | ||
669 | static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp, | ||
670 | unsigned int jack_status) | ||
671 | { | ||
672 | if (hcp->jack && jack_status != hcp->jack_status) { | ||
673 | snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT); | ||
674 | hcp->jack_status = jack_status; | ||
675 | } | ||
676 | } | ||
677 | |||
678 | static void plugged_cb(struct device *dev, bool plugged) | ||
679 | { | ||
680 | struct hdmi_codec_priv *hcp = dev_get_drvdata(dev); | ||
681 | |||
682 | if (plugged) | ||
683 | hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT); | ||
684 | else | ||
685 | hdmi_codec_jack_report(hcp, 0); | ||
686 | } | ||
687 | |||
688 | /** | ||
689 | * hdmi_codec_set_jack_detect - register HDMI plugged callback | ||
690 | * @component: the hdmi-codec instance | ||
691 | * @jack: ASoC jack to report (dis)connection events on | ||
692 | */ | ||
693 | int hdmi_codec_set_jack_detect(struct snd_soc_component *component, | ||
694 | struct snd_soc_jack *jack) | ||
695 | { | ||
696 | struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); | ||
697 | int ret = -EOPNOTSUPP; | ||
698 | |||
699 | if (hcp->hcd.ops->hook_plugged_cb) { | ||
700 | hcp->jack = jack; | ||
701 | ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent, | ||
702 | hcp->hcd.data, | ||
703 | plugged_cb, | ||
704 | component->dev); | ||
705 | if (ret) | ||
706 | hcp->jack = NULL; | ||
707 | } | ||
708 | return ret; | ||
709 | } | ||
710 | EXPORT_SYMBOL_GPL(hdmi_codec_set_jack_detect); | ||
711 | |||
666 | static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai) | 712 | static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai) |
667 | { | 713 | { |
668 | struct hdmi_codec_daifmt *cf = dai->playback_dma_data; | 714 | struct hdmi_codec_daifmt *cf = dai->playback_dma_data; |
diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 7feedbb7bbed..14d8fe1c28a4 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c | |||
@@ -405,7 +405,6 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev) | |||
405 | { | 405 | { |
406 | struct rk3036_codec_priv *priv; | 406 | struct rk3036_codec_priv *priv; |
407 | struct device_node *of_node = pdev->dev.of_node; | 407 | struct device_node *of_node = pdev->dev.of_node; |
408 | struct resource *res; | ||
409 | void __iomem *base; | 408 | void __iomem *base; |
410 | struct regmap *grf; | 409 | struct regmap *grf; |
411 | int ret; | 410 | int ret; |
@@ -414,8 +413,7 @@ static int rk3036_codec_platform_probe(struct platform_device *pdev) | |||
414 | if (!priv) | 413 | if (!priv) |
415 | return -ENOMEM; | 414 | return -ENOMEM; |
416 | 415 | ||
417 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 416 | base = devm_platform_ioremap_resource(pdev, 0); |
418 | base = devm_ioremap_resource(&pdev->dev, res); | ||
419 | if (IS_ERR(base)) | 417 | if (IS_ERR(base)) |
420 | return PTR_ERR(base); | 418 | return PTR_ERR(base); |
421 | 419 | ||
diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index 766354c73076..2567a5d15b55 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c | |||
@@ -545,15 +545,13 @@ static int jz4725b_codec_probe(struct platform_device *pdev) | |||
545 | { | 545 | { |
546 | struct device *dev = &pdev->dev; | 546 | struct device *dev = &pdev->dev; |
547 | struct jz_icdc *icdc; | 547 | struct jz_icdc *icdc; |
548 | struct resource *mem; | ||
549 | int ret; | 548 | int ret; |
550 | 549 | ||
551 | icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL); | 550 | icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL); |
552 | if (!icdc) | 551 | if (!icdc) |
553 | return -ENOMEM; | 552 | return -ENOMEM; |
554 | 553 | ||
555 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 554 | icdc->base = devm_platform_ioremap_resource(pdev, 0); |
556 | icdc->base = devm_ioremap_resource(dev, mem); | ||
557 | if (IS_ERR(icdc->base)) | 555 | if (IS_ERR(icdc->base)) |
558 | return PTR_ERR(icdc->base); | 556 | return PTR_ERR(icdc->base); |
559 | 557 | ||
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 974e17fa1911..460aa1fd1efe 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -318,7 +318,6 @@ static int jz4740_codec_probe(struct platform_device *pdev) | |||
318 | { | 318 | { |
319 | int ret; | 319 | int ret; |
320 | struct jz4740_codec *jz4740_codec; | 320 | struct jz4740_codec *jz4740_codec; |
321 | struct resource *mem; | ||
322 | void __iomem *base; | 321 | void __iomem *base; |
323 | 322 | ||
324 | jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec), | 323 | jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec), |
@@ -326,8 +325,7 @@ static int jz4740_codec_probe(struct platform_device *pdev) | |||
326 | if (!jz4740_codec) | 325 | if (!jz4740_codec) |
327 | return -ENOMEM; | 326 | return -ENOMEM; |
328 | 327 | ||
329 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 328 | base = devm_platform_ioremap_resource(pdev, 0); |
330 | base = devm_ioremap_resource(&pdev->dev, mem); | ||
331 | if (IS_ERR(base)) | 329 | if (IS_ERR(base)) |
332 | return PTR_ERR(base); | 330 | return PTR_ERR(base); |
333 | 331 | ||
diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 1b1be19a2f99..52639811cc52 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c | |||
@@ -87,6 +87,16 @@ | |||
87 | #define MADERA_FLLAO_MIN_N 4 | 87 | #define MADERA_FLLAO_MIN_N 4 |
88 | #define MADERA_FLLAO_MAX_N 1023 | 88 | #define MADERA_FLLAO_MAX_N 1023 |
89 | #define MADERA_FLLAO_MAX_FBDIV 254 | 89 | #define MADERA_FLLAO_MAX_FBDIV 254 |
90 | #define MADERA_FLLHJ_INT_MAX_N 1023 | ||
91 | #define MADERA_FLLHJ_INT_MIN_N 1 | ||
92 | #define MADERA_FLLHJ_FRAC_MAX_N 255 | ||
93 | #define MADERA_FLLHJ_FRAC_MIN_N 4 | ||
94 | #define MADERA_FLLHJ_LOW_THRESH 192000 | ||
95 | #define MADERA_FLLHJ_MID_THRESH 1152000 | ||
96 | #define MADERA_FLLHJ_MAX_THRESH 13000000 | ||
97 | #define MADERA_FLLHJ_LOW_GAINS 0x23f0 | ||
98 | #define MADERA_FLLHJ_MID_GAINS 0x22f2 | ||
99 | #define MADERA_FLLHJ_HIGH_GAINS 0x21f0 | ||
90 | 100 | ||
91 | #define MADERA_FLL_SYNCHRONISER_OFFS 0x10 | 101 | #define MADERA_FLL_SYNCHRONISER_OFFS 0x10 |
92 | #define CS47L35_FLL_SYNCHRONISER_OFFS 0xE | 102 | #define CS47L35_FLL_SYNCHRONISER_OFFS 0xE |
@@ -96,6 +106,7 @@ | |||
96 | #define MADERA_FLL_CONTROL_4_OFFS 0x4 | 106 | #define MADERA_FLL_CONTROL_4_OFFS 0x4 |
97 | #define MADERA_FLL_CONTROL_5_OFFS 0x5 | 107 | #define MADERA_FLL_CONTROL_5_OFFS 0x5 |
98 | #define MADERA_FLL_CONTROL_6_OFFS 0x6 | 108 | #define MADERA_FLL_CONTROL_6_OFFS 0x6 |
109 | #define MADERA_FLL_GAIN_OFFS 0x8 | ||
99 | #define MADERA_FLL_CONTROL_7_OFFS 0x9 | 110 | #define MADERA_FLL_CONTROL_7_OFFS 0x9 |
100 | #define MADERA_FLL_EFS_2_OFFS 0xA | 111 | #define MADERA_FLL_EFS_2_OFFS 0xA |
101 | #define MADERA_FLL_SYNCHRONISER_1_OFFS 0x1 | 112 | #define MADERA_FLL_SYNCHRONISER_1_OFFS 0x1 |
@@ -107,6 +118,9 @@ | |||
107 | #define MADERA_FLL_SYNCHRONISER_7_OFFS 0x7 | 118 | #define MADERA_FLL_SYNCHRONISER_7_OFFS 0x7 |
108 | #define MADERA_FLL_SPREAD_SPECTRUM_OFFS 0x9 | 119 | #define MADERA_FLL_SPREAD_SPECTRUM_OFFS 0x9 |
109 | #define MADERA_FLL_GPIO_CLOCK_OFFS 0xA | 120 | #define MADERA_FLL_GPIO_CLOCK_OFFS 0xA |
121 | #define MADERA_FLL_CONTROL_10_OFFS 0xA | ||
122 | #define MADERA_FLL_CONTROL_11_OFFS 0xB | ||
123 | #define MADERA_FLL1_DIGITAL_TEST_1_OFFS 0xD | ||
110 | 124 | ||
111 | #define MADERA_FLLAO_CONTROL_1_OFFS 0x1 | 125 | #define MADERA_FLLAO_CONTROL_1_OFFS 0x1 |
112 | #define MADERA_FLLAO_CONTROL_2_OFFS 0x2 | 126 | #define MADERA_FLLAO_CONTROL_2_OFFS 0x2 |
@@ -300,6 +314,100 @@ int madera_free_overheat(struct madera_priv *priv) | |||
300 | } | 314 | } |
301 | EXPORT_SYMBOL_GPL(madera_free_overheat); | 315 | EXPORT_SYMBOL_GPL(madera_free_overheat); |
302 | 316 | ||
317 | static int madera_get_variable_u32_array(struct device *dev, | ||
318 | const char *propname, | ||
319 | u32 *dest, int n_max, | ||
320 | int multiple) | ||
321 | { | ||
322 | int n, ret; | ||
323 | |||
324 | n = device_property_count_u32(dev, propname); | ||
325 | if (n < 0) { | ||
326 | if (n == -EINVAL) | ||
327 | return 0; /* missing, ignore */ | ||
328 | |||
329 | dev_warn(dev, "%s malformed (%d)\n", propname, n); | ||
330 | |||
331 | return n; | ||
332 | } else if ((n % multiple) != 0) { | ||
333 | dev_warn(dev, "%s not a multiple of %d entries\n", | ||
334 | propname, multiple); | ||
335 | |||
336 | return -EINVAL; | ||
337 | } | ||
338 | |||
339 | if (n > n_max) | ||
340 | n = n_max; | ||
341 | |||
342 | ret = device_property_read_u32_array(dev, propname, dest, n); | ||
343 | if (ret < 0) | ||
344 | return ret; | ||
345 | |||
346 | return n; | ||
347 | } | ||
348 | |||
349 | static void madera_prop_get_inmode(struct madera_priv *priv) | ||
350 | { | ||
351 | struct madera *madera = priv->madera; | ||
352 | struct madera_codec_pdata *pdata = &madera->pdata.codec; | ||
353 | u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS]; | ||
354 | int n, i, in_idx, ch_idx; | ||
355 | |||
356 | BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT); | ||
357 | BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS); | ||
358 | |||
359 | n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode", | ||
360 | tmp, ARRAY_SIZE(tmp), | ||
361 | MADERA_MAX_MUXED_CHANNELS); | ||
362 | if (n < 0) | ||
363 | return; | ||
364 | |||
365 | in_idx = 0; | ||
366 | ch_idx = 0; | ||
367 | for (i = 0; i < n; ++i) { | ||
368 | pdata->inmode[in_idx][ch_idx] = tmp[i]; | ||
369 | |||
370 | if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) { | ||
371 | ch_idx = 0; | ||
372 | ++in_idx; | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | |||
377 | static void madera_prop_get_pdata(struct madera_priv *priv) | ||
378 | { | ||
379 | struct madera *madera = priv->madera; | ||
380 | struct madera_codec_pdata *pdata = &madera->pdata.codec; | ||
381 | u32 out_mono[ARRAY_SIZE(pdata->out_mono)]; | ||
382 | int i, n; | ||
383 | |||
384 | madera_prop_get_inmode(priv); | ||
385 | |||
386 | n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono", | ||
387 | out_mono, ARRAY_SIZE(out_mono), 1); | ||
388 | if (n > 0) | ||
389 | for (i = 0; i < n; ++i) | ||
390 | pdata->out_mono[i] = !!out_mono[i]; | ||
391 | |||
392 | madera_get_variable_u32_array(madera->dev, | ||
393 | "cirrus,max-channels-clocked", | ||
394 | pdata->max_channels_clocked, | ||
395 | ARRAY_SIZE(pdata->max_channels_clocked), | ||
396 | 1); | ||
397 | |||
398 | madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt", | ||
399 | pdata->pdm_fmt, | ||
400 | ARRAY_SIZE(pdata->pdm_fmt), 1); | ||
401 | |||
402 | madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute", | ||
403 | pdata->pdm_mute, | ||
404 | ARRAY_SIZE(pdata->pdm_mute), 1); | ||
405 | |||
406 | madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref", | ||
407 | pdata->dmic_ref, | ||
408 | ARRAY_SIZE(pdata->dmic_ref), 1); | ||
409 | } | ||
410 | |||
303 | int madera_core_init(struct madera_priv *priv) | 411 | int madera_core_init(struct madera_priv *priv) |
304 | { | 412 | { |
305 | int i; | 413 | int i; |
@@ -308,6 +416,9 @@ int madera_core_init(struct madera_priv *priv) | |||
308 | BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]); | 416 | BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]); |
309 | BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]); | 417 | BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]); |
310 | 418 | ||
419 | if (!dev_get_platdata(priv->madera->dev)) | ||
420 | madera_prop_get_pdata(priv); | ||
421 | |||
311 | mutex_init(&priv->rate_lock); | 422 | mutex_init(&priv->rate_lock); |
312 | 423 | ||
313 | for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++) | 424 | for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++) |
@@ -944,6 +1055,10 @@ static void madera_configure_input_mode(struct madera *madera) | |||
944 | int max_analogue_inputs, max_dmic_sup, i; | 1055 | int max_analogue_inputs, max_dmic_sup, i; |
945 | 1056 | ||
946 | switch (madera->type) { | 1057 | switch (madera->type) { |
1058 | case CS47L15: | ||
1059 | max_analogue_inputs = 1; | ||
1060 | max_dmic_sup = 2; | ||
1061 | break; | ||
947 | case CS47L35: | 1062 | case CS47L35: |
948 | max_analogue_inputs = 2; | 1063 | max_analogue_inputs = 2; |
949 | max_dmic_sup = 2; | 1064 | max_dmic_sup = 2; |
@@ -1770,6 +1885,18 @@ const struct soc_enum madera_asrc1_rate[] = { | |||
1770 | }; | 1885 | }; |
1771 | EXPORT_SYMBOL_GPL(madera_asrc1_rate); | 1886 | EXPORT_SYMBOL_GPL(madera_asrc1_rate); |
1772 | 1887 | ||
1888 | const struct soc_enum madera_asrc1_bidir_rate[] = { | ||
1889 | SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1, | ||
1890 | MADERA_ASRC1_RATE1_SHIFT, 0xf, | ||
1891 | MADERA_RATE_ENUM_SIZE, | ||
1892 | madera_rate_text, madera_rate_val), | ||
1893 | SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2, | ||
1894 | MADERA_ASRC1_RATE2_SHIFT, 0xf, | ||
1895 | MADERA_RATE_ENUM_SIZE, | ||
1896 | madera_rate_text, madera_rate_val), | ||
1897 | }; | ||
1898 | EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate); | ||
1899 | |||
1773 | const struct soc_enum madera_asrc2_rate[] = { | 1900 | const struct soc_enum madera_asrc2_rate[] = { |
1774 | SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1, | 1901 | SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1, |
1775 | MADERA_ASRC2_RATE1_SHIFT, 0xf, | 1902 | MADERA_ASRC2_RATE1_SHIFT, 0xf, |
@@ -2149,6 +2276,9 @@ int madera_out_ev(struct snd_soc_dapm_widget *w, | |||
2149 | switch (madera->type) { | 2276 | switch (madera->type) { |
2150 | case CS47L90: | 2277 | case CS47L90: |
2151 | case CS47L91: | 2278 | case CS47L91: |
2279 | case CS42L92: | ||
2280 | case CS47L92: | ||
2281 | case CS47L93: | ||
2152 | out_up_delay = 6; | 2282 | out_up_delay = 6; |
2153 | break; | 2283 | break; |
2154 | default: | 2284 | default: |
@@ -2264,9 +2394,17 @@ int madera_hp_ev(struct snd_soc_dapm_widget *w, | |||
2264 | madera->hp_ena &= ~mask; | 2394 | madera->hp_ena &= ~mask; |
2265 | madera->hp_ena |= val; | 2395 | madera->hp_ena |= val; |
2266 | 2396 | ||
2267 | /* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */ | 2397 | switch (madera->type) { |
2268 | regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel); | 2398 | case CS42L92: |
2269 | ep_sel &= MADERA_EP_SEL_MASK; | 2399 | case CS47L92: |
2400 | case CS47L93: | ||
2401 | break; | ||
2402 | default: | ||
2403 | /* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */ | ||
2404 | regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel); | ||
2405 | ep_sel &= MADERA_EP_SEL_MASK; | ||
2406 | break; | ||
2407 | } | ||
2270 | 2408 | ||
2271 | /* Force off if HPDET has disabled the clamp for this output */ | 2409 | /* Force off if HPDET has disabled the clamp for this output */ |
2272 | if (!ep_sel && | 2410 | if (!ep_sel && |
@@ -2442,6 +2580,58 @@ static int madera_get_dspclk_setting(struct madera *madera, | |||
2442 | } | 2580 | } |
2443 | } | 2581 | } |
2444 | 2582 | ||
2583 | static int madera_set_outclk(struct snd_soc_component *component, | ||
2584 | unsigned int source, unsigned int freq) | ||
2585 | { | ||
2586 | int div, div_inc, rate; | ||
2587 | |||
2588 | switch (source) { | ||
2589 | case MADERA_OUTCLK_SYSCLK: | ||
2590 | dev_dbg(component->dev, "Configured OUTCLK to SYSCLK\n"); | ||
2591 | snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1, | ||
2592 | MADERA_OUT_CLK_SRC_MASK, source); | ||
2593 | return 0; | ||
2594 | case MADERA_OUTCLK_ASYNCCLK: | ||
2595 | dev_dbg(component->dev, "Configured OUTCLK to ASYNCCLK\n"); | ||
2596 | snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1, | ||
2597 | MADERA_OUT_CLK_SRC_MASK, source); | ||
2598 | return 0; | ||
2599 | case MADERA_OUTCLK_MCLK1: | ||
2600 | case MADERA_OUTCLK_MCLK2: | ||
2601 | case MADERA_OUTCLK_MCLK3: | ||
2602 | break; | ||
2603 | default: | ||
2604 | return -EINVAL; | ||
2605 | } | ||
2606 | |||
2607 | if (freq % 4000) | ||
2608 | rate = 5644800; | ||
2609 | else | ||
2610 | rate = 6144000; | ||
2611 | |||
2612 | div = 1; | ||
2613 | div_inc = 0; | ||
2614 | while (div <= 8) { | ||
2615 | if (freq / div == rate && !(freq % div)) { | ||
2616 | dev_dbg(component->dev, "Configured %dHz OUTCLK\n", rate); | ||
2617 | snd_soc_component_update_bits(component, | ||
2618 | MADERA_OUTPUT_RATE_1, | ||
2619 | MADERA_OUT_EXT_CLK_DIV_MASK | | ||
2620 | MADERA_OUT_CLK_SRC_MASK, | ||
2621 | (div_inc << MADERA_OUT_EXT_CLK_DIV_SHIFT) | | ||
2622 | source); | ||
2623 | return 0; | ||
2624 | } | ||
2625 | div_inc++; | ||
2626 | div *= 2; | ||
2627 | } | ||
2628 | |||
2629 | dev_err(component->dev, | ||
2630 | "Unable to generate %dHz OUTCLK from %dHz MCLK\n", | ||
2631 | rate, freq); | ||
2632 | return -EINVAL; | ||
2633 | } | ||
2634 | |||
2445 | int madera_set_sysclk(struct snd_soc_component *component, int clk_id, | 2635 | int madera_set_sysclk(struct snd_soc_component *component, int clk_id, |
2446 | int source, unsigned int freq, int dir) | 2636 | int source, unsigned int freq, int dir) |
2447 | { | 2637 | { |
@@ -2478,6 +2668,8 @@ int madera_set_sysclk(struct snd_soc_component *component, int clk_id, | |||
2478 | case MADERA_CLK_OPCLK: | 2668 | case MADERA_CLK_OPCLK: |
2479 | case MADERA_CLK_ASYNC_OPCLK: | 2669 | case MADERA_CLK_ASYNC_OPCLK: |
2480 | return madera_set_opclk(component, clk_id, freq); | 2670 | return madera_set_opclk(component, clk_id, freq); |
2671 | case MADERA_CLK_OUTCLK: | ||
2672 | return madera_set_outclk(component, source, freq); | ||
2481 | default: | 2673 | default: |
2482 | return -EINVAL; | 2674 | return -EINVAL; |
2483 | } | 2675 | } |
@@ -2691,6 +2883,10 @@ static const unsigned int madera_sr_vals[] = { | |||
2691 | #define MADERA_192K_44K1_RATE_MASK 0x003E00 | 2883 | #define MADERA_192K_44K1_RATE_MASK 0x003E00 |
2692 | #define MADERA_192K_RATE_MASK (MADERA_192K_48K_RATE_MASK | \ | 2884 | #define MADERA_192K_RATE_MASK (MADERA_192K_48K_RATE_MASK | \ |
2693 | MADERA_192K_44K1_RATE_MASK) | 2885 | MADERA_192K_44K1_RATE_MASK) |
2886 | #define MADERA_384K_48K_RATE_MASK 0x0F007E | ||
2887 | #define MADERA_384K_44K1_RATE_MASK 0x007E00 | ||
2888 | #define MADERA_384K_RATE_MASK (MADERA_384K_48K_RATE_MASK | \ | ||
2889 | MADERA_384K_44K1_RATE_MASK) | ||
2694 | 2890 | ||
2695 | static const struct snd_pcm_hw_constraint_list madera_constraint = { | 2891 | static const struct snd_pcm_hw_constraint_list madera_constraint = { |
2696 | .count = ARRAY_SIZE(madera_sr_vals), | 2892 | .count = ARRAY_SIZE(madera_sr_vals), |
@@ -2703,6 +2899,7 @@ static int madera_startup(struct snd_pcm_substream *substream, | |||
2703 | struct snd_soc_component *component = dai->component; | 2899 | struct snd_soc_component *component = dai->component; |
2704 | struct madera_priv *priv = snd_soc_component_get_drvdata(component); | 2900 | struct madera_priv *priv = snd_soc_component_get_drvdata(component); |
2705 | struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | 2901 | struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1]; |
2902 | struct madera *madera = priv->madera; | ||
2706 | unsigned int base_rate; | 2903 | unsigned int base_rate; |
2707 | 2904 | ||
2708 | if (!substream->runtime) | 2905 | if (!substream->runtime) |
@@ -2722,12 +2919,26 @@ static int madera_startup(struct snd_pcm_substream *substream, | |||
2722 | return 0; | 2919 | return 0; |
2723 | } | 2920 | } |
2724 | 2921 | ||
2725 | if (base_rate == 0) | 2922 | switch (madera->type) { |
2726 | dai_priv->constraint.mask = MADERA_192K_RATE_MASK; | 2923 | case CS42L92: |
2727 | else if (base_rate % 4000) | 2924 | case CS47L92: |
2728 | dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK; | 2925 | case CS47L93: |
2729 | else | 2926 | if (base_rate == 0) |
2730 | dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK; | 2927 | dai_priv->constraint.mask = MADERA_384K_RATE_MASK; |
2928 | else if (base_rate % 4000) | ||
2929 | dai_priv->constraint.mask = MADERA_384K_44K1_RATE_MASK; | ||
2930 | else | ||
2931 | dai_priv->constraint.mask = MADERA_384K_48K_RATE_MASK; | ||
2932 | break; | ||
2933 | default: | ||
2934 | if (base_rate == 0) | ||
2935 | dai_priv->constraint.mask = MADERA_192K_RATE_MASK; | ||
2936 | else if (base_rate % 4000) | ||
2937 | dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK; | ||
2938 | else | ||
2939 | dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK; | ||
2940 | break; | ||
2941 | } | ||
2731 | 2942 | ||
2732 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | 2943 | return snd_pcm_hw_constraint_list(substream->runtime, 0, |
2733 | SNDRV_PCM_HW_PARAM_RATE, | 2944 | SNDRV_PCM_HW_PARAM_RATE, |
@@ -4048,6 +4259,308 @@ int madera_set_fll_ao_refclk(struct madera_fll *fll, int source, | |||
4048 | } | 4259 | } |
4049 | EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk); | 4260 | EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk); |
4050 | 4261 | ||
4262 | static int madera_fllhj_disable(struct madera_fll *fll) | ||
4263 | { | ||
4264 | struct madera *madera = fll->madera; | ||
4265 | bool change; | ||
4266 | |||
4267 | madera_fll_dbg(fll, "Disabling FLL\n"); | ||
4268 | |||
4269 | /* Disable lockdet, but don't set ctrl_upd update but. This allows the | ||
4270 | * lock status bit to clear as normal, but should the FLL be enabled | ||
4271 | * again due to a control clock being required, the lock won't re-assert | ||
4272 | * as the FLL config registers are automatically applied when the FLL | ||
4273 | * enables. | ||
4274 | */ | ||
4275 | regmap_update_bits(madera->regmap, | ||
4276 | fll->base + MADERA_FLL_CONTROL_11_OFFS, | ||
4277 | MADERA_FLL1_LOCKDET_MASK, 0); | ||
4278 | regmap_update_bits(madera->regmap, | ||
4279 | fll->base + MADERA_FLL_CONTROL_1_OFFS, | ||
4280 | MADERA_FLL1_HOLD_MASK, MADERA_FLL1_HOLD_MASK); | ||
4281 | regmap_update_bits_check(madera->regmap, | ||
4282 | fll->base + MADERA_FLL_CONTROL_1_OFFS, | ||
4283 | MADERA_FLL1_ENA_MASK, 0, &change); | ||
4284 | |||
4285 | madera_wait_for_fll(fll, false); | ||
4286 | |||
4287 | /* ctrl_up gates the writes to all the fll's registers, setting it to 0 | ||
4288 | * here ensures that after a runtime suspend/resume cycle when one | ||
4289 | * enables the fll then ctrl_up is the last bit that is configured | ||
4290 | * by the fll enable code rather than the cache sync operation which | ||
4291 | * would have updated it much earlier before writing out all fll | ||
4292 | * registers | ||
4293 | */ | ||
4294 | regmap_update_bits(madera->regmap, | ||
4295 | fll->base + MADERA_FLL_CONTROL_2_OFFS, | ||
4296 | MADERA_FLL1_CTRL_UPD_MASK, 0); | ||
4297 | |||
4298 | if (change) | ||
4299 | pm_runtime_put_autosuspend(madera->dev); | ||
4300 | |||
4301 | return 0; | ||
4302 | } | ||
4303 | |||
4304 | static int madera_fllhj_apply(struct madera_fll *fll, int fin) | ||
4305 | { | ||
4306 | struct madera *madera = fll->madera; | ||
4307 | int refdiv, fref, fout, lockdet_thr, fbdiv, hp, fast_clk, fllgcd; | ||
4308 | bool frac = false; | ||
4309 | unsigned int fll_n, min_n, max_n, ratio, theta, lambda; | ||
4310 | unsigned int gains, val, num; | ||
4311 | |||
4312 | madera_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout); | ||
4313 | |||
4314 | for (refdiv = 0; refdiv < 4; refdiv++) | ||
4315 | if ((fin / (1 << refdiv)) <= MADERA_FLLHJ_MAX_THRESH) | ||
4316 | break; | ||
4317 | |||
4318 | fref = fin / (1 << refdiv); | ||
4319 | |||
4320 | /* Use simple heuristic approach to find a configuration that | ||
4321 | * should work for most input clocks. | ||
4322 | */ | ||
4323 | fast_clk = 0; | ||
4324 | fout = fll->fout; | ||
4325 | frac = fout % fref; | ||
4326 | |||
4327 | if (fref < MADERA_FLLHJ_LOW_THRESH) { | ||
4328 | lockdet_thr = 2; | ||
4329 | gains = MADERA_FLLHJ_LOW_GAINS; | ||
4330 | if (frac) | ||
4331 | fbdiv = 256; | ||
4332 | else | ||
4333 | fbdiv = 4; | ||
4334 | } else if (fref < MADERA_FLLHJ_MID_THRESH) { | ||
4335 | lockdet_thr = 8; | ||
4336 | gains = MADERA_FLLHJ_MID_GAINS; | ||
4337 | fbdiv = 1; | ||
4338 | } else { | ||
4339 | lockdet_thr = 8; | ||
4340 | gains = MADERA_FLLHJ_HIGH_GAINS; | ||
4341 | fbdiv = 1; | ||
4342 | /* For high speed input clocks, enable 300MHz fast oscillator | ||
4343 | * when we're in fractional divider mode. | ||
4344 | */ | ||
4345 | if (frac) { | ||
4346 | fast_clk = 0x3; | ||
4347 | fout = fll->fout * 6; | ||
4348 | } | ||
4349 | } | ||
4350 | /* Use high performance mode for fractional configurations. */ | ||
4351 | if (frac) { | ||
4352 | hp = 0x3; | ||
4353 | min_n = MADERA_FLLHJ_FRAC_MIN_N; | ||
4354 | max_n = MADERA_FLLHJ_FRAC_MAX_N; | ||
4355 | } else { | ||
4356 | hp = 0x0; | ||
4357 | min_n = MADERA_FLLHJ_INT_MIN_N; | ||
4358 | max_n = MADERA_FLLHJ_INT_MAX_N; | ||
4359 | } | ||
4360 | |||
4361 | ratio = fout / fref; | ||
4362 | |||
4363 | madera_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n", | ||
4364 | refdiv, fref, frac); | ||
4365 | |||
4366 | while (ratio / fbdiv < min_n) { | ||
4367 | fbdiv /= 2; | ||
4368 | if (fbdiv < 1) { | ||
4369 | madera_fll_err(fll, "FBDIV (%d) must be >= 1\n", fbdiv); | ||
4370 | return -EINVAL; | ||
4371 | } | ||
4372 | } | ||
4373 | while (frac && (ratio / fbdiv > max_n)) { | ||
4374 | fbdiv *= 2; | ||
4375 | if (fbdiv >= 1024) { | ||
4376 | madera_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv); | ||
4377 | return -EINVAL; | ||
4378 | } | ||
4379 | } | ||
4380 | |||
4381 | madera_fll_dbg(fll, "lockdet=%d, hp=0x%x, fbdiv:%d\n", | ||
4382 | lockdet_thr, hp, fbdiv); | ||
4383 | |||
4384 | /* Calculate N.K values */ | ||
4385 | fllgcd = gcd(fout, fbdiv * fref); | ||
4386 | num = fout / fllgcd; | ||
4387 | lambda = (fref * fbdiv) / fllgcd; | ||
4388 | fll_n = num / lambda; | ||
4389 | theta = num % lambda; | ||
4390 | |||
4391 | madera_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n", | ||
4392 | fll_n, fllgcd, theta, lambda); | ||
4393 | |||
4394 | /* Some sanity checks before any registers are written. */ | ||
4395 | if (fll_n < min_n || fll_n > max_n) { | ||
4396 | madera_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n", | ||
4397 | frac ? "fractional" : "integer", min_n, max_n, | ||
4398 | fll_n); | ||
4399 | return -EINVAL; | ||
4400 | } | ||
4401 | if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) { | ||
4402 | madera_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n", | ||
4403 | frac ? "fractional" : "integer", fbdiv); | ||
4404 | return -EINVAL; | ||
4405 | } | ||
4406 | |||
4407 | /* clear the ctrl_upd bit to guarantee we write to it later. */ | ||
4408 | regmap_write(madera->regmap, | ||
4409 | fll->base + MADERA_FLL_CONTROL_2_OFFS, | ||
4410 | fll_n << MADERA_FLL1_N_SHIFT); | ||
4411 | regmap_update_bits(madera->regmap, | ||
4412 | fll->base + MADERA_FLL_CONTROL_3_OFFS, | ||
4413 | MADERA_FLL1_THETA_MASK, | ||
4414 | theta << MADERA_FLL1_THETA_SHIFT); | ||
4415 | regmap_update_bits(madera->regmap, | ||
4416 | fll->base + MADERA_FLL_CONTROL_4_OFFS, | ||
4417 | MADERA_FLL1_LAMBDA_MASK, | ||
4418 | lambda << MADERA_FLL1_LAMBDA_SHIFT); | ||
4419 | regmap_update_bits(madera->regmap, | ||
4420 | fll->base + MADERA_FLL_CONTROL_5_OFFS, | ||
4421 | MADERA_FLL1_FB_DIV_MASK, | ||
4422 | fbdiv << MADERA_FLL1_FB_DIV_SHIFT); | ||
4423 | regmap_update_bits(madera->regmap, | ||
4424 | fll->base + MADERA_FLL_CONTROL_6_OFFS, | ||
4425 | MADERA_FLL1_REFCLK_DIV_MASK, | ||
4426 | refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT); | ||
4427 | regmap_update_bits(madera->regmap, | ||
4428 | fll->base + MADERA_FLL_GAIN_OFFS, | ||
4429 | 0xffff, | ||
4430 | gains); | ||
4431 | val = hp << MADERA_FLL1_HP_SHIFT; | ||
4432 | val |= 1 << MADERA_FLL1_PHASEDET_ENA_SHIFT; | ||
4433 | regmap_update_bits(madera->regmap, | ||
4434 | fll->base + MADERA_FLL_CONTROL_10_OFFS, | ||
4435 | MADERA_FLL1_HP_MASK | MADERA_FLL1_PHASEDET_ENA_MASK, | ||
4436 | val); | ||
4437 | regmap_update_bits(madera->regmap, | ||
4438 | fll->base + MADERA_FLL_CONTROL_11_OFFS, | ||
4439 | MADERA_FLL1_LOCKDET_THR_MASK, | ||
4440 | lockdet_thr << MADERA_FLL1_LOCKDET_THR_SHIFT); | ||
4441 | regmap_update_bits(madera->regmap, | ||
4442 | fll->base + MADERA_FLL1_DIGITAL_TEST_1_OFFS, | ||
4443 | MADERA_FLL1_SYNC_EFS_ENA_MASK | | ||
4444 | MADERA_FLL1_CLK_VCO_FAST_SRC_MASK, | ||
4445 | fast_clk); | ||
4446 | |||
4447 | return 0; | ||
4448 | } | ||
4449 | |||
4450 | static int madera_fllhj_enable(struct madera_fll *fll) | ||
4451 | { | ||
4452 | struct madera *madera = fll->madera; | ||
4453 | int already_enabled = madera_is_enabled_fll(fll, fll->base); | ||
4454 | int ret; | ||
4455 | |||
4456 | if (already_enabled < 0) | ||
4457 | return already_enabled; | ||
4458 | |||
4459 | if (!already_enabled) | ||
4460 | pm_runtime_get_sync(madera->dev); | ||
4461 | |||
4462 | madera_fll_dbg(fll, "Enabling FLL, initially %s\n", | ||
4463 | already_enabled ? "enabled" : "disabled"); | ||
4464 | |||
4465 | /* FLLn_HOLD must be set before configuring any registers */ | ||
4466 | regmap_update_bits(fll->madera->regmap, | ||
4467 | fll->base + MADERA_FLL_CONTROL_1_OFFS, | ||
4468 | MADERA_FLL1_HOLD_MASK, | ||
4469 | MADERA_FLL1_HOLD_MASK); | ||
4470 | |||
4471 | /* Apply refclk */ | ||
4472 | ret = madera_fllhj_apply(fll, fll->ref_freq); | ||
4473 | if (ret) { | ||
4474 | madera_fll_err(fll, "Failed to set FLL: %d\n", ret); | ||
4475 | goto out; | ||
4476 | } | ||
4477 | regmap_update_bits(madera->regmap, | ||
4478 | fll->base + MADERA_FLL_CONTROL_1_OFFS, | ||
4479 | CS47L92_FLL1_REFCLK_SRC_MASK, | ||
4480 | fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT); | ||
4481 | |||
4482 | regmap_update_bits(madera->regmap, | ||
4483 | fll->base + MADERA_FLL_CONTROL_1_OFFS, | ||
4484 | MADERA_FLL1_ENA_MASK, | ||
4485 | MADERA_FLL1_ENA_MASK); | ||
4486 | |||
4487 | out: | ||
4488 | regmap_update_bits(madera->regmap, | ||
4489 | fll->base + MADERA_FLL_CONTROL_11_OFFS, | ||
4490 | MADERA_FLL1_LOCKDET_MASK, | ||
4491 | MADERA_FLL1_LOCKDET_MASK); | ||
4492 | |||
4493 | regmap_update_bits(madera->regmap, | ||
4494 | fll->base + MADERA_FLL_CONTROL_2_OFFS, | ||
4495 | MADERA_FLL1_CTRL_UPD_MASK, | ||
4496 | MADERA_FLL1_CTRL_UPD_MASK); | ||
4497 | |||
4498 | /* Release the hold so that flln locks to external frequency */ | ||
4499 | regmap_update_bits(madera->regmap, | ||
4500 | fll->base + MADERA_FLL_CONTROL_1_OFFS, | ||
4501 | MADERA_FLL1_HOLD_MASK, | ||
4502 | 0); | ||
4503 | |||
4504 | if (!already_enabled) | ||
4505 | madera_wait_for_fll(fll, true); | ||
4506 | |||
4507 | return 0; | ||
4508 | } | ||
4509 | |||
4510 | static int madera_fllhj_validate(struct madera_fll *fll, | ||
4511 | unsigned int ref_in, | ||
4512 | unsigned int fout) | ||
4513 | { | ||
4514 | if (fout && !ref_in) { | ||
4515 | madera_fll_err(fll, "fllout set without valid input clk\n"); | ||
4516 | return -EINVAL; | ||
4517 | } | ||
4518 | |||
4519 | if (fll->fout && fout != fll->fout) { | ||
4520 | madera_fll_err(fll, "Can't change output on active FLL\n"); | ||
4521 | return -EINVAL; | ||
4522 | } | ||
4523 | |||
4524 | if (ref_in / MADERA_FLL_MAX_REFDIV > MADERA_FLLHJ_MAX_THRESH) { | ||
4525 | madera_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in); | ||
4526 | return -EINVAL; | ||
4527 | } | ||
4528 | |||
4529 | return 0; | ||
4530 | } | ||
4531 | |||
4532 | int madera_fllhj_set_refclk(struct madera_fll *fll, int source, | ||
4533 | unsigned int fin, unsigned int fout) | ||
4534 | { | ||
4535 | int ret = 0; | ||
4536 | |||
4537 | /* To remain consistent with previous FLLs, we expect fout to be | ||
4538 | * provided in the form of the required sysclk rate, which is | ||
4539 | * 2x the calculated fll out. | ||
4540 | */ | ||
4541 | if (fout) | ||
4542 | fout /= 2; | ||
4543 | |||
4544 | if (fll->ref_src == source && fll->ref_freq == fin && | ||
4545 | fll->fout == fout) | ||
4546 | return 0; | ||
4547 | |||
4548 | if (fin && fout && madera_fllhj_validate(fll, fin, fout)) | ||
4549 | return -EINVAL; | ||
4550 | |||
4551 | fll->ref_src = source; | ||
4552 | fll->ref_freq = fin; | ||
4553 | fll->fout = fout; | ||
4554 | |||
4555 | if (fout) | ||
4556 | ret = madera_fllhj_enable(fll); | ||
4557 | else | ||
4558 | madera_fllhj_disable(fll); | ||
4559 | |||
4560 | return ret; | ||
4561 | } | ||
4562 | EXPORT_SYMBOL_GPL(madera_fllhj_set_refclk); | ||
4563 | |||
4051 | /** | 4564 | /** |
4052 | * madera_set_output_mode - Set the mode of the specified output | 4565 | * madera_set_output_mode - Set the mode of the specified output |
4053 | * | 4566 | * |
diff --git a/sound/soc/codecs/madera.h b/sound/soc/codecs/madera.h index 0af66f280770..1f3e8e230cf2 100644 --- a/sound/soc/codecs/madera.h +++ b/sound/soc/codecs/madera.h | |||
@@ -47,6 +47,7 @@ | |||
47 | #define MADERA_CLK_SYSCLK_3 6 | 47 | #define MADERA_CLK_SYSCLK_3 6 |
48 | #define MADERA_CLK_ASYNCCLK_2 7 | 48 | #define MADERA_CLK_ASYNCCLK_2 7 |
49 | #define MADERA_CLK_DSPCLK 8 | 49 | #define MADERA_CLK_DSPCLK 8 |
50 | #define MADERA_CLK_OUTCLK 9 | ||
50 | 51 | ||
51 | #define MADERA_CLK_SRC_MCLK1 0x0 | 52 | #define MADERA_CLK_SRC_MCLK1 0x0 |
52 | #define MADERA_CLK_SRC_MCLK2 0x1 | 53 | #define MADERA_CLK_SRC_MCLK2 0x1 |
@@ -61,6 +62,12 @@ | |||
61 | #define MADERA_CLK_SRC_AIF4BCLK 0xB | 62 | #define MADERA_CLK_SRC_AIF4BCLK 0xB |
62 | #define MADERA_CLK_SRC_FLLAO 0xF | 63 | #define MADERA_CLK_SRC_FLLAO 0xF |
63 | 64 | ||
65 | #define MADERA_OUTCLK_SYSCLK 0 | ||
66 | #define MADERA_OUTCLK_ASYNCCLK 1 | ||
67 | #define MADERA_OUTCLK_MCLK1 4 | ||
68 | #define MADERA_OUTCLK_MCLK2 5 | ||
69 | #define MADERA_OUTCLK_MCLK3 6 | ||
70 | |||
64 | #define MADERA_MIXER_VOL_MASK 0x00FE | 71 | #define MADERA_MIXER_VOL_MASK 0x00FE |
65 | #define MADERA_MIXER_VOL_SHIFT 1 | 72 | #define MADERA_MIXER_VOL_SHIFT 1 |
66 | #define MADERA_MIXER_VOL_WIDTH 7 | 73 | #define MADERA_MIXER_VOL_WIDTH 7 |
@@ -326,6 +333,7 @@ extern const struct soc_enum madera_sample_rate[]; | |||
326 | extern const struct soc_enum madera_isrc_fsl[]; | 333 | extern const struct soc_enum madera_isrc_fsl[]; |
327 | extern const struct soc_enum madera_isrc_fsh[]; | 334 | extern const struct soc_enum madera_isrc_fsh[]; |
328 | extern const struct soc_enum madera_asrc1_rate[]; | 335 | extern const struct soc_enum madera_asrc1_rate[]; |
336 | extern const struct soc_enum madera_asrc1_bidir_rate[]; | ||
329 | extern const struct soc_enum madera_asrc2_rate[]; | 337 | extern const struct soc_enum madera_asrc2_rate[]; |
330 | extern const struct soc_enum madera_dfc_width[]; | 338 | extern const struct soc_enum madera_dfc_width[]; |
331 | extern const struct soc_enum madera_dfc_type[]; | 339 | extern const struct soc_enum madera_dfc_type[]; |
@@ -403,6 +411,8 @@ int madera_set_fll_syncclk(struct madera_fll *fll, int source, | |||
403 | unsigned int fref, unsigned int fout); | 411 | unsigned int fref, unsigned int fout); |
404 | int madera_set_fll_ao_refclk(struct madera_fll *fll, int source, | 412 | int madera_set_fll_ao_refclk(struct madera_fll *fll, int source, |
405 | unsigned int fin, unsigned int fout); | 413 | unsigned int fin, unsigned int fout); |
414 | int madera_fllhj_set_refclk(struct madera_fll *fll, int source, | ||
415 | unsigned int fin, unsigned int fout); | ||
406 | 416 | ||
407 | int madera_core_init(struct madera_priv *priv); | 417 | int madera_core_init(struct madera_priv *priv); |
408 | int madera_core_free(struct madera_priv *priv); | 418 | int madera_core_free(struct madera_priv *priv); |
diff --git a/sound/soc/codecs/max98371.c b/sound/soc/codecs/max98371.c index ce801489a86d..dfee05f985bd 100644 --- a/sound/soc/codecs/max98371.c +++ b/sound/soc/codecs/max98371.c | |||
@@ -154,10 +154,6 @@ static const DECLARE_TLV_DB_RANGE(max98371_gain_tlv, | |||
154 | 8, 10, TLV_DB_SCALE_ITEM(400, 100, 0) | 154 | 8, 10, TLV_DB_SCALE_ITEM(400, 100, 0) |
155 | ); | 155 | ); |
156 | 156 | ||
157 | static const DECLARE_TLV_DB_RANGE(max98371_noload_gain_tlv, | ||
158 | 0, 11, TLV_DB_SCALE_ITEM(950, 100, 0), | ||
159 | ); | ||
160 | |||
161 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -6300, 50, 1); | 157 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -6300, 50, 1); |
162 | 158 | ||
163 | static const struct snd_kcontrol_new max98371_snd_controls[] = { | 159 | static const struct snd_kcontrol_new max98371_snd_controls[] = { |
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 8c601a3ebc27..e609abcf3220 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <sound/pcm_params.h> | 12 | #include <sound/pcm_params.h> |
13 | #include <sound/soc.h> | 13 | #include <sound/soc.h> |
14 | #include <linux/gpio.h> | 14 | #include <linux/gpio.h> |
15 | #include <linux/of.h> | ||
15 | #include <linux/of_gpio.h> | 16 | #include <linux/of_gpio.h> |
16 | #include <sound/tlv.h> | 17 | #include <sound/tlv.h> |
17 | #include "max98373.h" | 18 | #include "max98373.h" |
@@ -901,6 +902,17 @@ static void max98373_slot_config(struct i2c_client *i2c, | |||
901 | else | 902 | else |
902 | max98373->i_slot = 1; | 903 | max98373->i_slot = 1; |
903 | 904 | ||
905 | max98373->reset_gpio = of_get_named_gpio(dev->of_node, | ||
906 | "maxim,reset-gpio", 0); | ||
907 | if (!gpio_is_valid(max98373->reset_gpio)) { | ||
908 | dev_err(dev, "Looking up %s property in node %s failed %d\n", | ||
909 | "maxim,reset-gpio", dev->of_node->full_name, | ||
910 | max98373->reset_gpio); | ||
911 | } else { | ||
912 | dev_dbg(dev, "maxim,reset-gpio=%d", | ||
913 | max98373->reset_gpio); | ||
914 | } | ||
915 | |||
904 | if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value)) | 916 | if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value)) |
905 | max98373->spkfb_slot = value & 0xF; | 917 | max98373->spkfb_slot = value & 0xF; |
906 | else | 918 | else |
@@ -929,7 +941,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c, | |||
929 | else | 941 | else |
930 | max98373->interleave_mode = false; | 942 | max98373->interleave_mode = false; |
931 | 943 | ||
932 | |||
933 | /* regmap initialization */ | 944 | /* regmap initialization */ |
934 | max98373->regmap | 945 | max98373->regmap |
935 | = devm_regmap_init_i2c(i2c, &max98373_regmap); | 946 | = devm_regmap_init_i2c(i2c, &max98373_regmap); |
@@ -940,6 +951,24 @@ static int max98373_i2c_probe(struct i2c_client *i2c, | |||
940 | return ret; | 951 | return ret; |
941 | } | 952 | } |
942 | 953 | ||
954 | /* voltage/current slot & gpio configuration */ | ||
955 | max98373_slot_config(i2c, max98373); | ||
956 | |||
957 | /* Power on device */ | ||
958 | if (gpio_is_valid(max98373->reset_gpio)) { | ||
959 | ret = gpio_request(max98373->reset_gpio, "MAX98373_RESET"); | ||
960 | if (ret) { | ||
961 | dev_err(&i2c->dev, "%s: Failed to request gpio %d\n", | ||
962 | __func__, max98373->reset_gpio); | ||
963 | gpio_free(max98373->reset_gpio); | ||
964 | return -EINVAL; | ||
965 | } | ||
966 | gpio_direction_output(max98373->reset_gpio, 0); | ||
967 | msleep(50); | ||
968 | gpio_direction_output(max98373->reset_gpio, 1); | ||
969 | msleep(20); | ||
970 | } | ||
971 | |||
943 | /* Check Revision ID */ | 972 | /* Check Revision ID */ |
944 | ret = regmap_read(max98373->regmap, | 973 | ret = regmap_read(max98373->regmap, |
945 | MAX98373_R21FF_REV_ID, ®); | 974 | MAX98373_R21FF_REV_ID, ®); |
@@ -950,9 +979,6 @@ static int max98373_i2c_probe(struct i2c_client *i2c, | |||
950 | } | 979 | } |
951 | dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); | 980 | dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); |
952 | 981 | ||
953 | /* voltage/current slot configuration */ | ||
954 | max98373_slot_config(i2c, max98373); | ||
955 | |||
956 | /* codec registeration */ | 982 | /* codec registeration */ |
957 | ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, | 983 | ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373, |
958 | max98373_dai, ARRAY_SIZE(max98373_dai)); | 984 | max98373_dai, ARRAY_SIZE(max98373_dai)); |
diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index a59e51355a84..63dae8be7105 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h | |||
@@ -205,6 +205,7 @@ | |||
205 | 205 | ||
206 | struct max98373_priv { | 206 | struct max98373_priv { |
207 | struct regmap *regmap; | 207 | struct regmap *regmap; |
208 | int reset_gpio; | ||
208 | unsigned int v_slot; | 209 | unsigned int v_slot; |
209 | unsigned int i_slot; | 210 | unsigned int i_slot; |
210 | unsigned int spkfb_slot; | 211 | unsigned int spkfb_slot; |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index f50ee8f5fe93..6f43748f9239 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
@@ -27,19 +27,6 @@ struct max9850_priv { | |||
27 | unsigned int sysclk; | 27 | unsigned int sysclk; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | /* max9850 register cache */ | ||
31 | static const struct reg_default max9850_reg[] = { | ||
32 | { 2, 0x0c }, | ||
33 | { 3, 0x00 }, | ||
34 | { 4, 0x00 }, | ||
35 | { 5, 0x00 }, | ||
36 | { 6, 0x00 }, | ||
37 | { 7, 0x00 }, | ||
38 | { 8, 0x00 }, | ||
39 | { 9, 0x00 }, | ||
40 | { 10, 0x00 }, | ||
41 | }; | ||
42 | |||
43 | /* these registers are not used at the moment but provided for the sake of | 30 | /* these registers are not used at the moment but provided for the sake of |
44 | * completeness */ | 31 | * completeness */ |
45 | static bool max9850_volatile_register(struct device *dev, unsigned int reg) | 32 | static bool max9850_volatile_register(struct device *dev, unsigned int reg) |
diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c index 818c0301fb29..c4dfa8ab1d49 100644 --- a/sound/soc/codecs/max98926.c +++ b/sound/soc/codecs/max98926.c | |||
@@ -20,15 +20,6 @@ static const char * const max98926_boost_voltage_txt[] = { | |||
20 | "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V" | 20 | "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V" |
21 | }; | 21 | }; |
22 | 22 | ||
23 | static const char * const max98926_boost_current_txt[] = { | ||
24 | "0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0", | ||
25 | "2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4" | ||
26 | }; | ||
27 | |||
28 | static const char *const max98926_dai_txt[] = { | ||
29 | "Left", "Right", "LeftRight", "LeftRightDiv2", | ||
30 | }; | ||
31 | |||
32 | static const char *const max98926_pdm_ch_text[] = { | 23 | static const char *const max98926_pdm_ch_text[] = { |
33 | "Current", "Voltage", | 24 | "Current", "Voltage", |
34 | }; | 25 | }; |
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 3abd27893ce6..55823bc95d06 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c | |||
@@ -56,7 +56,6 @@ static const DECLARE_TLV_DB_SCALE(alclvl, -2250, 150, 0); | |||
56 | static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0); | 56 | static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0); |
57 | static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0); | 57 | static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0); |
58 | static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0); | 58 | static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0); |
59 | static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); | ||
60 | 59 | ||
61 | static const char * const ml26124_companding[] = {"16bit PCM", "u-law", | 60 | static const char * const ml26124_companding[] = {"16bit PCM", "u-law", |
62 | "A-law"}; | 61 | "A-law"}; |
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 368b6c09474b..667e9f73aba3 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c | |||
@@ -1185,10 +1185,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) | |||
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | irq = platform_get_irq_byname(pdev, "mbhc_switch_int"); | 1187 | irq = platform_get_irq_byname(pdev, "mbhc_switch_int"); |
1188 | if (irq < 0) { | 1188 | if (irq < 0) |
1189 | dev_err(dev, "failed to get mbhc switch irq\n"); | ||
1190 | return irq; | 1189 | return irq; |
1191 | } | ||
1192 | 1190 | ||
1193 | ret = devm_request_threaded_irq(dev, irq, NULL, | 1191 | ret = devm_request_threaded_irq(dev, irq, NULL, |
1194 | pm8916_mbhc_switch_irq_handler, | 1192 | pm8916_mbhc_switch_irq_handler, |
@@ -1200,10 +1198,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) | |||
1200 | 1198 | ||
1201 | if (priv->mbhc_btn_enabled) { | 1199 | if (priv->mbhc_btn_enabled) { |
1202 | irq = platform_get_irq_byname(pdev, "mbhc_but_press_det"); | 1200 | irq = platform_get_irq_byname(pdev, "mbhc_but_press_det"); |
1203 | if (irq < 0) { | 1201 | if (irq < 0) |
1204 | dev_err(dev, "failed to get button press irq\n"); | ||
1205 | return irq; | 1202 | return irq; |
1206 | } | ||
1207 | 1203 | ||
1208 | ret = devm_request_threaded_irq(dev, irq, NULL, | 1204 | ret = devm_request_threaded_irq(dev, irq, NULL, |
1209 | mbhc_btn_press_irq_handler, | 1205 | mbhc_btn_press_irq_handler, |
@@ -1214,10 +1210,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) | |||
1214 | dev_err(dev, "cannot request mbhc button press irq\n"); | 1210 | dev_err(dev, "cannot request mbhc button press irq\n"); |
1215 | 1211 | ||
1216 | irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det"); | 1212 | irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det"); |
1217 | if (irq < 0) { | 1213 | if (irq < 0) |
1218 | dev_err(dev, "failed to get button release irq\n"); | ||
1219 | return irq; | 1214 | return irq; |
1220 | } | ||
1221 | 1215 | ||
1222 | ret = devm_request_threaded_irq(dev, irq, NULL, | 1216 | ret = devm_request_threaded_irq(dev, irq, NULL, |
1223 | mbhc_btn_release_irq_handler, | 1217 | mbhc_btn_release_irq_handler, |
diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index 1db7e43ec203..9fa5d44fdc79 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c | |||
@@ -1143,7 +1143,6 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev) | |||
1143 | struct msm8916_wcd_digital_priv *priv; | 1143 | struct msm8916_wcd_digital_priv *priv; |
1144 | struct device *dev = &pdev->dev; | 1144 | struct device *dev = &pdev->dev; |
1145 | void __iomem *base; | 1145 | void __iomem *base; |
1146 | struct resource *mem_res; | ||
1147 | struct regmap *digital_map; | 1146 | struct regmap *digital_map; |
1148 | int ret; | 1147 | int ret; |
1149 | 1148 | ||
@@ -1151,8 +1150,7 @@ static int msm8916_wcd_digital_probe(struct platform_device *pdev) | |||
1151 | if (!priv) | 1150 | if (!priv) |
1152 | return -ENOMEM; | 1151 | return -ENOMEM; |
1153 | 1152 | ||
1154 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1153 | base = devm_platform_ioremap_resource(pdev, 0); |
1155 | base = devm_ioremap_resource(&pdev->dev, mem_res); | ||
1156 | if (IS_ERR(base)) | 1154 | if (IS_ERR(base)) |
1157 | return PTR_ERR(base); | 1155 | return PTR_ERR(base); |
1158 | 1156 | ||
diff --git a/sound/soc/codecs/mt6351.c b/sound/soc/codecs/mt6351.c index 4b3ce01c5a93..5c0536eb1044 100644 --- a/sound/soc/codecs/mt6351.c +++ b/sound/soc/codecs/mt6351.c | |||
@@ -1066,11 +1066,6 @@ static int mt_mic_bias_2_event(struct snd_soc_dapm_widget *w, | |||
1066 | return 0; | 1066 | return 0; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | /* DAPM Kcontrols */ | ||
1070 | static const struct snd_kcontrol_new mt_lineout_control = | ||
1071 | SOC_DAPM_SINGLE("Switch", MT6351_AUDDEC_ANA_CON3, | ||
1072 | RG_AUDLOLPWRUP_VAUDP32_BIT, 1, 0); | ||
1073 | |||
1074 | /* DAPM Widgets */ | 1069 | /* DAPM Widgets */ |
1075 | static const struct snd_soc_dapm_widget mt6351_dapm_widgets[] = { | 1070 | static const struct snd_soc_dapm_widget mt6351_dapm_widgets[] = { |
1076 | /* Digital Clock */ | 1071 | /* Digital Clock */ |
diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 50b3fc5457ea..bb737fd678cc 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c | |||
@@ -1730,6 +1730,10 @@ static int mt6358_dmic_enable(struct mt6358_priv *priv) | |||
1730 | 1730 | ||
1731 | /* UL turn on */ | 1731 | /* UL turn on */ |
1732 | regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003); | 1732 | regmap_write(priv->regmap, MT6358_AFE_UL_SRC_CON0_L, 0x0003); |
1733 | |||
1734 | /* Prevent pop noise form dmic hw */ | ||
1735 | msleep(100); | ||
1736 | |||
1733 | return 0; | 1737 | return 0; |
1734 | } | 1738 | } |
1735 | 1739 | ||
@@ -2255,10 +2259,8 @@ static struct snd_soc_dai_driver mt6358_dai_driver[] = { | |||
2255 | }, | 2259 | }, |
2256 | }; | 2260 | }; |
2257 | 2261 | ||
2258 | static int mt6358_codec_init_reg(struct mt6358_priv *priv) | 2262 | static void mt6358_codec_init_reg(struct mt6358_priv *priv) |
2259 | { | 2263 | { |
2260 | int ret = 0; | ||
2261 | |||
2262 | /* Disable HeadphoneL/HeadphoneR short circuit protection */ | 2264 | /* Disable HeadphoneL/HeadphoneR short circuit protection */ |
2263 | regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON0, | 2265 | regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON0, |
2264 | RG_AUDHPLSCDISABLE_VAUDP15_MASK_SFT, | 2266 | RG_AUDHPLSCDISABLE_VAUDP15_MASK_SFT, |
@@ -2285,8 +2287,6 @@ static int mt6358_codec_init_reg(struct mt6358_priv *priv) | |||
2285 | /* set gpio */ | 2287 | /* set gpio */ |
2286 | playback_gpio_reset(priv); | 2288 | playback_gpio_reset(priv); |
2287 | capture_gpio_reset(priv); | 2289 | capture_gpio_reset(priv); |
2288 | |||
2289 | return ret; | ||
2290 | } | 2290 | } |
2291 | 2291 | ||
2292 | static int mt6358_codec_probe(struct snd_soc_component *cmpnt) | 2292 | static int mt6358_codec_probe(struct snd_soc_component *cmpnt) |
diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index f1104d7d6426..50ed86d45c26 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c | |||
@@ -44,18 +44,25 @@ static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = { | |||
44 | "VCCDA2" | 44 | "VCCDA2" |
45 | }; | 45 | }; |
46 | 46 | ||
47 | #define PCM3168A_DAI_DAC 0 | ||
48 | #define PCM3168A_DAI_ADC 1 | ||
49 | |||
50 | /* ADC/DAC side parameters */ | ||
51 | struct pcm3168a_io_params { | ||
52 | bool master_mode; | ||
53 | unsigned int fmt; | ||
54 | int tdm_slots; | ||
55 | u32 tdm_mask; | ||
56 | int slot_width; | ||
57 | }; | ||
58 | |||
47 | struct pcm3168a_priv { | 59 | struct pcm3168a_priv { |
48 | struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES]; | 60 | struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES]; |
49 | struct regmap *regmap; | 61 | struct regmap *regmap; |
50 | struct clk *scki; | 62 | struct clk *scki; |
51 | bool adc_master_mode; | ||
52 | bool dac_master_mode; | ||
53 | unsigned long sysclk; | 63 | unsigned long sysclk; |
54 | unsigned int adc_fmt; | 64 | |
55 | unsigned int dac_fmt; | 65 | struct pcm3168a_io_params io_params[2]; |
56 | int tdm_slots; | ||
57 | u32 tdm_mask[2]; | ||
58 | int slot_width; | ||
59 | }; | 66 | }; |
60 | 67 | ||
61 | static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" }; | 68 | static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" }; |
@@ -263,7 +270,7 @@ static unsigned int pcm3168a_scki_ratios[] = { | |||
263 | #define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios) | 270 | #define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios) |
264 | #define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2) | 271 | #define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2) |
265 | 272 | ||
266 | #define PCM1368A_MAX_SYSCLK 36864000 | 273 | #define PCM3168A_MAX_SYSCLK 36864000 |
267 | 274 | ||
268 | static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a) | 275 | static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a) |
269 | { | 276 | { |
@@ -296,7 +303,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, | |||
296 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component); | 303 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component); |
297 | int ret; | 304 | int ret; |
298 | 305 | ||
299 | if (freq > PCM1368A_MAX_SYSCLK) | 306 | if (freq > PCM3168A_MAX_SYSCLK) |
300 | return -EINVAL; | 307 | return -EINVAL; |
301 | 308 | ||
302 | ret = clk_set_rate(pcm3168a->scki, freq); | 309 | ret = clk_set_rate(pcm3168a->scki, freq); |
@@ -308,8 +315,7 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, | |||
308 | return 0; | 315 | return 0; |
309 | } | 316 | } |
310 | 317 | ||
311 | static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, | 318 | static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format) |
312 | unsigned int format, bool dac) | ||
313 | { | 319 | { |
314 | struct snd_soc_component *component = dai->component; | 320 | struct snd_soc_component *component = dai->component; |
315 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | 321 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); |
@@ -356,43 +362,31 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, | |||
356 | return -EINVAL; | 362 | return -EINVAL; |
357 | } | 363 | } |
358 | 364 | ||
359 | if (dac) { | 365 | if (dai->id == PCM3168A_DAI_DAC) { |
360 | reg = PCM3168A_DAC_PWR_MST_FMT; | 366 | reg = PCM3168A_DAC_PWR_MST_FMT; |
361 | mask = PCM3168A_DAC_FMT_MASK; | 367 | mask = PCM3168A_DAC_FMT_MASK; |
362 | shift = PCM3168A_DAC_FMT_SHIFT; | 368 | shift = PCM3168A_DAC_FMT_SHIFT; |
363 | pcm3168a->dac_master_mode = master_mode; | ||
364 | pcm3168a->dac_fmt = fmt; | ||
365 | } else { | 369 | } else { |
366 | reg = PCM3168A_ADC_MST_FMT; | 370 | reg = PCM3168A_ADC_MST_FMT; |
367 | mask = PCM3168A_ADC_FMTAD_MASK; | 371 | mask = PCM3168A_ADC_FMTAD_MASK; |
368 | shift = PCM3168A_ADC_FMTAD_SHIFT; | 372 | shift = PCM3168A_ADC_FMTAD_SHIFT; |
369 | pcm3168a->adc_master_mode = master_mode; | ||
370 | pcm3168a->adc_fmt = fmt; | ||
371 | } | 373 | } |
372 | 374 | ||
375 | pcm3168a->io_params[dai->id].master_mode = master_mode; | ||
376 | pcm3168a->io_params[dai->id].fmt = fmt; | ||
377 | |||
373 | regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); | 378 | regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); |
374 | 379 | ||
375 | return 0; | 380 | return 0; |
376 | } | 381 | } |
377 | 382 | ||
378 | static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai, | ||
379 | unsigned int format) | ||
380 | { | ||
381 | return pcm3168a_set_dai_fmt(dai, format, true); | ||
382 | } | ||
383 | |||
384 | static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai, | ||
385 | unsigned int format) | ||
386 | { | ||
387 | return pcm3168a_set_dai_fmt(dai, format, false); | ||
388 | } | ||
389 | |||
390 | static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | 383 | static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
391 | unsigned int rx_mask, int slots, | 384 | unsigned int rx_mask, int slots, |
392 | int slot_width) | 385 | int slot_width) |
393 | { | 386 | { |
394 | struct snd_soc_component *component = dai->component; | 387 | struct snd_soc_component *component = dai->component; |
395 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | 388 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); |
389 | struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; | ||
396 | 390 | ||
397 | if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) { | 391 | if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) { |
398 | dev_err(component->dev, | 392 | dev_err(component->dev, |
@@ -408,22 +402,13 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
408 | return -EINVAL; | 402 | return -EINVAL; |
409 | } | 403 | } |
410 | 404 | ||
411 | if (pcm3168a->tdm_slots && pcm3168a->tdm_slots != slots) { | 405 | io_params->tdm_slots = slots; |
412 | dev_err(component->dev, "Not matching slots %d vs %d\n", | 406 | io_params->slot_width = slot_width; |
413 | pcm3168a->tdm_slots, slots); | 407 | /* Ignore the not relevant mask for the DAI/direction */ |
414 | return -EINVAL; | 408 | if (dai->id == PCM3168A_DAI_DAC) |
415 | } | 409 | io_params->tdm_mask = tx_mask; |
416 | 410 | else | |
417 | if (pcm3168a->slot_width && pcm3168a->slot_width != slot_width) { | 411 | io_params->tdm_mask = rx_mask; |
418 | dev_err(component->dev, "Not matching slot_width %d vs %d\n", | ||
419 | pcm3168a->slot_width, slot_width); | ||
420 | return -EINVAL; | ||
421 | } | ||
422 | |||
423 | pcm3168a->tdm_slots = slots; | ||
424 | pcm3168a->slot_width = slot_width; | ||
425 | pcm3168a->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; | ||
426 | pcm3168a->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; | ||
427 | 412 | ||
428 | return 0; | 413 | return 0; |
429 | } | 414 | } |
@@ -434,7 +419,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
434 | { | 419 | { |
435 | struct snd_soc_component *component = dai->component; | 420 | struct snd_soc_component *component = dai->component; |
436 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | 421 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); |
437 | bool tx, master_mode; | 422 | struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id]; |
423 | bool master_mode; | ||
438 | u32 val, mask, shift, reg; | 424 | u32 val, mask, shift, reg; |
439 | unsigned int rate, fmt, ratio, max_ratio; | 425 | unsigned int rate, fmt, ratio, max_ratio; |
440 | unsigned int tdm_slots; | 426 | unsigned int tdm_slots; |
@@ -444,23 +430,21 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
444 | 430 | ||
445 | ratio = pcm3168a->sysclk / rate; | 431 | ratio = pcm3168a->sysclk / rate; |
446 | 432 | ||
447 | tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 433 | if (dai->id == PCM3168A_DAI_DAC) { |
448 | if (tx) { | ||
449 | max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC; | 434 | max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC; |
450 | reg = PCM3168A_DAC_PWR_MST_FMT; | 435 | reg = PCM3168A_DAC_PWR_MST_FMT; |
451 | mask = PCM3168A_DAC_MSDA_MASK; | 436 | mask = PCM3168A_DAC_MSDA_MASK; |
452 | shift = PCM3168A_DAC_MSDA_SHIFT; | 437 | shift = PCM3168A_DAC_MSDA_SHIFT; |
453 | master_mode = pcm3168a->dac_master_mode; | ||
454 | fmt = pcm3168a->dac_fmt; | ||
455 | } else { | 438 | } else { |
456 | max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC; | 439 | max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC; |
457 | reg = PCM3168A_ADC_MST_FMT; | 440 | reg = PCM3168A_ADC_MST_FMT; |
458 | mask = PCM3168A_ADC_MSAD_MASK; | 441 | mask = PCM3168A_ADC_MSAD_MASK; |
459 | shift = PCM3168A_ADC_MSAD_SHIFT; | 442 | shift = PCM3168A_ADC_MSAD_SHIFT; |
460 | master_mode = pcm3168a->adc_master_mode; | ||
461 | fmt = pcm3168a->adc_fmt; | ||
462 | } | 443 | } |
463 | 444 | ||
445 | master_mode = io_params->master_mode; | ||
446 | fmt = io_params->fmt; | ||
447 | |||
464 | for (i = 0; i < max_ratio; i++) { | 448 | for (i = 0; i < max_ratio; i++) { |
465 | if (pcm3168a_scki_ratios[i] == ratio) | 449 | if (pcm3168a_scki_ratios[i] == ratio) |
466 | break; | 450 | break; |
@@ -471,8 +455,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
471 | return -EINVAL; | 455 | return -EINVAL; |
472 | } | 456 | } |
473 | 457 | ||
474 | if (pcm3168a->slot_width) | 458 | if (io_params->slot_width) |
475 | slot_width = pcm3168a->slot_width; | 459 | slot_width = io_params->slot_width; |
476 | else | 460 | else |
477 | slot_width = params_width(params); | 461 | slot_width = params_width(params); |
478 | 462 | ||
@@ -497,8 +481,8 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
497 | return -EINVAL; | 481 | return -EINVAL; |
498 | } | 482 | } |
499 | 483 | ||
500 | if (pcm3168a->tdm_slots) | 484 | if (io_params->tdm_slots) |
501 | tdm_slots = pcm3168a->tdm_slots; | 485 | tdm_slots = io_params->tdm_slots; |
502 | else | 486 | else |
503 | tdm_slots = params_channels(params); | 487 | tdm_slots = params_channels(params); |
504 | 488 | ||
@@ -534,7 +518,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
534 | 518 | ||
535 | regmap_update_bits(pcm3168a->regmap, reg, mask, val); | 519 | regmap_update_bits(pcm3168a->regmap, reg, mask, val); |
536 | 520 | ||
537 | if (tx) { | 521 | if (dai->id == PCM3168A_DAI_DAC) { |
538 | mask = PCM3168A_DAC_FMT_MASK; | 522 | mask = PCM3168A_DAC_FMT_MASK; |
539 | shift = PCM3168A_DAC_FMT_SHIFT; | 523 | shift = PCM3168A_DAC_FMT_SHIFT; |
540 | } else { | 524 | } else { |
@@ -552,20 +536,13 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
552 | { | 536 | { |
553 | struct snd_soc_component *component = dai->component; | 537 | struct snd_soc_component *component = dai->component; |
554 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | 538 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); |
555 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
556 | unsigned int fmt; | ||
557 | unsigned int sample_min; | 539 | unsigned int sample_min; |
558 | unsigned int channel_max; | 540 | unsigned int channel_max; |
559 | unsigned int channel_maxs[] = { | 541 | unsigned int channel_maxs[] = { |
560 | 6, /* rx */ | 542 | 8, /* DAC */ |
561 | 8 /* tx */ | 543 | 6 /* ADC */ |
562 | }; | 544 | }; |
563 | 545 | ||
564 | if (tx) | ||
565 | fmt = pcm3168a->dac_fmt; | ||
566 | else | ||
567 | fmt = pcm3168a->adc_fmt; | ||
568 | |||
569 | /* | 546 | /* |
570 | * Available Data Bits | 547 | * Available Data Bits |
571 | * | 548 | * |
@@ -578,7 +555,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
578 | * I2S | 555 | * I2S |
579 | * LEFT_J | 556 | * LEFT_J |
580 | */ | 557 | */ |
581 | switch (fmt) { | 558 | switch (pcm3168a->io_params[dai->id].fmt) { |
582 | case PCM3168A_FMT_RIGHT_J: | 559 | case PCM3168A_FMT_RIGHT_J: |
583 | sample_min = 16; | 560 | sample_min = 16; |
584 | channel_max = 2; | 561 | channel_max = 2; |
@@ -588,7 +565,7 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
588 | case PCM3168A_FMT_DSP_A: | 565 | case PCM3168A_FMT_DSP_A: |
589 | case PCM3168A_FMT_DSP_B: | 566 | case PCM3168A_FMT_DSP_B: |
590 | sample_min = 24; | 567 | sample_min = 24; |
591 | channel_max = channel_maxs[tx]; | 568 | channel_max = channel_maxs[dai->id]; |
592 | break; | 569 | break; |
593 | default: | 570 | default: |
594 | sample_min = 24; | 571 | sample_min = 24; |
@@ -599,32 +576,29 @@ static int pcm3168a_startup(struct snd_pcm_substream *substream, | |||
599 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | 576 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, |
600 | sample_min, 32); | 577 | sample_min, 32); |
601 | 578 | ||
579 | /* Allow all channels in multi DIN/DOUT mode */ | ||
580 | if (pcm3168a->io_params[dai->id].tdm_slots == 2) | ||
581 | channel_max = channel_maxs[dai->id]; | ||
582 | |||
602 | snd_pcm_hw_constraint_minmax(substream->runtime, | 583 | snd_pcm_hw_constraint_minmax(substream->runtime, |
603 | SNDRV_PCM_HW_PARAM_CHANNELS, | 584 | SNDRV_PCM_HW_PARAM_CHANNELS, |
604 | 2, channel_max); | 585 | 2, channel_max); |
605 | 586 | ||
606 | return 0; | 587 | return 0; |
607 | } | 588 | } |
608 | static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { | 589 | static const struct snd_soc_dai_ops pcm3168a_dai_ops = { |
609 | .startup = pcm3168a_startup, | 590 | .startup = pcm3168a_startup, |
610 | .set_fmt = pcm3168a_set_dai_fmt_dac, | 591 | .set_fmt = pcm3168a_set_dai_fmt, |
611 | .set_sysclk = pcm3168a_set_dai_sysclk, | 592 | .set_sysclk = pcm3168a_set_dai_sysclk, |
612 | .hw_params = pcm3168a_hw_params, | 593 | .hw_params = pcm3168a_hw_params, |
613 | .digital_mute = pcm3168a_digital_mute, | 594 | .digital_mute = pcm3168a_digital_mute, |
614 | .set_tdm_slot = pcm3168a_set_tdm_slot, | 595 | .set_tdm_slot = pcm3168a_set_tdm_slot, |
615 | }; | 596 | }; |
616 | 597 | ||
617 | static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = { | ||
618 | .startup = pcm3168a_startup, | ||
619 | .set_fmt = pcm3168a_set_dai_fmt_adc, | ||
620 | .set_sysclk = pcm3168a_set_dai_sysclk, | ||
621 | .hw_params = pcm3168a_hw_params, | ||
622 | .set_tdm_slot = pcm3168a_set_tdm_slot, | ||
623 | }; | ||
624 | |||
625 | static struct snd_soc_dai_driver pcm3168a_dais[] = { | 598 | static struct snd_soc_dai_driver pcm3168a_dais[] = { |
626 | { | 599 | { |
627 | .name = "pcm3168a-dac", | 600 | .name = "pcm3168a-dac", |
601 | .id = PCM3168A_DAI_DAC, | ||
628 | .playback = { | 602 | .playback = { |
629 | .stream_name = "Playback", | 603 | .stream_name = "Playback", |
630 | .channels_min = 1, | 604 | .channels_min = 1, |
@@ -632,10 +606,11 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = { | |||
632 | .rates = SNDRV_PCM_RATE_8000_192000, | 606 | .rates = SNDRV_PCM_RATE_8000_192000, |
633 | .formats = PCM3168A_FORMATS | 607 | .formats = PCM3168A_FORMATS |
634 | }, | 608 | }, |
635 | .ops = &pcm3168a_dac_dai_ops | 609 | .ops = &pcm3168a_dai_ops |
636 | }, | 610 | }, |
637 | { | 611 | { |
638 | .name = "pcm3168a-adc", | 612 | .name = "pcm3168a-adc", |
613 | .id = PCM3168A_DAI_ADC, | ||
639 | .capture = { | 614 | .capture = { |
640 | .stream_name = "Capture", | 615 | .stream_name = "Capture", |
641 | .channels_min = 1, | 616 | .channels_min = 1, |
@@ -643,7 +618,7 @@ static struct snd_soc_dai_driver pcm3168a_dais[] = { | |||
643 | .rates = SNDRV_PCM_RATE_8000_96000, | 618 | .rates = SNDRV_PCM_RATE_8000_96000, |
644 | .formats = PCM3168A_FORMATS | 619 | .formats = PCM3168A_FORMATS |
645 | }, | 620 | }, |
646 | .ops = &pcm3168a_adc_dai_ops | 621 | .ops = &pcm3168a_dai_ops |
647 | }, | 622 | }, |
648 | }; | 623 | }; |
649 | 624 | ||
diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c index 24f8f86d58e9..287c962ba00d 100644 --- a/sound/soc/codecs/rk3328_codec.c +++ b/sound/soc/codecs/rk3328_codec.c | |||
@@ -432,7 +432,6 @@ static int rk3328_platform_probe(struct platform_device *pdev) | |||
432 | { | 432 | { |
433 | struct device_node *rk3328_np = pdev->dev.of_node; | 433 | struct device_node *rk3328_np = pdev->dev.of_node; |
434 | struct rk3328_codec_priv *rk3328; | 434 | struct rk3328_codec_priv *rk3328; |
435 | struct resource *res; | ||
436 | struct regmap *grf; | 435 | struct regmap *grf; |
437 | void __iomem *base; | 436 | void __iomem *base; |
438 | int ret = 0; | 437 | int ret = 0; |
@@ -482,8 +481,7 @@ static int rk3328_platform_probe(struct platform_device *pdev) | |||
482 | return ret; | 481 | return ret; |
483 | } | 482 | } |
484 | 483 | ||
485 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 484 | base = devm_platform_ioremap_resource(pdev, 0); |
486 | base = devm_ioremap_resource(&pdev->dev, res); | ||
487 | if (IS_ERR(base)) | 485 | if (IS_ERR(base)) |
488 | return PTR_ERR(base); | 486 | return PTR_ERR(base); |
489 | 487 | ||
diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index ed28250d5e34..be1e276e3631 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c | |||
@@ -978,9 +978,6 @@ static bool rt1011_readable_register(struct device *dev, unsigned int reg) | |||
978 | } | 978 | } |
979 | } | 979 | } |
980 | 980 | ||
981 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9435, 37, 0); | ||
982 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1739, 37, 0); | ||
983 | |||
984 | static const char * const rt1011_din_source_select[] = { | 981 | static const char * const rt1011_din_source_select[] = { |
985 | "Left", | 982 | "Left", |
986 | "Right", | 983 | "Right", |
@@ -1029,6 +1026,8 @@ static const char * const rt1011_tdm_adc_swap_select[] = { | |||
1029 | 1026 | ||
1030 | static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum, RT1011_TDM1_SET_3, 6, | 1027 | static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc1_1_enum, RT1011_TDM1_SET_3, 6, |
1031 | rt1011_tdm_adc_swap_select); | 1028 | rt1011_tdm_adc_swap_select); |
1029 | static SOC_ENUM_SINGLE_DECL(rt1011_tdm_adc2_1_enum, RT1011_TDM1_SET_3, 4, | ||
1030 | rt1011_tdm_adc_swap_select); | ||
1032 | 1031 | ||
1033 | static void rt1011_reset(struct regmap *regmap) | 1032 | static void rt1011_reset(struct regmap *regmap) |
1034 | { | 1033 | { |
@@ -1223,7 +1222,10 @@ static int rt1011_bq_drc_info(struct snd_kcontrol *kcontrol, | |||
1223 | static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol, | 1222 | static int rt1011_r0_cali_get(struct snd_kcontrol *kcontrol, |
1224 | struct snd_ctl_elem_value *ucontrol) | 1223 | struct snd_ctl_elem_value *ucontrol) |
1225 | { | 1224 | { |
1226 | ucontrol->value.integer.value[0] = 0; | 1225 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
1226 | struct rt1011_priv *rt1011 = snd_soc_component_get_drvdata(component); | ||
1227 | |||
1228 | ucontrol->value.integer.value[0] = rt1011->cali_done; | ||
1227 | 1229 | ||
1228 | return 0; | 1230 | return 0; |
1229 | } | 1231 | } |
@@ -1237,6 +1239,7 @@ static int rt1011_r0_cali_put(struct snd_kcontrol *kcontrol, | |||
1237 | if (!component->card->instantiated) | 1239 | if (!component->card->instantiated) |
1238 | return 0; | 1240 | return 0; |
1239 | 1241 | ||
1242 | rt1011->cali_done = 0; | ||
1240 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF && | 1243 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF && |
1241 | ucontrol->value.integer.value[0]) | 1244 | ucontrol->value.integer.value[0]) |
1242 | rt1011_calibrate(rt1011, 1); | 1245 | rt1011_calibrate(rt1011, 1); |
@@ -1333,7 +1336,8 @@ static const struct snd_kcontrol_new rt1011_snd_controls[] = { | |||
1333 | /* TDM1 Data Out Selection */ | 1336 | /* TDM1 Data Out Selection */ |
1334 | SOC_ENUM("TDM1 DOUT Source", rt1011_tdm1_adc1_dat_enum), | 1337 | SOC_ENUM("TDM1 DOUT Source", rt1011_tdm1_adc1_dat_enum), |
1335 | SOC_ENUM("TDM1 DOUT Location", rt1011_tdm1_adc1_loc_enum), | 1338 | SOC_ENUM("TDM1 DOUT Location", rt1011_tdm1_adc1_loc_enum), |
1336 | SOC_ENUM("TDM1 ADCDAT Swap Select", rt1011_tdm_adc1_1_enum), | 1339 | SOC_ENUM("TDM1 ADC1DAT Swap Select", rt1011_tdm_adc1_1_enum), |
1340 | SOC_ENUM("TDM1 ADC2DAT Swap Select", rt1011_tdm_adc2_1_enum), | ||
1337 | 1341 | ||
1338 | /* Data Out Mode */ | 1342 | /* Data Out Mode */ |
1339 | SOC_ENUM("I2S ADC DOUT Mode", rt1011_adc_dout_mode_enum), | 1343 | SOC_ENUM("I2S ADC DOUT Mode", rt1011_adc_dout_mode_enum), |
@@ -1355,6 +1359,10 @@ static const struct snd_kcontrol_new rt1011_snd_controls[] = { | |||
1355 | SOC_SINGLE_EXT("R0 Calibration", SND_SOC_NOPM, 0, 1, 0, | 1359 | SOC_SINGLE_EXT("R0 Calibration", SND_SOC_NOPM, 0, 1, 0, |
1356 | rt1011_r0_cali_get, rt1011_r0_cali_put), | 1360 | rt1011_r0_cali_get, rt1011_r0_cali_put), |
1357 | RT1011_R0_LOAD("R0 Load Mode"), | 1361 | RT1011_R0_LOAD("R0 Load Mode"), |
1362 | |||
1363 | /* R0 temperature */ | ||
1364 | SOC_SINGLE("R0 Temperature", RT1011_STP_INITIAL_RESISTANCE_TEMP, | ||
1365 | 2, 255, 0), | ||
1358 | }; | 1366 | }; |
1359 | 1367 | ||
1360 | static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | 1368 | static int rt1011_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, |
@@ -1511,7 +1519,8 @@ static const struct snd_soc_dapm_route rt1011_dapm_routes[] = { | |||
1511 | 1519 | ||
1512 | static int rt1011_get_clk_info(int sclk, int rate) | 1520 | static int rt1011_get_clk_info(int sclk, int rate) |
1513 | { | 1521 | { |
1514 | int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | 1522 | int i; |
1523 | static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | ||
1515 | 1524 | ||
1516 | if (sclk <= 0 || rate <= 0) | 1525 | if (sclk <= 0 || rate <= 0) |
1517 | return -EINVAL; | 1526 | return -EINVAL; |
@@ -2139,6 +2148,7 @@ static int rt1011_calibrate(struct rt1011_priv *rt1011, unsigned char cali_flag) | |||
2139 | r0_factor = ((format / r0[0] * 100) / 128) | 2148 | r0_factor = ((format / r0[0] * 100) / 128) |
2140 | - (r0_integer * 100); | 2149 | - (r0_integer * 100); |
2141 | rt1011->r0_reg = r0[0]; | 2150 | rt1011->r0_reg = r0[0]; |
2151 | rt1011->cali_done = 1; | ||
2142 | dev_info(dev, "r0 resistance about %d.%02d ohm, reg=0x%X\n", | 2152 | dev_info(dev, "r0 resistance about %d.%02d ohm, reg=0x%X\n", |
2143 | r0_integer, r0_factor, r0[0]); | 2153 | r0_integer, r0_factor, r0[0]); |
2144 | } | 2154 | } |
@@ -2189,6 +2199,13 @@ static void rt1011_calibration_work(struct work_struct *work) | |||
2189 | 2199 | ||
2190 | rt1011_calibrate(rt1011, 1); | 2200 | rt1011_calibrate(rt1011, 1); |
2191 | 2201 | ||
2202 | /* | ||
2203 | * This flag should reset after booting. | ||
2204 | * The factory test will do calibration again and use this flag to check | ||
2205 | * whether the calibration completed | ||
2206 | */ | ||
2207 | rt1011->cali_done = 0; | ||
2208 | |||
2192 | /* initial */ | 2209 | /* initial */ |
2193 | rt1011_reg_init(component); | 2210 | rt1011_reg_init(component); |
2194 | } | 2211 | } |
diff --git a/sound/soc/codecs/rt1011.h b/sound/soc/codecs/rt1011.h index 98a38800c4df..2d65983f3d0f 100644 --- a/sound/soc/codecs/rt1011.h +++ b/sound/soc/codecs/rt1011.h | |||
@@ -227,6 +227,7 @@ | |||
227 | #define RT1011_STP_CALIB_RS_TEMP 0x152a | 227 | #define RT1011_STP_CALIB_RS_TEMP 0x152a |
228 | #define RT1011_INIT_RECIPROCAL_REG_24_16 0x1538 | 228 | #define RT1011_INIT_RECIPROCAL_REG_24_16 0x1538 |
229 | #define RT1011_INIT_RECIPROCAL_REG_15_0 0x1539 | 229 | #define RT1011_INIT_RECIPROCAL_REG_15_0 0x1539 |
230 | #define RT1011_STP_INITIAL_RESISTANCE_TEMP 0x153c | ||
230 | #define RT1011_STP_ALPHA_RECIPROCAL_MSB 0x153e | 231 | #define RT1011_STP_ALPHA_RECIPROCAL_MSB 0x153e |
231 | #define RT1011_SPK_RESISTANCE_1 0x1544 | 232 | #define RT1011_SPK_RESISTANCE_1 0x1544 |
232 | #define RT1011_SPK_RESISTANCE_2 0x1546 | 233 | #define RT1011_SPK_RESISTANCE_2 0x1546 |
@@ -665,7 +666,7 @@ struct rt1011_priv { | |||
665 | int pll_out; | 666 | int pll_out; |
666 | 667 | ||
667 | int bq_drc_set; | 668 | int bq_drc_set; |
668 | unsigned int r0_reg; | 669 | unsigned int r0_reg, cali_done; |
669 | int recv_spk_mode; | 670 | int recv_spk_mode; |
670 | }; | 671 | }; |
671 | 672 | ||
diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index 9909369483f0..e27742abfa76 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c | |||
@@ -608,7 +608,8 @@ static const struct snd_soc_dapm_route rt1305_dapm_routes[] = { | |||
608 | 608 | ||
609 | static int rt1305_get_clk_info(int sclk, int rate) | 609 | static int rt1305_get_clk_info(int sclk, int rate) |
610 | { | 610 | { |
611 | int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | 611 | int i; |
612 | static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | ||
612 | 613 | ||
613 | if (sclk <= 0 || rate <= 0) | 614 | if (sclk <= 0 || rate <= 0) |
614 | return -EINVAL; | 615 | return -EINVAL; |
diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index d673506c7c39..b75931a69a1c 100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c | |||
@@ -1,13 +1,10 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * rt1308.c -- RT1308 ALSA SoC amplifier component driver | 2 | // |
3 | * | 3 | // rt1308.c -- RT1308 ALSA SoC amplifier component driver |
4 | * Copyright 2019 Realtek Semiconductor Corp. | 4 | // |
5 | * Author: Derek Fang <derek.fang@realtek.com> | 5 | // Copyright 2019 Realtek Semiconductor Corp. |
6 | * | 6 | // Author: Derek Fang <derek.fang@realtek.com> |
7 | * This program is free software; you can redistribute it and/or modify | 7 | // |
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | 8 | ||
12 | #include <linux/module.h> | 9 | #include <linux/module.h> |
13 | #include <linux/moduleparam.h> | 10 | #include <linux/moduleparam.h> |
@@ -40,10 +37,10 @@ static const struct reg_sequence init_list[] = { | |||
40 | { RT1308_VREF, 0x18100000 }, | 37 | { RT1308_VREF, 0x18100000 }, |
41 | { RT1308_IV_SENSE, 0x87010000 }, | 38 | { RT1308_IV_SENSE, 0x87010000 }, |
42 | { RT1308_DUMMY_REG, 0x00000200 }, | 39 | { RT1308_DUMMY_REG, 0x00000200 }, |
43 | { RT1308_SIL_DET, 0x61c30000 }, | 40 | { RT1308_SIL_DET, 0xe1c30000 }, |
44 | { RT1308_DC_CAL_2, 0x00ffff00 }, | 41 | { RT1308_DC_CAL_2, 0x00ffff00 }, |
45 | { RT1308_CLK_DET, 0x01000000 }, | 42 | { RT1308_CLK_DET, 0x01000000 }, |
46 | { RT1308_POWER_STATUS, 0x00800000 }, | 43 | { RT1308_POWER_STATUS, 0x08800000 }, |
47 | { RT1308_DAC_SET, 0xafaf0700 }, | 44 | { RT1308_DAC_SET, 0xafaf0700 }, |
48 | 45 | ||
49 | }; | 46 | }; |
@@ -308,12 +305,13 @@ static int rt1308_classd_event(struct snd_soc_dapm_widget *w, | |||
308 | case SND_SOC_DAPM_POST_PMU: | 305 | case SND_SOC_DAPM_POST_PMU: |
309 | msleep(30); | 306 | msleep(30); |
310 | snd_soc_component_update_bits(component, RT1308_POWER_STATUS, | 307 | snd_soc_component_update_bits(component, RT1308_POWER_STATUS, |
311 | RT1308_POW_PDB_REG_BIT, RT1308_POW_PDB_REG_BIT); | 308 | RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, |
309 | RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT); | ||
312 | msleep(40); | 310 | msleep(40); |
313 | break; | 311 | break; |
314 | case SND_SOC_DAPM_PRE_PMD: | 312 | case SND_SOC_DAPM_PRE_PMD: |
315 | snd_soc_component_update_bits(component, RT1308_POWER_STATUS, | 313 | snd_soc_component_update_bits(component, RT1308_POWER_STATUS, |
316 | RT1308_POW_PDB_REG_BIT, 0); | 314 | RT1308_POW_PDB_REG_BIT | RT1308_POW_PDB_MN_BIT, 0); |
317 | usleep_range(150000, 200000); | 315 | usleep_range(150000, 200000); |
318 | break; | 316 | break; |
319 | 317 | ||
@@ -438,7 +436,8 @@ static const struct snd_soc_dapm_route rt1308_dapm_routes[] = { | |||
438 | 436 | ||
439 | static int rt1308_get_clk_info(int sclk, int rate) | 437 | static int rt1308_get_clk_info(int sclk, int rate) |
440 | { | 438 | { |
441 | int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | 439 | int i; |
440 | static const int pd[] = {1, 2, 3, 4, 6, 8, 12, 16}; | ||
442 | 441 | ||
443 | if (sclk <= 0 || rate <= 0) | 442 | if (sclk <= 0 || rate <= 0) |
444 | return -EINVAL; | 443 | return -EINVAL; |
@@ -808,33 +807,11 @@ static void rt1308_efuse(struct rt1308_priv *rt1308) | |||
808 | { | 807 | { |
809 | regmap_write(rt1308->regmap, RT1308_RESET, 0); | 808 | regmap_write(rt1308->regmap, RT1308_RESET, 0); |
810 | 809 | ||
811 | regmap_write(rt1308->regmap, RT1308_POWER, 0xff371600); | ||
812 | regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52100000); | ||
813 | regmap_write(rt1308->regmap, RT1308_I2C_I2S_SDW_SET, 0x01014005); | ||
814 | regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501); | ||
815 | regmap_write(rt1308->regmap, RT1308_PADS_1, 0x50150505); | ||
816 | regmap_write(rt1308->regmap, RT1308_VREF, 0x18100000); | ||
817 | regmap_write(rt1308->regmap, RT1308_IV_SENSE, 0x87010000); | ||
818 | regmap_write(rt1308->regmap, RT1308_DUMMY_REG, 0x00000200); | ||
819 | regmap_write(rt1308->regmap, RT1308_SIL_DET, 0x61c30000); | ||
820 | regmap_write(rt1308->regmap, RT1308_CLK_DET, 0x03700000); | ||
821 | regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x50022f00); | ||
822 | regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000); | 810 | regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x01800000); |
823 | regmap_write(rt1308->regmap, RT1308_DC_CAL_2, 0x00ffff00); | ||
824 | regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x607e5501); | ||
825 | |||
826 | regmap_write(rt1308->regmap, RT1308_CLK_2, 0x0060e000); | ||
827 | regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x04fe0f00); | ||
828 | msleep(100); | 811 | msleep(100); |
829 | regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00); | 812 | regmap_write(rt1308->regmap, RT1308_EFUSE_1, 0x44fe0f00); |
830 | msleep(20); | 813 | msleep(20); |
831 | regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000); | 814 | regmap_write(rt1308->regmap, RT1308_PVDD_OFFSET_CTL, 0x10000000); |
832 | |||
833 | regmap_write(rt1308->regmap, RT1308_POWER_STATUS, 0x00800000); | ||
834 | regmap_write(rt1308->regmap, RT1308_POWER, 0x0); | ||
835 | regmap_write(rt1308->regmap, RT1308_CLK_1, 0x52000000); | ||
836 | regmap_write(rt1308->regmap, RT1308_CLASS_D_SET_2, 0x227f5501); | ||
837 | regmap_write(rt1308->regmap, RT1308_SINE_TONE_GEN_1, 0x10022f00); | ||
838 | } | 815 | } |
839 | 816 | ||
840 | static int rt1308_i2c_probe(struct i2c_client *i2c, | 817 | static int rt1308_i2c_probe(struct i2c_client *i2c, |
diff --git a/sound/soc/codecs/rt1308.h b/sound/soc/codecs/rt1308.h index c330aae1d527..ff7c423e879e 100644 --- a/sound/soc/codecs/rt1308.h +++ b/sound/soc/codecs/rt1308.h | |||
@@ -1,12 +1,10 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * RT1308.h -- RT1308 ALSA SoC amplifier component driver | 3 | * rt1308.h -- RT1308 ALSA SoC amplifier component driver |
3 | * | 4 | * |
4 | * Copyright 2019 Realtek Semiconductor Corp. | 5 | * Copyright 2019 Realtek Semiconductor Corp. |
5 | * Author: Derek Fang <derek.fang@realtek.com> | 6 | * Author: Derek Fang <derek.fang@realtek.com> |
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | 8 | */ |
11 | 9 | ||
12 | #ifndef _RT1308_H_ | 10 | #ifndef _RT1308_H_ |
diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index c050d84a6916..68299ce26d3e 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c | |||
@@ -2566,7 +2566,7 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w, | |||
2566 | return 0; | 2566 | return 0; |
2567 | } | 2567 | } |
2568 | 2568 | ||
2569 | static int rt5655_set_verf(struct snd_soc_dapm_widget *w, | 2569 | static int rt5665_set_verf(struct snd_soc_dapm_widget *w, |
2570 | struct snd_kcontrol *kcontrol, int event) | 2570 | struct snd_kcontrol *kcontrol, int event) |
2571 | { | 2571 | { |
2572 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | 2572 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); |
@@ -2686,11 +2686,11 @@ static const struct snd_soc_dapm_widget rt5665_dapm_widgets[] = { | |||
2686 | SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5665_PWR_VOL, | 2686 | SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5665_PWR_VOL, |
2687 | RT5665_PWR_MIC_DET_BIT, 0, NULL, 0), | 2687 | RT5665_PWR_MIC_DET_BIT, 0, NULL, 0), |
2688 | SND_SOC_DAPM_SUPPLY("Vref1", RT5665_PWR_ANLG_1, RT5665_PWR_VREF1_BIT, 0, | 2688 | SND_SOC_DAPM_SUPPLY("Vref1", RT5665_PWR_ANLG_1, RT5665_PWR_VREF1_BIT, 0, |
2689 | rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | 2689 | rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
2690 | SND_SOC_DAPM_SUPPLY("Vref2", RT5665_PWR_ANLG_1, RT5665_PWR_VREF2_BIT, 0, | 2690 | SND_SOC_DAPM_SUPPLY("Vref2", RT5665_PWR_ANLG_1, RT5665_PWR_VREF2_BIT, 0, |
2691 | rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | 2691 | rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
2692 | SND_SOC_DAPM_SUPPLY("Vref3", RT5665_PWR_ANLG_1, RT5665_PWR_VREF3_BIT, 0, | 2692 | SND_SOC_DAPM_SUPPLY("Vref3", RT5665_PWR_ANLG_1, RT5665_PWR_VREF3_BIT, 0, |
2693 | rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | 2693 | rt5665_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), |
2694 | 2694 | ||
2695 | /* ASRC */ | 2695 | /* ASRC */ |
2696 | SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5665_ASRC_1, | 2696 | SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5665_ASRC_1, |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index c779dc3474f9..315a3d39bc09 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -691,10 +691,12 @@ static void rt5677_set_dsp_mode(struct snd_soc_component *component, bool on) | |||
691 | struct rt5677_priv *rt5677 = snd_soc_component_get_drvdata(component); | 691 | struct rt5677_priv *rt5677 = snd_soc_component_get_drvdata(component); |
692 | 692 | ||
693 | if (on) { | 693 | if (on) { |
694 | regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x2); | 694 | regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, |
695 | RT5677_PWR_DSP, RT5677_PWR_DSP); | ||
695 | rt5677->is_dsp_mode = true; | 696 | rt5677->is_dsp_mode = true; |
696 | } else { | 697 | } else { |
697 | regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, 0x2, 0x0); | 698 | regmap_update_bits(rt5677->regmap, RT5677_PWR_DSP1, |
699 | RT5677_PWR_DSP, 0x0); | ||
698 | rt5677->is_dsp_mode = false; | 700 | rt5677->is_dsp_mode = false; |
699 | } | 701 | } |
700 | } | 702 | } |
@@ -4466,7 +4468,8 @@ static int rt5677_set_bias_level(struct snd_soc_component *component, | |||
4466 | 4468 | ||
4467 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, | 4469 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG1, |
4468 | RT5677_LDO1_SEL_MASK | RT5677_LDO2_SEL_MASK, | 4470 | RT5677_LDO1_SEL_MASK | RT5677_LDO2_SEL_MASK, |
4469 | 0x0055); | 4471 | 5 << RT5677_LDO1_SEL_SFT | |
4472 | 5 << RT5677_LDO2_SEL_SFT); | ||
4470 | regmap_update_bits(rt5677->regmap, | 4473 | regmap_update_bits(rt5677->regmap, |
4471 | RT5677_PR_BASE + RT5677_BIAS_CUR4, | 4474 | RT5677_PR_BASE + RT5677_BIAS_CUR4, |
4472 | 0x0f00, 0x0f00); | 4475 | 0x0f00, 0x0f00); |
@@ -4490,9 +4493,11 @@ static int rt5677_set_bias_level(struct snd_soc_component *component, | |||
4490 | case SND_SOC_BIAS_OFF: | 4493 | case SND_SOC_BIAS_OFF: |
4491 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0); | 4494 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x1, 0x0); |
4492 | regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000); | 4495 | regmap_write(rt5677->regmap, RT5677_PWR_DIG1, 0x0000); |
4493 | regmap_write(rt5677->regmap, RT5677_PWR_DIG2, 0x0000); | 4496 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, |
4494 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG1, 0x0022); | 4497 | 2 << RT5677_LDO1_SEL_SFT | |
4495 | regmap_write(rt5677->regmap, RT5677_PWR_ANLG2, 0x0000); | 4498 | 2 << RT5677_LDO2_SEL_SFT); |
4499 | regmap_update_bits(rt5677->regmap, RT5677_PWR_ANLG2, | ||
4500 | RT5677_PWR_CORE, 0); | ||
4496 | regmap_update_bits(rt5677->regmap, | 4501 | regmap_update_bits(rt5677->regmap, |
4497 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); | 4502 | RT5677_PR_BASE + RT5677_BIAS_CUR4, 0x0f00, 0x0000); |
4498 | 4503 | ||
@@ -4719,7 +4724,8 @@ static int rt5677_probe(struct snd_soc_component *component) | |||
4719 | 4724 | ||
4720 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, | 4725 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, |
4721 | ~RT5677_IRQ_DEBOUNCE_SEL_MASK, 0x0020); | 4726 | ~RT5677_IRQ_DEBOUNCE_SEL_MASK, 0x0020); |
4722 | regmap_write(rt5677->regmap, RT5677_PWR_DSP2, 0x0c00); | 4727 | regmap_write(rt5677->regmap, RT5677_PWR_DSP2, |
4728 | RT5677_PWR_SLIM_ISO | RT5677_PWR_CORE_ISO); | ||
4723 | 4729 | ||
4724 | for (i = 0; i < RT5677_GPIO_NUM; i++) | 4730 | for (i = 0; i < RT5677_GPIO_NUM; i++) |
4725 | rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]); | 4731 | rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]); |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index a6a4748c97f9..aa1f9637d895 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -31,6 +31,13 @@ | |||
31 | #define SGTL5000_DAP_REG_OFFSET 0x0100 | 31 | #define SGTL5000_DAP_REG_OFFSET 0x0100 |
32 | #define SGTL5000_MAX_REG_OFFSET 0x013A | 32 | #define SGTL5000_MAX_REG_OFFSET 0x013A |
33 | 33 | ||
34 | /* Delay for the VAG ramp up */ | ||
35 | #define SGTL5000_VAG_POWERUP_DELAY 500 /* ms */ | ||
36 | /* Delay for the VAG ramp down */ | ||
37 | #define SGTL5000_VAG_POWERDOWN_DELAY 500 /* ms */ | ||
38 | |||
39 | #define SGTL5000_OUTPUTS_MUTE (SGTL5000_HP_MUTE | SGTL5000_LINE_OUT_MUTE) | ||
40 | |||
34 | /* default value of sgtl5000 registers */ | 41 | /* default value of sgtl5000 registers */ |
35 | static const struct reg_default sgtl5000_reg_defaults[] = { | 42 | static const struct reg_default sgtl5000_reg_defaults[] = { |
36 | { SGTL5000_CHIP_DIG_POWER, 0x0000 }, | 43 | { SGTL5000_CHIP_DIG_POWER, 0x0000 }, |
@@ -123,6 +130,13 @@ enum { | |||
123 | I2S_SCLK_STRENGTH_HIGH, | 130 | I2S_SCLK_STRENGTH_HIGH, |
124 | }; | 131 | }; |
125 | 132 | ||
133 | enum { | ||
134 | HP_POWER_EVENT, | ||
135 | DAC_POWER_EVENT, | ||
136 | ADC_POWER_EVENT, | ||
137 | LAST_POWER_EVENT = ADC_POWER_EVENT | ||
138 | }; | ||
139 | |||
126 | /* sgtl5000 private structure in codec */ | 140 | /* sgtl5000 private structure in codec */ |
127 | struct sgtl5000_priv { | 141 | struct sgtl5000_priv { |
128 | int sysclk; /* sysclk rate */ | 142 | int sysclk; /* sysclk rate */ |
@@ -137,8 +151,109 @@ struct sgtl5000_priv { | |||
137 | u8 micbias_voltage; | 151 | u8 micbias_voltage; |
138 | u8 lrclk_strength; | 152 | u8 lrclk_strength; |
139 | u8 sclk_strength; | 153 | u8 sclk_strength; |
154 | u16 mute_state[LAST_POWER_EVENT + 1]; | ||
140 | }; | 155 | }; |
141 | 156 | ||
157 | static inline int hp_sel_input(struct snd_soc_component *component) | ||
158 | { | ||
159 | return (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_CTRL) & | ||
160 | SGTL5000_HP_SEL_MASK) >> SGTL5000_HP_SEL_SHIFT; | ||
161 | } | ||
162 | |||
163 | static inline u16 mute_output(struct snd_soc_component *component, | ||
164 | u16 mute_mask) | ||
165 | { | ||
166 | u16 mute_reg = snd_soc_component_read32(component, | ||
167 | SGTL5000_CHIP_ANA_CTRL); | ||
168 | |||
169 | snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, | ||
170 | mute_mask, mute_mask); | ||
171 | return mute_reg; | ||
172 | } | ||
173 | |||
174 | static inline void restore_output(struct snd_soc_component *component, | ||
175 | u16 mute_mask, u16 mute_reg) | ||
176 | { | ||
177 | snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, | ||
178 | mute_mask, mute_reg); | ||
179 | } | ||
180 | |||
181 | static void vag_power_on(struct snd_soc_component *component, u32 source) | ||
182 | { | ||
183 | if (snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & | ||
184 | SGTL5000_VAG_POWERUP) | ||
185 | return; | ||
186 | |||
187 | snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, | ||
188 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); | ||
189 | |||
190 | /* When VAG powering on to get local loop from Line-In, the sleep | ||
191 | * is required to avoid loud pop. | ||
192 | */ | ||
193 | if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN && | ||
194 | source == HP_POWER_EVENT) | ||
195 | msleep(SGTL5000_VAG_POWERUP_DELAY); | ||
196 | } | ||
197 | |||
198 | static int vag_power_consumers(struct snd_soc_component *component, | ||
199 | u16 ana_pwr_reg, u32 source) | ||
200 | { | ||
201 | int consumers = 0; | ||
202 | |||
203 | /* count dac/adc consumers unconditional */ | ||
204 | if (ana_pwr_reg & SGTL5000_DAC_POWERUP) | ||
205 | consumers++; | ||
206 | if (ana_pwr_reg & SGTL5000_ADC_POWERUP) | ||
207 | consumers++; | ||
208 | |||
209 | /* | ||
210 | * If the event comes from HP and Line-In is selected, | ||
211 | * current action is 'DAC to be powered down'. | ||
212 | * As HP_POWERUP is not set when HP muxed to line-in, | ||
213 | * we need to keep VAG power ON. | ||
214 | */ | ||
215 | if (source == HP_POWER_EVENT) { | ||
216 | if (hp_sel_input(component) == SGTL5000_HP_SEL_LINE_IN) | ||
217 | consumers++; | ||
218 | } else { | ||
219 | if (ana_pwr_reg & SGTL5000_HP_POWERUP) | ||
220 | consumers++; | ||
221 | } | ||
222 | |||
223 | return consumers; | ||
224 | } | ||
225 | |||
226 | static void vag_power_off(struct snd_soc_component *component, u32 source) | ||
227 | { | ||
228 | u16 ana_pwr = snd_soc_component_read32(component, | ||
229 | SGTL5000_CHIP_ANA_POWER); | ||
230 | |||
231 | if (!(ana_pwr & SGTL5000_VAG_POWERUP)) | ||
232 | return; | ||
233 | |||
234 | /* | ||
235 | * This function calls when any of VAG power consumers is disappearing. | ||
236 | * Thus, if there is more than one consumer at the moment, as minimum | ||
237 | * one consumer will definitely stay after the end of the current | ||
238 | * event. | ||
239 | * Don't clear VAG_POWERUP if 2 or more consumers of VAG present: | ||
240 | * - LINE_IN (for HP events) / HP (for DAC/ADC events) | ||
241 | * - DAC | ||
242 | * - ADC | ||
243 | * (the current consumer is disappearing right now) | ||
244 | */ | ||
245 | if (vag_power_consumers(component, ana_pwr, source) >= 2) | ||
246 | return; | ||
247 | |||
248 | snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, | ||
249 | SGTL5000_VAG_POWERUP, 0); | ||
250 | /* In power down case, we need wait 400-1000 ms | ||
251 | * when VAG fully ramped down. | ||
252 | * As longer we wait, as smaller pop we've got. | ||
253 | */ | ||
254 | msleep(SGTL5000_VAG_POWERDOWN_DELAY); | ||
255 | } | ||
256 | |||
142 | /* | 257 | /* |
143 | * mic_bias power on/off share the same register bits with | 258 | * mic_bias power on/off share the same register bits with |
144 | * output impedance of mic bias, when power on mic bias, we | 259 | * output impedance of mic bias, when power on mic bias, we |
@@ -170,36 +285,46 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, | |||
170 | return 0; | 285 | return 0; |
171 | } | 286 | } |
172 | 287 | ||
173 | /* | 288 | static int vag_and_mute_control(struct snd_soc_component *component, |
174 | * As manual described, ADC/DAC only works when VAG powerup, | 289 | int event, int event_source) |
175 | * So enabled VAG before ADC/DAC up. | ||
176 | * In power down case, we need wait 400ms when vag fully ramped down. | ||
177 | */ | ||
178 | static int power_vag_event(struct snd_soc_dapm_widget *w, | ||
179 | struct snd_kcontrol *kcontrol, int event) | ||
180 | { | 290 | { |
181 | struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); | 291 | static const u16 mute_mask[] = { |
182 | const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP; | 292 | /* |
293 | * Mask for HP_POWER_EVENT. | ||
294 | * Muxing Headphones have to be wrapped with mute/unmute | ||
295 | * headphones only. | ||
296 | */ | ||
297 | SGTL5000_HP_MUTE, | ||
298 | /* | ||
299 | * Masks for DAC_POWER_EVENT/ADC_POWER_EVENT. | ||
300 | * Muxing DAC or ADC block have to wrapped with mute/unmute | ||
301 | * both headphones and line-out. | ||
302 | */ | ||
303 | SGTL5000_OUTPUTS_MUTE, | ||
304 | SGTL5000_OUTPUTS_MUTE | ||
305 | }; | ||
306 | |||
307 | struct sgtl5000_priv *sgtl5000 = | ||
308 | snd_soc_component_get_drvdata(component); | ||
183 | 309 | ||
184 | switch (event) { | 310 | switch (event) { |
311 | case SND_SOC_DAPM_PRE_PMU: | ||
312 | sgtl5000->mute_state[event_source] = | ||
313 | mute_output(component, mute_mask[event_source]); | ||
314 | break; | ||
185 | case SND_SOC_DAPM_POST_PMU: | 315 | case SND_SOC_DAPM_POST_PMU: |
186 | snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, | 316 | vag_power_on(component, event_source); |
187 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); | 317 | restore_output(component, mute_mask[event_source], |
188 | msleep(400); | 318 | sgtl5000->mute_state[event_source]); |
189 | break; | 319 | break; |
190 | |||
191 | case SND_SOC_DAPM_PRE_PMD: | 320 | case SND_SOC_DAPM_PRE_PMD: |
192 | /* | 321 | sgtl5000->mute_state[event_source] = |
193 | * Don't clear VAG_POWERUP, when both DAC and ADC are | 322 | mute_output(component, mute_mask[event_source]); |
194 | * operational to prevent inadvertently starving the | 323 | vag_power_off(component, event_source); |
195 | * other one of them. | 324 | break; |
196 | */ | 325 | case SND_SOC_DAPM_POST_PMD: |
197 | if ((snd_soc_component_read32(component, SGTL5000_CHIP_ANA_POWER) & | 326 | restore_output(component, mute_mask[event_source], |
198 | mask) != mask) { | 327 | sgtl5000->mute_state[event_source]); |
199 | snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER, | ||
200 | SGTL5000_VAG_POWERUP, 0); | ||
201 | msleep(400); | ||
202 | } | ||
203 | break; | 328 | break; |
204 | default: | 329 | default: |
205 | break; | 330 | break; |
@@ -208,6 +333,41 @@ static int power_vag_event(struct snd_soc_dapm_widget *w, | |||
208 | return 0; | 333 | return 0; |
209 | } | 334 | } |
210 | 335 | ||
336 | /* | ||
337 | * Mute Headphone when power it up/down. | ||
338 | * Control VAG power on HP power path. | ||
339 | */ | ||
340 | static int headphone_pga_event(struct snd_soc_dapm_widget *w, | ||
341 | struct snd_kcontrol *kcontrol, int event) | ||
342 | { | ||
343 | struct snd_soc_component *component = | ||
344 | snd_soc_dapm_to_component(w->dapm); | ||
345 | |||
346 | return vag_and_mute_control(component, event, HP_POWER_EVENT); | ||
347 | } | ||
348 | |||
349 | /* As manual describes, ADC/DAC powering up/down requires | ||
350 | * to mute outputs to avoid pops. | ||
351 | * Control VAG power on ADC/DAC power path. | ||
352 | */ | ||
353 | static int adc_updown_depop(struct snd_soc_dapm_widget *w, | ||
354 | struct snd_kcontrol *kcontrol, int event) | ||
355 | { | ||
356 | struct snd_soc_component *component = | ||
357 | snd_soc_dapm_to_component(w->dapm); | ||
358 | |||
359 | return vag_and_mute_control(component, event, ADC_POWER_EVENT); | ||
360 | } | ||
361 | |||
362 | static int dac_updown_depop(struct snd_soc_dapm_widget *w, | ||
363 | struct snd_kcontrol *kcontrol, int event) | ||
364 | { | ||
365 | struct snd_soc_component *component = | ||
366 | snd_soc_dapm_to_component(w->dapm); | ||
367 | |||
368 | return vag_and_mute_control(component, event, DAC_POWER_EVENT); | ||
369 | } | ||
370 | |||
211 | /* input sources for ADC */ | 371 | /* input sources for ADC */ |
212 | static const char *adc_mux_text[] = { | 372 | static const char *adc_mux_text[] = { |
213 | "MIC_IN", "LINE_IN" | 373 | "MIC_IN", "LINE_IN" |
@@ -280,7 +440,10 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { | |||
280 | mic_bias_event, | 440 | mic_bias_event, |
281 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 441 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
282 | 442 | ||
283 | SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0), | 443 | SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0, |
444 | headphone_pga_event, | ||
445 | SND_SOC_DAPM_PRE_POST_PMU | | ||
446 | SND_SOC_DAPM_PRE_POST_PMD), | ||
284 | SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0), | 447 | SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0), |
285 | 448 | ||
286 | SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux), | 449 | SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux), |
@@ -301,11 +464,12 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { | |||
301 | 0, SGTL5000_CHIP_DIG_POWER, | 464 | 0, SGTL5000_CHIP_DIG_POWER, |
302 | 1, 0), | 465 | 1, 0), |
303 | 466 | ||
304 | SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), | 467 | SND_SOC_DAPM_ADC_E("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0, |
305 | SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), | 468 | adc_updown_depop, SND_SOC_DAPM_PRE_POST_PMU | |
306 | 469 | SND_SOC_DAPM_PRE_POST_PMD), | |
307 | SND_SOC_DAPM_PRE("VAG_POWER_PRE", power_vag_event), | 470 | SND_SOC_DAPM_DAC_E("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0, |
308 | SND_SOC_DAPM_POST("VAG_POWER_POST", power_vag_event), | 471 | dac_updown_depop, SND_SOC_DAPM_PRE_POST_PMU | |
472 | SND_SOC_DAPM_PRE_POST_PMD), | ||
309 | }; | 473 | }; |
310 | 474 | ||
311 | /* routes for sgtl5000 */ | 475 | /* routes for sgtl5000 */ |
@@ -556,6 +720,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { | |||
556 | SGTL5000_CHIP_ANA_ADC_CTRL, | 720 | SGTL5000_CHIP_ANA_ADC_CTRL, |
557 | 8, 1, 0, capture_6db_attenuate), | 721 | 8, 1, 0, capture_6db_attenuate), |
558 | SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), | 722 | SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), |
723 | SOC_SINGLE("Capture Switch", SGTL5000_CHIP_ANA_CTRL, 0, 1, 1), | ||
559 | 724 | ||
560 | SOC_DOUBLE_TLV("Headphone Playback Volume", | 725 | SOC_DOUBLE_TLV("Headphone Playback Volume", |
561 | SGTL5000_CHIP_ANA_HP_CTRL, | 726 | SGTL5000_CHIP_ANA_HP_CTRL, |
@@ -1173,12 +1338,17 @@ static int sgtl5000_set_power_regs(struct snd_soc_component *component) | |||
1173 | SGTL5000_INT_OSC_EN); | 1338 | SGTL5000_INT_OSC_EN); |
1174 | /* Enable VDDC charge pump */ | 1339 | /* Enable VDDC charge pump */ |
1175 | ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; | 1340 | ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; |
1176 | } else if (vddio >= 3100 && vdda >= 3100) { | 1341 | } else { |
1177 | ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP; | 1342 | ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP; |
1178 | /* VDDC use VDDIO rail */ | 1343 | /* |
1179 | lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; | 1344 | * if vddio == vdda the source of charge pump should be |
1180 | lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << | 1345 | * assigned manually to VDDIO |
1181 | SGTL5000_VDDC_MAN_ASSN_SHIFT; | 1346 | */ |
1347 | if (vddio == vdda) { | ||
1348 | lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; | ||
1349 | lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << | ||
1350 | SGTL5000_VDDC_MAN_ASSN_SHIFT; | ||
1351 | } | ||
1182 | } | 1352 | } |
1183 | 1353 | ||
1184 | snd_soc_component_write(component, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl); | 1354 | snd_soc_component_write(component, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl); |
@@ -1288,6 +1458,7 @@ static int sgtl5000_probe(struct snd_soc_component *component) | |||
1288 | int ret; | 1458 | int ret; |
1289 | u16 reg; | 1459 | u16 reg; |
1290 | struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component); | 1460 | struct sgtl5000_priv *sgtl5000 = snd_soc_component_get_drvdata(component); |
1461 | unsigned int zcd_mask = SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN; | ||
1291 | 1462 | ||
1292 | /* power up sgtl5000 */ | 1463 | /* power up sgtl5000 */ |
1293 | ret = sgtl5000_set_power_regs(component); | 1464 | ret = sgtl5000_set_power_regs(component); |
@@ -1296,7 +1467,7 @@ static int sgtl5000_probe(struct snd_soc_component *component) | |||
1296 | 1467 | ||
1297 | /* enable small pop, introduce 400ms delay in turning off */ | 1468 | /* enable small pop, introduce 400ms delay in turning off */ |
1298 | snd_soc_component_update_bits(component, SGTL5000_CHIP_REF_CTRL, | 1469 | snd_soc_component_update_bits(component, SGTL5000_CHIP_REF_CTRL, |
1299 | SGTL5000_SMALL_POP, 1); | 1470 | SGTL5000_SMALL_POP, SGTL5000_SMALL_POP); |
1300 | 1471 | ||
1301 | /* disable short cut detector */ | 1472 | /* disable short cut detector */ |
1302 | snd_soc_component_write(component, SGTL5000_CHIP_SHORT_CTRL, 0); | 1473 | snd_soc_component_write(component, SGTL5000_CHIP_SHORT_CTRL, 0); |
@@ -1315,9 +1486,8 @@ static int sgtl5000_probe(struct snd_soc_component *component) | |||
1315 | 0x1f); | 1486 | 0x1f); |
1316 | snd_soc_component_write(component, SGTL5000_CHIP_PAD_STRENGTH, reg); | 1487 | snd_soc_component_write(component, SGTL5000_CHIP_PAD_STRENGTH, reg); |
1317 | 1488 | ||
1318 | snd_soc_component_write(component, SGTL5000_CHIP_ANA_CTRL, | 1489 | snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_CTRL, |
1319 | SGTL5000_HP_ZCD_EN | | 1490 | zcd_mask, zcd_mask); |
1320 | SGTL5000_ADC_ZCD_EN); | ||
1321 | 1491 | ||
1322 | snd_soc_component_update_bits(component, SGTL5000_CHIP_MIC_CTRL, | 1492 | snd_soc_component_update_bits(component, SGTL5000_CHIP_MIC_CTRL, |
1323 | SGTL5000_BIAS_R_MASK, | 1493 | SGTL5000_BIAS_R_MASK, |
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 18cae08bbd3a..a4bf4bca95bf 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h | |||
@@ -273,7 +273,7 @@ | |||
273 | #define SGTL5000_BIAS_CTRL_MASK 0x000e | 273 | #define SGTL5000_BIAS_CTRL_MASK 0x000e |
274 | #define SGTL5000_BIAS_CTRL_SHIFT 1 | 274 | #define SGTL5000_BIAS_CTRL_SHIFT 1 |
275 | #define SGTL5000_BIAS_CTRL_WIDTH 3 | 275 | #define SGTL5000_BIAS_CTRL_WIDTH 3 |
276 | #define SGTL5000_SMALL_POP 1 | 276 | #define SGTL5000_SMALL_POP 0x0001 |
277 | 277 | ||
278 | /* | 278 | /* |
279 | * SGTL5000_CHIP_MIC_CTRL | 279 | * SGTL5000_CHIP_MIC_CTRL |
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 9009a7407b7a..a061d78473ac 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c | |||
@@ -459,7 +459,6 @@ static int sirf_audio_codec_driver_probe(struct platform_device *pdev) | |||
459 | int ret; | 459 | int ret; |
460 | struct sirf_audio_codec *sirf_audio_codec; | 460 | struct sirf_audio_codec *sirf_audio_codec; |
461 | void __iomem *base; | 461 | void __iomem *base; |
462 | struct resource *mem_res; | ||
463 | 462 | ||
464 | sirf_audio_codec = devm_kzalloc(&pdev->dev, | 463 | sirf_audio_codec = devm_kzalloc(&pdev->dev, |
465 | sizeof(struct sirf_audio_codec), GFP_KERNEL); | 464 | sizeof(struct sirf_audio_codec), GFP_KERNEL); |
@@ -468,8 +467,7 @@ static int sirf_audio_codec_driver_probe(struct platform_device *pdev) | |||
468 | 467 | ||
469 | platform_set_drvdata(pdev, sirf_audio_codec); | 468 | platform_set_drvdata(pdev, sirf_audio_codec); |
470 | 469 | ||
471 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 470 | base = devm_platform_ioremap_resource(pdev, 0); |
472 | base = devm_ioremap_resource(&pdev->dev, mem_res); | ||
473 | if (IS_ERR(base)) | 471 | if (IS_ERR(base)) |
474 | return PTR_ERR(base); | 472 | return PTR_ERR(base); |
475 | 473 | ||
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 080a840c987a..f8e2f4b74db3 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -67,8 +67,6 @@ static SOC_ENUM_SINGLE_DECL(rec_src_enum, | |||
67 | static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = | 67 | static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = |
68 | SOC_DAPM_ENUM("Input Select", rec_src_enum); | 68 | SOC_DAPM_ENUM("Input Select", rec_src_enum); |
69 | 69 | ||
70 | static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src, | ||
71 | TLV320AIC23_ANLG, 2, rec_src_text); | ||
72 | static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, | 70 | static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, |
73 | TLV320AIC23_DIGT, 1, deemph_text); | 71 | TLV320AIC23_DIGT, 1, deemph_text); |
74 | 72 | ||
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 9b37e98da0db..df627a08def9 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -258,7 +258,6 @@ static SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, | |||
258 | static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, | 258 | static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, |
259 | mic_select_text); | 259 | mic_select_text); |
260 | 260 | ||
261 | static SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); | ||
262 | static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, | 261 | static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, |
263 | mic_select_text); | 262 | mic_select_text); |
264 | 263 | ||
@@ -1553,7 +1552,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, | |||
1553 | aic31xx->gpio_reset = devm_gpiod_get_optional(aic31xx->dev, "reset", | 1552 | aic31xx->gpio_reset = devm_gpiod_get_optional(aic31xx->dev, "reset", |
1554 | GPIOD_OUT_LOW); | 1553 | GPIOD_OUT_LOW); |
1555 | if (IS_ERR(aic31xx->gpio_reset)) { | 1554 | if (IS_ERR(aic31xx->gpio_reset)) { |
1556 | dev_err(aic31xx->dev, "not able to acquire gpio\n"); | 1555 | if (PTR_ERR(aic31xx->gpio_reset) != -EPROBE_DEFER) |
1556 | dev_err(aic31xx->dev, "not able to acquire gpio\n"); | ||
1557 | return PTR_ERR(aic31xx->gpio_reset); | 1557 | return PTR_ERR(aic31xx->gpio_reset); |
1558 | } | 1558 | } |
1559 | 1559 | ||
@@ -1564,7 +1564,9 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, | |||
1564 | ARRAY_SIZE(aic31xx->supplies), | 1564 | ARRAY_SIZE(aic31xx->supplies), |
1565 | aic31xx->supplies); | 1565 | aic31xx->supplies); |
1566 | if (ret) { | 1566 | if (ret) { |
1567 | dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); | 1567 | if (ret != -EPROBE_DEFER) |
1568 | dev_err(aic31xx->dev, | ||
1569 | "Failed to request supplies: %d\n", ret); | ||
1568 | return ret; | 1570 | return ret; |
1569 | } | 1571 | } |
1570 | 1572 | ||
diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index 93d84e5ae2d5..c3587af9985c 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include "tscs454.h" | 23 | #include "tscs454.h" |
24 | 24 | ||
25 | static const unsigned int PLL_48K_RATE = (48000 * 256); | ||
26 | static const unsigned int PLL_44_1K_RATE = (44100 * 256); | 25 | static const unsigned int PLL_44_1K_RATE = (44100 * 256); |
27 | 26 | ||
28 | #define COEFF_SIZE 3 | 27 | #define COEFF_SIZE 3 |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 472c2fff34a8..f34637afee51 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -1108,10 +1108,8 @@ static int twl6040_probe(struct snd_soc_component *component) | |||
1108 | priv->component = component; | 1108 | priv->component = component; |
1109 | 1109 | ||
1110 | priv->plug_irq = platform_get_irq(pdev, 0); | 1110 | priv->plug_irq = platform_get_irq(pdev, 0); |
1111 | if (priv->plug_irq < 0) { | 1111 | if (priv->plug_irq < 0) |
1112 | dev_err(component->dev, "invalid irq: %d\n", priv->plug_irq); | ||
1113 | return priv->plug_irq; | 1112 | return priv->plug_irq; |
1114 | } | ||
1115 | 1113 | ||
1116 | INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work); | 1114 | INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work); |
1117 | 1115 | ||
diff --git a/sound/soc/codecs/uda1334.c b/sound/soc/codecs/uda1334.c new file mode 100644 index 000000000000..21ab8c5487ba --- /dev/null +++ b/sound/soc/codecs/uda1334.c | |||
@@ -0,0 +1,295 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | // | ||
3 | // uda1334.c -- UDA1334 ALSA SoC Audio driver | ||
4 | // | ||
5 | // Based on WM8523 ALSA SoC Audio driver written by Mark Brown | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/moduleparam.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/gpio/consumer.h> | ||
13 | #include <linux/of_device.h> | ||
14 | #include <sound/core.h> | ||
15 | #include <sound/pcm.h> | ||
16 | #include <sound/pcm_params.h> | ||
17 | #include <sound/soc.h> | ||
18 | #include <sound/initval.h> | ||
19 | |||
20 | #define UDA1334_NUM_RATES 6 | ||
21 | |||
22 | /* codec private data */ | ||
23 | struct uda1334_priv { | ||
24 | struct gpio_desc *mute; | ||
25 | struct gpio_desc *deemph; | ||
26 | unsigned int sysclk; | ||
27 | unsigned int rate_constraint_list[UDA1334_NUM_RATES]; | ||
28 | struct snd_pcm_hw_constraint_list rate_constraint; | ||
29 | }; | ||
30 | |||
31 | static const struct snd_soc_dapm_widget uda1334_dapm_widgets[] = { | ||
32 | SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), | ||
33 | SND_SOC_DAPM_OUTPUT("LINEVOUTL"), | ||
34 | SND_SOC_DAPM_OUTPUT("LINEVOUTR"), | ||
35 | }; | ||
36 | |||
37 | static const struct snd_soc_dapm_route uda1334_dapm_routes[] = { | ||
38 | { "LINEVOUTL", NULL, "DAC" }, | ||
39 | { "LINEVOUTR", NULL, "DAC" }, | ||
40 | }; | ||
41 | |||
42 | static int uda1334_put_deemph(struct snd_kcontrol *kcontrol, | ||
43 | struct snd_ctl_elem_value *ucontrol) | ||
44 | { | ||
45 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); | ||
46 | struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); | ||
47 | int deemph = ucontrol->value.integer.value[0]; | ||
48 | |||
49 | if (deemph > 1) | ||
50 | return -EINVAL; | ||
51 | |||
52 | gpiod_set_value_cansleep(uda1334->deemph, deemph); | ||
53 | |||
54 | return 0; | ||
55 | }; | ||
56 | |||
57 | static int uda1334_get_deemph(struct snd_kcontrol *kcontrol, | ||
58 | struct snd_ctl_elem_value *ucontrol) | ||
59 | { | ||
60 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); | ||
61 | struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); | ||
62 | int ret; | ||
63 | |||
64 | ret = gpiod_get_value_cansleep(uda1334->deemph); | ||
65 | if (ret < 0) | ||
66 | return -EINVAL; | ||
67 | |||
68 | ucontrol->value.integer.value[0] = ret; | ||
69 | |||
70 | return 0; | ||
71 | }; | ||
72 | |||
73 | static const struct snd_kcontrol_new uda1334_snd_controls[] = { | ||
74 | SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, | ||
75 | uda1334_get_deemph, uda1334_put_deemph), | ||
76 | }; | ||
77 | |||
78 | static const struct { | ||
79 | int value; | ||
80 | int ratio; | ||
81 | } lrclk_ratios[UDA1334_NUM_RATES] = { | ||
82 | { 1, 128 }, | ||
83 | { 2, 192 }, | ||
84 | { 3, 256 }, | ||
85 | { 4, 384 }, | ||
86 | { 5, 512 }, | ||
87 | { 6, 768 }, | ||
88 | }; | ||
89 | |||
90 | static int uda1334_startup(struct snd_pcm_substream *substream, | ||
91 | struct snd_soc_dai *dai) | ||
92 | { | ||
93 | struct snd_soc_component *component = dai->component; | ||
94 | struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); | ||
95 | |||
96 | /* | ||
97 | * The set of sample rates that can be supported depends on the | ||
98 | * MCLK supplied to the CODEC - enforce this. | ||
99 | */ | ||
100 | if (!uda1334->sysclk) { | ||
101 | dev_err(component->dev, | ||
102 | "No MCLK configured, call set_sysclk() on init\n"); | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
107 | SNDRV_PCM_HW_PARAM_RATE, | ||
108 | &uda1334->rate_constraint); | ||
109 | |||
110 | gpiod_set_value_cansleep(uda1334->mute, 1); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static void uda1334_shutdown(struct snd_pcm_substream *substream, | ||
116 | struct snd_soc_dai *dai) | ||
117 | { | ||
118 | struct snd_soc_component *component = dai->component; | ||
119 | struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); | ||
120 | |||
121 | gpiod_set_value_cansleep(uda1334->mute, 0); | ||
122 | } | ||
123 | |||
124 | static int uda1334_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
125 | int clk_id, unsigned int freq, int dir) | ||
126 | { | ||
127 | struct snd_soc_component *component = codec_dai->component; | ||
128 | struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); | ||
129 | unsigned int val; | ||
130 | int i, j = 0; | ||
131 | |||
132 | uda1334->sysclk = freq; | ||
133 | |||
134 | uda1334->rate_constraint.count = 0; | ||
135 | for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { | ||
136 | val = freq / lrclk_ratios[i].ratio; | ||
137 | /* | ||
138 | * Check that it's a standard rate since core can't | ||
139 | * cope with others and having the odd rates confuses | ||
140 | * constraint matching. | ||
141 | */ | ||
142 | |||
143 | switch (val) { | ||
144 | case 8000: | ||
145 | case 32000: | ||
146 | case 44100: | ||
147 | case 48000: | ||
148 | case 64000: | ||
149 | case 88200: | ||
150 | case 96000: | ||
151 | dev_dbg(component->dev, "Supported sample rate: %dHz\n", | ||
152 | val); | ||
153 | uda1334->rate_constraint_list[j++] = val; | ||
154 | uda1334->rate_constraint.count++; | ||
155 | break; | ||
156 | default: | ||
157 | dev_dbg(component->dev, "Skipping sample rate: %dHz\n", | ||
158 | val); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | /* Need at least one supported rate... */ | ||
163 | if (uda1334->rate_constraint.count == 0) | ||
164 | return -EINVAL; | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int uda1334_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
170 | { | ||
171 | fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK | | ||
172 | SND_SOC_DAIFMT_MASTER_MASK); | ||
173 | |||
174 | if (fmt != (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
175 | SND_SOC_DAIFMT_CBS_CFS)) { | ||
176 | dev_err(codec_dai->dev, "Invalid DAI format\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int uda1334_mute_stream(struct snd_soc_dai *dai, int mute, int stream) | ||
184 | { | ||
185 | struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(dai->component); | ||
186 | |||
187 | if (uda1334->mute) | ||
188 | gpiod_set_value_cansleep(uda1334->mute, mute); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | #define UDA1334_RATES SNDRV_PCM_RATE_8000_96000 | ||
194 | |||
195 | #define UDA1334_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
196 | |||
197 | static const struct snd_soc_dai_ops uda1334_dai_ops = { | ||
198 | .startup = uda1334_startup, | ||
199 | .shutdown = uda1334_shutdown, | ||
200 | .set_sysclk = uda1334_set_dai_sysclk, | ||
201 | .set_fmt = uda1334_set_fmt, | ||
202 | .mute_stream = uda1334_mute_stream, | ||
203 | }; | ||
204 | |||
205 | static struct snd_soc_dai_driver uda1334_dai = { | ||
206 | .name = "uda1334-hifi", | ||
207 | .playback = { | ||
208 | .stream_name = "Playback", | ||
209 | .channels_min = 2, | ||
210 | .channels_max = 2, | ||
211 | .rates = UDA1334_RATES, | ||
212 | .formats = UDA1334_FORMATS, | ||
213 | }, | ||
214 | .ops = &uda1334_dai_ops, | ||
215 | }; | ||
216 | |||
217 | static int uda1334_probe(struct snd_soc_component *component) | ||
218 | { | ||
219 | struct uda1334_priv *uda1334 = snd_soc_component_get_drvdata(component); | ||
220 | |||
221 | uda1334->rate_constraint.list = &uda1334->rate_constraint_list[0]; | ||
222 | uda1334->rate_constraint.count = | ||
223 | ARRAY_SIZE(uda1334->rate_constraint_list); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static const struct snd_soc_component_driver soc_component_dev_uda1334 = { | ||
229 | .probe = uda1334_probe, | ||
230 | .controls = uda1334_snd_controls, | ||
231 | .num_controls = ARRAY_SIZE(uda1334_snd_controls), | ||
232 | .dapm_widgets = uda1334_dapm_widgets, | ||
233 | .num_dapm_widgets = ARRAY_SIZE(uda1334_dapm_widgets), | ||
234 | .dapm_routes = uda1334_dapm_routes, | ||
235 | .num_dapm_routes = ARRAY_SIZE(uda1334_dapm_routes), | ||
236 | .idle_bias_on = 1, | ||
237 | .use_pmdown_time = 1, | ||
238 | .endianness = 1, | ||
239 | .non_legacy_dai_naming = 1, | ||
240 | }; | ||
241 | |||
242 | static const struct of_device_id uda1334_of_match[] = { | ||
243 | { .compatible = "nxp,uda1334" }, | ||
244 | { /* sentinel*/ } | ||
245 | }; | ||
246 | MODULE_DEVICE_TABLE(of, uda1334_of_match); | ||
247 | |||
248 | static int uda1334_codec_probe(struct platform_device *pdev) | ||
249 | { | ||
250 | struct uda1334_priv *uda1334; | ||
251 | int ret; | ||
252 | |||
253 | uda1334 = devm_kzalloc(&pdev->dev, sizeof(struct uda1334_priv), | ||
254 | GFP_KERNEL); | ||
255 | if (!uda1334) | ||
256 | return -ENOMEM; | ||
257 | |||
258 | platform_set_drvdata(pdev, uda1334); | ||
259 | |||
260 | uda1334->mute = devm_gpiod_get(&pdev->dev, "nxp,mute", GPIOD_OUT_LOW); | ||
261 | if (IS_ERR(uda1334->mute)) { | ||
262 | ret = PTR_ERR(uda1334->mute); | ||
263 | dev_err(&pdev->dev, "Failed to get mute line: %d\n", ret); | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | uda1334->deemph = devm_gpiod_get(&pdev->dev, "nxp,deemph", GPIOD_OUT_LOW); | ||
268 | if (IS_ERR(uda1334->deemph)) { | ||
269 | ret = PTR_ERR(uda1334->deemph); | ||
270 | dev_err(&pdev->dev, "Failed to get deemph line: %d\n", ret); | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
275 | &soc_component_dev_uda1334, | ||
276 | &uda1334_dai, 1); | ||
277 | if (ret < 0) | ||
278 | dev_err(&pdev->dev, "Failed to register component: %d\n", ret); | ||
279 | |||
280 | return ret; | ||
281 | } | ||
282 | |||
283 | static struct platform_driver uda1334_codec_driver = { | ||
284 | .probe = uda1334_codec_probe, | ||
285 | .driver = { | ||
286 | .name = "uda1334-codec", | ||
287 | .of_match_table = uda1334_of_match, | ||
288 | }, | ||
289 | }; | ||
290 | module_platform_driver(uda1334_codec_driver); | ||
291 | |||
292 | MODULE_DESCRIPTION("ASoC UDA1334 driver"); | ||
293 | MODULE_AUTHOR("Andra Danciu <andradanciu1997@gmail.com>"); | ||
294 | MODULE_ALIAS("platform:uda1334-codec"); | ||
295 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/wcd-clsh-v2.c b/sound/soc/codecs/wcd-clsh-v2.c index c397d713f01a..cc5a9c9b918b 100644 --- a/sound/soc/codecs/wcd-clsh-v2.c +++ b/sound/soc/codecs/wcd-clsh-v2.c | |||
@@ -65,7 +65,7 @@ struct wcd_clsh_ctrl { | |||
65 | #define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY 0 | 65 | #define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY 0 |
66 | #define WCD9XXX_RX_BIAS_FLYB_BUFF WCD9335_REG(0x6, 0xC7) | 66 | #define WCD9XXX_RX_BIAS_FLYB_BUFF WCD9335_REG(0x6, 0xC7) |
67 | #define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4) | 67 | #define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4) |
68 | #define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(0, 3) | 68 | #define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(3, 0) |
69 | #define WCD9XXX_HPH_L_EN WCD9335_REG(0x6, 0xD3) | 69 | #define WCD9XXX_HPH_L_EN WCD9335_REG(0x6, 0xD3) |
70 | #define WCD9XXX_HPH_CONST_SEL_L_MASK GENMASK(7, 3) | 70 | #define WCD9XXX_HPH_CONST_SEL_L_MASK GENMASK(7, 3) |
71 | #define WCD9XXX_HPH_CONST_SEL_BYPASS 0 | 71 | #define WCD9XXX_HPH_CONST_SEL_BYPASS 0 |
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 1bbbe421b999..03f8a94bba2f 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c | |||
@@ -2071,9 +2071,10 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = { | |||
2071 | .id = AIF1_PB, | 2071 | .id = AIF1_PB, |
2072 | .playback = { | 2072 | .playback = { |
2073 | .stream_name = "AIF1 Playback", | 2073 | .stream_name = "AIF1 Playback", |
2074 | .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, | 2074 | .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK | |
2075 | SNDRV_PCM_RATE_384000, | ||
2075 | .formats = WCD9335_FORMATS_S16_S24_LE, | 2076 | .formats = WCD9335_FORMATS_S16_S24_LE, |
2076 | .rate_max = 192000, | 2077 | .rate_max = 384000, |
2077 | .rate_min = 8000, | 2078 | .rate_min = 8000, |
2078 | .channels_min = 1, | 2079 | .channels_min = 1, |
2079 | .channels_max = 2, | 2080 | .channels_max = 2, |
@@ -2099,10 +2100,11 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = { | |||
2099 | .id = AIF2_PB, | 2100 | .id = AIF2_PB, |
2100 | .playback = { | 2101 | .playback = { |
2101 | .stream_name = "AIF2 Playback", | 2102 | .stream_name = "AIF2 Playback", |
2102 | .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, | 2103 | .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK | |
2104 | SNDRV_PCM_RATE_384000, | ||
2103 | .formats = WCD9335_FORMATS_S16_S24_LE, | 2105 | .formats = WCD9335_FORMATS_S16_S24_LE, |
2104 | .rate_min = 8000, | 2106 | .rate_min = 8000, |
2105 | .rate_max = 192000, | 2107 | .rate_max = 384000, |
2106 | .channels_min = 1, | 2108 | .channels_min = 1, |
2107 | .channels_max = 2, | 2109 | .channels_max = 2, |
2108 | }, | 2110 | }, |
@@ -2127,10 +2129,11 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = { | |||
2127 | .id = AIF3_PB, | 2129 | .id = AIF3_PB, |
2128 | .playback = { | 2130 | .playback = { |
2129 | .stream_name = "AIF3 Playback", | 2131 | .stream_name = "AIF3 Playback", |
2130 | .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, | 2132 | .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK | |
2133 | SNDRV_PCM_RATE_384000, | ||
2131 | .formats = WCD9335_FORMATS_S16_S24_LE, | 2134 | .formats = WCD9335_FORMATS_S16_S24_LE, |
2132 | .rate_min = 8000, | 2135 | .rate_min = 8000, |
2133 | .rate_max = 192000, | 2136 | .rate_max = 384000, |
2134 | .channels_min = 1, | 2137 | .channels_min = 1, |
2135 | .channels_max = 2, | 2138 | .channels_max = 2, |
2136 | }, | 2139 | }, |
@@ -2155,10 +2158,11 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = { | |||
2155 | .id = AIF4_PB, | 2158 | .id = AIF4_PB, |
2156 | .playback = { | 2159 | .playback = { |
2157 | .stream_name = "AIF4 Playback", | 2160 | .stream_name = "AIF4 Playback", |
2158 | .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK, | 2161 | .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK | |
2162 | SNDRV_PCM_RATE_384000, | ||
2159 | .formats = WCD9335_FORMATS_S16_S24_LE, | 2163 | .formats = WCD9335_FORMATS_S16_S24_LE, |
2160 | .rate_min = 8000, | 2164 | .rate_min = 8000, |
2161 | .rate_max = 192000, | 2165 | .rate_max = 384000, |
2162 | .channels_min = 1, | 2166 | .channels_min = 1, |
2163 | .channels_max = 2, | 2167 | .channels_max = 2, |
2164 | }, | 2168 | }, |
@@ -4062,7 +4066,8 @@ static int wcd9335_setup_irqs(struct wcd9335_codec *wcd) | |||
4062 | 4066 | ||
4063 | ret = devm_request_threaded_irq(wcd->dev, irq, NULL, | 4067 | ret = devm_request_threaded_irq(wcd->dev, irq, NULL, |
4064 | wcd9335_irqs[i].handler, | 4068 | wcd9335_irqs[i].handler, |
4065 | IRQF_TRIGGER_RISING, | 4069 | IRQF_TRIGGER_RISING | |
4070 | IRQF_ONESHOT, | ||
4066 | wcd9335_irqs[i].name, wcd); | 4071 | wcd9335_irqs[i].name, wcd); |
4067 | if (ret) { | 4072 | if (ret) { |
4068 | dev_err(wcd->dev, "Failed to request %s\n", | 4073 | dev_err(wcd->dev, "Failed to request %s\n", |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 66a5f1827aa9..9c7e2892c8cb 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -140,7 +140,7 @@ struct pll_factors { | |||
140 | * to allow rounding later */ | 140 | * to allow rounding later */ |
141 | #define FIXED_FLL_SIZE ((1 << 22) * 10) | 141 | #define FIXED_FLL_SIZE ((1 << 22) * 10) |
142 | 142 | ||
143 | static int wm8995_pll_factors(struct device *dev, | 143 | static int wm8955_pll_factors(struct device *dev, |
144 | int Fref, int Fout, struct pll_factors *pll) | 144 | int Fref, int Fout, struct pll_factors *pll) |
145 | { | 145 | { |
146 | u64 Kpart; | 146 | u64 Kpart; |
@@ -279,7 +279,7 @@ static int wm8955_configure_clocking(struct snd_soc_component *component) | |||
279 | 279 | ||
280 | /* Use the last divider configuration we saw for the | 280 | /* Use the last divider configuration we saw for the |
281 | * sample rate. */ | 281 | * sample rate. */ |
282 | ret = wm8995_pll_factors(component->dev, wm8955->mclk_rate, | 282 | ret = wm8955_pll_factors(component->dev, wm8955->mclk_rate, |
283 | clock_cfgs[sr].mclk, &pll); | 283 | clock_cfgs[sr].mclk, &pll); |
284 | if (ret != 0) { | 284 | if (ret != 0) { |
285 | dev_err(component->dev, | 285 | dev_err(component->dev, |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 25e74cf0666a..85bfd041d546 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -273,7 +273,7 @@ static const struct soc_enum wm8988_rline_enum = | |||
273 | wm8988_line_texts, | 273 | wm8988_line_texts, |
274 | wm8988_line_values); | 274 | wm8988_line_values); |
275 | static const struct snd_kcontrol_new wm8988_right_line_controls = | 275 | static const struct snd_kcontrol_new wm8988_right_line_controls = |
276 | SOC_DAPM_ENUM("Route", wm8988_lline_enum); | 276 | SOC_DAPM_ENUM("Route", wm8988_rline_enum); |
277 | 277 | ||
278 | /* Left Mixer */ | 278 | /* Left Mixer */ |
279 | static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = { | 279 | static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = { |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f5fbadc5e7e2..ae28d9907c30 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -4242,8 +4242,9 @@ static void wm_adsp_fatal_error(struct wm_adsp *dsp) | |||
4242 | } | 4242 | } |
4243 | } | 4243 | } |
4244 | 4244 | ||
4245 | irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp) | 4245 | irqreturn_t wm_adsp2_bus_error(int irq, void *data) |
4246 | { | 4246 | { |
4247 | struct wm_adsp *dsp = (struct wm_adsp *)data; | ||
4247 | unsigned int val; | 4248 | unsigned int val; |
4248 | struct regmap *regmap = dsp->regmap; | 4249 | struct regmap *regmap = dsp->regmap; |
4249 | int ret = 0; | 4250 | int ret = 0; |
@@ -4307,8 +4308,9 @@ error: | |||
4307 | } | 4308 | } |
4308 | EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); | 4309 | EXPORT_SYMBOL_GPL(wm_adsp2_bus_error); |
4309 | 4310 | ||
4310 | irqreturn_t wm_halo_bus_error(struct wm_adsp *dsp) | 4311 | irqreturn_t wm_halo_bus_error(int irq, void *data) |
4311 | { | 4312 | { |
4313 | struct wm_adsp *dsp = (struct wm_adsp *)data; | ||
4312 | struct regmap *regmap = dsp->regmap; | 4314 | struct regmap *regmap = dsp->regmap; |
4313 | unsigned int fault[6]; | 4315 | unsigned int fault[6]; |
4314 | struct reg_sequence clear[] = { | 4316 | struct reg_sequence clear[] = { |
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 3b03d1eb986f..aa634ef6c9f5 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
@@ -171,8 +171,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
171 | int wm_adsp_early_event(struct snd_soc_dapm_widget *w, | 171 | int wm_adsp_early_event(struct snd_soc_dapm_widget *w, |
172 | struct snd_kcontrol *kcontrol, int event); | 172 | struct snd_kcontrol *kcontrol, int event); |
173 | 173 | ||
174 | irqreturn_t wm_adsp2_bus_error(struct wm_adsp *adsp); | 174 | irqreturn_t wm_adsp2_bus_error(int irq, void *data); |
175 | irqreturn_t wm_halo_bus_error(struct wm_adsp *dsp); | 175 | irqreturn_t wm_halo_bus_error(int irq, void *data); |
176 | irqreturn_t wm_halo_wdt_expire(int irq, void *data); | 176 | irqreturn_t wm_halo_wdt_expire(int irq, void *data); |
177 | 177 | ||
178 | int wm_adsp_event(struct snd_soc_dapm_widget *w, | 178 | int wm_adsp_event(struct snd_soc_dapm_widget *w, |
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index cbbf6257f08a..cfa40ef6b1ca 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c | |||
@@ -885,10 +885,8 @@ static int fsl_asrc_probe(struct platform_device *pdev) | |||
885 | } | 885 | } |
886 | 886 | ||
887 | irq = platform_get_irq(pdev, 0); | 887 | irq = platform_get_irq(pdev, 0); |
888 | if (irq < 0) { | 888 | if (irq < 0) |
889 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); | ||
890 | return irq; | 889 | return irq; |
891 | } | ||
892 | 890 | ||
893 | ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, | 891 | ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, |
894 | dev_name(&pdev->dev), asrc_priv); | 892 | dev_name(&pdev->dev), asrc_priv); |
diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 3897a54a11fe..c7e4e9757dce 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c | |||
@@ -458,7 +458,6 @@ static int fsl_audmix_probe(struct platform_device *pdev) | |||
458 | { | 458 | { |
459 | struct device *dev = &pdev->dev; | 459 | struct device *dev = &pdev->dev; |
460 | struct fsl_audmix *priv; | 460 | struct fsl_audmix *priv; |
461 | struct resource *res; | ||
462 | const char *mdrv; | 461 | const char *mdrv; |
463 | const struct of_device_id *of_id; | 462 | const struct of_device_id *of_id; |
464 | void __iomem *regs; | 463 | void __iomem *regs; |
@@ -475,8 +474,7 @@ static int fsl_audmix_probe(struct platform_device *pdev) | |||
475 | return -ENOMEM; | 474 | return -ENOMEM; |
476 | 475 | ||
477 | /* Get the addresses */ | 476 | /* Get the addresses */ |
478 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 477 | regs = devm_platform_ioremap_resource(pdev, 0); |
479 | regs = devm_ioremap_resource(dev, res); | ||
480 | if (IS_ERR(regs)) | 478 | if (IS_ERR(regs)) |
481 | return PTR_ERR(regs); | 479 | return PTR_ERR(regs); |
482 | 480 | ||
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 10d2210c91ef..a78e4ab478df 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -32,15 +32,18 @@ | |||
32 | * @extalclk: esai clock source to derive HCK, SCK and FS | 32 | * @extalclk: esai clock source to derive HCK, SCK and FS |
33 | * @fsysclk: system clock source to derive HCK, SCK and FS | 33 | * @fsysclk: system clock source to derive HCK, SCK and FS |
34 | * @spbaclk: SPBA clock (optional, depending on SoC design) | 34 | * @spbaclk: SPBA clock (optional, depending on SoC design) |
35 | * @task: tasklet to handle the reset operation | ||
35 | * @fifo_depth: depth of tx/rx FIFO | 36 | * @fifo_depth: depth of tx/rx FIFO |
36 | * @slot_width: width of each DAI slot | 37 | * @slot_width: width of each DAI slot |
37 | * @slots: number of slots | 38 | * @slots: number of slots |
39 | * @channels: channel num for tx or rx | ||
38 | * @hck_rate: clock rate of desired HCKx clock | 40 | * @hck_rate: clock rate of desired HCKx clock |
39 | * @sck_rate: clock rate of desired SCKx clock | 41 | * @sck_rate: clock rate of desired SCKx clock |
40 | * @hck_dir: the direction of HCKx pads | 42 | * @hck_dir: the direction of HCKx pads |
41 | * @sck_div: if using PSR/PM dividers for SCKx clock | 43 | * @sck_div: if using PSR/PM dividers for SCKx clock |
42 | * @slave_mode: if fully using DAI slave mode | 44 | * @slave_mode: if fully using DAI slave mode |
43 | * @synchronous: if using tx/rx synchronous mode | 45 | * @synchronous: if using tx/rx synchronous mode |
46 | * @reset_at_xrun: flags for enable reset operaton | ||
44 | * @name: driver name | 47 | * @name: driver name |
45 | */ | 48 | */ |
46 | struct fsl_esai { | 49 | struct fsl_esai { |
@@ -52,17 +55,20 @@ struct fsl_esai { | |||
52 | struct clk *extalclk; | 55 | struct clk *extalclk; |
53 | struct clk *fsysclk; | 56 | struct clk *fsysclk; |
54 | struct clk *spbaclk; | 57 | struct clk *spbaclk; |
58 | struct tasklet_struct task; | ||
55 | u32 fifo_depth; | 59 | u32 fifo_depth; |
56 | u32 slot_width; | 60 | u32 slot_width; |
57 | u32 slots; | 61 | u32 slots; |
58 | u32 tx_mask; | 62 | u32 tx_mask; |
59 | u32 rx_mask; | 63 | u32 rx_mask; |
64 | u32 channels[2]; | ||
60 | u32 hck_rate[2]; | 65 | u32 hck_rate[2]; |
61 | u32 sck_rate[2]; | 66 | u32 sck_rate[2]; |
62 | bool hck_dir[2]; | 67 | bool hck_dir[2]; |
63 | bool sck_div[2]; | 68 | bool sck_div[2]; |
64 | bool slave_mode; | 69 | bool slave_mode; |
65 | bool synchronous; | 70 | bool synchronous; |
71 | bool reset_at_xrun; | ||
66 | char name[32]; | 72 | char name[32]; |
67 | }; | 73 | }; |
68 | 74 | ||
@@ -71,8 +77,16 @@ static irqreturn_t esai_isr(int irq, void *devid) | |||
71 | struct fsl_esai *esai_priv = (struct fsl_esai *)devid; | 77 | struct fsl_esai *esai_priv = (struct fsl_esai *)devid; |
72 | struct platform_device *pdev = esai_priv->pdev; | 78 | struct platform_device *pdev = esai_priv->pdev; |
73 | u32 esr; | 79 | u32 esr; |
80 | u32 saisr; | ||
74 | 81 | ||
75 | regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr); | 82 | regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr); |
83 | regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr); | ||
84 | |||
85 | if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) && | ||
86 | esai_priv->reset_at_xrun) { | ||
87 | dev_dbg(&pdev->dev, "reset module for xrun\n"); | ||
88 | tasklet_schedule(&esai_priv->task); | ||
89 | } | ||
76 | 90 | ||
77 | if (esr & ESAI_ESR_TINIT_MASK) | 91 | if (esr & ESAI_ESR_TINIT_MASK) |
78 | dev_dbg(&pdev->dev, "isr: Transmission Initialized\n"); | 92 | dev_dbg(&pdev->dev, "isr: Transmission Initialized\n"); |
@@ -543,64 +557,184 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, | |||
543 | return 0; | 557 | return 0; |
544 | } | 558 | } |
545 | 559 | ||
560 | static int fsl_esai_hw_init(struct fsl_esai *esai_priv) | ||
561 | { | ||
562 | struct platform_device *pdev = esai_priv->pdev; | ||
563 | int ret; | ||
564 | |||
565 | /* Reset ESAI unit */ | ||
566 | ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, | ||
567 | ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK, | ||
568 | ESAI_ECR_ESAIEN | ESAI_ECR_ERST); | ||
569 | if (ret) { | ||
570 | dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); | ||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | /* | ||
575 | * We need to enable ESAI so as to access some of its registers. | ||
576 | * Otherwise, we would fail to dump regmap from user space. | ||
577 | */ | ||
578 | ret = regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, | ||
579 | ESAI_ECR_ESAIEN_MASK | ESAI_ECR_ERST_MASK, | ||
580 | ESAI_ECR_ESAIEN); | ||
581 | if (ret) { | ||
582 | dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); | ||
583 | return ret; | ||
584 | } | ||
585 | |||
586 | regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, | ||
587 | ESAI_PRRC_PDC_MASK, 0); | ||
588 | regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, | ||
589 | ESAI_PCRC_PC_MASK, 0); | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static int fsl_esai_register_restore(struct fsl_esai *esai_priv) | ||
595 | { | ||
596 | int ret; | ||
597 | |||
598 | /* FIFO reset for safety */ | ||
599 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, | ||
600 | ESAI_xFCR_xFR, ESAI_xFCR_xFR); | ||
601 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, | ||
602 | ESAI_xFCR_xFR, ESAI_xFCR_xFR); | ||
603 | |||
604 | regcache_mark_dirty(esai_priv->regmap); | ||
605 | ret = regcache_sync(esai_priv->regmap); | ||
606 | if (ret) | ||
607 | return ret; | ||
608 | |||
609 | /* FIFO reset done */ | ||
610 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); | ||
611 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); | ||
612 | |||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static void fsl_esai_trigger_start(struct fsl_esai *esai_priv, bool tx) | ||
617 | { | ||
618 | u8 i, channels = esai_priv->channels[tx]; | ||
619 | u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); | ||
620 | u32 mask; | ||
621 | |||
622 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
623 | ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); | ||
624 | |||
625 | /* Write initial words reqiured by ESAI as normal procedure */ | ||
626 | for (i = 0; tx && i < channels; i++) | ||
627 | regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); | ||
628 | |||
629 | /* | ||
630 | * When set the TE/RE in the end of enablement flow, there | ||
631 | * will be channel swap issue for multi data line case. | ||
632 | * In order to workaround this issue, we switch the bit | ||
633 | * enablement sequence to below sequence | ||
634 | * 1) clear the xSMB & xSMA: which is done in probe and | ||
635 | * stop state. | ||
636 | * 2) set TE/RE | ||
637 | * 3) set xSMB | ||
638 | * 4) set xSMA: xSMA is the last one in this flow, which | ||
639 | * will trigger esai to start. | ||
640 | */ | ||
641 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | ||
642 | tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, | ||
643 | tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); | ||
644 | mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; | ||
645 | |||
646 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), | ||
647 | ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); | ||
648 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), | ||
649 | ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); | ||
650 | |||
651 | /* Enable Exception interrupt */ | ||
652 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | ||
653 | ESAI_xCR_xEIE_MASK, ESAI_xCR_xEIE); | ||
654 | } | ||
655 | |||
656 | static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx) | ||
657 | { | ||
658 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | ||
659 | ESAI_xCR_xEIE_MASK, 0); | ||
660 | |||
661 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | ||
662 | tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); | ||
663 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), | ||
664 | ESAI_xSMA_xS_MASK, 0); | ||
665 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), | ||
666 | ESAI_xSMB_xS_MASK, 0); | ||
667 | |||
668 | /* Disable and reset FIFO */ | ||
669 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
670 | ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); | ||
671 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
672 | ESAI_xFCR_xFR, 0); | ||
673 | } | ||
674 | |||
675 | static void fsl_esai_hw_reset(unsigned long arg) | ||
676 | { | ||
677 | struct fsl_esai *esai_priv = (struct fsl_esai *)arg; | ||
678 | bool tx = true, rx = false, enabled[2]; | ||
679 | u32 tfcr, rfcr; | ||
680 | |||
681 | /* Save the registers */ | ||
682 | regmap_read(esai_priv->regmap, REG_ESAI_TFCR, &tfcr); | ||
683 | regmap_read(esai_priv->regmap, REG_ESAI_RFCR, &rfcr); | ||
684 | enabled[tx] = tfcr & ESAI_xFCR_xFEN; | ||
685 | enabled[rx] = rfcr & ESAI_xFCR_xFEN; | ||
686 | |||
687 | /* Stop the tx & rx */ | ||
688 | fsl_esai_trigger_stop(esai_priv, tx); | ||
689 | fsl_esai_trigger_stop(esai_priv, rx); | ||
690 | |||
691 | /* Reset the esai, and ignore return value */ | ||
692 | fsl_esai_hw_init(esai_priv); | ||
693 | |||
694 | /* Enforce ESAI personal resets for both TX and RX */ | ||
695 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, | ||
696 | ESAI_xCR_xPR_MASK, ESAI_xCR_xPR); | ||
697 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, | ||
698 | ESAI_xCR_xPR_MASK, ESAI_xCR_xPR); | ||
699 | |||
700 | /* Restore registers by regcache_sync, and ignore return value */ | ||
701 | fsl_esai_register_restore(esai_priv); | ||
702 | |||
703 | /* Remove ESAI personal resets by configuring PCRC and PRRC also */ | ||
704 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, | ||
705 | ESAI_xCR_xPR_MASK, 0); | ||
706 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, | ||
707 | ESAI_xCR_xPR_MASK, 0); | ||
708 | regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, | ||
709 | ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); | ||
710 | regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, | ||
711 | ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); | ||
712 | |||
713 | /* Restart tx / rx, if they already enabled */ | ||
714 | if (enabled[tx]) | ||
715 | fsl_esai_trigger_start(esai_priv, tx); | ||
716 | if (enabled[rx]) | ||
717 | fsl_esai_trigger_start(esai_priv, rx); | ||
718 | } | ||
719 | |||
546 | static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, | 720 | static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, |
547 | struct snd_soc_dai *dai) | 721 | struct snd_soc_dai *dai) |
548 | { | 722 | { |
549 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | 723 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); |
550 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 724 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
551 | u8 i, channels = substream->runtime->channels; | 725 | |
552 | u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); | 726 | esai_priv->channels[tx] = substream->runtime->channels; |
553 | u32 mask; | ||
554 | 727 | ||
555 | switch (cmd) { | 728 | switch (cmd) { |
556 | case SNDRV_PCM_TRIGGER_START: | 729 | case SNDRV_PCM_TRIGGER_START: |
557 | case SNDRV_PCM_TRIGGER_RESUME: | 730 | case SNDRV_PCM_TRIGGER_RESUME: |
558 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 731 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
559 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | 732 | fsl_esai_trigger_start(esai_priv, tx); |
560 | ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); | ||
561 | |||
562 | /* Write initial words reqiured by ESAI as normal procedure */ | ||
563 | for (i = 0; tx && i < channels; i++) | ||
564 | regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); | ||
565 | |||
566 | /* | ||
567 | * When set the TE/RE in the end of enablement flow, there | ||
568 | * will be channel swap issue for multi data line case. | ||
569 | * In order to workaround this issue, we switch the bit | ||
570 | * enablement sequence to below sequence | ||
571 | * 1) clear the xSMB & xSMA: which is done in probe and | ||
572 | * stop state. | ||
573 | * 2) set TE/RE | ||
574 | * 3) set xSMB | ||
575 | * 4) set xSMA: xSMA is the last one in this flow, which | ||
576 | * will trigger esai to start. | ||
577 | */ | ||
578 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | ||
579 | tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, | ||
580 | tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins)); | ||
581 | mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask; | ||
582 | |||
583 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), | ||
584 | ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask)); | ||
585 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), | ||
586 | ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask)); | ||
587 | |||
588 | break; | 733 | break; |
589 | case SNDRV_PCM_TRIGGER_SUSPEND: | 734 | case SNDRV_PCM_TRIGGER_SUSPEND: |
590 | case SNDRV_PCM_TRIGGER_STOP: | 735 | case SNDRV_PCM_TRIGGER_STOP: |
591 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 736 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
592 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), | 737 | fsl_esai_trigger_stop(esai_priv, tx); |
593 | tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); | ||
594 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx), | ||
595 | ESAI_xSMA_xS_MASK, 0); | ||
596 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx), | ||
597 | ESAI_xSMB_xS_MASK, 0); | ||
598 | |||
599 | /* Disable and reset FIFO */ | ||
600 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
601 | ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); | ||
602 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), | ||
603 | ESAI_xFCR_xFR, 0); | ||
604 | break; | 738 | break; |
605 | default: | 739 | default: |
606 | return -EINVAL; | 740 | return -EINVAL; |
@@ -787,6 +921,10 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
787 | esai_priv->pdev = pdev; | 921 | esai_priv->pdev = pdev; |
788 | snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np); | 922 | snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np); |
789 | 923 | ||
924 | if (of_device_is_compatible(np, "fsl,vf610-esai") || | ||
925 | of_device_is_compatible(np, "fsl,imx35-esai")) | ||
926 | esai_priv->reset_at_xrun = true; | ||
927 | |||
790 | /* Get the addresses and IRQ */ | 928 | /* Get the addresses and IRQ */ |
791 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 929 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
792 | regs = devm_ioremap_resource(&pdev->dev, res); | 930 | regs = devm_ioremap_resource(&pdev->dev, res); |
@@ -824,10 +962,8 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
824 | PTR_ERR(esai_priv->spbaclk)); | 962 | PTR_ERR(esai_priv->spbaclk)); |
825 | 963 | ||
826 | irq = platform_get_irq(pdev, 0); | 964 | irq = platform_get_irq(pdev, 0); |
827 | if (irq < 0) { | 965 | if (irq < 0) |
828 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); | ||
829 | return irq; | 966 | return irq; |
830 | } | ||
831 | 967 | ||
832 | ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0, | 968 | ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0, |
833 | esai_priv->name, esai_priv); | 969 | esai_priv->name, esai_priv); |
@@ -866,22 +1002,9 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
866 | 1002 | ||
867 | dev_set_drvdata(&pdev->dev, esai_priv); | 1003 | dev_set_drvdata(&pdev->dev, esai_priv); |
868 | 1004 | ||
869 | /* Reset ESAI unit */ | 1005 | ret = fsl_esai_hw_init(esai_priv); |
870 | ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST); | 1006 | if (ret) |
871 | if (ret) { | ||
872 | dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); | ||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | /* | ||
877 | * We need to enable ESAI so as to access some of its registers. | ||
878 | * Otherwise, we would fail to dump regmap from user space. | ||
879 | */ | ||
880 | ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN); | ||
881 | if (ret) { | ||
882 | dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); | ||
883 | return ret; | 1007 | return ret; |
884 | } | ||
885 | 1008 | ||
886 | esai_priv->tx_mask = 0xFFFFFFFF; | 1009 | esai_priv->tx_mask = 0xFFFFFFFF; |
887 | esai_priv->rx_mask = 0xFFFFFFFF; | 1010 | esai_priv->rx_mask = 0xFFFFFFFF; |
@@ -899,6 +1022,9 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
899 | return ret; | 1022 | return ret; |
900 | } | 1023 | } |
901 | 1024 | ||
1025 | tasklet_init(&esai_priv->task, fsl_esai_hw_reset, | ||
1026 | (unsigned long)esai_priv); | ||
1027 | |||
902 | pm_runtime_enable(&pdev->dev); | 1028 | pm_runtime_enable(&pdev->dev); |
903 | 1029 | ||
904 | regcache_cache_only(esai_priv->regmap, true); | 1030 | regcache_cache_only(esai_priv->regmap, true); |
@@ -912,7 +1038,10 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
912 | 1038 | ||
913 | static int fsl_esai_remove(struct platform_device *pdev) | 1039 | static int fsl_esai_remove(struct platform_device *pdev) |
914 | { | 1040 | { |
1041 | struct fsl_esai *esai_priv = platform_get_drvdata(pdev); | ||
1042 | |||
915 | pm_runtime_disable(&pdev->dev); | 1043 | pm_runtime_disable(&pdev->dev); |
1044 | tasklet_kill(&esai_priv->task); | ||
916 | 1045 | ||
917 | return 0; | 1046 | return 0; |
918 | } | 1047 | } |
@@ -920,6 +1049,7 @@ static int fsl_esai_remove(struct platform_device *pdev) | |||
920 | static const struct of_device_id fsl_esai_dt_ids[] = { | 1049 | static const struct of_device_id fsl_esai_dt_ids[] = { |
921 | { .compatible = "fsl,imx35-esai", }, | 1050 | { .compatible = "fsl,imx35-esai", }, |
922 | { .compatible = "fsl,vf610-esai", }, | 1051 | { .compatible = "fsl,vf610-esai", }, |
1052 | { .compatible = "fsl,imx6ull-esai", }, | ||
923 | {} | 1053 | {} |
924 | }; | 1054 | }; |
925 | MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); | 1055 | MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); |
@@ -955,20 +1085,10 @@ static int fsl_esai_runtime_resume(struct device *dev) | |||
955 | 1085 | ||
956 | regcache_cache_only(esai->regmap, false); | 1086 | regcache_cache_only(esai->regmap, false); |
957 | 1087 | ||
958 | /* FIFO reset for safety */ | 1088 | ret = fsl_esai_register_restore(esai); |
959 | regmap_update_bits(esai->regmap, REG_ESAI_TFCR, | ||
960 | ESAI_xFCR_xFR, ESAI_xFCR_xFR); | ||
961 | regmap_update_bits(esai->regmap, REG_ESAI_RFCR, | ||
962 | ESAI_xFCR_xFR, ESAI_xFCR_xFR); | ||
963 | |||
964 | ret = regcache_sync(esai->regmap); | ||
965 | if (ret) | 1089 | if (ret) |
966 | goto err_regcache_sync; | 1090 | goto err_regcache_sync; |
967 | 1091 | ||
968 | /* FIFO reset done */ | ||
969 | regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); | ||
970 | regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); | ||
971 | |||
972 | return 0; | 1092 | return 0; |
973 | 1093 | ||
974 | err_regcache_sync: | 1094 | err_regcache_sync: |
@@ -991,7 +1111,6 @@ static int fsl_esai_runtime_suspend(struct device *dev) | |||
991 | struct fsl_esai *esai = dev_get_drvdata(dev); | 1111 | struct fsl_esai *esai = dev_get_drvdata(dev); |
992 | 1112 | ||
993 | regcache_cache_only(esai->regmap, true); | 1113 | regcache_cache_only(esai->regmap, true); |
994 | regcache_mark_dirty(esai->regmap); | ||
995 | 1114 | ||
996 | if (!IS_ERR(esai->fsysclk)) | 1115 | if (!IS_ERR(esai->fsysclk)) |
997 | clk_disable_unprepare(esai->fsysclk); | 1116 | clk_disable_unprepare(esai->fsysclk); |
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index d58cc3ae90d8..728307acab90 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/dmaengine.h> | 9 | #include <linux/dmaengine.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/of_address.h> | 11 | #include <linux/of_address.h> |
12 | #include <linux/of_device.h> | ||
12 | #include <linux/pm_runtime.h> | 13 | #include <linux/pm_runtime.h> |
13 | #include <linux/regmap.h> | 14 | #include <linux/regmap.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
@@ -39,6 +40,7 @@ static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = { | |||
39 | static irqreturn_t fsl_sai_isr(int irq, void *devid) | 40 | static irqreturn_t fsl_sai_isr(int irq, void *devid) |
40 | { | 41 | { |
41 | struct fsl_sai *sai = (struct fsl_sai *)devid; | 42 | struct fsl_sai *sai = (struct fsl_sai *)devid; |
43 | unsigned int ofs = sai->soc_data->reg_offset; | ||
42 | struct device *dev = &sai->pdev->dev; | 44 | struct device *dev = &sai->pdev->dev; |
43 | u32 flags, xcsr, mask; | 45 | u32 flags, xcsr, mask; |
44 | bool irq_none = true; | 46 | bool irq_none = true; |
@@ -51,7 +53,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid) | |||
51 | mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT; | 53 | mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT; |
52 | 54 | ||
53 | /* Tx IRQ */ | 55 | /* Tx IRQ */ |
54 | regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr); | 56 | regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr); |
55 | flags = xcsr & mask; | 57 | flags = xcsr & mask; |
56 | 58 | ||
57 | if (flags) | 59 | if (flags) |
@@ -81,11 +83,11 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid) | |||
81 | xcsr &= ~FSL_SAI_CSR_xF_MASK; | 83 | xcsr &= ~FSL_SAI_CSR_xF_MASK; |
82 | 84 | ||
83 | if (flags) | 85 | if (flags) |
84 | regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr); | 86 | regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr); |
85 | 87 | ||
86 | irq_rx: | 88 | irq_rx: |
87 | /* Rx IRQ */ | 89 | /* Rx IRQ */ |
88 | regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr); | 90 | regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr); |
89 | flags = xcsr & mask; | 91 | flags = xcsr & mask; |
90 | 92 | ||
91 | if (flags) | 93 | if (flags) |
@@ -115,7 +117,7 @@ irq_rx: | |||
115 | xcsr &= ~FSL_SAI_CSR_xF_MASK; | 117 | xcsr &= ~FSL_SAI_CSR_xF_MASK; |
116 | 118 | ||
117 | if (flags) | 119 | if (flags) |
118 | regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr); | 120 | regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr); |
119 | 121 | ||
120 | out: | 122 | out: |
121 | if (irq_none) | 123 | if (irq_none) |
@@ -139,6 +141,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, | |||
139 | int clk_id, unsigned int freq, int fsl_dir) | 141 | int clk_id, unsigned int freq, int fsl_dir) |
140 | { | 142 | { |
141 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 143 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
144 | unsigned int ofs = sai->soc_data->reg_offset; | ||
142 | bool tx = fsl_dir == FSL_FMT_TRANSMITTER; | 145 | bool tx = fsl_dir == FSL_FMT_TRANSMITTER; |
143 | u32 val_cr2 = 0; | 146 | u32 val_cr2 = 0; |
144 | 147 | ||
@@ -159,7 +162,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, | |||
159 | return -EINVAL; | 162 | return -EINVAL; |
160 | } | 163 | } |
161 | 164 | ||
162 | regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx), | 165 | regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), |
163 | FSL_SAI_CR2_MSEL_MASK, val_cr2); | 166 | FSL_SAI_CR2_MSEL_MASK, val_cr2); |
164 | 167 | ||
165 | return 0; | 168 | return 0; |
@@ -192,6 +195,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, | |||
192 | unsigned int fmt, int fsl_dir) | 195 | unsigned int fmt, int fsl_dir) |
193 | { | 196 | { |
194 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 197 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
198 | unsigned int ofs = sai->soc_data->reg_offset; | ||
195 | bool tx = fsl_dir == FSL_FMT_TRANSMITTER; | 199 | bool tx = fsl_dir == FSL_FMT_TRANSMITTER; |
196 | u32 val_cr2 = 0, val_cr4 = 0; | 200 | u32 val_cr2 = 0, val_cr4 = 0; |
197 | 201 | ||
@@ -286,9 +290,9 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, | |||
286 | return -EINVAL; | 290 | return -EINVAL; |
287 | } | 291 | } |
288 | 292 | ||
289 | regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx), | 293 | regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), |
290 | FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2); | 294 | FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2); |
291 | regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx), | 295 | regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), |
292 | FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE | | 296 | FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE | |
293 | FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4); | 297 | FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4); |
294 | 298 | ||
@@ -315,6 +319,7 @@ static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | |||
315 | static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) | 319 | static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) |
316 | { | 320 | { |
317 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai); | 321 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai); |
322 | unsigned int ofs = sai->soc_data->reg_offset; | ||
318 | unsigned long clk_rate; | 323 | unsigned long clk_rate; |
319 | u32 savediv = 0, ratio, savesub = freq; | 324 | u32 savediv = 0, ratio, savesub = freq; |
320 | u32 id; | 325 | u32 id; |
@@ -377,17 +382,17 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) | |||
377 | */ | 382 | */ |
378 | if ((sai->synchronous[TX] && !sai->synchronous[RX]) || | 383 | if ((sai->synchronous[TX] && !sai->synchronous[RX]) || |
379 | (!tx && !sai->synchronous[RX])) { | 384 | (!tx && !sai->synchronous[RX])) { |
380 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, | 385 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), |
381 | FSL_SAI_CR2_MSEL_MASK, | 386 | FSL_SAI_CR2_MSEL_MASK, |
382 | FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); | 387 | FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); |
383 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, | 388 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), |
384 | FSL_SAI_CR2_DIV_MASK, savediv - 1); | 389 | FSL_SAI_CR2_DIV_MASK, savediv - 1); |
385 | } else if ((sai->synchronous[RX] && !sai->synchronous[TX]) || | 390 | } else if ((sai->synchronous[RX] && !sai->synchronous[TX]) || |
386 | (tx && !sai->synchronous[TX])) { | 391 | (tx && !sai->synchronous[TX])) { |
387 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2, | 392 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), |
388 | FSL_SAI_CR2_MSEL_MASK, | 393 | FSL_SAI_CR2_MSEL_MASK, |
389 | FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); | 394 | FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); |
390 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2, | 395 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), |
391 | FSL_SAI_CR2_DIV_MASK, savediv - 1); | 396 | FSL_SAI_CR2_DIV_MASK, savediv - 1); |
392 | } | 397 | } |
393 | 398 | ||
@@ -402,6 +407,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | |||
402 | struct snd_soc_dai *cpu_dai) | 407 | struct snd_soc_dai *cpu_dai) |
403 | { | 408 | { |
404 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 409 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
410 | unsigned int ofs = sai->soc_data->reg_offset; | ||
405 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 411 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
406 | unsigned int channels = params_channels(params); | 412 | unsigned int channels = params_channels(params); |
407 | u32 word_width = params_width(params); | 413 | u32 word_width = params_width(params); |
@@ -454,19 +460,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | |||
454 | 460 | ||
455 | if (!sai->is_slave_mode) { | 461 | if (!sai->is_slave_mode) { |
456 | if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) { | 462 | if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) { |
457 | regmap_update_bits(sai->regmap, FSL_SAI_TCR4, | 463 | regmap_update_bits(sai->regmap, FSL_SAI_TCR4(ofs), |
458 | FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, | 464 | FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, |
459 | val_cr4); | 465 | val_cr4); |
460 | regmap_update_bits(sai->regmap, FSL_SAI_TCR5, | 466 | regmap_update_bits(sai->regmap, FSL_SAI_TCR5(ofs), |
461 | FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | | 467 | FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | |
462 | FSL_SAI_CR5_FBT_MASK, val_cr5); | 468 | FSL_SAI_CR5_FBT_MASK, val_cr5); |
463 | regmap_write(sai->regmap, FSL_SAI_TMR, | 469 | regmap_write(sai->regmap, FSL_SAI_TMR, |
464 | ~0UL - ((1 << channels) - 1)); | 470 | ~0UL - ((1 << channels) - 1)); |
465 | } else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) { | 471 | } else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) { |
466 | regmap_update_bits(sai->regmap, FSL_SAI_RCR4, | 472 | regmap_update_bits(sai->regmap, FSL_SAI_RCR4(ofs), |
467 | FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, | 473 | FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, |
468 | val_cr4); | 474 | val_cr4); |
469 | regmap_update_bits(sai->regmap, FSL_SAI_RCR5, | 475 | regmap_update_bits(sai->regmap, FSL_SAI_RCR5(ofs), |
470 | FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | | 476 | FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | |
471 | FSL_SAI_CR5_FBT_MASK, val_cr5); | 477 | FSL_SAI_CR5_FBT_MASK, val_cr5); |
472 | regmap_write(sai->regmap, FSL_SAI_RMR, | 478 | regmap_write(sai->regmap, FSL_SAI_RMR, |
@@ -474,10 +480,10 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | |||
474 | } | 480 | } |
475 | } | 481 | } |
476 | 482 | ||
477 | regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx), | 483 | regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), |
478 | FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, | 484 | FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, |
479 | val_cr4); | 485 | val_cr4); |
480 | regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx), | 486 | regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs), |
481 | FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | | 487 | FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | |
482 | FSL_SAI_CR5_FBT_MASK, val_cr5); | 488 | FSL_SAI_CR5_FBT_MASK, val_cr5); |
483 | regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1)); | 489 | regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1)); |
@@ -505,6 +511,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
505 | struct snd_soc_dai *cpu_dai) | 511 | struct snd_soc_dai *cpu_dai) |
506 | { | 512 | { |
507 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 513 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
514 | unsigned int ofs = sai->soc_data->reg_offset; | ||
515 | |||
508 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 516 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
509 | u32 xcsr, count = 100; | 517 | u32 xcsr, count = 100; |
510 | 518 | ||
@@ -513,9 +521,9 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
513 | * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx. | 521 | * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx. |
514 | * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx. | 522 | * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx. |
515 | */ | 523 | */ |
516 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, | 524 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC, |
517 | sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0); | 525 | sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0); |
518 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, | 526 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC, |
519 | sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0); | 527 | sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0); |
520 | 528 | ||
521 | /* | 529 | /* |
@@ -526,43 +534,44 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
526 | case SNDRV_PCM_TRIGGER_START: | 534 | case SNDRV_PCM_TRIGGER_START: |
527 | case SNDRV_PCM_TRIGGER_RESUME: | 535 | case SNDRV_PCM_TRIGGER_RESUME: |
528 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 536 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
529 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), | 537 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), |
530 | FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); | 538 | FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); |
531 | 539 | ||
532 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | 540 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), |
533 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); | 541 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); |
534 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | 542 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), |
535 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); | 543 | FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); |
536 | 544 | ||
537 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), | 545 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), |
538 | FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS); | 546 | FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS); |
539 | break; | 547 | break; |
540 | case SNDRV_PCM_TRIGGER_STOP: | 548 | case SNDRV_PCM_TRIGGER_STOP: |
541 | case SNDRV_PCM_TRIGGER_SUSPEND: | 549 | case SNDRV_PCM_TRIGGER_SUSPEND: |
542 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 550 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
543 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), | 551 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), |
544 | FSL_SAI_CSR_FRDE, 0); | 552 | FSL_SAI_CSR_FRDE, 0); |
545 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx), | 553 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), |
546 | FSL_SAI_CSR_xIE_MASK, 0); | 554 | FSL_SAI_CSR_xIE_MASK, 0); |
547 | 555 | ||
548 | /* Check if the opposite FRDE is also disabled */ | 556 | /* Check if the opposite FRDE is also disabled */ |
549 | regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr); | 557 | regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr); |
550 | if (!(xcsr & FSL_SAI_CSR_FRDE)) { | 558 | if (!(xcsr & FSL_SAI_CSR_FRDE)) { |
551 | /* Disable both directions and reset their FIFOs */ | 559 | /* Disable both directions and reset their FIFOs */ |
552 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | 560 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), |
553 | FSL_SAI_CSR_TERE, 0); | 561 | FSL_SAI_CSR_TERE, 0); |
554 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | 562 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), |
555 | FSL_SAI_CSR_TERE, 0); | 563 | FSL_SAI_CSR_TERE, 0); |
556 | 564 | ||
557 | /* TERE will remain set till the end of current frame */ | 565 | /* TERE will remain set till the end of current frame */ |
558 | do { | 566 | do { |
559 | udelay(10); | 567 | udelay(10); |
560 | regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr); | 568 | regmap_read(sai->regmap, |
569 | FSL_SAI_xCSR(tx, ofs), &xcsr); | ||
561 | } while (--count && xcsr & FSL_SAI_CSR_TERE); | 570 | } while (--count && xcsr & FSL_SAI_CSR_TERE); |
562 | 571 | ||
563 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, | 572 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), |
564 | FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); | 573 | FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); |
565 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, | 574 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), |
566 | FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); | 575 | FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); |
567 | 576 | ||
568 | /* | 577 | /* |
@@ -574,13 +583,13 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
574 | */ | 583 | */ |
575 | if (!sai->is_slave_mode) { | 584 | if (!sai->is_slave_mode) { |
576 | /* Software Reset for both Tx and Rx */ | 585 | /* Software Reset for both Tx and Rx */ |
577 | regmap_write(sai->regmap, | 586 | regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), |
578 | FSL_SAI_TCSR, FSL_SAI_CSR_SR); | 587 | FSL_SAI_CSR_SR); |
579 | regmap_write(sai->regmap, | 588 | regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), |
580 | FSL_SAI_RCSR, FSL_SAI_CSR_SR); | 589 | FSL_SAI_CSR_SR); |
581 | /* Clear SR bit to finish the reset */ | 590 | /* Clear SR bit to finish the reset */ |
582 | regmap_write(sai->regmap, FSL_SAI_TCSR, 0); | 591 | regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); |
583 | regmap_write(sai->regmap, FSL_SAI_RCSR, 0); | 592 | regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); |
584 | } | 593 | } |
585 | } | 594 | } |
586 | break; | 595 | break; |
@@ -595,10 +604,12 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, | |||
595 | struct snd_soc_dai *cpu_dai) | 604 | struct snd_soc_dai *cpu_dai) |
596 | { | 605 | { |
597 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 606 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
607 | unsigned int ofs = sai->soc_data->reg_offset; | ||
598 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 608 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
599 | int ret; | 609 | int ret; |
600 | 610 | ||
601 | regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, | 611 | regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs), |
612 | FSL_SAI_CR3_TRCE_MASK, | ||
602 | FSL_SAI_CR3_TRCE); | 613 | FSL_SAI_CR3_TRCE); |
603 | 614 | ||
604 | ret = snd_pcm_hw_constraint_list(substream->runtime, 0, | 615 | ret = snd_pcm_hw_constraint_list(substream->runtime, 0, |
@@ -611,9 +622,11 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream, | |||
611 | struct snd_soc_dai *cpu_dai) | 622 | struct snd_soc_dai *cpu_dai) |
612 | { | 623 | { |
613 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 624 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
625 | unsigned int ofs = sai->soc_data->reg_offset; | ||
614 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 626 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
615 | 627 | ||
616 | regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0); | 628 | regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs), |
629 | FSL_SAI_CR3_TRCE_MASK, 0); | ||
617 | } | 630 | } |
618 | 631 | ||
619 | static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { | 632 | static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { |
@@ -630,18 +643,20 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { | |||
630 | static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) | 643 | static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) |
631 | { | 644 | { |
632 | struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); | 645 | struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); |
646 | unsigned int ofs = sai->soc_data->reg_offset; | ||
633 | 647 | ||
634 | /* Software Reset for both Tx and Rx */ | 648 | /* Software Reset for both Tx and Rx */ |
635 | regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); | 649 | regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); |
636 | regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR); | 650 | regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); |
637 | /* Clear SR bit to finish the reset */ | 651 | /* Clear SR bit to finish the reset */ |
638 | regmap_write(sai->regmap, FSL_SAI_TCSR, 0); | 652 | regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); |
639 | regmap_write(sai->regmap, FSL_SAI_RCSR, 0); | 653 | regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); |
640 | 654 | ||
641 | regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, | 655 | regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs), |
642 | FSL_SAI_MAXBURST_TX * 2); | 656 | FSL_SAI_CR1_RFW_MASK, |
643 | regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, | 657 | sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX); |
644 | FSL_SAI_MAXBURST_RX - 1); | 658 | regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs), |
659 | FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1); | ||
645 | 660 | ||
646 | snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, | 661 | snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, |
647 | &sai->dma_params_rx); | 662 | &sai->dma_params_rx); |
@@ -678,41 +693,89 @@ static const struct snd_soc_component_driver fsl_component = { | |||
678 | .name = "fsl-sai", | 693 | .name = "fsl-sai", |
679 | }; | 694 | }; |
680 | 695 | ||
681 | static struct reg_default fsl_sai_reg_defaults[] = { | 696 | static struct reg_default fsl_sai_reg_defaults_ofs0[] = { |
682 | {FSL_SAI_TCR1, 0}, | 697 | {FSL_SAI_TCR1(0), 0}, |
683 | {FSL_SAI_TCR2, 0}, | 698 | {FSL_SAI_TCR2(0), 0}, |
684 | {FSL_SAI_TCR3, 0}, | 699 | {FSL_SAI_TCR3(0), 0}, |
685 | {FSL_SAI_TCR4, 0}, | 700 | {FSL_SAI_TCR4(0), 0}, |
686 | {FSL_SAI_TCR5, 0}, | 701 | {FSL_SAI_TCR5(0), 0}, |
687 | {FSL_SAI_TDR, 0}, | 702 | {FSL_SAI_TDR0, 0}, |
688 | {FSL_SAI_TMR, 0}, | 703 | {FSL_SAI_TDR1, 0}, |
689 | {FSL_SAI_RCR1, 0}, | 704 | {FSL_SAI_TDR2, 0}, |
690 | {FSL_SAI_RCR2, 0}, | 705 | {FSL_SAI_TDR3, 0}, |
691 | {FSL_SAI_RCR3, 0}, | 706 | {FSL_SAI_TDR4, 0}, |
692 | {FSL_SAI_RCR4, 0}, | 707 | {FSL_SAI_TDR5, 0}, |
693 | {FSL_SAI_RCR5, 0}, | 708 | {FSL_SAI_TDR6, 0}, |
694 | {FSL_SAI_RMR, 0}, | 709 | {FSL_SAI_TDR7, 0}, |
710 | {FSL_SAI_TMR, 0}, | ||
711 | {FSL_SAI_RCR1(0), 0}, | ||
712 | {FSL_SAI_RCR2(0), 0}, | ||
713 | {FSL_SAI_RCR3(0), 0}, | ||
714 | {FSL_SAI_RCR4(0), 0}, | ||
715 | {FSL_SAI_RCR5(0), 0}, | ||
716 | {FSL_SAI_RMR, 0}, | ||
717 | }; | ||
718 | |||
719 | static struct reg_default fsl_sai_reg_defaults_ofs8[] = { | ||
720 | {FSL_SAI_TCR1(8), 0}, | ||
721 | {FSL_SAI_TCR2(8), 0}, | ||
722 | {FSL_SAI_TCR3(8), 0}, | ||
723 | {FSL_SAI_TCR4(8), 0}, | ||
724 | {FSL_SAI_TCR5(8), 0}, | ||
725 | {FSL_SAI_TDR0, 0}, | ||
726 | {FSL_SAI_TDR1, 0}, | ||
727 | {FSL_SAI_TDR2, 0}, | ||
728 | {FSL_SAI_TDR3, 0}, | ||
729 | {FSL_SAI_TDR4, 0}, | ||
730 | {FSL_SAI_TDR5, 0}, | ||
731 | {FSL_SAI_TDR6, 0}, | ||
732 | {FSL_SAI_TDR7, 0}, | ||
733 | {FSL_SAI_TMR, 0}, | ||
734 | {FSL_SAI_RCR1(8), 0}, | ||
735 | {FSL_SAI_RCR2(8), 0}, | ||
736 | {FSL_SAI_RCR3(8), 0}, | ||
737 | {FSL_SAI_RCR4(8), 0}, | ||
738 | {FSL_SAI_RCR5(8), 0}, | ||
739 | {FSL_SAI_RMR, 0}, | ||
695 | }; | 740 | }; |
696 | 741 | ||
697 | static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) | 742 | static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) |
698 | { | 743 | { |
744 | struct fsl_sai *sai = dev_get_drvdata(dev); | ||
745 | unsigned int ofs = sai->soc_data->reg_offset; | ||
746 | |||
747 | if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs)) | ||
748 | return true; | ||
749 | |||
750 | if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs)) | ||
751 | return true; | ||
752 | |||
699 | switch (reg) { | 753 | switch (reg) { |
700 | case FSL_SAI_TCSR: | 754 | case FSL_SAI_TFR0: |
701 | case FSL_SAI_TCR1: | 755 | case FSL_SAI_TFR1: |
702 | case FSL_SAI_TCR2: | 756 | case FSL_SAI_TFR2: |
703 | case FSL_SAI_TCR3: | 757 | case FSL_SAI_TFR3: |
704 | case FSL_SAI_TCR4: | 758 | case FSL_SAI_TFR4: |
705 | case FSL_SAI_TCR5: | 759 | case FSL_SAI_TFR5: |
706 | case FSL_SAI_TFR: | 760 | case FSL_SAI_TFR6: |
761 | case FSL_SAI_TFR7: | ||
707 | case FSL_SAI_TMR: | 762 | case FSL_SAI_TMR: |
708 | case FSL_SAI_RCSR: | 763 | case FSL_SAI_RDR0: |
709 | case FSL_SAI_RCR1: | 764 | case FSL_SAI_RDR1: |
710 | case FSL_SAI_RCR2: | 765 | case FSL_SAI_RDR2: |
711 | case FSL_SAI_RCR3: | 766 | case FSL_SAI_RDR3: |
712 | case FSL_SAI_RCR4: | 767 | case FSL_SAI_RDR4: |
713 | case FSL_SAI_RCR5: | 768 | case FSL_SAI_RDR5: |
714 | case FSL_SAI_RDR: | 769 | case FSL_SAI_RDR6: |
715 | case FSL_SAI_RFR: | 770 | case FSL_SAI_RDR7: |
771 | case FSL_SAI_RFR0: | ||
772 | case FSL_SAI_RFR1: | ||
773 | case FSL_SAI_RFR2: | ||
774 | case FSL_SAI_RFR3: | ||
775 | case FSL_SAI_RFR4: | ||
776 | case FSL_SAI_RFR5: | ||
777 | case FSL_SAI_RFR6: | ||
778 | case FSL_SAI_RFR7: | ||
716 | case FSL_SAI_RMR: | 779 | case FSL_SAI_RMR: |
717 | return true; | 780 | return true; |
718 | default: | 781 | default: |
@@ -722,12 +785,37 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) | |||
722 | 785 | ||
723 | static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) | 786 | static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) |
724 | { | 787 | { |
788 | struct fsl_sai *sai = dev_get_drvdata(dev); | ||
789 | unsigned int ofs = sai->soc_data->reg_offset; | ||
790 | |||
791 | if (reg == FSL_SAI_TCSR(ofs) || reg == FSL_SAI_RCSR(ofs)) | ||
792 | return true; | ||
793 | |||
725 | switch (reg) { | 794 | switch (reg) { |
726 | case FSL_SAI_TCSR: | 795 | case FSL_SAI_TFR0: |
727 | case FSL_SAI_RCSR: | 796 | case FSL_SAI_TFR1: |
728 | case FSL_SAI_TFR: | 797 | case FSL_SAI_TFR2: |
729 | case FSL_SAI_RFR: | 798 | case FSL_SAI_TFR3: |
730 | case FSL_SAI_RDR: | 799 | case FSL_SAI_TFR4: |
800 | case FSL_SAI_TFR5: | ||
801 | case FSL_SAI_TFR6: | ||
802 | case FSL_SAI_TFR7: | ||
803 | case FSL_SAI_RFR0: | ||
804 | case FSL_SAI_RFR1: | ||
805 | case FSL_SAI_RFR2: | ||
806 | case FSL_SAI_RFR3: | ||
807 | case FSL_SAI_RFR4: | ||
808 | case FSL_SAI_RFR5: | ||
809 | case FSL_SAI_RFR6: | ||
810 | case FSL_SAI_RFR7: | ||
811 | case FSL_SAI_RDR0: | ||
812 | case FSL_SAI_RDR1: | ||
813 | case FSL_SAI_RDR2: | ||
814 | case FSL_SAI_RDR3: | ||
815 | case FSL_SAI_RDR4: | ||
816 | case FSL_SAI_RDR5: | ||
817 | case FSL_SAI_RDR6: | ||
818 | case FSL_SAI_RDR7: | ||
731 | return true; | 819 | return true; |
732 | default: | 820 | default: |
733 | return false; | 821 | return false; |
@@ -736,21 +824,25 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) | |||
736 | 824 | ||
737 | static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) | 825 | static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) |
738 | { | 826 | { |
827 | struct fsl_sai *sai = dev_get_drvdata(dev); | ||
828 | unsigned int ofs = sai->soc_data->reg_offset; | ||
829 | |||
830 | if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs)) | ||
831 | return true; | ||
832 | |||
833 | if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs)) | ||
834 | return true; | ||
835 | |||
739 | switch (reg) { | 836 | switch (reg) { |
740 | case FSL_SAI_TCSR: | 837 | case FSL_SAI_TDR0: |
741 | case FSL_SAI_TCR1: | 838 | case FSL_SAI_TDR1: |
742 | case FSL_SAI_TCR2: | 839 | case FSL_SAI_TDR2: |
743 | case FSL_SAI_TCR3: | 840 | case FSL_SAI_TDR3: |
744 | case FSL_SAI_TCR4: | 841 | case FSL_SAI_TDR4: |
745 | case FSL_SAI_TCR5: | 842 | case FSL_SAI_TDR5: |
746 | case FSL_SAI_TDR: | 843 | case FSL_SAI_TDR6: |
844 | case FSL_SAI_TDR7: | ||
747 | case FSL_SAI_TMR: | 845 | case FSL_SAI_TMR: |
748 | case FSL_SAI_RCSR: | ||
749 | case FSL_SAI_RCR1: | ||
750 | case FSL_SAI_RCR2: | ||
751 | case FSL_SAI_RCR3: | ||
752 | case FSL_SAI_RCR4: | ||
753 | case FSL_SAI_RCR5: | ||
754 | case FSL_SAI_RMR: | 846 | case FSL_SAI_RMR: |
755 | return true; | 847 | return true; |
756 | default: | 848 | default: |
@@ -758,14 +850,15 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) | |||
758 | } | 850 | } |
759 | } | 851 | } |
760 | 852 | ||
761 | static const struct regmap_config fsl_sai_regmap_config = { | 853 | static struct regmap_config fsl_sai_regmap_config = { |
762 | .reg_bits = 32, | 854 | .reg_bits = 32, |
763 | .reg_stride = 4, | 855 | .reg_stride = 4, |
764 | .val_bits = 32, | 856 | .val_bits = 32, |
857 | .fast_io = true, | ||
765 | 858 | ||
766 | .max_register = FSL_SAI_RMR, | 859 | .max_register = FSL_SAI_RMR, |
767 | .reg_defaults = fsl_sai_reg_defaults, | 860 | .reg_defaults = fsl_sai_reg_defaults_ofs0, |
768 | .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults), | 861 | .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0), |
769 | .readable_reg = fsl_sai_readable_reg, | 862 | .readable_reg = fsl_sai_readable_reg, |
770 | .volatile_reg = fsl_sai_volatile_reg, | 863 | .volatile_reg = fsl_sai_volatile_reg, |
771 | .writeable_reg = fsl_sai_writeable_reg, | 864 | .writeable_reg = fsl_sai_writeable_reg, |
@@ -788,10 +881,7 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
788 | return -ENOMEM; | 881 | return -ENOMEM; |
789 | 882 | ||
790 | sai->pdev = pdev; | 883 | sai->pdev = pdev; |
791 | 884 | sai->soc_data = of_device_get_match_data(&pdev->dev); | |
792 | if (of_device_is_compatible(np, "fsl,imx6sx-sai") || | ||
793 | of_device_is_compatible(np, "fsl,imx6ul-sai")) | ||
794 | sai->sai_on_imx = true; | ||
795 | 885 | ||
796 | sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); | 886 | sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); |
797 | 887 | ||
@@ -800,6 +890,12 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
800 | if (IS_ERR(base)) | 890 | if (IS_ERR(base)) |
801 | return PTR_ERR(base); | 891 | return PTR_ERR(base); |
802 | 892 | ||
893 | if (sai->soc_data->reg_offset == 8) { | ||
894 | fsl_sai_regmap_config.reg_defaults = fsl_sai_reg_defaults_ofs8; | ||
895 | fsl_sai_regmap_config.num_reg_defaults = | ||
896 | ARRAY_SIZE(fsl_sai_reg_defaults_ofs8); | ||
897 | } | ||
898 | |||
803 | sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, | 899 | sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, |
804 | "bus", base, &fsl_sai_regmap_config); | 900 | "bus", base, &fsl_sai_regmap_config); |
805 | 901 | ||
@@ -832,10 +928,8 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
832 | } | 928 | } |
833 | 929 | ||
834 | irq = platform_get_irq(pdev, 0); | 930 | irq = platform_get_irq(pdev, 0); |
835 | if (irq < 0) { | 931 | if (irq < 0) |
836 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); | ||
837 | return irq; | 932 | return irq; |
838 | } | ||
839 | 933 | ||
840 | ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai); | 934 | ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, 0, np->name, sai); |
841 | if (ret) { | 935 | if (ret) { |
@@ -886,8 +980,8 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
886 | MCLK_DIR(index)); | 980 | MCLK_DIR(index)); |
887 | } | 981 | } |
888 | 982 | ||
889 | sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; | 983 | sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0; |
890 | sai->dma_params_tx.addr = res->start + FSL_SAI_TDR; | 984 | sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0; |
891 | sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; | 985 | sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; |
892 | sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; | 986 | sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; |
893 | 987 | ||
@@ -900,7 +994,7 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
900 | if (ret) | 994 | if (ret) |
901 | return ret; | 995 | return ret; |
902 | 996 | ||
903 | if (sai->sai_on_imx) | 997 | if (sai->soc_data->use_imx_pcm) |
904 | return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); | 998 | return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); |
905 | else | 999 | else |
906 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | 1000 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
@@ -913,10 +1007,43 @@ static int fsl_sai_remove(struct platform_device *pdev) | |||
913 | return 0; | 1007 | return 0; |
914 | } | 1008 | } |
915 | 1009 | ||
1010 | static const struct fsl_sai_soc_data fsl_sai_vf610_data = { | ||
1011 | .use_imx_pcm = false, | ||
1012 | .fifo_depth = 32, | ||
1013 | .reg_offset = 0, | ||
1014 | }; | ||
1015 | |||
1016 | static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { | ||
1017 | .use_imx_pcm = true, | ||
1018 | .fifo_depth = 32, | ||
1019 | .reg_offset = 0, | ||
1020 | }; | ||
1021 | |||
1022 | static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = { | ||
1023 | .use_imx_pcm = true, | ||
1024 | .fifo_depth = 16, | ||
1025 | .reg_offset = 8, | ||
1026 | }; | ||
1027 | |||
1028 | static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = { | ||
1029 | .use_imx_pcm = true, | ||
1030 | .fifo_depth = 128, | ||
1031 | .reg_offset = 8, | ||
1032 | }; | ||
1033 | |||
1034 | static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = { | ||
1035 | .use_imx_pcm = true, | ||
1036 | .fifo_depth = 64, | ||
1037 | .reg_offset = 0, | ||
1038 | }; | ||
1039 | |||
916 | static const struct of_device_id fsl_sai_ids[] = { | 1040 | static const struct of_device_id fsl_sai_ids[] = { |
917 | { .compatible = "fsl,vf610-sai", }, | 1041 | { .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data }, |
918 | { .compatible = "fsl,imx6sx-sai", }, | 1042 | { .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data }, |
919 | { .compatible = "fsl,imx6ul-sai", }, | 1043 | { .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data }, |
1044 | { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data }, | ||
1045 | { .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data }, | ||
1046 | { .compatible = "fsl,imx8qm-sai", .data = &fsl_sai_imx8qm_data }, | ||
920 | { /* sentinel */ } | 1047 | { /* sentinel */ } |
921 | }; | 1048 | }; |
922 | MODULE_DEVICE_TABLE(of, fsl_sai_ids); | 1049 | MODULE_DEVICE_TABLE(of, fsl_sai_ids); |
@@ -943,6 +1070,7 @@ static int fsl_sai_runtime_suspend(struct device *dev) | |||
943 | static int fsl_sai_runtime_resume(struct device *dev) | 1070 | static int fsl_sai_runtime_resume(struct device *dev) |
944 | { | 1071 | { |
945 | struct fsl_sai *sai = dev_get_drvdata(dev); | 1072 | struct fsl_sai *sai = dev_get_drvdata(dev); |
1073 | unsigned int ofs = sai->soc_data->reg_offset; | ||
946 | int ret; | 1074 | int ret; |
947 | 1075 | ||
948 | ret = clk_prepare_enable(sai->bus_clk); | 1076 | ret = clk_prepare_enable(sai->bus_clk); |
@@ -964,11 +1092,11 @@ static int fsl_sai_runtime_resume(struct device *dev) | |||
964 | } | 1092 | } |
965 | 1093 | ||
966 | regcache_cache_only(sai->regmap, false); | 1094 | regcache_cache_only(sai->regmap, false); |
967 | regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); | 1095 | regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); |
968 | regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR); | 1096 | regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); |
969 | usleep_range(1000, 2000); | 1097 | usleep_range(1000, 2000); |
970 | regmap_write(sai->regmap, FSL_SAI_TCSR, 0); | 1098 | regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); |
971 | regmap_write(sai->regmap, FSL_SAI_RCSR, 0); | 1099 | regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); |
972 | 1100 | ||
973 | ret = regcache_sync(sai->regmap); | 1101 | ret = regcache_sync(sai->regmap); |
974 | if (ret) | 1102 | if (ret) |
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 24cb156bf995..b89b0ca26053 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h | |||
@@ -14,33 +14,61 @@ | |||
14 | SNDRV_PCM_FMTBIT_S32_LE) | 14 | SNDRV_PCM_FMTBIT_S32_LE) |
15 | 15 | ||
16 | /* SAI Register Map Register */ | 16 | /* SAI Register Map Register */ |
17 | #define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */ | 17 | #define FSL_SAI_TCSR(ofs) (0x00 + ofs) /* SAI Transmit Control */ |
18 | #define FSL_SAI_TCR1 0x04 /* SAI Transmit Configuration 1 */ | 18 | #define FSL_SAI_TCR1(ofs) (0x04 + ofs) /* SAI Transmit Configuration 1 */ |
19 | #define FSL_SAI_TCR2 0x08 /* SAI Transmit Configuration 2 */ | 19 | #define FSL_SAI_TCR2(ofs) (0x08 + ofs) /* SAI Transmit Configuration 2 */ |
20 | #define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */ | 20 | #define FSL_SAI_TCR3(ofs) (0x0c + ofs) /* SAI Transmit Configuration 3 */ |
21 | #define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */ | 21 | #define FSL_SAI_TCR4(ofs) (0x10 + ofs) /* SAI Transmit Configuration 4 */ |
22 | #define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */ | 22 | #define FSL_SAI_TCR5(ofs) (0x14 + ofs) /* SAI Transmit Configuration 5 */ |
23 | #define FSL_SAI_TDR 0x20 /* SAI Transmit Data */ | 23 | #define FSL_SAI_TDR0 0x20 /* SAI Transmit Data 0 */ |
24 | #define FSL_SAI_TFR 0x40 /* SAI Transmit FIFO */ | 24 | #define FSL_SAI_TDR1 0x24 /* SAI Transmit Data 1 */ |
25 | #define FSL_SAI_TDR2 0x28 /* SAI Transmit Data 2 */ | ||
26 | #define FSL_SAI_TDR3 0x2C /* SAI Transmit Data 3 */ | ||
27 | #define FSL_SAI_TDR4 0x30 /* SAI Transmit Data 4 */ | ||
28 | #define FSL_SAI_TDR5 0x34 /* SAI Transmit Data 5 */ | ||
29 | #define FSL_SAI_TDR6 0x38 /* SAI Transmit Data 6 */ | ||
30 | #define FSL_SAI_TDR7 0x3C /* SAI Transmit Data 7 */ | ||
31 | #define FSL_SAI_TFR0 0x40 /* SAI Transmit FIFO 0 */ | ||
32 | #define FSL_SAI_TFR1 0x44 /* SAI Transmit FIFO 1 */ | ||
33 | #define FSL_SAI_TFR2 0x48 /* SAI Transmit FIFO 2 */ | ||
34 | #define FSL_SAI_TFR3 0x4C /* SAI Transmit FIFO 3 */ | ||
35 | #define FSL_SAI_TFR4 0x50 /* SAI Transmit FIFO 4 */ | ||
36 | #define FSL_SAI_TFR5 0x54 /* SAI Transmit FIFO 5 */ | ||
37 | #define FSL_SAI_TFR6 0x58 /* SAI Transmit FIFO 6 */ | ||
38 | #define FSL_SAI_TFR7 0x5C /* SAI Transmit FIFO 7 */ | ||
25 | #define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */ | 39 | #define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */ |
26 | #define FSL_SAI_RCSR 0x80 /* SAI Receive Control */ | 40 | #define FSL_SAI_RCSR(ofs) (0x80 + ofs) /* SAI Receive Control */ |
27 | #define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */ | 41 | #define FSL_SAI_RCR1(ofs) (0x84 + ofs)/* SAI Receive Configuration 1 */ |
28 | #define FSL_SAI_RCR2 0x88 /* SAI Receive Configuration 2 */ | 42 | #define FSL_SAI_RCR2(ofs) (0x88 + ofs) /* SAI Receive Configuration 2 */ |
29 | #define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */ | 43 | #define FSL_SAI_RCR3(ofs) (0x8c + ofs) /* SAI Receive Configuration 3 */ |
30 | #define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */ | 44 | #define FSL_SAI_RCR4(ofs) (0x90 + ofs) /* SAI Receive Configuration 4 */ |
31 | #define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */ | 45 | #define FSL_SAI_RCR5(ofs) (0x94 + ofs) /* SAI Receive Configuration 5 */ |
32 | #define FSL_SAI_RDR 0xa0 /* SAI Receive Data */ | 46 | #define FSL_SAI_RDR0 0xa0 /* SAI Receive Data 0 */ |
33 | #define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */ | 47 | #define FSL_SAI_RDR1 0xa4 /* SAI Receive Data 1 */ |
48 | #define FSL_SAI_RDR2 0xa8 /* SAI Receive Data 2 */ | ||
49 | #define FSL_SAI_RDR3 0xac /* SAI Receive Data 3 */ | ||
50 | #define FSL_SAI_RDR4 0xb0 /* SAI Receive Data 4 */ | ||
51 | #define FSL_SAI_RDR5 0xb4 /* SAI Receive Data 5 */ | ||
52 | #define FSL_SAI_RDR6 0xb8 /* SAI Receive Data 6 */ | ||
53 | #define FSL_SAI_RDR7 0xbc /* SAI Receive Data 7 */ | ||
54 | #define FSL_SAI_RFR0 0xc0 /* SAI Receive FIFO 0 */ | ||
55 | #define FSL_SAI_RFR1 0xc4 /* SAI Receive FIFO 1 */ | ||
56 | #define FSL_SAI_RFR2 0xc8 /* SAI Receive FIFO 2 */ | ||
57 | #define FSL_SAI_RFR3 0xcc /* SAI Receive FIFO 3 */ | ||
58 | #define FSL_SAI_RFR4 0xd0 /* SAI Receive FIFO 4 */ | ||
59 | #define FSL_SAI_RFR5 0xd4 /* SAI Receive FIFO 5 */ | ||
60 | #define FSL_SAI_RFR6 0xd8 /* SAI Receive FIFO 6 */ | ||
61 | #define FSL_SAI_RFR7 0xdc /* SAI Receive FIFO 7 */ | ||
34 | #define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ | 62 | #define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ |
35 | 63 | ||
36 | #define FSL_SAI_xCSR(tx) (tx ? FSL_SAI_TCSR : FSL_SAI_RCSR) | 64 | #define FSL_SAI_xCSR(tx, ofs) (tx ? FSL_SAI_TCSR(ofs) : FSL_SAI_RCSR(ofs)) |
37 | #define FSL_SAI_xCR1(tx) (tx ? FSL_SAI_TCR1 : FSL_SAI_RCR1) | 65 | #define FSL_SAI_xCR1(tx, ofs) (tx ? FSL_SAI_TCR1(ofs) : FSL_SAI_RCR1(ofs)) |
38 | #define FSL_SAI_xCR2(tx) (tx ? FSL_SAI_TCR2 : FSL_SAI_RCR2) | 66 | #define FSL_SAI_xCR2(tx, ofs) (tx ? FSL_SAI_TCR2(ofs) : FSL_SAI_RCR2(ofs)) |
39 | #define FSL_SAI_xCR3(tx) (tx ? FSL_SAI_TCR3 : FSL_SAI_RCR3) | 67 | #define FSL_SAI_xCR3(tx, ofs) (tx ? FSL_SAI_TCR3(ofs) : FSL_SAI_RCR3(ofs)) |
40 | #define FSL_SAI_xCR4(tx) (tx ? FSL_SAI_TCR4 : FSL_SAI_RCR4) | 68 | #define FSL_SAI_xCR4(tx, ofs) (tx ? FSL_SAI_TCR4(ofs) : FSL_SAI_RCR4(ofs)) |
41 | #define FSL_SAI_xCR5(tx) (tx ? FSL_SAI_TCR5 : FSL_SAI_RCR5) | 69 | #define FSL_SAI_xCR5(tx, ofs) (tx ? FSL_SAI_TCR5(ofs) : FSL_SAI_RCR5(ofs)) |
42 | #define FSL_SAI_xDR(tx) (tx ? FSL_SAI_TDR : FSL_SAI_RDR) | 70 | #define FSL_SAI_xDR(tx, ofs) (tx ? FSL_SAI_TDR(ofs) : FSL_SAI_RDR(ofs)) |
43 | #define FSL_SAI_xFR(tx) (tx ? FSL_SAI_TFR : FSL_SAI_RFR) | 71 | #define FSL_SAI_xFR(tx, ofs) (tx ? FSL_SAI_TFR(ofs) : FSL_SAI_RFR(ofs)) |
44 | #define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR) | 72 | #define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR) |
45 | 73 | ||
46 | /* SAI Transmit/Receive Control Register */ | 74 | /* SAI Transmit/Receive Control Register */ |
@@ -82,6 +110,7 @@ | |||
82 | 110 | ||
83 | /* SAI Transmit and Receive Configuration 3 Register */ | 111 | /* SAI Transmit and Receive Configuration 3 Register */ |
84 | #define FSL_SAI_CR3_TRCE BIT(16) | 112 | #define FSL_SAI_CR3_TRCE BIT(16) |
113 | #define FSL_SAI_CR3_TRCE_MASK GENMASK(23, 16) | ||
85 | #define FSL_SAI_CR3_WDFL(x) (x) | 114 | #define FSL_SAI_CR3_WDFL(x) (x) |
86 | #define FSL_SAI_CR3_WDFL_MASK 0x1f | 115 | #define FSL_SAI_CR3_WDFL_MASK 0x1f |
87 | 116 | ||
@@ -126,6 +155,12 @@ | |||
126 | #define FSL_SAI_MAXBURST_TX 6 | 155 | #define FSL_SAI_MAXBURST_TX 6 |
127 | #define FSL_SAI_MAXBURST_RX 6 | 156 | #define FSL_SAI_MAXBURST_RX 6 |
128 | 157 | ||
158 | struct fsl_sai_soc_data { | ||
159 | bool use_imx_pcm; | ||
160 | unsigned int fifo_depth; | ||
161 | unsigned int reg_offset; | ||
162 | }; | ||
163 | |||
129 | struct fsl_sai { | 164 | struct fsl_sai { |
130 | struct platform_device *pdev; | 165 | struct platform_device *pdev; |
131 | struct regmap *regmap; | 166 | struct regmap *regmap; |
@@ -135,7 +170,6 @@ struct fsl_sai { | |||
135 | bool is_slave_mode; | 170 | bool is_slave_mode; |
136 | bool is_lsb_first; | 171 | bool is_lsb_first; |
137 | bool is_dsp_mode; | 172 | bool is_dsp_mode; |
138 | bool sai_on_imx; | ||
139 | bool synchronous[2]; | 173 | bool synchronous[2]; |
140 | 174 | ||
141 | unsigned int mclk_id[2]; | 175 | unsigned int mclk_id[2]; |
@@ -143,6 +177,7 @@ struct fsl_sai { | |||
143 | unsigned int slots; | 177 | unsigned int slots; |
144 | unsigned int slot_width; | 178 | unsigned int slot_width; |
145 | 179 | ||
180 | const struct fsl_sai_soc_data *soc_data; | ||
146 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 181 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
147 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 182 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
148 | }; | 183 | }; |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 4842e6df9a2d..7858a5499ac5 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -1248,10 +1248,8 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1248 | } | 1248 | } |
1249 | 1249 | ||
1250 | irq = platform_get_irq(pdev, 0); | 1250 | irq = platform_get_irq(pdev, 0); |
1251 | if (irq < 0) { | 1251 | if (irq < 0) |
1252 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); | ||
1253 | return irq; | 1252 | return irq; |
1254 | } | ||
1255 | 1253 | ||
1256 | ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, | 1254 | ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, |
1257 | dev_name(&pdev->dev), spdif_priv); | 1255 | dev_name(&pdev->dev), spdif_priv); |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 085855f9b08d..537dc69256f0 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -1510,10 +1510,8 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1510 | } | 1510 | } |
1511 | 1511 | ||
1512 | ssi->irq = platform_get_irq(pdev, 0); | 1512 | ssi->irq = platform_get_irq(pdev, 0); |
1513 | if (ssi->irq < 0) { | 1513 | if (ssi->irq < 0) |
1514 | dev_err(dev, "no irq for node %s\n", pdev->name); | ||
1515 | return ssi->irq; | 1514 | return ssi->irq; |
1516 | } | ||
1517 | 1515 | ||
1518 | /* Set software limitations for synchronous mode except AC97 */ | 1516 | /* Set software limitations for synchronous mode except AC97 */ |
1519 | if (ssi->synchronous && !fsl_ssi_is_ac97(ssi)) { | 1517 | if (ssi->synchronous && !fsl_ssi_is_ac97(ssi)) { |
diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 9e1cb18859ce..71590ca6394b 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c | |||
@@ -325,14 +325,14 @@ static int imx_audmix_probe(struct platform_device *pdev) | |||
325 | priv->card.num_configs = priv->num_dai_conf; | 325 | priv->card.num_configs = priv->num_dai_conf; |
326 | priv->card.dapm_routes = priv->dapm_routes; | 326 | priv->card.dapm_routes = priv->dapm_routes; |
327 | priv->card.num_dapm_routes = priv->num_dapm_routes; | 327 | priv->card.num_dapm_routes = priv->num_dapm_routes; |
328 | priv->card.dev = pdev->dev.parent; | 328 | priv->card.dev = &pdev->dev; |
329 | priv->card.owner = THIS_MODULE; | 329 | priv->card.owner = THIS_MODULE; |
330 | priv->card.name = "imx-audmix"; | 330 | priv->card.name = "imx-audmix"; |
331 | 331 | ||
332 | platform_set_drvdata(pdev, &priv->card); | 332 | platform_set_drvdata(pdev, &priv->card); |
333 | snd_soc_card_set_drvdata(&priv->card, priv); | 333 | snd_soc_card_set_drvdata(&priv->card, priv); |
334 | 334 | ||
335 | ret = devm_snd_soc_register_card(pdev->dev.parent, &priv->card); | 335 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); |
336 | if (ret) { | 336 | if (ret) { |
337 | dev_err(&pdev->dev, "snd_soc_register_card failed\n"); | 337 | dev_err(&pdev->dev, "snd_soc_register_card failed\n"); |
338 | return ret; | 338 | return ret; |
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 16ede3b5cb32..3ce85a43e08f 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
@@ -300,12 +300,10 @@ static int imx_audmux_parse_dt_defaults(struct platform_device *pdev, | |||
300 | 300 | ||
301 | static int imx_audmux_probe(struct platform_device *pdev) | 301 | static int imx_audmux_probe(struct platform_device *pdev) |
302 | { | 302 | { |
303 | struct resource *res; | ||
304 | const struct of_device_id *of_id = | 303 | const struct of_device_id *of_id = |
305 | of_match_device(imx_audmux_dt_ids, &pdev->dev); | 304 | of_match_device(imx_audmux_dt_ids, &pdev->dev); |
306 | 305 | ||
307 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 306 | audmux_base = devm_platform_ioremap_resource(pdev, 0); |
308 | audmux_base = devm_ioremap_resource(&pdev->dev, res); | ||
309 | if (IS_ERR(audmux_base)) | 307 | if (IS_ERR(audmux_base)) |
310 | return PTR_ERR(audmux_base); | 308 | return PTR_ERR(audmux_base); |
311 | 309 | ||
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 9038b61317be..42031ba7da31 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -520,10 +520,8 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
520 | } | 520 | } |
521 | 521 | ||
522 | ssi->irq = platform_get_irq(pdev, 0); | 522 | ssi->irq = platform_get_irq(pdev, 0); |
523 | if (ssi->irq < 0) { | 523 | if (ssi->irq < 0) |
524 | dev_err(&pdev->dev, "Failed to get IRQ: %d\n", ssi->irq); | ||
525 | return ssi->irq; | 524 | return ssi->irq; |
526 | } | ||
527 | 525 | ||
528 | ssi->clk = devm_clk_get(&pdev->dev, NULL); | 526 | ssi->clk = devm_clk_get(&pdev->dev, NULL); |
529 | if (IS_ERR(ssi->clk)) { | 527 | if (IS_ERR(ssi->clk)) { |
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 288df245b2f0..6007e6305735 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c | |||
@@ -129,6 +129,25 @@ static int asoc_simple_parse_dai(struct device_node *ep, | |||
129 | args.args[0] = graph_get_dai_id(ep); | 129 | args.args[0] = graph_get_dai_id(ep); |
130 | args.args_count = (of_graph_get_endpoint_count(node) > 1); | 130 | args.args_count = (of_graph_get_endpoint_count(node) > 1); |
131 | 131 | ||
132 | /* | ||
133 | * FIXME | ||
134 | * | ||
135 | * Here, dlc->dai_name is pointer to CPU/Codec DAI name. | ||
136 | * If user unbinded CPU or Codec driver, but not for Sound Card, | ||
137 | * dlc->dai_name is keeping unbinded CPU or Codec | ||
138 | * driver's pointer. | ||
139 | * | ||
140 | * If user re-bind CPU or Codec driver again, ALSA SoC will try | ||
141 | * to rebind Card via snd_soc_try_rebind_card(), but because of | ||
142 | * above reason, it might can't bind Sound Card. | ||
143 | * Because Sound Card is pointing to released dai_name pointer. | ||
144 | * | ||
145 | * To avoid this rebind Card issue, | ||
146 | * 1) It needs to alloc memory to keep dai_name eventhough | ||
147 | * CPU or Codec driver was unbinded, or | ||
148 | * 2) user need to rebind Sound Card everytime | ||
149 | * if he unbinded CPU or Codec. | ||
150 | */ | ||
132 | ret = snd_soc_get_dai_name(&args, &dlc->dai_name); | 151 | ret = snd_soc_get_dai_name(&args, &dlc->dai_name); |
133 | if (ret < 0) | 152 | if (ret < 0) |
134 | return ret; | 153 | return ret; |
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 556b1a789629..9b794775df53 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c | |||
@@ -213,10 +213,17 @@ EXPORT_SYMBOL_GPL(asoc_simple_startup); | |||
213 | void asoc_simple_shutdown(struct snd_pcm_substream *substream) | 213 | void asoc_simple_shutdown(struct snd_pcm_substream *substream) |
214 | { | 214 | { |
215 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 215 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
216 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
217 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
216 | struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); | 218 | struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); |
217 | struct simple_dai_props *dai_props = | 219 | struct simple_dai_props *dai_props = |
218 | simple_priv_to_props(priv, rtd->num); | 220 | simple_priv_to_props(priv, rtd->num); |
219 | 221 | ||
222 | if (dai_props->mclk_fs) { | ||
223 | snd_soc_dai_set_sysclk(codec_dai, 0, 0, SND_SOC_CLOCK_IN); | ||
224 | snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT); | ||
225 | } | ||
226 | |||
220 | asoc_simple_clk_disable(dai_props->cpu_dai); | 227 | asoc_simple_clk_disable(dai_props->cpu_dai); |
221 | 228 | ||
222 | asoc_simple_clk_disable(dai_props->codec_dai); | 229 | asoc_simple_clk_disable(dai_props->codec_dai); |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index ef849151ba56..fc9c753db8dd 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -46,7 +46,25 @@ static int asoc_simple_parse_dai(struct device_node *node, | |||
46 | if (ret) | 46 | if (ret) |
47 | return ret; | 47 | return ret; |
48 | 48 | ||
49 | /* Get dai->name */ | 49 | /* |
50 | * FIXME | ||
51 | * | ||
52 | * Here, dlc->dai_name is pointer to CPU/Codec DAI name. | ||
53 | * If user unbinded CPU or Codec driver, but not for Sound Card, | ||
54 | * dlc->dai_name is keeping unbinded CPU or Codec | ||
55 | * driver's pointer. | ||
56 | * | ||
57 | * If user re-bind CPU or Codec driver again, ALSA SoC will try | ||
58 | * to rebind Card via snd_soc_try_rebind_card(), but because of | ||
59 | * above reason, it might can't bind Sound Card. | ||
60 | * Because Sound Card is pointing to released dai_name pointer. | ||
61 | * | ||
62 | * To avoid this rebind Card issue, | ||
63 | * 1) It needs to alloc memory to keep dai_name eventhough | ||
64 | * CPU or Codec driver was unbinded, or | ||
65 | * 2) user need to rebind Sound Card everytime | ||
66 | * if he unbinded CPU or Codec. | ||
67 | */ | ||
50 | ret = snd_soc_of_get_dai_name(node, &dlc->dai_name); | 68 | ret = snd_soc_of_get_dai_name(node, &dlc->dai_name); |
51 | if (ret < 0) | 69 | if (ret < 0) |
52 | return ret; | 70 | return ret; |
@@ -424,7 +442,7 @@ static int simple_parse_aux_devs(struct device_node *node, | |||
424 | aux_node = of_parse_phandle(node, PREFIX "aux-devs", i); | 442 | aux_node = of_parse_phandle(node, PREFIX "aux-devs", i); |
425 | if (!aux_node) | 443 | if (!aux_node) |
426 | return -EINVAL; | 444 | return -EINVAL; |
427 | card->aux_dev[i].codec_of_node = aux_node; | 445 | card->aux_dev[i].dlc.of_node = aux_node; |
428 | } | 446 | } |
429 | 447 | ||
430 | card->num_aux_devs = n; | 448 | card->num_aux_devs = n; |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 96a00a9d4cf8..01c99750212a 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -215,6 +215,7 @@ config SND_SOC_INTEL_SKYLAKE_COMMON | |||
215 | select SND_SOC_INTEL_SST | 215 | select SND_SOC_INTEL_SST |
216 | select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC | 216 | select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC |
217 | select SND_SOC_ACPI_INTEL_MATCH | 217 | select SND_SOC_ACPI_INTEL_MATCH |
218 | select SND_INTEL_NHLT if ACPI | ||
218 | help | 219 | help |
219 | If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/ | 220 | If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/ |
220 | GeminiLake or CannonLake platform with the DSP enabled in the BIOS | 221 | GeminiLake or CannonLake platform with the DSP enabled in the BIOS |
diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index 8bd1eddcc091..74274bd38f7a 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c | |||
@@ -211,7 +211,7 @@ static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt, | |||
211 | static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) | 211 | static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) |
212 | { | 212 | { |
213 | struct sst_byt_stream *stream; | 213 | struct sst_byt_stream *stream; |
214 | u64 header = msg->header; | 214 | u64 header = msg->tx.header; |
215 | u8 stream_id = sst_byt_header_str_id(header); | 215 | u8 stream_id = sst_byt_header_str_id(header); |
216 | u8 stream_msg = sst_byt_header_msg_id(header); | 216 | u8 stream_msg = sst_byt_header_msg_id(header); |
217 | 217 | ||
@@ -240,9 +240,10 @@ static int sst_byt_process_reply(struct sst_byt *byt, u64 header) | |||
240 | if (msg == NULL) | 240 | if (msg == NULL) |
241 | return 1; | 241 | return 1; |
242 | 242 | ||
243 | msg->rx.header = header; | ||
243 | if (header & IPC_HEADER_LARGE(true)) { | 244 | if (header & IPC_HEADER_LARGE(true)) { |
244 | msg->rx_size = sst_byt_header_data(header); | 245 | msg->rx.size = sst_byt_header_data(header); |
245 | sst_dsp_inbox_read(byt->dsp, msg->rx_data, msg->rx_size); | 246 | sst_dsp_inbox_read(byt->dsp, msg->rx.data, msg->rx.size); |
246 | } | 247 | } |
247 | 248 | ||
248 | /* update any stream states */ | 249 | /* update any stream states */ |
@@ -407,17 +408,18 @@ int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream, | |||
407 | 408 | ||
408 | int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) | 409 | int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) |
409 | { | 410 | { |
410 | struct sst_byt_alloc_params *str_req = &stream->request; | 411 | struct sst_ipc_message request, reply = {0}; |
411 | struct sst_byt_alloc_response *reply = &stream->reply; | ||
412 | u64 header; | ||
413 | int ret; | 412 | int ret; |
414 | 413 | ||
415 | header = sst_byt_header(IPC_IA_ALLOC_STREAM, | 414 | request.header = sst_byt_header(IPC_IA_ALLOC_STREAM, |
416 | sizeof(*str_req) + sizeof(u32), | 415 | sizeof(stream->request) + sizeof(u32), |
417 | true, stream->str_id); | 416 | true, stream->str_id); |
418 | ret = sst_ipc_tx_message_wait(&byt->ipc, header, str_req, | 417 | request.data = &stream->request; |
419 | sizeof(*str_req), | 418 | request.size = sizeof(stream->request); |
420 | reply, sizeof(*reply)); | 419 | reply.data = &stream->reply; |
420 | reply.size = sizeof(stream->reply); | ||
421 | |||
422 | ret = sst_ipc_tx_message_wait(&byt->ipc, request, &reply); | ||
421 | if (ret < 0) { | 423 | if (ret < 0) { |
422 | dev_err(byt->dev, "ipc: error stream commit failed\n"); | 424 | dev_err(byt->dev, "ipc: error stream commit failed\n"); |
423 | return ret; | 425 | return ret; |
@@ -430,7 +432,7 @@ int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) | |||
430 | 432 | ||
431 | int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) | 433 | int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) |
432 | { | 434 | { |
433 | u64 header; | 435 | struct sst_ipc_message request = {0}; |
434 | int ret = 0; | 436 | int ret = 0; |
435 | struct sst_dsp *sst = byt->dsp; | 437 | struct sst_dsp *sst = byt->dsp; |
436 | unsigned long flags; | 438 | unsigned long flags; |
@@ -438,8 +440,9 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) | |||
438 | if (!stream->commited) | 440 | if (!stream->commited) |
439 | goto out; | 441 | goto out; |
440 | 442 | ||
441 | header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id); | 443 | request.header = sst_byt_header(IPC_IA_FREE_STREAM, |
442 | ret = sst_ipc_tx_message_wait(&byt->ipc, header, NULL, 0, NULL, 0); | 444 | 0, false, stream->str_id); |
445 | ret = sst_ipc_tx_message_wait(&byt->ipc, request, NULL); | ||
443 | if (ret < 0) { | 446 | if (ret < 0) { |
444 | dev_err(byt->dev, "ipc: free stream %d failed\n", | 447 | dev_err(byt->dev, "ipc: free stream %d failed\n", |
445 | stream->str_id); | 448 | stream->str_id); |
@@ -459,15 +462,13 @@ out: | |||
459 | static int sst_byt_stream_operations(struct sst_byt *byt, int type, | 462 | static int sst_byt_stream_operations(struct sst_byt *byt, int type, |
460 | int stream_id, int wait) | 463 | int stream_id, int wait) |
461 | { | 464 | { |
462 | u64 header; | 465 | struct sst_ipc_message request = {0}; |
463 | 466 | ||
464 | header = sst_byt_header(type, 0, false, stream_id); | 467 | request.header = sst_byt_header(type, 0, false, stream_id); |
465 | if (wait) | 468 | if (wait) |
466 | return sst_ipc_tx_message_wait(&byt->ipc, header, NULL, | 469 | return sst_ipc_tx_message_wait(&byt->ipc, request, NULL); |
467 | 0, NULL, 0); | ||
468 | else | 470 | else |
469 | return sst_ipc_tx_message_nowait(&byt->ipc, header, | 471 | return sst_ipc_tx_message_nowait(&byt->ipc, request); |
470 | NULL, 0); | ||
471 | } | 472 | } |
472 | 473 | ||
473 | /* stream ALSA trigger operations */ | 474 | /* stream ALSA trigger operations */ |
@@ -475,19 +476,17 @@ int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream, | |||
475 | u32 start_offset) | 476 | u32 start_offset) |
476 | { | 477 | { |
477 | struct sst_byt_start_stream_params start_stream; | 478 | struct sst_byt_start_stream_params start_stream; |
478 | void *tx_msg; | 479 | struct sst_ipc_message request; |
479 | size_t size; | ||
480 | u64 header; | ||
481 | int ret; | 480 | int ret; |
482 | 481 | ||
483 | start_stream.byte_offset = start_offset; | 482 | start_stream.byte_offset = start_offset; |
484 | header = sst_byt_header(IPC_IA_START_STREAM, | 483 | request.header = sst_byt_header(IPC_IA_START_STREAM, |
485 | sizeof(start_stream) + sizeof(u32), | 484 | sizeof(start_stream) + sizeof(u32), |
486 | true, stream->str_id); | 485 | true, stream->str_id); |
487 | tx_msg = &start_stream; | 486 | request.data = &start_stream; |
488 | size = sizeof(start_stream); | 487 | request.size = sizeof(start_stream); |
489 | 488 | ||
490 | ret = sst_ipc_tx_message_nowait(&byt->ipc, header, tx_msg, size); | 489 | ret = sst_ipc_tx_message_nowait(&byt->ipc, request); |
491 | if (ret < 0) | 490 | if (ret < 0) |
492 | dev_err(byt->dev, "ipc: error failed to start stream %d\n", | 491 | dev_err(byt->dev, "ipc: error failed to start stream %d\n", |
493 | stream->str_id); | 492 | stream->str_id); |
@@ -623,10 +622,10 @@ EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready); | |||
623 | 622 | ||
624 | static void byt_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) | 623 | static void byt_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) |
625 | { | 624 | { |
626 | if (msg->header & IPC_HEADER_LARGE(true)) | 625 | if (msg->tx.header & IPC_HEADER_LARGE(true)) |
627 | sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); | 626 | sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); |
628 | 627 | ||
629 | sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->header); | 628 | sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->tx.header); |
630 | } | 629 | } |
631 | 630 | ||
632 | static void byt_shim_dbg(struct sst_generic_ipc *ipc, const char *text) | 631 | static void byt_shim_dbg(struct sst_generic_ipc *ipc, const char *text) |
@@ -648,9 +647,9 @@ static void byt_tx_data_copy(struct ipc_message *msg, char *tx_data, | |||
648 | size_t tx_size) | 647 | size_t tx_size) |
649 | { | 648 | { |
650 | /* msg content = lower 32-bit of the header + data */ | 649 | /* msg content = lower 32-bit of the header + data */ |
651 | *(u32 *)msg->tx_data = (u32)(msg->header & (u32)-1); | 650 | *(u32 *)msg->tx.data = (u32)(msg->tx.header & (u32)-1); |
652 | memcpy(msg->tx_data + sizeof(u32), tx_data, tx_size); | 651 | memcpy(msg->tx.data + sizeof(u32), tx_data, tx_size); |
653 | msg->tx_size += sizeof(u32); | 652 | msg->tx.size += sizeof(u32); |
654 | } | 653 | } |
655 | 654 | ||
656 | static u64 byt_reply_msg_match(u64 header, u64 *mask) | 655 | static u64 byt_reply_msg_match(u64 header, u64 *mask) |
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 50bf149818b5..5c27f7ab4a5f 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig | |||
@@ -256,16 +256,20 @@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH | |||
256 | 256 | ||
257 | endif ## SND_SOC_INTEL_SKL | 257 | endif ## SND_SOC_INTEL_SKL |
258 | 258 | ||
259 | config SND_SOC_INTEL_DA7219_MAX98357A_GENERIC | ||
260 | tristate | ||
261 | select SND_SOC_DA7219 | ||
262 | select SND_SOC_MAX98357A | ||
263 | select SND_SOC_DMIC | ||
264 | select SND_SOC_HDAC_HDMI | ||
265 | |||
259 | if SND_SOC_INTEL_APL | 266 | if SND_SOC_INTEL_APL |
260 | 267 | ||
261 | config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH | 268 | config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH |
262 | tristate "Broxton with DA7219 and MAX98357A in I2S Mode" | 269 | tristate "Broxton with DA7219 and MAX98357A in I2S Mode" |
263 | depends on I2C && ACPI | 270 | depends on I2C && ACPI |
264 | depends on MFD_INTEL_LPSS || COMPILE_TEST | 271 | depends on MFD_INTEL_LPSS || COMPILE_TEST |
265 | select SND_SOC_DA7219 | 272 | select SND_SOC_INTEL_DA7219_MAX98357A_GENERIC |
266 | select SND_SOC_MAX98357A | ||
267 | select SND_SOC_DMIC | ||
268 | select SND_SOC_HDAC_HDMI | ||
269 | select SND_HDA_DSP_LOADER | 273 | select SND_HDA_DSP_LOADER |
270 | help | 274 | help |
271 | This adds support for ASoC machine driver for Broxton-P platforms | 275 | This adds support for ASoC machine driver for Broxton-P platforms |
@@ -326,10 +330,7 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH | |||
326 | tristate "KBL with DA7219 and MAX98357A in I2S Mode" | 330 | tristate "KBL with DA7219 and MAX98357A in I2S Mode" |
327 | depends on I2C && ACPI | 331 | depends on I2C && ACPI |
328 | depends on MFD_INTEL_LPSS || COMPILE_TEST | 332 | depends on MFD_INTEL_LPSS || COMPILE_TEST |
329 | select SND_SOC_DA7219 | 333 | select SND_SOC_INTEL_DA7219_MAX98357A_GENERIC |
330 | select SND_SOC_MAX98357A | ||
331 | select SND_SOC_DMIC | ||
332 | select SND_SOC_HDAC_HDMI | ||
333 | help | 334 | help |
334 | This adds support for ASoC Onboard Codec I2S machine driver. This will | 335 | This adds support for ASoC Onboard Codec I2S machine driver. This will |
335 | create an alsa sound card for DA7219 + MAX98357A I2S audio codec. | 336 | create an alsa sound card for DA7219 + MAX98357A I2S audio codec. |
@@ -387,6 +388,7 @@ if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC | |||
387 | config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH | 388 | config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH |
388 | tristate "SKL/KBL/BXT/APL with HDA Codecs" | 389 | tristate "SKL/KBL/BXT/APL with HDA Codecs" |
389 | select SND_SOC_HDAC_HDMI | 390 | select SND_SOC_HDAC_HDMI |
391 | select SND_SOC_DMIC | ||
390 | # SND_SOC_HDAC_HDA is already selected | 392 | # SND_SOC_HDAC_HDA is already selected |
391 | help | 393 | help |
392 | This adds support for ASoC machine driver for Intel platforms | 394 | This adds support for ASoC machine driver for Intel platforms |
@@ -412,4 +414,14 @@ config SND_SOC_INTEL_SOF_RT5682_MACH | |||
412 | If unsure select "N". | 414 | If unsure select "N". |
413 | endif ## SND_SOC_SOF_HDA_COMMON || SND_SOC_SOF_BAYTRAIL | 415 | endif ## SND_SOC_SOF_HDA_COMMON || SND_SOC_SOF_BAYTRAIL |
414 | 416 | ||
417 | if (SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK) | ||
418 | |||
419 | config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH | ||
420 | tristate "CML_LP with DA7219 and MAX98357A in I2S Mode" | ||
421 | depends on I2C && ACPI | ||
422 | depends on MFD_INTEL_LPSS || COMPILE_TEST | ||
423 | select SND_SOC_INTEL_DA7219_MAX98357A_GENERIC | ||
424 | |||
425 | endif ## SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK | ||
426 | |||
415 | endif ## SND_SOC_INTEL_MACH | 427 | endif ## SND_SOC_INTEL_MACH |
diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index e8e9c3dc82a5..4a4d3353e26d 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c | |||
@@ -340,7 +340,6 @@ static int bdw_rt5677_probe(struct platform_device *pdev) | |||
340 | { | 340 | { |
341 | struct bdw_rt5677_priv *bdw_rt5677; | 341 | struct bdw_rt5677_priv *bdw_rt5677; |
342 | struct snd_soc_acpi_mach *mach; | 342 | struct snd_soc_acpi_mach *mach; |
343 | const char *platform_name = NULL; | ||
344 | int ret; | 343 | int ret; |
345 | 344 | ||
346 | bdw_rt5677_card.dev = &pdev->dev; | 345 | bdw_rt5677_card.dev = &pdev->dev; |
@@ -355,11 +354,8 @@ static int bdw_rt5677_probe(struct platform_device *pdev) | |||
355 | 354 | ||
356 | /* override plaform name, if required */ | 355 | /* override plaform name, if required */ |
357 | mach = (&pdev->dev)->platform_data; | 356 | mach = (&pdev->dev)->platform_data; |
358 | if (mach) /* extra check since legacy does not pass parameters */ | ||
359 | platform_name = mach->mach_params.platform; | ||
360 | |||
361 | ret = snd_soc_fixup_dai_links_platform_name(&bdw_rt5677_card, | 357 | ret = snd_soc_fixup_dai_links_platform_name(&bdw_rt5677_card, |
362 | platform_name); | 358 | mach->mach_params.platform); |
363 | if (ret) | 359 | if (ret) |
364 | return ret; | 360 | return ret; |
365 | 361 | ||
diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index ab38ef30dfff..db7e1e87156d 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c | |||
@@ -270,18 +270,14 @@ static struct snd_soc_card broadwell_rt286 = { | |||
270 | static int broadwell_audio_probe(struct platform_device *pdev) | 270 | static int broadwell_audio_probe(struct platform_device *pdev) |
271 | { | 271 | { |
272 | struct snd_soc_acpi_mach *mach; | 272 | struct snd_soc_acpi_mach *mach; |
273 | const char *platform_name = NULL; | ||
274 | int ret; | 273 | int ret; |
275 | 274 | ||
276 | broadwell_rt286.dev = &pdev->dev; | 275 | broadwell_rt286.dev = &pdev->dev; |
277 | 276 | ||
278 | /* override plaform name, if required */ | 277 | /* override plaform name, if required */ |
279 | mach = (&pdev->dev)->platform_data; | 278 | mach = (&pdev->dev)->platform_data; |
280 | if (mach) /* extra check since legacy does not pass parameters */ | ||
281 | platform_name = mach->mach_params.platform; | ||
282 | |||
283 | ret = snd_soc_fixup_dai_links_platform_name(&broadwell_rt286, | 279 | ret = snd_soc_fixup_dai_links_platform_name(&broadwell_rt286, |
284 | platform_name); | 280 | mach->mach_params.platform); |
285 | if (ret) | 281 | if (ret) |
286 | return ret; | 282 | return ret; |
287 | 283 | ||
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index c0d865a940dc..ac1dea5f9d11 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c | |||
@@ -179,10 +179,17 @@ static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) | |||
179 | int ret; | 179 | int ret; |
180 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 180 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
181 | struct snd_soc_component *component = rtd->codec_dai->component; | 181 | struct snd_soc_component *component = rtd->codec_dai->component; |
182 | int clk_freq; | ||
182 | 183 | ||
183 | /* Configure sysclk for codec */ | 184 | /* Configure sysclk for codec */ |
184 | ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 19200000, | 185 | if (soc_intel_is_cml()) |
186 | clk_freq = 24000000; | ||
187 | else | ||
188 | clk_freq = 19200000; | ||
189 | |||
190 | ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, clk_freq, | ||
185 | SND_SOC_CLOCK_IN); | 191 | SND_SOC_CLOCK_IN); |
192 | |||
186 | if (ret) { | 193 | if (ret) { |
187 | dev_err(rtd->dev, "can't set codec sysclk configuration\n"); | 194 | dev_err(rtd->dev, "can't set codec sysclk configuration\n"); |
188 | return ret; | 195 | return ret; |
@@ -683,6 +690,25 @@ static int broxton_audio_probe(struct platform_device *pdev) | |||
683 | broxton_dais[i].cpus->dai_name = "SSP2 Pin"; | 690 | broxton_dais[i].cpus->dai_name = "SSP2 Pin"; |
684 | } | 691 | } |
685 | } | 692 | } |
693 | } else if (soc_intel_is_cml()) { | ||
694 | unsigned int i; | ||
695 | |||
696 | broxton_audio_card.name = "cmlda7219max"; | ||
697 | |||
698 | for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { | ||
699 | /* MAXIM_CODEC is connected to SSP1. */ | ||
700 | if (!strcmp(broxton_dais[i].codecs->dai_name, | ||
701 | BXT_MAXIM_CODEC_DAI)) { | ||
702 | broxton_dais[i].name = "SSP1-Codec"; | ||
703 | broxton_dais[i].cpus->dai_name = "SSP1 Pin"; | ||
704 | } | ||
705 | /* DIALOG_CODEC is connected to SSP0 */ | ||
706 | else if (!strcmp(broxton_dais[i].codecs->dai_name, | ||
707 | BXT_DIALOG_CODEC_DAI)) { | ||
708 | broxton_dais[i].name = "SSP0-Codec"; | ||
709 | broxton_dais[i].cpus->dai_name = "SSP0 Pin"; | ||
710 | } | ||
711 | } | ||
686 | } | 712 | } |
687 | 713 | ||
688 | /* override plaform name, if required */ | 714 | /* override plaform name, if required */ |
@@ -700,6 +726,7 @@ static int broxton_audio_probe(struct platform_device *pdev) | |||
700 | static const struct platform_device_id bxt_board_ids[] = { | 726 | static const struct platform_device_id bxt_board_ids[] = { |
701 | { .name = "bxt_da7219_max98357a" }, | 727 | { .name = "bxt_da7219_max98357a" }, |
702 | { .name = "glk_da7219_max98357a" }, | 728 | { .name = "glk_da7219_max98357a" }, |
729 | { .name = "cml_da7219_max98357a" }, | ||
703 | { } | 730 | { } |
704 | }; | 731 | }; |
705 | 732 | ||
@@ -720,6 +747,8 @@ MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com>"); | |||
720 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); | 747 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); |
721 | MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>"); | 748 | MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>"); |
722 | MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>"); | 749 | MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>"); |
750 | MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>"); | ||
723 | MODULE_LICENSE("GPL v2"); | 751 | MODULE_LICENSE("GPL v2"); |
724 | MODULE_ALIAS("platform:bxt_da7219_max98357a"); | 752 | MODULE_ALIAS("platform:bxt_da7219_max98357a"); |
725 | MODULE_ALIAS("platform:glk_da7219_max98357a"); | 753 | MODULE_ALIAS("platform:glk_da7219_max98357a"); |
754 | MODULE_ALIAS("platform:cml_da7219_max98357a"); | ||
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 83b978e7b4c4..eaf3e2208a06 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c | |||
@@ -324,9 +324,8 @@ static const struct snd_soc_ops cht_be_ssp2_ops = { | |||
324 | }; | 324 | }; |
325 | 325 | ||
326 | static struct snd_soc_aux_dev cht_max98090_headset_dev = { | 326 | static struct snd_soc_aux_dev cht_max98090_headset_dev = { |
327 | .name = "Headset Chip", | 327 | .dlc = COMP_AUX("i2c-104C227E:00"), |
328 | .init = cht_max98090_headset_init, | 328 | .init = cht_max98090_headset_init, |
329 | .codec_name = "i2c-104C227E:00", | ||
330 | }; | 329 | }; |
331 | 330 | ||
332 | SND_SOC_DAILINK_DEF(dummy, | 331 | SND_SOC_DAILINK_DEF(dummy, |
diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 4d3822cff98c..3dadf9bff796 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c | |||
@@ -188,18 +188,14 @@ static struct snd_soc_card haswell_rt5640 = { | |||
188 | static int haswell_audio_probe(struct platform_device *pdev) | 188 | static int haswell_audio_probe(struct platform_device *pdev) |
189 | { | 189 | { |
190 | struct snd_soc_acpi_mach *mach; | 190 | struct snd_soc_acpi_mach *mach; |
191 | const char *platform_name = NULL; | ||
192 | int ret; | 191 | int ret; |
193 | 192 | ||
194 | haswell_rt5640.dev = &pdev->dev; | 193 | haswell_rt5640.dev = &pdev->dev; |
195 | 194 | ||
196 | /* override plaform name, if required */ | 195 | /* override plaform name, if required */ |
197 | mach = (&pdev->dev)->platform_data; | 196 | mach = (&pdev->dev)->platform_data; |
198 | if (mach) /* extra check since legacy does not pass parameters */ | ||
199 | platform_name = mach->mach_params.platform; | ||
200 | |||
201 | ret = snd_soc_fixup_dai_links_platform_name(&haswell_rt5640, | 197 | ret = snd_soc_fixup_dai_links_platform_name(&haswell_rt5640, |
202 | platform_name); | 198 | mach->mach_params.platform); |
203 | if (ret) | 199 | if (ret) |
204 | return ret; | 200 | return ret; |
205 | 201 | ||
diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c index 55fd82e05e2c..58409b6e476e 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.c +++ b/sound/soc/intel/boards/skl_hda_dsp_common.c | |||
@@ -147,6 +147,11 @@ int skl_hda_hdmi_jack_init(struct snd_soc_card *card) | |||
147 | if (err) | 147 | if (err) |
148 | return err; | 148 | return err; |
149 | 149 | ||
150 | err = snd_jack_add_new_kctl(pcm->hdmi_jack.jack, | ||
151 | jack_name, SND_JACK_AVOUT); | ||
152 | if (err) | ||
153 | dev_warn(component->dev, "failed creating Jack kctl\n"); | ||
154 | |||
150 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | 155 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, |
151 | &pcm->hdmi_jack); | 156 | &pcm->hdmi_jack); |
152 | if (err < 0) | 157 | if (err < 0) |
diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 9ed68eb4f058..1778acdc367c 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c | |||
@@ -23,6 +23,7 @@ static const struct snd_soc_dapm_widget skl_hda_widgets[] = { | |||
23 | SND_SOC_DAPM_MIC("Alt Analog In", NULL), | 23 | SND_SOC_DAPM_MIC("Alt Analog In", NULL), |
24 | SND_SOC_DAPM_SPK("Digital Out", NULL), | 24 | SND_SOC_DAPM_SPK("Digital Out", NULL), |
25 | SND_SOC_DAPM_MIC("Digital In", NULL), | 25 | SND_SOC_DAPM_MIC("Digital In", NULL), |
26 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | static const struct snd_soc_dapm_route skl_hda_map[] = { | 29 | static const struct snd_soc_dapm_route skl_hda_map[] = { |
@@ -41,6 +42,9 @@ static const struct snd_soc_dapm_route skl_hda_map[] = { | |||
41 | { "Codec Input Pin2", NULL, "Digital In" }, | 42 | { "Codec Input Pin2", NULL, "Digital In" }, |
42 | { "Codec Input Pin3", NULL, "Alt Analog In" }, | 43 | { "Codec Input Pin3", NULL, "Alt Analog In" }, |
43 | 44 | ||
45 | /* digital mics */ | ||
46 | {"DMic", NULL, "SoC DMIC"}, | ||
47 | |||
44 | /* CODEC BE connections */ | 48 | /* CODEC BE connections */ |
45 | { "Analog Codec Playback", NULL, "Analog CPU Playback" }, | 49 | { "Analog Codec Playback", NULL, "Analog CPU Playback" }, |
46 | { "Analog CPU Playback", NULL, "codec0_out" }, | 50 | { "Analog CPU Playback", NULL, "codec0_out" }, |
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 0b12d61cf1e7..a437567b8cee 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c | |||
@@ -91,8 +91,7 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { | |||
91 | { | 91 | { |
92 | .callback = sof_rt5682_quirk_cb, | 92 | .callback = sof_rt5682_quirk_cb, |
93 | .matches = { | 93 | .matches = { |
94 | DMI_MATCH(DMI_SYS_VENDOR, "Google"), | 94 | DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"), |
95 | DMI_MATCH(DMI_PRODUCT_NAME, "Hatch"), | ||
96 | }, | 95 | }, |
97 | .driver_data = (void *)(SOF_RT5682_MCLK_EN | | 96 | .driver_data = (void *)(SOF_RT5682_MCLK_EN | |
98 | SOF_RT5682_MCLK_24MHZ | | 97 | SOF_RT5682_MCLK_24MHZ | |
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index 56c81e20b5bf..18d9630ae9a2 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile | |||
@@ -8,6 +8,7 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m | |||
8 | soc-acpi-intel-skl-match.o soc-acpi-intel-kbl-match.o \ | 8 | soc-acpi-intel-skl-match.o soc-acpi-intel-kbl-match.o \ |
9 | soc-acpi-intel-bxt-match.o soc-acpi-intel-glk-match.o \ | 9 | soc-acpi-intel-bxt-match.o soc-acpi-intel-glk-match.o \ |
10 | soc-acpi-intel-cnl-match.o soc-acpi-intel-icl-match.o \ | 10 | soc-acpi-intel-cnl-match.o soc-acpi-intel-icl-match.o \ |
11 | soc-acpi-intel-tgl-match.o soc-acpi-intel-ehl-match.o \ | ||
11 | soc-acpi-intel-hda-match.o | 12 | soc-acpi-intel-hda-match.o |
12 | 13 | ||
13 | obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o | 14 | obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o |
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index 771b0ef21051..985aa366c9e8 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c | |||
@@ -19,6 +19,11 @@ static struct snd_soc_acpi_codecs cml_codecs = { | |||
19 | .codecs = {"10EC5682"} | 19 | .codecs = {"10EC5682"} |
20 | }; | 20 | }; |
21 | 21 | ||
22 | static struct snd_soc_acpi_codecs cml_spk_codecs = { | ||
23 | .num_codecs = 1, | ||
24 | .codecs = {"MX98357A"} | ||
25 | }; | ||
26 | |||
22 | struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = { | 27 | struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = { |
23 | { | 28 | { |
24 | .id = "INT34C2", | 29 | .id = "INT34C2", |
@@ -29,6 +34,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = { | |||
29 | .sof_tplg_filename = "sof-cnl-rt274.tplg", | 34 | .sof_tplg_filename = "sof-cnl-rt274.tplg", |
30 | }, | 35 | }, |
31 | { | 36 | { |
37 | .id = "DLGS7219", | ||
38 | .drv_name = "cml_da7219_max98357a", | ||
39 | .quirk_data = &cml_spk_codecs, | ||
40 | .sof_fw_filename = "sof-cnl.ri", | ||
41 | .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg", | ||
42 | }, | ||
43 | { | ||
32 | .id = "MX98357A", | 44 | .id = "MX98357A", |
33 | .drv_name = "sof_rt5682", | 45 | .drv_name = "sof_rt5682", |
34 | .quirk_data = &cml_codecs, | 46 | .quirk_data = &cml_codecs, |
diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c new file mode 100644 index 000000000000..a1290c3fa99f --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c | |||
@@ -0,0 +1,18 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * soc-apci-intel-ehl-match.c - tables and support for EHL ACPI enumeration. | ||
4 | * | ||
5 | * Copyright (c) 2019, Intel Corporation. | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <sound/soc-acpi.h> | ||
10 | #include <sound/soc-acpi-intel-match.h> | ||
11 | |||
12 | struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = { | ||
13 | {}, | ||
14 | }; | ||
15 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ehl_machines); | ||
16 | |||
17 | MODULE_LICENSE("GPL v2"); | ||
18 | MODULE_DESCRIPTION("Intel Common ACPI Match module"); | ||
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c new file mode 100644 index 000000000000..57a6298d6dca --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c | |||
@@ -0,0 +1,24 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * soc-apci-intel-tgl-match.c - tables and support for ICL ACPI enumeration. | ||
4 | * | ||
5 | * Copyright (c) 2019, Intel Corporation. | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <sound/soc-acpi.h> | ||
10 | #include <sound/soc-acpi-intel-match.h> | ||
11 | |||
12 | struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = { | ||
13 | { | ||
14 | .id = "10EC1308", | ||
15 | .drv_name = "tgl_rt1308", | ||
16 | .sof_fw_filename = "sof-tgl.ri", | ||
17 | .sof_tplg_filename = "sof-tgl-rt1308.tplg", | ||
18 | }, | ||
19 | {}, | ||
20 | }; | ||
21 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines); | ||
22 | |||
23 | MODULE_LICENSE("GPL v2"); | ||
24 | MODULE_DESCRIPTION("Intel Common ACPI Match module"); | ||
diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h index 4718fd3cf636..e6357d306cb8 100644 --- a/sound/soc/intel/common/soc-intel-quirks.h +++ b/sound/soc/intel/common/soc-intel-quirks.h | |||
@@ -36,6 +36,7 @@ SOC_INTEL_IS_CPU(byt, INTEL_FAM6_ATOM_SILVERMONT); | |||
36 | SOC_INTEL_IS_CPU(cht, INTEL_FAM6_ATOM_AIRMONT); | 36 | SOC_INTEL_IS_CPU(cht, INTEL_FAM6_ATOM_AIRMONT); |
37 | SOC_INTEL_IS_CPU(apl, INTEL_FAM6_ATOM_GOLDMONT); | 37 | SOC_INTEL_IS_CPU(apl, INTEL_FAM6_ATOM_GOLDMONT); |
38 | SOC_INTEL_IS_CPU(glk, INTEL_FAM6_ATOM_GOLDMONT_PLUS); | 38 | SOC_INTEL_IS_CPU(glk, INTEL_FAM6_ATOM_GOLDMONT_PLUS); |
39 | SOC_INTEL_IS_CPU(cml, INTEL_FAM6_KABYLAKE_MOBILE); | ||
39 | 40 | ||
40 | static inline bool soc_intel_is_byt_cr(struct platform_device *pdev) | 41 | static inline bool soc_intel_is_byt_cr(struct platform_device *pdev) |
41 | { | 42 | { |
@@ -110,6 +111,10 @@ static inline bool soc_intel_is_glk(void) | |||
110 | return false; | 111 | return false; |
111 | } | 112 | } |
112 | 113 | ||
114 | static inline bool soc_intel_is_cml(void) | ||
115 | { | ||
116 | return false; | ||
117 | } | ||
113 | #endif | 118 | #endif |
114 | 119 | ||
115 | #endif /* _SND_SOC_INTEL_QUIRKS_H */ | 120 | #endif /* _SND_SOC_INTEL_QUIRKS_H */ |
diff --git a/sound/soc/intel/common/sst-acpi.c b/sound/soc/intel/common/sst-acpi.c index 0e8e0a7a11df..5854868650b9 100644 --- a/sound/soc/intel/common/sst-acpi.c +++ b/sound/soc/intel/common/sst-acpi.c | |||
@@ -141,11 +141,12 @@ static int sst_acpi_probe(struct platform_device *pdev) | |||
141 | } | 141 | } |
142 | 142 | ||
143 | platform_set_drvdata(pdev, sst_acpi); | 143 | platform_set_drvdata(pdev, sst_acpi); |
144 | mach->pdata = sst_pdata; | ||
144 | 145 | ||
145 | /* register machine driver */ | 146 | /* register machine driver */ |
146 | sst_acpi->pdev_mach = | 147 | sst_acpi->pdev_mach = |
147 | platform_device_register_data(dev, mach->drv_name, -1, | 148 | platform_device_register_data(dev, mach->drv_name, -1, |
148 | sst_pdata, sizeof(*sst_pdata)); | 149 | mach, sizeof(*mach)); |
149 | if (IS_ERR(sst_acpi->pdev_mach)) | 150 | if (IS_ERR(sst_acpi->pdev_mach)) |
150 | return PTR_ERR(sst_acpi->pdev_mach); | 151 | return PTR_ERR(sst_acpi->pdev_mach); |
151 | 152 | ||
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index 3a66121ee9bb..6068bb697e22 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c | |||
@@ -43,7 +43,7 @@ static struct ipc_message *msg_get_empty(struct sst_generic_ipc *ipc) | |||
43 | } | 43 | } |
44 | 44 | ||
45 | static int tx_wait_done(struct sst_generic_ipc *ipc, | 45 | static int tx_wait_done(struct sst_generic_ipc *ipc, |
46 | struct ipc_message *msg, void *rx_data) | 46 | struct ipc_message *msg, struct sst_ipc_message *reply) |
47 | { | 47 | { |
48 | unsigned long flags; | 48 | unsigned long flags; |
49 | int ret; | 49 | int ret; |
@@ -62,8 +62,11 @@ static int tx_wait_done(struct sst_generic_ipc *ipc, | |||
62 | } else { | 62 | } else { |
63 | 63 | ||
64 | /* copy the data returned from DSP */ | 64 | /* copy the data returned from DSP */ |
65 | if (rx_data) | 65 | if (reply) { |
66 | memcpy(rx_data, msg->rx_data, msg->rx_size); | 66 | reply->header = msg->rx.header; |
67 | if (reply->data) | ||
68 | memcpy(reply->data, msg->rx.data, msg->rx.size); | ||
69 | } | ||
67 | ret = msg->errno; | 70 | ret = msg->errno; |
68 | } | 71 | } |
69 | 72 | ||
@@ -72,9 +75,9 @@ static int tx_wait_done(struct sst_generic_ipc *ipc, | |||
72 | return ret; | 75 | return ret; |
73 | } | 76 | } |
74 | 77 | ||
75 | static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header, | 78 | static int ipc_tx_message(struct sst_generic_ipc *ipc, |
76 | void *tx_data, size_t tx_bytes, void *rx_data, | 79 | struct sst_ipc_message request, |
77 | size_t rx_bytes, int wait) | 80 | struct sst_ipc_message *reply, int wait) |
78 | { | 81 | { |
79 | struct ipc_message *msg; | 82 | struct ipc_message *msg; |
80 | unsigned long flags; | 83 | unsigned long flags; |
@@ -87,23 +90,24 @@ static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header, | |||
87 | return -EBUSY; | 90 | return -EBUSY; |
88 | } | 91 | } |
89 | 92 | ||
90 | msg->header = header; | 93 | msg->tx.header = request.header; |
91 | msg->tx_size = tx_bytes; | 94 | msg->tx.size = request.size; |
92 | msg->rx_size = rx_bytes; | 95 | msg->rx.header = 0; |
96 | msg->rx.size = reply ? reply->size : 0; | ||
93 | msg->wait = wait; | 97 | msg->wait = wait; |
94 | msg->errno = 0; | 98 | msg->errno = 0; |
95 | msg->pending = false; | 99 | msg->pending = false; |
96 | msg->complete = false; | 100 | msg->complete = false; |
97 | 101 | ||
98 | if ((tx_bytes) && (ipc->ops.tx_data_copy != NULL)) | 102 | if ((request.size) && (ipc->ops.tx_data_copy != NULL)) |
99 | ipc->ops.tx_data_copy(msg, tx_data, tx_bytes); | 103 | ipc->ops.tx_data_copy(msg, request.data, request.size); |
100 | 104 | ||
101 | list_add_tail(&msg->list, &ipc->tx_list); | 105 | list_add_tail(&msg->list, &ipc->tx_list); |
102 | schedule_work(&ipc->kwork); | 106 | schedule_work(&ipc->kwork); |
103 | spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); | 107 | spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); |
104 | 108 | ||
105 | if (wait) | 109 | if (wait) |
106 | return tx_wait_done(ipc, msg, rx_data); | 110 | return tx_wait_done(ipc, msg, reply); |
107 | else | 111 | else |
108 | return 0; | 112 | return 0; |
109 | } | 113 | } |
@@ -118,13 +122,13 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) | |||
118 | return -ENOMEM; | 122 | return -ENOMEM; |
119 | 123 | ||
120 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { | 124 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { |
121 | ipc->msg[i].tx_data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL); | 125 | ipc->msg[i].tx.data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL); |
122 | if (ipc->msg[i].tx_data == NULL) | 126 | if (ipc->msg[i].tx.data == NULL) |
123 | goto free_mem; | 127 | goto free_mem; |
124 | 128 | ||
125 | ipc->msg[i].rx_data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL); | 129 | ipc->msg[i].rx.data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL); |
126 | if (ipc->msg[i].rx_data == NULL) { | 130 | if (ipc->msg[i].rx.data == NULL) { |
127 | kfree(ipc->msg[i].tx_data); | 131 | kfree(ipc->msg[i].tx.data); |
128 | goto free_mem; | 132 | goto free_mem; |
129 | } | 133 | } |
130 | 134 | ||
@@ -136,8 +140,8 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) | |||
136 | 140 | ||
137 | free_mem: | 141 | free_mem: |
138 | while (i > 0) { | 142 | while (i > 0) { |
139 | kfree(ipc->msg[i-1].tx_data); | 143 | kfree(ipc->msg[i-1].tx.data); |
140 | kfree(ipc->msg[i-1].rx_data); | 144 | kfree(ipc->msg[i-1].rx.data); |
141 | --i; | 145 | --i; |
142 | } | 146 | } |
143 | kfree(ipc->msg); | 147 | kfree(ipc->msg); |
@@ -173,8 +177,8 @@ static void ipc_tx_msgs(struct work_struct *work) | |||
173 | spin_unlock_irq(&ipc->dsp->spinlock); | 177 | spin_unlock_irq(&ipc->dsp->spinlock); |
174 | } | 178 | } |
175 | 179 | ||
176 | int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header, | 180 | int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, |
177 | void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes) | 181 | struct sst_ipc_message request, struct sst_ipc_message *reply) |
178 | { | 182 | { |
179 | int ret; | 183 | int ret; |
180 | 184 | ||
@@ -187,8 +191,7 @@ int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header, | |||
187 | if (ipc->ops.check_dsp_lp_on(ipc->dsp, true)) | 191 | if (ipc->ops.check_dsp_lp_on(ipc->dsp, true)) |
188 | return -EIO; | 192 | return -EIO; |
189 | 193 | ||
190 | ret = ipc_tx_message(ipc, header, tx_data, tx_bytes, | 194 | ret = ipc_tx_message(ipc, request, reply, 1); |
191 | rx_data, rx_bytes, 1); | ||
192 | 195 | ||
193 | if (ipc->ops.check_dsp_lp_on) | 196 | if (ipc->ops.check_dsp_lp_on) |
194 | if (ipc->ops.check_dsp_lp_on(ipc->dsp, false)) | 197 | if (ipc->ops.check_dsp_lp_on(ipc->dsp, false)) |
@@ -198,19 +201,17 @@ int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header, | |||
198 | } | 201 | } |
199 | EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait); | 202 | EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait); |
200 | 203 | ||
201 | int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header, | 204 | int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, |
202 | void *tx_data, size_t tx_bytes) | 205 | struct sst_ipc_message request) |
203 | { | 206 | { |
204 | return ipc_tx_message(ipc, header, tx_data, tx_bytes, | 207 | return ipc_tx_message(ipc, request, NULL, 0); |
205 | NULL, 0, 0); | ||
206 | } | 208 | } |
207 | EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait); | 209 | EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait); |
208 | 210 | ||
209 | int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, u64 header, | 211 | int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, |
210 | void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes) | 212 | struct sst_ipc_message request, struct sst_ipc_message *reply) |
211 | { | 213 | { |
212 | return ipc_tx_message(ipc, header, tx_data, tx_bytes, | 214 | return ipc_tx_message(ipc, request, reply, 1); |
213 | rx_data, rx_bytes, 1); | ||
214 | } | 215 | } |
215 | EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nopm); | 216 | EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nopm); |
216 | 217 | ||
@@ -232,7 +233,7 @@ struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc, | |||
232 | } | 233 | } |
233 | 234 | ||
234 | list_for_each_entry(msg, &ipc->rx_list, list) { | 235 | list_for_each_entry(msg, &ipc->rx_list, list) { |
235 | if ((msg->header & mask) == header) | 236 | if ((msg->tx.header & mask) == header) |
236 | return msg; | 237 | return msg; |
237 | } | 238 | } |
238 | 239 | ||
@@ -306,8 +307,8 @@ void sst_ipc_fini(struct sst_generic_ipc *ipc) | |||
306 | 307 | ||
307 | if (ipc->msg) { | 308 | if (ipc->msg) { |
308 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { | 309 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { |
309 | kfree(ipc->msg[i].tx_data); | 310 | kfree(ipc->msg[i].tx.data); |
310 | kfree(ipc->msg[i].rx_data); | 311 | kfree(ipc->msg[i].rx.data); |
311 | } | 312 | } |
312 | kfree(ipc->msg); | 313 | kfree(ipc->msg); |
313 | } | 314 | } |
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index c6779e2ac830..08c4831b2664 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h | |||
@@ -17,15 +17,16 @@ | |||
17 | 17 | ||
18 | #define IPC_MAX_MAILBOX_BYTES 256 | 18 | #define IPC_MAX_MAILBOX_BYTES 256 |
19 | 19 | ||
20 | struct ipc_message { | 20 | struct sst_ipc_message { |
21 | struct list_head list; | ||
22 | u64 header; | 21 | u64 header; |
22 | void *data; | ||
23 | size_t size; | ||
24 | }; | ||
23 | 25 | ||
24 | /* direction wrt host CPU */ | 26 | struct ipc_message { |
25 | char *tx_data; | 27 | struct list_head list; |
26 | size_t tx_size; | 28 | struct sst_ipc_message tx; |
27 | char *rx_data; | 29 | struct sst_ipc_message rx; |
28 | size_t rx_size; | ||
29 | 30 | ||
30 | wait_queue_head_t waitq; | 31 | wait_queue_head_t waitq; |
31 | bool pending; | 32 | bool pending; |
@@ -35,6 +36,7 @@ struct ipc_message { | |||
35 | }; | 36 | }; |
36 | 37 | ||
37 | struct sst_generic_ipc; | 38 | struct sst_generic_ipc; |
39 | struct sst_dsp; | ||
38 | 40 | ||
39 | struct sst_plat_ipc_ops { | 41 | struct sst_plat_ipc_ops { |
40 | void (*tx_msg)(struct sst_generic_ipc *, struct ipc_message *); | 42 | void (*tx_msg)(struct sst_generic_ipc *, struct ipc_message *); |
@@ -65,14 +67,14 @@ struct sst_generic_ipc { | |||
65 | struct sst_plat_ipc_ops ops; | 67 | struct sst_plat_ipc_ops ops; |
66 | }; | 68 | }; |
67 | 69 | ||
68 | int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header, | 70 | int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, |
69 | void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes); | 71 | struct sst_ipc_message request, struct sst_ipc_message *reply); |
70 | 72 | ||
71 | int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header, | 73 | int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, |
72 | void *tx_data, size_t tx_bytes); | 74 | struct sst_ipc_message request); |
73 | 75 | ||
74 | int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, u64 header, | 76 | int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, |
75 | void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes); | 77 | struct sst_ipc_message request, struct sst_ipc_message *reply); |
76 | 78 | ||
77 | struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc, | 79 | struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc, |
78 | u64 header); | 80 | u64 header); |
diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c index a83b92d6bea8..0ff89ea96ccf 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.c +++ b/sound/soc/intel/haswell/sst-haswell-ipc.c | |||
@@ -511,7 +511,7 @@ static void hsw_notification_work(struct work_struct *work) | |||
511 | static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) | 511 | static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) |
512 | { | 512 | { |
513 | struct sst_hsw_stream *stream; | 513 | struct sst_hsw_stream *stream; |
514 | u32 header = msg->header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); | 514 | u32 header = msg->tx.header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); |
515 | u32 stream_id = msg_get_stream_id(header); | 515 | u32 stream_id = msg_get_stream_id(header); |
516 | u32 stream_msg = msg_get_stream_type(header); | 516 | u32 stream_msg = msg_get_stream_type(header); |
517 | 517 | ||
@@ -552,6 +552,7 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header) | |||
552 | return -EIO; | 552 | return -EIO; |
553 | } | 553 | } |
554 | 554 | ||
555 | msg->rx.header = header; | ||
555 | /* first process the header */ | 556 | /* first process the header */ |
556 | switch (reply) { | 557 | switch (reply) { |
557 | case IPC_GLB_REPLY_PENDING: | 558 | case IPC_GLB_REPLY_PENDING: |
@@ -562,13 +563,13 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header) | |||
562 | case IPC_GLB_REPLY_SUCCESS: | 563 | case IPC_GLB_REPLY_SUCCESS: |
563 | if (msg->pending) { | 564 | if (msg->pending) { |
564 | trace_ipc_pending_reply("completed", header); | 565 | trace_ipc_pending_reply("completed", header); |
565 | sst_dsp_inbox_read(hsw->dsp, msg->rx_data, | 566 | sst_dsp_inbox_read(hsw->dsp, msg->rx.data, |
566 | msg->rx_size); | 567 | msg->rx.size); |
567 | hsw->ipc.pending = false; | 568 | hsw->ipc.pending = false; |
568 | } else { | 569 | } else { |
569 | /* copy data from the DSP */ | 570 | /* copy data from the DSP */ |
570 | sst_dsp_outbox_read(hsw->dsp, msg->rx_data, | 571 | sst_dsp_outbox_read(hsw->dsp, msg->rx.data, |
571 | msg->rx_size); | 572 | msg->rx.size); |
572 | } | 573 | } |
573 | break; | 574 | break; |
574 | /* these will be rare - but useful for debug */ | 575 | /* these will be rare - but useful for debug */ |
@@ -810,11 +811,13 @@ static irqreturn_t hsw_irq_thread(int irq, void *context) | |||
810 | int sst_hsw_fw_get_version(struct sst_hsw *hsw, | 811 | int sst_hsw_fw_get_version(struct sst_hsw *hsw, |
811 | struct sst_hsw_ipc_fw_version *version) | 812 | struct sst_hsw_ipc_fw_version *version) |
812 | { | 813 | { |
814 | struct sst_ipc_message request = {0}, reply = {0}; | ||
813 | int ret; | 815 | int ret; |
814 | 816 | ||
815 | ret = sst_ipc_tx_message_wait(&hsw->ipc, | 817 | request.header = IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION); |
816 | IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION), | 818 | reply.data = version; |
817 | NULL, 0, version, sizeof(*version)); | 819 | reply.size = sizeof(*version); |
820 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply); | ||
818 | if (ret < 0) | 821 | if (ret < 0) |
819 | dev_err(hsw->dev, "error: get version failed\n"); | 822 | dev_err(hsw->dev, "error: get version failed\n"); |
820 | 823 | ||
@@ -840,7 +843,7 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | |||
840 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) | 843 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) |
841 | { | 844 | { |
842 | struct sst_hsw_ipc_volume_req *req; | 845 | struct sst_hsw_ipc_volume_req *req; |
843 | u32 header; | 846 | struct sst_ipc_message request; |
844 | int ret; | 847 | int ret; |
845 | 848 | ||
846 | trace_ipc_request("set stream volume", stream->reply.stream_hw_id); | 849 | trace_ipc_request("set stream volume", stream->reply.stream_hw_id); |
@@ -848,11 +851,11 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | |||
848 | if (channel >= 2 && channel != SST_HSW_CHANNELS_ALL) | 851 | if (channel >= 2 && channel != SST_HSW_CHANNELS_ALL) |
849 | return -EINVAL; | 852 | return -EINVAL; |
850 | 853 | ||
851 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | | 854 | request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | |
852 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); | 855 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); |
853 | header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); | 856 | request.header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); |
854 | header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); | 857 | request.header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); |
855 | header |= (stage_id << IPC_STG_ID_SHIFT); | 858 | request.header |= (stage_id << IPC_STG_ID_SHIFT); |
856 | 859 | ||
857 | req = &stream->vol_req; | 860 | req = &stream->vol_req; |
858 | req->target_volume = volume; | 861 | req->target_volume = volume; |
@@ -877,8 +880,9 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | |||
877 | req->channel = channel; | 880 | req->channel = channel; |
878 | } | 881 | } |
879 | 882 | ||
880 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, req, | 883 | request.data = req; |
881 | sizeof(*req), NULL, 0); | 884 | request.size = sizeof(*req); |
885 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); | ||
882 | if (ret < 0) { | 886 | if (ret < 0) { |
883 | dev_err(hsw->dev, "error: set stream volume failed\n"); | 887 | dev_err(hsw->dev, "error: set stream volume failed\n"); |
884 | return ret; | 888 | return ret; |
@@ -905,7 +909,7 @@ int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | |||
905 | u32 volume) | 909 | u32 volume) |
906 | { | 910 | { |
907 | struct sst_hsw_ipc_volume_req req; | 911 | struct sst_hsw_ipc_volume_req req; |
908 | u32 header; | 912 | struct sst_ipc_message request; |
909 | int ret; | 913 | int ret; |
910 | 914 | ||
911 | trace_ipc_request("set mixer volume", volume); | 915 | trace_ipc_request("set mixer volume", volume); |
@@ -933,18 +937,19 @@ int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | |||
933 | req.channel = channel; | 937 | req.channel = channel; |
934 | } | 938 | } |
935 | 939 | ||
936 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | | 940 | request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | |
937 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); | 941 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); |
938 | header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT); | 942 | request.header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT); |
939 | header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); | 943 | request.header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); |
940 | header |= (stage_id << IPC_STG_ID_SHIFT); | 944 | request.header |= (stage_id << IPC_STG_ID_SHIFT); |
941 | 945 | ||
942 | req.curve_duration = hsw->curve_duration; | 946 | req.curve_duration = hsw->curve_duration; |
943 | req.curve_type = hsw->curve_type; | 947 | req.curve_type = hsw->curve_type; |
944 | req.target_volume = volume; | 948 | req.target_volume = volume; |
945 | 949 | ||
946 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &req, | 950 | request.data = &req; |
947 | sizeof(req), NULL, 0); | 951 | request.size = sizeof(req); |
952 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); | ||
948 | if (ret < 0) { | 953 | if (ret < 0) { |
949 | dev_err(hsw->dev, "error: set mixer volume failed\n"); | 954 | dev_err(hsw->dev, "error: set mixer volume failed\n"); |
950 | return ret; | 955 | return ret; |
@@ -983,7 +988,7 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | |||
983 | 988 | ||
984 | int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | 989 | int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) |
985 | { | 990 | { |
986 | u32 header; | 991 | struct sst_ipc_message request; |
987 | int ret = 0; | 992 | int ret = 0; |
988 | struct sst_dsp *sst = hsw->dsp; | 993 | struct sst_dsp *sst = hsw->dsp; |
989 | unsigned long flags; | 994 | unsigned long flags; |
@@ -1000,10 +1005,11 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | |||
1000 | trace_ipc_request("stream free", stream->host_id); | 1005 | trace_ipc_request("stream free", stream->host_id); |
1001 | 1006 | ||
1002 | stream->free_req.stream_id = stream->reply.stream_hw_id; | 1007 | stream->free_req.stream_id = stream->reply.stream_hw_id; |
1003 | header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM); | 1008 | request.header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM); |
1009 | request.data = &stream->free_req; | ||
1010 | request.size = sizeof(stream->free_req); | ||
1004 | 1011 | ||
1005 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &stream->free_req, | 1012 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); |
1006 | sizeof(stream->free_req), NULL, 0); | ||
1007 | if (ret < 0) { | 1013 | if (ret < 0) { |
1008 | dev_err(hsw->dev, "error: free stream %d failed\n", | 1014 | dev_err(hsw->dev, "error: free stream %d failed\n", |
1009 | stream->free_req.stream_id); | 1015 | stream->free_req.stream_id); |
@@ -1175,9 +1181,7 @@ int sst_hsw_stream_set_module_info(struct sst_hsw *hsw, | |||
1175 | 1181 | ||
1176 | int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | 1182 | int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) |
1177 | { | 1183 | { |
1178 | struct sst_hsw_ipc_stream_alloc_req *str_req = &stream->request; | 1184 | struct sst_ipc_message request, reply = {0}; |
1179 | struct sst_hsw_ipc_stream_alloc_reply *reply = &stream->reply; | ||
1180 | u32 header; | ||
1181 | int ret; | 1185 | int ret; |
1182 | 1186 | ||
1183 | if (!stream) { | 1187 | if (!stream) { |
@@ -1192,10 +1196,13 @@ int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | |||
1192 | 1196 | ||
1193 | trace_ipc_request("stream alloc", stream->host_id); | 1197 | trace_ipc_request("stream alloc", stream->host_id); |
1194 | 1198 | ||
1195 | header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM); | 1199 | request.header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM); |
1200 | request.data = &stream->request; | ||
1201 | request.size = sizeof(stream->request); | ||
1202 | reply.data = &stream->reply; | ||
1203 | reply.size = sizeof(stream->reply); | ||
1196 | 1204 | ||
1197 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, str_req, | 1205 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply); |
1198 | sizeof(*str_req), reply, sizeof(*reply)); | ||
1199 | if (ret < 0) { | 1206 | if (ret < 0) { |
1200 | dev_err(hsw->dev, "error: stream commit failed\n"); | 1207 | dev_err(hsw->dev, "error: stream commit failed\n"); |
1201 | return ret; | 1208 | return ret; |
@@ -1235,23 +1242,22 @@ void sst_hsw_stream_set_silence_start(struct sst_hsw *hsw, | |||
1235 | ABI to be opaque to client PCM drivers to cope with any future ABI changes */ | 1242 | ABI to be opaque to client PCM drivers to cope with any future ABI changes */ |
1236 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw) | 1243 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw) |
1237 | { | 1244 | { |
1238 | struct sst_hsw_ipc_stream_info_reply *reply; | 1245 | struct sst_ipc_message request = {0}, reply = {0}; |
1239 | u32 header; | ||
1240 | int ret; | 1246 | int ret; |
1241 | 1247 | ||
1242 | reply = &hsw->mixer_info; | 1248 | request.header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO); |
1243 | header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO); | 1249 | reply.data = &hsw->mixer_info; |
1250 | reply.size = sizeof(hsw->mixer_info); | ||
1244 | 1251 | ||
1245 | trace_ipc_request("get global mixer info", 0); | 1252 | trace_ipc_request("get global mixer info", 0); |
1246 | 1253 | ||
1247 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, NULL, 0, | 1254 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply); |
1248 | reply, sizeof(*reply)); | ||
1249 | if (ret < 0) { | 1255 | if (ret < 0) { |
1250 | dev_err(hsw->dev, "error: get stream info failed\n"); | 1256 | dev_err(hsw->dev, "error: get stream info failed\n"); |
1251 | return ret; | 1257 | return ret; |
1252 | } | 1258 | } |
1253 | 1259 | ||
1254 | trace_hsw_mixer_info_reply(reply); | 1260 | trace_hsw_mixer_info_reply(&hsw->mixer_info); |
1255 | 1261 | ||
1256 | return 0; | 1262 | return 0; |
1257 | } | 1263 | } |
@@ -1260,16 +1266,15 @@ int sst_hsw_mixer_get_info(struct sst_hsw *hsw) | |||
1260 | static int sst_hsw_stream_operations(struct sst_hsw *hsw, int type, | 1266 | static int sst_hsw_stream_operations(struct sst_hsw *hsw, int type, |
1261 | int stream_id, int wait) | 1267 | int stream_id, int wait) |
1262 | { | 1268 | { |
1263 | u32 header; | 1269 | struct sst_ipc_message request = {0}; |
1264 | 1270 | ||
1265 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(type); | 1271 | request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE); |
1266 | header |= (stream_id << IPC_STR_ID_SHIFT); | 1272 | request.header |= IPC_STR_TYPE(type) | (stream_id << IPC_STR_ID_SHIFT); |
1267 | 1273 | ||
1268 | if (wait) | 1274 | if (wait) |
1269 | return sst_ipc_tx_message_wait(&hsw->ipc, header, | 1275 | return sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); |
1270 | NULL, 0, NULL, 0); | ||
1271 | else | 1276 | else |
1272 | return sst_ipc_tx_message_nowait(&hsw->ipc, header, NULL, 0); | 1277 | return sst_ipc_tx_message_nowait(&hsw->ipc, request); |
1273 | } | 1278 | } |
1274 | 1279 | ||
1275 | /* Stream ALSA trigger operations */ | 1280 | /* Stream ALSA trigger operations */ |
@@ -1377,8 +1382,8 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw, | |||
1377 | enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, | 1382 | enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, |
1378 | enum sst_hsw_device_mode mode, u32 clock_divider) | 1383 | enum sst_hsw_device_mode mode, u32 clock_divider) |
1379 | { | 1384 | { |
1385 | struct sst_ipc_message request; | ||
1380 | struct sst_hsw_ipc_device_config_req config; | 1386 | struct sst_hsw_ipc_device_config_req config; |
1381 | u32 header; | ||
1382 | int ret; | 1387 | int ret; |
1383 | 1388 | ||
1384 | trace_ipc_request("set device config", dev); | 1389 | trace_ipc_request("set device config", dev); |
@@ -1394,10 +1399,11 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw, | |||
1394 | 1399 | ||
1395 | trace_hsw_device_config_req(&config); | 1400 | trace_hsw_device_config_req(&config); |
1396 | 1401 | ||
1397 | header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS); | 1402 | request.header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS); |
1403 | request.data = &config; | ||
1404 | request.size = sizeof(config); | ||
1398 | 1405 | ||
1399 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &config, | 1406 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); |
1400 | sizeof(config), NULL, 0); | ||
1401 | if (ret < 0) | 1407 | if (ret < 0) |
1402 | dev_err(hsw->dev, "error: set device formats failed\n"); | 1408 | dev_err(hsw->dev, "error: set device formats failed\n"); |
1403 | 1409 | ||
@@ -1409,16 +1415,20 @@ EXPORT_SYMBOL_GPL(sst_hsw_device_set_config); | |||
1409 | int sst_hsw_dx_set_state(struct sst_hsw *hsw, | 1415 | int sst_hsw_dx_set_state(struct sst_hsw *hsw, |
1410 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) | 1416 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) |
1411 | { | 1417 | { |
1412 | u32 header, state_; | 1418 | struct sst_ipc_message request, reply = {0}; |
1419 | u32 state_; | ||
1413 | int ret, item; | 1420 | int ret, item; |
1414 | 1421 | ||
1415 | header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); | ||
1416 | state_ = state; | 1422 | state_ = state; |
1423 | request.header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); | ||
1424 | request.data = &state_; | ||
1425 | request.size = sizeof(state_); | ||
1426 | reply.data = dx; | ||
1427 | reply.size = sizeof(*dx); | ||
1417 | 1428 | ||
1418 | trace_ipc_request("PM enter Dx state", state); | 1429 | trace_ipc_request("PM enter Dx state", state); |
1419 | 1430 | ||
1420 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &state_, | 1431 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply); |
1421 | sizeof(state_), dx, sizeof(*dx)); | ||
1422 | if (ret < 0) { | 1432 | if (ret < 0) { |
1423 | dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); | 1433 | dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); |
1424 | return ret; | 1434 | return ret; |
@@ -1878,7 +1888,7 @@ int sst_hsw_module_enable(struct sst_hsw *hsw, | |||
1878 | u32 module_id, u32 instance_id) | 1888 | u32 module_id, u32 instance_id) |
1879 | { | 1889 | { |
1880 | int ret; | 1890 | int ret; |
1881 | u32 header = 0; | 1891 | struct sst_ipc_message request; |
1882 | struct sst_hsw_ipc_module_config config; | 1892 | struct sst_hsw_ipc_module_config config; |
1883 | struct sst_module *module; | 1893 | struct sst_module *module; |
1884 | struct sst_module_runtime *runtime; | 1894 | struct sst_module_runtime *runtime; |
@@ -1907,10 +1917,10 @@ int sst_hsw_module_enable(struct sst_hsw *hsw, | |||
1907 | return -ENXIO; | 1917 | return -ENXIO; |
1908 | } | 1918 | } |
1909 | 1919 | ||
1910 | header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | | 1920 | request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | |
1911 | IPC_MODULE_OPERATION(IPC_MODULE_ENABLE) | | 1921 | IPC_MODULE_OPERATION(IPC_MODULE_ENABLE) | |
1912 | IPC_MODULE_ID(module_id); | 1922 | IPC_MODULE_ID(module_id); |
1913 | dev_dbg(dev, "module enable header: %x\n", header); | 1923 | dev_dbg(dev, "module enable header: %x\n", (u32)request.header); |
1914 | 1924 | ||
1915 | config.map.module_entries_count = 1; | 1925 | config.map.module_entries_count = 1; |
1916 | config.map.module_entries[0].module_id = module->id; | 1926 | config.map.module_entries[0].module_id = module->id; |
@@ -1932,8 +1942,9 @@ int sst_hsw_module_enable(struct sst_hsw *hsw, | |||
1932 | config.scratch_mem.size, config.scratch_mem.offset, | 1942 | config.scratch_mem.size, config.scratch_mem.offset, |
1933 | config.map.module_entries[0].entry_point); | 1943 | config.map.module_entries[0].entry_point); |
1934 | 1944 | ||
1935 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, | 1945 | request.data = &config; |
1936 | &config, sizeof(config), NULL, 0); | 1946 | request.size = sizeof(config); |
1947 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); | ||
1937 | if (ret < 0) | 1948 | if (ret < 0) |
1938 | dev_err(dev, "ipc: module enable failed - %d\n", ret); | 1949 | dev_err(dev, "ipc: module enable failed - %d\n", ret); |
1939 | else | 1950 | else |
@@ -1946,7 +1957,7 @@ int sst_hsw_module_disable(struct sst_hsw *hsw, | |||
1946 | u32 module_id, u32 instance_id) | 1957 | u32 module_id, u32 instance_id) |
1947 | { | 1958 | { |
1948 | int ret; | 1959 | int ret; |
1949 | u32 header; | 1960 | struct sst_ipc_message request = {0}; |
1950 | struct sst_module *module; | 1961 | struct sst_module *module; |
1951 | struct device *dev = hsw->dev; | 1962 | struct device *dev = hsw->dev; |
1952 | struct sst_dsp *dsp = hsw->dsp; | 1963 | struct sst_dsp *dsp = hsw->dsp; |
@@ -1967,11 +1978,11 @@ int sst_hsw_module_disable(struct sst_hsw *hsw, | |||
1967 | return -ENXIO; | 1978 | return -ENXIO; |
1968 | } | 1979 | } |
1969 | 1980 | ||
1970 | header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | | 1981 | request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | |
1971 | IPC_MODULE_OPERATION(IPC_MODULE_DISABLE) | | 1982 | IPC_MODULE_OPERATION(IPC_MODULE_DISABLE) | |
1972 | IPC_MODULE_ID(module_id); | 1983 | IPC_MODULE_ID(module_id); |
1973 | 1984 | ||
1974 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, NULL, 0, NULL, 0); | 1985 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); |
1975 | if (ret < 0) | 1986 | if (ret < 0) |
1976 | dev_err(dev, "module disable failed - %d\n", ret); | 1987 | dev_err(dev, "module disable failed - %d\n", ret); |
1977 | else | 1988 | else |
@@ -1985,15 +1996,16 @@ int sst_hsw_module_set_param(struct sst_hsw *hsw, | |||
1985 | u32 param_size, char *param) | 1996 | u32 param_size, char *param) |
1986 | { | 1997 | { |
1987 | int ret; | 1998 | int ret; |
1988 | u32 header = 0; | 1999 | struct sst_ipc_message request = {0}; |
1989 | u32 payload_size = 0, transfer_parameter_size = 0; | 2000 | u32 payload_size = 0; |
1990 | struct sst_hsw_transfer_parameter *parameter; | 2001 | struct sst_hsw_transfer_parameter *parameter; |
1991 | struct device *dev = hsw->dev; | 2002 | struct device *dev = hsw->dev; |
1992 | 2003 | ||
1993 | header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | | 2004 | request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) | |
1994 | IPC_MODULE_OPERATION(IPC_MODULE_SET_PARAMETER) | | 2005 | IPC_MODULE_OPERATION(IPC_MODULE_SET_PARAMETER) | |
1995 | IPC_MODULE_ID(module_id); | 2006 | IPC_MODULE_ID(module_id); |
1996 | dev_dbg(dev, "sst_hsw_module_set_param header=%x\n", header); | 2007 | dev_dbg(dev, "sst_hsw_module_set_param header=%x\n", |
2008 | (u32)request.header); | ||
1997 | 2009 | ||
1998 | payload_size = param_size + | 2010 | payload_size = param_size + |
1999 | sizeof(struct sst_hsw_transfer_parameter) - | 2011 | sizeof(struct sst_hsw_transfer_parameter) - |
@@ -2003,14 +2015,14 @@ int sst_hsw_module_set_param(struct sst_hsw *hsw, | |||
2003 | 2015 | ||
2004 | if (payload_size <= SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE) { | 2016 | if (payload_size <= SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE) { |
2005 | /* short parameter, mailbox can contain data */ | 2017 | /* short parameter, mailbox can contain data */ |
2006 | dev_dbg(dev, "transfer parameter size : %d\n", | 2018 | dev_dbg(dev, "transfer parameter size : %zu\n", |
2007 | transfer_parameter_size); | 2019 | request.size); |
2008 | 2020 | ||
2009 | transfer_parameter_size = ALIGN(payload_size, 4); | 2021 | request.size = ALIGN(payload_size, 4); |
2010 | dev_dbg(dev, "transfer parameter aligned size : %d\n", | 2022 | dev_dbg(dev, "transfer parameter aligned size : %zu\n", |
2011 | transfer_parameter_size); | 2023 | request.size); |
2012 | 2024 | ||
2013 | parameter = kzalloc(transfer_parameter_size, GFP_KERNEL); | 2025 | parameter = kzalloc(request.size, GFP_KERNEL); |
2014 | if (parameter == NULL) | 2026 | if (parameter == NULL) |
2015 | return -ENOMEM; | 2027 | return -ENOMEM; |
2016 | 2028 | ||
@@ -2022,9 +2034,9 @@ int sst_hsw_module_set_param(struct sst_hsw *hsw, | |||
2022 | 2034 | ||
2023 | parameter->parameter_id = parameter_id; | 2035 | parameter->parameter_id = parameter_id; |
2024 | parameter->data_size = param_size; | 2036 | parameter->data_size = param_size; |
2037 | request.data = parameter; | ||
2025 | 2038 | ||
2026 | ret = sst_ipc_tx_message_wait(&hsw->ipc, header, | 2039 | ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL); |
2027 | parameter, transfer_parameter_size , NULL, 0); | ||
2028 | if (ret < 0) | 2040 | if (ret < 0) |
2029 | dev_err(dev, "ipc: module set parameter failed - %d\n", ret); | 2041 | dev_err(dev, "ipc: module set parameter failed - %d\n", ret); |
2030 | 2042 | ||
@@ -2041,8 +2053,8 @@ static struct sst_dsp_device hsw_dev = { | |||
2041 | static void hsw_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) | 2053 | static void hsw_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) |
2042 | { | 2054 | { |
2043 | /* send the message */ | 2055 | /* send the message */ |
2044 | sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); | 2056 | sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); |
2045 | sst_dsp_ipc_msg_tx(ipc->dsp, msg->header); | 2057 | sst_dsp_ipc_msg_tx(ipc->dsp, msg->tx.header); |
2046 | } | 2058 | } |
2047 | 2059 | ||
2048 | static void hsw_shim_dbg(struct sst_generic_ipc *ipc, const char *text) | 2060 | static void hsw_shim_dbg(struct sst_generic_ipc *ipc, const char *text) |
@@ -2063,7 +2075,7 @@ static void hsw_shim_dbg(struct sst_generic_ipc *ipc, const char *text) | |||
2063 | static void hsw_tx_data_copy(struct ipc_message *msg, char *tx_data, | 2075 | static void hsw_tx_data_copy(struct ipc_message *msg, char *tx_data, |
2064 | size_t tx_size) | 2076 | size_t tx_size) |
2065 | { | 2077 | { |
2066 | memcpy(msg->tx_data, tx_data, tx_size); | 2078 | memcpy(msg->tx.data, tx_data, tx_size); |
2067 | } | 2079 | } |
2068 | 2080 | ||
2069 | static u64 hsw_reply_msg_match(u64 header, u64 *mask) | 2081 | static u64 hsw_reply_msg_match(u64 header, u64 *mask) |
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 86f6e1d801af..48544ff1a3e6 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \ | 2 | snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \ |
3 | skl-topology.o | 3 | skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o skl-sst-cldma.o \ |
4 | skl-sst.o bxt-sst.o cnl-sst.o skl-sst-utils.o | ||
4 | 5 | ||
5 | ifdef CONFIG_DEBUG_FS | 6 | ifdef CONFIG_DEBUG_FS |
6 | snd-soc-skl-objs += skl-debug.o | 7 | snd-soc-skl-objs += skl-debug.o |
@@ -8,13 +9,6 @@ endif | |||
8 | 9 | ||
9 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o | 10 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o |
10 | 11 | ||
11 | # Skylake IPC Support | ||
12 | snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \ | ||
13 | skl-sst-cldma.o skl-sst.o bxt-sst.o cnl-sst.o \ | ||
14 | skl-sst-utils.o | ||
15 | |||
16 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o | ||
17 | |||
18 | #Skylake Clock device support | 12 | #Skylake Clock device support |
19 | snd-soc-skl-ssp-clk-objs := skl-ssp-clk.o | 13 | snd-soc-skl-ssp-clk-objs := skl-ssp-clk.o |
20 | 14 | ||
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 46d5159cf905..92a82e6b5fe6 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include "../common/sst-dsp.h" | 15 | #include "../common/sst-dsp.h" |
16 | #include "../common/sst-dsp-priv.h" | 16 | #include "../common/sst-dsp-priv.h" |
17 | #include "skl-sst-ipc.h" | 17 | #include "skl.h" |
18 | 18 | ||
19 | #define BXT_BASEFW_TIMEOUT 3000 | 19 | #define BXT_BASEFW_TIMEOUT 3000 |
20 | #define BXT_INIT_TIMEOUT 300 | 20 | #define BXT_INIT_TIMEOUT 300 |
@@ -49,7 +49,7 @@ static int | |||
49 | bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) | 49 | bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) |
50 | { | 50 | { |
51 | struct snd_dma_buffer dmab; | 51 | struct snd_dma_buffer dmab; |
52 | struct skl_sst *skl = ctx->thread_context; | 52 | struct skl_dev *skl = ctx->thread_context; |
53 | struct firmware stripped_fw; | 53 | struct firmware stripped_fw; |
54 | int ret = 0, i, dma_id, stream_tag; | 54 | int ret = 0, i, dma_id, stream_tag; |
55 | 55 | ||
@@ -184,7 +184,7 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) | |||
184 | static int bxt_load_base_firmware(struct sst_dsp *ctx) | 184 | static int bxt_load_base_firmware(struct sst_dsp *ctx) |
185 | { | 185 | { |
186 | struct firmware stripped_fw; | 186 | struct firmware stripped_fw; |
187 | struct skl_sst *skl = ctx->thread_context; | 187 | struct skl_dev *skl = ctx->thread_context; |
188 | int ret, i; | 188 | int ret, i; |
189 | 189 | ||
190 | if (ctx->fw == NULL) { | 190 | if (ctx->fw == NULL) { |
@@ -268,7 +268,7 @@ sst_load_base_firmware_failed: | |||
268 | */ | 268 | */ |
269 | static int bxt_d0i3_target_state(struct sst_dsp *ctx) | 269 | static int bxt_d0i3_target_state(struct sst_dsp *ctx) |
270 | { | 270 | { |
271 | struct skl_sst *skl = ctx->thread_context; | 271 | struct skl_dev *skl = ctx->thread_context; |
272 | struct skl_d0i3_data *d0i3 = &skl->d0i3; | 272 | struct skl_d0i3_data *d0i3 = &skl->d0i3; |
273 | 273 | ||
274 | if (skl->cores.state[SKL_DSP_CORE0_ID] != SKL_DSP_RUNNING) | 274 | if (skl->cores.state[SKL_DSP_CORE0_ID] != SKL_DSP_RUNNING) |
@@ -288,8 +288,8 @@ static void bxt_set_dsp_D0i3(struct work_struct *work) | |||
288 | { | 288 | { |
289 | int ret; | 289 | int ret; |
290 | struct skl_ipc_d0ix_msg msg; | 290 | struct skl_ipc_d0ix_msg msg; |
291 | struct skl_sst *skl = container_of(work, | 291 | struct skl_dev *skl = container_of(work, |
292 | struct skl_sst, d0i3.work.work); | 292 | struct skl_dev, d0i3.work.work); |
293 | struct sst_dsp *ctx = skl->dsp; | 293 | struct sst_dsp *ctx = skl->dsp; |
294 | struct skl_d0i3_data *d0i3 = &skl->d0i3; | 294 | struct skl_d0i3_data *d0i3 = &skl->d0i3; |
295 | int target_state; | 295 | int target_state; |
@@ -331,7 +331,7 @@ static void bxt_set_dsp_D0i3(struct work_struct *work) | |||
331 | 331 | ||
332 | static int bxt_schedule_dsp_D0i3(struct sst_dsp *ctx) | 332 | static int bxt_schedule_dsp_D0i3(struct sst_dsp *ctx) |
333 | { | 333 | { |
334 | struct skl_sst *skl = ctx->thread_context; | 334 | struct skl_dev *skl = ctx->thread_context; |
335 | struct skl_d0i3_data *d0i3 = &skl->d0i3; | 335 | struct skl_d0i3_data *d0i3 = &skl->d0i3; |
336 | 336 | ||
337 | /* Schedule D0i3 only if the usecase ref counts are appropriate */ | 337 | /* Schedule D0i3 only if the usecase ref counts are appropriate */ |
@@ -350,7 +350,7 @@ static int bxt_set_dsp_D0i0(struct sst_dsp *ctx) | |||
350 | { | 350 | { |
351 | int ret; | 351 | int ret; |
352 | struct skl_ipc_d0ix_msg msg; | 352 | struct skl_ipc_d0ix_msg msg; |
353 | struct skl_sst *skl = ctx->thread_context; | 353 | struct skl_dev *skl = ctx->thread_context; |
354 | 354 | ||
355 | dev_dbg(ctx->dev, "In %s:\n", __func__); | 355 | dev_dbg(ctx->dev, "In %s:\n", __func__); |
356 | 356 | ||
@@ -389,7 +389,7 @@ static int bxt_set_dsp_D0i0(struct sst_dsp *ctx) | |||
389 | 389 | ||
390 | static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) | 390 | static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) |
391 | { | 391 | { |
392 | struct skl_sst *skl = ctx->thread_context; | 392 | struct skl_dev *skl = ctx->thread_context; |
393 | int ret; | 393 | int ret; |
394 | struct skl_ipc_dxstate_info dx; | 394 | struct skl_ipc_dxstate_info dx; |
395 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | 395 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
@@ -486,7 +486,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) | |||
486 | { | 486 | { |
487 | int ret; | 487 | int ret; |
488 | struct skl_ipc_dxstate_info dx; | 488 | struct skl_ipc_dxstate_info dx; |
489 | struct skl_sst *skl = ctx->thread_context; | 489 | struct skl_dev *skl = ctx->thread_context; |
490 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | 490 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
491 | 491 | ||
492 | dx.core_mask = core_mask; | 492 | dx.core_mask = core_mask; |
@@ -548,9 +548,9 @@ static struct sst_dsp_device skl_dev = { | |||
548 | 548 | ||
549 | int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | 549 | int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, |
550 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, | 550 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, |
551 | struct skl_sst **dsp) | 551 | struct skl_dev **dsp) |
552 | { | 552 | { |
553 | struct skl_sst *skl; | 553 | struct skl_dev *skl; |
554 | struct sst_dsp *sst; | 554 | struct sst_dsp *sst; |
555 | int ret; | 555 | int ret; |
556 | 556 | ||
@@ -591,10 +591,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | |||
591 | } | 591 | } |
592 | EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); | 592 | EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); |
593 | 593 | ||
594 | int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) | 594 | int bxt_sst_init_fw(struct device *dev, struct skl_dev *skl) |
595 | { | 595 | { |
596 | int ret; | 596 | int ret; |
597 | struct sst_dsp *sst = ctx->dsp; | 597 | struct sst_dsp *sst = skl->dsp; |
598 | 598 | ||
599 | ret = sst->fw_ops.load_fw(sst); | 599 | ret = sst->fw_ops.load_fw(sst); |
600 | if (ret < 0) { | 600 | if (ret < 0) { |
@@ -604,29 +604,29 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) | |||
604 | 604 | ||
605 | skl_dsp_init_core_state(sst); | 605 | skl_dsp_init_core_state(sst); |
606 | 606 | ||
607 | if (ctx->lib_count > 1) { | 607 | if (skl->lib_count > 1) { |
608 | ret = sst->fw_ops.load_library(sst, ctx->lib_info, | 608 | ret = sst->fw_ops.load_library(sst, skl->lib_info, |
609 | ctx->lib_count); | 609 | skl->lib_count); |
610 | if (ret < 0) { | 610 | if (ret < 0) { |
611 | dev_err(dev, "Load Library failed : %x\n", ret); | 611 | dev_err(dev, "Load Library failed : %x\n", ret); |
612 | return ret; | 612 | return ret; |
613 | } | 613 | } |
614 | } | 614 | } |
615 | ctx->is_first_boot = false; | 615 | skl->is_first_boot = false; |
616 | 616 | ||
617 | return 0; | 617 | return 0; |
618 | } | 618 | } |
619 | EXPORT_SYMBOL_GPL(bxt_sst_init_fw); | 619 | EXPORT_SYMBOL_GPL(bxt_sst_init_fw); |
620 | 620 | ||
621 | void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) | 621 | void bxt_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) |
622 | { | 622 | { |
623 | 623 | ||
624 | skl_release_library(ctx->lib_info, ctx->lib_count); | 624 | skl_release_library(skl->lib_info, skl->lib_count); |
625 | if (ctx->dsp->fw) | 625 | if (skl->dsp->fw) |
626 | release_firmware(ctx->dsp->fw); | 626 | release_firmware(skl->dsp->fw); |
627 | skl_freeup_uuid_list(ctx); | 627 | skl_freeup_uuid_list(skl); |
628 | skl_ipc_free(&ctx->ipc); | 628 | skl_ipc_free(&skl->ipc); |
629 | ctx->dsp->ops->free(ctx->dsp); | 629 | skl->dsp->ops->free(skl->dsp); |
630 | } | 630 | } |
631 | EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); | 631 | EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); |
632 | 632 | ||
diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h index 426515faab52..7bd4d2a8fdfa 100644 --- a/sound/soc/intel/skylake/cnl-sst-dsp.h +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h | |||
@@ -9,7 +9,6 @@ | |||
9 | #define __CNL_SST_DSP_H__ | 9 | #define __CNL_SST_DSP_H__ |
10 | 10 | ||
11 | struct sst_dsp; | 11 | struct sst_dsp; |
12 | struct skl_sst; | ||
13 | struct sst_dsp_device; | 12 | struct sst_dsp_device; |
14 | struct sst_generic_ipc; | 13 | struct sst_generic_ipc; |
15 | 14 | ||
@@ -97,8 +96,8 @@ void cnl_ipc_free(struct sst_generic_ipc *ipc); | |||
97 | 96 | ||
98 | int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | 97 | int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, |
99 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, | 98 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, |
100 | struct skl_sst **dsp); | 99 | struct skl_dev **dsp); |
101 | int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx); | 100 | int cnl_sst_init_fw(struct device *dev, struct skl_dev *skl); |
102 | void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); | 101 | void cnl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); |
103 | 102 | ||
104 | #endif /*__CNL_SST_DSP_H__*/ | 103 | #endif /*__CNL_SST_DSP_H__*/ |
diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index f2c09fa6ea40..4f64f097e9ae 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c | |||
@@ -24,8 +24,7 @@ | |||
24 | #include "../common/sst-dsp-priv.h" | 24 | #include "../common/sst-dsp-priv.h" |
25 | #include "../common/sst-ipc.h" | 25 | #include "../common/sst-ipc.h" |
26 | #include "cnl-sst-dsp.h" | 26 | #include "cnl-sst-dsp.h" |
27 | #include "skl-sst-dsp.h" | 27 | #include "skl.h" |
28 | #include "skl-sst-ipc.h" | ||
29 | 28 | ||
30 | #define CNL_FW_ROM_INIT 0x1 | 29 | #define CNL_FW_ROM_INIT 0x1 |
31 | #define CNL_FW_INIT 0x5 | 30 | #define CNL_FW_INIT 0x5 |
@@ -109,7 +108,7 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) | |||
109 | static int cnl_load_base_firmware(struct sst_dsp *ctx) | 108 | static int cnl_load_base_firmware(struct sst_dsp *ctx) |
110 | { | 109 | { |
111 | struct firmware stripped_fw; | 110 | struct firmware stripped_fw; |
112 | struct skl_sst *cnl = ctx->thread_context; | 111 | struct skl_dev *cnl = ctx->thread_context; |
113 | int ret; | 112 | int ret; |
114 | 113 | ||
115 | if (!ctx->fw) { | 114 | if (!ctx->fw) { |
@@ -167,7 +166,7 @@ cnl_load_base_firmware_failed: | |||
167 | 166 | ||
168 | static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) | 167 | static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) |
169 | { | 168 | { |
170 | struct skl_sst *cnl = ctx->thread_context; | 169 | struct skl_dev *cnl = ctx->thread_context; |
171 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | 170 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
172 | struct skl_ipc_dxstate_info dx; | 171 | struct skl_ipc_dxstate_info dx; |
173 | int ret; | 172 | int ret; |
@@ -229,7 +228,7 @@ err: | |||
229 | 228 | ||
230 | static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) | 229 | static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) |
231 | { | 230 | { |
232 | struct skl_sst *cnl = ctx->thread_context; | 231 | struct skl_dev *cnl = ctx->thread_context; |
233 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | 232 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
234 | struct skl_ipc_dxstate_info dx; | 233 | struct skl_ipc_dxstate_info dx; |
235 | int ret; | 234 | int ret; |
@@ -293,7 +292,7 @@ static struct sst_ops cnl_ops = { | |||
293 | static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) | 292 | static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) |
294 | { | 293 | { |
295 | struct sst_dsp *dsp = context; | 294 | struct sst_dsp *dsp = context; |
296 | struct skl_sst *cnl = sst_dsp_get_thread_context(dsp); | 295 | struct skl_dev *cnl = sst_dsp_get_thread_context(dsp); |
297 | struct sst_generic_ipc *ipc = &cnl->ipc; | 296 | struct sst_generic_ipc *ipc = &cnl->ipc; |
298 | struct skl_ipc_header header = {0}; | 297 | struct skl_ipc_header header = {0}; |
299 | u32 hipcida, hipctdr, hipctdd; | 298 | u32 hipcida, hipctdr, hipctdd; |
@@ -367,10 +366,10 @@ static struct sst_dsp_device cnl_dev = { | |||
367 | 366 | ||
368 | static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) | 367 | static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) |
369 | { | 368 | { |
370 | struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); | 369 | struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header); |
371 | 370 | ||
372 | if (msg->tx_size) | 371 | if (msg->tx.size) |
373 | sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); | 372 | sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); |
374 | sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, | 373 | sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, |
375 | header->extension); | 374 | header->extension); |
376 | sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, | 375 | sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, |
@@ -386,7 +385,7 @@ static bool cnl_ipc_is_dsp_busy(struct sst_dsp *dsp) | |||
386 | return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); | 385 | return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); |
387 | } | 386 | } |
388 | 387 | ||
389 | static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) | 388 | static int cnl_ipc_init(struct device *dev, struct skl_dev *cnl) |
390 | { | 389 | { |
391 | struct sst_generic_ipc *ipc; | 390 | struct sst_generic_ipc *ipc; |
392 | int err; | 391 | int err; |
@@ -415,9 +414,9 @@ static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) | |||
415 | 414 | ||
416 | int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | 415 | int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, |
417 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, | 416 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, |
418 | struct skl_sst **dsp) | 417 | struct skl_dev **dsp) |
419 | { | 418 | { |
420 | struct skl_sst *cnl; | 419 | struct skl_dev *cnl; |
421 | struct sst_dsp *sst; | 420 | struct sst_dsp *sst; |
422 | int ret; | 421 | int ret; |
423 | 422 | ||
@@ -454,12 +453,12 @@ int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | |||
454 | } | 453 | } |
455 | EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); | 454 | EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); |
456 | 455 | ||
457 | int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) | 456 | int cnl_sst_init_fw(struct device *dev, struct skl_dev *skl) |
458 | { | 457 | { |
459 | int ret; | 458 | int ret; |
460 | struct sst_dsp *sst = ctx->dsp; | 459 | struct sst_dsp *sst = skl->dsp; |
461 | 460 | ||
462 | ret = ctx->dsp->fw_ops.load_fw(sst); | 461 | ret = skl->dsp->fw_ops.load_fw(sst); |
463 | if (ret < 0) { | 462 | if (ret < 0) { |
464 | dev_err(dev, "load base fw failed: %d", ret); | 463 | dev_err(dev, "load base fw failed: %d", ret); |
465 | return ret; | 464 | return ret; |
@@ -467,21 +466,21 @@ int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) | |||
467 | 466 | ||
468 | skl_dsp_init_core_state(sst); | 467 | skl_dsp_init_core_state(sst); |
469 | 468 | ||
470 | ctx->is_first_boot = false; | 469 | skl->is_first_boot = false; |
471 | 470 | ||
472 | return 0; | 471 | return 0; |
473 | } | 472 | } |
474 | EXPORT_SYMBOL_GPL(cnl_sst_init_fw); | 473 | EXPORT_SYMBOL_GPL(cnl_sst_init_fw); |
475 | 474 | ||
476 | void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) | 475 | void cnl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) |
477 | { | 476 | { |
478 | if (ctx->dsp->fw) | 477 | if (skl->dsp->fw) |
479 | release_firmware(ctx->dsp->fw); | 478 | release_firmware(skl->dsp->fw); |
480 | 479 | ||
481 | skl_freeup_uuid_list(ctx); | 480 | skl_freeup_uuid_list(skl); |
482 | cnl_ipc_free(&ctx->ipc); | 481 | cnl_ipc_free(&skl->ipc); |
483 | 482 | ||
484 | ctx->dsp->ops->free(ctx->dsp); | 483 | skl->dsp->ops->free(skl->dsp); |
485 | } | 484 | } |
486 | EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); | 485 | EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); |
487 | 486 | ||
diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c index b28a9c2b0380..3466675f2678 100644 --- a/sound/soc/intel/skylake/skl-debug.c +++ b/sound/soc/intel/skylake/skl-debug.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #define FW_REG_SIZE 0x60 | 20 | #define FW_REG_SIZE 0x60 |
21 | 21 | ||
22 | struct skl_debug { | 22 | struct skl_debug { |
23 | struct skl *skl; | 23 | struct skl_dev *skl; |
24 | struct device *dev; | 24 | struct device *dev; |
25 | 25 | ||
26 | struct dentry *fs; | 26 | struct dentry *fs; |
@@ -66,6 +66,8 @@ static ssize_t module_read(struct file *file, char __user *user_buf, | |||
66 | size_t count, loff_t *ppos) | 66 | size_t count, loff_t *ppos) |
67 | { | 67 | { |
68 | struct skl_module_cfg *mconfig = file->private_data; | 68 | struct skl_module_cfg *mconfig = file->private_data; |
69 | struct skl_module *module = mconfig->module; | ||
70 | struct skl_module_res *res = &module->resources[mconfig->res_idx]; | ||
69 | char *buf; | 71 | char *buf; |
70 | ssize_t ret; | 72 | ssize_t ret; |
71 | 73 | ||
@@ -79,8 +81,8 @@ static ssize_t module_read(struct file *file, char __user *user_buf, | |||
79 | mconfig->id.pvt_id); | 81 | mconfig->id.pvt_id); |
80 | 82 | ||
81 | ret += snprintf(buf + ret, MOD_BUF - ret, | 83 | ret += snprintf(buf + ret, MOD_BUF - ret, |
82 | "Resources:\n\tMCPS %#x\n\tIBS %#x\n\tOBS %#x\t\n", | 84 | "Resources:\n\tCPC %#x\n\tIBS %#x\n\tOBS %#x\t\n", |
83 | mconfig->mcps, mconfig->ibs, mconfig->obs); | 85 | res->cpc, res->ibs, res->obs); |
84 | 86 | ||
85 | ret += snprintf(buf + ret, MOD_BUF - ret, | 87 | ret += snprintf(buf + ret, MOD_BUF - ret, |
86 | "Module data:\n\tCore %d\n\tIn queue %d\n\t" | 88 | "Module data:\n\tCore %d\n\tIn queue %d\n\t" |
@@ -162,17 +164,15 @@ void skl_debug_init_module(struct skl_debug *d, | |||
162 | struct snd_soc_dapm_widget *w, | 164 | struct snd_soc_dapm_widget *w, |
163 | struct skl_module_cfg *mconfig) | 165 | struct skl_module_cfg *mconfig) |
164 | { | 166 | { |
165 | if (!debugfs_create_file(w->name, 0444, | 167 | debugfs_create_file(w->name, 0444, d->modules, mconfig, |
166 | d->modules, mconfig, | 168 | &mcfg_fops); |
167 | &mcfg_fops)) | ||
168 | dev_err(d->dev, "%s: module debugfs init failed\n", w->name); | ||
169 | } | 169 | } |
170 | 170 | ||
171 | static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, | 171 | static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, |
172 | size_t count, loff_t *ppos) | 172 | size_t count, loff_t *ppos) |
173 | { | 173 | { |
174 | struct skl_debug *d = file->private_data; | 174 | struct skl_debug *d = file->private_data; |
175 | struct sst_dsp *sst = d->skl->skl_sst->dsp; | 175 | struct sst_dsp *sst = d->skl->dsp; |
176 | size_t w0_stat_sz = sst->addr.w0_stat_sz; | 176 | size_t w0_stat_sz = sst->addr.w0_stat_sz; |
177 | void __iomem *in_base = sst->mailbox.in_base; | 177 | void __iomem *in_base = sst->mailbox.in_base; |
178 | void __iomem *fw_reg_addr; | 178 | void __iomem *fw_reg_addr; |
@@ -213,7 +213,7 @@ static const struct file_operations soft_regs_ctrl_fops = { | |||
213 | .llseek = default_llseek, | 213 | .llseek = default_llseek, |
214 | }; | 214 | }; |
215 | 215 | ||
216 | struct skl_debug *skl_debugfs_init(struct skl *skl) | 216 | struct skl_debug *skl_debugfs_init(struct skl_dev *skl) |
217 | { | 217 | { |
218 | struct skl_debug *d; | 218 | struct skl_debug *d; |
219 | 219 | ||
@@ -222,37 +222,21 @@ struct skl_debug *skl_debugfs_init(struct skl *skl) | |||
222 | return NULL; | 222 | return NULL; |
223 | 223 | ||
224 | /* create the debugfs dir with platform component's debugfs as parent */ | 224 | /* create the debugfs dir with platform component's debugfs as parent */ |
225 | d->fs = debugfs_create_dir("dsp", | 225 | d->fs = debugfs_create_dir("dsp", skl->component->debugfs_root); |
226 | skl->component->debugfs_root); | ||
227 | if (IS_ERR(d->fs) || !d->fs) { | ||
228 | dev_err(&skl->pci->dev, "debugfs root creation failed\n"); | ||
229 | return NULL; | ||
230 | } | ||
231 | 226 | ||
232 | d->skl = skl; | 227 | d->skl = skl; |
233 | d->dev = &skl->pci->dev; | 228 | d->dev = &skl->pci->dev; |
234 | 229 | ||
235 | /* now create the module dir */ | 230 | /* now create the module dir */ |
236 | d->modules = debugfs_create_dir("modules", d->fs); | 231 | d->modules = debugfs_create_dir("modules", d->fs); |
237 | if (IS_ERR(d->modules) || !d->modules) { | ||
238 | dev_err(&skl->pci->dev, "modules debugfs create failed\n"); | ||
239 | goto err; | ||
240 | } | ||
241 | 232 | ||
242 | if (!debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d, | 233 | debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d, |
243 | &soft_regs_ctrl_fops)) { | 234 | &soft_regs_ctrl_fops); |
244 | dev_err(d->dev, "fw soft regs control debugfs init failed\n"); | ||
245 | goto err; | ||
246 | } | ||
247 | 235 | ||
248 | return d; | 236 | return d; |
249 | |||
250 | err: | ||
251 | debugfs_remove_recursive(d->fs); | ||
252 | return NULL; | ||
253 | } | 237 | } |
254 | 238 | ||
255 | void skl_debugfs_exit(struct skl *skl) | 239 | void skl_debugfs_exit(struct skl_dev *skl) |
256 | { | 240 | { |
257 | struct skl_debug *d = skl->debugfs; | 241 | struct skl_debug *d = skl->debugfs; |
258 | 242 | ||
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index febc070839e0..476ef1897961 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c | |||
@@ -25,29 +25,18 @@ | |||
25 | static int skl_alloc_dma_buf(struct device *dev, | 25 | static int skl_alloc_dma_buf(struct device *dev, |
26 | struct snd_dma_buffer *dmab, size_t size) | 26 | struct snd_dma_buffer *dmab, size_t size) |
27 | { | 27 | { |
28 | struct hdac_bus *bus = dev_get_drvdata(dev); | 28 | return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, dmab); |
29 | |||
30 | if (!bus) | ||
31 | return -ENODEV; | ||
32 | |||
33 | return bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV, size, dmab); | ||
34 | } | 29 | } |
35 | 30 | ||
36 | static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) | 31 | static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) |
37 | { | 32 | { |
38 | struct hdac_bus *bus = dev_get_drvdata(dev); | 33 | snd_dma_free_pages(dmab); |
39 | |||
40 | if (!bus) | ||
41 | return -ENODEV; | ||
42 | |||
43 | bus->io_ops->dma_free_pages(bus, dmab); | ||
44 | |||
45 | return 0; | 34 | return 0; |
46 | } | 35 | } |
47 | 36 | ||
48 | #define SKL_ASTATE_PARAM_ID 4 | 37 | #define SKL_ASTATE_PARAM_ID 4 |
49 | 38 | ||
50 | void skl_dsp_set_astate_cfg(struct skl_sst *ctx, u32 cnt, void *data) | 39 | void skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data) |
51 | { | 40 | { |
52 | struct skl_ipc_large_config_msg msg = {0}; | 41 | struct skl_ipc_large_config_msg msg = {0}; |
53 | 42 | ||
@@ -55,25 +44,7 @@ void skl_dsp_set_astate_cfg(struct skl_sst *ctx, u32 cnt, void *data) | |||
55 | msg.param_data_size = (cnt * sizeof(struct skl_astate_param) + | 44 | msg.param_data_size = (cnt * sizeof(struct skl_astate_param) + |
56 | sizeof(cnt)); | 45 | sizeof(cnt)); |
57 | 46 | ||
58 | skl_ipc_set_large_config(&ctx->ipc, &msg, data); | 47 | skl_ipc_set_large_config(&skl->ipc, &msg, data); |
59 | } | ||
60 | |||
61 | #define NOTIFICATION_PARAM_ID 3 | ||
62 | #define NOTIFICATION_MASK 0xf | ||
63 | |||
64 | /* disable notfication for underruns/overruns from firmware module */ | ||
65 | void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) | ||
66 | { | ||
67 | struct notification_mask mask; | ||
68 | struct skl_ipc_large_config_msg msg = {0}; | ||
69 | |||
70 | mask.notify = NOTIFICATION_MASK; | ||
71 | mask.enable = enable; | ||
72 | |||
73 | msg.large_param_id = NOTIFICATION_PARAM_ID; | ||
74 | msg.param_data_size = sizeof(mask); | ||
75 | |||
76 | skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); | ||
77 | } | 48 | } |
78 | 49 | ||
79 | static int skl_dsp_setup_spib(struct device *dev, unsigned int size, | 50 | static int skl_dsp_setup_spib(struct device *dev, unsigned int size, |
@@ -277,7 +248,7 @@ const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) | |||
277 | return NULL; | 248 | return NULL; |
278 | } | 249 | } |
279 | 250 | ||
280 | int skl_init_dsp(struct skl *skl) | 251 | int skl_init_dsp(struct skl_dev *skl) |
281 | { | 252 | { |
282 | void __iomem *mmio_base; | 253 | void __iomem *mmio_base; |
283 | struct hdac_bus *bus = skl_to_bus(skl); | 254 | struct hdac_bus *bus = skl_to_bus(skl); |
@@ -307,13 +278,13 @@ int skl_init_dsp(struct skl *skl) | |||
307 | loader_ops = ops->loader_ops(); | 278 | loader_ops = ops->loader_ops(); |
308 | ret = ops->init(bus->dev, mmio_base, irq, | 279 | ret = ops->init(bus->dev, mmio_base, irq, |
309 | skl->fw_name, loader_ops, | 280 | skl->fw_name, loader_ops, |
310 | &skl->skl_sst); | 281 | &skl); |
311 | 282 | ||
312 | if (ret < 0) | 283 | if (ret < 0) |
313 | goto unmap_mmio; | 284 | goto unmap_mmio; |
314 | 285 | ||
315 | skl->skl_sst->dsp_ops = ops; | 286 | skl->dsp_ops = ops; |
316 | cores = &skl->skl_sst->cores; | 287 | cores = &skl->cores; |
317 | cores->count = ops->num_cores; | 288 | cores->count = ops->num_cores; |
318 | 289 | ||
319 | cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); | 290 | cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); |
@@ -342,21 +313,20 @@ unmap_mmio: | |||
342 | return ret; | 313 | return ret; |
343 | } | 314 | } |
344 | 315 | ||
345 | int skl_free_dsp(struct skl *skl) | 316 | int skl_free_dsp(struct skl_dev *skl) |
346 | { | 317 | { |
347 | struct hdac_bus *bus = skl_to_bus(skl); | 318 | struct hdac_bus *bus = skl_to_bus(skl); |
348 | struct skl_sst *ctx = skl->skl_sst; | ||
349 | 319 | ||
350 | /* disable ppcap interrupt */ | 320 | /* disable ppcap interrupt */ |
351 | snd_hdac_ext_bus_ppcap_int_enable(bus, false); | 321 | snd_hdac_ext_bus_ppcap_int_enable(bus, false); |
352 | 322 | ||
353 | ctx->dsp_ops->cleanup(bus->dev, ctx); | 323 | skl->dsp_ops->cleanup(bus->dev, skl); |
354 | 324 | ||
355 | kfree(ctx->cores.state); | 325 | kfree(skl->cores.state); |
356 | kfree(ctx->cores.usage_count); | 326 | kfree(skl->cores.usage_count); |
357 | 327 | ||
358 | if (ctx->dsp->addr.lpe) | 328 | if (skl->dsp->addr.lpe) |
359 | iounmap(ctx->dsp->addr.lpe); | 329 | iounmap(skl->dsp->addr.lpe); |
360 | 330 | ||
361 | return 0; | 331 | return 0; |
362 | } | 332 | } |
@@ -368,15 +338,14 @@ int skl_free_dsp(struct skl *skl) | |||
368 | * mode during system suspend. In the case of normal suspend, cancel | 338 | * mode during system suspend. In the case of normal suspend, cancel |
369 | * any pending D0i3 work. | 339 | * any pending D0i3 work. |
370 | */ | 340 | */ |
371 | int skl_suspend_late_dsp(struct skl *skl) | 341 | int skl_suspend_late_dsp(struct skl_dev *skl) |
372 | { | 342 | { |
373 | struct skl_sst *ctx = skl->skl_sst; | ||
374 | struct delayed_work *dwork; | 343 | struct delayed_work *dwork; |
375 | 344 | ||
376 | if (!ctx) | 345 | if (!skl) |
377 | return 0; | 346 | return 0; |
378 | 347 | ||
379 | dwork = &ctx->d0i3.work; | 348 | dwork = &skl->d0i3.work; |
380 | 349 | ||
381 | if (dwork->work.func) { | 350 | if (dwork->work.func) { |
382 | if (skl->supend_active) | 351 | if (skl->supend_active) |
@@ -388,9 +357,8 @@ int skl_suspend_late_dsp(struct skl *skl) | |||
388 | return 0; | 357 | return 0; |
389 | } | 358 | } |
390 | 359 | ||
391 | int skl_suspend_dsp(struct skl *skl) | 360 | int skl_suspend_dsp(struct skl_dev *skl) |
392 | { | 361 | { |
393 | struct skl_sst *ctx = skl->skl_sst; | ||
394 | struct hdac_bus *bus = skl_to_bus(skl); | 362 | struct hdac_bus *bus = skl_to_bus(skl); |
395 | int ret; | 363 | int ret; |
396 | 364 | ||
@@ -398,7 +366,7 @@ int skl_suspend_dsp(struct skl *skl) | |||
398 | if (!bus->ppcap) | 366 | if (!bus->ppcap) |
399 | return 0; | 367 | return 0; |
400 | 368 | ||
401 | ret = skl_dsp_sleep(ctx->dsp); | 369 | ret = skl_dsp_sleep(skl->dsp); |
402 | if (ret < 0) | 370 | if (ret < 0) |
403 | return ret; | 371 | return ret; |
404 | 372 | ||
@@ -409,9 +377,8 @@ int skl_suspend_dsp(struct skl *skl) | |||
409 | return 0; | 377 | return 0; |
410 | } | 378 | } |
411 | 379 | ||
412 | int skl_resume_dsp(struct skl *skl) | 380 | int skl_resume_dsp(struct skl_dev *skl) |
413 | { | 381 | { |
414 | struct skl_sst *ctx = skl->skl_sst; | ||
415 | struct hdac_bus *bus = skl_to_bus(skl); | 382 | struct hdac_bus *bus = skl_to_bus(skl); |
416 | int ret; | 383 | int ret; |
417 | 384 | ||
@@ -424,26 +391,24 @@ int skl_resume_dsp(struct skl *skl) | |||
424 | snd_hdac_ext_bus_ppcap_int_enable(bus, true); | 391 | snd_hdac_ext_bus_ppcap_int_enable(bus, true); |
425 | 392 | ||
426 | /* check if DSP 1st boot is done */ | 393 | /* check if DSP 1st boot is done */ |
427 | if (skl->skl_sst->is_first_boot) | 394 | if (skl->is_first_boot) |
428 | return 0; | 395 | return 0; |
429 | 396 | ||
430 | /* | 397 | /* |
431 | * Disable dynamic clock and power gating during firmware | 398 | * Disable dynamic clock and power gating during firmware |
432 | * and library download | 399 | * and library download |
433 | */ | 400 | */ |
434 | ctx->enable_miscbdcge(ctx->dev, false); | 401 | skl->enable_miscbdcge(skl->dev, false); |
435 | ctx->clock_power_gating(ctx->dev, false); | 402 | skl->clock_power_gating(skl->dev, false); |
436 | 403 | ||
437 | ret = skl_dsp_wake(ctx->dsp); | 404 | ret = skl_dsp_wake(skl->dsp); |
438 | ctx->enable_miscbdcge(ctx->dev, true); | 405 | skl->enable_miscbdcge(skl->dev, true); |
439 | ctx->clock_power_gating(ctx->dev, true); | 406 | skl->clock_power_gating(skl->dev, true); |
440 | if (ret < 0) | 407 | if (ret < 0) |
441 | return ret; | 408 | return ret; |
442 | 409 | ||
443 | skl_dsp_enable_notification(skl->skl_sst, false); | ||
444 | |||
445 | if (skl->cfg.astate_cfg != NULL) { | 410 | if (skl->cfg.astate_cfg != NULL) { |
446 | skl_dsp_set_astate_cfg(skl->skl_sst, skl->cfg.astate_cfg->count, | 411 | skl_dsp_set_astate_cfg(skl, skl->cfg.astate_cfg->count, |
447 | skl->cfg.astate_cfg); | 412 | skl->cfg.astate_cfg); |
448 | } | 413 | } |
449 | return ret; | 414 | return ret; |
@@ -476,7 +441,7 @@ enum skl_bitdepth skl_get_bit_depth(int params) | |||
476 | * which are read from widget information passed through topology binary | 441 | * which are read from widget information passed through topology binary |
477 | * This is send when we create a module with INIT_INSTANCE IPC msg | 442 | * This is send when we create a module with INIT_INSTANCE IPC msg |
478 | */ | 443 | */ |
479 | static void skl_set_base_module_format(struct skl_sst *ctx, | 444 | static void skl_set_base_module_format(struct skl_dev *skl, |
480 | struct skl_module_cfg *mconfig, | 445 | struct skl_module_cfg *mconfig, |
481 | struct skl_base_cfg *base_cfg) | 446 | struct skl_base_cfg *base_cfg) |
482 | { | 447 | { |
@@ -493,7 +458,7 @@ static void skl_set_base_module_format(struct skl_sst *ctx, | |||
493 | base_cfg->audio_fmt.ch_cfg = format->ch_cfg; | 458 | base_cfg->audio_fmt.ch_cfg = format->ch_cfg; |
494 | base_cfg->audio_fmt.sample_type = format->sample_type; | 459 | base_cfg->audio_fmt.sample_type = format->sample_type; |
495 | 460 | ||
496 | dev_dbg(ctx->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", | 461 | dev_dbg(skl->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", |
497 | format->bit_depth, format->valid_bit_depth, | 462 | format->bit_depth, format->valid_bit_depth, |
498 | format->ch_cfg); | 463 | format->ch_cfg); |
499 | 464 | ||
@@ -501,7 +466,7 @@ static void skl_set_base_module_format(struct skl_sst *ctx, | |||
501 | 466 | ||
502 | base_cfg->audio_fmt.interleaving = format->interleaving_style; | 467 | base_cfg->audio_fmt.interleaving = format->interleaving_style; |
503 | 468 | ||
504 | base_cfg->cps = res->cps; | 469 | base_cfg->cpc = res->cpc; |
505 | base_cfg->ibs = res->ibs; | 470 | base_cfg->ibs = res->ibs; |
506 | base_cfg->obs = res->obs; | 471 | base_cfg->obs = res->obs; |
507 | base_cfg->is_pages = res->is_pages; | 472 | base_cfg->is_pages = res->is_pages; |
@@ -530,7 +495,7 @@ static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, | |||
530 | * Calculate the gatewat settings required for copier module, type of | 495 | * Calculate the gatewat settings required for copier module, type of |
531 | * gateway and index of gateway to use | 496 | * gateway and index of gateway to use |
532 | */ | 497 | */ |
533 | static u32 skl_get_node_id(struct skl_sst *ctx, | 498 | static u32 skl_get_node_id(struct skl_dev *skl, |
534 | struct skl_module_cfg *mconfig) | 499 | struct skl_module_cfg *mconfig) |
535 | { | 500 | { |
536 | union skl_connector_node_id node_id = {0}; | 501 | union skl_connector_node_id node_id = {0}; |
@@ -587,16 +552,15 @@ static u32 skl_get_node_id(struct skl_sst *ctx, | |||
587 | return node_id.val; | 552 | return node_id.val; |
588 | } | 553 | } |
589 | 554 | ||
590 | static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | 555 | static void skl_setup_cpr_gateway_cfg(struct skl_dev *skl, |
591 | struct skl_module_cfg *mconfig, | 556 | struct skl_module_cfg *mconfig, |
592 | struct skl_cpr_cfg *cpr_mconfig) | 557 | struct skl_cpr_cfg *cpr_mconfig) |
593 | { | 558 | { |
594 | u32 dma_io_buf; | 559 | u32 dma_io_buf; |
595 | struct skl_module_res *res; | 560 | struct skl_module_res *res; |
596 | int res_idx = mconfig->res_idx; | 561 | int res_idx = mconfig->res_idx; |
597 | struct skl *skl = get_skl_ctx(ctx->dev); | ||
598 | 562 | ||
599 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); | 563 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(skl, mconfig); |
600 | 564 | ||
601 | if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { | 565 | if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { |
602 | cpr_mconfig->cpr_feature_mask = 0; | 566 | cpr_mconfig->cpr_feature_mask = 0; |
@@ -627,7 +591,7 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | |||
627 | break; | 591 | break; |
628 | 592 | ||
629 | default: | 593 | default: |
630 | dev_warn(ctx->dev, "wrong connection type: %d\n", | 594 | dev_warn(skl->dev, "wrong connection type: %d\n", |
631 | mconfig->hw_conn_type); | 595 | mconfig->hw_conn_type); |
632 | return; | 596 | return; |
633 | } | 597 | } |
@@ -653,7 +617,7 @@ skip_buf_size_calc: | |||
653 | #define DMA_CONTROL_ID 5 | 617 | #define DMA_CONTROL_ID 5 |
654 | #define DMA_I2S_BLOB_SIZE 21 | 618 | #define DMA_I2S_BLOB_SIZE 21 |
655 | 619 | ||
656 | int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, | 620 | int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, |
657 | u32 caps_size, u32 node_id) | 621 | u32 caps_size, u32 node_id) |
658 | { | 622 | { |
659 | struct skl_dma_control *dma_ctrl; | 623 | struct skl_dma_control *dma_ctrl; |
@@ -686,14 +650,14 @@ int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, | |||
686 | 650 | ||
687 | memcpy(dma_ctrl->config_data, caps, caps_size); | 651 | memcpy(dma_ctrl->config_data, caps, caps_size); |
688 | 652 | ||
689 | err = skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)dma_ctrl); | 653 | err = skl_ipc_set_large_config(&skl->ipc, &msg, (u32 *)dma_ctrl); |
690 | 654 | ||
691 | kfree(dma_ctrl); | 655 | kfree(dma_ctrl); |
692 | return err; | 656 | return err; |
693 | } | 657 | } |
694 | EXPORT_SYMBOL_GPL(skl_dsp_set_dma_control); | 658 | EXPORT_SYMBOL_GPL(skl_dsp_set_dma_control); |
695 | 659 | ||
696 | static void skl_setup_out_format(struct skl_sst *ctx, | 660 | static void skl_setup_out_format(struct skl_dev *skl, |
697 | struct skl_module_cfg *mconfig, | 661 | struct skl_module_cfg *mconfig, |
698 | struct skl_audio_data_format *out_fmt) | 662 | struct skl_audio_data_format *out_fmt) |
699 | { | 663 | { |
@@ -711,7 +675,7 @@ static void skl_setup_out_format(struct skl_sst *ctx, | |||
711 | out_fmt->interleaving = format->interleaving_style; | 675 | out_fmt->interleaving = format->interleaving_style; |
712 | out_fmt->sample_type = format->sample_type; | 676 | out_fmt->sample_type = format->sample_type; |
713 | 677 | ||
714 | dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", | 678 | dev_dbg(skl->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", |
715 | out_fmt->number_of_channels, format->s_freq, format->bit_depth); | 679 | out_fmt->number_of_channels, format->s_freq, format->bit_depth); |
716 | } | 680 | } |
717 | 681 | ||
@@ -720,7 +684,7 @@ static void skl_setup_out_format(struct skl_sst *ctx, | |||
720 | * configuration and the target frequency as extra parameter passed as src | 684 | * configuration and the target frequency as extra parameter passed as src |
721 | * config | 685 | * config |
722 | */ | 686 | */ |
723 | static void skl_set_src_format(struct skl_sst *ctx, | 687 | static void skl_set_src_format(struct skl_dev *skl, |
724 | struct skl_module_cfg *mconfig, | 688 | struct skl_module_cfg *mconfig, |
725 | struct skl_src_module_cfg *src_mconfig) | 689 | struct skl_src_module_cfg *src_mconfig) |
726 | { | 690 | { |
@@ -728,7 +692,7 @@ static void skl_set_src_format(struct skl_sst *ctx, | |||
728 | struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; | 692 | struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; |
729 | struct skl_module_fmt *fmt = &iface->outputs[0].fmt; | 693 | struct skl_module_fmt *fmt = &iface->outputs[0].fmt; |
730 | 694 | ||
731 | skl_set_base_module_format(ctx, mconfig, | 695 | skl_set_base_module_format(skl, mconfig, |
732 | (struct skl_base_cfg *)src_mconfig); | 696 | (struct skl_base_cfg *)src_mconfig); |
733 | 697 | ||
734 | src_mconfig->src_cfg = fmt->s_freq; | 698 | src_mconfig->src_cfg = fmt->s_freq; |
@@ -739,7 +703,7 @@ static void skl_set_src_format(struct skl_sst *ctx, | |||
739 | * module configuration and channel configuration | 703 | * module configuration and channel configuration |
740 | * It also take coefficients and now we have defaults applied here | 704 | * It also take coefficients and now we have defaults applied here |
741 | */ | 705 | */ |
742 | static void skl_set_updown_mixer_format(struct skl_sst *ctx, | 706 | static void skl_set_updown_mixer_format(struct skl_dev *skl, |
743 | struct skl_module_cfg *mconfig, | 707 | struct skl_module_cfg *mconfig, |
744 | struct skl_up_down_mixer_cfg *mixer_mconfig) | 708 | struct skl_up_down_mixer_cfg *mixer_mconfig) |
745 | { | 709 | { |
@@ -747,7 +711,7 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx, | |||
747 | struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; | 711 | struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; |
748 | struct skl_module_fmt *fmt = &iface->outputs[0].fmt; | 712 | struct skl_module_fmt *fmt = &iface->outputs[0].fmt; |
749 | 713 | ||
750 | skl_set_base_module_format(ctx, mconfig, | 714 | skl_set_base_module_format(skl, mconfig, |
751 | (struct skl_base_cfg *)mixer_mconfig); | 715 | (struct skl_base_cfg *)mixer_mconfig); |
752 | mixer_mconfig->out_ch_cfg = fmt->ch_cfg; | 716 | mixer_mconfig->out_ch_cfg = fmt->ch_cfg; |
753 | mixer_mconfig->ch_map = fmt->ch_map; | 717 | mixer_mconfig->ch_map = fmt->ch_map; |
@@ -760,17 +724,17 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx, | |||
760 | * format, gateway settings | 724 | * format, gateway settings |
761 | * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg | 725 | * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg |
762 | */ | 726 | */ |
763 | static void skl_set_copier_format(struct skl_sst *ctx, | 727 | static void skl_set_copier_format(struct skl_dev *skl, |
764 | struct skl_module_cfg *mconfig, | 728 | struct skl_module_cfg *mconfig, |
765 | struct skl_cpr_cfg *cpr_mconfig) | 729 | struct skl_cpr_cfg *cpr_mconfig) |
766 | { | 730 | { |
767 | struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; | 731 | struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; |
768 | struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; | 732 | struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; |
769 | 733 | ||
770 | skl_set_base_module_format(ctx, mconfig, base_cfg); | 734 | skl_set_base_module_format(skl, mconfig, base_cfg); |
771 | 735 | ||
772 | skl_setup_out_format(ctx, mconfig, out_fmt); | 736 | skl_setup_out_format(skl, mconfig, out_fmt); |
773 | skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig); | 737 | skl_setup_cpr_gateway_cfg(skl, mconfig, cpr_mconfig); |
774 | } | 738 | } |
775 | 739 | ||
776 | /* | 740 | /* |
@@ -778,13 +742,13 @@ static void skl_set_copier_format(struct skl_sst *ctx, | |||
778 | * configuration and params | 742 | * configuration and params |
779 | */ | 743 | */ |
780 | 744 | ||
781 | static void skl_set_algo_format(struct skl_sst *ctx, | 745 | static void skl_set_algo_format(struct skl_dev *skl, |
782 | struct skl_module_cfg *mconfig, | 746 | struct skl_module_cfg *mconfig, |
783 | struct skl_algo_cfg *algo_mcfg) | 747 | struct skl_algo_cfg *algo_mcfg) |
784 | { | 748 | { |
785 | struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg; | 749 | struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg; |
786 | 750 | ||
787 | skl_set_base_module_format(ctx, mconfig, base_cfg); | 751 | skl_set_base_module_format(skl, mconfig, base_cfg); |
788 | 752 | ||
789 | if (mconfig->formats_config.caps_size == 0) | 753 | if (mconfig->formats_config.caps_size == 0) |
790 | return; | 754 | return; |
@@ -802,7 +766,7 @@ static void skl_set_algo_format(struct skl_sst *ctx, | |||
802 | * Mic select module take base module configuration and out-format | 766 | * Mic select module take base module configuration and out-format |
803 | * configuration | 767 | * configuration |
804 | */ | 768 | */ |
805 | static void skl_set_base_outfmt_format(struct skl_sst *ctx, | 769 | static void skl_set_base_outfmt_format(struct skl_dev *skl, |
806 | struct skl_module_cfg *mconfig, | 770 | struct skl_module_cfg *mconfig, |
807 | struct skl_base_outfmt_cfg *base_outfmt_mcfg) | 771 | struct skl_base_outfmt_cfg *base_outfmt_mcfg) |
808 | { | 772 | { |
@@ -810,11 +774,11 @@ static void skl_set_base_outfmt_format(struct skl_sst *ctx, | |||
810 | struct skl_base_cfg *base_cfg = | 774 | struct skl_base_cfg *base_cfg = |
811 | (struct skl_base_cfg *)base_outfmt_mcfg; | 775 | (struct skl_base_cfg *)base_outfmt_mcfg; |
812 | 776 | ||
813 | skl_set_base_module_format(ctx, mconfig, base_cfg); | 777 | skl_set_base_module_format(skl, mconfig, base_cfg); |
814 | skl_setup_out_format(ctx, mconfig, out_fmt); | 778 | skl_setup_out_format(skl, mconfig, out_fmt); |
815 | } | 779 | } |
816 | 780 | ||
817 | static u16 skl_get_module_param_size(struct skl_sst *ctx, | 781 | static u16 skl_get_module_param_size(struct skl_dev *skl, |
818 | struct skl_module_cfg *mconfig) | 782 | struct skl_module_cfg *mconfig) |
819 | { | 783 | { |
820 | u16 param_size; | 784 | u16 param_size; |
@@ -859,14 +823,14 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, | |||
859 | * base module format configuration | 823 | * base module format configuration |
860 | */ | 824 | */ |
861 | 825 | ||
862 | static int skl_set_module_format(struct skl_sst *ctx, | 826 | static int skl_set_module_format(struct skl_dev *skl, |
863 | struct skl_module_cfg *module_config, | 827 | struct skl_module_cfg *module_config, |
864 | u16 *module_config_size, | 828 | u16 *module_config_size, |
865 | void **param_data) | 829 | void **param_data) |
866 | { | 830 | { |
867 | u16 param_size; | 831 | u16 param_size; |
868 | 832 | ||
869 | param_size = skl_get_module_param_size(ctx, module_config); | 833 | param_size = skl_get_module_param_size(skl, module_config); |
870 | 834 | ||
871 | *param_data = kzalloc(param_size, GFP_KERNEL); | 835 | *param_data = kzalloc(param_size, GFP_KERNEL); |
872 | if (NULL == *param_data) | 836 | if (NULL == *param_data) |
@@ -876,35 +840,36 @@ static int skl_set_module_format(struct skl_sst *ctx, | |||
876 | 840 | ||
877 | switch (module_config->m_type) { | 841 | switch (module_config->m_type) { |
878 | case SKL_MODULE_TYPE_COPIER: | 842 | case SKL_MODULE_TYPE_COPIER: |
879 | skl_set_copier_format(ctx, module_config, *param_data); | 843 | skl_set_copier_format(skl, module_config, *param_data); |
880 | break; | 844 | break; |
881 | 845 | ||
882 | case SKL_MODULE_TYPE_SRCINT: | 846 | case SKL_MODULE_TYPE_SRCINT: |
883 | skl_set_src_format(ctx, module_config, *param_data); | 847 | skl_set_src_format(skl, module_config, *param_data); |
884 | break; | 848 | break; |
885 | 849 | ||
886 | case SKL_MODULE_TYPE_UPDWMIX: | 850 | case SKL_MODULE_TYPE_UPDWMIX: |
887 | skl_set_updown_mixer_format(ctx, module_config, *param_data); | 851 | skl_set_updown_mixer_format(skl, module_config, *param_data); |
888 | break; | 852 | break; |
889 | 853 | ||
890 | case SKL_MODULE_TYPE_ALGO: | 854 | case SKL_MODULE_TYPE_ALGO: |
891 | skl_set_algo_format(ctx, module_config, *param_data); | 855 | skl_set_algo_format(skl, module_config, *param_data); |
892 | break; | 856 | break; |
893 | 857 | ||
894 | case SKL_MODULE_TYPE_BASE_OUTFMT: | 858 | case SKL_MODULE_TYPE_BASE_OUTFMT: |
895 | case SKL_MODULE_TYPE_MIC_SELECT: | 859 | case SKL_MODULE_TYPE_MIC_SELECT: |
896 | case SKL_MODULE_TYPE_KPB: | 860 | case SKL_MODULE_TYPE_KPB: |
897 | skl_set_base_outfmt_format(ctx, module_config, *param_data); | 861 | skl_set_base_outfmt_format(skl, module_config, *param_data); |
898 | break; | 862 | break; |
899 | 863 | ||
900 | default: | 864 | default: |
901 | skl_set_base_module_format(ctx, module_config, *param_data); | 865 | skl_set_base_module_format(skl, module_config, *param_data); |
902 | break; | 866 | break; |
903 | 867 | ||
904 | } | 868 | } |
905 | 869 | ||
906 | dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n", | 870 | dev_dbg(skl->dev, "Module type=%d id=%d config size: %d bytes\n", |
907 | module_config->id.module_id, param_size); | 871 | module_config->m_type, module_config->id.module_id, |
872 | param_size); | ||
908 | print_hex_dump_debug("Module params:", DUMP_PREFIX_OFFSET, 8, 4, | 873 | print_hex_dump_debug("Module params:", DUMP_PREFIX_OFFSET, 8, 4, |
909 | *param_data, param_size, false); | 874 | *param_data, param_size, false); |
910 | return 0; | 875 | return 0; |
@@ -1004,7 +969,7 @@ static void skl_clear_module_state(struct skl_module_pin *mpin, int max, | |||
1004 | * We first calculate the module format, based on module type and then | 969 | * We first calculate the module format, based on module type and then |
1005 | * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper | 970 | * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper |
1006 | */ | 971 | */ |
1007 | int skl_init_module(struct skl_sst *ctx, | 972 | int skl_init_module(struct skl_dev *skl, |
1008 | struct skl_module_cfg *mconfig) | 973 | struct skl_module_cfg *mconfig) |
1009 | { | 974 | { |
1010 | u16 module_config_size = 0; | 975 | u16 module_config_size = 0; |
@@ -1012,19 +977,19 @@ int skl_init_module(struct skl_sst *ctx, | |||
1012 | int ret; | 977 | int ret; |
1013 | struct skl_ipc_init_instance_msg msg; | 978 | struct skl_ipc_init_instance_msg msg; |
1014 | 979 | ||
1015 | dev_dbg(ctx->dev, "%s: module_id = %d instance=%d\n", __func__, | 980 | dev_dbg(skl->dev, "%s: module_id = %d instance=%d\n", __func__, |
1016 | mconfig->id.module_id, mconfig->id.pvt_id); | 981 | mconfig->id.module_id, mconfig->id.pvt_id); |
1017 | 982 | ||
1018 | if (mconfig->pipe->state != SKL_PIPE_CREATED) { | 983 | if (mconfig->pipe->state != SKL_PIPE_CREATED) { |
1019 | dev_err(ctx->dev, "Pipe not created state= %d pipe_id= %d\n", | 984 | dev_err(skl->dev, "Pipe not created state= %d pipe_id= %d\n", |
1020 | mconfig->pipe->state, mconfig->pipe->ppl_id); | 985 | mconfig->pipe->state, mconfig->pipe->ppl_id); |
1021 | return -EIO; | 986 | return -EIO; |
1022 | } | 987 | } |
1023 | 988 | ||
1024 | ret = skl_set_module_format(ctx, mconfig, | 989 | ret = skl_set_module_format(skl, mconfig, |
1025 | &module_config_size, ¶m_data); | 990 | &module_config_size, ¶m_data); |
1026 | if (ret < 0) { | 991 | if (ret < 0) { |
1027 | dev_err(ctx->dev, "Failed to set module format ret=%d\n", ret); | 992 | dev_err(skl->dev, "Failed to set module format ret=%d\n", ret); |
1028 | return ret; | 993 | return ret; |
1029 | } | 994 | } |
1030 | 995 | ||
@@ -1035,9 +1000,9 @@ int skl_init_module(struct skl_sst *ctx, | |||
1035 | msg.core_id = mconfig->core_id; | 1000 | msg.core_id = mconfig->core_id; |
1036 | msg.domain = mconfig->domain; | 1001 | msg.domain = mconfig->domain; |
1037 | 1002 | ||
1038 | ret = skl_ipc_init_instance(&ctx->ipc, &msg, param_data); | 1003 | ret = skl_ipc_init_instance(&skl->ipc, &msg, param_data); |
1039 | if (ret < 0) { | 1004 | if (ret < 0) { |
1040 | dev_err(ctx->dev, "Failed to init instance ret=%d\n", ret); | 1005 | dev_err(skl->dev, "Failed to init instance ret=%d\n", ret); |
1041 | kfree(param_data); | 1006 | kfree(param_data); |
1042 | return ret; | 1007 | return ret; |
1043 | } | 1008 | } |
@@ -1046,15 +1011,15 @@ int skl_init_module(struct skl_sst *ctx, | |||
1046 | return ret; | 1011 | return ret; |
1047 | } | 1012 | } |
1048 | 1013 | ||
1049 | static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg | 1014 | static void skl_dump_bind_info(struct skl_dev *skl, struct skl_module_cfg |
1050 | *src_module, struct skl_module_cfg *dst_module) | 1015 | *src_module, struct skl_module_cfg *dst_module) |
1051 | { | 1016 | { |
1052 | dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", | 1017 | dev_dbg(skl->dev, "%s: src module_id = %d src_instance=%d\n", |
1053 | __func__, src_module->id.module_id, src_module->id.pvt_id); | 1018 | __func__, src_module->id.module_id, src_module->id.pvt_id); |
1054 | dev_dbg(ctx->dev, "%s: dst_module=%d dst_instance=%d\n", __func__, | 1019 | dev_dbg(skl->dev, "%s: dst_module=%d dst_instance=%d\n", __func__, |
1055 | dst_module->id.module_id, dst_module->id.pvt_id); | 1020 | dst_module->id.module_id, dst_module->id.pvt_id); |
1056 | 1021 | ||
1057 | dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", | 1022 | dev_dbg(skl->dev, "src_module state = %d dst module state = %d\n", |
1058 | src_module->m_state, dst_module->m_state); | 1023 | src_module->m_state, dst_module->m_state); |
1059 | } | 1024 | } |
1060 | 1025 | ||
@@ -1063,7 +1028,7 @@ static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg | |||
1063 | * it is already bind. | 1028 | * it is already bind. |
1064 | * Find the pin allocated and unbind then using bind_unbind IPC | 1029 | * Find the pin allocated and unbind then using bind_unbind IPC |
1065 | */ | 1030 | */ |
1066 | int skl_unbind_modules(struct skl_sst *ctx, | 1031 | int skl_unbind_modules(struct skl_dev *skl, |
1067 | struct skl_module_cfg *src_mcfg, | 1032 | struct skl_module_cfg *src_mcfg, |
1068 | struct skl_module_cfg *dst_mcfg) | 1033 | struct skl_module_cfg *dst_mcfg) |
1069 | { | 1034 | { |
@@ -1075,7 +1040,7 @@ int skl_unbind_modules(struct skl_sst *ctx, | |||
1075 | int out_max = src_mcfg->module->max_output_pins; | 1040 | int out_max = src_mcfg->module->max_output_pins; |
1076 | int src_index, dst_index, src_pin_state, dst_pin_state; | 1041 | int src_index, dst_index, src_pin_state, dst_pin_state; |
1077 | 1042 | ||
1078 | skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); | 1043 | skl_dump_bind_info(skl, src_mcfg, dst_mcfg); |
1079 | 1044 | ||
1080 | /* get src queue index */ | 1045 | /* get src queue index */ |
1081 | src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); | 1046 | src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); |
@@ -1104,7 +1069,7 @@ int skl_unbind_modules(struct skl_sst *ctx, | |||
1104 | msg.dst_instance_id = dst_mcfg->id.pvt_id; | 1069 | msg.dst_instance_id = dst_mcfg->id.pvt_id; |
1105 | msg.bind = false; | 1070 | msg.bind = false; |
1106 | 1071 | ||
1107 | ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); | 1072 | ret = skl_ipc_bind_unbind(&skl->ipc, &msg); |
1108 | if (!ret) { | 1073 | if (!ret) { |
1109 | /* free queue only if unbind is success */ | 1074 | /* free queue only if unbind is success */ |
1110 | skl_free_queue(src_mcfg->m_out_pin, src_index); | 1075 | skl_free_queue(src_mcfg->m_out_pin, src_index); |
@@ -1142,7 +1107,7 @@ static void fill_pin_params(struct skl_audio_data_format *pin_fmt, | |||
1142 | * This function finds the pins and then sends bund_unbind IPC message to | 1107 | * This function finds the pins and then sends bund_unbind IPC message to |
1143 | * DSP using IPC helper | 1108 | * DSP using IPC helper |
1144 | */ | 1109 | */ |
1145 | int skl_bind_modules(struct skl_sst *ctx, | 1110 | int skl_bind_modules(struct skl_dev *skl, |
1146 | struct skl_module_cfg *src_mcfg, | 1111 | struct skl_module_cfg *src_mcfg, |
1147 | struct skl_module_cfg *dst_mcfg) | 1112 | struct skl_module_cfg *dst_mcfg) |
1148 | { | 1113 | { |
@@ -1156,7 +1121,7 @@ int skl_bind_modules(struct skl_sst *ctx, | |||
1156 | struct skl_module *module; | 1121 | struct skl_module *module; |
1157 | struct skl_module_iface *fmt; | 1122 | struct skl_module_iface *fmt; |
1158 | 1123 | ||
1159 | skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); | 1124 | skl_dump_bind_info(skl, src_mcfg, dst_mcfg); |
1160 | 1125 | ||
1161 | if (src_mcfg->m_state < SKL_MODULE_INIT_DONE || | 1126 | if (src_mcfg->m_state < SKL_MODULE_INIT_DONE || |
1162 | dst_mcfg->m_state < SKL_MODULE_INIT_DONE) | 1127 | dst_mcfg->m_state < SKL_MODULE_INIT_DONE) |
@@ -1188,7 +1153,7 @@ int skl_bind_modules(struct skl_sst *ctx, | |||
1188 | 1153 | ||
1189 | format = &fmt->outputs[src_index].fmt; | 1154 | format = &fmt->outputs[src_index].fmt; |
1190 | fill_pin_params(&(pin_fmt.dst_fmt), format); | 1155 | fill_pin_params(&(pin_fmt.dst_fmt), format); |
1191 | ret = skl_set_module_params(ctx, (void *)&pin_fmt, | 1156 | ret = skl_set_module_params(skl, (void *)&pin_fmt, |
1192 | sizeof(struct skl_cpr_pin_fmt), | 1157 | sizeof(struct skl_cpr_pin_fmt), |
1193 | CPR_SINK_FMT_PARAM_ID, src_mcfg); | 1158 | CPR_SINK_FMT_PARAM_ID, src_mcfg); |
1194 | 1159 | ||
@@ -1198,7 +1163,7 @@ int skl_bind_modules(struct skl_sst *ctx, | |||
1198 | 1163 | ||
1199 | msg.dst_queue = dst_index; | 1164 | msg.dst_queue = dst_index; |
1200 | 1165 | ||
1201 | dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", | 1166 | dev_dbg(skl->dev, "src queue = %d dst queue =%d\n", |
1202 | msg.src_queue, msg.dst_queue); | 1167 | msg.src_queue, msg.dst_queue); |
1203 | 1168 | ||
1204 | msg.module_id = src_mcfg->id.module_id; | 1169 | msg.module_id = src_mcfg->id.module_id; |
@@ -1207,7 +1172,7 @@ int skl_bind_modules(struct skl_sst *ctx, | |||
1207 | msg.dst_instance_id = dst_mcfg->id.pvt_id; | 1172 | msg.dst_instance_id = dst_mcfg->id.pvt_id; |
1208 | msg.bind = true; | 1173 | msg.bind = true; |
1209 | 1174 | ||
1210 | ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); | 1175 | ret = skl_ipc_bind_unbind(&skl->ipc, &msg); |
1211 | 1176 | ||
1212 | if (!ret) { | 1177 | if (!ret) { |
1213 | src_mcfg->m_state = SKL_MODULE_BIND_DONE; | 1178 | src_mcfg->m_state = SKL_MODULE_BIND_DONE; |
@@ -1223,12 +1188,12 @@ out: | |||
1223 | return ret; | 1188 | return ret; |
1224 | } | 1189 | } |
1225 | 1190 | ||
1226 | static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, | 1191 | static int skl_set_pipe_state(struct skl_dev *skl, struct skl_pipe *pipe, |
1227 | enum skl_ipc_pipeline_state state) | 1192 | enum skl_ipc_pipeline_state state) |
1228 | { | 1193 | { |
1229 | dev_dbg(ctx->dev, "%s: pipe_state = %d\n", __func__, state); | 1194 | dev_dbg(skl->dev, "%s: pipe_state = %d\n", __func__, state); |
1230 | 1195 | ||
1231 | return skl_ipc_set_pipeline_state(&ctx->ipc, pipe->ppl_id, state); | 1196 | return skl_ipc_set_pipeline_state(&skl->ipc, pipe->ppl_id, state); |
1232 | } | 1197 | } |
1233 | 1198 | ||
1234 | /* | 1199 | /* |
@@ -1237,17 +1202,17 @@ static int skl_set_pipe_state(struct skl_sst *ctx, struct skl_pipe *pipe, | |||
1237 | * This function creates pipeline, by sending create pipeline IPC messages | 1202 | * This function creates pipeline, by sending create pipeline IPC messages |
1238 | * to FW | 1203 | * to FW |
1239 | */ | 1204 | */ |
1240 | int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) | 1205 | int skl_create_pipeline(struct skl_dev *skl, struct skl_pipe *pipe) |
1241 | { | 1206 | { |
1242 | int ret; | 1207 | int ret; |
1243 | 1208 | ||
1244 | dev_dbg(ctx->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); | 1209 | dev_dbg(skl->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); |
1245 | 1210 | ||
1246 | ret = skl_ipc_create_pipeline(&ctx->ipc, pipe->memory_pages, | 1211 | ret = skl_ipc_create_pipeline(&skl->ipc, pipe->memory_pages, |
1247 | pipe->pipe_priority, pipe->ppl_id, | 1212 | pipe->pipe_priority, pipe->ppl_id, |
1248 | pipe->lp_mode); | 1213 | pipe->lp_mode); |
1249 | if (ret < 0) { | 1214 | if (ret < 0) { |
1250 | dev_err(ctx->dev, "Failed to create pipeline\n"); | 1215 | dev_err(skl->dev, "Failed to create pipeline\n"); |
1251 | return ret; | 1216 | return ret; |
1252 | } | 1217 | } |
1253 | 1218 | ||
@@ -1262,11 +1227,11 @@ int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe) | |||
1262 | * reset state. Finish the procedure by sending delete pipeline IPC. | 1227 | * reset state. Finish the procedure by sending delete pipeline IPC. |
1263 | * DSP will stop the DMA engines and release resources | 1228 | * DSP will stop the DMA engines and release resources |
1264 | */ | 1229 | */ |
1265 | int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | 1230 | int skl_delete_pipe(struct skl_dev *skl, struct skl_pipe *pipe) |
1266 | { | 1231 | { |
1267 | int ret; | 1232 | int ret; |
1268 | 1233 | ||
1269 | dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); | 1234 | dev_dbg(skl->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); |
1270 | 1235 | ||
1271 | /* If pipe was not created in FW, do not try to delete it */ | 1236 | /* If pipe was not created in FW, do not try to delete it */ |
1272 | if (pipe->state < SKL_PIPE_CREATED) | 1237 | if (pipe->state < SKL_PIPE_CREATED) |
@@ -1274,9 +1239,9 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | |||
1274 | 1239 | ||
1275 | /* If pipe is started, do stop the pipe in FW. */ | 1240 | /* If pipe is started, do stop the pipe in FW. */ |
1276 | if (pipe->state >= SKL_PIPE_STARTED) { | 1241 | if (pipe->state >= SKL_PIPE_STARTED) { |
1277 | ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); | 1242 | ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); |
1278 | if (ret < 0) { | 1243 | if (ret < 0) { |
1279 | dev_err(ctx->dev, "Failed to stop pipeline\n"); | 1244 | dev_err(skl->dev, "Failed to stop pipeline\n"); |
1280 | return ret; | 1245 | return ret; |
1281 | } | 1246 | } |
1282 | 1247 | ||
@@ -1284,17 +1249,17 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | |||
1284 | } | 1249 | } |
1285 | 1250 | ||
1286 | /* reset pipe state before deletion */ | 1251 | /* reset pipe state before deletion */ |
1287 | ret = skl_set_pipe_state(ctx, pipe, PPL_RESET); | 1252 | ret = skl_set_pipe_state(skl, pipe, PPL_RESET); |
1288 | if (ret < 0) { | 1253 | if (ret < 0) { |
1289 | dev_err(ctx->dev, "Failed to reset pipe ret=%d\n", ret); | 1254 | dev_err(skl->dev, "Failed to reset pipe ret=%d\n", ret); |
1290 | return ret; | 1255 | return ret; |
1291 | } | 1256 | } |
1292 | 1257 | ||
1293 | pipe->state = SKL_PIPE_RESET; | 1258 | pipe->state = SKL_PIPE_RESET; |
1294 | 1259 | ||
1295 | ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); | 1260 | ret = skl_ipc_delete_pipeline(&skl->ipc, pipe->ppl_id); |
1296 | if (ret < 0) { | 1261 | if (ret < 0) { |
1297 | dev_err(ctx->dev, "Failed to delete pipeline\n"); | 1262 | dev_err(skl->dev, "Failed to delete pipeline\n"); |
1298 | return ret; | 1263 | return ret; |
1299 | } | 1264 | } |
1300 | 1265 | ||
@@ -1308,28 +1273,28 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | |||
1308 | * For processing data the pipe need to be run by sending IPC set pipe state | 1273 | * For processing data the pipe need to be run by sending IPC set pipe state |
1309 | * to DSP | 1274 | * to DSP |
1310 | */ | 1275 | */ |
1311 | int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | 1276 | int skl_run_pipe(struct skl_dev *skl, struct skl_pipe *pipe) |
1312 | { | 1277 | { |
1313 | int ret; | 1278 | int ret; |
1314 | 1279 | ||
1315 | dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); | 1280 | dev_dbg(skl->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); |
1316 | 1281 | ||
1317 | /* If pipe was not created in FW, do not try to pause or delete */ | 1282 | /* If pipe was not created in FW, do not try to pause or delete */ |
1318 | if (pipe->state < SKL_PIPE_CREATED) | 1283 | if (pipe->state < SKL_PIPE_CREATED) |
1319 | return 0; | 1284 | return 0; |
1320 | 1285 | ||
1321 | /* Pipe has to be paused before it is started */ | 1286 | /* Pipe has to be paused before it is started */ |
1322 | ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); | 1287 | ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); |
1323 | if (ret < 0) { | 1288 | if (ret < 0) { |
1324 | dev_err(ctx->dev, "Failed to pause pipe\n"); | 1289 | dev_err(skl->dev, "Failed to pause pipe\n"); |
1325 | return ret; | 1290 | return ret; |
1326 | } | 1291 | } |
1327 | 1292 | ||
1328 | pipe->state = SKL_PIPE_PAUSED; | 1293 | pipe->state = SKL_PIPE_PAUSED; |
1329 | 1294 | ||
1330 | ret = skl_set_pipe_state(ctx, pipe, PPL_RUNNING); | 1295 | ret = skl_set_pipe_state(skl, pipe, PPL_RUNNING); |
1331 | if (ret < 0) { | 1296 | if (ret < 0) { |
1332 | dev_err(ctx->dev, "Failed to start pipe\n"); | 1297 | dev_err(skl->dev, "Failed to start pipe\n"); |
1333 | return ret; | 1298 | return ret; |
1334 | } | 1299 | } |
1335 | 1300 | ||
@@ -1342,19 +1307,19 @@ int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | |||
1342 | * Stop the pipeline by sending set pipe state IPC | 1307 | * Stop the pipeline by sending set pipe state IPC |
1343 | * DSP doesnt implement stop so we always send pause message | 1308 | * DSP doesnt implement stop so we always send pause message |
1344 | */ | 1309 | */ |
1345 | int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | 1310 | int skl_stop_pipe(struct skl_dev *skl, struct skl_pipe *pipe) |
1346 | { | 1311 | { |
1347 | int ret; | 1312 | int ret; |
1348 | 1313 | ||
1349 | dev_dbg(ctx->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); | 1314 | dev_dbg(skl->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); |
1350 | 1315 | ||
1351 | /* If pipe was not created in FW, do not try to pause or delete */ | 1316 | /* If pipe was not created in FW, do not try to pause or delete */ |
1352 | if (pipe->state < SKL_PIPE_PAUSED) | 1317 | if (pipe->state < SKL_PIPE_PAUSED) |
1353 | return 0; | 1318 | return 0; |
1354 | 1319 | ||
1355 | ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); | 1320 | ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); |
1356 | if (ret < 0) { | 1321 | if (ret < 0) { |
1357 | dev_dbg(ctx->dev, "Failed to stop pipe\n"); | 1322 | dev_dbg(skl->dev, "Failed to stop pipe\n"); |
1358 | return ret; | 1323 | return ret; |
1359 | } | 1324 | } |
1360 | 1325 | ||
@@ -1367,7 +1332,7 @@ int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | |||
1367 | * Reset the pipeline by sending set pipe state IPC this will reset the DMA | 1332 | * Reset the pipeline by sending set pipe state IPC this will reset the DMA |
1368 | * from the DSP side | 1333 | * from the DSP side |
1369 | */ | 1334 | */ |
1370 | int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | 1335 | int skl_reset_pipe(struct skl_dev *skl, struct skl_pipe *pipe) |
1371 | { | 1336 | { |
1372 | int ret; | 1337 | int ret; |
1373 | 1338 | ||
@@ -1375,9 +1340,9 @@ int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | |||
1375 | if (pipe->state < SKL_PIPE_PAUSED) | 1340 | if (pipe->state < SKL_PIPE_PAUSED) |
1376 | return 0; | 1341 | return 0; |
1377 | 1342 | ||
1378 | ret = skl_set_pipe_state(ctx, pipe, PPL_RESET); | 1343 | ret = skl_set_pipe_state(skl, pipe, PPL_RESET); |
1379 | if (ret < 0) { | 1344 | if (ret < 0) { |
1380 | dev_dbg(ctx->dev, "Failed to reset pipe ret=%d\n", ret); | 1345 | dev_dbg(skl->dev, "Failed to reset pipe ret=%d\n", ret); |
1381 | return ret; | 1346 | return ret; |
1382 | } | 1347 | } |
1383 | 1348 | ||
@@ -1387,7 +1352,7 @@ int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) | |||
1387 | } | 1352 | } |
1388 | 1353 | ||
1389 | /* Algo parameter set helper function */ | 1354 | /* Algo parameter set helper function */ |
1390 | int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, | 1355 | int skl_set_module_params(struct skl_dev *skl, u32 *params, int size, |
1391 | u32 param_id, struct skl_module_cfg *mcfg) | 1356 | u32 param_id, struct skl_module_cfg *mcfg) |
1392 | { | 1357 | { |
1393 | struct skl_ipc_large_config_msg msg; | 1358 | struct skl_ipc_large_config_msg msg; |
@@ -1397,18 +1362,19 @@ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, | |||
1397 | msg.param_data_size = size; | 1362 | msg.param_data_size = size; |
1398 | msg.large_param_id = param_id; | 1363 | msg.large_param_id = param_id; |
1399 | 1364 | ||
1400 | return skl_ipc_set_large_config(&ctx->ipc, &msg, params); | 1365 | return skl_ipc_set_large_config(&skl->ipc, &msg, params); |
1401 | } | 1366 | } |
1402 | 1367 | ||
1403 | int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, | 1368 | int skl_get_module_params(struct skl_dev *skl, u32 *params, int size, |
1404 | u32 param_id, struct skl_module_cfg *mcfg) | 1369 | u32 param_id, struct skl_module_cfg *mcfg) |
1405 | { | 1370 | { |
1406 | struct skl_ipc_large_config_msg msg; | 1371 | struct skl_ipc_large_config_msg msg; |
1372 | size_t bytes = size; | ||
1407 | 1373 | ||
1408 | msg.module_id = mcfg->id.module_id; | 1374 | msg.module_id = mcfg->id.module_id; |
1409 | msg.instance_id = mcfg->id.pvt_id; | 1375 | msg.instance_id = mcfg->id.pvt_id; |
1410 | msg.param_data_size = size; | 1376 | msg.param_data_size = size; |
1411 | msg.large_param_id = param_id; | 1377 | msg.large_param_id = param_id; |
1412 | 1378 | ||
1413 | return skl_ipc_get_large_config(&ctx->ipc, &msg, params); | 1379 | return skl_ipc_get_large_config(&skl->ipc, &msg, ¶ms, &bytes); |
1414 | } | 1380 | } |
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index e01815cec6fd..19f328d71f24 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c | |||
@@ -9,57 +9,10 @@ | |||
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
10 | */ | 10 | */ |
11 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
12 | #include <sound/intel-nhlt.h> | ||
12 | #include "skl.h" | 13 | #include "skl.h" |
13 | #include "skl-i2s.h" | 14 | #include "skl-i2s.h" |
14 | 15 | ||
15 | #define NHLT_ACPI_HEADER_SIG "NHLT" | ||
16 | |||
17 | /* Unique identification for getting NHLT blobs */ | ||
18 | static guid_t osc_guid = | ||
19 | GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, | ||
20 | 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); | ||
21 | |||
22 | |||
23 | struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) | ||
24 | { | ||
25 | acpi_handle handle; | ||
26 | union acpi_object *obj; | ||
27 | struct nhlt_resource_desc *nhlt_ptr = NULL; | ||
28 | struct nhlt_acpi_table *nhlt_table = NULL; | ||
29 | |||
30 | handle = ACPI_HANDLE(dev); | ||
31 | if (!handle) { | ||
32 | dev_err(dev, "Didn't find ACPI_HANDLE\n"); | ||
33 | return NULL; | ||
34 | } | ||
35 | |||
36 | obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); | ||
37 | if (obj && obj->type == ACPI_TYPE_BUFFER) { | ||
38 | nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; | ||
39 | if (nhlt_ptr->length) | ||
40 | nhlt_table = (struct nhlt_acpi_table *) | ||
41 | memremap(nhlt_ptr->min_addr, nhlt_ptr->length, | ||
42 | MEMREMAP_WB); | ||
43 | ACPI_FREE(obj); | ||
44 | if (nhlt_table && (strncmp(nhlt_table->header.signature, | ||
45 | NHLT_ACPI_HEADER_SIG, | ||
46 | strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { | ||
47 | memunmap(nhlt_table); | ||
48 | dev_err(dev, "NHLT ACPI header signature incorrect\n"); | ||
49 | return NULL; | ||
50 | } | ||
51 | return nhlt_table; | ||
52 | } | ||
53 | |||
54 | dev_err(dev, "device specific method to extract NHLT blob failed\n"); | ||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | void skl_nhlt_free(struct nhlt_acpi_table *nhlt) | ||
59 | { | ||
60 | memunmap((void *) nhlt); | ||
61 | } | ||
62 | |||
63 | static struct nhlt_specific_cfg *skl_get_specific_cfg( | 16 | static struct nhlt_specific_cfg *skl_get_specific_cfg( |
64 | struct device *dev, struct nhlt_fmt *fmt, | 17 | struct device *dev, struct nhlt_fmt *fmt, |
65 | u8 no_ch, u32 rate, u16 bps, u8 linktype) | 18 | u8 no_ch, u32 rate, u16 bps, u8 linktype) |
@@ -126,7 +79,7 @@ static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, | |||
126 | } | 79 | } |
127 | 80 | ||
128 | struct nhlt_specific_cfg | 81 | struct nhlt_specific_cfg |
129 | *skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type, | 82 | *skl_get_ep_blob(struct skl_dev *skl, u32 instance, u8 link_type, |
130 | u8 s_fmt, u8 num_ch, u32 s_rate, | 83 | u8 s_fmt, u8 num_ch, u32 s_rate, |
131 | u8 dirn, u8 dev_type) | 84 | u8 dirn, u8 dev_type) |
132 | { | 85 | { |
@@ -162,48 +115,6 @@ struct nhlt_specific_cfg | |||
162 | return NULL; | 115 | return NULL; |
163 | } | 116 | } |
164 | 117 | ||
165 | int skl_get_dmic_geo(struct skl *skl) | ||
166 | { | ||
167 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; | ||
168 | struct nhlt_endpoint *epnt; | ||
169 | struct nhlt_dmic_array_config *cfg; | ||
170 | struct device *dev = &skl->pci->dev; | ||
171 | unsigned int dmic_geo = 0; | ||
172 | u8 j; | ||
173 | |||
174 | if (!nhlt) | ||
175 | return 0; | ||
176 | |||
177 | epnt = (struct nhlt_endpoint *)nhlt->desc; | ||
178 | |||
179 | for (j = 0; j < nhlt->endpoint_count; j++) { | ||
180 | if (epnt->linktype == NHLT_LINK_DMIC) { | ||
181 | cfg = (struct nhlt_dmic_array_config *) | ||
182 | (epnt->config.caps); | ||
183 | switch (cfg->array_type) { | ||
184 | case NHLT_MIC_ARRAY_2CH_SMALL: | ||
185 | case NHLT_MIC_ARRAY_2CH_BIG: | ||
186 | dmic_geo |= MIC_ARRAY_2CH; | ||
187 | break; | ||
188 | |||
189 | case NHLT_MIC_ARRAY_4CH_1ST_GEOM: | ||
190 | case NHLT_MIC_ARRAY_4CH_L_SHAPED: | ||
191 | case NHLT_MIC_ARRAY_4CH_2ND_GEOM: | ||
192 | dmic_geo |= MIC_ARRAY_4CH; | ||
193 | break; | ||
194 | |||
195 | default: | ||
196 | dev_warn(dev, "undefined DMIC array_type 0x%0x\n", | ||
197 | cfg->array_type); | ||
198 | |||
199 | } | ||
200 | } | ||
201 | epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); | ||
202 | } | ||
203 | |||
204 | return dmic_geo; | ||
205 | } | ||
206 | |||
207 | static void skl_nhlt_trim_space(char *trim) | 118 | static void skl_nhlt_trim_space(char *trim) |
208 | { | 119 | { |
209 | char *s = trim; | 120 | char *s = trim; |
@@ -219,7 +130,7 @@ static void skl_nhlt_trim_space(char *trim) | |||
219 | s[cnt] = '\0'; | 130 | s[cnt] = '\0'; |
220 | } | 131 | } |
221 | 132 | ||
222 | int skl_nhlt_update_topology_bin(struct skl *skl) | 133 | int skl_nhlt_update_topology_bin(struct skl_dev *skl) |
223 | { | 134 | { |
224 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; | 135 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; |
225 | struct hdac_bus *bus = skl_to_bus(skl); | 136 | struct hdac_bus *bus = skl_to_bus(skl); |
@@ -243,7 +154,7 @@ static ssize_t skl_nhlt_platform_id_show(struct device *dev, | |||
243 | { | 154 | { |
244 | struct pci_dev *pci = to_pci_dev(dev); | 155 | struct pci_dev *pci = to_pci_dev(dev); |
245 | struct hdac_bus *bus = pci_get_drvdata(pci); | 156 | struct hdac_bus *bus = pci_get_drvdata(pci); |
246 | struct skl *skl = bus_to_skl(bus); | 157 | struct skl_dev *skl = bus_to_skl(bus); |
247 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; | 158 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; |
248 | char platform_id[32]; | 159 | char platform_id[32]; |
249 | 160 | ||
@@ -257,7 +168,7 @@ static ssize_t skl_nhlt_platform_id_show(struct device *dev, | |||
257 | 168 | ||
258 | static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL); | 169 | static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL); |
259 | 170 | ||
260 | int skl_nhlt_create_sysfs(struct skl *skl) | 171 | int skl_nhlt_create_sysfs(struct skl_dev *skl) |
261 | { | 172 | { |
262 | struct device *dev = &skl->pci->dev; | 173 | struct device *dev = &skl->pci->dev; |
263 | 174 | ||
@@ -267,7 +178,7 @@ int skl_nhlt_create_sysfs(struct skl *skl) | |||
267 | return 0; | 178 | return 0; |
268 | } | 179 | } |
269 | 180 | ||
270 | void skl_nhlt_remove_sysfs(struct skl *skl) | 181 | void skl_nhlt_remove_sysfs(struct skl_dev *skl) |
271 | { | 182 | { |
272 | struct device *dev = &skl->pci->dev; | 183 | struct device *dev = &skl->pci->dev; |
273 | 184 | ||
@@ -279,7 +190,7 @@ void skl_nhlt_remove_sysfs(struct skl *skl) | |||
279 | * stores all possible rates supported in a rate table for the corresponding | 190 | * stores all possible rates supported in a rate table for the corresponding |
280 | * sclk/sclkfs. | 191 | * sclk/sclkfs. |
281 | */ | 192 | */ |
282 | static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks, | 193 | static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, |
283 | struct nhlt_fmt *fmt, u8 id) | 194 | struct nhlt_fmt *fmt, u8 id) |
284 | { | 195 | { |
285 | struct skl_i2s_config_blob_ext *i2s_config_ext; | 196 | struct skl_i2s_config_blob_ext *i2s_config_ext; |
@@ -377,7 +288,7 @@ static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks, | |||
377 | } | 288 | } |
378 | } | 289 | } |
379 | 290 | ||
380 | static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk, | 291 | static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk, |
381 | struct nhlt_fmt *fmt, u8 id) | 292 | struct nhlt_fmt *fmt, u8 id) |
382 | { | 293 | { |
383 | struct skl_i2s_config_blob_ext *i2s_config_ext; | 294 | struct skl_i2s_config_blob_ext *i2s_config_ext; |
@@ -421,7 +332,7 @@ static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk, | |||
421 | mclk[id].parent_name = parent->name; | 332 | mclk[id].parent_name = parent->name; |
422 | } | 333 | } |
423 | 334 | ||
424 | void skl_get_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks) | 335 | void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks) |
425 | { | 336 | { |
426 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; | 337 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; |
427 | struct nhlt_endpoint *epnt; | 338 | struct nhlt_endpoint *epnt; |
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 760bbcf9a469..7f287424af9b 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c | |||
@@ -116,7 +116,7 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, | |||
116 | { | 116 | { |
117 | struct hdac_bus *bus = dev_get_drvdata(dai->dev); | 117 | struct hdac_bus *bus = dev_get_drvdata(dai->dev); |
118 | struct snd_soc_dapm_widget *w; | 118 | struct snd_soc_dapm_widget *w; |
119 | struct skl *skl = bus_to_skl(bus); | 119 | struct skl_dev *skl = bus_to_skl(bus); |
120 | 120 | ||
121 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 121 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
122 | w = dai->playback_widget; | 122 | w = dai->playback_widget; |
@@ -132,7 +132,7 @@ static void skl_set_suspend_active(struct snd_pcm_substream *substream, | |||
132 | int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) | 132 | int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) |
133 | { | 133 | { |
134 | struct hdac_bus *bus = dev_get_drvdata(dev); | 134 | struct hdac_bus *bus = dev_get_drvdata(dev); |
135 | struct skl *skl = bus_to_skl(bus); | 135 | struct skl_dev *skl = bus_to_skl(bus); |
136 | unsigned int format_val; | 136 | unsigned int format_val; |
137 | struct hdac_stream *hstream; | 137 | struct hdac_stream *hstream; |
138 | struct hdac_ext_stream *stream; | 138 | struct hdac_ext_stream *stream; |
@@ -224,7 +224,7 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, | |||
224 | struct hdac_ext_stream *stream; | 224 | struct hdac_ext_stream *stream; |
225 | struct snd_pcm_runtime *runtime = substream->runtime; | 225 | struct snd_pcm_runtime *runtime = substream->runtime; |
226 | struct skl_dma_params *dma_params; | 226 | struct skl_dma_params *dma_params; |
227 | struct skl *skl = get_skl_ctx(dai->dev); | 227 | struct skl_dev *skl = get_skl_ctx(dai->dev); |
228 | struct skl_module_cfg *mconfig; | 228 | struct skl_module_cfg *mconfig; |
229 | 229 | ||
230 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | 230 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); |
@@ -271,7 +271,7 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, | |||
271 | static int skl_pcm_prepare(struct snd_pcm_substream *substream, | 271 | static int skl_pcm_prepare(struct snd_pcm_substream *substream, |
272 | struct snd_soc_dai *dai) | 272 | struct snd_soc_dai *dai) |
273 | { | 273 | { |
274 | struct skl *skl = get_skl_ctx(dai->dev); | 274 | struct skl_dev *skl = get_skl_ctx(dai->dev); |
275 | struct skl_module_cfg *mconfig; | 275 | struct skl_module_cfg *mconfig; |
276 | int ret; | 276 | int ret; |
277 | 277 | ||
@@ -288,7 +288,7 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream, | |||
288 | mconfig->pipe->state == SKL_PIPE_CREATED || | 288 | mconfig->pipe->state == SKL_PIPE_CREATED || |
289 | mconfig->pipe->state == SKL_PIPE_PAUSED)) { | 289 | mconfig->pipe->state == SKL_PIPE_PAUSED)) { |
290 | 290 | ||
291 | ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe); | 291 | ret = skl_reset_pipe(skl, mconfig->pipe); |
292 | 292 | ||
293 | if (ret < 0) | 293 | if (ret < 0) |
294 | return ret; | 294 | return ret; |
@@ -350,7 +350,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream, | |||
350 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | 350 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); |
351 | struct hdac_bus *bus = dev_get_drvdata(dai->dev); | 351 | struct hdac_bus *bus = dev_get_drvdata(dai->dev); |
352 | struct skl_dma_params *dma_params = NULL; | 352 | struct skl_dma_params *dma_params = NULL; |
353 | struct skl *skl = bus_to_skl(bus); | 353 | struct skl_dev *skl = bus_to_skl(bus); |
354 | struct skl_module_cfg *mconfig; | 354 | struct skl_module_cfg *mconfig; |
355 | 355 | ||
356 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); | 356 | dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); |
@@ -370,9 +370,9 @@ static void skl_pcm_close(struct snd_pcm_substream *substream, | |||
370 | * CGCTL.MISCBDCGE if disabled by driver | 370 | * CGCTL.MISCBDCGE if disabled by driver |
371 | */ | 371 | */ |
372 | if (!strncmp(dai->name, "Reference Pin", 13) && | 372 | if (!strncmp(dai->name, "Reference Pin", 13) && |
373 | skl->skl_sst->miscbdcg_disabled) { | 373 | skl->miscbdcg_disabled) { |
374 | skl->skl_sst->enable_miscbdcge(dai->dev, true); | 374 | skl->enable_miscbdcge(dai->dev, true); |
375 | skl->skl_sst->miscbdcg_disabled = false; | 375 | skl->miscbdcg_disabled = false; |
376 | } | 376 | } |
377 | 377 | ||
378 | mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); | 378 | mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); |
@@ -387,7 +387,7 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream, | |||
387 | { | 387 | { |
388 | struct hdac_bus *bus = dev_get_drvdata(dai->dev); | 388 | struct hdac_bus *bus = dev_get_drvdata(dai->dev); |
389 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | 389 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); |
390 | struct skl *skl = get_skl_ctx(dai->dev); | 390 | struct skl_dev *skl = get_skl_ctx(dai->dev); |
391 | struct skl_module_cfg *mconfig; | 391 | struct skl_module_cfg *mconfig; |
392 | int ret; | 392 | int ret; |
393 | 393 | ||
@@ -396,7 +396,7 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream, | |||
396 | mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); | 396 | mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); |
397 | 397 | ||
398 | if (mconfig) { | 398 | if (mconfig) { |
399 | ret = skl_reset_pipe(skl->skl_sst, mconfig->pipe); | 399 | ret = skl_reset_pipe(skl, mconfig->pipe); |
400 | if (ret < 0) | 400 | if (ret < 0) |
401 | dev_err(dai->dev, "%s:Reset failed ret =%d", | 401 | dev_err(dai->dev, "%s:Reset failed ret =%d", |
402 | __func__, ret); | 402 | __func__, ret); |
@@ -471,8 +471,7 @@ static int skl_decoupled_trigger(struct snd_pcm_substream *substream, | |||
471 | static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | 471 | static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, |
472 | struct snd_soc_dai *dai) | 472 | struct snd_soc_dai *dai) |
473 | { | 473 | { |
474 | struct skl *skl = get_skl_ctx(dai->dev); | 474 | struct skl_dev *skl = get_skl_ctx(dai->dev); |
475 | struct skl_sst *ctx = skl->skl_sst; | ||
476 | struct skl_module_cfg *mconfig; | 475 | struct skl_module_cfg *mconfig; |
477 | struct hdac_bus *bus = get_bus_ctx(substream); | 476 | struct hdac_bus *bus = get_bus_ctx(substream); |
478 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); | 477 | struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); |
@@ -515,7 +514,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
515 | ret = skl_decoupled_trigger(substream, cmd); | 514 | ret = skl_decoupled_trigger(substream, cmd); |
516 | if (ret < 0) | 515 | if (ret < 0) |
517 | return ret; | 516 | return ret; |
518 | return skl_run_pipe(ctx, mconfig->pipe); | 517 | return skl_run_pipe(skl, mconfig->pipe); |
519 | break; | 518 | break; |
520 | 519 | ||
521 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 520 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
@@ -526,7 +525,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
526 | * there are no underrun/overrun in the case if there is a delay | 525 | * there are no underrun/overrun in the case if there is a delay |
527 | * between the two operations. | 526 | * between the two operations. |
528 | */ | 527 | */ |
529 | ret = skl_stop_pipe(ctx, mconfig->pipe); | 528 | ret = skl_stop_pipe(skl, mconfig->pipe); |
530 | if (ret < 0) | 529 | if (ret < 0) |
531 | return ret; | 530 | return ret; |
532 | 531 | ||
@@ -602,14 +601,14 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, | |||
602 | static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, | 601 | static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, |
603 | struct snd_soc_dai *dai) | 602 | struct snd_soc_dai *dai) |
604 | { | 603 | { |
605 | struct skl *skl = get_skl_ctx(dai->dev); | 604 | struct skl_dev *skl = get_skl_ctx(dai->dev); |
606 | struct skl_module_cfg *mconfig = NULL; | 605 | struct skl_module_cfg *mconfig = NULL; |
607 | 606 | ||
608 | /* In case of XRUN recovery, reset the FW pipe to clean state */ | 607 | /* In case of XRUN recovery, reset the FW pipe to clean state */ |
609 | mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); | 608 | mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); |
610 | if (mconfig && !mconfig->pipe->passthru && | 609 | if (mconfig && !mconfig->pipe->passthru && |
611 | (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) | 610 | (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) |
612 | skl_reset_pipe(skl->skl_sst, mconfig->pipe); | 611 | skl_reset_pipe(skl, mconfig->pipe); |
613 | 612 | ||
614 | return 0; | 613 | return 0; |
615 | } | 614 | } |
@@ -1301,7 +1300,7 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
1301 | struct hdac_bus *bus = dev_get_drvdata(dai->dev); | 1300 | struct hdac_bus *bus = dev_get_drvdata(dai->dev); |
1302 | struct snd_pcm *pcm = rtd->pcm; | 1301 | struct snd_pcm *pcm = rtd->pcm; |
1303 | unsigned int size; | 1302 | unsigned int size; |
1304 | struct skl *skl = bus_to_skl(bus); | 1303 | struct skl_dev *skl = bus_to_skl(bus); |
1305 | 1304 | ||
1306 | if (dai->driver->playback.channels_min || | 1305 | if (dai->driver->playback.channels_min || |
1307 | dai->driver->capture.channels_min) { | 1306 | dai->driver->capture.channels_min) { |
@@ -1318,9 +1317,9 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
1318 | return 0; | 1317 | return 0; |
1319 | } | 1318 | } |
1320 | 1319 | ||
1321 | static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) | 1320 | static int skl_get_module_info(struct skl_dev *skl, |
1321 | struct skl_module_cfg *mconfig) | ||
1322 | { | 1322 | { |
1323 | struct skl_sst *ctx = skl->skl_sst; | ||
1324 | struct skl_module_inst_id *pin_id; | 1323 | struct skl_module_inst_id *pin_id; |
1325 | guid_t *uuid_mod, *uuid_tplg; | 1324 | guid_t *uuid_mod, *uuid_tplg; |
1326 | struct skl_module *skl_module; | 1325 | struct skl_module *skl_module; |
@@ -1329,12 +1328,12 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) | |||
1329 | 1328 | ||
1330 | uuid_mod = (guid_t *)mconfig->guid; | 1329 | uuid_mod = (guid_t *)mconfig->guid; |
1331 | 1330 | ||
1332 | if (list_empty(&ctx->uuid_list)) { | 1331 | if (list_empty(&skl->uuid_list)) { |
1333 | dev_err(ctx->dev, "Module list is empty\n"); | 1332 | dev_err(skl->dev, "Module list is empty\n"); |
1334 | return -EIO; | 1333 | return -EIO; |
1335 | } | 1334 | } |
1336 | 1335 | ||
1337 | list_for_each_entry(module, &ctx->uuid_list, list) { | 1336 | list_for_each_entry(module, &skl->uuid_list, list) { |
1338 | if (guid_equal(uuid_mod, &module->uuid)) { | 1337 | if (guid_equal(uuid_mod, &module->uuid)) { |
1339 | mconfig->id.module_id = module->id; | 1338 | mconfig->id.module_id = module->id; |
1340 | if (mconfig->module) | 1339 | if (mconfig->module) |
@@ -1361,7 +1360,7 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) | |||
1361 | if (skl->nr_modules && ret) | 1360 | if (skl->nr_modules && ret) |
1362 | return ret; | 1361 | return ret; |
1363 | 1362 | ||
1364 | list_for_each_entry(module, &ctx->uuid_list, list) { | 1363 | list_for_each_entry(module, &skl->uuid_list, list) { |
1365 | for (i = 0; i < MAX_IN_QUEUE; i++) { | 1364 | for (i = 0; i < MAX_IN_QUEUE; i++) { |
1366 | pin_id = &mconfig->m_in_pin[i].id; | 1365 | pin_id = &mconfig->m_in_pin[i].id; |
1367 | if (guid_equal(&pin_id->mod_uuid, &module->uuid)) | 1366 | if (guid_equal(&pin_id->mod_uuid, &module->uuid)) |
@@ -1378,7 +1377,7 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) | |||
1378 | return 0; | 1377 | return 0; |
1379 | } | 1378 | } |
1380 | 1379 | ||
1381 | static int skl_populate_modules(struct skl *skl) | 1380 | static int skl_populate_modules(struct skl_dev *skl) |
1382 | { | 1381 | { |
1383 | struct skl_pipeline *p; | 1382 | struct skl_pipeline *p; |
1384 | struct skl_pipe_module *m; | 1383 | struct skl_pipe_module *m; |
@@ -1393,7 +1392,7 @@ static int skl_populate_modules(struct skl *skl) | |||
1393 | 1392 | ||
1394 | ret = skl_get_module_info(skl, mconfig); | 1393 | ret = skl_get_module_info(skl, mconfig); |
1395 | if (ret < 0) { | 1394 | if (ret < 0) { |
1396 | dev_err(skl->skl_sst->dev, | 1395 | dev_err(skl->dev, |
1397 | "query module info failed\n"); | 1396 | "query module info failed\n"); |
1398 | return ret; | 1397 | return ret; |
1399 | } | 1398 | } |
@@ -1408,7 +1407,7 @@ static int skl_populate_modules(struct skl *skl) | |||
1408 | static int skl_platform_soc_probe(struct snd_soc_component *component) | 1407 | static int skl_platform_soc_probe(struct snd_soc_component *component) |
1409 | { | 1408 | { |
1410 | struct hdac_bus *bus = dev_get_drvdata(component->dev); | 1409 | struct hdac_bus *bus = dev_get_drvdata(component->dev); |
1411 | struct skl *skl = bus_to_skl(bus); | 1410 | struct skl_dev *skl = bus_to_skl(bus); |
1412 | const struct skl_dsp_ops *ops; | 1411 | const struct skl_dsp_ops *ops; |
1413 | int ret; | 1412 | int ret; |
1414 | 1413 | ||
@@ -1434,22 +1433,21 @@ static int skl_platform_soc_probe(struct snd_soc_component *component) | |||
1434 | * Disable dynamic clock and power gating during firmware | 1433 | * Disable dynamic clock and power gating during firmware |
1435 | * and library download | 1434 | * and library download |
1436 | */ | 1435 | */ |
1437 | skl->skl_sst->enable_miscbdcge(component->dev, false); | 1436 | skl->enable_miscbdcge(component->dev, false); |
1438 | skl->skl_sst->clock_power_gating(component->dev, false); | 1437 | skl->clock_power_gating(component->dev, false); |
1439 | 1438 | ||
1440 | ret = ops->init_fw(component->dev, skl->skl_sst); | 1439 | ret = ops->init_fw(component->dev, skl); |
1441 | skl->skl_sst->enable_miscbdcge(component->dev, true); | 1440 | skl->enable_miscbdcge(component->dev, true); |
1442 | skl->skl_sst->clock_power_gating(component->dev, true); | 1441 | skl->clock_power_gating(component->dev, true); |
1443 | if (ret < 0) { | 1442 | if (ret < 0) { |
1444 | dev_err(component->dev, "Failed to boot first fw: %d\n", ret); | 1443 | dev_err(component->dev, "Failed to boot first fw: %d\n", ret); |
1445 | return ret; | 1444 | return ret; |
1446 | } | 1445 | } |
1447 | skl_populate_modules(skl); | 1446 | skl_populate_modules(skl); |
1448 | skl->skl_sst->update_d0i3c = skl_update_d0i3c; | 1447 | skl->update_d0i3c = skl_update_d0i3c; |
1449 | skl_dsp_enable_notification(skl->skl_sst, false); | ||
1450 | 1448 | ||
1451 | if (skl->cfg.astate_cfg != NULL) { | 1449 | if (skl->cfg.astate_cfg != NULL) { |
1452 | skl_dsp_set_astate_cfg(skl->skl_sst, | 1450 | skl_dsp_set_astate_cfg(skl, |
1453 | skl->cfg.astate_cfg->count, | 1451 | skl->cfg.astate_cfg->count, |
1454 | skl->cfg.astate_cfg); | 1452 | skl->cfg.astate_cfg); |
1455 | } | 1453 | } |
@@ -1463,7 +1461,7 @@ static int skl_platform_soc_probe(struct snd_soc_component *component) | |||
1463 | static void skl_pcm_remove(struct snd_soc_component *component) | 1461 | static void skl_pcm_remove(struct snd_soc_component *component) |
1464 | { | 1462 | { |
1465 | struct hdac_bus *bus = dev_get_drvdata(component->dev); | 1463 | struct hdac_bus *bus = dev_get_drvdata(component->dev); |
1466 | struct skl *skl = bus_to_skl(bus); | 1464 | struct skl_dev *skl = bus_to_skl(bus); |
1467 | 1465 | ||
1468 | skl_tplg_exit(component, bus); | 1466 | skl_tplg_exit(component, bus); |
1469 | 1467 | ||
@@ -1486,7 +1484,7 @@ int skl_platform_register(struct device *dev) | |||
1486 | struct snd_soc_dai_driver *dais; | 1484 | struct snd_soc_dai_driver *dais; |
1487 | int num_dais = ARRAY_SIZE(skl_platform_dai); | 1485 | int num_dais = ARRAY_SIZE(skl_platform_dai); |
1488 | struct hdac_bus *bus = dev_get_drvdata(dev); | 1486 | struct hdac_bus *bus = dev_get_drvdata(dev); |
1489 | struct skl *skl = bus_to_skl(bus); | 1487 | struct skl_dev *skl = bus_to_skl(bus); |
1490 | 1488 | ||
1491 | skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai), | 1489 | skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai), |
1492 | GFP_KERNEL); | 1490 | GFP_KERNEL); |
@@ -1520,7 +1518,7 @@ err: | |||
1520 | int skl_platform_unregister(struct device *dev) | 1518 | int skl_platform_unregister(struct device *dev) |
1521 | { | 1519 | { |
1522 | struct hdac_bus *bus = dev_get_drvdata(dev); | 1520 | struct hdac_bus *bus = dev_get_drvdata(dev); |
1523 | struct skl *skl = bus_to_skl(bus); | 1521 | struct skl_dev *skl = bus_to_skl(bus); |
1524 | struct skl_module_deferred_bind *modules, *tmp; | 1522 | struct skl_module_deferred_bind *modules, *tmp; |
1525 | 1523 | ||
1526 | if (!list_empty(&skl->bind_list)) { | 1524 | if (!list_empty(&skl->bind_list)) { |
diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index 5bb6e40d4d3e..1c0e5226cb5b 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | #include <linux/clk-provider.h> | 12 | #include <linux/clk-provider.h> |
13 | #include <linux/clkdev.h> | 13 | #include <linux/clkdev.h> |
14 | #include <sound/intel-nhlt.h> | ||
14 | #include "skl.h" | 15 | #include "skl.h" |
15 | #include "skl-ssp-clk.h" | 16 | #include "skl-ssp-clk.h" |
16 | #include "skl-topology.h" | 17 | #include "skl-topology.h" |
@@ -101,7 +102,7 @@ static void skl_fill_clk_ipc(struct skl_clk_rate_cfg_table *rcfg, u8 clk_type) | |||
101 | } | 102 | } |
102 | 103 | ||
103 | /* Sends dma control IPC to turn the clock ON/OFF */ | 104 | /* Sends dma control IPC to turn the clock ON/OFF */ |
104 | static int skl_send_clk_dma_control(struct skl *skl, | 105 | static int skl_send_clk_dma_control(struct skl_dev *skl, |
105 | struct skl_clk_rate_cfg_table *rcfg, | 106 | struct skl_clk_rate_cfg_table *rcfg, |
106 | u32 vbus_id, u8 clk_type, | 107 | u32 vbus_id, u8 clk_type, |
107 | bool enable) | 108 | bool enable) |
@@ -152,7 +153,7 @@ static int skl_send_clk_dma_control(struct skl *skl, | |||
152 | memcpy(i2s_config + sp_cfg->size, data, size); | 153 | memcpy(i2s_config + sp_cfg->size, data, size); |
153 | 154 | ||
154 | node_id = ((SKL_DMA_I2S_LINK_INPUT_CLASS << 8) | (vbus_id << 4)); | 155 | node_id = ((SKL_DMA_I2S_LINK_INPUT_CLASS << 8) | (vbus_id << 4)); |
155 | ret = skl_dsp_set_dma_control(skl->skl_sst, (u32 *)i2s_config, | 156 | ret = skl_dsp_set_dma_control(skl, (u32 *)i2s_config, |
156 | i2s_config_size, node_id); | 157 | i2s_config_size, node_id); |
157 | kfree(i2s_config); | 158 | kfree(i2s_config); |
158 | 159 | ||
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 36590c5b4673..225706d148d8 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include "../common/sst-dsp.h" | 12 | #include "../common/sst-dsp.h" |
13 | #include "../common/sst-ipc.h" | 13 | #include "../common/sst-ipc.h" |
14 | #include "../common/sst-dsp-priv.h" | 14 | #include "../common/sst-dsp-priv.h" |
15 | #include "skl-sst-ipc.h" | 15 | #include "skl.h" |
16 | 16 | ||
17 | /* various timeout values */ | 17 | /* various timeout values */ |
18 | #define SKL_DSP_PU_TO 50 | 18 | #define SKL_DSP_PU_TO 50 |
@@ -33,7 +33,7 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) | |||
33 | */ | 33 | */ |
34 | void skl_dsp_init_core_state(struct sst_dsp *ctx) | 34 | void skl_dsp_init_core_state(struct sst_dsp *ctx) |
35 | { | 35 | { |
36 | struct skl_sst *skl = ctx->thread_context; | 36 | struct skl_dev *skl = ctx->thread_context; |
37 | int i; | 37 | int i; |
38 | 38 | ||
39 | skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; | 39 | skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; |
@@ -48,7 +48,7 @@ void skl_dsp_init_core_state(struct sst_dsp *ctx) | |||
48 | /* Get the mask for all enabled cores */ | 48 | /* Get the mask for all enabled cores */ |
49 | unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) | 49 | unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) |
50 | { | 50 | { |
51 | struct skl_sst *skl = ctx->thread_context; | 51 | struct skl_dev *skl = ctx->thread_context; |
52 | unsigned int core_mask, en_cores_mask; | 52 | unsigned int core_mask, en_cores_mask; |
53 | u32 val; | 53 | u32 val; |
54 | 54 | ||
@@ -335,7 +335,7 @@ irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) | |||
335 | */ | 335 | */ |
336 | int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) | 336 | int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) |
337 | { | 337 | { |
338 | struct skl_sst *skl = ctx->thread_context; | 338 | struct skl_dev *skl = ctx->thread_context; |
339 | int ret = 0; | 339 | int ret = 0; |
340 | 340 | ||
341 | if (core_id >= skl->cores.count) { | 341 | if (core_id >= skl->cores.count) { |
@@ -364,7 +364,7 @@ EXPORT_SYMBOL_GPL(skl_dsp_get_core); | |||
364 | 364 | ||
365 | int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) | 365 | int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) |
366 | { | 366 | { |
367 | struct skl_sst *skl = ctx->thread_context; | 367 | struct skl_dev *skl = ctx->thread_context; |
368 | int ret = 0; | 368 | int ret = 0; |
369 | 369 | ||
370 | if (core_id >= skl->cores.count) { | 370 | if (core_id >= skl->cores.count) { |
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index a80219562036..cdfec0fca577 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h | |||
@@ -15,9 +15,9 @@ | |||
15 | #include "skl-sst-cldma.h" | 15 | #include "skl-sst-cldma.h" |
16 | 16 | ||
17 | struct sst_dsp; | 17 | struct sst_dsp; |
18 | struct skl_sst; | ||
19 | struct sst_dsp_device; | 18 | struct sst_dsp_device; |
20 | struct skl_lib_info; | 19 | struct skl_lib_info; |
20 | struct skl_dev; | ||
21 | 21 | ||
22 | /* Intel HD Audio General DSP Registers */ | 22 | /* Intel HD Audio General DSP Registers */ |
23 | #define SKL_ADSP_GEN_BASE 0x0 | 23 | #define SKL_ADSP_GEN_BASE 0x0 |
@@ -222,32 +222,31 @@ int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id); | |||
222 | int skl_dsp_boot(struct sst_dsp *ctx); | 222 | int skl_dsp_boot(struct sst_dsp *ctx); |
223 | int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | 223 | int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, |
224 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, | 224 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, |
225 | struct skl_sst **dsp); | 225 | struct skl_dev **dsp); |
226 | int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | 226 | int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, |
227 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, | 227 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, |
228 | struct skl_sst **dsp); | 228 | struct skl_dev **dsp); |
229 | int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx); | 229 | int skl_sst_init_fw(struct device *dev, struct skl_dev *skl); |
230 | int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx); | 230 | int bxt_sst_init_fw(struct device *dev, struct skl_dev *skl); |
231 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); | 231 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); |
232 | void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); | 232 | void bxt_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); |
233 | 233 | ||
234 | int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, | 234 | int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, |
235 | unsigned int offset, int index); | 235 | unsigned int offset, int index); |
236 | int skl_get_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int instance_id); | 236 | int skl_get_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int instance_id); |
237 | int skl_put_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int *pvt_id); | 237 | int skl_put_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int *pvt_id); |
238 | int skl_get_pvt_instance_id_map(struct skl_sst *ctx, | 238 | int skl_get_pvt_instance_id_map(struct skl_dev *skl, |
239 | int module_id, int instance_id); | 239 | int module_id, int instance_id); |
240 | void skl_freeup_uuid_list(struct skl_sst *ctx); | 240 | void skl_freeup_uuid_list(struct skl_dev *skl); |
241 | 241 | ||
242 | int skl_dsp_strip_extended_manifest(struct firmware *fw); | 242 | int skl_dsp_strip_extended_manifest(struct firmware *fw); |
243 | void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable); | ||
244 | 243 | ||
245 | void skl_dsp_set_astate_cfg(struct skl_sst *ctx, u32 cnt, void *data); | 244 | void skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data); |
246 | 245 | ||
247 | int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, | 246 | int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, |
248 | struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp, | 247 | struct skl_dsp_loader_ops dsp_ops, struct skl_dev **dsp, |
249 | struct sst_dsp_device *skl_dev); | 248 | struct sst_dsp_device *skl_dev); |
250 | int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, | 249 | int skl_prepare_lib_load(struct skl_dev *skl, struct skl_lib_info *linfo, |
251 | struct firmware *stripped_fw, | 250 | struct firmware *stripped_fw, |
252 | unsigned int hdr_offset, int index); | 251 | unsigned int hdr_offset, int index); |
253 | void skl_release_library(struct skl_lib_info *linfo, int lib_count); | 252 | void skl_release_library(struct skl_lib_info *linfo, int lib_count); |
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 2cc8f7d2d319..667cdddc289f 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c | |||
@@ -281,7 +281,7 @@ void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, | |||
281 | size_t tx_size) | 281 | size_t tx_size) |
282 | { | 282 | { |
283 | if (tx_size) | 283 | if (tx_size) |
284 | memcpy(msg->tx_data, tx_data, tx_size); | 284 | memcpy(msg->tx.data, tx_data, tx_size); |
285 | } | 285 | } |
286 | 286 | ||
287 | static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) | 287 | static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) |
@@ -295,10 +295,10 @@ static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) | |||
295 | /* Lock to be held by caller */ | 295 | /* Lock to be held by caller */ |
296 | static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) | 296 | static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) |
297 | { | 297 | { |
298 | struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); | 298 | struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header); |
299 | 299 | ||
300 | if (msg->tx_size) | 300 | if (msg->tx.size) |
301 | sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); | 301 | sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); |
302 | sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE, | 302 | sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE, |
303 | header->extension); | 303 | header->extension); |
304 | sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI, | 304 | sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI, |
@@ -345,7 +345,7 @@ out: | |||
345 | int skl_ipc_process_notification(struct sst_generic_ipc *ipc, | 345 | int skl_ipc_process_notification(struct sst_generic_ipc *ipc, |
346 | struct skl_ipc_header header) | 346 | struct skl_ipc_header header) |
347 | { | 347 | { |
348 | struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); | 348 | struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc); |
349 | 349 | ||
350 | if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { | 350 | if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { |
351 | switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { | 351 | switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { |
@@ -436,7 +436,7 @@ void skl_ipc_process_reply(struct sst_generic_ipc *ipc, | |||
436 | struct ipc_message *msg; | 436 | struct ipc_message *msg; |
437 | u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; | 437 | u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; |
438 | u64 *ipc_header = (u64 *)(&header); | 438 | u64 *ipc_header = (u64 *)(&header); |
439 | struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); | 439 | struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc); |
440 | unsigned long flags; | 440 | unsigned long flags; |
441 | 441 | ||
442 | spin_lock_irqsave(&ipc->dsp->spinlock, flags); | 442 | spin_lock_irqsave(&ipc->dsp->spinlock, flags); |
@@ -447,11 +447,12 @@ void skl_ipc_process_reply(struct sst_generic_ipc *ipc, | |||
447 | return; | 447 | return; |
448 | } | 448 | } |
449 | 449 | ||
450 | msg->rx.header = *ipc_header; | ||
450 | /* first process the header */ | 451 | /* first process the header */ |
451 | if (reply == IPC_GLB_REPLY_SUCCESS) { | 452 | if (reply == IPC_GLB_REPLY_SUCCESS) { |
452 | dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary); | 453 | dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary); |
453 | /* copy the rx data from the mailbox */ | 454 | /* copy the rx data from the mailbox */ |
454 | sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size); | 455 | sst_dsp_inbox_read(ipc->dsp, msg->rx.data, msg->rx.size); |
455 | switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { | 456 | switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { |
456 | case IPC_GLB_LOAD_MULTIPLE_MODS: | 457 | case IPC_GLB_LOAD_MULTIPLE_MODS: |
457 | case IPC_GLB_LOAD_LIBRARY: | 458 | case IPC_GLB_LOAD_LIBRARY: |
@@ -488,7 +489,7 @@ void skl_ipc_process_reply(struct sst_generic_ipc *ipc, | |||
488 | irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) | 489 | irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) |
489 | { | 490 | { |
490 | struct sst_dsp *dsp = context; | 491 | struct sst_dsp *dsp = context; |
491 | struct skl_sst *skl = sst_dsp_get_thread_context(dsp); | 492 | struct skl_dev *skl = sst_dsp_get_thread_context(dsp); |
492 | struct sst_generic_ipc *ipc = &skl->ipc; | 493 | struct sst_generic_ipc *ipc = &skl->ipc; |
493 | struct skl_ipc_header header = {0}; | 494 | struct skl_ipc_header header = {0}; |
494 | u32 hipcie, hipct, hipcte; | 495 | u32 hipcie, hipct, hipcte; |
@@ -595,7 +596,7 @@ bool skl_ipc_int_status(struct sst_dsp *ctx) | |||
595 | SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC; | 596 | SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC; |
596 | } | 597 | } |
597 | 598 | ||
598 | int skl_ipc_init(struct device *dev, struct skl_sst *skl) | 599 | int skl_ipc_init(struct device *dev, struct skl_dev *skl) |
599 | { | 600 | { |
600 | struct sst_generic_ipc *ipc; | 601 | struct sst_generic_ipc *ipc; |
601 | int err; | 602 | int err; |
@@ -635,7 +636,7 @@ int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, | |||
635 | u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode) | 636 | u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode) |
636 | { | 637 | { |
637 | struct skl_ipc_header header = {0}; | 638 | struct skl_ipc_header header = {0}; |
638 | u64 *ipc_header = (u64 *)(&header); | 639 | struct sst_ipc_message request = {0}; |
639 | int ret; | 640 | int ret; |
640 | 641 | ||
641 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | 642 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); |
@@ -646,9 +647,10 @@ int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, | |||
646 | header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size); | 647 | header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size); |
647 | 648 | ||
648 | header.extension = IPC_PPL_LP_MODE(lp_mode); | 649 | header.extension = IPC_PPL_LP_MODE(lp_mode); |
650 | request.header = *(u64 *)(&header); | ||
649 | 651 | ||
650 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | 652 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); |
651 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | 653 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
652 | if (ret < 0) { | 654 | if (ret < 0) { |
653 | dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret); | 655 | dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret); |
654 | return ret; | 656 | return ret; |
@@ -661,16 +663,17 @@ EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline); | |||
661 | int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) | 663 | int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) |
662 | { | 664 | { |
663 | struct skl_ipc_header header = {0}; | 665 | struct skl_ipc_header header = {0}; |
664 | u64 *ipc_header = (u64 *)(&header); | 666 | struct sst_ipc_message request = {0}; |
665 | int ret; | 667 | int ret; |
666 | 668 | ||
667 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | 669 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); |
668 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | 670 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); |
669 | header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL); | 671 | header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL); |
670 | header.primary |= IPC_INSTANCE_ID(instance_id); | 672 | header.primary |= IPC_INSTANCE_ID(instance_id); |
673 | request.header = *(u64 *)(&header); | ||
671 | 674 | ||
672 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | 675 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); |
673 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | 676 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
674 | if (ret < 0) { | 677 | if (ret < 0) { |
675 | dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret); | 678 | dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret); |
676 | return ret; | 679 | return ret; |
@@ -684,7 +687,7 @@ int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, | |||
684 | u8 instance_id, enum skl_ipc_pipeline_state state) | 687 | u8 instance_id, enum skl_ipc_pipeline_state state) |
685 | { | 688 | { |
686 | struct skl_ipc_header header = {0}; | 689 | struct skl_ipc_header header = {0}; |
687 | u64 *ipc_header = (u64 *)(&header); | 690 | struct sst_ipc_message request = {0}; |
688 | int ret; | 691 | int ret; |
689 | 692 | ||
690 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | 693 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); |
@@ -692,9 +695,10 @@ int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, | |||
692 | header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE); | 695 | header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE); |
693 | header.primary |= IPC_INSTANCE_ID(instance_id); | 696 | header.primary |= IPC_INSTANCE_ID(instance_id); |
694 | header.primary |= IPC_PPL_STATE(state); | 697 | header.primary |= IPC_PPL_STATE(state); |
698 | request.header = *(u64 *)(&header); | ||
695 | 699 | ||
696 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | 700 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); |
697 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | 701 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
698 | if (ret < 0) { | 702 | if (ret < 0) { |
699 | dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret); | 703 | dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret); |
700 | return ret; | 704 | return ret; |
@@ -707,7 +711,7 @@ int | |||
707 | skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) | 711 | skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) |
708 | { | 712 | { |
709 | struct skl_ipc_header header = {0}; | 713 | struct skl_ipc_header header = {0}; |
710 | u64 *ipc_header = (u64 *)(&header); | 714 | struct sst_ipc_message request = {0}; |
711 | int ret; | 715 | int ret; |
712 | 716 | ||
713 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | 717 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); |
@@ -716,8 +720,10 @@ skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) | |||
716 | header.primary |= IPC_INSTANCE_ID(instance_id); | 720 | header.primary |= IPC_INSTANCE_ID(instance_id); |
717 | 721 | ||
718 | header.extension = IPC_DMA_ID(dma_id); | 722 | header.extension = IPC_DMA_ID(dma_id); |
723 | request.header = *(u64 *)(&header); | ||
724 | |||
719 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | 725 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); |
720 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | 726 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
721 | if (ret < 0) { | 727 | if (ret < 0) { |
722 | dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret); | 728 | dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret); |
723 | return ret; | 729 | return ret; |
@@ -730,16 +736,17 @@ EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline); | |||
730 | int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) | 736 | int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) |
731 | { | 737 | { |
732 | struct skl_ipc_header header = {0}; | 738 | struct skl_ipc_header header = {0}; |
733 | u64 *ipc_header = (u64 *)(&header); | 739 | struct sst_ipc_message request = {0}; |
734 | int ret; | 740 | int ret; |
735 | 741 | ||
736 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | 742 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); |
737 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | 743 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); |
738 | header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL); | 744 | header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL); |
739 | header.primary |= IPC_INSTANCE_ID(instance_id); | 745 | header.primary |= IPC_INSTANCE_ID(instance_id); |
746 | request.header = *(u64 *)(&header); | ||
740 | 747 | ||
741 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); | 748 | dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); |
742 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | 749 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
743 | if (ret < 0) { | 750 | if (ret < 0) { |
744 | dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret); | 751 | dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret); |
745 | return ret; | 752 | return ret; |
@@ -753,7 +760,7 @@ int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, | |||
753 | u16 module_id, struct skl_ipc_dxstate_info *dx) | 760 | u16 module_id, struct skl_ipc_dxstate_info *dx) |
754 | { | 761 | { |
755 | struct skl_ipc_header header = {0}; | 762 | struct skl_ipc_header header = {0}; |
756 | u64 *ipc_header = (u64 *)(&header); | 763 | struct sst_ipc_message request; |
757 | int ret; | 764 | int ret; |
758 | 765 | ||
759 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); | 766 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); |
@@ -762,10 +769,13 @@ int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, | |||
762 | header.primary |= IPC_MOD_INSTANCE_ID(instance_id); | 769 | header.primary |= IPC_MOD_INSTANCE_ID(instance_id); |
763 | header.primary |= IPC_MOD_ID(module_id); | 770 | header.primary |= IPC_MOD_ID(module_id); |
764 | 771 | ||
772 | request.header = *(u64 *)(&header); | ||
773 | request.data = dx; | ||
774 | request.size = sizeof(*dx); | ||
775 | |||
765 | dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, | 776 | dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, |
766 | header.primary, header.extension); | 777 | header.primary, header.extension); |
767 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, | 778 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
768 | dx, sizeof(*dx), NULL, 0); | ||
769 | if (ret < 0) { | 779 | if (ret < 0) { |
770 | dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); | 780 | dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); |
771 | return ret; | 781 | return ret; |
@@ -779,7 +789,7 @@ int skl_ipc_init_instance(struct sst_generic_ipc *ipc, | |||
779 | struct skl_ipc_init_instance_msg *msg, void *param_data) | 789 | struct skl_ipc_init_instance_msg *msg, void *param_data) |
780 | { | 790 | { |
781 | struct skl_ipc_header header = {0}; | 791 | struct skl_ipc_header header = {0}; |
782 | u64 *ipc_header = (u64 *)(&header); | 792 | struct sst_ipc_message request; |
783 | int ret; | 793 | int ret; |
784 | u32 *buffer = (u32 *)param_data; | 794 | u32 *buffer = (u32 *)param_data; |
785 | /* param_block_size must be in dwords */ | 795 | /* param_block_size must be in dwords */ |
@@ -799,10 +809,13 @@ int skl_ipc_init_instance(struct sst_generic_ipc *ipc, | |||
799 | header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); | 809 | header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); |
800 | header.extension |= IPC_DOMAIN(msg->domain); | 810 | header.extension |= IPC_DOMAIN(msg->domain); |
801 | 811 | ||
812 | request.header = *(u64 *)(&header); | ||
813 | request.data = param_data; | ||
814 | request.size = msg->param_data_size; | ||
815 | |||
802 | dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, | 816 | dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, |
803 | header.primary, header.extension); | 817 | header.primary, header.extension); |
804 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data, | 818 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
805 | msg->param_data_size, NULL, 0); | ||
806 | 819 | ||
807 | if (ret < 0) { | 820 | if (ret < 0) { |
808 | dev_err(ipc->dev, "ipc: init instance failed\n"); | 821 | dev_err(ipc->dev, "ipc: init instance failed\n"); |
@@ -817,7 +830,7 @@ int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, | |||
817 | struct skl_ipc_bind_unbind_msg *msg) | 830 | struct skl_ipc_bind_unbind_msg *msg) |
818 | { | 831 | { |
819 | struct skl_ipc_header header = {0}; | 832 | struct skl_ipc_header header = {0}; |
820 | u64 *ipc_header = (u64 *)(&header); | 833 | struct sst_ipc_message request = {0}; |
821 | u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; | 834 | u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; |
822 | int ret; | 835 | int ret; |
823 | 836 | ||
@@ -831,10 +844,11 @@ int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, | |||
831 | header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); | 844 | header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); |
832 | header.extension |= IPC_DST_QUEUE(msg->dst_queue); | 845 | header.extension |= IPC_DST_QUEUE(msg->dst_queue); |
833 | header.extension |= IPC_SRC_QUEUE(msg->src_queue); | 846 | header.extension |= IPC_SRC_QUEUE(msg->src_queue); |
847 | request.header = *(u64 *)(&header); | ||
834 | 848 | ||
835 | dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, | 849 | dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, |
836 | header.extension); | 850 | header.extension); |
837 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); | 851 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
838 | if (ret < 0) { | 852 | if (ret < 0) { |
839 | dev_err(ipc->dev, "ipc: bind/unbind failed\n"); | 853 | dev_err(ipc->dev, "ipc: bind/unbind failed\n"); |
840 | return ret; | 854 | return ret; |
@@ -854,7 +868,7 @@ int skl_ipc_load_modules(struct sst_generic_ipc *ipc, | |||
854 | u8 module_cnt, void *data) | 868 | u8 module_cnt, void *data) |
855 | { | 869 | { |
856 | struct skl_ipc_header header = {0}; | 870 | struct skl_ipc_header header = {0}; |
857 | u64 *ipc_header = (u64 *)(&header); | 871 | struct sst_ipc_message request; |
858 | int ret; | 872 | int ret; |
859 | 873 | ||
860 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | 874 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); |
@@ -862,8 +876,11 @@ int skl_ipc_load_modules(struct sst_generic_ipc *ipc, | |||
862 | header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS); | 876 | header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS); |
863 | header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); | 877 | header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); |
864 | 878 | ||
865 | ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, data, | 879 | request.header = *(u64 *)(&header); |
866 | (sizeof(u16) * module_cnt)); | 880 | request.data = data; |
881 | request.size = sizeof(u16) * module_cnt; | ||
882 | |||
883 | ret = sst_ipc_tx_message_nowait(ipc, request); | ||
867 | if (ret < 0) | 884 | if (ret < 0) |
868 | dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret); | 885 | dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret); |
869 | 886 | ||
@@ -875,7 +892,7 @@ int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, | |||
875 | void *data) | 892 | void *data) |
876 | { | 893 | { |
877 | struct skl_ipc_header header = {0}; | 894 | struct skl_ipc_header header = {0}; |
878 | u64 *ipc_header = (u64 *)(&header); | 895 | struct sst_ipc_message request; |
879 | int ret; | 896 | int ret; |
880 | 897 | ||
881 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | 898 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); |
@@ -883,8 +900,11 @@ int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, | |||
883 | header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS); | 900 | header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS); |
884 | header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); | 901 | header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); |
885 | 902 | ||
886 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data, | 903 | request.header = *(u64 *)(&header); |
887 | (sizeof(u16) * module_cnt), NULL, 0); | 904 | request.data = data; |
905 | request.size = sizeof(u16) * module_cnt; | ||
906 | |||
907 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); | ||
888 | if (ret < 0) | 908 | if (ret < 0) |
889 | dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret); | 909 | dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret); |
890 | 910 | ||
@@ -896,7 +916,7 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, | |||
896 | struct skl_ipc_large_config_msg *msg, u32 *param) | 916 | struct skl_ipc_large_config_msg *msg, u32 *param) |
897 | { | 917 | { |
898 | struct skl_ipc_header header = {0}; | 918 | struct skl_ipc_header header = {0}; |
899 | u64 *ipc_header = (u64 *)(&header); | 919 | struct sst_ipc_message request; |
900 | int ret = 0; | 920 | int ret = 0; |
901 | size_t sz_remaining, tx_size, data_offset; | 921 | size_t sz_remaining, tx_size, data_offset; |
902 | 922 | ||
@@ -923,9 +943,11 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, | |||
923 | header.primary, header.extension); | 943 | header.primary, header.extension); |
924 | dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", | 944 | dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", |
925 | (unsigned)data_offset, (unsigned)tx_size); | 945 | (unsigned)data_offset, (unsigned)tx_size); |
926 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, | 946 | |
927 | ((char *)param) + data_offset, | 947 | request.header = *(u64 *)(&header); |
928 | tx_size, NULL, 0); | 948 | request.data = ((char *)param) + data_offset; |
949 | request.size = tx_size; | ||
950 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); | ||
929 | if (ret < 0) { | 951 | if (ret < 0) { |
930 | dev_err(ipc->dev, | 952 | dev_err(ipc->dev, |
931 | "ipc: set large config fail, err: %d\n", ret); | 953 | "ipc: set large config fail, err: %d\n", ret); |
@@ -947,12 +969,17 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, | |||
947 | EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); | 969 | EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); |
948 | 970 | ||
949 | int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, | 971 | int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, |
950 | struct skl_ipc_large_config_msg *msg, u32 *param) | 972 | struct skl_ipc_large_config_msg *msg, |
973 | u32 **payload, size_t *bytes) | ||
951 | { | 974 | { |
952 | struct skl_ipc_header header = {0}; | 975 | struct skl_ipc_header header = {0}; |
953 | u64 *ipc_header = (u64 *)(&header); | 976 | struct sst_ipc_message request, reply = {0}; |
954 | int ret = 0; | 977 | unsigned int *buf; |
955 | size_t sz_remaining, rx_size, data_offset; | 978 | int ret; |
979 | |||
980 | reply.data = kzalloc(SKL_ADSP_W1_SZ, GFP_KERNEL); | ||
981 | if (!reply.data) | ||
982 | return -ENOMEM; | ||
956 | 983 | ||
957 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); | 984 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); |
958 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); | 985 | header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); |
@@ -965,33 +992,21 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, | |||
965 | header.extension |= IPC_FINAL_BLOCK(1); | 992 | header.extension |= IPC_FINAL_BLOCK(1); |
966 | header.extension |= IPC_INITIAL_BLOCK(1); | 993 | header.extension |= IPC_INITIAL_BLOCK(1); |
967 | 994 | ||
968 | sz_remaining = msg->param_data_size; | 995 | request.header = *(u64 *)&header; |
969 | data_offset = 0; | 996 | request.data = *payload; |
997 | request.size = *bytes; | ||
998 | reply.size = SKL_ADSP_W1_SZ; | ||
970 | 999 | ||
971 | while (sz_remaining != 0) { | 1000 | ret = sst_ipc_tx_message_wait(ipc, request, &reply); |
972 | rx_size = sz_remaining > SKL_ADSP_W1_SZ | 1001 | if (ret < 0) |
973 | ? SKL_ADSP_W1_SZ : sz_remaining; | 1002 | dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret); |
974 | if (rx_size == sz_remaining) | ||
975 | header.extension |= IPC_FINAL_BLOCK(1); | ||
976 | |||
977 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, | ||
978 | ((char *)param) + data_offset, | ||
979 | msg->param_data_size); | ||
980 | if (ret < 0) { | ||
981 | dev_err(ipc->dev, | ||
982 | "ipc: get large config fail, err: %d\n", ret); | ||
983 | return ret; | ||
984 | } | ||
985 | sz_remaining -= rx_size; | ||
986 | data_offset = msg->param_data_size - sz_remaining; | ||
987 | 1003 | ||
988 | /* clear the fields */ | 1004 | reply.size = (reply.header >> 32) & IPC_DATA_OFFSET_SZ_MASK; |
989 | header.extension &= IPC_INITIAL_BLOCK_CLEAR; | 1005 | buf = krealloc(reply.data, reply.size, GFP_KERNEL); |
990 | header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; | 1006 | if (!buf) |
991 | /* fill the fields */ | 1007 | return -ENOMEM; |
992 | header.extension |= IPC_INITIAL_BLOCK(1); | 1008 | *payload = buf; |
993 | header.extension |= IPC_DATA_OFFSET_SZ(data_offset); | 1009 | *bytes = reply.size; |
994 | } | ||
995 | 1010 | ||
996 | return ret; | 1011 | return ret; |
997 | } | 1012 | } |
@@ -1001,7 +1016,7 @@ int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, | |||
1001 | u8 dma_id, u8 table_id, bool wait) | 1016 | u8 dma_id, u8 table_id, bool wait) |
1002 | { | 1017 | { |
1003 | struct skl_ipc_header header = {0}; | 1018 | struct skl_ipc_header header = {0}; |
1004 | u64 *ipc_header = (u64 *)(&header); | 1019 | struct sst_ipc_message request = {0}; |
1005 | int ret = 0; | 1020 | int ret = 0; |
1006 | 1021 | ||
1007 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); | 1022 | header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); |
@@ -1009,12 +1024,12 @@ int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, | |||
1009 | header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY); | 1024 | header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY); |
1010 | header.primary |= IPC_MOD_INSTANCE_ID(table_id); | 1025 | header.primary |= IPC_MOD_INSTANCE_ID(table_id); |
1011 | header.primary |= IPC_MOD_ID(dma_id); | 1026 | header.primary |= IPC_MOD_ID(dma_id); |
1027 | request.header = *(u64 *)(&header); | ||
1012 | 1028 | ||
1013 | if (wait) | 1029 | if (wait) |
1014 | ret = sst_ipc_tx_message_wait(ipc, *ipc_header, | 1030 | ret = sst_ipc_tx_message_wait(ipc, request, NULL); |
1015 | NULL, 0, NULL, 0); | ||
1016 | else | 1031 | else |
1017 | ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, NULL, 0); | 1032 | ret = sst_ipc_tx_message_nowait(ipc, request); |
1018 | 1033 | ||
1019 | if (ret < 0) | 1034 | if (ret < 0) |
1020 | dev_err(ipc->dev, "ipc: load lib failed\n"); | 1035 | dev_err(ipc->dev, "ipc: load lib failed\n"); |
@@ -1026,7 +1041,7 @@ EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library); | |||
1026 | int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) | 1041 | int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) |
1027 | { | 1042 | { |
1028 | struct skl_ipc_header header = {0}; | 1043 | struct skl_ipc_header header = {0}; |
1029 | u64 *ipc_header = (u64 *)(&header); | 1044 | struct sst_ipc_message request = {0}; |
1030 | int ret; | 1045 | int ret; |
1031 | 1046 | ||
1032 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); | 1047 | header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); |
@@ -1037,6 +1052,7 @@ int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) | |||
1037 | 1052 | ||
1038 | header.extension = IPC_D0IX_WAKE(msg->wake); | 1053 | header.extension = IPC_D0IX_WAKE(msg->wake); |
1039 | header.extension |= IPC_D0IX_STREAMING(msg->streaming); | 1054 | header.extension |= IPC_D0IX_STREAMING(msg->streaming); |
1055 | request.header = *(u64 *)(&header); | ||
1040 | 1056 | ||
1041 | dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__, | 1057 | dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__, |
1042 | header.primary, header.extension); | 1058 | header.primary, header.extension); |
@@ -1044,7 +1060,7 @@ int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) | |||
1044 | /* | 1060 | /* |
1045 | * Use the nopm IPC here as we dont want it checking for D0iX | 1061 | * Use the nopm IPC here as we dont want it checking for D0iX |
1046 | */ | 1062 | */ |
1047 | ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0); | 1063 | ret = sst_ipc_tx_message_nopm(ipc, request, NULL); |
1048 | if (ret < 0) | 1064 | if (ret < 0) |
1049 | dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret); | 1065 | dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret); |
1050 | 1066 | ||
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index 9c31a48e99dd..08ac31778325 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h | |||
@@ -10,9 +10,9 @@ | |||
10 | 10 | ||
11 | #include <linux/irqreturn.h> | 11 | #include <linux/irqreturn.h> |
12 | #include "../common/sst-ipc.h" | 12 | #include "../common/sst-ipc.h" |
13 | #include "skl-sst-dsp.h" | ||
13 | 14 | ||
14 | struct sst_dsp; | 15 | struct sst_dsp; |
15 | struct skl_sst; | ||
16 | struct sst_generic_ipc; | 16 | struct sst_generic_ipc; |
17 | 17 | ||
18 | enum skl_ipc_pipeline_state { | 18 | enum skl_ipc_pipeline_state { |
@@ -67,54 +67,6 @@ struct skl_lib_info { | |||
67 | const struct firmware *fw; | 67 | const struct firmware *fw; |
68 | }; | 68 | }; |
69 | 69 | ||
70 | struct skl_sst { | ||
71 | struct device *dev; | ||
72 | struct sst_dsp *dsp; | ||
73 | |||
74 | /* boot */ | ||
75 | wait_queue_head_t boot_wait; | ||
76 | bool boot_complete; | ||
77 | |||
78 | /* module load */ | ||
79 | wait_queue_head_t mod_load_wait; | ||
80 | bool mod_load_complete; | ||
81 | bool mod_load_status; | ||
82 | |||
83 | /* IPC messaging */ | ||
84 | struct sst_generic_ipc ipc; | ||
85 | |||
86 | /* callback for miscbdge */ | ||
87 | void (*enable_miscbdcge)(struct device *dev, bool enable); | ||
88 | /* Is CGCTL.MISCBDCGE disabled */ | ||
89 | bool miscbdcg_disabled; | ||
90 | |||
91 | /* Populate module information */ | ||
92 | struct list_head uuid_list; | ||
93 | |||
94 | /* Is firmware loaded */ | ||
95 | bool fw_loaded; | ||
96 | |||
97 | /* first boot ? */ | ||
98 | bool is_first_boot; | ||
99 | |||
100 | /* multi-core */ | ||
101 | struct skl_dsp_cores cores; | ||
102 | |||
103 | /* library info */ | ||
104 | struct skl_lib_info lib_info[SKL_MAX_LIB]; | ||
105 | int lib_count; | ||
106 | |||
107 | /* Callback to update D0i3C register */ | ||
108 | void (*update_d0i3c)(struct device *dev, bool enable); | ||
109 | |||
110 | struct skl_d0i3_data d0i3; | ||
111 | |||
112 | const struct skl_dsp_ops *dsp_ops; | ||
113 | |||
114 | /* Callback to update dynamic clock and power gating registers */ | ||
115 | void (*clock_power_gating)(struct device *dev, bool enable); | ||
116 | }; | ||
117 | |||
118 | struct skl_ipc_init_instance_msg { | 70 | struct skl_ipc_init_instance_msg { |
119 | u32 module_id; | 71 | u32 module_id; |
120 | u32 instance_id; | 72 | u32 instance_id; |
@@ -187,7 +139,8 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, | |||
187 | struct skl_ipc_large_config_msg *msg, u32 *param); | 139 | struct skl_ipc_large_config_msg *msg, u32 *param); |
188 | 140 | ||
189 | int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, | 141 | int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, |
190 | struct skl_ipc_large_config_msg *msg, u32 *param); | 142 | struct skl_ipc_large_config_msg *msg, |
143 | u32 **payload, size_t *bytes); | ||
191 | 144 | ||
192 | int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, | 145 | int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, |
193 | u8 dma_id, u8 table_id, bool wait); | 146 | u8 dma_id, u8 table_id, bool wait); |
@@ -204,7 +157,7 @@ void skl_ipc_int_disable(struct sst_dsp *dsp); | |||
204 | 157 | ||
205 | bool skl_ipc_int_status(struct sst_dsp *dsp); | 158 | bool skl_ipc_int_status(struct sst_dsp *dsp); |
206 | void skl_ipc_free(struct sst_generic_ipc *ipc); | 159 | void skl_ipc_free(struct sst_generic_ipc *ipc); |
207 | int skl_ipc_init(struct device *dev, struct skl_sst *skl); | 160 | int skl_ipc_init(struct device *dev, struct skl_dev *skl); |
208 | void skl_clear_module_cnt(struct sst_dsp *ctx); | 161 | void skl_clear_module_cnt(struct sst_dsp *ctx); |
209 | 162 | ||
210 | void skl_ipc_process_reply(struct sst_generic_ipc *ipc, | 163 | void skl_ipc_process_reply(struct sst_generic_ipc *ipc, |
diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 928c677b506c..d43cbf4a71ef 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c | |||
@@ -8,10 +8,9 @@ | |||
8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <linux/uuid.h> | 10 | #include <linux/uuid.h> |
11 | #include "skl-sst-dsp.h" | ||
12 | #include "../common/sst-dsp.h" | 11 | #include "../common/sst-dsp.h" |
13 | #include "../common/sst-dsp-priv.h" | 12 | #include "../common/sst-dsp-priv.h" |
14 | #include "skl-sst-ipc.h" | 13 | #include "skl.h" |
15 | 14 | ||
16 | #define DEFAULT_HASH_SHA256_LEN 32 | 15 | #define DEFAULT_HASH_SHA256_LEN 32 |
17 | 16 | ||
@@ -99,12 +98,12 @@ static int skl_get_pvtid_map(struct uuid_module *module, int instance_id) | |||
99 | return -EINVAL; | 98 | return -EINVAL; |
100 | } | 99 | } |
101 | 100 | ||
102 | int skl_get_pvt_instance_id_map(struct skl_sst *ctx, | 101 | int skl_get_pvt_instance_id_map(struct skl_dev *skl, |
103 | int module_id, int instance_id) | 102 | int module_id, int instance_id) |
104 | { | 103 | { |
105 | struct uuid_module *module; | 104 | struct uuid_module *module; |
106 | 105 | ||
107 | list_for_each_entry(module, &ctx->uuid_list, list) { | 106 | list_for_each_entry(module, &skl->uuid_list, list) { |
108 | if (module->id == module_id) | 107 | if (module->id == module_id) |
109 | return skl_get_pvtid_map(module, instance_id); | 108 | return skl_get_pvtid_map(module, instance_id); |
110 | } | 109 | } |
@@ -163,19 +162,19 @@ static inline int skl_pvtid_128(struct uuid_module *module) | |||
163 | /** | 162 | /** |
164 | * skl_get_pvt_id: generate a private id for use as module id | 163 | * skl_get_pvt_id: generate a private id for use as module id |
165 | * | 164 | * |
166 | * @ctx: driver context | 165 | * @skl: driver context |
167 | * @uuid_mod: module's uuid | 166 | * @uuid_mod: module's uuid |
168 | * @instance_id: module's instance id | 167 | * @instance_id: module's instance id |
169 | * | 168 | * |
170 | * This generates a 128 bit private unique id for a module TYPE so that | 169 | * This generates a 128 bit private unique id for a module TYPE so that |
171 | * module instance is unique | 170 | * module instance is unique |
172 | */ | 171 | */ |
173 | int skl_get_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int instance_id) | 172 | int skl_get_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int instance_id) |
174 | { | 173 | { |
175 | struct uuid_module *module; | 174 | struct uuid_module *module; |
176 | int pvt_id; | 175 | int pvt_id; |
177 | 176 | ||
178 | list_for_each_entry(module, &ctx->uuid_list, list) { | 177 | list_for_each_entry(module, &skl->uuid_list, list) { |
179 | if (guid_equal(uuid_mod, &module->uuid)) { | 178 | if (guid_equal(uuid_mod, &module->uuid)) { |
180 | 179 | ||
181 | pvt_id = skl_pvtid_128(module); | 180 | pvt_id = skl_pvtid_128(module); |
@@ -194,18 +193,18 @@ EXPORT_SYMBOL_GPL(skl_get_pvt_id); | |||
194 | /** | 193 | /** |
195 | * skl_put_pvt_id: free up the private id allocated | 194 | * skl_put_pvt_id: free up the private id allocated |
196 | * | 195 | * |
197 | * @ctx: driver context | 196 | * @skl: driver context |
198 | * @uuid_mod: module's uuid | 197 | * @uuid_mod: module's uuid |
199 | * @pvt_id: module pvt id | 198 | * @pvt_id: module pvt id |
200 | * | 199 | * |
201 | * This frees a 128 bit private unique id previously generated | 200 | * This frees a 128 bit private unique id previously generated |
202 | */ | 201 | */ |
203 | int skl_put_pvt_id(struct skl_sst *ctx, guid_t *uuid_mod, int *pvt_id) | 202 | int skl_put_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int *pvt_id) |
204 | { | 203 | { |
205 | int i; | 204 | int i; |
206 | struct uuid_module *module; | 205 | struct uuid_module *module; |
207 | 206 | ||
208 | list_for_each_entry(module, &ctx->uuid_list, list) { | 207 | list_for_each_entry(module, &skl->uuid_list, list) { |
209 | if (guid_equal(uuid_mod, &module->uuid)) { | 208 | if (guid_equal(uuid_mod, &module->uuid)) { |
210 | 209 | ||
211 | if (*pvt_id != 0) | 210 | if (*pvt_id != 0) |
@@ -234,7 +233,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, | |||
234 | struct adsp_module_entry *mod_entry; | 233 | struct adsp_module_entry *mod_entry; |
235 | int i, num_entry, size; | 234 | int i, num_entry, size; |
236 | const char *buf; | 235 | const char *buf; |
237 | struct skl_sst *skl = ctx->thread_context; | 236 | struct skl_dev *skl = ctx->thread_context; |
238 | struct uuid_module *module; | 237 | struct uuid_module *module; |
239 | struct firmware stripped_fw; | 238 | struct firmware stripped_fw; |
240 | unsigned int safe_file; | 239 | unsigned int safe_file; |
@@ -317,11 +316,11 @@ free_uuid_list: | |||
317 | return ret; | 316 | return ret; |
318 | } | 317 | } |
319 | 318 | ||
320 | void skl_freeup_uuid_list(struct skl_sst *ctx) | 319 | void skl_freeup_uuid_list(struct skl_dev *skl) |
321 | { | 320 | { |
322 | struct uuid_module *uuid, *_uuid; | 321 | struct uuid_module *uuid, *_uuid; |
323 | 322 | ||
324 | list_for_each_entry_safe(uuid, _uuid, &ctx->uuid_list, list) { | 323 | list_for_each_entry_safe(uuid, _uuid, &skl->uuid_list, list) { |
325 | list_del(&uuid->list); | 324 | list_del(&uuid->list); |
326 | kfree(uuid); | 325 | kfree(uuid); |
327 | } | 326 | } |
@@ -355,16 +354,12 @@ int skl_dsp_strip_extended_manifest(struct firmware *fw) | |||
355 | } | 354 | } |
356 | 355 | ||
357 | int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, | 356 | int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, |
358 | struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp, | 357 | struct skl_dsp_loader_ops dsp_ops, struct skl_dev **dsp, |
359 | struct sst_dsp_device *skl_dev) | 358 | struct sst_dsp_device *skl_dev) |
360 | { | 359 | { |
361 | struct skl_sst *skl; | 360 | struct skl_dev *skl = *dsp; |
362 | struct sst_dsp *sst; | 361 | struct sst_dsp *sst; |
363 | 362 | ||
364 | skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); | ||
365 | if (skl == NULL) | ||
366 | return -ENOMEM; | ||
367 | |||
368 | skl->dev = dev; | 363 | skl->dev = dev; |
369 | skl_dev->thread_context = skl; | 364 | skl_dev->thread_context = skl; |
370 | INIT_LIST_HEAD(&skl->uuid_list); | 365 | INIT_LIST_HEAD(&skl->uuid_list); |
@@ -381,13 +376,11 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, | |||
381 | INIT_LIST_HEAD(&sst->module_list); | 376 | INIT_LIST_HEAD(&sst->module_list); |
382 | 377 | ||
383 | skl->is_first_boot = true; | 378 | skl->is_first_boot = true; |
384 | if (dsp) | ||
385 | *dsp = skl; | ||
386 | 379 | ||
387 | return 0; | 380 | return 0; |
388 | } | 381 | } |
389 | 382 | ||
390 | int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, | 383 | int skl_prepare_lib_load(struct skl_dev *skl, struct skl_lib_info *linfo, |
391 | struct firmware *stripped_fw, | 384 | struct firmware *stripped_fw, |
392 | unsigned int hdr_offset, int index) | 385 | unsigned int hdr_offset, int index) |
393 | { | 386 | { |
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 70c3a604c381..61a8e4756a2b 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include "../common/sst-dsp.h" | 16 | #include "../common/sst-dsp.h" |
17 | #include "../common/sst-dsp-priv.h" | 17 | #include "../common/sst-dsp-priv.h" |
18 | #include "../common/sst-ipc.h" | 18 | #include "../common/sst-ipc.h" |
19 | #include "skl-sst-ipc.h" | 19 | #include "skl.h" |
20 | 20 | ||
21 | #define SKL_BASEFW_TIMEOUT 300 | 21 | #define SKL_BASEFW_TIMEOUT 300 |
22 | #define SKL_INIT_TIMEOUT 1000 | 22 | #define SKL_INIT_TIMEOUT 1000 |
@@ -66,7 +66,7 @@ static int skl_transfer_firmware(struct sst_dsp *ctx, | |||
66 | static int skl_load_base_firmware(struct sst_dsp *ctx) | 66 | static int skl_load_base_firmware(struct sst_dsp *ctx) |
67 | { | 67 | { |
68 | int ret = 0, i; | 68 | int ret = 0, i; |
69 | struct skl_sst *skl = ctx->thread_context; | 69 | struct skl_dev *skl = ctx->thread_context; |
70 | struct firmware stripped_fw; | 70 | struct firmware stripped_fw; |
71 | u32 reg; | 71 | u32 reg; |
72 | 72 | ||
@@ -161,7 +161,7 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) | |||
161 | { | 161 | { |
162 | int ret; | 162 | int ret; |
163 | struct skl_ipc_dxstate_info dx; | 163 | struct skl_ipc_dxstate_info dx; |
164 | struct skl_sst *skl = ctx->thread_context; | 164 | struct skl_dev *skl = ctx->thread_context; |
165 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | 165 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
166 | 166 | ||
167 | /* If core0 is being turned on, we need to load the FW */ | 167 | /* If core0 is being turned on, we need to load the FW */ |
@@ -215,7 +215,7 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) | |||
215 | { | 215 | { |
216 | int ret; | 216 | int ret; |
217 | struct skl_ipc_dxstate_info dx; | 217 | struct skl_ipc_dxstate_info dx; |
218 | struct skl_sst *skl = ctx->thread_context; | 218 | struct skl_dev *skl = ctx->thread_context; |
219 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | 219 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
220 | 220 | ||
221 | dx.core_mask = core_mask; | 221 | dx.core_mask = core_mask; |
@@ -332,7 +332,7 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, | |||
332 | u32 size, u16 mod_id, u8 table_id, bool is_module) | 332 | u32 size, u16 mod_id, u8 table_id, bool is_module) |
333 | { | 333 | { |
334 | int ret, bytes_left, curr_pos; | 334 | int ret, bytes_left, curr_pos; |
335 | struct skl_sst *skl = ctx->thread_context; | 335 | struct skl_dev *skl = ctx->thread_context; |
336 | skl->mod_load_complete = false; | 336 | skl->mod_load_complete = false; |
337 | 337 | ||
338 | bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, data, size, false); | 338 | bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, data, size, false); |
@@ -384,7 +384,7 @@ out: | |||
384 | static int | 384 | static int |
385 | skl_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) | 385 | skl_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) |
386 | { | 386 | { |
387 | struct skl_sst *skl = ctx->thread_context; | 387 | struct skl_dev *skl = ctx->thread_context; |
388 | struct firmware stripped_fw; | 388 | struct firmware stripped_fw; |
389 | int ret, i; | 389 | int ret, i; |
390 | 390 | ||
@@ -413,8 +413,7 @@ static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid) | |||
413 | int ret = 0; | 413 | int ret = 0; |
414 | char mod_name[64]; /* guid str = 32 chars + 4 hyphens */ | 414 | char mod_name[64]; /* guid str = 32 chars + 4 hyphens */ |
415 | 415 | ||
416 | snprintf(mod_name, sizeof(mod_name), "%s%pUL%s", | 416 | snprintf(mod_name, sizeof(mod_name), "intel/dsp_fw_%pUL.bin", guid); |
417 | "intel/dsp_fw_", guid, ".bin"); | ||
418 | 417 | ||
419 | module_entry = skl_module_get_from_id(ctx, mod_id); | 418 | module_entry = skl_module_get_from_id(ctx, mod_id); |
420 | if (module_entry == NULL) { | 419 | if (module_entry == NULL) { |
@@ -443,7 +442,7 @@ static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid) | |||
443 | static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id) | 442 | static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id) |
444 | { | 443 | { |
445 | int usage_cnt; | 444 | int usage_cnt; |
446 | struct skl_sst *skl = ctx->thread_context; | 445 | struct skl_dev *skl = ctx->thread_context; |
447 | int ret = 0; | 446 | int ret = 0; |
448 | 447 | ||
449 | usage_cnt = skl_put_module(ctx, mod_id); | 448 | usage_cnt = skl_put_module(ctx, mod_id); |
@@ -518,9 +517,10 @@ static struct sst_dsp_device skl_dev = { | |||
518 | }; | 517 | }; |
519 | 518 | ||
520 | int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | 519 | int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, |
521 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp) | 520 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, |
521 | struct skl_dev **dsp) | ||
522 | { | 522 | { |
523 | struct skl_sst *skl; | 523 | struct skl_dev *skl; |
524 | struct sst_dsp *sst; | 524 | struct sst_dsp *sst; |
525 | int ret; | 525 | int ret; |
526 | 526 | ||
@@ -554,10 +554,10 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | |||
554 | } | 554 | } |
555 | EXPORT_SYMBOL_GPL(skl_sst_dsp_init); | 555 | EXPORT_SYMBOL_GPL(skl_sst_dsp_init); |
556 | 556 | ||
557 | int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) | 557 | int skl_sst_init_fw(struct device *dev, struct skl_dev *skl) |
558 | { | 558 | { |
559 | int ret; | 559 | int ret; |
560 | struct sst_dsp *sst = ctx->dsp; | 560 | struct sst_dsp *sst = skl->dsp; |
561 | 561 | ||
562 | ret = sst->fw_ops.load_fw(sst); | 562 | ret = sst->fw_ops.load_fw(sst); |
563 | if (ret < 0) { | 563 | if (ret < 0) { |
@@ -567,32 +567,32 @@ int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) | |||
567 | 567 | ||
568 | skl_dsp_init_core_state(sst); | 568 | skl_dsp_init_core_state(sst); |
569 | 569 | ||
570 | if (ctx->lib_count > 1) { | 570 | if (skl->lib_count > 1) { |
571 | ret = sst->fw_ops.load_library(sst, ctx->lib_info, | 571 | ret = sst->fw_ops.load_library(sst, skl->lib_info, |
572 | ctx->lib_count); | 572 | skl->lib_count); |
573 | if (ret < 0) { | 573 | if (ret < 0) { |
574 | dev_err(dev, "Load Library failed : %x\n", ret); | 574 | dev_err(dev, "Load Library failed : %x\n", ret); |
575 | return ret; | 575 | return ret; |
576 | } | 576 | } |
577 | } | 577 | } |
578 | ctx->is_first_boot = false; | 578 | skl->is_first_boot = false; |
579 | 579 | ||
580 | return 0; | 580 | return 0; |
581 | } | 581 | } |
582 | EXPORT_SYMBOL_GPL(skl_sst_init_fw); | 582 | EXPORT_SYMBOL_GPL(skl_sst_init_fw); |
583 | 583 | ||
584 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) | 584 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) |
585 | { | 585 | { |
586 | 586 | ||
587 | if (ctx->dsp->fw) | 587 | if (skl->dsp->fw) |
588 | release_firmware(ctx->dsp->fw); | 588 | release_firmware(skl->dsp->fw); |
589 | skl_clear_module_table(ctx->dsp); | 589 | skl_clear_module_table(skl->dsp); |
590 | skl_freeup_uuid_list(ctx); | 590 | skl_freeup_uuid_list(skl); |
591 | skl_ipc_free(&ctx->ipc); | 591 | skl_ipc_free(&skl->ipc); |
592 | ctx->dsp->ops->free(ctx->dsp); | 592 | skl->dsp->ops->free(skl->dsp); |
593 | if (ctx->boot_complete) { | 593 | if (skl->boot_complete) { |
594 | ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); | 594 | skl->dsp->cl_dev.ops.cl_cleanup_controller(skl->dsp); |
595 | skl_cldma_int_disable(ctx->dsp); | 595 | skl_cldma_int_disable(skl->dsp); |
596 | } | 596 | } |
597 | } | 597 | } |
598 | EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup); | 598 | EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup); |
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 6241e35213af..69cd7a81bf2a 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/firmware.h> | 13 | #include <linux/firmware.h> |
14 | #include <linux/uuid.h> | 14 | #include <linux/uuid.h> |
15 | #include <sound/intel-nhlt.h> | ||
15 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
16 | #include <sound/soc-topology.h> | 17 | #include <sound/soc-topology.h> |
17 | #include <uapi/sound/snd_sst_tokens.h> | 18 | #include <uapi/sound/snd_sst_tokens.h> |
@@ -45,9 +46,9 @@ static const int mic_quatro_list[][SKL_CH_QUATRO] = { | |||
45 | #define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ | 46 | #define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ |
46 | ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) | 47 | ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) |
47 | 48 | ||
48 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) | 49 | void skl_tplg_d0i3_get(struct skl_dev *skl, enum d0i3_capability caps) |
49 | { | 50 | { |
50 | struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; | 51 | struct skl_d0i3_data *d0i3 = &skl->d0i3; |
51 | 52 | ||
52 | switch (caps) { | 53 | switch (caps) { |
53 | case SKL_D0I3_NONE: | 54 | case SKL_D0I3_NONE: |
@@ -64,9 +65,9 @@ void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) | |||
64 | } | 65 | } |
65 | } | 66 | } |
66 | 67 | ||
67 | void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps) | 68 | void skl_tplg_d0i3_put(struct skl_dev *skl, enum d0i3_capability caps) |
68 | { | 69 | { |
69 | struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; | 70 | struct skl_d0i3_data *d0i3 = &skl->d0i3; |
70 | 71 | ||
71 | switch (caps) { | 72 | switch (caps) { |
72 | case SKL_D0I3_NONE: | 73 | case SKL_D0I3_NONE: |
@@ -109,118 +110,23 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w, | |||
109 | } | 110 | } |
110 | } | 111 | } |
111 | 112 | ||
112 | /* | 113 | static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg) |
113 | * Each pipelines needs memory to be allocated. Check if we have free memory | ||
114 | * from available pool. | ||
115 | */ | ||
116 | static bool skl_is_pipe_mem_avail(struct skl *skl, | ||
117 | struct skl_module_cfg *mconfig) | ||
118 | { | ||
119 | struct skl_sst *ctx = skl->skl_sst; | ||
120 | |||
121 | if (skl->resource.mem + mconfig->pipe->memory_pages > | ||
122 | skl->resource.max_mem) { | ||
123 | dev_err(ctx->dev, | ||
124 | "%s: module_id %d instance %d\n", __func__, | ||
125 | mconfig->id.module_id, | ||
126 | mconfig->id.instance_id); | ||
127 | dev_err(ctx->dev, | ||
128 | "exceeds ppl memory available %d mem %d\n", | ||
129 | skl->resource.max_mem, skl->resource.mem); | ||
130 | return false; | ||
131 | } else { | ||
132 | return true; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Add the mem to the mem pool. This is freed when pipe is deleted. | ||
138 | * Note: DSP does actual memory management we only keep track for complete | ||
139 | * pool | ||
140 | */ | ||
141 | static void skl_tplg_alloc_pipe_mem(struct skl *skl, | ||
142 | struct skl_module_cfg *mconfig) | ||
143 | { | ||
144 | skl->resource.mem += mconfig->pipe->memory_pages; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * Pipeline needs needs DSP CPU resources for computation, this is | ||
149 | * quantified in MCPS (Million Clocks Per Second) required for module/pipe | ||
150 | * | ||
151 | * Each pipelines needs mcps to be allocated. Check if we have mcps for this | ||
152 | * pipe. | ||
153 | */ | ||
154 | |||
155 | static bool skl_is_pipe_mcps_avail(struct skl *skl, | ||
156 | struct skl_module_cfg *mconfig) | ||
157 | { | ||
158 | struct skl_sst *ctx = skl->skl_sst; | ||
159 | u8 res_idx = mconfig->res_idx; | ||
160 | struct skl_module_res *res = &mconfig->module->resources[res_idx]; | ||
161 | |||
162 | if (skl->resource.mcps + res->cps > skl->resource.max_mcps) { | ||
163 | dev_err(ctx->dev, | ||
164 | "%s: module_id %d instance %d\n", __func__, | ||
165 | mconfig->id.module_id, mconfig->id.instance_id); | ||
166 | dev_err(ctx->dev, | ||
167 | "exceeds ppl mcps available %d > mem %d\n", | ||
168 | skl->resource.max_mcps, skl->resource.mcps); | ||
169 | return false; | ||
170 | } else { | ||
171 | return true; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | static void skl_tplg_alloc_pipe_mcps(struct skl *skl, | ||
176 | struct skl_module_cfg *mconfig) | ||
177 | { | ||
178 | u8 res_idx = mconfig->res_idx; | ||
179 | struct skl_module_res *res = &mconfig->module->resources[res_idx]; | ||
180 | |||
181 | skl->resource.mcps += res->cps; | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * Free the mcps when tearing down | ||
186 | */ | ||
187 | static void | ||
188 | skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) | ||
189 | { | ||
190 | u8 res_idx = mconfig->res_idx; | ||
191 | struct skl_module_res *res = &mconfig->module->resources[res_idx]; | ||
192 | |||
193 | skl->resource.mcps -= res->cps; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * Free the memory when tearing down | ||
198 | */ | ||
199 | static void | ||
200 | skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig) | ||
201 | { | ||
202 | skl->resource.mem -= mconfig->pipe->memory_pages; | ||
203 | } | ||
204 | |||
205 | |||
206 | static void skl_dump_mconfig(struct skl_sst *ctx, | ||
207 | struct skl_module_cfg *mcfg) | ||
208 | { | 114 | { |
209 | struct skl_module_iface *iface = &mcfg->module->formats[0]; | 115 | struct skl_module_iface *iface = &mcfg->module->formats[0]; |
210 | 116 | ||
211 | dev_dbg(ctx->dev, "Dumping config\n"); | 117 | dev_dbg(skl->dev, "Dumping config\n"); |
212 | dev_dbg(ctx->dev, "Input Format:\n"); | 118 | dev_dbg(skl->dev, "Input Format:\n"); |
213 | dev_dbg(ctx->dev, "channels = %d\n", iface->inputs[0].fmt.channels); | 119 | dev_dbg(skl->dev, "channels = %d\n", iface->inputs[0].fmt.channels); |
214 | dev_dbg(ctx->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); | 120 | dev_dbg(skl->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); |
215 | dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); | 121 | dev_dbg(skl->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); |
216 | dev_dbg(ctx->dev, "valid bit depth = %d\n", | 122 | dev_dbg(skl->dev, "valid bit depth = %d\n", |
217 | iface->inputs[0].fmt.valid_bit_depth); | 123 | iface->inputs[0].fmt.valid_bit_depth); |
218 | dev_dbg(ctx->dev, "Output Format:\n"); | 124 | dev_dbg(skl->dev, "Output Format:\n"); |
219 | dev_dbg(ctx->dev, "channels = %d\n", iface->outputs[0].fmt.channels); | 125 | dev_dbg(skl->dev, "channels = %d\n", iface->outputs[0].fmt.channels); |
220 | dev_dbg(ctx->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); | 126 | dev_dbg(skl->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); |
221 | dev_dbg(ctx->dev, "valid bit depth = %d\n", | 127 | dev_dbg(skl->dev, "valid bit depth = %d\n", |
222 | iface->outputs[0].fmt.valid_bit_depth); | 128 | iface->outputs[0].fmt.valid_bit_depth); |
223 | dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); | 129 | dev_dbg(skl->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); |
224 | } | 130 | } |
225 | 131 | ||
226 | static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) | 132 | static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) |
@@ -322,7 +228,7 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, | |||
322 | * params, so once we have calculate params, we need buffer calculation as | 228 | * params, so once we have calculate params, we need buffer calculation as |
323 | * well. | 229 | * well. |
324 | */ | 230 | */ |
325 | static void skl_tplg_update_buffer_size(struct skl_sst *ctx, | 231 | static void skl_tplg_update_buffer_size(struct skl_dev *skl, |
326 | struct skl_module_cfg *mcfg) | 232 | struct skl_module_cfg *mcfg) |
327 | { | 233 | { |
328 | int multiplier = 1; | 234 | int multiplier = 1; |
@@ -374,13 +280,12 @@ static u8 skl_tplg_be_dev_type(int dev_type) | |||
374 | } | 280 | } |
375 | 281 | ||
376 | static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, | 282 | static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, |
377 | struct skl_sst *ctx) | 283 | struct skl_dev *skl) |
378 | { | 284 | { |
379 | struct skl_module_cfg *m_cfg = w->priv; | 285 | struct skl_module_cfg *m_cfg = w->priv; |
380 | int link_type, dir; | 286 | int link_type, dir; |
381 | u32 ch, s_freq, s_fmt; | 287 | u32 ch, s_freq, s_fmt; |
382 | struct nhlt_specific_cfg *cfg; | 288 | struct nhlt_specific_cfg *cfg; |
383 | struct skl *skl = get_skl_ctx(ctx->dev); | ||
384 | u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); | 289 | u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); |
385 | int fmt_idx = m_cfg->fmt_idx; | 290 | int fmt_idx = m_cfg->fmt_idx; |
386 | struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; | 291 | struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; |
@@ -389,7 +294,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, | |||
389 | if (m_cfg->formats_config.caps_size > 0) | 294 | if (m_cfg->formats_config.caps_size > 0) |
390 | return 0; | 295 | return 0; |
391 | 296 | ||
392 | dev_dbg(ctx->dev, "Applying default cfg blob\n"); | 297 | dev_dbg(skl->dev, "Applying default cfg blob\n"); |
393 | switch (m_cfg->dev_type) { | 298 | switch (m_cfg->dev_type) { |
394 | case SKL_DEVICE_DMIC: | 299 | case SKL_DEVICE_DMIC: |
395 | link_type = NHLT_LINK_DMIC; | 300 | link_type = NHLT_LINK_DMIC; |
@@ -425,9 +330,9 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, | |||
425 | m_cfg->formats_config.caps_size = cfg->size; | 330 | m_cfg->formats_config.caps_size = cfg->size; |
426 | m_cfg->formats_config.caps = (u32 *) &cfg->caps; | 331 | m_cfg->formats_config.caps = (u32 *) &cfg->caps; |
427 | } else { | 332 | } else { |
428 | dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n", | 333 | dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n", |
429 | m_cfg->vbus_id, link_type, dir); | 334 | m_cfg->vbus_id, link_type, dir); |
430 | dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n", | 335 | dev_err(skl->dev, "PCM: ch %d, freq %d, fmt %d\n", |
431 | ch, s_freq, s_fmt); | 336 | ch, s_freq, s_fmt); |
432 | return -EIO; | 337 | return -EIO; |
433 | } | 338 | } |
@@ -436,7 +341,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, | |||
436 | } | 341 | } |
437 | 342 | ||
438 | static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, | 343 | static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, |
439 | struct skl_sst *ctx) | 344 | struct skl_dev *skl) |
440 | { | 345 | { |
441 | struct skl_module_cfg *m_cfg = w->priv; | 346 | struct skl_module_cfg *m_cfg = w->priv; |
442 | struct skl_pipe_params *params = m_cfg->pipe->p_params; | 347 | struct skl_pipe_params *params = m_cfg->pipe->p_params; |
@@ -446,10 +351,10 @@ static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, | |||
446 | if (!m_cfg->params_fixup) | 351 | if (!m_cfg->params_fixup) |
447 | return; | 352 | return; |
448 | 353 | ||
449 | dev_dbg(ctx->dev, "Mconfig for widget=%s BEFORE updation\n", | 354 | dev_dbg(skl->dev, "Mconfig for widget=%s BEFORE updation\n", |
450 | w->name); | 355 | w->name); |
451 | 356 | ||
452 | skl_dump_mconfig(ctx, m_cfg); | 357 | skl_dump_mconfig(skl, m_cfg); |
453 | 358 | ||
454 | if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) | 359 | if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) |
455 | is_fe = true; | 360 | is_fe = true; |
@@ -457,12 +362,12 @@ static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, | |||
457 | is_fe = false; | 362 | is_fe = false; |
458 | 363 | ||
459 | skl_tplg_update_params_fixup(m_cfg, params, is_fe); | 364 | skl_tplg_update_params_fixup(m_cfg, params, is_fe); |
460 | skl_tplg_update_buffer_size(ctx, m_cfg); | 365 | skl_tplg_update_buffer_size(skl, m_cfg); |
461 | 366 | ||
462 | dev_dbg(ctx->dev, "Mconfig for widget=%s AFTER updation\n", | 367 | dev_dbg(skl->dev, "Mconfig for widget=%s AFTER updation\n", |
463 | w->name); | 368 | w->name); |
464 | 369 | ||
465 | skl_dump_mconfig(ctx, m_cfg); | 370 | skl_dump_mconfig(skl, m_cfg); |
466 | } | 371 | } |
467 | 372 | ||
468 | /* | 373 | /* |
@@ -471,7 +376,7 @@ static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, | |||
471 | * set module params will be done after module is initialised. | 376 | * set module params will be done after module is initialised. |
472 | */ | 377 | */ |
473 | static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, | 378 | static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, |
474 | struct skl_sst *ctx) | 379 | struct skl_dev *skl) |
475 | { | 380 | { |
476 | int i, ret; | 381 | int i, ret; |
477 | struct skl_module_cfg *mconfig = w->priv; | 382 | struct skl_module_cfg *mconfig = w->priv; |
@@ -483,7 +388,7 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, | |||
483 | if (mconfig->formats_config.caps_size > 0 && | 388 | if (mconfig->formats_config.caps_size > 0 && |
484 | mconfig->formats_config.set_params == SKL_PARAM_SET) { | 389 | mconfig->formats_config.set_params == SKL_PARAM_SET) { |
485 | sp_cfg = &mconfig->formats_config; | 390 | sp_cfg = &mconfig->formats_config; |
486 | ret = skl_set_module_params(ctx, sp_cfg->caps, | 391 | ret = skl_set_module_params(skl, sp_cfg->caps, |
487 | sp_cfg->caps_size, | 392 | sp_cfg->caps_size, |
488 | sp_cfg->param_id, mconfig); | 393 | sp_cfg->param_id, mconfig); |
489 | if (ret < 0) | 394 | if (ret < 0) |
@@ -497,7 +402,7 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, | |||
497 | bc = (struct skl_algo_data *)sb->dobj.private; | 402 | bc = (struct skl_algo_data *)sb->dobj.private; |
498 | 403 | ||
499 | if (bc->set_params == SKL_PARAM_SET) { | 404 | if (bc->set_params == SKL_PARAM_SET) { |
500 | ret = skl_set_module_params(ctx, | 405 | ret = skl_set_module_params(skl, |
501 | (u32 *)bc->params, bc->size, | 406 | (u32 *)bc->params, bc->size, |
502 | bc->param_id, mconfig); | 407 | bc->param_id, mconfig); |
503 | if (ret < 0) | 408 | if (ret < 0) |
@@ -542,15 +447,15 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) | |||
542 | return 0; | 447 | return 0; |
543 | } | 448 | } |
544 | 449 | ||
545 | static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, | 450 | static int skl_tplg_module_prepare(struct skl_dev *skl, struct skl_pipe *pipe, |
546 | struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) | 451 | struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) |
547 | { | 452 | { |
548 | switch (mcfg->dev_type) { | 453 | switch (mcfg->dev_type) { |
549 | case SKL_DEVICE_HDAHOST: | 454 | case SKL_DEVICE_HDAHOST: |
550 | return skl_pcm_host_dma_prepare(ctx->dev, pipe->p_params); | 455 | return skl_pcm_host_dma_prepare(skl->dev, pipe->p_params); |
551 | 456 | ||
552 | case SKL_DEVICE_HDALINK: | 457 | case SKL_DEVICE_HDALINK: |
553 | return skl_pcm_link_dma_prepare(ctx->dev, pipe->p_params); | 458 | return skl_pcm_link_dma_prepare(skl->dev, pipe->p_params); |
554 | } | 459 | } |
555 | 460 | ||
556 | return 0; | 461 | return 0; |
@@ -562,12 +467,11 @@ static int skl_tplg_module_prepare(struct skl_sst *ctx, struct skl_pipe *pipe, | |||
562 | * skl_init_module() routine, so invoke that for all modules in a pipeline | 467 | * skl_init_module() routine, so invoke that for all modules in a pipeline |
563 | */ | 468 | */ |
564 | static int | 469 | static int |
565 | skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) | 470 | skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) |
566 | { | 471 | { |
567 | struct skl_pipe_module *w_module; | 472 | struct skl_pipe_module *w_module; |
568 | struct snd_soc_dapm_widget *w; | 473 | struct snd_soc_dapm_widget *w; |
569 | struct skl_module_cfg *mconfig; | 474 | struct skl_module_cfg *mconfig; |
570 | struct skl_sst *ctx = skl->skl_sst; | ||
571 | u8 cfg_idx; | 475 | u8 cfg_idx; |
572 | int ret = 0; | 476 | int ret = 0; |
573 | 477 | ||
@@ -578,7 +482,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) | |||
578 | 482 | ||
579 | /* check if module ids are populated */ | 483 | /* check if module ids are populated */ |
580 | if (mconfig->id.module_id < 0) { | 484 | if (mconfig->id.module_id < 0) { |
581 | dev_err(skl->skl_sst->dev, | 485 | dev_err(skl->dev, |
582 | "module %pUL id not populated\n", | 486 | "module %pUL id not populated\n", |
583 | (guid_t *)mconfig->guid); | 487 | (guid_t *)mconfig->guid); |
584 | return -EIO; | 488 | return -EIO; |
@@ -588,12 +492,8 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) | |||
588 | mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; | 492 | mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; |
589 | mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; | 493 | mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; |
590 | 494 | ||
591 | /* check resource available */ | 495 | if (mconfig->module->loadable && skl->dsp->fw_ops.load_mod) { |
592 | if (!skl_is_pipe_mcps_avail(skl, mconfig)) | 496 | ret = skl->dsp->fw_ops.load_mod(skl->dsp, |
593 | return -ENOMEM; | ||
594 | |||
595 | if (mconfig->module->loadable && ctx->dsp->fw_ops.load_mod) { | ||
596 | ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, | ||
597 | mconfig->id.module_id, mconfig->guid); | 497 | mconfig->id.module_id, mconfig->guid); |
598 | if (ret < 0) | 498 | if (ret < 0) |
599 | return ret; | 499 | return ret; |
@@ -602,50 +502,50 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) | |||
602 | } | 502 | } |
603 | 503 | ||
604 | /* prepare the DMA if the module is gateway cpr */ | 504 | /* prepare the DMA if the module is gateway cpr */ |
605 | ret = skl_tplg_module_prepare(ctx, pipe, w, mconfig); | 505 | ret = skl_tplg_module_prepare(skl, pipe, w, mconfig); |
606 | if (ret < 0) | 506 | if (ret < 0) |
607 | return ret; | 507 | return ret; |
608 | 508 | ||
609 | /* update blob if blob is null for be with default value */ | 509 | /* update blob if blob is null for be with default value */ |
610 | skl_tplg_update_be_blob(w, ctx); | 510 | skl_tplg_update_be_blob(w, skl); |
611 | 511 | ||
612 | /* | 512 | /* |
613 | * apply fix/conversion to module params based on | 513 | * apply fix/conversion to module params based on |
614 | * FE/BE params | 514 | * FE/BE params |
615 | */ | 515 | */ |
616 | skl_tplg_update_module_params(w, ctx); | 516 | skl_tplg_update_module_params(w, skl); |
617 | uuid_mod = (guid_t *)mconfig->guid; | 517 | uuid_mod = (guid_t *)mconfig->guid; |
618 | mconfig->id.pvt_id = skl_get_pvt_id(ctx, uuid_mod, | 518 | mconfig->id.pvt_id = skl_get_pvt_id(skl, uuid_mod, |
619 | mconfig->id.instance_id); | 519 | mconfig->id.instance_id); |
620 | if (mconfig->id.pvt_id < 0) | 520 | if (mconfig->id.pvt_id < 0) |
621 | return ret; | 521 | return ret; |
622 | skl_tplg_set_module_init_data(w); | 522 | skl_tplg_set_module_init_data(w); |
623 | 523 | ||
624 | ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id); | 524 | ret = skl_dsp_get_core(skl->dsp, mconfig->core_id); |
625 | if (ret < 0) { | 525 | if (ret < 0) { |
626 | dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n", | 526 | dev_err(skl->dev, "Failed to wake up core %d ret=%d\n", |
627 | mconfig->core_id, ret); | 527 | mconfig->core_id, ret); |
628 | return ret; | 528 | return ret; |
629 | } | 529 | } |
630 | 530 | ||
631 | ret = skl_init_module(ctx, mconfig); | 531 | ret = skl_init_module(skl, mconfig); |
632 | if (ret < 0) { | 532 | if (ret < 0) { |
633 | skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); | 533 | skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); |
634 | goto err; | 534 | goto err; |
635 | } | 535 | } |
636 | skl_tplg_alloc_pipe_mcps(skl, mconfig); | 536 | |
637 | ret = skl_tplg_set_module_params(w, ctx); | 537 | ret = skl_tplg_set_module_params(w, skl); |
638 | if (ret < 0) | 538 | if (ret < 0) |
639 | goto err; | 539 | goto err; |
640 | } | 540 | } |
641 | 541 | ||
642 | return 0; | 542 | return 0; |
643 | err: | 543 | err: |
644 | skl_dsp_put_core(ctx->dsp, mconfig->core_id); | 544 | skl_dsp_put_core(skl->dsp, mconfig->core_id); |
645 | return ret; | 545 | return ret; |
646 | } | 546 | } |
647 | 547 | ||
648 | static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, | 548 | static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, |
649 | struct skl_pipe *pipe) | 549 | struct skl_pipe *pipe) |
650 | { | 550 | { |
651 | int ret = 0; | 551 | int ret = 0; |
@@ -657,19 +557,19 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, | |||
657 | mconfig = w_module->w->priv; | 557 | mconfig = w_module->w->priv; |
658 | uuid_mod = (guid_t *)mconfig->guid; | 558 | uuid_mod = (guid_t *)mconfig->guid; |
659 | 559 | ||
660 | if (mconfig->module->loadable && ctx->dsp->fw_ops.unload_mod && | 560 | if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod && |
661 | mconfig->m_state > SKL_MODULE_UNINIT) { | 561 | mconfig->m_state > SKL_MODULE_UNINIT) { |
662 | ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, | 562 | ret = skl->dsp->fw_ops.unload_mod(skl->dsp, |
663 | mconfig->id.module_id); | 563 | mconfig->id.module_id); |
664 | if (ret < 0) | 564 | if (ret < 0) |
665 | return -EIO; | 565 | return -EIO; |
666 | } | 566 | } |
667 | skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); | 567 | skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); |
668 | 568 | ||
669 | ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id); | 569 | ret = skl_dsp_put_core(skl->dsp, mconfig->core_id); |
670 | if (ret < 0) { | 570 | if (ret < 0) { |
671 | /* don't return; continue with other modules */ | 571 | /* don't return; continue with other modules */ |
672 | dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n", | 572 | dev_err(skl->dev, "Failed to sleep core %d ret=%d\n", |
673 | mconfig->core_id, ret); | 573 | mconfig->core_id, ret); |
674 | } | 574 | } |
675 | } | 575 | } |
@@ -686,9 +586,8 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, | |||
686 | * 0th configuratation by default for such pipes. | 586 | * 0th configuratation by default for such pipes. |
687 | */ | 587 | */ |
688 | static int | 588 | static int |
689 | skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) | 589 | skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) |
690 | { | 590 | { |
691 | struct skl_sst *ctx = skl->skl_sst; | ||
692 | struct skl_pipe *pipe = mconfig->pipe; | 591 | struct skl_pipe *pipe = mconfig->pipe; |
693 | struct skl_pipe_params *params = pipe->p_params; | 592 | struct skl_pipe_params *params = pipe->p_params; |
694 | struct skl_path_config *pconfig = &pipe->configs[0]; | 593 | struct skl_path_config *pconfig = &pipe->configs[0]; |
@@ -702,7 +601,7 @@ skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) | |||
702 | } | 601 | } |
703 | 602 | ||
704 | if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { | 603 | if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { |
705 | dev_dbg(ctx->dev, "No conn_type detected, take 0th config\n"); | 604 | dev_dbg(skl->dev, "No conn_type detected, take 0th config\n"); |
706 | pipe->cur_config_idx = 0; | 605 | pipe->cur_config_idx = 0; |
707 | pipe->memory_pages = pconfig->mem_pages; | 606 | pipe->memory_pages = pconfig->mem_pages; |
708 | 607 | ||
@@ -726,13 +625,13 @@ skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) | |||
726 | fmt->channels, fmt->freq, fmt->bps)) { | 625 | fmt->channels, fmt->freq, fmt->bps)) { |
727 | pipe->cur_config_idx = i; | 626 | pipe->cur_config_idx = i; |
728 | pipe->memory_pages = pconfig->mem_pages; | 627 | pipe->memory_pages = pconfig->mem_pages; |
729 | dev_dbg(ctx->dev, "Using pipe config: %d\n", i); | 628 | dev_dbg(skl->dev, "Using pipe config: %d\n", i); |
730 | 629 | ||
731 | return 0; | 630 | return 0; |
732 | } | 631 | } |
733 | } | 632 | } |
734 | 633 | ||
735 | dev_err(ctx->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", | 634 | dev_err(skl->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", |
736 | params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); | 635 | params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); |
737 | return -EINVAL; | 636 | return -EINVAL; |
738 | } | 637 | } |
@@ -740,44 +639,32 @@ skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) | |||
740 | /* | 639 | /* |
741 | * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we | 640 | * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we |
742 | * need create the pipeline. So we do following: | 641 | * need create the pipeline. So we do following: |
743 | * - check the resources | ||
744 | * - Create the pipeline | 642 | * - Create the pipeline |
745 | * - Initialize the modules in pipeline | 643 | * - Initialize the modules in pipeline |
746 | * - finally bind all modules together | 644 | * - finally bind all modules together |
747 | */ | 645 | */ |
748 | static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | 646 | static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, |
749 | struct skl *skl) | 647 | struct skl_dev *skl) |
750 | { | 648 | { |
751 | int ret; | 649 | int ret; |
752 | struct skl_module_cfg *mconfig = w->priv; | 650 | struct skl_module_cfg *mconfig = w->priv; |
753 | struct skl_pipe_module *w_module; | 651 | struct skl_pipe_module *w_module; |
754 | struct skl_pipe *s_pipe = mconfig->pipe; | 652 | struct skl_pipe *s_pipe = mconfig->pipe; |
755 | struct skl_module_cfg *src_module = NULL, *dst_module, *module; | 653 | struct skl_module_cfg *src_module = NULL, *dst_module, *module; |
756 | struct skl_sst *ctx = skl->skl_sst; | ||
757 | struct skl_module_deferred_bind *modules; | 654 | struct skl_module_deferred_bind *modules; |
758 | 655 | ||
759 | ret = skl_tplg_get_pipe_config(skl, mconfig); | 656 | ret = skl_tplg_get_pipe_config(skl, mconfig); |
760 | if (ret < 0) | 657 | if (ret < 0) |
761 | return ret; | 658 | return ret; |
762 | 659 | ||
763 | /* check resource available */ | ||
764 | if (!skl_is_pipe_mcps_avail(skl, mconfig)) | ||
765 | return -EBUSY; | ||
766 | |||
767 | if (!skl_is_pipe_mem_avail(skl, mconfig)) | ||
768 | return -ENOMEM; | ||
769 | |||
770 | /* | 660 | /* |
771 | * Create a list of modules for pipe. | 661 | * Create a list of modules for pipe. |
772 | * This list contains modules from source to sink | 662 | * This list contains modules from source to sink |
773 | */ | 663 | */ |
774 | ret = skl_create_pipeline(ctx, mconfig->pipe); | 664 | ret = skl_create_pipeline(skl, mconfig->pipe); |
775 | if (ret < 0) | 665 | if (ret < 0) |
776 | return ret; | 666 | return ret; |
777 | 667 | ||
778 | skl_tplg_alloc_pipe_mem(skl, mconfig); | ||
779 | skl_tplg_alloc_pipe_mcps(skl, mconfig); | ||
780 | |||
781 | /* Init all pipe modules from source to sink */ | 668 | /* Init all pipe modules from source to sink */ |
782 | ret = skl_tplg_init_pipe_modules(skl, s_pipe); | 669 | ret = skl_tplg_init_pipe_modules(skl, s_pipe); |
783 | if (ret < 0) | 670 | if (ret < 0) |
@@ -792,7 +679,7 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | |||
792 | continue; | 679 | continue; |
793 | } | 680 | } |
794 | 681 | ||
795 | ret = skl_bind_modules(ctx, src_module, dst_module); | 682 | ret = skl_bind_modules(skl, src_module, dst_module); |
796 | if (ret < 0) | 683 | if (ret < 0) |
797 | return ret; | 684 | return ret; |
798 | 685 | ||
@@ -810,7 +697,7 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | |||
810 | list_for_each_entry(modules, &skl->bind_list, node) { | 697 | list_for_each_entry(modules, &skl->bind_list, node) { |
811 | module = w_module->w->priv; | 698 | module = w_module->w->priv; |
812 | if (modules->dst == module) | 699 | if (modules->dst == module) |
813 | skl_bind_modules(ctx, modules->src, | 700 | skl_bind_modules(skl, modules->src, |
814 | modules->dst); | 701 | modules->dst); |
815 | } | 702 | } |
816 | } | 703 | } |
@@ -818,7 +705,7 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | |||
818 | return 0; | 705 | return 0; |
819 | } | 706 | } |
820 | 707 | ||
821 | static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, | 708 | static int skl_fill_sink_instance_id(struct skl_dev *skl, u32 *params, |
822 | int size, struct skl_module_cfg *mcfg) | 709 | int size, struct skl_module_cfg *mcfg) |
823 | { | 710 | { |
824 | int i, pvt_id; | 711 | int i, pvt_id; |
@@ -829,7 +716,7 @@ static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, | |||
829 | struct skl_mod_inst_map *inst = kpb_params->u.map; | 716 | struct skl_mod_inst_map *inst = kpb_params->u.map; |
830 | 717 | ||
831 | for (i = 0; i < kpb_params->num_modules; i++) { | 718 | for (i = 0; i < kpb_params->num_modules; i++) { |
832 | pvt_id = skl_get_pvt_instance_id_map(ctx, inst->mod_id, | 719 | pvt_id = skl_get_pvt_instance_id_map(skl, inst->mod_id, |
833 | inst->inst_id); | 720 | inst->inst_id); |
834 | if (pvt_id < 0) | 721 | if (pvt_id < 0) |
835 | return -EINVAL; | 722 | return -EINVAL; |
@@ -849,7 +736,7 @@ static int skl_fill_sink_instance_id(struct skl_sst *ctx, u32 *params, | |||
849 | * send params after binding | 736 | * send params after binding |
850 | */ | 737 | */ |
851 | static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, | 738 | static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, |
852 | struct skl_module_cfg *mcfg, struct skl_sst *ctx) | 739 | struct skl_module_cfg *mcfg, struct skl_dev *skl) |
853 | { | 740 | { |
854 | int i, ret; | 741 | int i, ret; |
855 | struct skl_module_cfg *mconfig = w->priv; | 742 | struct skl_module_cfg *mconfig = w->priv; |
@@ -876,7 +763,7 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, | |||
876 | if (mconfig->formats_config.caps_size > 0 && | 763 | if (mconfig->formats_config.caps_size > 0 && |
877 | mconfig->formats_config.set_params == SKL_PARAM_BIND) { | 764 | mconfig->formats_config.set_params == SKL_PARAM_BIND) { |
878 | sp_cfg = &mconfig->formats_config; | 765 | sp_cfg = &mconfig->formats_config; |
879 | ret = skl_set_module_params(ctx, sp_cfg->caps, | 766 | ret = skl_set_module_params(skl, sp_cfg->caps, |
880 | sp_cfg->caps_size, | 767 | sp_cfg->caps_size, |
881 | sp_cfg->param_id, mconfig); | 768 | sp_cfg->param_id, mconfig); |
882 | if (ret < 0) | 769 | if (ret < 0) |
@@ -894,10 +781,10 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, | |||
894 | if (!params) | 781 | if (!params) |
895 | return -ENOMEM; | 782 | return -ENOMEM; |
896 | 783 | ||
897 | skl_fill_sink_instance_id(ctx, params, bc->max, | 784 | skl_fill_sink_instance_id(skl, params, bc->max, |
898 | mconfig); | 785 | mconfig); |
899 | 786 | ||
900 | ret = skl_set_module_params(ctx, params, | 787 | ret = skl_set_module_params(skl, params, |
901 | bc->max, bc->param_id, mconfig); | 788 | bc->max, bc->param_id, mconfig); |
902 | kfree(params); | 789 | kfree(params); |
903 | 790 | ||
@@ -910,11 +797,11 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, | |||
910 | return 0; | 797 | return 0; |
911 | } | 798 | } |
912 | 799 | ||
913 | static int skl_get_module_id(struct skl_sst *ctx, guid_t *uuid) | 800 | static int skl_get_module_id(struct skl_dev *skl, guid_t *uuid) |
914 | { | 801 | { |
915 | struct uuid_module *module; | 802 | struct uuid_module *module; |
916 | 803 | ||
917 | list_for_each_entry(module, &ctx->uuid_list, list) { | 804 | list_for_each_entry(module, &skl->uuid_list, list) { |
918 | if (guid_equal(uuid, &module->uuid)) | 805 | if (guid_equal(uuid, &module->uuid)) |
919 | return module->id; | 806 | return module->id; |
920 | } | 807 | } |
@@ -922,7 +809,7 @@ static int skl_get_module_id(struct skl_sst *ctx, guid_t *uuid) | |||
922 | return -EINVAL; | 809 | return -EINVAL; |
923 | } | 810 | } |
924 | 811 | ||
925 | static int skl_tplg_find_moduleid_from_uuid(struct skl *skl, | 812 | static int skl_tplg_find_moduleid_from_uuid(struct skl_dev *skl, |
926 | const struct snd_kcontrol_new *k) | 813 | const struct snd_kcontrol_new *k) |
927 | { | 814 | { |
928 | struct soc_bytes_ext *sb = (void *) k->private_value; | 815 | struct soc_bytes_ext *sb = (void *) k->private_value; |
@@ -942,7 +829,7 @@ static int skl_tplg_find_moduleid_from_uuid(struct skl *skl, | |||
942 | params->num_modules = uuid_params->num_modules; | 829 | params->num_modules = uuid_params->num_modules; |
943 | 830 | ||
944 | for (i = 0; i < uuid_params->num_modules; i++) { | 831 | for (i = 0; i < uuid_params->num_modules; i++) { |
945 | module_id = skl_get_module_id(skl->skl_sst, | 832 | module_id = skl_get_module_id(skl, |
946 | &uuid_params->u.map_uuid[i].mod_uuid); | 833 | &uuid_params->u.map_uuid[i].mod_uuid); |
947 | if (module_id < 0) { | 834 | if (module_id < 0) { |
948 | devm_kfree(bus->dev, params); | 835 | devm_kfree(bus->dev, params); |
@@ -966,7 +853,7 @@ static int skl_tplg_find_moduleid_from_uuid(struct skl *skl, | |||
966 | * Retrieve the module id from UUID mentioned in the | 853 | * Retrieve the module id from UUID mentioned in the |
967 | * post bind params | 854 | * post bind params |
968 | */ | 855 | */ |
969 | void skl_tplg_add_moduleid_in_bind_params(struct skl *skl, | 856 | void skl_tplg_add_moduleid_in_bind_params(struct skl_dev *skl, |
970 | struct snd_soc_dapm_widget *w) | 857 | struct snd_soc_dapm_widget *w) |
971 | { | 858 | { |
972 | struct skl_module_cfg *mconfig = w->priv; | 859 | struct skl_module_cfg *mconfig = w->priv; |
@@ -985,12 +872,12 @@ void skl_tplg_add_moduleid_in_bind_params(struct skl *skl, | |||
985 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && | 872 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && |
986 | (skl_tplg_find_moduleid_from_uuid(skl, | 873 | (skl_tplg_find_moduleid_from_uuid(skl, |
987 | &w->kcontrol_news[i]) < 0)) | 874 | &w->kcontrol_news[i]) < 0)) |
988 | dev_err(skl->skl_sst->dev, | 875 | dev_err(skl->dev, |
989 | "%s: invalid kpb post bind params\n", | 876 | "%s: invalid kpb post bind params\n", |
990 | __func__); | 877 | __func__); |
991 | } | 878 | } |
992 | 879 | ||
993 | static int skl_tplg_module_add_deferred_bind(struct skl *skl, | 880 | static int skl_tplg_module_add_deferred_bind(struct skl_dev *skl, |
994 | struct skl_module_cfg *src, struct skl_module_cfg *dst) | 881 | struct skl_module_cfg *src, struct skl_module_cfg *dst) |
995 | { | 882 | { |
996 | struct skl_module_deferred_bind *m_list, *modules; | 883 | struct skl_module_deferred_bind *m_list, *modules; |
@@ -1028,26 +915,27 @@ static int skl_tplg_module_add_deferred_bind(struct skl *skl, | |||
1028 | } | 915 | } |
1029 | 916 | ||
1030 | static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, | 917 | static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, |
1031 | struct skl *skl, | 918 | struct skl_dev *skl, |
1032 | struct snd_soc_dapm_widget *src_w, | 919 | struct snd_soc_dapm_widget *src_w, |
1033 | struct skl_module_cfg *src_mconfig) | 920 | struct skl_module_cfg *src_mconfig) |
1034 | { | 921 | { |
1035 | struct snd_soc_dapm_path *p; | 922 | struct snd_soc_dapm_path *p; |
1036 | struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; | 923 | struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; |
1037 | struct skl_module_cfg *sink_mconfig; | 924 | struct skl_module_cfg *sink_mconfig; |
1038 | struct skl_sst *ctx = skl->skl_sst; | ||
1039 | int ret; | 925 | int ret; |
1040 | 926 | ||
1041 | snd_soc_dapm_widget_for_each_sink_path(w, p) { | 927 | snd_soc_dapm_widget_for_each_sink_path(w, p) { |
1042 | if (!p->connect) | 928 | if (!p->connect) |
1043 | continue; | 929 | continue; |
1044 | 930 | ||
1045 | dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name); | 931 | dev_dbg(skl->dev, |
1046 | dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name); | 932 | "%s: src widget=%s\n", __func__, w->name); |
933 | dev_dbg(skl->dev, | ||
934 | "%s: sink widget=%s\n", __func__, p->sink->name); | ||
1047 | 935 | ||
1048 | next_sink = p->sink; | 936 | next_sink = p->sink; |
1049 | 937 | ||
1050 | if (!is_skl_dsp_widget_type(p->sink, ctx->dev)) | 938 | if (!is_skl_dsp_widget_type(p->sink, skl->dev)) |
1051 | return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); | 939 | return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); |
1052 | 940 | ||
1053 | /* | 941 | /* |
@@ -1056,7 +944,7 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, | |||
1056 | * they are ones used for SKL so check that first | 944 | * they are ones used for SKL so check that first |
1057 | */ | 945 | */ |
1058 | if ((p->sink->priv != NULL) && | 946 | if ((p->sink->priv != NULL) && |
1059 | is_skl_dsp_widget_type(p->sink, ctx->dev)) { | 947 | is_skl_dsp_widget_type(p->sink, skl->dev)) { |
1060 | 948 | ||
1061 | sink = p->sink; | 949 | sink = p->sink; |
1062 | sink_mconfig = sink->priv; | 950 | sink_mconfig = sink->priv; |
@@ -1088,19 +976,21 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, | |||
1088 | continue; | 976 | continue; |
1089 | 977 | ||
1090 | /* Bind source to sink, mixin is always source */ | 978 | /* Bind source to sink, mixin is always source */ |
1091 | ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); | 979 | ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); |
1092 | if (ret) | 980 | if (ret) |
1093 | return ret; | 981 | return ret; |
1094 | 982 | ||
1095 | /* set module params after bind */ | 983 | /* set module params after bind */ |
1096 | skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx); | 984 | skl_tplg_set_module_bind_params(src_w, |
1097 | skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); | 985 | src_mconfig, skl); |
986 | skl_tplg_set_module_bind_params(sink, | ||
987 | sink_mconfig, skl); | ||
1098 | 988 | ||
1099 | /* Start sinks pipe first */ | 989 | /* Start sinks pipe first */ |
1100 | if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { | 990 | if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { |
1101 | if (sink_mconfig->pipe->conn_type != | 991 | if (sink_mconfig->pipe->conn_type != |
1102 | SKL_PIPE_CONN_TYPE_FE) | 992 | SKL_PIPE_CONN_TYPE_FE) |
1103 | ret = skl_run_pipe(ctx, | 993 | ret = skl_run_pipe(skl, |
1104 | sink_mconfig->pipe); | 994 | sink_mconfig->pipe); |
1105 | if (ret) | 995 | if (ret) |
1106 | return ret; | 996 | return ret; |
@@ -1125,10 +1015,9 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, | |||
1125 | * - Then run current pipe | 1015 | * - Then run current pipe |
1126 | */ | 1016 | */ |
1127 | static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | 1017 | static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, |
1128 | struct skl *skl) | 1018 | struct skl_dev *skl) |
1129 | { | 1019 | { |
1130 | struct skl_module_cfg *src_mconfig; | 1020 | struct skl_module_cfg *src_mconfig; |
1131 | struct skl_sst *ctx = skl->skl_sst; | ||
1132 | int ret = 0; | 1021 | int ret = 0; |
1133 | 1022 | ||
1134 | src_mconfig = w->priv; | 1023 | src_mconfig = w->priv; |
@@ -1144,25 +1033,24 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, | |||
1144 | 1033 | ||
1145 | /* Start source pipe last after starting all sinks */ | 1034 | /* Start source pipe last after starting all sinks */ |
1146 | if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) | 1035 | if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) |
1147 | return skl_run_pipe(ctx, src_mconfig->pipe); | 1036 | return skl_run_pipe(skl, src_mconfig->pipe); |
1148 | 1037 | ||
1149 | return 0; | 1038 | return 0; |
1150 | } | 1039 | } |
1151 | 1040 | ||
1152 | static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( | 1041 | static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( |
1153 | struct snd_soc_dapm_widget *w, struct skl *skl) | 1042 | struct snd_soc_dapm_widget *w, struct skl_dev *skl) |
1154 | { | 1043 | { |
1155 | struct snd_soc_dapm_path *p; | 1044 | struct snd_soc_dapm_path *p; |
1156 | struct snd_soc_dapm_widget *src_w = NULL; | 1045 | struct snd_soc_dapm_widget *src_w = NULL; |
1157 | struct skl_sst *ctx = skl->skl_sst; | ||
1158 | 1046 | ||
1159 | snd_soc_dapm_widget_for_each_source_path(w, p) { | 1047 | snd_soc_dapm_widget_for_each_source_path(w, p) { |
1160 | src_w = p->source; | 1048 | src_w = p->source; |
1161 | if (!p->connect) | 1049 | if (!p->connect) |
1162 | continue; | 1050 | continue; |
1163 | 1051 | ||
1164 | dev_dbg(ctx->dev, "sink widget=%s\n", w->name); | 1052 | dev_dbg(skl->dev, "sink widget=%s\n", w->name); |
1165 | dev_dbg(ctx->dev, "src widget=%s\n", p->source->name); | 1053 | dev_dbg(skl->dev, "src widget=%s\n", p->source->name); |
1166 | 1054 | ||
1167 | /* | 1055 | /* |
1168 | * here we will check widgets in sink pipelines, so that can | 1056 | * here we will check widgets in sink pipelines, so that can |
@@ -1170,7 +1058,7 @@ static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( | |||
1170 | * ones used for SKL so check that first | 1058 | * ones used for SKL so check that first |
1171 | */ | 1059 | */ |
1172 | if ((p->source->priv != NULL) && | 1060 | if ((p->source->priv != NULL) && |
1173 | is_skl_dsp_widget_type(p->source, ctx->dev)) { | 1061 | is_skl_dsp_widget_type(p->source, skl->dev)) { |
1174 | return p->source; | 1062 | return p->source; |
1175 | } | 1063 | } |
1176 | } | 1064 | } |
@@ -1191,12 +1079,11 @@ static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( | |||
1191 | * - start this pipeline | 1079 | * - start this pipeline |
1192 | */ | 1080 | */ |
1193 | static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, | 1081 | static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, |
1194 | struct skl *skl) | 1082 | struct skl_dev *skl) |
1195 | { | 1083 | { |
1196 | int ret = 0; | 1084 | int ret = 0; |
1197 | struct snd_soc_dapm_widget *source, *sink; | 1085 | struct snd_soc_dapm_widget *source, *sink; |
1198 | struct skl_module_cfg *src_mconfig, *sink_mconfig; | 1086 | struct skl_module_cfg *src_mconfig, *sink_mconfig; |
1199 | struct skl_sst *ctx = skl->skl_sst; | ||
1200 | int src_pipe_started = 0; | 1087 | int src_pipe_started = 0; |
1201 | 1088 | ||
1202 | sink = w; | 1089 | sink = w; |
@@ -1222,16 +1109,16 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, | |||
1222 | } | 1109 | } |
1223 | 1110 | ||
1224 | if (src_pipe_started) { | 1111 | if (src_pipe_started) { |
1225 | ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); | 1112 | ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); |
1226 | if (ret) | 1113 | if (ret) |
1227 | return ret; | 1114 | return ret; |
1228 | 1115 | ||
1229 | /* set module params after bind */ | 1116 | /* set module params after bind */ |
1230 | skl_tplg_set_module_bind_params(source, src_mconfig, ctx); | 1117 | skl_tplg_set_module_bind_params(source, src_mconfig, skl); |
1231 | skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx); | 1118 | skl_tplg_set_module_bind_params(sink, sink_mconfig, skl); |
1232 | 1119 | ||
1233 | if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) | 1120 | if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) |
1234 | ret = skl_run_pipe(ctx, sink_mconfig->pipe); | 1121 | ret = skl_run_pipe(skl, sink_mconfig->pipe); |
1235 | } | 1122 | } |
1236 | 1123 | ||
1237 | return ret; | 1124 | return ret; |
@@ -1244,16 +1131,15 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, | |||
1244 | * - unbind with source pipelines if still connected | 1131 | * - unbind with source pipelines if still connected |
1245 | */ | 1132 | */ |
1246 | static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, | 1133 | static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, |
1247 | struct skl *skl) | 1134 | struct skl_dev *skl) |
1248 | { | 1135 | { |
1249 | struct skl_module_cfg *src_mconfig, *sink_mconfig; | 1136 | struct skl_module_cfg *src_mconfig, *sink_mconfig; |
1250 | int ret = 0, i; | 1137 | int ret = 0, i; |
1251 | struct skl_sst *ctx = skl->skl_sst; | ||
1252 | 1138 | ||
1253 | sink_mconfig = w->priv; | 1139 | sink_mconfig = w->priv; |
1254 | 1140 | ||
1255 | /* Stop the pipe */ | 1141 | /* Stop the pipe */ |
1256 | ret = skl_stop_pipe(ctx, sink_mconfig->pipe); | 1142 | ret = skl_stop_pipe(skl, sink_mconfig->pipe); |
1257 | if (ret) | 1143 | if (ret) |
1258 | return ret; | 1144 | return ret; |
1259 | 1145 | ||
@@ -1263,7 +1149,7 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, | |||
1263 | if (!src_mconfig) | 1149 | if (!src_mconfig) |
1264 | continue; | 1150 | continue; |
1265 | 1151 | ||
1266 | ret = skl_unbind_modules(ctx, | 1152 | ret = skl_unbind_modules(skl, |
1267 | src_mconfig, sink_mconfig); | 1153 | src_mconfig, sink_mconfig); |
1268 | } | 1154 | } |
1269 | } | 1155 | } |
@@ -1273,28 +1159,22 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, | |||
1273 | 1159 | ||
1274 | /* | 1160 | /* |
1275 | * in the Post-PMD event of mixer we need to do following: | 1161 | * in the Post-PMD event of mixer we need to do following: |
1276 | * - Free the mcps used | ||
1277 | * - Free the mem used | ||
1278 | * - Unbind the modules within the pipeline | 1162 | * - Unbind the modules within the pipeline |
1279 | * - Delete the pipeline (modules are not required to be explicitly | 1163 | * - Delete the pipeline (modules are not required to be explicitly |
1280 | * deleted, pipeline delete is enough here | 1164 | * deleted, pipeline delete is enough here |
1281 | */ | 1165 | */ |
1282 | static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, | 1166 | static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, |
1283 | struct skl *skl) | 1167 | struct skl_dev *skl) |
1284 | { | 1168 | { |
1285 | struct skl_module_cfg *mconfig = w->priv; | 1169 | struct skl_module_cfg *mconfig = w->priv; |
1286 | struct skl_pipe_module *w_module; | 1170 | struct skl_pipe_module *w_module; |
1287 | struct skl_module_cfg *src_module = NULL, *dst_module; | 1171 | struct skl_module_cfg *src_module = NULL, *dst_module; |
1288 | struct skl_sst *ctx = skl->skl_sst; | ||
1289 | struct skl_pipe *s_pipe = mconfig->pipe; | 1172 | struct skl_pipe *s_pipe = mconfig->pipe; |
1290 | struct skl_module_deferred_bind *modules, *tmp; | 1173 | struct skl_module_deferred_bind *modules, *tmp; |
1291 | 1174 | ||
1292 | if (s_pipe->state == SKL_PIPE_INVALID) | 1175 | if (s_pipe->state == SKL_PIPE_INVALID) |
1293 | return -EINVAL; | 1176 | return -EINVAL; |
1294 | 1177 | ||
1295 | skl_tplg_free_pipe_mcps(skl, mconfig); | ||
1296 | skl_tplg_free_pipe_mem(skl, mconfig); | ||
1297 | |||
1298 | list_for_each_entry(w_module, &s_pipe->w_list, node) { | 1178 | list_for_each_entry(w_module, &s_pipe->w_list, node) { |
1299 | if (list_empty(&skl->bind_list)) | 1179 | if (list_empty(&skl->bind_list)) |
1300 | break; | 1180 | break; |
@@ -1307,7 +1187,7 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, | |||
1307 | * modules from deferred bind list. | 1187 | * modules from deferred bind list. |
1308 | */ | 1188 | */ |
1309 | if (modules->dst == src_module) { | 1189 | if (modules->dst == src_module) { |
1310 | skl_unbind_modules(ctx, modules->src, | 1190 | skl_unbind_modules(skl, modules->src, |
1311 | modules->dst); | 1191 | modules->dst); |
1312 | } | 1192 | } |
1313 | 1193 | ||
@@ -1327,44 +1207,40 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, | |||
1327 | list_for_each_entry(w_module, &s_pipe->w_list, node) { | 1207 | list_for_each_entry(w_module, &s_pipe->w_list, node) { |
1328 | dst_module = w_module->w->priv; | 1208 | dst_module = w_module->w->priv; |
1329 | 1209 | ||
1330 | if (mconfig->m_state >= SKL_MODULE_INIT_DONE) | ||
1331 | skl_tplg_free_pipe_mcps(skl, dst_module); | ||
1332 | if (src_module == NULL) { | 1210 | if (src_module == NULL) { |
1333 | src_module = dst_module; | 1211 | src_module = dst_module; |
1334 | continue; | 1212 | continue; |
1335 | } | 1213 | } |
1336 | 1214 | ||
1337 | skl_unbind_modules(ctx, src_module, dst_module); | 1215 | skl_unbind_modules(skl, src_module, dst_module); |
1338 | src_module = dst_module; | 1216 | src_module = dst_module; |
1339 | } | 1217 | } |
1340 | 1218 | ||
1341 | skl_delete_pipe(ctx, mconfig->pipe); | 1219 | skl_delete_pipe(skl, mconfig->pipe); |
1342 | 1220 | ||
1343 | list_for_each_entry(w_module, &s_pipe->w_list, node) { | 1221 | list_for_each_entry(w_module, &s_pipe->w_list, node) { |
1344 | src_module = w_module->w->priv; | 1222 | src_module = w_module->w->priv; |
1345 | src_module->m_state = SKL_MODULE_UNINIT; | 1223 | src_module->m_state = SKL_MODULE_UNINIT; |
1346 | } | 1224 | } |
1347 | 1225 | ||
1348 | return skl_tplg_unload_pipe_modules(ctx, s_pipe); | 1226 | return skl_tplg_unload_pipe_modules(skl, s_pipe); |
1349 | } | 1227 | } |
1350 | 1228 | ||
1351 | /* | 1229 | /* |
1352 | * in the Post-PMD event of PGA we need to do following: | 1230 | * in the Post-PMD event of PGA we need to do following: |
1353 | * - Free the mcps used | ||
1354 | * - Stop the pipeline | 1231 | * - Stop the pipeline |
1355 | * - In source pipe is connected, unbind with source pipelines | 1232 | * - In source pipe is connected, unbind with source pipelines |
1356 | */ | 1233 | */ |
1357 | static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, | 1234 | static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, |
1358 | struct skl *skl) | 1235 | struct skl_dev *skl) |
1359 | { | 1236 | { |
1360 | struct skl_module_cfg *src_mconfig, *sink_mconfig; | 1237 | struct skl_module_cfg *src_mconfig, *sink_mconfig; |
1361 | int ret = 0, i; | 1238 | int ret = 0, i; |
1362 | struct skl_sst *ctx = skl->skl_sst; | ||
1363 | 1239 | ||
1364 | src_mconfig = w->priv; | 1240 | src_mconfig = w->priv; |
1365 | 1241 | ||
1366 | /* Stop the pipe since this is a mixin module */ | 1242 | /* Stop the pipe since this is a mixin module */ |
1367 | ret = skl_stop_pipe(ctx, src_mconfig->pipe); | 1243 | ret = skl_stop_pipe(skl, src_mconfig->pipe); |
1368 | if (ret) | 1244 | if (ret) |
1369 | return ret; | 1245 | return ret; |
1370 | 1246 | ||
@@ -1377,7 +1253,7 @@ static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, | |||
1377 | * This is a connecter and if path is found that means | 1253 | * This is a connecter and if path is found that means |
1378 | * unbind between source and sink has not happened yet | 1254 | * unbind between source and sink has not happened yet |
1379 | */ | 1255 | */ |
1380 | ret = skl_unbind_modules(ctx, src_mconfig, | 1256 | ret = skl_unbind_modules(skl, src_mconfig, |
1381 | sink_mconfig); | 1257 | sink_mconfig); |
1382 | } | 1258 | } |
1383 | } | 1259 | } |
@@ -1395,7 +1271,7 @@ static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w, | |||
1395 | struct snd_kcontrol *k, int event) | 1271 | struct snd_kcontrol *k, int event) |
1396 | { | 1272 | { |
1397 | struct snd_soc_dapm_context *dapm = w->dapm; | 1273 | struct snd_soc_dapm_context *dapm = w->dapm; |
1398 | struct skl *skl = get_skl_ctx(dapm->dev); | 1274 | struct skl_dev *skl = get_skl_ctx(dapm->dev); |
1399 | 1275 | ||
1400 | switch (event) { | 1276 | switch (event) { |
1401 | case SND_SOC_DAPM_PRE_PMU: | 1277 | case SND_SOC_DAPM_PRE_PMU: |
@@ -1425,7 +1301,7 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, | |||
1425 | 1301 | ||
1426 | { | 1302 | { |
1427 | struct snd_soc_dapm_context *dapm = w->dapm; | 1303 | struct snd_soc_dapm_context *dapm = w->dapm; |
1428 | struct skl *skl = get_skl_ctx(dapm->dev); | 1304 | struct skl_dev *skl = get_skl_ctx(dapm->dev); |
1429 | 1305 | ||
1430 | switch (event) { | 1306 | switch (event) { |
1431 | case SND_SOC_DAPM_PRE_PMU: | 1307 | case SND_SOC_DAPM_PRE_PMU: |
@@ -1446,10 +1322,10 @@ static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, | |||
1446 | struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; | 1322 | struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; |
1447 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); | 1323 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); |
1448 | struct skl_module_cfg *mconfig = w->priv; | 1324 | struct skl_module_cfg *mconfig = w->priv; |
1449 | struct skl *skl = get_skl_ctx(w->dapm->dev); | 1325 | struct skl_dev *skl = get_skl_ctx(w->dapm->dev); |
1450 | 1326 | ||
1451 | if (w->power) | 1327 | if (w->power) |
1452 | skl_get_module_params(skl->skl_sst, (u32 *)bc->params, | 1328 | skl_get_module_params(skl, (u32 *)bc->params, |
1453 | bc->size, bc->param_id, mconfig); | 1329 | bc->size, bc->param_id, mconfig); |
1454 | 1330 | ||
1455 | /* decrement size for TLV header */ | 1331 | /* decrement size for TLV header */ |
@@ -1481,7 +1357,7 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, | |||
1481 | struct soc_bytes_ext *sb = | 1357 | struct soc_bytes_ext *sb = |
1482 | (struct soc_bytes_ext *)kcontrol->private_value; | 1358 | (struct soc_bytes_ext *)kcontrol->private_value; |
1483 | struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; | 1359 | struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; |
1484 | struct skl *skl = get_skl_ctx(w->dapm->dev); | 1360 | struct skl_dev *skl = get_skl_ctx(w->dapm->dev); |
1485 | 1361 | ||
1486 | if (ac->params) { | 1362 | if (ac->params) { |
1487 | /* | 1363 | /* |
@@ -1498,7 +1374,7 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, | |||
1498 | return -EFAULT; | 1374 | return -EFAULT; |
1499 | 1375 | ||
1500 | if (w->power) | 1376 | if (w->power) |
1501 | return skl_set_module_params(skl->skl_sst, | 1377 | return skl_set_module_params(skl, |
1502 | (u32 *)ac->params, ac->size, | 1378 | (u32 *)ac->params, ac->size, |
1503 | ac->param_id, mconfig); | 1379 | ac->param_id, mconfig); |
1504 | } | 1380 | } |
@@ -1659,7 +1535,7 @@ int skl_tplg_update_pipe_params(struct device *dev, | |||
1659 | struct skl_pipe_params *params) | 1535 | struct skl_pipe_params *params) |
1660 | { | 1536 | { |
1661 | struct skl_module_res *res = &mconfig->module->resources[0]; | 1537 | struct skl_module_res *res = &mconfig->module->resources[0]; |
1662 | struct skl *skl = get_skl_ctx(dev); | 1538 | struct skl_dev *skl = get_skl_ctx(dev); |
1663 | struct skl_module_fmt *format = NULL; | 1539 | struct skl_module_fmt *format = NULL; |
1664 | u8 cfg_idx = mconfig->pipe->cur_config_idx; | 1540 | u8 cfg_idx = mconfig->pipe->cur_config_idx; |
1665 | 1541 | ||
@@ -1856,7 +1732,7 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, | |||
1856 | struct skl_pipe_params *params) | 1732 | struct skl_pipe_params *params) |
1857 | { | 1733 | { |
1858 | struct nhlt_specific_cfg *cfg; | 1734 | struct nhlt_specific_cfg *cfg; |
1859 | struct skl *skl = get_skl_ctx(dai->dev); | 1735 | struct skl_dev *skl = get_skl_ctx(dai->dev); |
1860 | int link_type = skl_tplg_be_link_type(mconfig->dev_type); | 1736 | int link_type = skl_tplg_be_link_type(mconfig->dev_type); |
1861 | u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); | 1737 | u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); |
1862 | 1738 | ||
@@ -2070,7 +1946,7 @@ static int skl_tplg_fill_pipe_tkn(struct device *dev, | |||
2070 | * Return an existing pipe if the pipe already exists. | 1946 | * Return an existing pipe if the pipe already exists. |
2071 | */ | 1947 | */ |
2072 | static int skl_tplg_add_pipe(struct device *dev, | 1948 | static int skl_tplg_add_pipe(struct device *dev, |
2073 | struct skl_module_cfg *mconfig, struct skl *skl, | 1949 | struct skl_module_cfg *mconfig, struct skl_dev *skl, |
2074 | struct snd_soc_tplg_vendor_value_elem *tkn_elem) | 1950 | struct snd_soc_tplg_vendor_value_elem *tkn_elem) |
2075 | { | 1951 | { |
2076 | struct skl_pipeline *ppl; | 1952 | struct skl_pipeline *ppl; |
@@ -2330,10 +2206,6 @@ static int skl_tplg_fill_res_tkn(struct device *dev, | |||
2330 | return -EINVAL; | 2206 | return -EINVAL; |
2331 | 2207 | ||
2332 | switch (tkn_elem->token) { | 2208 | switch (tkn_elem->token) { |
2333 | case SKL_TKN_MM_U32_CPS: | ||
2334 | res->cps = tkn_elem->value; | ||
2335 | break; | ||
2336 | |||
2337 | case SKL_TKN_MM_U32_DMA_SIZE: | 2209 | case SKL_TKN_MM_U32_DMA_SIZE: |
2338 | res->dma_buffer_size = tkn_elem->value; | 2210 | res->dma_buffer_size = tkn_elem->value; |
2339 | break; | 2211 | break; |
@@ -2354,10 +2226,6 @@ static int skl_tplg_fill_res_tkn(struct device *dev, | |||
2354 | res->ibs = tkn_elem->value; | 2226 | res->ibs = tkn_elem->value; |
2355 | break; | 2227 | break; |
2356 | 2228 | ||
2357 | case SKL_TKN_U32_MAX_MCPS: | ||
2358 | res->cps = tkn_elem->value; | ||
2359 | break; | ||
2360 | |||
2361 | case SKL_TKN_MM_U32_RES_PIN_ID: | 2229 | case SKL_TKN_MM_U32_RES_PIN_ID: |
2362 | case SKL_TKN_MM_U32_PIN_BUF: | 2230 | case SKL_TKN_MM_U32_PIN_BUF: |
2363 | ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, | 2231 | ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, |
@@ -2366,6 +2234,11 @@ static int skl_tplg_fill_res_tkn(struct device *dev, | |||
2366 | return ret; | 2234 | return ret; |
2367 | break; | 2235 | break; |
2368 | 2236 | ||
2237 | case SKL_TKN_MM_U32_CPS: | ||
2238 | case SKL_TKN_U32_MAX_MCPS: | ||
2239 | /* ignore unused tokens */ | ||
2240 | break; | ||
2241 | |||
2369 | default: | 2242 | default: |
2370 | dev_err(dev, "Not a res type token: %d", tkn_elem->token); | 2243 | dev_err(dev, "Not a res type token: %d", tkn_elem->token); |
2371 | return -EINVAL; | 2244 | return -EINVAL; |
@@ -2381,7 +2254,7 @@ static int skl_tplg_fill_res_tkn(struct device *dev, | |||
2381 | */ | 2254 | */ |
2382 | static int skl_tplg_get_token(struct device *dev, | 2255 | static int skl_tplg_get_token(struct device *dev, |
2383 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | 2256 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, |
2384 | struct skl *skl, struct skl_module_cfg *mconfig) | 2257 | struct skl_dev *skl, struct skl_module_cfg *mconfig) |
2385 | { | 2258 | { |
2386 | int tkn_count = 0; | 2259 | int tkn_count = 0; |
2387 | int ret; | 2260 | int ret; |
@@ -2631,7 +2504,7 @@ static int skl_tplg_get_token(struct device *dev, | |||
2631 | * module private data | 2504 | * module private data |
2632 | */ | 2505 | */ |
2633 | static int skl_tplg_get_tokens(struct device *dev, | 2506 | static int skl_tplg_get_tokens(struct device *dev, |
2634 | char *pvt_data, struct skl *skl, | 2507 | char *pvt_data, struct skl_dev *skl, |
2635 | struct skl_module_cfg *mconfig, int block_size) | 2508 | struct skl_module_cfg *mconfig, int block_size) |
2636 | { | 2509 | { |
2637 | struct snd_soc_tplg_vendor_array *array; | 2510 | struct snd_soc_tplg_vendor_array *array; |
@@ -2727,8 +2600,8 @@ static int skl_tplg_get_desc_blocks(struct device *dev, | |||
2727 | * Otherwise we create a new instance and add into driver list | 2600 | * Otherwise we create a new instance and add into driver list |
2728 | */ | 2601 | */ |
2729 | static int skl_tplg_add_pipe_v4(struct device *dev, | 2602 | static int skl_tplg_add_pipe_v4(struct device *dev, |
2730 | struct skl_module_cfg *mconfig, struct skl *skl, | 2603 | struct skl_module_cfg *mconfig, struct skl_dev *skl, |
2731 | struct skl_dfw_v4_pipe *dfw_pipe) | 2604 | struct skl_dfw_v4_pipe *dfw_pipe) |
2732 | { | 2605 | { |
2733 | struct skl_pipeline *ppl; | 2606 | struct skl_pipeline *ppl; |
2734 | struct skl_pipe *pipe; | 2607 | struct skl_pipe *pipe; |
@@ -2804,7 +2677,7 @@ static void skl_tplg_fill_fmt_v4(struct skl_module_pin_fmt *dst_fmt, | |||
2804 | } | 2677 | } |
2805 | 2678 | ||
2806 | static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, | 2679 | static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, |
2807 | struct skl *skl, struct device *dev, | 2680 | struct skl_dev *skl, struct device *dev, |
2808 | struct skl_module_cfg *mconfig) | 2681 | struct skl_module_cfg *mconfig) |
2809 | { | 2682 | { |
2810 | struct skl_dfw_v4_module *dfw = | 2683 | struct skl_dfw_v4_module *dfw = |
@@ -2818,7 +2691,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, | |||
2818 | return ret; | 2691 | return ret; |
2819 | mconfig->id.module_id = -1; | 2692 | mconfig->id.module_id = -1; |
2820 | mconfig->id.instance_id = dfw->instance_id; | 2693 | mconfig->id.instance_id = dfw->instance_id; |
2821 | mconfig->module->resources[0].cps = dfw->max_mcps; | 2694 | mconfig->module->resources[0].cpc = dfw->max_mcps / 1000; |
2822 | mconfig->module->resources[0].ibs = dfw->ibs; | 2695 | mconfig->module->resources[0].ibs = dfw->ibs; |
2823 | mconfig->module->resources[0].obs = dfw->obs; | 2696 | mconfig->module->resources[0].obs = dfw->obs; |
2824 | mconfig->core_id = dfw->core_id; | 2697 | mconfig->core_id = dfw->core_id; |
@@ -2886,7 +2759,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, | |||
2886 | * for the type and size of the suceeding data block. | 2759 | * for the type and size of the suceeding data block. |
2887 | */ | 2760 | */ |
2888 | static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, | 2761 | static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, |
2889 | struct skl *skl, struct device *dev, | 2762 | struct skl_dev *skl, struct device *dev, |
2890 | struct skl_module_cfg *mconfig) | 2763 | struct skl_module_cfg *mconfig) |
2891 | { | 2764 | { |
2892 | struct snd_soc_tplg_vendor_array *array; | 2765 | struct snd_soc_tplg_vendor_array *array; |
@@ -2981,9 +2854,8 @@ static void skl_clear_pin_config(struct snd_soc_component *component, | |||
2981 | } | 2854 | } |
2982 | } | 2855 | } |
2983 | 2856 | ||
2984 | void skl_cleanup_resources(struct skl *skl) | 2857 | void skl_cleanup_resources(struct skl_dev *skl) |
2985 | { | 2858 | { |
2986 | struct skl_sst *ctx = skl->skl_sst; | ||
2987 | struct snd_soc_component *soc_component = skl->component; | 2859 | struct snd_soc_component *soc_component = skl->component; |
2988 | struct snd_soc_dapm_widget *w; | 2860 | struct snd_soc_dapm_widget *w; |
2989 | struct snd_soc_card *card; | 2861 | struct snd_soc_card *card; |
@@ -2995,15 +2867,12 @@ void skl_cleanup_resources(struct skl *skl) | |||
2995 | if (!card || !card->instantiated) | 2867 | if (!card || !card->instantiated) |
2996 | return; | 2868 | return; |
2997 | 2869 | ||
2998 | skl->resource.mem = 0; | ||
2999 | skl->resource.mcps = 0; | ||
3000 | |||
3001 | list_for_each_entry(w, &card->widgets, list) { | 2870 | list_for_each_entry(w, &card->widgets, list) { |
3002 | if (is_skl_dsp_widget_type(w, ctx->dev) && w->priv != NULL) | 2871 | if (is_skl_dsp_widget_type(w, skl->dev) && w->priv != NULL) |
3003 | skl_clear_pin_config(soc_component, w); | 2872 | skl_clear_pin_config(soc_component, w); |
3004 | } | 2873 | } |
3005 | 2874 | ||
3006 | skl_clear_module_cnt(ctx->dsp); | 2875 | skl_clear_module_cnt(skl->dsp); |
3007 | } | 2876 | } |
3008 | 2877 | ||
3009 | /* | 2878 | /* |
@@ -3019,7 +2888,7 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index, | |||
3019 | { | 2888 | { |
3020 | int ret; | 2889 | int ret; |
3021 | struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); | 2890 | struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); |
3022 | struct skl *skl = bus_to_skl(bus); | 2891 | struct skl_dev *skl = bus_to_skl(bus); |
3023 | struct skl_module_cfg *mconfig; | 2892 | struct skl_module_cfg *mconfig; |
3024 | 2893 | ||
3025 | if (!tplg_w->priv.size) | 2894 | if (!tplg_w->priv.size) |
@@ -3163,21 +3032,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, | |||
3163 | 3032 | ||
3164 | static int skl_tplg_fill_str_mfest_tkn(struct device *dev, | 3033 | static int skl_tplg_fill_str_mfest_tkn(struct device *dev, |
3165 | struct snd_soc_tplg_vendor_string_elem *str_elem, | 3034 | struct snd_soc_tplg_vendor_string_elem *str_elem, |
3166 | struct skl *skl) | 3035 | struct skl_dev *skl) |
3167 | { | 3036 | { |
3168 | int tkn_count = 0; | 3037 | int tkn_count = 0; |
3169 | static int ref_count; | 3038 | static int ref_count; |
3170 | 3039 | ||
3171 | switch (str_elem->token) { | 3040 | switch (str_elem->token) { |
3172 | case SKL_TKN_STR_LIB_NAME: | 3041 | case SKL_TKN_STR_LIB_NAME: |
3173 | if (ref_count > skl->skl_sst->lib_count - 1) { | 3042 | if (ref_count > skl->lib_count - 1) { |
3174 | ref_count = 0; | 3043 | ref_count = 0; |
3175 | return -EINVAL; | 3044 | return -EINVAL; |
3176 | } | 3045 | } |
3177 | 3046 | ||
3178 | strncpy(skl->skl_sst->lib_info[ref_count].name, | 3047 | strncpy(skl->lib_info[ref_count].name, |
3179 | str_elem->string, | 3048 | str_elem->string, |
3180 | ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); | 3049 | ARRAY_SIZE(skl->lib_info[ref_count].name)); |
3181 | ref_count++; | 3050 | ref_count++; |
3182 | break; | 3051 | break; |
3183 | 3052 | ||
@@ -3192,7 +3061,7 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev, | |||
3192 | 3061 | ||
3193 | static int skl_tplg_get_str_tkn(struct device *dev, | 3062 | static int skl_tplg_get_str_tkn(struct device *dev, |
3194 | struct snd_soc_tplg_vendor_array *array, | 3063 | struct snd_soc_tplg_vendor_array *array, |
3195 | struct skl *skl) | 3064 | struct skl_dev *skl) |
3196 | { | 3065 | { |
3197 | int tkn_count = 0, ret; | 3066 | int tkn_count = 0, ret; |
3198 | struct snd_soc_tplg_vendor_string_elem *str_elem; | 3067 | struct snd_soc_tplg_vendor_string_elem *str_elem; |
@@ -3299,7 +3168,7 @@ static int skl_tplg_fill_mod_info(struct device *dev, | |||
3299 | 3168 | ||
3300 | static int skl_tplg_get_int_tkn(struct device *dev, | 3169 | static int skl_tplg_get_int_tkn(struct device *dev, |
3301 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | 3170 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, |
3302 | struct skl *skl) | 3171 | struct skl_dev *skl) |
3303 | { | 3172 | { |
3304 | int tkn_count = 0, ret; | 3173 | int tkn_count = 0, ret; |
3305 | static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; | 3174 | static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; |
@@ -3319,7 +3188,7 @@ static int skl_tplg_get_int_tkn(struct device *dev, | |||
3319 | 3188 | ||
3320 | switch (tkn_elem->token) { | 3189 | switch (tkn_elem->token) { |
3321 | case SKL_TKN_U32_LIB_COUNT: | 3190 | case SKL_TKN_U32_LIB_COUNT: |
3322 | skl->skl_sst->lib_count = tkn_elem->value; | 3191 | skl->lib_count = tkn_elem->value; |
3323 | break; | 3192 | break; |
3324 | 3193 | ||
3325 | case SKL_TKN_U8_NUM_MOD: | 3194 | case SKL_TKN_U8_NUM_MOD: |
@@ -3465,35 +3334,17 @@ static int skl_tplg_get_int_tkn(struct device *dev, | |||
3465 | return tkn_count; | 3334 | return tkn_count; |
3466 | } | 3335 | } |
3467 | 3336 | ||
3468 | static int skl_tplg_get_manifest_uuid(struct device *dev, | ||
3469 | struct skl *skl, | ||
3470 | struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) | ||
3471 | { | ||
3472 | static int ref_count; | ||
3473 | struct skl_module *mod; | ||
3474 | |||
3475 | if (uuid_tkn->token == SKL_TKN_UUID) { | ||
3476 | mod = skl->modules[ref_count]; | ||
3477 | guid_copy(&mod->uuid, (guid_t *)&uuid_tkn->uuid); | ||
3478 | ref_count++; | ||
3479 | } else { | ||
3480 | dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); | ||
3481 | return -EINVAL; | ||
3482 | } | ||
3483 | |||
3484 | return 0; | ||
3485 | } | ||
3486 | |||
3487 | /* | 3337 | /* |
3488 | * Fill the manifest structure by parsing the tokens based on the | 3338 | * Fill the manifest structure by parsing the tokens based on the |
3489 | * type. | 3339 | * type. |
3490 | */ | 3340 | */ |
3491 | static int skl_tplg_get_manifest_tkn(struct device *dev, | 3341 | static int skl_tplg_get_manifest_tkn(struct device *dev, |
3492 | char *pvt_data, struct skl *skl, | 3342 | char *pvt_data, struct skl_dev *skl, |
3493 | int block_size) | 3343 | int block_size) |
3494 | { | 3344 | { |
3495 | int tkn_count = 0, ret; | 3345 | int tkn_count = 0, ret; |
3496 | int off = 0, tuple_size = 0; | 3346 | int off = 0, tuple_size = 0; |
3347 | u8 uuid_index = 0; | ||
3497 | struct snd_soc_tplg_vendor_array *array; | 3348 | struct snd_soc_tplg_vendor_array *array; |
3498 | struct snd_soc_tplg_vendor_value_elem *tkn_elem; | 3349 | struct snd_soc_tplg_vendor_value_elem *tkn_elem; |
3499 | 3350 | ||
@@ -3516,9 +3367,17 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, | |||
3516 | continue; | 3367 | continue; |
3517 | 3368 | ||
3518 | case SND_SOC_TPLG_TUPLE_TYPE_UUID: | 3369 | case SND_SOC_TPLG_TUPLE_TYPE_UUID: |
3519 | ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid); | 3370 | if (array->uuid->token != SKL_TKN_UUID) { |
3520 | if (ret < 0) | 3371 | dev_err(dev, "Not an UUID token: %d\n", |
3521 | return ret; | 3372 | array->uuid->token); |
3373 | return -EINVAL; | ||
3374 | } | ||
3375 | if (uuid_index >= skl->nr_modules) { | ||
3376 | dev_err(dev, "Too many UUID tokens\n"); | ||
3377 | return -EINVAL; | ||
3378 | } | ||
3379 | guid_copy(&skl->modules[uuid_index++]->uuid, | ||
3380 | (guid_t *)&array->uuid->uuid); | ||
3522 | 3381 | ||
3523 | tuple_size += sizeof(*array->uuid); | 3382 | tuple_size += sizeof(*array->uuid); |
3524 | continue; | 3383 | continue; |
@@ -3550,7 +3409,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, | |||
3550 | * preceded by descriptors for type and size of data block. | 3409 | * preceded by descriptors for type and size of data block. |
3551 | */ | 3410 | */ |
3552 | static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, | 3411 | static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, |
3553 | struct device *dev, struct skl *skl) | 3412 | struct device *dev, struct skl_dev *skl) |
3554 | { | 3413 | { |
3555 | struct snd_soc_tplg_vendor_array *array; | 3414 | struct snd_soc_tplg_vendor_array *array; |
3556 | int num_blocks, block_size = 0, block_type, off = 0; | 3415 | int num_blocks, block_size = 0, block_type, off = 0; |
@@ -3612,7 +3471,7 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, | |||
3612 | struct snd_soc_tplg_manifest *manifest) | 3471 | struct snd_soc_tplg_manifest *manifest) |
3613 | { | 3472 | { |
3614 | struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); | 3473 | struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); |
3615 | struct skl *skl = bus_to_skl(bus); | 3474 | struct skl_dev *skl = bus_to_skl(bus); |
3616 | 3475 | ||
3617 | /* proceed only if we have private data defined */ | 3476 | /* proceed only if we have private data defined */ |
3618 | if (manifest->priv.size == 0) | 3477 | if (manifest->priv.size == 0) |
@@ -3620,9 +3479,9 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, | |||
3620 | 3479 | ||
3621 | skl_tplg_get_manifest_data(manifest, bus->dev, skl); | 3480 | skl_tplg_get_manifest_data(manifest, bus->dev, skl); |
3622 | 3481 | ||
3623 | if (skl->skl_sst->lib_count > SKL_MAX_LIB) { | 3482 | if (skl->lib_count > SKL_MAX_LIB) { |
3624 | dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", | 3483 | dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", |
3625 | skl->skl_sst->lib_count); | 3484 | skl->lib_count); |
3626 | return -EINVAL; | 3485 | return -EINVAL; |
3627 | } | 3486 | } |
3628 | 3487 | ||
@@ -3671,7 +3530,7 @@ static int skl_tplg_create_pipe_widget_list(struct snd_soc_component *component) | |||
3671 | return 0; | 3530 | return 0; |
3672 | } | 3531 | } |
3673 | 3532 | ||
3674 | static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe) | 3533 | static void skl_tplg_set_pipe_type(struct skl_dev *skl, struct skl_pipe *pipe) |
3675 | { | 3534 | { |
3676 | struct skl_pipe_module *w_module; | 3535 | struct skl_pipe_module *w_module; |
3677 | struct snd_soc_dapm_widget *w; | 3536 | struct snd_soc_dapm_widget *w; |
@@ -3694,10 +3553,6 @@ static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe) | |||
3694 | pipe->passthru = false; | 3553 | pipe->passthru = false; |
3695 | } | 3554 | } |
3696 | 3555 | ||
3697 | /* This will be read from topology manifest, currently defined here */ | ||
3698 | #define SKL_MAX_MCPS 30000000 | ||
3699 | #define SKL_FW_MAX_MEM 1000000 | ||
3700 | |||
3701 | /* | 3556 | /* |
3702 | * SKL topology init routine | 3557 | * SKL topology init routine |
3703 | */ | 3558 | */ |
@@ -3705,7 +3560,7 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) | |||
3705 | { | 3560 | { |
3706 | int ret; | 3561 | int ret; |
3707 | const struct firmware *fw; | 3562 | const struct firmware *fw; |
3708 | struct skl *skl = bus_to_skl(bus); | 3563 | struct skl_dev *skl = bus_to_skl(bus); |
3709 | struct skl_pipeline *ppl; | 3564 | struct skl_pipeline *ppl; |
3710 | 3565 | ||
3711 | ret = request_firmware(&fw, skl->tplg_name, bus->dev); | 3566 | ret = request_firmware(&fw, skl->tplg_name, bus->dev); |
@@ -3724,31 +3579,30 @@ int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) | |||
3724 | * The complete tplg for SKL is loaded as index 0, we don't use | 3579 | * The complete tplg for SKL is loaded as index 0, we don't use |
3725 | * any other index | 3580 | * any other index |
3726 | */ | 3581 | */ |
3727 | ret = snd_soc_tplg_component_load(component, | 3582 | ret = snd_soc_tplg_component_load(component, &skl_tplg_ops, fw, 0); |
3728 | &skl_tplg_ops, fw, 0); | ||
3729 | if (ret < 0) { | 3583 | if (ret < 0) { |
3730 | dev_err(bus->dev, "tplg component load failed%d\n", ret); | 3584 | dev_err(bus->dev, "tplg component load failed%d\n", ret); |
3731 | release_firmware(fw); | 3585 | goto err; |
3732 | return -EINVAL; | ||
3733 | } | 3586 | } |
3734 | 3587 | ||
3735 | skl->resource.max_mcps = SKL_MAX_MCPS; | ||
3736 | skl->resource.max_mem = SKL_FW_MAX_MEM; | ||
3737 | |||
3738 | skl->tplg = fw; | ||
3739 | ret = skl_tplg_create_pipe_widget_list(component); | 3588 | ret = skl_tplg_create_pipe_widget_list(component); |
3740 | if (ret < 0) | 3589 | if (ret < 0) { |
3741 | return ret; | 3590 | dev_err(bus->dev, "tplg create pipe widget list failed%d\n", |
3591 | ret); | ||
3592 | goto err; | ||
3593 | } | ||
3742 | 3594 | ||
3743 | list_for_each_entry(ppl, &skl->ppl_list, node) | 3595 | list_for_each_entry(ppl, &skl->ppl_list, node) |
3744 | skl_tplg_set_pipe_type(skl, ppl->pipe); | 3596 | skl_tplg_set_pipe_type(skl, ppl->pipe); |
3745 | 3597 | ||
3746 | return 0; | 3598 | err: |
3599 | release_firmware(fw); | ||
3600 | return ret; | ||
3747 | } | 3601 | } |
3748 | 3602 | ||
3749 | void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) | 3603 | void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) |
3750 | { | 3604 | { |
3751 | struct skl *skl = bus_to_skl(bus); | 3605 | struct skl_dev *skl = bus_to_skl(bus); |
3752 | struct skl_pipeline *ppl, *tmp; | 3606 | struct skl_pipeline *ppl, *tmp; |
3753 | 3607 | ||
3754 | if (!list_empty(&skl->ppl_list)) | 3608 | if (!list_empty(&skl->ppl_list)) |
@@ -3757,6 +3611,4 @@ void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) | |||
3757 | 3611 | ||
3758 | /* clean up topology */ | 3612 | /* clean up topology */ |
3759 | snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); | 3613 | snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); |
3760 | |||
3761 | release_firmware(skl->tplg); | ||
3762 | } | 3614 | } |
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 665e35cee50d..e967800dbb62 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h | |||
@@ -101,7 +101,7 @@ struct skl_audio_data_format { | |||
101 | } __packed; | 101 | } __packed; |
102 | 102 | ||
103 | struct skl_base_cfg { | 103 | struct skl_base_cfg { |
104 | u32 cps; | 104 | u32 cpc; |
105 | u32 ibs; | 105 | u32 ibs; |
106 | u32 obs; | 106 | u32 obs; |
107 | u32 is_pages; | 107 | u32 is_pages; |
@@ -140,11 +140,6 @@ struct skl_src_module_cfg { | |||
140 | enum skl_s_freq src_cfg; | 140 | enum skl_s_freq src_cfg; |
141 | } __packed; | 141 | } __packed; |
142 | 142 | ||
143 | struct notification_mask { | ||
144 | u32 notify; | ||
145 | u32 enable; | ||
146 | } __packed; | ||
147 | |||
148 | struct skl_up_down_mixer_cfg { | 143 | struct skl_up_down_mixer_cfg { |
149 | struct skl_base_cfg base_cfg; | 144 | struct skl_base_cfg base_cfg; |
150 | enum skl_ch_cfg out_ch_cfg; | 145 | enum skl_ch_cfg out_ch_cfg; |
@@ -348,7 +343,6 @@ struct skl_module_pin_resources { | |||
348 | struct skl_module_res { | 343 | struct skl_module_res { |
349 | u8 id; | 344 | u8 id; |
350 | u32 is_pages; | 345 | u32 is_pages; |
351 | u32 cps; | ||
352 | u32 ibs; | 346 | u32 ibs; |
353 | u32 obs; | 347 | u32 obs; |
354 | u32 dma_buffer_size; | 348 | u32 dma_buffer_size; |
@@ -389,9 +383,6 @@ struct skl_module_cfg { | |||
389 | u8 out_queue_mask; | 383 | u8 out_queue_mask; |
390 | u8 in_queue; | 384 | u8 in_queue; |
391 | u8 out_queue; | 385 | u8 out_queue; |
392 | u32 mcps; | ||
393 | u32 ibs; | ||
394 | u32 obs; | ||
395 | u8 is_loadable; | 386 | u8 is_loadable; |
396 | u8 core_id; | 387 | u8 core_id; |
397 | u8 dev_type; | 388 | u8 dev_type; |
@@ -447,7 +438,7 @@ enum skl_channel { | |||
447 | SKL_CH_QUATRO = 4, | 438 | SKL_CH_QUATRO = 4, |
448 | }; | 439 | }; |
449 | 440 | ||
450 | static inline struct skl *get_skl_ctx(struct device *dev) | 441 | static inline struct skl_dev *get_skl_ctx(struct device *dev) |
451 | { | 442 | { |
452 | struct hdac_bus *bus = dev_get_drvdata(dev); | 443 | struct hdac_bus *bus = dev_get_drvdata(dev); |
453 | 444 | ||
@@ -456,7 +447,7 @@ static inline struct skl *get_skl_ctx(struct device *dev) | |||
456 | 447 | ||
457 | int skl_tplg_be_update_params(struct snd_soc_dai *dai, | 448 | int skl_tplg_be_update_params(struct snd_soc_dai *dai, |
458 | struct skl_pipe_params *params); | 449 | struct skl_pipe_params *params); |
459 | int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, | 450 | int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, |
460 | u32 caps_size, u32 node_id); | 451 | u32 caps_size, u32 node_id); |
461 | void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai, | 452 | void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai, |
462 | struct skl_pipe_params *params, int stream); | 453 | struct skl_pipe_params *params, int stream); |
@@ -469,32 +460,32 @@ struct skl_module_cfg *skl_tplg_fe_get_cpr_module( | |||
469 | int skl_tplg_update_pipe_params(struct device *dev, | 460 | int skl_tplg_update_pipe_params(struct device *dev, |
470 | struct skl_module_cfg *mconfig, struct skl_pipe_params *params); | 461 | struct skl_module_cfg *mconfig, struct skl_pipe_params *params); |
471 | 462 | ||
472 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps); | 463 | void skl_tplg_d0i3_get(struct skl_dev *skl, enum d0i3_capability caps); |
473 | void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps); | 464 | void skl_tplg_d0i3_put(struct skl_dev *skl, enum d0i3_capability caps); |
474 | 465 | ||
475 | int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe); | 466 | int skl_create_pipeline(struct skl_dev *skl, struct skl_pipe *pipe); |
476 | 467 | ||
477 | int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | 468 | int skl_run_pipe(struct skl_dev *skl, struct skl_pipe *pipe); |
478 | 469 | ||
479 | int skl_pause_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | 470 | int skl_pause_pipe(struct skl_dev *skl, struct skl_pipe *pipe); |
480 | 471 | ||
481 | int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | 472 | int skl_delete_pipe(struct skl_dev *skl, struct skl_pipe *pipe); |
482 | 473 | ||
483 | int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | 474 | int skl_stop_pipe(struct skl_dev *skl, struct skl_pipe *pipe); |
484 | 475 | ||
485 | int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | 476 | int skl_reset_pipe(struct skl_dev *skl, struct skl_pipe *pipe); |
486 | 477 | ||
487 | int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config); | 478 | int skl_init_module(struct skl_dev *skl, struct skl_module_cfg *module_config); |
488 | 479 | ||
489 | int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg | 480 | int skl_bind_modules(struct skl_dev *skl, struct skl_module_cfg |
490 | *src_module, struct skl_module_cfg *dst_module); | 481 | *src_module, struct skl_module_cfg *dst_module); |
491 | 482 | ||
492 | int skl_unbind_modules(struct skl_sst *ctx, struct skl_module_cfg | 483 | int skl_unbind_modules(struct skl_dev *skl, struct skl_module_cfg |
493 | *src_module, struct skl_module_cfg *dst_module); | 484 | *src_module, struct skl_module_cfg *dst_module); |
494 | 485 | ||
495 | int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, | 486 | int skl_set_module_params(struct skl_dev *skl, u32 *params, int size, |
496 | u32 param_id, struct skl_module_cfg *mcfg); | 487 | u32 param_id, struct skl_module_cfg *mcfg); |
497 | int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, | 488 | int skl_get_module_params(struct skl_dev *skl, u32 *params, int size, |
498 | u32 param_id, struct skl_module_cfg *mcfg); | 489 | u32 param_id, struct skl_module_cfg *mcfg); |
499 | 490 | ||
500 | struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, | 491 | struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, |
@@ -508,6 +499,6 @@ int skl_pcm_link_dma_prepare(struct device *dev, | |||
508 | int skl_dai_load(struct snd_soc_component *cmp, int index, | 499 | int skl_dai_load(struct snd_soc_component *cmp, int index, |
509 | struct snd_soc_dai_driver *dai_drv, | 500 | struct snd_soc_dai_driver *dai_drv, |
510 | struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai); | 501 | struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai); |
511 | void skl_tplg_add_moduleid_in_bind_params(struct skl *skl, | 502 | void skl_tplg_add_moduleid_in_bind_params(struct skl_dev *skl, |
512 | struct snd_soc_dapm_widget *w); | 503 | struct snd_soc_dapm_widget *w); |
513 | #endif | 504 | #endif |
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 3362e71b4563..141dbbf975ac 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c | |||
@@ -26,9 +26,11 @@ | |||
26 | #include <sound/hdaudio.h> | 26 | #include <sound/hdaudio.h> |
27 | #include <sound/hda_i915.h> | 27 | #include <sound/hda_i915.h> |
28 | #include <sound/hda_codec.h> | 28 | #include <sound/hda_codec.h> |
29 | #include <sound/intel-nhlt.h> | ||
29 | #include "skl.h" | 30 | #include "skl.h" |
30 | #include "skl-sst-dsp.h" | 31 | #include "skl-sst-dsp.h" |
31 | #include "skl-sst-ipc.h" | 32 | #include "skl-sst-ipc.h" |
33 | |||
32 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) | 34 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) |
33 | #include "../../../soc/codecs/hdac_hda.h" | 35 | #include "../../../soc/codecs/hdac_hda.h" |
34 | #endif | 36 | #endif |
@@ -50,7 +52,7 @@ static void skl_update_pci_byte(struct pci_dev *pci, unsigned int reg, | |||
50 | pci_write_config_byte(pci, reg, data); | 52 | pci_write_config_byte(pci, reg, data); |
51 | } | 53 | } |
52 | 54 | ||
53 | static void skl_init_pci(struct skl *skl) | 55 | static void skl_init_pci(struct skl_dev *skl) |
54 | { | 56 | { |
55 | struct hdac_bus *bus = skl_to_bus(skl); | 57 | struct hdac_bus *bus = skl_to_bus(skl); |
56 | 58 | ||
@@ -132,7 +134,7 @@ static int skl_init_chip(struct hdac_bus *bus, bool full_reset) | |||
132 | 134 | ||
133 | /* Reset stream-to-link mapping */ | 135 | /* Reset stream-to-link mapping */ |
134 | list_for_each_entry(hlink, &bus->hlink_list, list) | 136 | list_for_each_entry(hlink, &bus->hlink_list, list) |
135 | bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); | 137 | writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); |
136 | 138 | ||
137 | skl_enable_miscbdcge(bus->dev, true); | 139 | skl_enable_miscbdcge(bus->dev, true); |
138 | 140 | ||
@@ -252,7 +254,7 @@ static irqreturn_t skl_threaded_handler(int irq, void *dev_id) | |||
252 | 254 | ||
253 | static int skl_acquire_irq(struct hdac_bus *bus, int do_disconnect) | 255 | static int skl_acquire_irq(struct hdac_bus *bus, int do_disconnect) |
254 | { | 256 | { |
255 | struct skl *skl = bus_to_skl(bus); | 257 | struct skl_dev *skl = bus_to_skl(bus); |
256 | int ret; | 258 | int ret; |
257 | 259 | ||
258 | ret = request_threaded_irq(skl->pci->irq, skl_interrupt, | 260 | ret = request_threaded_irq(skl->pci->irq, skl_interrupt, |
@@ -276,7 +278,7 @@ static int skl_suspend_late(struct device *dev) | |||
276 | { | 278 | { |
277 | struct pci_dev *pci = to_pci_dev(dev); | 279 | struct pci_dev *pci = to_pci_dev(dev); |
278 | struct hdac_bus *bus = pci_get_drvdata(pci); | 280 | struct hdac_bus *bus = pci_get_drvdata(pci); |
279 | struct skl *skl = bus_to_skl(bus); | 281 | struct skl_dev *skl = bus_to_skl(bus); |
280 | 282 | ||
281 | return skl_suspend_late_dsp(skl); | 283 | return skl_suspend_late_dsp(skl); |
282 | } | 284 | } |
@@ -284,7 +286,7 @@ static int skl_suspend_late(struct device *dev) | |||
284 | #ifdef CONFIG_PM | 286 | #ifdef CONFIG_PM |
285 | static int _skl_suspend(struct hdac_bus *bus) | 287 | static int _skl_suspend(struct hdac_bus *bus) |
286 | { | 288 | { |
287 | struct skl *skl = bus_to_skl(bus); | 289 | struct skl_dev *skl = bus_to_skl(bus); |
288 | struct pci_dev *pci = to_pci_dev(bus->dev); | 290 | struct pci_dev *pci = to_pci_dev(bus->dev); |
289 | int ret; | 291 | int ret; |
290 | 292 | ||
@@ -307,7 +309,7 @@ static int _skl_suspend(struct hdac_bus *bus) | |||
307 | 309 | ||
308 | static int _skl_resume(struct hdac_bus *bus) | 310 | static int _skl_resume(struct hdac_bus *bus) |
309 | { | 311 | { |
310 | struct skl *skl = bus_to_skl(bus); | 312 | struct skl_dev *skl = bus_to_skl(bus); |
311 | 313 | ||
312 | skl_init_pci(skl); | 314 | skl_init_pci(skl); |
313 | skl_dum_set(bus); | 315 | skl_dum_set(bus); |
@@ -325,7 +327,7 @@ static int skl_suspend(struct device *dev) | |||
325 | { | 327 | { |
326 | struct pci_dev *pci = to_pci_dev(dev); | 328 | struct pci_dev *pci = to_pci_dev(dev); |
327 | struct hdac_bus *bus = pci_get_drvdata(pci); | 329 | struct hdac_bus *bus = pci_get_drvdata(pci); |
328 | struct skl *skl = bus_to_skl(bus); | 330 | struct skl_dev *skl = bus_to_skl(bus); |
329 | int ret; | 331 | int ret; |
330 | 332 | ||
331 | /* | 333 | /* |
@@ -345,7 +347,7 @@ static int skl_suspend(struct device *dev) | |||
345 | ret = _skl_suspend(bus); | 347 | ret = _skl_suspend(bus); |
346 | if (ret < 0) | 348 | if (ret < 0) |
347 | return ret; | 349 | return ret; |
348 | skl->skl_sst->fw_loaded = false; | 350 | skl->fw_loaded = false; |
349 | } | 351 | } |
350 | 352 | ||
351 | return 0; | 353 | return 0; |
@@ -355,7 +357,7 @@ static int skl_resume(struct device *dev) | |||
355 | { | 357 | { |
356 | struct pci_dev *pci = to_pci_dev(dev); | 358 | struct pci_dev *pci = to_pci_dev(dev); |
357 | struct hdac_bus *bus = pci_get_drvdata(pci); | 359 | struct hdac_bus *bus = pci_get_drvdata(pci); |
358 | struct skl *skl = bus_to_skl(bus); | 360 | struct skl_dev *skl = bus_to_skl(bus); |
359 | struct hdac_ext_link *hlink = NULL; | 361 | struct hdac_ext_link *hlink = NULL; |
360 | int ret; | 362 | int ret; |
361 | 363 | ||
@@ -430,7 +432,7 @@ static const struct dev_pm_ops skl_pm = { | |||
430 | */ | 432 | */ |
431 | static int skl_free(struct hdac_bus *bus) | 433 | static int skl_free(struct hdac_bus *bus) |
432 | { | 434 | { |
433 | struct skl *skl = bus_to_skl(bus); | 435 | struct skl_dev *skl = bus_to_skl(bus); |
434 | 436 | ||
435 | skl->init_done = 0; /* to be sure */ | 437 | skl->init_done = 0; /* to be sure */ |
436 | 438 | ||
@@ -475,7 +477,7 @@ static struct skl_ssp_clk skl_ssp_clks[] = { | |||
475 | {.name = "ssp5_sclkfs"}, | 477 | {.name = "ssp5_sclkfs"}, |
476 | }; | 478 | }; |
477 | 479 | ||
478 | static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl *skl, | 480 | static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl_dev *skl, |
479 | struct snd_soc_acpi_mach *machines) | 481 | struct snd_soc_acpi_mach *machines) |
480 | { | 482 | { |
481 | struct hdac_bus *bus = skl_to_bus(skl); | 483 | struct hdac_bus *bus = skl_to_bus(skl); |
@@ -494,7 +496,7 @@ static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl *skl, | |||
494 | return mach; | 496 | return mach; |
495 | } | 497 | } |
496 | 498 | ||
497 | static int skl_find_machine(struct skl *skl, void *driver_data) | 499 | static int skl_find_machine(struct skl_dev *skl, void *driver_data) |
498 | { | 500 | { |
499 | struct hdac_bus *bus = skl_to_bus(skl); | 501 | struct hdac_bus *bus = skl_to_bus(skl); |
500 | struct snd_soc_acpi_mach *mach = driver_data; | 502 | struct snd_soc_acpi_mach *mach = driver_data; |
@@ -516,13 +518,15 @@ static int skl_find_machine(struct skl *skl, void *driver_data) | |||
516 | 518 | ||
517 | if (pdata) { | 519 | if (pdata) { |
518 | skl->use_tplg_pcm = pdata->use_tplg_pcm; | 520 | skl->use_tplg_pcm = pdata->use_tplg_pcm; |
519 | mach->mach_params.dmic_num = skl_get_dmic_geo(skl); | 521 | mach->mach_params.dmic_num = |
522 | intel_nhlt_get_dmic_geo(&skl->pci->dev, | ||
523 | skl->nhlt); | ||
520 | } | 524 | } |
521 | 525 | ||
522 | return 0; | 526 | return 0; |
523 | } | 527 | } |
524 | 528 | ||
525 | static int skl_machine_device_register(struct skl *skl) | 529 | static int skl_machine_device_register(struct skl_dev *skl) |
526 | { | 530 | { |
527 | struct snd_soc_acpi_mach *mach = skl->mach; | 531 | struct snd_soc_acpi_mach *mach = skl->mach; |
528 | struct hdac_bus *bus = skl_to_bus(skl); | 532 | struct hdac_bus *bus = skl_to_bus(skl); |
@@ -558,13 +562,13 @@ static int skl_machine_device_register(struct skl *skl) | |||
558 | return 0; | 562 | return 0; |
559 | } | 563 | } |
560 | 564 | ||
561 | static void skl_machine_device_unregister(struct skl *skl) | 565 | static void skl_machine_device_unregister(struct skl_dev *skl) |
562 | { | 566 | { |
563 | if (skl->i2s_dev) | 567 | if (skl->i2s_dev) |
564 | platform_device_unregister(skl->i2s_dev); | 568 | platform_device_unregister(skl->i2s_dev); |
565 | } | 569 | } |
566 | 570 | ||
567 | static int skl_dmic_device_register(struct skl *skl) | 571 | static int skl_dmic_device_register(struct skl_dev *skl) |
568 | { | 572 | { |
569 | struct hdac_bus *bus = skl_to_bus(skl); | 573 | struct hdac_bus *bus = skl_to_bus(skl); |
570 | struct platform_device *pdev; | 574 | struct platform_device *pdev; |
@@ -588,7 +592,7 @@ static int skl_dmic_device_register(struct skl *skl) | |||
588 | return 0; | 592 | return 0; |
589 | } | 593 | } |
590 | 594 | ||
591 | static void skl_dmic_device_unregister(struct skl *skl) | 595 | static void skl_dmic_device_unregister(struct skl_dev *skl) |
592 | { | 596 | { |
593 | if (skl->dmic_dev) | 597 | if (skl->dmic_dev) |
594 | platform_device_unregister(skl->dmic_dev); | 598 | platform_device_unregister(skl->dmic_dev); |
@@ -626,7 +630,7 @@ static void init_skl_xtal_rate(int pci_id) | |||
626 | } | 630 | } |
627 | } | 631 | } |
628 | 632 | ||
629 | static int skl_clock_device_register(struct skl *skl) | 633 | static int skl_clock_device_register(struct skl_dev *skl) |
630 | { | 634 | { |
631 | struct platform_device_info pdevinfo = {NULL}; | 635 | struct platform_device_info pdevinfo = {NULL}; |
632 | struct skl_clk_pdata *clk_pdata; | 636 | struct skl_clk_pdata *clk_pdata; |
@@ -656,7 +660,7 @@ static int skl_clock_device_register(struct skl *skl) | |||
656 | return PTR_ERR_OR_ZERO(skl->clk_dev); | 660 | return PTR_ERR_OR_ZERO(skl->clk_dev); |
657 | } | 661 | } |
658 | 662 | ||
659 | static void skl_clock_device_unregister(struct skl *skl) | 663 | static void skl_clock_device_unregister(struct skl_dev *skl) |
660 | { | 664 | { |
661 | if (skl->clk_dev) | 665 | if (skl->clk_dev) |
662 | platform_device_unregister(skl->clk_dev); | 666 | platform_device_unregister(skl->clk_dev); |
@@ -692,7 +696,7 @@ static int probe_codec(struct hdac_bus *bus, int addr) | |||
692 | unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | | 696 | unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | |
693 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; | 697 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; |
694 | unsigned int res = -1; | 698 | unsigned int res = -1; |
695 | struct skl *skl = bus_to_skl(bus); | 699 | struct skl_dev *skl = bus_to_skl(bus); |
696 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) | 700 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) |
697 | struct hdac_hda_priv *hda_codec; | 701 | struct hdac_hda_priv *hda_codec; |
698 | int err; | 702 | int err; |
@@ -792,7 +796,7 @@ static int skl_i915_init(struct hdac_bus *bus) | |||
792 | 796 | ||
793 | static void skl_probe_work(struct work_struct *work) | 797 | static void skl_probe_work(struct work_struct *work) |
794 | { | 798 | { |
795 | struct skl *skl = container_of(work, struct skl, probe_work); | 799 | struct skl_dev *skl = container_of(work, struct skl_dev, probe_work); |
796 | struct hdac_bus *bus = skl_to_bus(skl); | 800 | struct hdac_bus *bus = skl_to_bus(skl); |
797 | struct hdac_ext_link *hlink = NULL; | 801 | struct hdac_ext_link *hlink = NULL; |
798 | int err; | 802 | int err; |
@@ -854,11 +858,10 @@ out_err: | |||
854 | * constructor | 858 | * constructor |
855 | */ | 859 | */ |
856 | static int skl_create(struct pci_dev *pci, | 860 | static int skl_create(struct pci_dev *pci, |
857 | const struct hdac_io_ops *io_ops, | 861 | struct skl_dev **rskl) |
858 | struct skl **rskl) | ||
859 | { | 862 | { |
860 | struct hdac_ext_bus_ops *ext_ops = NULL; | 863 | struct hdac_ext_bus_ops *ext_ops = NULL; |
861 | struct skl *skl; | 864 | struct skl_dev *skl; |
862 | struct hdac_bus *bus; | 865 | struct hdac_bus *bus; |
863 | struct hda_bus *hbus; | 866 | struct hda_bus *hbus; |
864 | int err; | 867 | int err; |
@@ -884,7 +887,7 @@ static int skl_create(struct pci_dev *pci, | |||
884 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) | 887 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) |
885 | ext_ops = snd_soc_hdac_hda_get_ops(); | 888 | ext_ops = snd_soc_hdac_hda_get_ops(); |
886 | #endif | 889 | #endif |
887 | snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops); | 890 | snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, ext_ops); |
888 | bus->use_posbuf = 1; | 891 | bus->use_posbuf = 1; |
889 | skl->pci = pci; | 892 | skl->pci = pci; |
890 | INIT_WORK(&skl->probe_work, skl_probe_work); | 893 | INIT_WORK(&skl->probe_work, skl_probe_work); |
@@ -902,7 +905,7 @@ static int skl_create(struct pci_dev *pci, | |||
902 | 905 | ||
903 | static int skl_first_init(struct hdac_bus *bus) | 906 | static int skl_first_init(struct hdac_bus *bus) |
904 | { | 907 | { |
905 | struct skl *skl = bus_to_skl(bus); | 908 | struct skl_dev *skl = bus_to_skl(bus); |
906 | struct pci_dev *pci = skl->pci; | 909 | struct pci_dev *pci = skl->pci; |
907 | int err; | 910 | int err; |
908 | unsigned short gcap; | 911 | unsigned short gcap; |
@@ -978,7 +981,7 @@ static int skl_first_init(struct hdac_bus *bus) | |||
978 | static int skl_probe(struct pci_dev *pci, | 981 | static int skl_probe(struct pci_dev *pci, |
979 | const struct pci_device_id *pci_id) | 982 | const struct pci_device_id *pci_id) |
980 | { | 983 | { |
981 | struct skl *skl; | 984 | struct skl_dev *skl; |
982 | struct hdac_bus *bus = NULL; | 985 | struct hdac_bus *bus = NULL; |
983 | int err; | 986 | int err; |
984 | 987 | ||
@@ -1013,7 +1016,7 @@ static int skl_probe(struct pci_dev *pci, | |||
1013 | } | 1016 | } |
1014 | 1017 | ||
1015 | /* we use ext core ops, so provide NULL for ops here */ | 1018 | /* we use ext core ops, so provide NULL for ops here */ |
1016 | err = skl_create(pci, NULL, &skl); | 1019 | err = skl_create(pci, &skl); |
1017 | if (err < 0) | 1020 | if (err < 0) |
1018 | return err; | 1021 | return err; |
1019 | 1022 | ||
@@ -1029,7 +1032,7 @@ static int skl_probe(struct pci_dev *pci, | |||
1029 | 1032 | ||
1030 | device_disable_async_suspend(bus->dev); | 1033 | device_disable_async_suspend(bus->dev); |
1031 | 1034 | ||
1032 | skl->nhlt = skl_nhlt_init(bus->dev); | 1035 | skl->nhlt = intel_nhlt_init(bus->dev); |
1033 | 1036 | ||
1034 | if (skl->nhlt == NULL) { | 1037 | if (skl->nhlt == NULL) { |
1035 | #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) | 1038 | #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) |
@@ -1071,8 +1074,8 @@ static int skl_probe(struct pci_dev *pci, | |||
1071 | dev_dbg(bus->dev, "error failed to register dsp\n"); | 1074 | dev_dbg(bus->dev, "error failed to register dsp\n"); |
1072 | goto out_nhlt_free; | 1075 | goto out_nhlt_free; |
1073 | } | 1076 | } |
1074 | skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge; | 1077 | skl->enable_miscbdcge = skl_enable_miscbdcge; |
1075 | skl->skl_sst->clock_power_gating = skl_clock_power_gating; | 1078 | skl->clock_power_gating = skl_clock_power_gating; |
1076 | 1079 | ||
1077 | if (bus->mlcap) | 1080 | if (bus->mlcap) |
1078 | snd_hdac_ext_bus_get_ml_capabilities(bus); | 1081 | snd_hdac_ext_bus_get_ml_capabilities(bus); |
@@ -1095,7 +1098,7 @@ out_dsp_free: | |||
1095 | out_clk_free: | 1098 | out_clk_free: |
1096 | skl_clock_device_unregister(skl); | 1099 | skl_clock_device_unregister(skl); |
1097 | out_nhlt_free: | 1100 | out_nhlt_free: |
1098 | skl_nhlt_free(skl->nhlt); | 1101 | intel_nhlt_free(skl->nhlt); |
1099 | out_free: | 1102 | out_free: |
1100 | skl_free(bus); | 1103 | skl_free(bus); |
1101 | 1104 | ||
@@ -1107,7 +1110,7 @@ static void skl_shutdown(struct pci_dev *pci) | |||
1107 | struct hdac_bus *bus = pci_get_drvdata(pci); | 1110 | struct hdac_bus *bus = pci_get_drvdata(pci); |
1108 | struct hdac_stream *s; | 1111 | struct hdac_stream *s; |
1109 | struct hdac_ext_stream *stream; | 1112 | struct hdac_ext_stream *stream; |
1110 | struct skl *skl; | 1113 | struct skl_dev *skl; |
1111 | 1114 | ||
1112 | if (!bus) | 1115 | if (!bus) |
1113 | return; | 1116 | return; |
@@ -1129,7 +1132,7 @@ static void skl_shutdown(struct pci_dev *pci) | |||
1129 | static void skl_remove(struct pci_dev *pci) | 1132 | static void skl_remove(struct pci_dev *pci) |
1130 | { | 1133 | { |
1131 | struct hdac_bus *bus = pci_get_drvdata(pci); | 1134 | struct hdac_bus *bus = pci_get_drvdata(pci); |
1132 | struct skl *skl = bus_to_skl(bus); | 1135 | struct skl_dev *skl = bus_to_skl(bus); |
1133 | 1136 | ||
1134 | cancel_work_sync(&skl->probe_work); | 1137 | cancel_work_sync(&skl->probe_work); |
1135 | 1138 | ||
@@ -1144,7 +1147,7 @@ static void skl_remove(struct pci_dev *pci) | |||
1144 | skl_dmic_device_unregister(skl); | 1147 | skl_dmic_device_unregister(skl); |
1145 | skl_clock_device_unregister(skl); | 1148 | skl_clock_device_unregister(skl); |
1146 | skl_nhlt_remove_sysfs(skl); | 1149 | skl_nhlt_remove_sysfs(skl); |
1147 | skl_nhlt_free(skl->nhlt); | 1150 | intel_nhlt_free(skl->nhlt); |
1148 | skl_free(bus); | 1151 | skl_free(bus); |
1149 | dev_set_drvdata(&pci->dev, NULL); | 1152 | dev_set_drvdata(&pci->dev, NULL); |
1150 | } | 1153 | } |
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 6070666a6392..2bfbf59277c4 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h | |||
@@ -16,8 +16,8 @@ | |||
16 | #include <sound/hdaudio_ext.h> | 16 | #include <sound/hdaudio_ext.h> |
17 | #include <sound/hda_codec.h> | 17 | #include <sound/hda_codec.h> |
18 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
19 | #include "skl-nhlt.h" | ||
20 | #include "skl-ssp-clk.h" | 19 | #include "skl-ssp-clk.h" |
20 | #include "skl-sst-ipc.h" | ||
21 | 21 | ||
22 | #define SKL_SUSPEND_DELAY 2000 | 22 | #define SKL_SUSPEND_DELAY 2000 |
23 | 23 | ||
@@ -40,13 +40,6 @@ | |||
40 | #define AZX_VS_EM2_DUM BIT(23) | 40 | #define AZX_VS_EM2_DUM BIT(23) |
41 | #define AZX_REG_VS_EM2_L1SEN BIT(13) | 41 | #define AZX_REG_VS_EM2_L1SEN BIT(13) |
42 | 42 | ||
43 | struct skl_dsp_resource { | ||
44 | u32 max_mcps; | ||
45 | u32 max_mem; | ||
46 | u32 mcps; | ||
47 | u32 mem; | ||
48 | }; | ||
49 | |||
50 | struct skl_debug; | 43 | struct skl_debug; |
51 | 44 | ||
52 | struct skl_astate_param { | 45 | struct skl_astate_param { |
@@ -63,7 +56,7 @@ struct skl_fw_config { | |||
63 | struct skl_astate_config *astate_cfg; | 56 | struct skl_astate_config *astate_cfg; |
64 | }; | 57 | }; |
65 | 58 | ||
66 | struct skl { | 59 | struct skl_dev { |
67 | struct hda_bus hbus; | 60 | struct hda_bus hbus; |
68 | struct pci_dev *pci; | 61 | struct pci_dev *pci; |
69 | 62 | ||
@@ -75,16 +68,13 @@ struct skl { | |||
75 | struct snd_soc_dai_driver *dais; | 68 | struct snd_soc_dai_driver *dais; |
76 | 69 | ||
77 | struct nhlt_acpi_table *nhlt; /* nhlt ptr */ | 70 | struct nhlt_acpi_table *nhlt; /* nhlt ptr */ |
78 | struct skl_sst *skl_sst; /* sst skl ctx */ | ||
79 | 71 | ||
80 | struct skl_dsp_resource resource; | ||
81 | struct list_head ppl_list; | 72 | struct list_head ppl_list; |
82 | struct list_head bind_list; | 73 | struct list_head bind_list; |
83 | 74 | ||
84 | const char *fw_name; | 75 | const char *fw_name; |
85 | char tplg_name[64]; | 76 | char tplg_name[64]; |
86 | unsigned short pci_id; | 77 | unsigned short pci_id; |
87 | const struct firmware *tplg; | ||
88 | 78 | ||
89 | int supend_active; | 79 | int supend_active; |
90 | 80 | ||
@@ -96,13 +86,59 @@ struct skl { | |||
96 | bool use_tplg_pcm; | 86 | bool use_tplg_pcm; |
97 | struct skl_fw_config cfg; | 87 | struct skl_fw_config cfg; |
98 | struct snd_soc_acpi_mach *mach; | 88 | struct snd_soc_acpi_mach *mach; |
89 | |||
90 | struct device *dev; | ||
91 | struct sst_dsp *dsp; | ||
92 | |||
93 | /* boot */ | ||
94 | wait_queue_head_t boot_wait; | ||
95 | bool boot_complete; | ||
96 | |||
97 | /* module load */ | ||
98 | wait_queue_head_t mod_load_wait; | ||
99 | bool mod_load_complete; | ||
100 | bool mod_load_status; | ||
101 | |||
102 | /* IPC messaging */ | ||
103 | struct sst_generic_ipc ipc; | ||
104 | |||
105 | /* callback for miscbdge */ | ||
106 | void (*enable_miscbdcge)(struct device *dev, bool enable); | ||
107 | /* Is CGCTL.MISCBDCGE disabled */ | ||
108 | bool miscbdcg_disabled; | ||
109 | |||
110 | /* Populate module information */ | ||
111 | struct list_head uuid_list; | ||
112 | |||
113 | /* Is firmware loaded */ | ||
114 | bool fw_loaded; | ||
115 | |||
116 | /* first boot ? */ | ||
117 | bool is_first_boot; | ||
118 | |||
119 | /* multi-core */ | ||
120 | struct skl_dsp_cores cores; | ||
121 | |||
122 | /* library info */ | ||
123 | struct skl_lib_info lib_info[SKL_MAX_LIB]; | ||
124 | int lib_count; | ||
125 | |||
126 | /* Callback to update D0i3C register */ | ||
127 | void (*update_d0i3c)(struct device *dev, bool enable); | ||
128 | |||
129 | struct skl_d0i3_data d0i3; | ||
130 | |||
131 | const struct skl_dsp_ops *dsp_ops; | ||
132 | |||
133 | /* Callback to update dynamic clock and power gating registers */ | ||
134 | void (*clock_power_gating)(struct device *dev, bool enable); | ||
99 | }; | 135 | }; |
100 | 136 | ||
101 | #define skl_to_bus(s) (&(s)->hbus.core) | 137 | #define skl_to_bus(s) (&(s)->hbus.core) |
102 | #define bus_to_skl(bus) container_of(bus, struct skl, hbus.core) | 138 | #define bus_to_skl(bus) container_of(bus, struct skl_dev, hbus.core) |
103 | 139 | ||
104 | #define skl_to_hbus(s) (&(s)->hbus) | 140 | #define skl_to_hbus(s) (&(s)->hbus) |
105 | #define hbus_to_skl(hbus) container_of((hbus), struct skl, (hbus)) | 141 | #define hbus_to_skl(hbus) container_of((hbus), struct skl_dev, (hbus)) |
106 | 142 | ||
107 | /* to pass dai dma data */ | 143 | /* to pass dai dma data */ |
108 | struct skl_dma_params { | 144 | struct skl_dma_params { |
@@ -121,52 +157,49 @@ struct skl_dsp_ops { | |||
121 | int (*init)(struct device *dev, void __iomem *mmio_base, | 157 | int (*init)(struct device *dev, void __iomem *mmio_base, |
122 | int irq, const char *fw_name, | 158 | int irq, const char *fw_name, |
123 | struct skl_dsp_loader_ops loader_ops, | 159 | struct skl_dsp_loader_ops loader_ops, |
124 | struct skl_sst **skl_sst); | 160 | struct skl_dev **skl_sst); |
125 | int (*init_fw)(struct device *dev, struct skl_sst *ctx); | 161 | int (*init_fw)(struct device *dev, struct skl_dev *skl); |
126 | void (*cleanup)(struct device *dev, struct skl_sst *ctx); | 162 | void (*cleanup)(struct device *dev, struct skl_dev *skl); |
127 | }; | 163 | }; |
128 | 164 | ||
129 | int skl_platform_unregister(struct device *dev); | 165 | int skl_platform_unregister(struct device *dev); |
130 | int skl_platform_register(struct device *dev); | 166 | int skl_platform_register(struct device *dev); |
131 | 167 | ||
132 | struct nhlt_acpi_table *skl_nhlt_init(struct device *dev); | 168 | struct nhlt_specific_cfg *skl_get_ep_blob(struct skl_dev *skl, u32 instance, |
133 | void skl_nhlt_free(struct nhlt_acpi_table *addr); | ||
134 | struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, | ||
135 | u8 link_type, u8 s_fmt, u8 no_ch, | 169 | u8 link_type, u8 s_fmt, u8 no_ch, |
136 | u32 s_rate, u8 dirn, u8 dev_type); | 170 | u32 s_rate, u8 dirn, u8 dev_type); |
137 | 171 | ||
138 | int skl_get_dmic_geo(struct skl *skl); | 172 | int skl_nhlt_update_topology_bin(struct skl_dev *skl); |
139 | int skl_nhlt_update_topology_bin(struct skl *skl); | 173 | int skl_init_dsp(struct skl_dev *skl); |
140 | int skl_init_dsp(struct skl *skl); | 174 | int skl_free_dsp(struct skl_dev *skl); |
141 | int skl_free_dsp(struct skl *skl); | 175 | int skl_suspend_late_dsp(struct skl_dev *skl); |
142 | int skl_suspend_late_dsp(struct skl *skl); | 176 | int skl_suspend_dsp(struct skl_dev *skl); |
143 | int skl_suspend_dsp(struct skl *skl); | 177 | int skl_resume_dsp(struct skl_dev *skl); |
144 | int skl_resume_dsp(struct skl *skl); | 178 | void skl_cleanup_resources(struct skl_dev *skl); |
145 | void skl_cleanup_resources(struct skl *skl); | ||
146 | const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); | 179 | const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); |
147 | void skl_update_d0i3c(struct device *dev, bool enable); | 180 | void skl_update_d0i3c(struct device *dev, bool enable); |
148 | int skl_nhlt_create_sysfs(struct skl *skl); | 181 | int skl_nhlt_create_sysfs(struct skl_dev *skl); |
149 | void skl_nhlt_remove_sysfs(struct skl *skl); | 182 | void skl_nhlt_remove_sysfs(struct skl_dev *skl); |
150 | void skl_get_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks); | 183 | void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks); |
151 | struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id); | 184 | struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id); |
152 | int skl_dsp_set_dma_control(struct skl_sst *ctx, u32 *caps, | 185 | int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, |
153 | u32 caps_size, u32 node_id); | 186 | u32 caps_size, u32 node_id); |
154 | 187 | ||
155 | struct skl_module_cfg; | 188 | struct skl_module_cfg; |
156 | 189 | ||
157 | #ifdef CONFIG_DEBUG_FS | 190 | #ifdef CONFIG_DEBUG_FS |
158 | struct skl_debug *skl_debugfs_init(struct skl *skl); | 191 | struct skl_debug *skl_debugfs_init(struct skl_dev *skl); |
159 | void skl_debugfs_exit(struct skl *skl); | 192 | void skl_debugfs_exit(struct skl_dev *skl); |
160 | void skl_debug_init_module(struct skl_debug *d, | 193 | void skl_debug_init_module(struct skl_debug *d, |
161 | struct snd_soc_dapm_widget *w, | 194 | struct snd_soc_dapm_widget *w, |
162 | struct skl_module_cfg *mconfig); | 195 | struct skl_module_cfg *mconfig); |
163 | #else | 196 | #else |
164 | static inline struct skl_debug *skl_debugfs_init(struct skl *skl) | 197 | static inline struct skl_debug *skl_debugfs_init(struct skl_dev *skl) |
165 | { | 198 | { |
166 | return NULL; | 199 | return NULL; |
167 | } | 200 | } |
168 | 201 | ||
169 | static inline void skl_debugfs_exit(struct skl *skl) | 202 | static inline void skl_debugfs_exit(struct skl_dev *skl) |
170 | {} | 203 | {} |
171 | 204 | ||
172 | static inline void skl_debug_init_module(struct skl_debug *d, | 205 | static inline void skl_debug_init_module(struct skl_debug *d, |
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 3446a113f482..61226fefe1c4 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
@@ -523,7 +523,6 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) | |||
523 | struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; | 523 | struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data; |
524 | struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai; | 524 | struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai; |
525 | struct kirkwood_dma_data *priv; | 525 | struct kirkwood_dma_data *priv; |
526 | struct resource *mem; | ||
527 | struct device_node *np = pdev->dev.of_node; | 526 | struct device_node *np = pdev->dev.of_node; |
528 | int err; | 527 | int err; |
529 | 528 | ||
@@ -533,16 +532,13 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) | |||
533 | 532 | ||
534 | dev_set_drvdata(&pdev->dev, priv); | 533 | dev_set_drvdata(&pdev->dev, priv); |
535 | 534 | ||
536 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 535 | priv->io = devm_platform_ioremap_resource(pdev, 0); |
537 | priv->io = devm_ioremap_resource(&pdev->dev, mem); | ||
538 | if (IS_ERR(priv->io)) | 536 | if (IS_ERR(priv->io)) |
539 | return PTR_ERR(priv->io); | 537 | return PTR_ERR(priv->io); |
540 | 538 | ||
541 | priv->irq = platform_get_irq(pdev, 0); | 539 | priv->irq = platform_get_irq(pdev, 0); |
542 | if (priv->irq < 0) { | 540 | if (priv->irq < 0) |
543 | dev_err(&pdev->dev, "platform_get_irq failed: %d\n", priv->irq); | ||
544 | return priv->irq; | 541 | return priv->irq; |
545 | } | ||
546 | 542 | ||
547 | if (np) { | 543 | if (np) { |
548 | priv->burst = 128; /* might be 32 or 128 */ | 544 | priv->burst = 128; /* might be 32 or 128 */ |
diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c index c7a81c4be068..d00608c73c6e 100644 --- a/sound/soc/mediatek/common/mtk-btcvsd.c +++ b/sound/soc/mediatek/common/mtk-btcvsd.c | |||
@@ -1335,10 +1335,8 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev) | |||
1335 | 1335 | ||
1336 | /* irq */ | 1336 | /* irq */ |
1337 | irq_id = platform_get_irq(pdev, 0); | 1337 | irq_id = platform_get_irq(pdev, 0); |
1338 | if (irq_id <= 0) { | 1338 | if (irq_id <= 0) |
1339 | dev_err(dev, "%pOFn no irq found\n", dev->of_node); | ||
1340 | return irq_id < 0 ? irq_id : -ENXIO; | 1339 | return irq_id < 0 ? irq_id : -ENXIO; |
1341 | } | ||
1342 | 1340 | ||
1343 | ret = devm_request_irq(dev, irq_id, mtk_btcvsd_snd_irq_handler, | 1341 | ret = devm_request_irq(dev, irq_id, mtk_btcvsd_snd_irq_handler, |
1344 | IRQF_TRIGGER_LOW, "BTCVSD_ISR_Handle", | 1342 | IRQF_TRIGGER_LOW, "BTCVSD_ISR_Handle", |
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h index d44faba27d3c..32bef5e2a56d 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h +++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h | |||
@@ -63,27 +63,6 @@ enum audio_base_clock { | |||
63 | MT2701_BASE_CLK_NUM, | 63 | MT2701_BASE_CLK_NUM, |
64 | }; | 64 | }; |
65 | 65 | ||
66 | static const unsigned int mt2701_afe_backup_list[] = { | ||
67 | AUDIO_TOP_CON0, | ||
68 | AUDIO_TOP_CON4, | ||
69 | AUDIO_TOP_CON5, | ||
70 | ASYS_TOP_CON, | ||
71 | AFE_CONN0, | ||
72 | AFE_CONN1, | ||
73 | AFE_CONN2, | ||
74 | AFE_CONN3, | ||
75 | AFE_CONN15, | ||
76 | AFE_CONN16, | ||
77 | AFE_CONN17, | ||
78 | AFE_CONN18, | ||
79 | AFE_CONN19, | ||
80 | AFE_CONN20, | ||
81 | AFE_CONN21, | ||
82 | AFE_CONN22, | ||
83 | AFE_DAC_CON0, | ||
84 | AFE_MEMIF_PBUF_SIZE, | ||
85 | }; | ||
86 | |||
87 | struct mt2701_i2s_data { | 66 | struct mt2701_i2s_data { |
88 | int i2s_ctrl_reg; | 67 | int i2s_ctrl_reg; |
89 | int i2s_asrc_fs_shift; | 68 | int i2s_asrc_fs_shift; |
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index 7064a9fd6f74..76502ba261c8 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | |||
@@ -60,6 +60,27 @@ static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = { | |||
60 | { .rate = 352800, .regvalue = 24 }, | 60 | { .rate = 352800, .regvalue = 24 }, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | static const unsigned int mt2701_afe_backup_list[] = { | ||
64 | AUDIO_TOP_CON0, | ||
65 | AUDIO_TOP_CON4, | ||
66 | AUDIO_TOP_CON5, | ||
67 | ASYS_TOP_CON, | ||
68 | AFE_CONN0, | ||
69 | AFE_CONN1, | ||
70 | AFE_CONN2, | ||
71 | AFE_CONN3, | ||
72 | AFE_CONN15, | ||
73 | AFE_CONN16, | ||
74 | AFE_CONN17, | ||
75 | AFE_CONN18, | ||
76 | AFE_CONN19, | ||
77 | AFE_CONN20, | ||
78 | AFE_CONN21, | ||
79 | AFE_CONN22, | ||
80 | AFE_DAC_CON0, | ||
81 | AFE_MEMIF_PBUF_SIZE, | ||
82 | }; | ||
83 | |||
63 | static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num) | 84 | static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num) |
64 | { | 85 | { |
65 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | 86 | struct mt2701_afe_private *afe_priv = afe->platform_priv; |
@@ -796,14 +817,6 @@ static const struct snd_kcontrol_new mt2701_afe_o22_mix[] = { | |||
796 | SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0), | 817 | SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0), |
797 | }; | 818 | }; |
798 | 819 | ||
799 | static const struct snd_kcontrol_new mt2701_afe_o23_mix[] = { | ||
800 | SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN23, 20, 1, 0), | ||
801 | }; | ||
802 | |||
803 | static const struct snd_kcontrol_new mt2701_afe_o24_mix[] = { | ||
804 | SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN24, 21, 1, 0), | ||
805 | }; | ||
806 | |||
807 | static const struct snd_kcontrol_new mt2701_afe_o31_mix[] = { | 820 | static const struct snd_kcontrol_new mt2701_afe_o31_mix[] = { |
808 | SOC_DAPM_SINGLE_AUTODISABLE("I35 Switch", AFE_CONN41, 9, 1, 0), | 821 | SOC_DAPM_SINGLE_AUTODISABLE("I35 Switch", AFE_CONN41, 9, 1, 0), |
809 | }; | 822 | }; |
@@ -832,11 +845,6 @@ static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s3[] = { | |||
832 | PWR2_TOP_CON, 18, 1, 0), | 845 | PWR2_TOP_CON, 18, 1, 0), |
833 | }; | 846 | }; |
834 | 847 | ||
835 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s4[] = { | ||
836 | SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S4 Out Switch", | ||
837 | PWR2_TOP_CON, 19, 1, 0), | ||
838 | }; | ||
839 | |||
840 | static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = { | 848 | static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = { |
841 | /* inter-connections */ | 849 | /* inter-connections */ |
842 | SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0), | 850 | SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0), |
@@ -1342,10 +1350,8 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) | |||
1342 | return -ENOMEM; | 1350 | return -ENOMEM; |
1343 | 1351 | ||
1344 | irq_id = platform_get_irq_byname(pdev, "asys"); | 1352 | irq_id = platform_get_irq_byname(pdev, "asys"); |
1345 | if (irq_id < 0) { | 1353 | if (irq_id < 0) |
1346 | dev_err(dev, "unable to get ASYS IRQ\n"); | ||
1347 | return irq_id; | 1354 | return irq_id; |
1348 | } | ||
1349 | 1355 | ||
1350 | ret = devm_request_irq(dev, irq_id, mt2701_asys_isr, | 1356 | ret = devm_request_irq(dev, irq_id, mt2701_asys_isr, |
1351 | IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); | 1357 | IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); |
diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index 08a6532da322..e52c032d53aa 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | |||
@@ -749,7 +749,6 @@ static int mt6797_afe_pcm_dev_probe(struct platform_device *pdev) | |||
749 | { | 749 | { |
750 | struct mtk_base_afe *afe; | 750 | struct mtk_base_afe *afe; |
751 | struct mt6797_afe_private *afe_priv; | 751 | struct mt6797_afe_private *afe_priv; |
752 | struct resource *res; | ||
753 | struct device *dev; | 752 | struct device *dev; |
754 | int i, irq_id, ret; | 753 | int i, irq_id, ret; |
755 | 754 | ||
@@ -774,9 +773,7 @@ static int mt6797_afe_pcm_dev_probe(struct platform_device *pdev) | |||
774 | } | 773 | } |
775 | 774 | ||
776 | /* regmap init */ | 775 | /* regmap init */ |
777 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 776 | afe->base_addr = devm_platform_ioremap_resource(pdev, 0); |
778 | |||
779 | afe->base_addr = devm_ioremap_resource(&pdev->dev, res); | ||
780 | if (IS_ERR(afe->base_addr)) | 777 | if (IS_ERR(afe->base_addr)) |
781 | return PTR_ERR(afe->base_addr); | 778 | return PTR_ERR(afe->base_addr); |
782 | 779 | ||
diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 0382896c162e..0ee29255e731 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | |||
@@ -1056,7 +1056,6 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) | |||
1056 | int irq_id; | 1056 | int irq_id; |
1057 | struct mtk_base_afe *afe; | 1057 | struct mtk_base_afe *afe; |
1058 | struct mt8173_afe_private *afe_priv; | 1058 | struct mt8173_afe_private *afe_priv; |
1059 | struct resource *res; | ||
1060 | 1059 | ||
1061 | ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); | 1060 | ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); |
1062 | if (ret) | 1061 | if (ret) |
@@ -1075,10 +1074,8 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) | |||
1075 | afe->dev = &pdev->dev; | 1074 | afe->dev = &pdev->dev; |
1076 | 1075 | ||
1077 | irq_id = platform_get_irq(pdev, 0); | 1076 | irq_id = platform_get_irq(pdev, 0); |
1078 | if (irq_id <= 0) { | 1077 | if (irq_id <= 0) |
1079 | dev_err(afe->dev, "np %pOFn no irq\n", afe->dev->of_node); | ||
1080 | return irq_id < 0 ? irq_id : -ENXIO; | 1078 | return irq_id < 0 ? irq_id : -ENXIO; |
1081 | } | ||
1082 | ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, | 1079 | ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, |
1083 | 0, "Afe_ISR_Handle", (void *)afe); | 1080 | 0, "Afe_ISR_Handle", (void *)afe); |
1084 | if (ret) { | 1081 | if (ret) { |
@@ -1086,8 +1083,7 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) | |||
1086 | return ret; | 1083 | return ret; |
1087 | } | 1084 | } |
1088 | 1085 | ||
1089 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1086 | afe->base_addr = devm_platform_ioremap_resource(pdev, 0); |
1090 | afe->base_addr = devm_ioremap_resource(&pdev->dev, res); | ||
1091 | if (IS_ERR(afe->base_addr)) | 1087 | if (IS_ERR(afe->base_addr)) |
1092 | return PTR_ERR(afe->base_addr); | 1088 | return PTR_ERR(afe->base_addr); |
1093 | 1089 | ||
diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 59076e21cb47..43f99e59a078 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | |||
@@ -116,15 +116,6 @@ static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | |||
116 | return 0; | 116 | return 0; |
117 | } | 117 | } |
118 | 118 | ||
119 | static const struct snd_soc_dapm_widget | ||
120 | mt8183_da7219_max98357_dapm_widgets[] = { | ||
121 | SND_SOC_DAPM_OUTPUT("IT6505_8CH"), | ||
122 | }; | ||
123 | |||
124 | static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = { | ||
125 | {"IT6505_8CH", NULL, "TDM"}, | ||
126 | }; | ||
127 | |||
128 | /* FE */ | 119 | /* FE */ |
129 | SND_SOC_DAILINK_DEFS(playback1, | 120 | SND_SOC_DAILINK_DEFS(playback1, |
130 | DAILINK_COMP_ARRAY(COMP_CPU("DL1")), | 121 | DAILINK_COMP_ARRAY(COMP_CPU("DL1")), |
@@ -370,7 +361,7 @@ static int | |||
370 | mt8183_da7219_max98357_headset_init(struct snd_soc_component *component); | 361 | mt8183_da7219_max98357_headset_init(struct snd_soc_component *component); |
371 | 362 | ||
372 | static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = { | 363 | static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = { |
373 | .name = "Headset Chip", | 364 | .dlc = COMP_EMPTY(), |
374 | .init = mt8183_da7219_max98357_headset_init, | 365 | .init = mt8183_da7219_max98357_headset_init, |
375 | }; | 366 | }; |
376 | 367 | ||
@@ -436,10 +427,10 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) | |||
436 | dai_link->platforms->of_node = platform_node; | 427 | dai_link->platforms->of_node = platform_node; |
437 | } | 428 | } |
438 | 429 | ||
439 | mt8183_da7219_max98357_headset_dev.codec_of_node = | 430 | mt8183_da7219_max98357_headset_dev.dlc.of_node = |
440 | of_parse_phandle(pdev->dev.of_node, | 431 | of_parse_phandle(pdev->dev.of_node, |
441 | "mediatek,headset-codec", 0); | 432 | "mediatek,headset-codec", 0); |
442 | if (!mt8183_da7219_max98357_headset_dev.codec_of_node) { | 433 | if (!mt8183_da7219_max98357_headset_dev.dlc.of_node) { |
443 | dev_err(&pdev->dev, | 434 | dev_err(&pdev->dev, |
444 | "Property 'mediatek,headset-codec' missing/invalid\n"); | 435 | "Property 'mediatek,headset-codec' missing/invalid\n"); |
445 | return -EINVAL; | 436 | return -EINVAL; |
diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-tdm.c b/sound/soc/mediatek/mt8183/mt8183-dai-tdm.c index 8983d54a9b67..0d69cf440407 100644 --- a/sound/soc/mediatek/mt8183/mt8183-dai-tdm.c +++ b/sound/soc/mediatek/mt8183/mt8183-dai-tdm.c | |||
@@ -15,7 +15,9 @@ | |||
15 | struct mtk_afe_tdm_priv { | 15 | struct mtk_afe_tdm_priv { |
16 | int bck_id; | 16 | int bck_id; |
17 | int bck_rate; | 17 | int bck_rate; |
18 | 18 | int tdm_out_mode; | |
19 | int bck_invert; | ||
20 | int lck_invert; | ||
19 | int mclk_id; | 21 | int mclk_id; |
20 | int mclk_multiple; /* according to sample rate */ | 22 | int mclk_multiple; /* according to sample rate */ |
21 | int mclk_rate; | 23 | int mclk_rate; |
@@ -23,6 +25,21 @@ struct mtk_afe_tdm_priv { | |||
23 | }; | 25 | }; |
24 | 26 | ||
25 | enum { | 27 | enum { |
28 | TDM_OUT_I2S = 0, | ||
29 | TDM_OUT_TDM = 1, | ||
30 | }; | ||
31 | |||
32 | enum { | ||
33 | TDM_BCK_NON_INV = 0, | ||
34 | TDM_BCK_INV = 1, | ||
35 | }; | ||
36 | |||
37 | enum { | ||
38 | TDM_LCK_NON_INV = 0, | ||
39 | TDM_LCK_INV = 1, | ||
40 | }; | ||
41 | |||
42 | enum { | ||
26 | TDM_WLEN_16_BIT = 1, | 43 | TDM_WLEN_16_BIT = 1, |
27 | TDM_WLEN_32_BIT = 2, | 44 | TDM_WLEN_32_BIT = 2, |
28 | }; | 45 | }; |
@@ -93,6 +110,25 @@ static unsigned int get_tdm_ch(unsigned int ch) | |||
93 | } | 110 | } |
94 | } | 111 | } |
95 | 112 | ||
113 | static unsigned int get_tdm_ch_fixup(unsigned int channels) | ||
114 | { | ||
115 | if (channels > 4) | ||
116 | return 8; | ||
117 | else if (channels > 2) | ||
118 | return 4; | ||
119 | else | ||
120 | return 2; | ||
121 | } | ||
122 | |||
123 | static unsigned int get_tdm_ch_per_sdata(unsigned int mode, | ||
124 | unsigned int channels) | ||
125 | { | ||
126 | if (mode == TDM_OUT_TDM) | ||
127 | return get_tdm_ch_fixup(channels); | ||
128 | else | ||
129 | return 2; | ||
130 | } | ||
131 | |||
96 | /* interconnection */ | 132 | /* interconnection */ |
97 | enum { | 133 | enum { |
98 | HDMI_CONN_CH0 = 0, | 134 | HDMI_CONN_CH0 = 0, |
@@ -433,8 +469,11 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, | |||
433 | struct mt8183_afe_private *afe_priv = afe->platform_priv; | 469 | struct mt8183_afe_private *afe_priv = afe->platform_priv; |
434 | int tdm_id = dai->id; | 470 | int tdm_id = dai->id; |
435 | struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id]; | 471 | struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id]; |
472 | unsigned int tdm_out_mode = tdm_priv->tdm_out_mode; | ||
436 | unsigned int rate = params_rate(params); | 473 | unsigned int rate = params_rate(params); |
437 | unsigned int channels = params_channels(params); | 474 | unsigned int channels = params_channels(params); |
475 | unsigned int out_channels_per_sdata = | ||
476 | get_tdm_ch_per_sdata(tdm_out_mode, channels); | ||
438 | snd_pcm_format_t format = params_format(params); | 477 | snd_pcm_format_t format = params_format(params); |
439 | unsigned int tdm_con = 0; | 478 | unsigned int tdm_con = 0; |
440 | 479 | ||
@@ -448,7 +487,7 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, | |||
448 | 487 | ||
449 | /* calculate bck */ | 488 | /* calculate bck */ |
450 | tdm_priv->bck_rate = rate * | 489 | tdm_priv->bck_rate = rate * |
451 | channels * | 490 | out_channels_per_sdata * |
452 | snd_pcm_format_physical_width(format); | 491 | snd_pcm_format_physical_width(format); |
453 | 492 | ||
454 | if (tdm_priv->bck_rate > tdm_priv->mclk_rate) | 493 | if (tdm_priv->bck_rate > tdm_priv->mclk_rate) |
@@ -461,50 +500,72 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, | |||
461 | __func__, | 500 | __func__, |
462 | tdm_id, rate, channels, format, | 501 | tdm_id, rate, channels, format, |
463 | tdm_priv->mclk_rate, tdm_priv->bck_rate); | 502 | tdm_priv->mclk_rate, tdm_priv->bck_rate); |
503 | dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n", | ||
504 | __func__, out_channels_per_sdata); | ||
464 | 505 | ||
465 | /* set tdm */ | 506 | /* set tdm */ |
466 | tdm_con = 1 << BCK_INVERSE_SFT; | 507 | if (tdm_priv->bck_invert) |
467 | tdm_con |= 1 << LRCK_INVERSE_SFT; | 508 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON3, |
468 | tdm_con |= 1 << DELAY_DATA_SFT; | 509 | BCK_INVERSE_MASK_SFT, |
510 | 0x1 << BCK_INVERSE_SFT); | ||
511 | |||
512 | if (tdm_priv->lck_invert) | ||
513 | tdm_con |= 1 << LRCK_INVERSE_SFT; | ||
514 | |||
515 | if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) { | ||
516 | tdm_con |= 1 << DELAY_DATA_SFT; | ||
517 | tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT; | ||
518 | } else if (tdm_priv->tdm_out_mode == TDM_OUT_TDM) { | ||
519 | tdm_con |= 0 << DELAY_DATA_SFT; | ||
520 | tdm_con |= 0 << LRCK_TDM_WIDTH_SFT; | ||
521 | } | ||
522 | |||
469 | tdm_con |= 1 << LEFT_ALIGN_SFT; | 523 | tdm_con |= 1 << LEFT_ALIGN_SFT; |
470 | tdm_con |= get_tdm_wlen(format) << WLEN_SFT; | 524 | tdm_con |= get_tdm_wlen(format) << WLEN_SFT; |
471 | tdm_con |= get_tdm_ch(channels) << CHANNEL_NUM_SFT; | 525 | tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT; |
472 | tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT; | 526 | tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT; |
473 | tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT; | ||
474 | regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con); | 527 | regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con); |
475 | 528 | ||
476 | switch (channels) { | 529 | if (out_channels_per_sdata == 2) { |
477 | case 1: | 530 | switch (channels) { |
478 | case 2: | 531 | case 1: |
532 | case 2: | ||
533 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; | ||
534 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT; | ||
535 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; | ||
536 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; | ||
537 | break; | ||
538 | case 3: | ||
539 | case 4: | ||
540 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; | ||
541 | tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; | ||
542 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; | ||
543 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; | ||
544 | break; | ||
545 | case 5: | ||
546 | case 6: | ||
547 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; | ||
548 | tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; | ||
549 | tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; | ||
550 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; | ||
551 | break; | ||
552 | case 7: | ||
553 | case 8: | ||
554 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; | ||
555 | tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; | ||
556 | tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; | ||
557 | tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT; | ||
558 | break; | ||
559 | default: | ||
560 | tdm_con = 0; | ||
561 | } | ||
562 | } else { | ||
479 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; | 563 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; |
480 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT; | 564 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT; |
481 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; | 565 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; |
482 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; | 566 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; |
483 | break; | ||
484 | case 3: | ||
485 | case 4: | ||
486 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; | ||
487 | tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; | ||
488 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; | ||
489 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; | ||
490 | break; | ||
491 | case 5: | ||
492 | case 6: | ||
493 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; | ||
494 | tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; | ||
495 | tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; | ||
496 | tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; | ||
497 | break; | ||
498 | case 7: | ||
499 | case 8: | ||
500 | tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; | ||
501 | tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; | ||
502 | tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; | ||
503 | tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT; | ||
504 | break; | ||
505 | default: | ||
506 | tdm_con = 0; | ||
507 | } | 567 | } |
568 | |||
508 | regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con); | 569 | regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con); |
509 | 570 | ||
510 | regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, | 571 | regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, |
@@ -573,10 +634,58 @@ static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai, | |||
573 | return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); | 634 | return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); |
574 | } | 635 | } |
575 | 636 | ||
637 | static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
638 | { | ||
639 | struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); | ||
640 | struct mt8183_afe_private *afe_priv = afe->platform_priv; | ||
641 | struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; | ||
642 | |||
643 | if (!tdm_priv) { | ||
644 | dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__); | ||
645 | return -EINVAL; | ||
646 | } | ||
647 | |||
648 | /* DAI mode*/ | ||
649 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
650 | case SND_SOC_DAIFMT_I2S: | ||
651 | tdm_priv->tdm_out_mode = TDM_OUT_I2S; | ||
652 | break; | ||
653 | case SND_SOC_DAIFMT_DSP_A: | ||
654 | tdm_priv->tdm_out_mode = TDM_OUT_TDM; | ||
655 | break; | ||
656 | default: | ||
657 | tdm_priv->tdm_out_mode = TDM_OUT_I2S; | ||
658 | } | ||
659 | |||
660 | /* DAI clock inversion*/ | ||
661 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
662 | case SND_SOC_DAIFMT_NB_NF: | ||
663 | tdm_priv->bck_invert = TDM_BCK_NON_INV; | ||
664 | tdm_priv->lck_invert = TDM_LCK_NON_INV; | ||
665 | break; | ||
666 | case SND_SOC_DAIFMT_NB_IF: | ||
667 | tdm_priv->bck_invert = TDM_BCK_NON_INV; | ||
668 | tdm_priv->lck_invert = TDM_LCK_INV; | ||
669 | break; | ||
670 | case SND_SOC_DAIFMT_IB_NF: | ||
671 | tdm_priv->bck_invert = TDM_BCK_INV; | ||
672 | tdm_priv->lck_invert = TDM_LCK_NON_INV; | ||
673 | break; | ||
674 | case SND_SOC_DAIFMT_IB_IF: | ||
675 | default: | ||
676 | tdm_priv->bck_invert = TDM_BCK_INV; | ||
677 | tdm_priv->lck_invert = TDM_LCK_INV; | ||
678 | break; | ||
679 | } | ||
680 | |||
681 | return 0; | ||
682 | } | ||
683 | |||
576 | static const struct snd_soc_dai_ops mtk_dai_tdm_ops = { | 684 | static const struct snd_soc_dai_ops mtk_dai_tdm_ops = { |
577 | .hw_params = mtk_dai_tdm_hw_params, | 685 | .hw_params = mtk_dai_tdm_hw_params, |
578 | .trigger = mtk_dai_tdm_trigger, | 686 | .trigger = mtk_dai_tdm_trigger, |
579 | .set_sysclk = mtk_dai_tdm_set_sysclk, | 687 | .set_sysclk = mtk_dai_tdm_set_sysclk, |
688 | .set_fmt = mtk_dai_tdm_set_fmt, | ||
580 | }; | 689 | }; |
581 | 690 | ||
582 | /* dai driver */ | 691 | /* dai driver */ |
diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 887c932229d0..bb9cdc0d6552 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | |||
@@ -15,7 +15,22 @@ | |||
15 | #include "mt8183-afe-common.h" | 15 | #include "mt8183-afe-common.h" |
16 | #include "../../codecs/ts3a227e.h" | 16 | #include "../../codecs/ts3a227e.h" |
17 | 17 | ||
18 | static struct snd_soc_jack headset_jack; | 18 | enum PINCTRL_PIN_STATE { |
19 | PIN_STATE_DEFAULT = 0, | ||
20 | PIN_TDM_OUT_ON, | ||
21 | PIN_TDM_OUT_OFF, | ||
22 | PIN_STATE_MAX | ||
23 | }; | ||
24 | |||
25 | static const char * const mt8183_pin_str[PIN_STATE_MAX] = { | ||
26 | "default", "aud_tdm_out_on", "aud_tdm_out_off", | ||
27 | }; | ||
28 | |||
29 | struct mt8183_mt6358_ts3a227_max98357_priv { | ||
30 | struct pinctrl *pinctrl; | ||
31 | struct pinctrl_state *pin_states[PIN_STATE_MAX]; | ||
32 | struct snd_soc_jack headset_jack; | ||
33 | }; | ||
19 | 34 | ||
20 | static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, | 35 | static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, |
21 | struct snd_pcm_hw_params *params) | 36 | struct snd_pcm_hw_params *params) |
@@ -46,16 +61,6 @@ static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | |||
46 | return 0; | 61 | return 0; |
47 | } | 62 | } |
48 | 63 | ||
49 | static const struct snd_soc_dapm_widget | ||
50 | mt8183_mt6358_ts3a227_max98357_dapm_widgets[] = { | ||
51 | SND_SOC_DAPM_OUTPUT("IT6505_8CH"), | ||
52 | }; | ||
53 | |||
54 | static const struct snd_soc_dapm_route | ||
55 | mt8183_mt6358_ts3a227_max98357_dapm_routes[] = { | ||
56 | {"IT6505_8CH", NULL, "TDM"}, | ||
57 | }; | ||
58 | |||
59 | static int | 64 | static int |
60 | mt8183_mt6358_ts3a227_max98357_bt_sco_startup( | 65 | mt8183_mt6358_ts3a227_max98357_bt_sco_startup( |
61 | struct snd_pcm_substream *substream) | 66 | struct snd_pcm_substream *substream) |
@@ -183,6 +188,47 @@ SND_SOC_DAILINK_DEFS(tdm, | |||
183 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | 188 | DAILINK_COMP_ARRAY(COMP_DUMMY()), |
184 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | 189 | DAILINK_COMP_ARRAY(COMP_EMPTY())); |
185 | 190 | ||
191 | static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream) | ||
192 | { | ||
193 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
194 | struct mt8183_mt6358_ts3a227_max98357_priv *priv = | ||
195 | snd_soc_card_get_drvdata(rtd->card); | ||
196 | int ret; | ||
197 | |||
198 | if (IS_ERR(priv->pin_states[PIN_TDM_OUT_ON])) | ||
199 | return PTR_ERR(priv->pin_states[PIN_TDM_OUT_ON]); | ||
200 | |||
201 | ret = pinctrl_select_state(priv->pinctrl, | ||
202 | priv->pin_states[PIN_TDM_OUT_ON]); | ||
203 | if (ret) | ||
204 | dev_err(rtd->card->dev, "%s failed to select state %d\n", | ||
205 | __func__, ret); | ||
206 | |||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | static void mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream *substream) | ||
211 | { | ||
212 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
213 | struct mt8183_mt6358_ts3a227_max98357_priv *priv = | ||
214 | snd_soc_card_get_drvdata(rtd->card); | ||
215 | int ret; | ||
216 | |||
217 | if (IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) | ||
218 | return; | ||
219 | |||
220 | ret = pinctrl_select_state(priv->pinctrl, | ||
221 | priv->pin_states[PIN_TDM_OUT_OFF]); | ||
222 | if (ret) | ||
223 | dev_err(rtd->card->dev, "%s failed to select state %d\n", | ||
224 | __func__, ret); | ||
225 | } | ||
226 | |||
227 | static struct snd_soc_ops mt8183_mt6358_tdm_ops = { | ||
228 | .startup = mt8183_mt6358_tdm_startup, | ||
229 | .shutdown = mt8183_mt6358_tdm_shutdown, | ||
230 | }; | ||
231 | |||
186 | static struct snd_soc_dai_link | 232 | static struct snd_soc_dai_link |
187 | mt8183_mt6358_ts3a227_max98357_dai_links[] = { | 233 | mt8183_mt6358_ts3a227_max98357_dai_links[] = { |
188 | /* FE */ | 234 | /* FE */ |
@@ -333,33 +379,30 @@ mt8183_mt6358_ts3a227_max98357_dai_links[] = { | |||
333 | { | 379 | { |
334 | .name = "TDM", | 380 | .name = "TDM", |
335 | .no_pcm = 1, | 381 | .no_pcm = 1, |
382 | .dai_fmt = SND_SOC_DAIFMT_I2S | | ||
383 | SND_SOC_DAIFMT_IB_IF | | ||
384 | SND_SOC_DAIFMT_CBM_CFM, | ||
336 | .dpcm_playback = 1, | 385 | .dpcm_playback = 1, |
337 | .ignore_suspend = 1, | 386 | .ignore_suspend = 1, |
387 | .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, | ||
388 | .ops = &mt8183_mt6358_tdm_ops, | ||
338 | SND_SOC_DAILINK_REG(tdm), | 389 | SND_SOC_DAILINK_REG(tdm), |
339 | }, | 390 | }, |
340 | }; | 391 | }; |
341 | 392 | ||
342 | static int | ||
343 | mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *cpnt); | ||
344 | |||
345 | static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = { | ||
346 | .name = "Headset Chip", | ||
347 | .init = mt8183_mt6358_ts3a227_max98357_headset_init, | ||
348 | }; | ||
349 | |||
350 | static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = { | 393 | static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = { |
351 | .name = "mt8183_mt6358_ts3a227_max98357", | 394 | .name = "mt8183_mt6358_ts3a227_max98357", |
352 | .owner = THIS_MODULE, | 395 | .owner = THIS_MODULE, |
353 | .dai_link = mt8183_mt6358_ts3a227_max98357_dai_links, | 396 | .dai_link = mt8183_mt6358_ts3a227_max98357_dai_links, |
354 | .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dai_links), | 397 | .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dai_links), |
355 | .aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev, | ||
356 | .num_aux_devs = 1, | ||
357 | }; | 398 | }; |
358 | 399 | ||
359 | static int | 400 | static int |
360 | mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) | 401 | mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) |
361 | { | 402 | { |
362 | int ret; | 403 | int ret; |
404 | struct mt8183_mt6358_ts3a227_max98357_priv *priv = | ||
405 | snd_soc_card_get_drvdata(component->card); | ||
363 | 406 | ||
364 | /* Enable Headset and 4 Buttons Jack detection */ | 407 | /* Enable Headset and 4 Buttons Jack detection */ |
365 | ret = snd_soc_card_jack_new(&mt8183_mt6358_ts3a227_max98357_card, | 408 | ret = snd_soc_card_jack_new(&mt8183_mt6358_ts3a227_max98357_card, |
@@ -367,23 +410,29 @@ mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) | |||
367 | SND_JACK_HEADSET | | 410 | SND_JACK_HEADSET | |
368 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | 411 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
369 | SND_JACK_BTN_2 | SND_JACK_BTN_3, | 412 | SND_JACK_BTN_2 | SND_JACK_BTN_3, |
370 | &headset_jack, | 413 | &priv->headset_jack, |
371 | NULL, 0); | 414 | NULL, 0); |
372 | if (ret) | 415 | if (ret) |
373 | return ret; | 416 | return ret; |
374 | 417 | ||
375 | ret = ts3a227e_enable_jack_detect(component, &headset_jack); | 418 | ret = ts3a227e_enable_jack_detect(component, &priv->headset_jack); |
376 | 419 | ||
377 | return ret; | 420 | return ret; |
378 | } | 421 | } |
379 | 422 | ||
423 | static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = { | ||
424 | .dlc = COMP_EMPTY(), | ||
425 | .init = mt8183_mt6358_ts3a227_max98357_headset_init, | ||
426 | }; | ||
427 | |||
380 | static int | 428 | static int |
381 | mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) | 429 | mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) |
382 | { | 430 | { |
383 | struct snd_soc_card *card = &mt8183_mt6358_ts3a227_max98357_card; | 431 | struct snd_soc_card *card = &mt8183_mt6358_ts3a227_max98357_card; |
384 | struct device_node *platform_node; | 432 | struct device_node *platform_node; |
385 | struct snd_soc_dai_link *dai_link; | 433 | struct snd_soc_dai_link *dai_link; |
386 | struct pinctrl *default_pins; | 434 | struct mt8183_mt6358_ts3a227_max98357_priv *priv; |
435 | int ret; | ||
387 | int i; | 436 | int i; |
388 | 437 | ||
389 | card->dev = &pdev->dev; | 438 | card->dev = &pdev->dev; |
@@ -401,21 +450,53 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) | |||
401 | dai_link->platforms->of_node = platform_node; | 450 | dai_link->platforms->of_node = platform_node; |
402 | } | 451 | } |
403 | 452 | ||
404 | mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node = | 453 | mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node = |
405 | of_parse_phandle(pdev->dev.of_node, | 454 | of_parse_phandle(pdev->dev.of_node, |
406 | "mediatek,headset-codec", 0); | 455 | "mediatek,headset-codec", 0); |
407 | if (!mt8183_mt6358_ts3a227_max98357_headset_dev.codec_of_node) { | 456 | if (mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node) { |
408 | dev_err(&pdev->dev, | 457 | card->aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev; |
409 | "Property 'mediatek,headset-codec' missing/invalid\n"); | 458 | card->num_aux_devs = 1; |
410 | return -EINVAL; | ||
411 | } | 459 | } |
412 | 460 | ||
413 | default_pins = | 461 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
414 | devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT); | 462 | if (!priv) |
415 | if (IS_ERR(default_pins)) { | 463 | return -ENOMEM; |
416 | dev_err(&pdev->dev, "%s set pins failed\n", | 464 | |
465 | snd_soc_card_set_drvdata(card, priv); | ||
466 | |||
467 | priv->pinctrl = devm_pinctrl_get(&pdev->dev); | ||
468 | if (IS_ERR(priv->pinctrl)) { | ||
469 | dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n", | ||
417 | __func__); | 470 | __func__); |
418 | return PTR_ERR(default_pins); | 471 | return PTR_ERR(priv->pinctrl); |
472 | } | ||
473 | |||
474 | for (i = 0; i < PIN_STATE_MAX; i++) { | ||
475 | priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl, | ||
476 | mt8183_pin_str[i]); | ||
477 | if (IS_ERR(priv->pin_states[i])) { | ||
478 | ret = PTR_ERR(priv->pin_states[i]); | ||
479 | dev_info(&pdev->dev, "%s Can't find pin state %s %d\n", | ||
480 | __func__, mt8183_pin_str[i], ret); | ||
481 | } | ||
482 | } | ||
483 | |||
484 | if (!IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) { | ||
485 | ret = pinctrl_select_state(priv->pinctrl, | ||
486 | priv->pin_states[PIN_TDM_OUT_OFF]); | ||
487 | if (ret) | ||
488 | dev_info(&pdev->dev, | ||
489 | "%s failed to select state %d\n", | ||
490 | __func__, ret); | ||
491 | } | ||
492 | |||
493 | if (!IS_ERR(priv->pin_states[PIN_STATE_DEFAULT])) { | ||
494 | ret = pinctrl_select_state(priv->pinctrl, | ||
495 | priv->pin_states[PIN_STATE_DEFAULT]); | ||
496 | if (ret) | ||
497 | dev_info(&pdev->dev, | ||
498 | "%s failed to select state %d\n", | ||
499 | __func__, ret); | ||
419 | } | 500 | } |
420 | 501 | ||
421 | return devm_snd_soc_register_card(&pdev->dev, card); | 502 | return devm_snd_soc_register_card(&pdev->dev, card); |
@@ -445,4 +526,3 @@ MODULE_DESCRIPTION("MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver"); | |||
445 | MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>"); | 526 | MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>"); |
446 | MODULE_LICENSE("GPL v2"); | 527 | MODULE_LICENSE("GPL v2"); |
447 | MODULE_ALIAS("mt8183_mt6358_ts3a227_max98357 soc card"); | 528 | MODULE_ALIAS("mt8183_mt6358_ts3a227_max98357 soc card"); |
448 | |||
diff --git a/sound/soc/mediatek/mt8183/mt8183-reg.h b/sound/soc/mediatek/mt8183/mt8183-reg.h index e0482f2826da..e544a09e1913 100644 --- a/sound/soc/mediatek/mt8183/mt8183-reg.h +++ b/sound/soc/mediatek/mt8183/mt8183-reg.h | |||
@@ -413,6 +413,11 @@ | |||
413 | #define AFE_MAX_REGISTER AFE_GENERAL2_ASRC_2CH_CON13 | 413 | #define AFE_MAX_REGISTER AFE_GENERAL2_ASRC_2CH_CON13 |
414 | #define AFE_IRQ_STATUS_BITS 0x1fff | 414 | #define AFE_IRQ_STATUS_BITS 0x1fff |
415 | 415 | ||
416 | /* AUDIO_TOP_CON3 */ | ||
417 | #define BCK_INVERSE_SFT 3 | ||
418 | #define BCK_INVERSE_MASK 0x1 | ||
419 | #define BCK_INVERSE_MASK_SFT (0x1 << 3) | ||
420 | |||
416 | /* AFE_DAC_CON0 */ | 421 | /* AFE_DAC_CON0 */ |
417 | #define AWB2_ON_SFT 29 | 422 | #define AWB2_ON_SFT 29 |
418 | #define AWB2_ON_MASK 0x1 | 423 | #define AWB2_ON_MASK 0x1 |
@@ -1596,9 +1601,6 @@ | |||
1596 | #define TDM_EN_SFT 0 | 1601 | #define TDM_EN_SFT 0 |
1597 | #define TDM_EN_MASK 0x1 | 1602 | #define TDM_EN_MASK 0x1 |
1598 | #define TDM_EN_MASK_SFT (0x1 << 0) | 1603 | #define TDM_EN_MASK_SFT (0x1 << 0) |
1599 | #define BCK_INVERSE_SFT 1 | ||
1600 | #define BCK_INVERSE_MASK 0x1 | ||
1601 | #define BCK_INVERSE_MASK_SFT (0x1 << 1) | ||
1602 | #define LRCK_INVERSE_SFT 2 | 1604 | #define LRCK_INVERSE_SFT 2 |
1603 | #define LRCK_INVERSE_MASK 0x1 | 1605 | #define LRCK_INVERSE_MASK 0x1 |
1604 | #define LRCK_INVERSE_MASK_SFT (0x1 << 2) | 1606 | #define LRCK_INVERSE_MASK_SFT (0x1 << 2) |
diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 14a8321744da..1f698adde506 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c | |||
@@ -111,6 +111,7 @@ static void axg_card_clean_references(struct axg_card *priv) | |||
111 | struct snd_soc_card *card = &priv->card; | 111 | struct snd_soc_card *card = &priv->card; |
112 | struct snd_soc_dai_link *link; | 112 | struct snd_soc_dai_link *link; |
113 | struct snd_soc_dai_link_component *codec; | 113 | struct snd_soc_dai_link_component *codec; |
114 | struct snd_soc_aux_dev *aux; | ||
114 | int i, j; | 115 | int i, j; |
115 | 116 | ||
116 | if (card->dai_link) { | 117 | if (card->dai_link) { |
@@ -123,8 +124,8 @@ static void axg_card_clean_references(struct axg_card *priv) | |||
123 | } | 124 | } |
124 | 125 | ||
125 | if (card->aux_dev) { | 126 | if (card->aux_dev) { |
126 | for (i = 0; i < card->num_aux_devs; i++) | 127 | for_each_card_pre_auxs(card, i, aux) |
127 | of_node_put(card->aux_dev[i].codec_of_node); | 128 | of_node_put(aux->dlc.of_node); |
128 | } | 129 | } |
129 | 130 | ||
130 | kfree(card->dai_link); | 131 | kfree(card->dai_link); |
@@ -157,10 +158,10 @@ static int axg_card_add_aux_devices(struct snd_soc_card *card) | |||
157 | card->aux_dev = aux; | 158 | card->aux_dev = aux; |
158 | card->num_aux_devs = num; | 159 | card->num_aux_devs = num; |
159 | 160 | ||
160 | for (i = 0; i < card->num_aux_devs; i++, aux++) { | 161 | for_each_card_pre_auxs(card, i, aux) { |
161 | aux->codec_of_node = | 162 | aux->dlc.of_node = |
162 | of_parse_phandle(node, "audio-aux-devs", i); | 163 | of_parse_phandle(node, "audio-aux-devs", i); |
163 | if (!aux->codec_of_node) | 164 | if (!aux->dlc.of_node) |
164 | return -EINVAL; | 165 | return -EINVAL; |
165 | } | 166 | } |
166 | 167 | ||
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index 01c1c7db2510..5a3749938900 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c | |||
@@ -306,7 +306,7 @@ static const struct regmap_config axg_fifo_regmap_cfg = { | |||
306 | .reg_bits = 32, | 306 | .reg_bits = 32, |
307 | .val_bits = 32, | 307 | .val_bits = 32, |
308 | .reg_stride = 4, | 308 | .reg_stride = 4, |
309 | .max_register = FIFO_INIT_ADDR, | 309 | .max_register = FIFO_CTRL2, |
310 | }; | 310 | }; |
311 | 311 | ||
312 | int axg_fifo_probe(struct platform_device *pdev) | 312 | int axg_fifo_probe(struct platform_device *pdev) |
@@ -314,7 +314,6 @@ int axg_fifo_probe(struct platform_device *pdev) | |||
314 | struct device *dev = &pdev->dev; | 314 | struct device *dev = &pdev->dev; |
315 | const struct axg_fifo_match_data *data; | 315 | const struct axg_fifo_match_data *data; |
316 | struct axg_fifo *fifo; | 316 | struct axg_fifo *fifo; |
317 | struct resource *res; | ||
318 | void __iomem *regs; | 317 | void __iomem *regs; |
319 | 318 | ||
320 | data = of_device_get_match_data(dev); | 319 | data = of_device_get_match_data(dev); |
@@ -328,8 +327,7 @@ int axg_fifo_probe(struct platform_device *pdev) | |||
328 | return -ENOMEM; | 327 | return -ENOMEM; |
329 | platform_set_drvdata(pdev, fifo); | 328 | platform_set_drvdata(pdev, fifo); |
330 | 329 | ||
331 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 330 | regs = devm_platform_ioremap_resource(pdev, 0); |
332 | regs = devm_ioremap_resource(dev, res); | ||
333 | if (IS_ERR(regs)) | 331 | if (IS_ERR(regs)) |
334 | return PTR_ERR(regs); | 332 | return PTR_ERR(regs); |
335 | 333 | ||
diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h index 5caf81241dfe..bb1e2ce50256 100644 --- a/sound/soc/meson/axg-fifo.h +++ b/sound/soc/meson/axg-fifo.h | |||
@@ -61,6 +61,7 @@ struct snd_soc_pcm_runtime; | |||
61 | #define STATUS1_INT_STS(x) ((x) << 0) | 61 | #define STATUS1_INT_STS(x) ((x) << 0) |
62 | #define FIFO_STATUS2 0x18 | 62 | #define FIFO_STATUS2 0x18 |
63 | #define FIFO_INIT_ADDR 0x24 | 63 | #define FIFO_INIT_ADDR 0x24 |
64 | #define FIFO_CTRL2 0x28 | ||
64 | 65 | ||
65 | struct axg_fifo { | 66 | struct axg_fifo { |
66 | struct regmap *map; | 67 | struct regmap *map; |
diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c index 2b8807737b2b..6ab111c31b28 100644 --- a/sound/soc/meson/axg-frddr.c +++ b/sound/soc/meson/axg-frddr.c | |||
@@ -23,6 +23,12 @@ | |||
23 | #define CTRL0_SEL3_SHIFT 8 | 23 | #define CTRL0_SEL3_SHIFT 8 |
24 | #define CTRL0_SEL3_EN_SHIFT 11 | 24 | #define CTRL0_SEL3_EN_SHIFT 11 |
25 | #define CTRL1_FRDDR_FORCE_FINISH BIT(12) | 25 | #define CTRL1_FRDDR_FORCE_FINISH BIT(12) |
26 | #define CTRL2_SEL1_SHIFT 0 | ||
27 | #define CTRL2_SEL1_EN_SHIFT 4 | ||
28 | #define CTRL2_SEL2_SHIFT 8 | ||
29 | #define CTRL2_SEL2_EN_SHIFT 12 | ||
30 | #define CTRL2_SEL3_SHIFT 16 | ||
31 | #define CTRL2_SEL3_EN_SHIFT 20 | ||
26 | 32 | ||
27 | static int g12a_frddr_dai_prepare(struct snd_pcm_substream *substream, | 33 | static int g12a_frddr_dai_prepare(struct snd_pcm_substream *substream, |
28 | struct snd_soc_dai *dai) | 34 | struct snd_soc_dai *dai) |
@@ -104,7 +110,7 @@ static struct snd_soc_dai_driver axg_frddr_dai_drv = { | |||
104 | }; | 110 | }; |
105 | 111 | ||
106 | static const char * const axg_frddr_sel_texts[] = { | 112 | static const char * const axg_frddr_sel_texts[] = { |
107 | "OUT 0", "OUT 1", "OUT 2", "OUT 3" | 113 | "OUT 0", "OUT 1", "OUT 2", "OUT 3", "OUT 4", "OUT 5", "OUT 6", "OUT 7", |
108 | }; | 114 | }; |
109 | 115 | ||
110 | static SOC_ENUM_SINGLE_DECL(axg_frddr_sel_enum, FIFO_CTRL0, CTRL0_SEL_SHIFT, | 116 | static SOC_ENUM_SINGLE_DECL(axg_frddr_sel_enum, FIFO_CTRL0, CTRL0_SEL_SHIFT, |
@@ -120,6 +126,10 @@ static const struct snd_soc_dapm_widget axg_frddr_dapm_widgets[] = { | |||
120 | SND_SOC_DAPM_AIF_OUT("OUT 1", NULL, 0, SND_SOC_NOPM, 0, 0), | 126 | SND_SOC_DAPM_AIF_OUT("OUT 1", NULL, 0, SND_SOC_NOPM, 0, 0), |
121 | SND_SOC_DAPM_AIF_OUT("OUT 2", NULL, 0, SND_SOC_NOPM, 0, 0), | 127 | SND_SOC_DAPM_AIF_OUT("OUT 2", NULL, 0, SND_SOC_NOPM, 0, 0), |
122 | SND_SOC_DAPM_AIF_OUT("OUT 3", NULL, 0, SND_SOC_NOPM, 0, 0), | 128 | SND_SOC_DAPM_AIF_OUT("OUT 3", NULL, 0, SND_SOC_NOPM, 0, 0), |
129 | SND_SOC_DAPM_AIF_OUT("OUT 4", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
130 | SND_SOC_DAPM_AIF_OUT("OUT 5", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
131 | SND_SOC_DAPM_AIF_OUT("OUT 6", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
132 | SND_SOC_DAPM_AIF_OUT("OUT 7", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
123 | }; | 133 | }; |
124 | 134 | ||
125 | static const struct snd_soc_dapm_route axg_frddr_dapm_routes[] = { | 135 | static const struct snd_soc_dapm_route axg_frddr_dapm_routes[] = { |
@@ -128,6 +138,10 @@ static const struct snd_soc_dapm_route axg_frddr_dapm_routes[] = { | |||
128 | { "OUT 1", "OUT 1", "SINK SEL" }, | 138 | { "OUT 1", "OUT 1", "SINK SEL" }, |
129 | { "OUT 2", "OUT 2", "SINK SEL" }, | 139 | { "OUT 2", "OUT 2", "SINK SEL" }, |
130 | { "OUT 3", "OUT 3", "SINK SEL" }, | 140 | { "OUT 3", "OUT 3", "SINK SEL" }, |
141 | { "OUT 4", "OUT 4", "SINK SEL" }, | ||
142 | { "OUT 5", "OUT 5", "SINK SEL" }, | ||
143 | { "OUT 6", "OUT 6", "SINK SEL" }, | ||
144 | { "OUT 7", "OUT 7", "SINK SEL" }, | ||
131 | }; | 145 | }; |
132 | 146 | ||
133 | static const struct snd_soc_component_driver axg_frddr_component_drv = { | 147 | static const struct snd_soc_component_driver axg_frddr_component_drv = { |
@@ -162,16 +176,12 @@ static struct snd_soc_dai_driver g12a_frddr_dai_drv = { | |||
162 | .pcm_new = axg_frddr_pcm_new, | 176 | .pcm_new = axg_frddr_pcm_new, |
163 | }; | 177 | }; |
164 | 178 | ||
165 | static const char * const g12a_frddr_sel_texts[] = { | ||
166 | "OUT 0", "OUT 1", "OUT 2", "OUT 3", "OUT 4", | ||
167 | }; | ||
168 | |||
169 | static SOC_ENUM_SINGLE_DECL(g12a_frddr_sel1_enum, FIFO_CTRL0, CTRL0_SEL_SHIFT, | 179 | static SOC_ENUM_SINGLE_DECL(g12a_frddr_sel1_enum, FIFO_CTRL0, CTRL0_SEL_SHIFT, |
170 | g12a_frddr_sel_texts); | 180 | axg_frddr_sel_texts); |
171 | static SOC_ENUM_SINGLE_DECL(g12a_frddr_sel2_enum, FIFO_CTRL0, CTRL0_SEL2_SHIFT, | 181 | static SOC_ENUM_SINGLE_DECL(g12a_frddr_sel2_enum, FIFO_CTRL0, CTRL0_SEL2_SHIFT, |
172 | g12a_frddr_sel_texts); | 182 | axg_frddr_sel_texts); |
173 | static SOC_ENUM_SINGLE_DECL(g12a_frddr_sel3_enum, FIFO_CTRL0, CTRL0_SEL3_SHIFT, | 183 | static SOC_ENUM_SINGLE_DECL(g12a_frddr_sel3_enum, FIFO_CTRL0, CTRL0_SEL3_SHIFT, |
174 | g12a_frddr_sel_texts); | 184 | axg_frddr_sel_texts); |
175 | 185 | ||
176 | static const struct snd_kcontrol_new g12a_frddr_out1_demux = | 186 | static const struct snd_kcontrol_new g12a_frddr_out1_demux = |
177 | SOC_DAPM_ENUM("Output Src 1", g12a_frddr_sel1_enum); | 187 | SOC_DAPM_ENUM("Output Src 1", g12a_frddr_sel1_enum); |
@@ -211,6 +221,9 @@ static const struct snd_soc_dapm_widget g12a_frddr_dapm_widgets[] = { | |||
211 | SND_SOC_DAPM_AIF_OUT("OUT 2", NULL, 0, SND_SOC_NOPM, 0, 0), | 221 | SND_SOC_DAPM_AIF_OUT("OUT 2", NULL, 0, SND_SOC_NOPM, 0, 0), |
212 | SND_SOC_DAPM_AIF_OUT("OUT 3", NULL, 0, SND_SOC_NOPM, 0, 0), | 222 | SND_SOC_DAPM_AIF_OUT("OUT 3", NULL, 0, SND_SOC_NOPM, 0, 0), |
213 | SND_SOC_DAPM_AIF_OUT("OUT 4", NULL, 0, SND_SOC_NOPM, 0, 0), | 223 | SND_SOC_DAPM_AIF_OUT("OUT 4", NULL, 0, SND_SOC_NOPM, 0, 0), |
224 | SND_SOC_DAPM_AIF_OUT("OUT 5", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
225 | SND_SOC_DAPM_AIF_OUT("OUT 6", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
226 | SND_SOC_DAPM_AIF_OUT("OUT 7", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
214 | }; | 227 | }; |
215 | 228 | ||
216 | static const struct snd_soc_dapm_route g12a_frddr_dapm_routes[] = { | 229 | static const struct snd_soc_dapm_route g12a_frddr_dapm_routes[] = { |
@@ -228,16 +241,25 @@ static const struct snd_soc_dapm_route g12a_frddr_dapm_routes[] = { | |||
228 | { "OUT 2", "OUT 2", "SINK 1 SEL" }, | 241 | { "OUT 2", "OUT 2", "SINK 1 SEL" }, |
229 | { "OUT 3", "OUT 3", "SINK 1 SEL" }, | 242 | { "OUT 3", "OUT 3", "SINK 1 SEL" }, |
230 | { "OUT 4", "OUT 4", "SINK 1 SEL" }, | 243 | { "OUT 4", "OUT 4", "SINK 1 SEL" }, |
244 | { "OUT 5", "OUT 5", "SINK 1 SEL" }, | ||
245 | { "OUT 6", "OUT 6", "SINK 1 SEL" }, | ||
246 | { "OUT 7", "OUT 7", "SINK 1 SEL" }, | ||
231 | { "OUT 0", "OUT 0", "SINK 2 SEL" }, | 247 | { "OUT 0", "OUT 0", "SINK 2 SEL" }, |
232 | { "OUT 1", "OUT 1", "SINK 2 SEL" }, | 248 | { "OUT 1", "OUT 1", "SINK 2 SEL" }, |
233 | { "OUT 2", "OUT 2", "SINK 2 SEL" }, | 249 | { "OUT 2", "OUT 2", "SINK 2 SEL" }, |
234 | { "OUT 3", "OUT 3", "SINK 2 SEL" }, | 250 | { "OUT 3", "OUT 3", "SINK 2 SEL" }, |
235 | { "OUT 4", "OUT 4", "SINK 2 SEL" }, | 251 | { "OUT 4", "OUT 4", "SINK 2 SEL" }, |
252 | { "OUT 5", "OUT 5", "SINK 2 SEL" }, | ||
253 | { "OUT 6", "OUT 6", "SINK 2 SEL" }, | ||
254 | { "OUT 7", "OUT 7", "SINK 2 SEL" }, | ||
236 | { "OUT 0", "OUT 0", "SINK 3 SEL" }, | 255 | { "OUT 0", "OUT 0", "SINK 3 SEL" }, |
237 | { "OUT 1", "OUT 1", "SINK 3 SEL" }, | 256 | { "OUT 1", "OUT 1", "SINK 3 SEL" }, |
238 | { "OUT 2", "OUT 2", "SINK 3 SEL" }, | 257 | { "OUT 2", "OUT 2", "SINK 3 SEL" }, |
239 | { "OUT 3", "OUT 3", "SINK 3 SEL" }, | 258 | { "OUT 3", "OUT 3", "SINK 3 SEL" }, |
240 | { "OUT 4", "OUT 4", "SINK 3 SEL" }, | 259 | { "OUT 4", "OUT 4", "SINK 3 SEL" }, |
260 | { "OUT 5", "OUT 5", "SINK 3 SEL" }, | ||
261 | { "OUT 6", "OUT 6", "SINK 3 SEL" }, | ||
262 | { "OUT 7", "OUT 7", "SINK 3 SEL" }, | ||
241 | }; | 263 | }; |
242 | 264 | ||
243 | static const struct snd_soc_component_driver g12a_frddr_component_drv = { | 265 | static const struct snd_soc_component_driver g12a_frddr_component_drv = { |
@@ -253,6 +275,70 @@ static const struct axg_fifo_match_data g12a_frddr_match_data = { | |||
253 | .dai_drv = &g12a_frddr_dai_drv | 275 | .dai_drv = &g12a_frddr_dai_drv |
254 | }; | 276 | }; |
255 | 277 | ||
278 | /* On SM1, the output selection in on CTRL2 */ | ||
279 | static const struct snd_kcontrol_new sm1_frddr_out1_enable = | ||
280 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", FIFO_CTRL2, | ||
281 | CTRL2_SEL1_EN_SHIFT, 1, 0); | ||
282 | static const struct snd_kcontrol_new sm1_frddr_out2_enable = | ||
283 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", FIFO_CTRL2, | ||
284 | CTRL2_SEL2_EN_SHIFT, 1, 0); | ||
285 | static const struct snd_kcontrol_new sm1_frddr_out3_enable = | ||
286 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", FIFO_CTRL2, | ||
287 | CTRL2_SEL3_EN_SHIFT, 1, 0); | ||
288 | |||
289 | static SOC_ENUM_SINGLE_DECL(sm1_frddr_sel1_enum, FIFO_CTRL2, CTRL2_SEL1_SHIFT, | ||
290 | axg_frddr_sel_texts); | ||
291 | static SOC_ENUM_SINGLE_DECL(sm1_frddr_sel2_enum, FIFO_CTRL2, CTRL2_SEL2_SHIFT, | ||
292 | axg_frddr_sel_texts); | ||
293 | static SOC_ENUM_SINGLE_DECL(sm1_frddr_sel3_enum, FIFO_CTRL2, CTRL2_SEL3_SHIFT, | ||
294 | axg_frddr_sel_texts); | ||
295 | |||
296 | static const struct snd_kcontrol_new sm1_frddr_out1_demux = | ||
297 | SOC_DAPM_ENUM("Output Src 1", sm1_frddr_sel1_enum); | ||
298 | static const struct snd_kcontrol_new sm1_frddr_out2_demux = | ||
299 | SOC_DAPM_ENUM("Output Src 2", sm1_frddr_sel2_enum); | ||
300 | static const struct snd_kcontrol_new sm1_frddr_out3_demux = | ||
301 | SOC_DAPM_ENUM("Output Src 3", sm1_frddr_sel3_enum); | ||
302 | |||
303 | static const struct snd_soc_dapm_widget sm1_frddr_dapm_widgets[] = { | ||
304 | SND_SOC_DAPM_AIF_OUT("SRC 1", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
305 | SND_SOC_DAPM_AIF_OUT("SRC 2", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
306 | SND_SOC_DAPM_AIF_OUT("SRC 3", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
307 | SND_SOC_DAPM_SWITCH("SRC 1 EN", SND_SOC_NOPM, 0, 0, | ||
308 | &sm1_frddr_out1_enable), | ||
309 | SND_SOC_DAPM_SWITCH("SRC 2 EN", SND_SOC_NOPM, 0, 0, | ||
310 | &sm1_frddr_out2_enable), | ||
311 | SND_SOC_DAPM_SWITCH("SRC 3 EN", SND_SOC_NOPM, 0, 0, | ||
312 | &sm1_frddr_out3_enable), | ||
313 | SND_SOC_DAPM_DEMUX("SINK 1 SEL", SND_SOC_NOPM, 0, 0, | ||
314 | &sm1_frddr_out1_demux), | ||
315 | SND_SOC_DAPM_DEMUX("SINK 2 SEL", SND_SOC_NOPM, 0, 0, | ||
316 | &sm1_frddr_out2_demux), | ||
317 | SND_SOC_DAPM_DEMUX("SINK 3 SEL", SND_SOC_NOPM, 0, 0, | ||
318 | &sm1_frddr_out3_demux), | ||
319 | SND_SOC_DAPM_AIF_OUT("OUT 0", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
320 | SND_SOC_DAPM_AIF_OUT("OUT 1", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
321 | SND_SOC_DAPM_AIF_OUT("OUT 2", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
322 | SND_SOC_DAPM_AIF_OUT("OUT 3", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
323 | SND_SOC_DAPM_AIF_OUT("OUT 4", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
324 | SND_SOC_DAPM_AIF_OUT("OUT 5", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
325 | SND_SOC_DAPM_AIF_OUT("OUT 6", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
326 | SND_SOC_DAPM_AIF_OUT("OUT 7", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
327 | }; | ||
328 | |||
329 | static const struct snd_soc_component_driver sm1_frddr_component_drv = { | ||
330 | .dapm_widgets = sm1_frddr_dapm_widgets, | ||
331 | .num_dapm_widgets = ARRAY_SIZE(sm1_frddr_dapm_widgets), | ||
332 | .dapm_routes = g12a_frddr_dapm_routes, | ||
333 | .num_dapm_routes = ARRAY_SIZE(g12a_frddr_dapm_routes), | ||
334 | .ops = &g12a_fifo_pcm_ops | ||
335 | }; | ||
336 | |||
337 | static const struct axg_fifo_match_data sm1_frddr_match_data = { | ||
338 | .component_drv = &sm1_frddr_component_drv, | ||
339 | .dai_drv = &g12a_frddr_dai_drv | ||
340 | }; | ||
341 | |||
256 | static const struct of_device_id axg_frddr_of_match[] = { | 342 | static const struct of_device_id axg_frddr_of_match[] = { |
257 | { | 343 | { |
258 | .compatible = "amlogic,axg-frddr", | 344 | .compatible = "amlogic,axg-frddr", |
@@ -260,6 +346,9 @@ static const struct of_device_id axg_frddr_of_match[] = { | |||
260 | }, { | 346 | }, { |
261 | .compatible = "amlogic,g12a-frddr", | 347 | .compatible = "amlogic,g12a-frddr", |
262 | .data = &g12a_frddr_match_data, | 348 | .data = &g12a_frddr_match_data, |
349 | }, { | ||
350 | .compatible = "amlogic,sm1-frddr", | ||
351 | .data = &sm1_frddr_match_data, | ||
263 | }, {} | 352 | }, {} |
264 | }; | 353 | }; |
265 | MODULE_DEVICE_TABLE(of, axg_frddr_of_match); | 354 | MODULE_DEVICE_TABLE(of, axg_frddr_of_match); |
diff --git a/sound/soc/meson/axg-pdm.c b/sound/soc/meson/axg-pdm.c index 9d5684493ffc..bfd37d49a73e 100644 --- a/sound/soc/meson/axg-pdm.c +++ b/sound/soc/meson/axg-pdm.c | |||
@@ -585,7 +585,6 @@ static int axg_pdm_probe(struct platform_device *pdev) | |||
585 | { | 585 | { |
586 | struct device *dev = &pdev->dev; | 586 | struct device *dev = &pdev->dev; |
587 | struct axg_pdm *priv; | 587 | struct axg_pdm *priv; |
588 | struct resource *res; | ||
589 | void __iomem *regs; | 588 | void __iomem *regs; |
590 | int ret; | 589 | int ret; |
591 | 590 | ||
@@ -600,8 +599,7 @@ static int axg_pdm_probe(struct platform_device *pdev) | |||
600 | return -ENODEV; | 599 | return -ENODEV; |
601 | } | 600 | } |
602 | 601 | ||
603 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 602 | regs = devm_platform_ioremap_resource(pdev, 0); |
604 | regs = devm_ioremap_resource(dev, res); | ||
605 | if (IS_ERR(regs)) | 603 | if (IS_ERR(regs)) |
606 | return PTR_ERR(regs); | 604 | return PTR_ERR(regs); |
607 | 605 | ||
diff --git a/sound/soc/meson/axg-spdifin.c b/sound/soc/meson/axg-spdifin.c index 01b2035fa841..d0d09f945b48 100644 --- a/sound/soc/meson/axg-spdifin.c +++ b/sound/soc/meson/axg-spdifin.c | |||
@@ -453,7 +453,6 @@ static int axg_spdifin_probe(struct platform_device *pdev) | |||
453 | struct device *dev = &pdev->dev; | 453 | struct device *dev = &pdev->dev; |
454 | struct axg_spdifin *priv; | 454 | struct axg_spdifin *priv; |
455 | struct snd_soc_dai_driver *dai_drv; | 455 | struct snd_soc_dai_driver *dai_drv; |
456 | struct resource *res; | ||
457 | void __iomem *regs; | 456 | void __iomem *regs; |
458 | int ret; | 457 | int ret; |
459 | 458 | ||
@@ -468,8 +467,7 @@ static int axg_spdifin_probe(struct platform_device *pdev) | |||
468 | return -ENODEV; | 467 | return -ENODEV; |
469 | } | 468 | } |
470 | 469 | ||
471 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 470 | regs = devm_platform_ioremap_resource(pdev, 0); |
472 | regs = devm_ioremap_resource(dev, res); | ||
473 | if (IS_ERR(regs)) | 471 | if (IS_ERR(regs)) |
474 | return PTR_ERR(regs); | 472 | return PTR_ERR(regs); |
475 | 473 | ||
diff --git a/sound/soc/meson/axg-spdifout.c b/sound/soc/meson/axg-spdifout.c index 9dea528053ad..7ce6aa97ddf7 100644 --- a/sound/soc/meson/axg-spdifout.c +++ b/sound/soc/meson/axg-spdifout.c | |||
@@ -401,7 +401,6 @@ static int axg_spdifout_probe(struct platform_device *pdev) | |||
401 | { | 401 | { |
402 | struct device *dev = &pdev->dev; | 402 | struct device *dev = &pdev->dev; |
403 | struct axg_spdifout *priv; | 403 | struct axg_spdifout *priv; |
404 | struct resource *res; | ||
405 | void __iomem *regs; | 404 | void __iomem *regs; |
406 | int ret; | 405 | int ret; |
407 | 406 | ||
@@ -410,8 +409,7 @@ static int axg_spdifout_probe(struct platform_device *pdev) | |||
410 | return -ENOMEM; | 409 | return -ENOMEM; |
411 | platform_set_drvdata(pdev, priv); | 410 | platform_set_drvdata(pdev, priv); |
412 | 411 | ||
413 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 412 | regs = devm_platform_ioremap_resource(pdev, 0); |
414 | regs = devm_ioremap_resource(dev, res); | ||
415 | if (IS_ERR(regs)) | 413 | if (IS_ERR(regs)) |
416 | return PTR_ERR(regs); | 414 | return PTR_ERR(regs); |
417 | 415 | ||
diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index 1a0bf9d3836d..358c8c0d861c 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c | |||
@@ -253,7 +253,6 @@ int axg_tdm_formatter_probe(struct platform_device *pdev) | |||
253 | struct device *dev = &pdev->dev; | 253 | struct device *dev = &pdev->dev; |
254 | const struct axg_tdm_formatter_driver *drv; | 254 | const struct axg_tdm_formatter_driver *drv; |
255 | struct axg_tdm_formatter *formatter; | 255 | struct axg_tdm_formatter *formatter; |
256 | struct resource *res; | ||
257 | void __iomem *regs; | 256 | void __iomem *regs; |
258 | int ret; | 257 | int ret; |
259 | 258 | ||
@@ -269,8 +268,7 @@ int axg_tdm_formatter_probe(struct platform_device *pdev) | |||
269 | platform_set_drvdata(pdev, formatter); | 268 | platform_set_drvdata(pdev, formatter); |
270 | formatter->drv = drv; | 269 | formatter->drv = drv; |
271 | 270 | ||
272 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 271 | regs = devm_platform_ioremap_resource(pdev, 0); |
273 | regs = devm_ioremap_resource(dev, res); | ||
274 | if (IS_ERR(regs)) | 272 | if (IS_ERR(regs)) |
275 | return PTR_ERR(regs); | 273 | return PTR_ERR(regs); |
276 | 274 | ||
diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c index cb87f17f3e95..973d4c02ef8d 100644 --- a/sound/soc/meson/axg-tdmin.c +++ b/sound/soc/meson/axg-tdmin.c | |||
@@ -43,7 +43,8 @@ static const struct regmap_config axg_tdmin_regmap_cfg = { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | static const char * const axg_tdmin_sel_texts[] = { | 45 | static const char * const axg_tdmin_sel_texts[] = { |
46 | "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 5", | 46 | "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 5", "IN 6", "IN 7", |
47 | "IN 8", "IN 9", "IN 10", "IN 11", "IN 12", "IN 13", "IN 14", "IN 15", | ||
47 | }; | 48 | }; |
48 | 49 | ||
49 | /* Change to special mux control to reset dapm */ | 50 | /* Change to special mux control to reset dapm */ |
@@ -164,12 +165,22 @@ static int axg_tdmin_prepare(struct regmap *map, | |||
164 | } | 165 | } |
165 | 166 | ||
166 | static const struct snd_soc_dapm_widget axg_tdmin_dapm_widgets[] = { | 167 | static const struct snd_soc_dapm_widget axg_tdmin_dapm_widgets[] = { |
167 | SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), | 168 | SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), |
168 | SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), | 169 | SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), |
169 | SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), | 170 | SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), |
170 | SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0), | 171 | SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0), |
171 | SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0), | 172 | SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0), |
172 | SND_SOC_DAPM_AIF_IN("IN 5", NULL, 0, SND_SOC_NOPM, 0, 0), | 173 | SND_SOC_DAPM_AIF_IN("IN 5", NULL, 0, SND_SOC_NOPM, 0, 0), |
174 | SND_SOC_DAPM_AIF_IN("IN 6", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
175 | SND_SOC_DAPM_AIF_IN("IN 7", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
176 | SND_SOC_DAPM_AIF_IN("IN 8", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
177 | SND_SOC_DAPM_AIF_IN("IN 9", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
178 | SND_SOC_DAPM_AIF_IN("IN 10", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
179 | SND_SOC_DAPM_AIF_IN("IN 11", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
180 | SND_SOC_DAPM_AIF_IN("IN 12", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
181 | SND_SOC_DAPM_AIF_IN("IN 13", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
182 | SND_SOC_DAPM_AIF_IN("IN 14", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
183 | SND_SOC_DAPM_AIF_IN("IN 15", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
173 | SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &axg_tdmin_in_mux), | 184 | SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &axg_tdmin_in_mux), |
174 | SND_SOC_DAPM_PGA_E("DEC", SND_SOC_NOPM, 0, 0, NULL, 0, | 185 | SND_SOC_DAPM_PGA_E("DEC", SND_SOC_NOPM, 0, 0, NULL, 0, |
175 | axg_tdm_formatter_event, | 186 | axg_tdm_formatter_event, |
@@ -178,12 +189,22 @@ static const struct snd_soc_dapm_widget axg_tdmin_dapm_widgets[] = { | |||
178 | }; | 189 | }; |
179 | 190 | ||
180 | static const struct snd_soc_dapm_route axg_tdmin_dapm_routes[] = { | 191 | static const struct snd_soc_dapm_route axg_tdmin_dapm_routes[] = { |
181 | { "SRC SEL", "IN 0", "IN 0" }, | 192 | { "SRC SEL", "IN 0", "IN 0" }, |
182 | { "SRC SEL", "IN 1", "IN 1" }, | 193 | { "SRC SEL", "IN 1", "IN 1" }, |
183 | { "SRC SEL", "IN 2", "IN 2" }, | 194 | { "SRC SEL", "IN 2", "IN 2" }, |
184 | { "SRC SEL", "IN 3", "IN 3" }, | 195 | { "SRC SEL", "IN 3", "IN 3" }, |
185 | { "SRC SEL", "IN 4", "IN 4" }, | 196 | { "SRC SEL", "IN 4", "IN 4" }, |
186 | { "SRC SEL", "IN 5", "IN 5" }, | 197 | { "SRC SEL", "IN 5", "IN 5" }, |
198 | { "SRC SEL", "IN 6", "IN 6" }, | ||
199 | { "SRC SEL", "IN 7", "IN 7" }, | ||
200 | { "SRC SEL", "IN 8", "IN 8" }, | ||
201 | { "SRC SEL", "IN 9", "IN 9" }, | ||
202 | { "SRC SEL", "IN 10", "IN 10" }, | ||
203 | { "SRC SEL", "IN 11", "IN 11" }, | ||
204 | { "SRC SEL", "IN 12", "IN 12" }, | ||
205 | { "SRC SEL", "IN 13", "IN 13" }, | ||
206 | { "SRC SEL", "IN 14", "IN 14" }, | ||
207 | { "SRC SEL", "IN 15", "IN 15" }, | ||
187 | { "DEC", NULL, "SRC SEL" }, | 208 | { "DEC", NULL, "SRC SEL" }, |
188 | { "OUT", NULL, "DEC" }, | 209 | { "OUT", NULL, "DEC" }, |
189 | }; | 210 | }; |
diff --git a/sound/soc/meson/axg-tdmout.c b/sound/soc/meson/axg-tdmout.c index 86537fc0ecb5..418ec314b37d 100644 --- a/sound/soc/meson/axg-tdmout.c +++ b/sound/soc/meson/axg-tdmout.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #define TDMOUT_CTRL1 0x04 | 24 | #define TDMOUT_CTRL1 0x04 |
25 | #define TDMOUT_CTRL1_TYPE_MASK GENMASK(6, 4) | 25 | #define TDMOUT_CTRL1_TYPE_MASK GENMASK(6, 4) |
26 | #define TDMOUT_CTRL1_TYPE(x) ((x) << 4) | 26 | #define TDMOUT_CTRL1_TYPE(x) ((x) << 4) |
27 | #define SM1_TDMOUT_CTRL1_GAIN_EN 7 | ||
27 | #define TDMOUT_CTRL1_MSB_POS_MASK GENMASK(12, 8) | 28 | #define TDMOUT_CTRL1_MSB_POS_MASK GENMASK(12, 8) |
28 | #define TDMOUT_CTRL1_MSB_POS(x) ((x) << 8) | 29 | #define TDMOUT_CTRL1_MSB_POS(x) ((x) << 8) |
29 | #define TDMOUT_CTRL1_SEL_SHIFT 24 | 30 | #define TDMOUT_CTRL1_SEL_SHIFT 24 |
@@ -51,25 +52,6 @@ static const struct regmap_config axg_tdmout_regmap_cfg = { | |||
51 | .max_register = TDMOUT_MASK_VAL, | 52 | .max_register = TDMOUT_MASK_VAL, |
52 | }; | 53 | }; |
53 | 54 | ||
54 | static const struct snd_kcontrol_new axg_tdmout_controls[] = { | ||
55 | SOC_DOUBLE("Lane 0 Volume", TDMOUT_GAIN0, 0, 8, 255, 0), | ||
56 | SOC_DOUBLE("Lane 1 Volume", TDMOUT_GAIN0, 16, 24, 255, 0), | ||
57 | SOC_DOUBLE("Lane 2 Volume", TDMOUT_GAIN1, 0, 8, 255, 0), | ||
58 | SOC_DOUBLE("Lane 3 Volume", TDMOUT_GAIN1, 16, 24, 255, 0), | ||
59 | SOC_SINGLE("Gain Enable Switch", TDMOUT_CTRL1, | ||
60 | TDMOUT_CTRL1_GAIN_EN, 1, 0), | ||
61 | }; | ||
62 | |||
63 | static const char * const tdmout_sel_texts[] = { | ||
64 | "IN 0", "IN 1", "IN 2", | ||
65 | }; | ||
66 | |||
67 | static SOC_ENUM_SINGLE_DECL(axg_tdmout_sel_enum, TDMOUT_CTRL1, | ||
68 | TDMOUT_CTRL1_SEL_SHIFT, tdmout_sel_texts); | ||
69 | |||
70 | static const struct snd_kcontrol_new axg_tdmout_in_mux = | ||
71 | SOC_DAPM_ENUM("Input Source", axg_tdmout_sel_enum); | ||
72 | |||
73 | static struct snd_soc_dai * | 55 | static struct snd_soc_dai * |
74 | axg_tdmout_get_be(struct snd_soc_dapm_widget *w) | 56 | axg_tdmout_get_be(struct snd_soc_dapm_widget *w) |
75 | { | 57 | { |
@@ -197,6 +179,25 @@ static int axg_tdmout_prepare(struct regmap *map, | |||
197 | return axg_tdm_formatter_set_channel_masks(map, ts, TDMOUT_MASK0); | 179 | return axg_tdm_formatter_set_channel_masks(map, ts, TDMOUT_MASK0); |
198 | } | 180 | } |
199 | 181 | ||
182 | static const struct snd_kcontrol_new axg_tdmout_controls[] = { | ||
183 | SOC_DOUBLE("Lane 0 Volume", TDMOUT_GAIN0, 0, 8, 255, 0), | ||
184 | SOC_DOUBLE("Lane 1 Volume", TDMOUT_GAIN0, 16, 24, 255, 0), | ||
185 | SOC_DOUBLE("Lane 2 Volume", TDMOUT_GAIN1, 0, 8, 255, 0), | ||
186 | SOC_DOUBLE("Lane 3 Volume", TDMOUT_GAIN1, 16, 24, 255, 0), | ||
187 | SOC_SINGLE("Gain Enable Switch", TDMOUT_CTRL1, | ||
188 | TDMOUT_CTRL1_GAIN_EN, 1, 0), | ||
189 | }; | ||
190 | |||
191 | static const char * const axg_tdmout_sel_texts[] = { | ||
192 | "IN 0", "IN 1", "IN 2", | ||
193 | }; | ||
194 | |||
195 | static SOC_ENUM_SINGLE_DECL(axg_tdmout_sel_enum, TDMOUT_CTRL1, | ||
196 | TDMOUT_CTRL1_SEL_SHIFT, axg_tdmout_sel_texts); | ||
197 | |||
198 | static const struct snd_kcontrol_new axg_tdmout_in_mux = | ||
199 | SOC_DAPM_ENUM("Input Source", axg_tdmout_sel_enum); | ||
200 | |||
200 | static const struct snd_soc_dapm_widget axg_tdmout_dapm_widgets[] = { | 201 | static const struct snd_soc_dapm_widget axg_tdmout_dapm_widgets[] = { |
201 | SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), | 202 | SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), |
202 | SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), | 203 | SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), |
@@ -252,6 +253,67 @@ static const struct axg_tdm_formatter_driver g12a_tdmout_drv = { | |||
252 | }, | 253 | }, |
253 | }; | 254 | }; |
254 | 255 | ||
256 | static const struct snd_kcontrol_new sm1_tdmout_controls[] = { | ||
257 | SOC_DOUBLE("Lane 0 Volume", TDMOUT_GAIN0, 0, 8, 255, 0), | ||
258 | SOC_DOUBLE("Lane 1 Volume", TDMOUT_GAIN0, 16, 24, 255, 0), | ||
259 | SOC_DOUBLE("Lane 2 Volume", TDMOUT_GAIN1, 0, 8, 255, 0), | ||
260 | SOC_DOUBLE("Lane 3 Volume", TDMOUT_GAIN1, 16, 24, 255, 0), | ||
261 | SOC_SINGLE("Gain Enable Switch", TDMOUT_CTRL1, | ||
262 | SM1_TDMOUT_CTRL1_GAIN_EN, 1, 0), | ||
263 | }; | ||
264 | |||
265 | static const char * const sm1_tdmout_sel_texts[] = { | ||
266 | "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", | ||
267 | }; | ||
268 | |||
269 | static SOC_ENUM_SINGLE_DECL(sm1_tdmout_sel_enum, TDMOUT_CTRL1, | ||
270 | TDMOUT_CTRL1_SEL_SHIFT, sm1_tdmout_sel_texts); | ||
271 | |||
272 | static const struct snd_kcontrol_new sm1_tdmout_in_mux = | ||
273 | SOC_DAPM_ENUM("Input Source", sm1_tdmout_sel_enum); | ||
274 | |||
275 | static const struct snd_soc_dapm_widget sm1_tdmout_dapm_widgets[] = { | ||
276 | SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
277 | SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
278 | SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
279 | SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
280 | SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
281 | SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &sm1_tdmout_in_mux), | ||
282 | SND_SOC_DAPM_PGA_E("ENC", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
283 | axg_tdm_formatter_event, | ||
284 | (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD)), | ||
285 | SND_SOC_DAPM_AIF_OUT("OUT", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
286 | }; | ||
287 | |||
288 | static const struct snd_soc_dapm_route sm1_tdmout_dapm_routes[] = { | ||
289 | { "SRC SEL", "IN 0", "IN 0" }, | ||
290 | { "SRC SEL", "IN 1", "IN 1" }, | ||
291 | { "SRC SEL", "IN 2", "IN 2" }, | ||
292 | { "SRC SEL", "IN 3", "IN 3" }, | ||
293 | { "SRC SEL", "IN 4", "IN 4" }, | ||
294 | { "ENC", NULL, "SRC SEL" }, | ||
295 | { "OUT", NULL, "ENC" }, | ||
296 | }; | ||
297 | |||
298 | static const struct snd_soc_component_driver sm1_tdmout_component_drv = { | ||
299 | .controls = sm1_tdmout_controls, | ||
300 | .num_controls = ARRAY_SIZE(sm1_tdmout_controls), | ||
301 | .dapm_widgets = sm1_tdmout_dapm_widgets, | ||
302 | .num_dapm_widgets = ARRAY_SIZE(sm1_tdmout_dapm_widgets), | ||
303 | .dapm_routes = sm1_tdmout_dapm_routes, | ||
304 | .num_dapm_routes = ARRAY_SIZE(sm1_tdmout_dapm_routes), | ||
305 | }; | ||
306 | |||
307 | static const struct axg_tdm_formatter_driver sm1_tdmout_drv = { | ||
308 | .component_drv = &sm1_tdmout_component_drv, | ||
309 | .regmap_cfg = &axg_tdmout_regmap_cfg, | ||
310 | .ops = &axg_tdmout_ops, | ||
311 | .quirks = &(const struct axg_tdm_formatter_hw) { | ||
312 | .invert_sclk = true, | ||
313 | .skew_offset = 2, | ||
314 | }, | ||
315 | }; | ||
316 | |||
255 | static const struct of_device_id axg_tdmout_of_match[] = { | 317 | static const struct of_device_id axg_tdmout_of_match[] = { |
256 | { | 318 | { |
257 | .compatible = "amlogic,axg-tdmout", | 319 | .compatible = "amlogic,axg-tdmout", |
@@ -259,6 +321,9 @@ static const struct of_device_id axg_tdmout_of_match[] = { | |||
259 | }, { | 321 | }, { |
260 | .compatible = "amlogic,g12a-tdmout", | 322 | .compatible = "amlogic,g12a-tdmout", |
261 | .data = &g12a_tdmout_drv, | 323 | .data = &g12a_tdmout_drv, |
324 | }, { | ||
325 | .compatible = "amlogic,sm1-tdmout", | ||
326 | .data = &sm1_tdmout_drv, | ||
262 | }, {} | 327 | }, {} |
263 | }; | 328 | }; |
264 | MODULE_DEVICE_TABLE(of, axg_tdmout_of_match); | 329 | MODULE_DEVICE_TABLE(of, axg_tdmout_of_match); |
diff --git a/sound/soc/meson/axg-toddr.c b/sound/soc/meson/axg-toddr.c index 4f63e434fad4..c8ea2145f576 100644 --- a/sound/soc/meson/axg-toddr.c +++ b/sound/soc/meson/axg-toddr.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #define CTRL0_TODDR_LSB_POS_MASK GENMASK(7, 3) | 25 | #define CTRL0_TODDR_LSB_POS_MASK GENMASK(7, 3) |
26 | #define CTRL0_TODDR_LSB_POS(x) ((x) << 3) | 26 | #define CTRL0_TODDR_LSB_POS(x) ((x) << 3) |
27 | #define CTRL1_TODDR_FORCE_FINISH BIT(25) | 27 | #define CTRL1_TODDR_FORCE_FINISH BIT(25) |
28 | #define CTRL1_SEL_SHIFT 28 | ||
28 | 29 | ||
29 | #define TODDR_MSB_POS 31 | 30 | #define TODDR_MSB_POS 31 |
30 | 31 | ||
@@ -142,16 +143,11 @@ static struct snd_soc_dai_driver axg_toddr_dai_drv = { | |||
142 | }; | 143 | }; |
143 | 144 | ||
144 | static const char * const axg_toddr_sel_texts[] = { | 145 | static const char * const axg_toddr_sel_texts[] = { |
145 | "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 6" | 146 | "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 5", "IN 6", "IN 7" |
146 | }; | 147 | }; |
147 | 148 | ||
148 | static const unsigned int axg_toddr_sel_values[] = { | 149 | static SOC_ENUM_SINGLE_DECL(axg_toddr_sel_enum, FIFO_CTRL0, CTRL0_SEL_SHIFT, |
149 | 0, 1, 2, 3, 4, 6 | 150 | axg_toddr_sel_texts); |
150 | }; | ||
151 | |||
152 | static SOC_VALUE_ENUM_SINGLE_DECL(axg_toddr_sel_enum, FIFO_CTRL0, | ||
153 | CTRL0_SEL_SHIFT, CTRL0_SEL_MASK, | ||
154 | axg_toddr_sel_texts, axg_toddr_sel_values); | ||
155 | 151 | ||
156 | static const struct snd_kcontrol_new axg_toddr_in_mux = | 152 | static const struct snd_kcontrol_new axg_toddr_in_mux = |
157 | SOC_DAPM_ENUM("Input Source", axg_toddr_sel_enum); | 153 | SOC_DAPM_ENUM("Input Source", axg_toddr_sel_enum); |
@@ -163,7 +159,9 @@ static const struct snd_soc_dapm_widget axg_toddr_dapm_widgets[] = { | |||
163 | SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), | 159 | SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), |
164 | SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0), | 160 | SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0), |
165 | SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0), | 161 | SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0), |
162 | SND_SOC_DAPM_AIF_IN("IN 5", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
166 | SND_SOC_DAPM_AIF_IN("IN 6", NULL, 0, SND_SOC_NOPM, 0, 0), | 163 | SND_SOC_DAPM_AIF_IN("IN 6", NULL, 0, SND_SOC_NOPM, 0, 0), |
164 | SND_SOC_DAPM_AIF_IN("IN 7", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
167 | }; | 165 | }; |
168 | 166 | ||
169 | static const struct snd_soc_dapm_route axg_toddr_dapm_routes[] = { | 167 | static const struct snd_soc_dapm_route axg_toddr_dapm_routes[] = { |
@@ -173,7 +171,9 @@ static const struct snd_soc_dapm_route axg_toddr_dapm_routes[] = { | |||
173 | { "SRC SEL", "IN 2", "IN 2" }, | 171 | { "SRC SEL", "IN 2", "IN 2" }, |
174 | { "SRC SEL", "IN 3", "IN 3" }, | 172 | { "SRC SEL", "IN 3", "IN 3" }, |
175 | { "SRC SEL", "IN 4", "IN 4" }, | 173 | { "SRC SEL", "IN 4", "IN 4" }, |
174 | { "SRC SEL", "IN 5", "IN 5" }, | ||
176 | { "SRC SEL", "IN 6", "IN 6" }, | 175 | { "SRC SEL", "IN 6", "IN 6" }, |
176 | { "SRC SEL", "IN 7", "IN 7" }, | ||
177 | }; | 177 | }; |
178 | 178 | ||
179 | static const struct snd_soc_component_driver axg_toddr_component_drv = { | 179 | static const struct snd_soc_component_driver axg_toddr_component_drv = { |
@@ -222,6 +222,70 @@ static const struct axg_fifo_match_data g12a_toddr_match_data = { | |||
222 | .dai_drv = &g12a_toddr_dai_drv | 222 | .dai_drv = &g12a_toddr_dai_drv |
223 | }; | 223 | }; |
224 | 224 | ||
225 | static const char * const sm1_toddr_sel_texts[] = { | ||
226 | "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 5", "IN 6", "IN 7", | ||
227 | "IN 8", "IN 9", "IN 10", "IN 11", "IN 12", "IN 13", "IN 14", "IN 15" | ||
228 | }; | ||
229 | |||
230 | static SOC_ENUM_SINGLE_DECL(sm1_toddr_sel_enum, FIFO_CTRL1, CTRL1_SEL_SHIFT, | ||
231 | sm1_toddr_sel_texts); | ||
232 | |||
233 | static const struct snd_kcontrol_new sm1_toddr_in_mux = | ||
234 | SOC_DAPM_ENUM("Input Source", sm1_toddr_sel_enum); | ||
235 | |||
236 | static const struct snd_soc_dapm_widget sm1_toddr_dapm_widgets[] = { | ||
237 | SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &sm1_toddr_in_mux), | ||
238 | SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
239 | SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
240 | SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
241 | SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
242 | SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
243 | SND_SOC_DAPM_AIF_IN("IN 5", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
244 | SND_SOC_DAPM_AIF_IN("IN 6", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
245 | SND_SOC_DAPM_AIF_IN("IN 7", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
246 | SND_SOC_DAPM_AIF_IN("IN 8", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
247 | SND_SOC_DAPM_AIF_IN("IN 9", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
248 | SND_SOC_DAPM_AIF_IN("IN 10", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
249 | SND_SOC_DAPM_AIF_IN("IN 11", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
250 | SND_SOC_DAPM_AIF_IN("IN 12", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
251 | SND_SOC_DAPM_AIF_IN("IN 13", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
252 | SND_SOC_DAPM_AIF_IN("IN 14", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
253 | SND_SOC_DAPM_AIF_IN("IN 15", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
254 | }; | ||
255 | |||
256 | static const struct snd_soc_dapm_route sm1_toddr_dapm_routes[] = { | ||
257 | { "Capture", NULL, "SRC SEL" }, | ||
258 | { "SRC SEL", "IN 0", "IN 0" }, | ||
259 | { "SRC SEL", "IN 1", "IN 1" }, | ||
260 | { "SRC SEL", "IN 2", "IN 2" }, | ||
261 | { "SRC SEL", "IN 3", "IN 3" }, | ||
262 | { "SRC SEL", "IN 4", "IN 4" }, | ||
263 | { "SRC SEL", "IN 5", "IN 5" }, | ||
264 | { "SRC SEL", "IN 6", "IN 6" }, | ||
265 | { "SRC SEL", "IN 7", "IN 7" }, | ||
266 | { "SRC SEL", "IN 8", "IN 8" }, | ||
267 | { "SRC SEL", "IN 9", "IN 9" }, | ||
268 | { "SRC SEL", "IN 10", "IN 10" }, | ||
269 | { "SRC SEL", "IN 11", "IN 11" }, | ||
270 | { "SRC SEL", "IN 12", "IN 12" }, | ||
271 | { "SRC SEL", "IN 13", "IN 13" }, | ||
272 | { "SRC SEL", "IN 14", "IN 14" }, | ||
273 | { "SRC SEL", "IN 15", "IN 15" }, | ||
274 | }; | ||
275 | |||
276 | static const struct snd_soc_component_driver sm1_toddr_component_drv = { | ||
277 | .dapm_widgets = sm1_toddr_dapm_widgets, | ||
278 | .num_dapm_widgets = ARRAY_SIZE(sm1_toddr_dapm_widgets), | ||
279 | .dapm_routes = sm1_toddr_dapm_routes, | ||
280 | .num_dapm_routes = ARRAY_SIZE(sm1_toddr_dapm_routes), | ||
281 | .ops = &g12a_fifo_pcm_ops | ||
282 | }; | ||
283 | |||
284 | static const struct axg_fifo_match_data sm1_toddr_match_data = { | ||
285 | .component_drv = &sm1_toddr_component_drv, | ||
286 | .dai_drv = &g12a_toddr_dai_drv | ||
287 | }; | ||
288 | |||
225 | static const struct of_device_id axg_toddr_of_match[] = { | 289 | static const struct of_device_id axg_toddr_of_match[] = { |
226 | { | 290 | { |
227 | .compatible = "amlogic,axg-toddr", | 291 | .compatible = "amlogic,axg-toddr", |
@@ -229,6 +293,9 @@ static const struct of_device_id axg_toddr_of_match[] = { | |||
229 | }, { | 293 | }, { |
230 | .compatible = "amlogic,g12a-toddr", | 294 | .compatible = "amlogic,g12a-toddr", |
231 | .data = &g12a_toddr_match_data, | 295 | .data = &g12a_toddr_match_data, |
296 | }, { | ||
297 | .compatible = "amlogic,sm1-toddr", | ||
298 | .data = &sm1_toddr_match_data, | ||
232 | }, {} | 299 | }, {} |
233 | }; | 300 | }; |
234 | MODULE_DEVICE_TABLE(of, axg_toddr_of_match); | 301 | MODULE_DEVICE_TABLE(of, axg_toddr_of_match); |
diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c index 707ccb192e4c..9cfbd343a00c 100644 --- a/sound/soc/meson/g12a-tohdmitx.c +++ b/sound/soc/meson/g12a-tohdmitx.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #define CTRL0_SPDIF_CLK_SEL BIT(0) | 28 | #define CTRL0_SPDIF_CLK_SEL BIT(0) |
29 | 29 | ||
30 | struct g12a_tohdmitx_input { | 30 | struct g12a_tohdmitx_input { |
31 | struct snd_pcm_hw_params params; | 31 | struct snd_soc_pcm_stream params; |
32 | unsigned int fmt; | 32 | unsigned int fmt; |
33 | }; | 33 | }; |
34 | 34 | ||
@@ -225,26 +225,17 @@ static int g12a_tohdmitx_input_hw_params(struct snd_pcm_substream *substream, | |||
225 | { | 225 | { |
226 | struct g12a_tohdmitx_input *data = dai->playback_dma_data; | 226 | struct g12a_tohdmitx_input *data = dai->playback_dma_data; |
227 | 227 | ||
228 | /* Save the stream params for the downstream link */ | 228 | data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params)); |
229 | memcpy(&data->params, params, sizeof(*params)); | 229 | data->params.rate_min = params_rate(params); |
230 | data->params.rate_max = params_rate(params); | ||
231 | data->params.formats = 1 << params_format(params); | ||
232 | data->params.channels_min = params_channels(params); | ||
233 | data->params.channels_max = params_channels(params); | ||
234 | data->params.sig_bits = dai->driver->playback.sig_bits; | ||
230 | 235 | ||
231 | return 0; | 236 | return 0; |
232 | } | 237 | } |
233 | 238 | ||
234 | static int g12a_tohdmitx_output_hw_params(struct snd_pcm_substream *substream, | ||
235 | struct snd_pcm_hw_params *params, | ||
236 | struct snd_soc_dai *dai) | ||
237 | { | ||
238 | struct g12a_tohdmitx_input *in_data = | ||
239 | g12a_tohdmitx_get_input_data(dai->capture_widget); | ||
240 | |||
241 | if (!in_data) | ||
242 | return -ENODEV; | ||
243 | |||
244 | memcpy(params, &in_data->params, sizeof(*params)); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | 239 | ||
249 | static int g12a_tohdmitx_input_set_fmt(struct snd_soc_dai *dai, | 240 | static int g12a_tohdmitx_input_set_fmt(struct snd_soc_dai *dai, |
250 | unsigned int fmt) | 241 | unsigned int fmt) |
@@ -266,6 +257,14 @@ static int g12a_tohdmitx_output_startup(struct snd_pcm_substream *substream, | |||
266 | if (!in_data) | 257 | if (!in_data) |
267 | return -ENODEV; | 258 | return -ENODEV; |
268 | 259 | ||
260 | if (WARN_ON(!rtd->dai_link->params)) { | ||
261 | dev_warn(dai->dev, "codec2codec link expected\n"); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | /* Replace link params with the input params */ | ||
266 | rtd->dai_link->params = &in_data->params; | ||
267 | |||
269 | if (!in_data->fmt) | 268 | if (!in_data->fmt) |
270 | return 0; | 269 | return 0; |
271 | 270 | ||
@@ -278,7 +277,6 @@ static const struct snd_soc_dai_ops g12a_tohdmitx_input_ops = { | |||
278 | }; | 277 | }; |
279 | 278 | ||
280 | static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = { | 279 | static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = { |
281 | .hw_params = g12a_tohdmitx_output_hw_params, | ||
282 | .startup = g12a_tohdmitx_output_startup, | 280 | .startup = g12a_tohdmitx_output_startup, |
283 | }; | 281 | }; |
284 | 282 | ||
@@ -378,12 +376,10 @@ MODULE_DEVICE_TABLE(of, g12a_tohdmitx_of_match); | |||
378 | static int g12a_tohdmitx_probe(struct platform_device *pdev) | 376 | static int g12a_tohdmitx_probe(struct platform_device *pdev) |
379 | { | 377 | { |
380 | struct device *dev = &pdev->dev; | 378 | struct device *dev = &pdev->dev; |
381 | struct resource *res; | ||
382 | void __iomem *regs; | 379 | void __iomem *regs; |
383 | struct regmap *map; | 380 | struct regmap *map; |
384 | 381 | ||
385 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 382 | regs = devm_platform_ioremap_resource(pdev, 0); |
386 | regs = devm_ioremap_resource(dev, res); | ||
387 | if (IS_ERR(regs)) | 383 | if (IS_ERR(regs)) |
388 | return PTR_ERR(regs); | 384 | return PTR_ERR(regs); |
389 | 385 | ||
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 269b6d6df250..1e38ce858326 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -732,7 +732,6 @@ static int mxs_saif_mclk_init(struct platform_device *pdev) | |||
732 | static int mxs_saif_probe(struct platform_device *pdev) | 732 | static int mxs_saif_probe(struct platform_device *pdev) |
733 | { | 733 | { |
734 | struct device_node *np = pdev->dev.of_node; | 734 | struct device_node *np = pdev->dev.of_node; |
735 | struct resource *iores; | ||
736 | struct mxs_saif *saif; | 735 | struct mxs_saif *saif; |
737 | int irq, ret = 0; | 736 | int irq, ret = 0; |
738 | struct device_node *master; | 737 | struct device_node *master; |
@@ -786,19 +785,13 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
786 | return ret; | 785 | return ret; |
787 | } | 786 | } |
788 | 787 | ||
789 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 788 | saif->base = devm_platform_ioremap_resource(pdev, 0); |
790 | |||
791 | saif->base = devm_ioremap_resource(&pdev->dev, iores); | ||
792 | if (IS_ERR(saif->base)) | 789 | if (IS_ERR(saif->base)) |
793 | return PTR_ERR(saif->base); | 790 | return PTR_ERR(saif->base); |
794 | 791 | ||
795 | irq = platform_get_irq(pdev, 0); | 792 | irq = platform_get_irq(pdev, 0); |
796 | if (irq < 0) { | 793 | if (irq < 0) |
797 | ret = irq; | 794 | return irq; |
798 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", | ||
799 | ret); | ||
800 | return ret; | ||
801 | } | ||
802 | 795 | ||
803 | saif->dev = &pdev->dev; | 796 | saif->dev = &pdev->dev; |
804 | ret = devm_request_irq(&pdev->dev, irq, mxs_saif_irq, 0, | 797 | ret = devm_request_irq(&pdev->dev, irq, mxs_saif_irq, 0, |
diff --git a/sound/soc/nuc900/Kconfig b/sound/soc/nuc900/Kconfig deleted file mode 100644 index e1b22fbcb159..000000000000 --- a/sound/soc/nuc900/Kconfig +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | ## | ||
3 | ## NUC900 series AC97 API | ||
4 | ## | ||
5 | config SND_SOC_NUC900 | ||
6 | tristate "SoC Audio for NUC900 series" | ||
7 | depends on ARCH_W90X900 | ||
8 | select SND_SOC_NUC900_AC97 | ||
9 | help | ||
10 | This option enables support for AC97 mode on the NUC900 SoC. | ||
11 | |||
12 | config SND_SOC_NUC900_AC97 | ||
13 | tristate | ||
14 | select AC97_BUS | ||
15 | select SND_AC97_CODEC | ||
16 | select SND_SOC_AC97_BUS | ||
17 | |||
18 | |||
19 | ## | ||
20 | ## Boards | ||
21 | ## | ||
22 | config SND_SOC_NUC900EVB | ||
23 | tristate "NUC900 AC97 support for demo board" | ||
24 | depends on SND_SOC_NUC900 | ||
25 | select SND_SOC_NUC900_AC97 | ||
26 | select SND_SOC_AC97_CODEC | ||
27 | help | ||
28 | Select this option to enable audio (AC97) on the | ||
29 | NUC900 demoboard. | ||
diff --git a/sound/soc/nuc900/Makefile b/sound/soc/nuc900/Makefile deleted file mode 100644 index c7ba2b9549d2..000000000000 --- a/sound/soc/nuc900/Makefile +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | # NUC900 series audio | ||
3 | snd-soc-nuc900-pcm-objs := nuc900-pcm.o | ||
4 | snd-soc-nuc900-ac97-objs := nuc900-ac97.o | ||
5 | |||
6 | obj-$(CONFIG_SND_SOC_NUC900) += snd-soc-nuc900-pcm.o | ||
7 | obj-$(CONFIG_SND_SOC_NUC900_AC97) += snd-soc-nuc900-ac97.o | ||
8 | |||
9 | # Boards | ||
10 | snd-soc-nuc900-audio-objs := nuc900-audio.o | ||
11 | |||
12 | obj-$(CONFIG_SND_SOC_NUC900EVB) += snd-soc-nuc900-audio.o | ||
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c deleted file mode 100644 index 5f2e5c069377..000000000000 --- a/sound/soc/nuc900/nuc900-ac97.c +++ /dev/null | |||
@@ -1,391 +0,0 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /* | ||
3 | * Copyright (c) 2009-2010 Nuvoton technology corporation. | ||
4 | * | ||
5 | * Wan ZongShun <mcuos.com@gmail.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/mutex.h> | ||
14 | #include <linux/suspend.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/initval.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <linux/clk.h> | ||
20 | |||
21 | #include <mach/mfp.h> | ||
22 | |||
23 | #include "nuc900-audio.h" | ||
24 | |||
25 | static DEFINE_MUTEX(ac97_mutex); | ||
26 | struct nuc900_audio *nuc900_ac97_data; | ||
27 | EXPORT_SYMBOL_GPL(nuc900_ac97_data); | ||
28 | |||
29 | static int nuc900_checkready(void) | ||
30 | { | ||
31 | struct nuc900_audio *nuc900_audio = nuc900_ac97_data; | ||
32 | |||
33 | if (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS0) & CODEC_READY)) | ||
34 | return -EPERM; | ||
35 | |||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | /* AC97 controller reads codec register */ | ||
40 | static unsigned short nuc900_ac97_read(struct snd_ac97 *ac97, | ||
41 | unsigned short reg) | ||
42 | { | ||
43 | struct nuc900_audio *nuc900_audio = nuc900_ac97_data; | ||
44 | unsigned long timeout = 0x10000, val; | ||
45 | |||
46 | mutex_lock(&ac97_mutex); | ||
47 | |||
48 | val = nuc900_checkready(); | ||
49 | if (val) { | ||
50 | dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); | ||
51 | goto out; | ||
52 | } | ||
53 | |||
54 | /* set the R_WB bit and write register index */ | ||
55 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, R_WB | reg); | ||
56 | |||
57 | /* set the valid frame bit and valid slots */ | ||
58 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); | ||
59 | val |= (VALID_FRAME | SLOT1_VALID); | ||
60 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val); | ||
61 | |||
62 | udelay(100); | ||
63 | |||
64 | /* polling the AC_R_FINISH */ | ||
65 | while (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_R_FINISH) | ||
66 | && --timeout) | ||
67 | mdelay(1); | ||
68 | |||
69 | if (!timeout) { | ||
70 | dev_err(nuc900_audio->dev, "AC97 read register time out !\n"); | ||
71 | val = -EPERM; | ||
72 | goto out; | ||
73 | } | ||
74 | |||
75 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0) ; | ||
76 | val &= ~SLOT1_VALID; | ||
77 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val); | ||
78 | |||
79 | if (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS1) >> 2 != reg) { | ||
80 | dev_err(nuc900_audio->dev, | ||
81 | "R_INDEX of REG_ACTL_ACIS1 not match!\n"); | ||
82 | } | ||
83 | |||
84 | udelay(100); | ||
85 | val = (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS2) & 0xFFFF); | ||
86 | |||
87 | out: | ||
88 | mutex_unlock(&ac97_mutex); | ||
89 | return val; | ||
90 | } | ||
91 | |||
92 | /* AC97 controller writes to codec register */ | ||
93 | static void nuc900_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | ||
94 | unsigned short val) | ||
95 | { | ||
96 | struct nuc900_audio *nuc900_audio = nuc900_ac97_data; | ||
97 | unsigned long tmp, timeout = 0x10000; | ||
98 | |||
99 | mutex_lock(&ac97_mutex); | ||
100 | |||
101 | tmp = nuc900_checkready(); | ||
102 | if (tmp) | ||
103 | dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); | ||
104 | |||
105 | /* clear the R_WB bit and write register index */ | ||
106 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, reg); | ||
107 | |||
108 | /* write register value */ | ||
109 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS2, val); | ||
110 | |||
111 | /* set the valid frame bit and valid slots */ | ||
112 | tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); | ||
113 | tmp |= SLOT1_VALID | SLOT2_VALID | VALID_FRAME; | ||
114 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); | ||
115 | |||
116 | udelay(100); | ||
117 | |||
118 | /* polling the AC_W_FINISH */ | ||
119 | while ((AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_W_FINISH) | ||
120 | && --timeout) | ||
121 | mdelay(1); | ||
122 | |||
123 | if (!timeout) | ||
124 | dev_err(nuc900_audio->dev, "AC97 write register time out !\n"); | ||
125 | |||
126 | tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); | ||
127 | tmp &= ~(SLOT1_VALID | SLOT2_VALID); | ||
128 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); | ||
129 | |||
130 | mutex_unlock(&ac97_mutex); | ||
131 | |||
132 | } | ||
133 | |||
134 | static void nuc900_ac97_warm_reset(struct snd_ac97 *ac97) | ||
135 | { | ||
136 | struct nuc900_audio *nuc900_audio = nuc900_ac97_data; | ||
137 | unsigned long val; | ||
138 | |||
139 | mutex_lock(&ac97_mutex); | ||
140 | |||
141 | /* warm reset AC 97 */ | ||
142 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); | ||
143 | val |= AC_W_RES; | ||
144 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); | ||
145 | |||
146 | udelay(100); | ||
147 | |||
148 | val = nuc900_checkready(); | ||
149 | if (val) | ||
150 | dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); | ||
151 | |||
152 | mutex_unlock(&ac97_mutex); | ||
153 | } | ||
154 | |||
155 | static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97) | ||
156 | { | ||
157 | struct nuc900_audio *nuc900_audio = nuc900_ac97_data; | ||
158 | unsigned long val; | ||
159 | |||
160 | mutex_lock(&ac97_mutex); | ||
161 | |||
162 | /* reset Audio Controller */ | ||
163 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); | ||
164 | val |= ACTL_RESET_BIT; | ||
165 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); | ||
166 | |||
167 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); | ||
168 | val &= (~ACTL_RESET_BIT); | ||
169 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); | ||
170 | |||
171 | /* reset AC-link interface */ | ||
172 | |||
173 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); | ||
174 | val |= AC_RESET; | ||
175 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); | ||
176 | |||
177 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); | ||
178 | val &= ~AC_RESET; | ||
179 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); | ||
180 | |||
181 | /* cold reset AC 97 */ | ||
182 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); | ||
183 | val |= AC_C_RES; | ||
184 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); | ||
185 | |||
186 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); | ||
187 | val &= (~AC_C_RES); | ||
188 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); | ||
189 | |||
190 | udelay(100); | ||
191 | |||
192 | mutex_unlock(&ac97_mutex); | ||
193 | |||
194 | } | ||
195 | |||
196 | /* AC97 controller operations */ | ||
197 | static struct snd_ac97_bus_ops nuc900_ac97_ops = { | ||
198 | .read = nuc900_ac97_read, | ||
199 | .write = nuc900_ac97_write, | ||
200 | .reset = nuc900_ac97_cold_reset, | ||
201 | .warm_reset = nuc900_ac97_warm_reset, | ||
202 | }; | ||
203 | |||
204 | static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, | ||
205 | int cmd, struct snd_soc_dai *dai) | ||
206 | { | ||
207 | struct nuc900_audio *nuc900_audio = nuc900_ac97_data; | ||
208 | int ret; | ||
209 | unsigned long val, tmp; | ||
210 | |||
211 | ret = 0; | ||
212 | |||
213 | switch (cmd) { | ||
214 | case SNDRV_PCM_TRIGGER_START: | ||
215 | case SNDRV_PCM_TRIGGER_RESUME: | ||
216 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); | ||
217 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
218 | tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); | ||
219 | tmp |= (SLOT3_VALID | SLOT4_VALID | VALID_FRAME); | ||
220 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); | ||
221 | |||
222 | tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR); | ||
223 | tmp |= (P_DMA_END_IRQ | P_DMA_MIDDLE_IRQ); | ||
224 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, tmp); | ||
225 | val |= AC_PLAY; | ||
226 | } else { | ||
227 | tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR); | ||
228 | tmp |= (R_DMA_END_IRQ | R_DMA_MIDDLE_IRQ); | ||
229 | |||
230 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, tmp); | ||
231 | val |= AC_RECORD; | ||
232 | } | ||
233 | |||
234 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); | ||
235 | |||
236 | break; | ||
237 | case SNDRV_PCM_TRIGGER_STOP: | ||
238 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
239 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); | ||
240 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
241 | tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); | ||
242 | tmp &= ~(SLOT3_VALID | SLOT4_VALID); | ||
243 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); | ||
244 | |||
245 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, RESET_PRSR); | ||
246 | val &= ~AC_PLAY; | ||
247 | } else { | ||
248 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, RESET_PRSR); | ||
249 | val &= ~AC_RECORD; | ||
250 | } | ||
251 | |||
252 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); | ||
253 | |||
254 | break; | ||
255 | default: | ||
256 | ret = -EINVAL; | ||
257 | } | ||
258 | |||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | static int nuc900_ac97_probe(struct snd_soc_dai *dai) | ||
263 | { | ||
264 | struct nuc900_audio *nuc900_audio = nuc900_ac97_data; | ||
265 | unsigned long val; | ||
266 | |||
267 | mutex_lock(&ac97_mutex); | ||
268 | |||
269 | /* enable unit clock */ | ||
270 | clk_enable(nuc900_audio->clk); | ||
271 | |||
272 | /* enable audio controller and AC-link interface */ | ||
273 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); | ||
274 | val |= (IIS_AC_PIN_SEL | ACLINK_EN); | ||
275 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); | ||
276 | |||
277 | mutex_unlock(&ac97_mutex); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int nuc900_ac97_remove(struct snd_soc_dai *dai) | ||
283 | { | ||
284 | struct nuc900_audio *nuc900_audio = nuc900_ac97_data; | ||
285 | |||
286 | clk_disable(nuc900_audio->clk); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = { | ||
291 | .trigger = nuc900_ac97_trigger, | ||
292 | }; | ||
293 | |||
294 | static struct snd_soc_dai_driver nuc900_ac97_dai = { | ||
295 | .probe = nuc900_ac97_probe, | ||
296 | .remove = nuc900_ac97_remove, | ||
297 | .bus_control = true, | ||
298 | .playback = { | ||
299 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
300 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
301 | .channels_min = 1, | ||
302 | .channels_max = 2, | ||
303 | }, | ||
304 | .capture = { | ||
305 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
306 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
307 | .channels_min = 1, | ||
308 | .channels_max = 2, | ||
309 | }, | ||
310 | .ops = &nuc900_ac97_dai_ops, | ||
311 | }; | ||
312 | |||
313 | static const struct snd_soc_component_driver nuc900_ac97_component = { | ||
314 | .name = "nuc900-ac97", | ||
315 | }; | ||
316 | |||
317 | static int nuc900_ac97_drvprobe(struct platform_device *pdev) | ||
318 | { | ||
319 | struct nuc900_audio *nuc900_audio; | ||
320 | int ret; | ||
321 | |||
322 | if (nuc900_ac97_data) | ||
323 | return -EBUSY; | ||
324 | |||
325 | nuc900_audio = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_audio), | ||
326 | GFP_KERNEL); | ||
327 | if (!nuc900_audio) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | spin_lock_init(&nuc900_audio->lock); | ||
331 | |||
332 | nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
333 | nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev, | ||
334 | nuc900_audio->res); | ||
335 | if (IS_ERR(nuc900_audio->mmio)) | ||
336 | return PTR_ERR(nuc900_audio->mmio); | ||
337 | |||
338 | nuc900_audio->clk = devm_clk_get(&pdev->dev, NULL); | ||
339 | if (IS_ERR(nuc900_audio->clk)) { | ||
340 | ret = PTR_ERR(nuc900_audio->clk); | ||
341 | goto out; | ||
342 | } | ||
343 | |||
344 | ret = platform_get_irq(pdev, 0); | ||
345 | if (ret < 0) | ||
346 | goto out; | ||
347 | nuc900_audio->irq_num = ret; | ||
348 | |||
349 | nuc900_ac97_data = nuc900_audio; | ||
350 | |||
351 | ret = snd_soc_set_ac97_ops(&nuc900_ac97_ops); | ||
352 | if (ret) | ||
353 | goto out; | ||
354 | |||
355 | ret = devm_snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, | ||
356 | &nuc900_ac97_dai, 1); | ||
357 | if (ret) | ||
358 | goto out; | ||
359 | |||
360 | /* enbale ac97 multifunction pin */ | ||
361 | mfp_set_groupg(nuc900_audio->dev, NULL); | ||
362 | |||
363 | return 0; | ||
364 | |||
365 | out: | ||
366 | snd_soc_set_ac97_ops(NULL); | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | static int nuc900_ac97_drvremove(struct platform_device *pdev) | ||
371 | { | ||
372 | nuc900_ac97_data = NULL; | ||
373 | snd_soc_set_ac97_ops(NULL); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static struct platform_driver nuc900_ac97_driver = { | ||
379 | .driver = { | ||
380 | .name = "nuc900-ac97", | ||
381 | }, | ||
382 | .probe = nuc900_ac97_drvprobe, | ||
383 | .remove = nuc900_ac97_drvremove, | ||
384 | }; | ||
385 | |||
386 | module_platform_driver(nuc900_ac97_driver); | ||
387 | |||
388 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
389 | MODULE_DESCRIPTION("NUC900 AC97 SoC driver!"); | ||
390 | MODULE_LICENSE("GPL"); | ||
391 | MODULE_ALIAS("platform:nuc900-ac97"); | ||
diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c deleted file mode 100644 index 19146690d514..000000000000 --- a/sound/soc/nuc900/nuc900-audio.c +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /* | ||
3 | * Copyright (c) 2010 Nuvoton technology corporation. | ||
4 | * | ||
5 | * Wan ZongShun <mcuos.com@gmail.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/moduleparam.h> | ||
10 | #include <linux/timer.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | #include <sound/core.h> | ||
15 | #include <sound/pcm.h> | ||
16 | #include <sound/soc.h> | ||
17 | |||
18 | #include "nuc900-audio.h" | ||
19 | |||
20 | SND_SOC_DAILINK_DEFS(ac97, | ||
21 | DAILINK_COMP_ARRAY(COMP_CPU("nuc900-ac97")), | ||
22 | DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), | ||
23 | DAILINK_COMP_ARRAY(COMP_PLATFORM("nuc900-pcm-audio"))); | ||
24 | |||
25 | static struct snd_soc_dai_link nuc900evb_ac97_dai = { | ||
26 | .name = "AC97", | ||
27 | .stream_name = "AC97 HiFi", | ||
28 | SND_SOC_DAILINK_REG(ac97), | ||
29 | }; | ||
30 | |||
31 | static struct snd_soc_card nuc900evb_audio_machine = { | ||
32 | .name = "NUC900EVB_AC97", | ||
33 | .owner = THIS_MODULE, | ||
34 | .dai_link = &nuc900evb_ac97_dai, | ||
35 | .num_links = 1, | ||
36 | }; | ||
37 | |||
38 | static struct platform_device *nuc900evb_asoc_dev; | ||
39 | |||
40 | static int __init nuc900evb_audio_init(void) | ||
41 | { | ||
42 | int ret; | ||
43 | |||
44 | ret = -ENOMEM; | ||
45 | nuc900evb_asoc_dev = platform_device_alloc("soc-audio", -1); | ||
46 | if (!nuc900evb_asoc_dev) | ||
47 | goto out; | ||
48 | |||
49 | /* nuc900 board audio device */ | ||
50 | platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_audio_machine); | ||
51 | |||
52 | ret = platform_device_add(nuc900evb_asoc_dev); | ||
53 | |||
54 | if (ret) { | ||
55 | platform_device_put(nuc900evb_asoc_dev); | ||
56 | nuc900evb_asoc_dev = NULL; | ||
57 | } | ||
58 | |||
59 | out: | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static void __exit nuc900evb_audio_exit(void) | ||
64 | { | ||
65 | platform_device_unregister(nuc900evb_asoc_dev); | ||
66 | } | ||
67 | |||
68 | module_init(nuc900evb_audio_init); | ||
69 | module_exit(nuc900evb_audio_exit); | ||
70 | |||
71 | MODULE_LICENSE("GPL"); | ||
72 | MODULE_DESCRIPTION("NUC900 Series ASoC audio support"); | ||
73 | MODULE_AUTHOR("Wan ZongShun"); | ||
diff --git a/sound/soc/nuc900/nuc900-audio.h b/sound/soc/nuc900/nuc900-audio.h deleted file mode 100644 index 90ffa7bbce01..000000000000 --- a/sound/soc/nuc900/nuc900-audio.h +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
2 | /* | ||
3 | * Copyright (c) 2010 Nuvoton technology corporation. | ||
4 | * | ||
5 | * Wan ZongShun <mcuos.com@gmail.com> | ||
6 | */ | ||
7 | |||
8 | #ifndef _NUC900_AUDIO_H | ||
9 | #define _NUC900_AUDIO_H | ||
10 | |||
11 | #include <linux/io.h> | ||
12 | |||
13 | /* Audio Control Registers */ | ||
14 | #define ACTL_CON 0x00 | ||
15 | #define ACTL_RESET 0x04 | ||
16 | #define ACTL_RDSTB 0x08 | ||
17 | #define ACTL_RDST_LENGTH 0x0C | ||
18 | #define ACTL_RDSTC 0x10 | ||
19 | #define ACTL_RSR 0x14 | ||
20 | #define ACTL_PDSTB 0x18 | ||
21 | #define ACTL_PDST_LENGTH 0x1C | ||
22 | #define ACTL_PDSTC 0x20 | ||
23 | #define ACTL_PSR 0x24 | ||
24 | #define ACTL_IISCON 0x28 | ||
25 | #define ACTL_ACCON 0x2C | ||
26 | #define ACTL_ACOS0 0x30 | ||
27 | #define ACTL_ACOS1 0x34 | ||
28 | #define ACTL_ACOS2 0x38 | ||
29 | #define ACTL_ACIS0 0x3C | ||
30 | #define ACTL_ACIS1 0x40 | ||
31 | #define ACTL_ACIS2 0x44 | ||
32 | #define ACTL_COUNTER 0x48 | ||
33 | |||
34 | /* bit definition of REG_ACTL_CON register */ | ||
35 | #define R_DMA_IRQ 0x1000 | ||
36 | #define T_DMA_IRQ 0x0800 | ||
37 | #define IIS_AC_PIN_SEL 0x0100 | ||
38 | #define FIFO_TH 0x0080 | ||
39 | #define ADC_EN 0x0010 | ||
40 | #define M80_EN 0x0008 | ||
41 | #define ACLINK_EN 0x0004 | ||
42 | #define IIS_EN 0x0002 | ||
43 | |||
44 | /* bit definition of REG_ACTL_RESET register */ | ||
45 | #define W5691_PLAY 0x20000 | ||
46 | #define ACTL_RESET_BIT 0x10000 | ||
47 | #define RECORD_RIGHT_CHNNEL 0x08000 | ||
48 | #define RECORD_LEFT_CHNNEL 0x04000 | ||
49 | #define PLAY_RIGHT_CHNNEL 0x02000 | ||
50 | #define PLAY_LEFT_CHNNEL 0x01000 | ||
51 | #define DAC_PLAY 0x00800 | ||
52 | #define ADC_RECORD 0x00400 | ||
53 | #define M80_PLAY 0x00200 | ||
54 | #define AC_RECORD 0x00100 | ||
55 | #define AC_PLAY 0x00080 | ||
56 | #define IIS_RECORD 0x00040 | ||
57 | #define IIS_PLAY 0x00020 | ||
58 | #define DAC_RESET 0x00010 | ||
59 | #define ADC_RESET 0x00008 | ||
60 | #define M80_RESET 0x00004 | ||
61 | #define AC_RESET 0x00002 | ||
62 | #define IIS_RESET 0x00001 | ||
63 | |||
64 | /* bit definition of REG_ACTL_ACCON register */ | ||
65 | #define AC_BCLK_PU_EN 0x20 | ||
66 | #define AC_R_FINISH 0x10 | ||
67 | #define AC_W_FINISH 0x08 | ||
68 | #define AC_W_RES 0x04 | ||
69 | #define AC_C_RES 0x02 | ||
70 | |||
71 | /* bit definition of ACTL_RSR register */ | ||
72 | #define R_FIFO_EMPTY 0x04 | ||
73 | #define R_DMA_END_IRQ 0x02 | ||
74 | #define R_DMA_MIDDLE_IRQ 0x01 | ||
75 | |||
76 | /* bit definition of ACTL_PSR register */ | ||
77 | #define P_FIFO_EMPTY 0x04 | ||
78 | #define P_DMA_END_IRQ 0x02 | ||
79 | #define P_DMA_MIDDLE_IRQ 0x01 | ||
80 | |||
81 | /* bit definition of ACTL_ACOS0 register */ | ||
82 | #define SLOT1_VALID 0x01 | ||
83 | #define SLOT2_VALID 0x02 | ||
84 | #define SLOT3_VALID 0x04 | ||
85 | #define SLOT4_VALID 0x08 | ||
86 | #define VALID_FRAME 0x10 | ||
87 | |||
88 | /* bit definition of ACTL_ACOS1 register */ | ||
89 | #define R_WB 0x80 | ||
90 | |||
91 | #define CODEC_READY 0x10 | ||
92 | #define RESET_PRSR 0x00 | ||
93 | #define AUDIO_WRITE(addr, val) __raw_writel(val, addr) | ||
94 | #define AUDIO_READ(addr) __raw_readl(addr) | ||
95 | |||
96 | struct nuc900_audio { | ||
97 | void __iomem *mmio; | ||
98 | spinlock_t lock; | ||
99 | unsigned long irq_num; | ||
100 | struct resource *res; | ||
101 | struct clk *clk; | ||
102 | struct device *dev; | ||
103 | |||
104 | }; | ||
105 | |||
106 | extern struct nuc900_audio *nuc900_ac97_data; | ||
107 | |||
108 | #endif /*end _NUC900_AUDIO_H */ | ||
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c deleted file mode 100644 index 4442a26e9502..000000000000 --- a/sound/soc/nuc900/nuc900-pcm.c +++ /dev/null | |||
@@ -1,321 +0,0 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /* | ||
3 | * Copyright (c) 2010 Nuvoton technology corporation. | ||
4 | * | ||
5 | * Wan ZongShun <mcuos.com@gmail.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/io.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/dma-mapping.h> | ||
14 | |||
15 | #include <sound/core.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | ||
19 | |||
20 | #include <mach/hardware.h> | ||
21 | |||
22 | #include "nuc900-audio.h" | ||
23 | |||
24 | static const struct snd_pcm_hardware nuc900_pcm_hardware = { | ||
25 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
26 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
27 | SNDRV_PCM_INFO_MMAP | | ||
28 | SNDRV_PCM_INFO_MMAP_VALID | | ||
29 | SNDRV_PCM_INFO_PAUSE | | ||
30 | SNDRV_PCM_INFO_RESUME, | ||
31 | .buffer_bytes_max = 4*1024, | ||
32 | .period_bytes_min = 1*1024, | ||
33 | .period_bytes_max = 4*1024, | ||
34 | .periods_min = 1, | ||
35 | .periods_max = 1024, | ||
36 | }; | ||
37 | |||
38 | static int nuc900_dma_hw_params(struct snd_pcm_substream *substream, | ||
39 | struct snd_pcm_hw_params *params) | ||
40 | { | ||
41 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
42 | } | ||
43 | |||
44 | static void nuc900_update_dma_register(struct snd_pcm_substream *substream) | ||
45 | { | ||
46 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
47 | struct nuc900_audio *nuc900_audio = runtime->private_data; | ||
48 | void __iomem *mmio_addr, *mmio_len; | ||
49 | |||
50 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
51 | mmio_addr = nuc900_audio->mmio + ACTL_PDSTB; | ||
52 | mmio_len = nuc900_audio->mmio + ACTL_PDST_LENGTH; | ||
53 | } else { | ||
54 | mmio_addr = nuc900_audio->mmio + ACTL_RDSTB; | ||
55 | mmio_len = nuc900_audio->mmio + ACTL_RDST_LENGTH; | ||
56 | } | ||
57 | |||
58 | AUDIO_WRITE(mmio_addr, runtime->dma_addr); | ||
59 | AUDIO_WRITE(mmio_len, runtime->dma_bytes); | ||
60 | } | ||
61 | |||
62 | static void nuc900_dma_start(struct snd_pcm_substream *substream) | ||
63 | { | ||
64 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
65 | struct nuc900_audio *nuc900_audio = runtime->private_data; | ||
66 | unsigned long val; | ||
67 | |||
68 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); | ||
69 | val |= (T_DMA_IRQ | R_DMA_IRQ); | ||
70 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); | ||
71 | } | ||
72 | |||
73 | static void nuc900_dma_stop(struct snd_pcm_substream *substream) | ||
74 | { | ||
75 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
76 | struct nuc900_audio *nuc900_audio = runtime->private_data; | ||
77 | unsigned long val; | ||
78 | |||
79 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); | ||
80 | val &= ~(T_DMA_IRQ | R_DMA_IRQ); | ||
81 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); | ||
82 | } | ||
83 | |||
84 | static irqreturn_t nuc900_dma_interrupt(int irq, void *dev_id) | ||
85 | { | ||
86 | struct snd_pcm_substream *substream = dev_id; | ||
87 | struct nuc900_audio *nuc900_audio = substream->runtime->private_data; | ||
88 | unsigned long val; | ||
89 | |||
90 | spin_lock(&nuc900_audio->lock); | ||
91 | |||
92 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); | ||
93 | |||
94 | if (val & R_DMA_IRQ) { | ||
95 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | R_DMA_IRQ); | ||
96 | |||
97 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR); | ||
98 | |||
99 | if (val & R_DMA_MIDDLE_IRQ) { | ||
100 | val |= R_DMA_MIDDLE_IRQ; | ||
101 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val); | ||
102 | } | ||
103 | |||
104 | if (val & R_DMA_END_IRQ) { | ||
105 | val |= R_DMA_END_IRQ; | ||
106 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val); | ||
107 | } | ||
108 | } else if (val & T_DMA_IRQ) { | ||
109 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | T_DMA_IRQ); | ||
110 | |||
111 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR); | ||
112 | |||
113 | if (val & P_DMA_MIDDLE_IRQ) { | ||
114 | val |= P_DMA_MIDDLE_IRQ; | ||
115 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val); | ||
116 | } | ||
117 | |||
118 | if (val & P_DMA_END_IRQ) { | ||
119 | val |= P_DMA_END_IRQ; | ||
120 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val); | ||
121 | } | ||
122 | } else { | ||
123 | dev_err(nuc900_audio->dev, "Wrong DMA interrupt status!\n"); | ||
124 | spin_unlock(&nuc900_audio->lock); | ||
125 | return IRQ_HANDLED; | ||
126 | } | ||
127 | |||
128 | spin_unlock(&nuc900_audio->lock); | ||
129 | |||
130 | snd_pcm_period_elapsed(substream); | ||
131 | |||
132 | return IRQ_HANDLED; | ||
133 | } | ||
134 | |||
135 | static int nuc900_dma_hw_free(struct snd_pcm_substream *substream) | ||
136 | { | ||
137 | snd_pcm_lib_free_pages(substream); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int nuc900_dma_prepare(struct snd_pcm_substream *substream) | ||
142 | { | ||
143 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
144 | struct nuc900_audio *nuc900_audio = runtime->private_data; | ||
145 | unsigned long flags, val; | ||
146 | int ret = 0; | ||
147 | |||
148 | spin_lock_irqsave(&nuc900_audio->lock, flags); | ||
149 | |||
150 | nuc900_update_dma_register(substream); | ||
151 | |||
152 | val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); | ||
153 | |||
154 | switch (runtime->channels) { | ||
155 | case 1: | ||
156 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
157 | val &= ~(PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL); | ||
158 | val |= PLAY_RIGHT_CHNNEL; | ||
159 | } else { | ||
160 | val &= ~(RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL); | ||
161 | val |= RECORD_RIGHT_CHNNEL; | ||
162 | } | ||
163 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); | ||
164 | break; | ||
165 | case 2: | ||
166 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
167 | val |= (PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL); | ||
168 | else | ||
169 | val |= (RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL); | ||
170 | AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); | ||
171 | break; | ||
172 | default: | ||
173 | ret = -EINVAL; | ||
174 | } | ||
175 | spin_unlock_irqrestore(&nuc900_audio->lock, flags); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd) | ||
180 | { | ||
181 | int ret = 0; | ||
182 | |||
183 | switch (cmd) { | ||
184 | case SNDRV_PCM_TRIGGER_START: | ||
185 | case SNDRV_PCM_TRIGGER_RESUME: | ||
186 | nuc900_dma_start(substream); | ||
187 | break; | ||
188 | |||
189 | case SNDRV_PCM_TRIGGER_STOP: | ||
190 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
191 | nuc900_dma_stop(substream); | ||
192 | break; | ||
193 | |||
194 | default: | ||
195 | ret = -EINVAL; | ||
196 | break; | ||
197 | } | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | static int nuc900_dma_getposition(struct snd_pcm_substream *substream, | ||
203 | dma_addr_t *src, dma_addr_t *dst) | ||
204 | { | ||
205 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
206 | struct nuc900_audio *nuc900_audio = runtime->private_data; | ||
207 | |||
208 | if (src != NULL) | ||
209 | *src = AUDIO_READ(nuc900_audio->mmio + ACTL_PDSTC); | ||
210 | |||
211 | if (dst != NULL) | ||
212 | *dst = AUDIO_READ(nuc900_audio->mmio + ACTL_RDSTC); | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static snd_pcm_uframes_t nuc900_dma_pointer(struct snd_pcm_substream *substream) | ||
218 | { | ||
219 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
220 | dma_addr_t src, dst; | ||
221 | unsigned long res; | ||
222 | |||
223 | nuc900_dma_getposition(substream, &src, &dst); | ||
224 | |||
225 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
226 | res = dst - runtime->dma_addr; | ||
227 | else | ||
228 | res = src - runtime->dma_addr; | ||
229 | |||
230 | return bytes_to_frames(substream->runtime, res); | ||
231 | } | ||
232 | |||
233 | static int nuc900_dma_open(struct snd_pcm_substream *substream) | ||
234 | { | ||
235 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
236 | struct nuc900_audio *nuc900_audio; | ||
237 | |||
238 | snd_soc_set_runtime_hwparams(substream, &nuc900_pcm_hardware); | ||
239 | |||
240 | nuc900_audio = nuc900_ac97_data; | ||
241 | |||
242 | if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt, | ||
243 | 0, "nuc900-dma", substream)) | ||
244 | return -EBUSY; | ||
245 | |||
246 | runtime->private_data = nuc900_audio; | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int nuc900_dma_close(struct snd_pcm_substream *substream) | ||
252 | { | ||
253 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
254 | struct nuc900_audio *nuc900_audio = runtime->private_data; | ||
255 | |||
256 | free_irq(nuc900_audio->irq_num, substream); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int nuc900_dma_mmap(struct snd_pcm_substream *substream, | ||
262 | struct vm_area_struct *vma) | ||
263 | { | ||
264 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
265 | |||
266 | return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area, | ||
267 | runtime->dma_addr, runtime->dma_bytes); | ||
268 | } | ||
269 | |||
270 | static const struct snd_pcm_ops nuc900_dma_ops = { | ||
271 | .open = nuc900_dma_open, | ||
272 | .close = nuc900_dma_close, | ||
273 | .ioctl = snd_pcm_lib_ioctl, | ||
274 | .hw_params = nuc900_dma_hw_params, | ||
275 | .hw_free = nuc900_dma_hw_free, | ||
276 | .prepare = nuc900_dma_prepare, | ||
277 | .trigger = nuc900_dma_trigger, | ||
278 | .pointer = nuc900_dma_pointer, | ||
279 | .mmap = nuc900_dma_mmap, | ||
280 | }; | ||
281 | |||
282 | static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) | ||
283 | { | ||
284 | struct snd_card *card = rtd->card->snd_card; | ||
285 | struct snd_pcm *pcm = rtd->pcm; | ||
286 | int ret; | ||
287 | |||
288 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
289 | if (ret) | ||
290 | return ret; | ||
291 | |||
292 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
293 | card->dev, 4 * 1024, (4 * 1024) - 1); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static const struct snd_soc_component_driver nuc900_soc_component = { | ||
299 | .ops = &nuc900_dma_ops, | ||
300 | .pcm_new = nuc900_dma_new, | ||
301 | }; | ||
302 | |||
303 | static int nuc900_soc_platform_probe(struct platform_device *pdev) | ||
304 | { | ||
305 | return devm_snd_soc_register_component(&pdev->dev, &nuc900_soc_component, | ||
306 | NULL, 0); | ||
307 | } | ||
308 | |||
309 | static struct platform_driver nuc900_pcm_driver = { | ||
310 | .driver = { | ||
311 | .name = "nuc900-pcm-audio", | ||
312 | }, | ||
313 | |||
314 | .probe = nuc900_soc_platform_probe, | ||
315 | }; | ||
316 | |||
317 | module_platform_driver(nuc900_pcm_driver); | ||
318 | |||
319 | MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>"); | ||
320 | MODULE_DESCRIPTION("nuc900 Audio DMA module"); | ||
321 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 72f4364b2d20..e3e5425b5c62 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c | |||
@@ -399,7 +399,6 @@ static const struct snd_soc_component_driver mmp_sspa_component = { | |||
399 | static int asoc_mmp_sspa_probe(struct platform_device *pdev) | 399 | static int asoc_mmp_sspa_probe(struct platform_device *pdev) |
400 | { | 400 | { |
401 | struct sspa_priv *priv; | 401 | struct sspa_priv *priv; |
402 | struct resource *res; | ||
403 | 402 | ||
404 | priv = devm_kzalloc(&pdev->dev, | 403 | priv = devm_kzalloc(&pdev->dev, |
405 | sizeof(struct sspa_priv), GFP_KERNEL); | 404 | sizeof(struct sspa_priv), GFP_KERNEL); |
@@ -417,8 +416,7 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev) | |||
417 | if (priv->dma_params == NULL) | 416 | if (priv->dma_params == NULL) |
418 | return -ENOMEM; | 417 | return -ENOMEM; |
419 | 418 | ||
420 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 419 | priv->sspa->mmio_base = devm_platform_ioremap_resource(pdev, 0); |
421 | priv->sspa->mmio_base = devm_ioremap_resource(&pdev->dev, res); | ||
422 | if (IS_ERR(priv->sspa->mmio_base)) | 420 | if (IS_ERR(priv->sspa->mmio_base)) |
423 | return PTR_ERR(priv->sspa->mmio_base); | 421 | return PTR_ERR(priv->sspa->mmio_base); |
424 | 422 | ||
diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 2c7348ddbbb3..6c20bdd850f3 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c | |||
@@ -53,12 +53,18 @@ int qcom_snd_parse_of(struct snd_soc_card *card) | |||
53 | link->num_cpus = 1; | 53 | link->num_cpus = 1; |
54 | link->num_platforms = 1; | 54 | link->num_platforms = 1; |
55 | 55 | ||
56 | ret = of_property_read_string(np, "link-name", &link->name); | ||
57 | if (ret) { | ||
58 | dev_err(card->dev, "error getting codec dai_link name\n"); | ||
59 | goto err; | ||
60 | } | ||
61 | |||
56 | cpu = of_get_child_by_name(np, "cpu"); | 62 | cpu = of_get_child_by_name(np, "cpu"); |
57 | platform = of_get_child_by_name(np, "platform"); | 63 | platform = of_get_child_by_name(np, "platform"); |
58 | codec = of_get_child_by_name(np, "codec"); | 64 | codec = of_get_child_by_name(np, "codec"); |
59 | 65 | ||
60 | if (!cpu) { | 66 | if (!cpu) { |
61 | dev_err(dev, "Can't find cpu DT node\n"); | 67 | dev_err(dev, "%s: Can't find cpu DT node\n", link->name); |
62 | ret = -EINVAL; | 68 | ret = -EINVAL; |
63 | goto err; | 69 | goto err; |
64 | } | 70 | } |
@@ -66,7 +72,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) | |||
66 | ret = of_parse_phandle_with_args(cpu, "sound-dai", | 72 | ret = of_parse_phandle_with_args(cpu, "sound-dai", |
67 | "#sound-dai-cells", 0, &args); | 73 | "#sound-dai-cells", 0, &args); |
68 | if (ret) { | 74 | if (ret) { |
69 | dev_err(card->dev, "error getting cpu phandle\n"); | 75 | dev_err(card->dev, "%s: error getting cpu phandle\n", link->name); |
70 | goto err; | 76 | goto err; |
71 | } | 77 | } |
72 | link->cpus->of_node = args.np; | 78 | link->cpus->of_node = args.np; |
@@ -74,7 +80,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) | |||
74 | 80 | ||
75 | ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); | 81 | ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); |
76 | if (ret) { | 82 | if (ret) { |
77 | dev_err(card->dev, "error getting cpu dai name\n"); | 83 | dev_err(card->dev, "%s: error getting cpu dai name\n", link->name); |
78 | goto err; | 84 | goto err; |
79 | } | 85 | } |
80 | 86 | ||
@@ -83,14 +89,14 @@ int qcom_snd_parse_of(struct snd_soc_card *card) | |||
83 | "sound-dai", | 89 | "sound-dai", |
84 | 0); | 90 | 0); |
85 | if (!link->platforms->of_node) { | 91 | if (!link->platforms->of_node) { |
86 | dev_err(card->dev, "platform dai not found\n"); | 92 | dev_err(card->dev, "%s: platform dai not found\n", link->name); |
87 | ret = -EINVAL; | 93 | ret = -EINVAL; |
88 | goto err; | 94 | goto err; |
89 | } | 95 | } |
90 | 96 | ||
91 | ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); | 97 | ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); |
92 | if (ret < 0) { | 98 | if (ret < 0) { |
93 | dev_err(card->dev, "codec dai not found\n"); | 99 | dev_err(card->dev, "%s: codec dai not found\n", link->name); |
94 | goto err; | 100 | goto err; |
95 | } | 101 | } |
96 | link->no_pcm = 1; | 102 | link->no_pcm = 1; |
@@ -110,12 +116,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card) | |||
110 | } | 116 | } |
111 | 117 | ||
112 | link->ignore_suspend = 1; | 118 | link->ignore_suspend = 1; |
113 | ret = of_property_read_string(np, "link-name", &link->name); | ||
114 | if (ret) { | ||
115 | dev_err(card->dev, "error getting codec dai_link name\n"); | ||
116 | goto err; | ||
117 | } | ||
118 | |||
119 | link->nonatomic = 1; | 119 | link->nonatomic = 1; |
120 | link->dpcm_playback = 1; | 120 | link->dpcm_playback = 1; |
121 | link->dpcm_capture = 1; | 121 | link->dpcm_capture = 1; |
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index cf7a299f4547..4c745baa39f7 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c | |||
@@ -564,11 +564,8 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) | |||
564 | int ret; | 564 | int ret; |
565 | 565 | ||
566 | drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); | 566 | drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); |
567 | if (drvdata->lpaif_irq < 0) { | 567 | if (drvdata->lpaif_irq < 0) |
568 | dev_err(&pdev->dev, "error getting irq handle: %d\n", | ||
569 | drvdata->lpaif_irq); | ||
570 | return -ENODEV; | 568 | return -ENODEV; |
571 | } | ||
572 | 569 | ||
573 | /* ensure audio hardware is disabled */ | 570 | /* ensure audio hardware is disabled */ |
574 | ret = regmap_write(drvdata->lpaif_map, | 571 | ret = regmap_write(drvdata->lpaif_map, |
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 88ebaf6e1880..af2d5a6124c8 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -419,6 +419,9 @@ static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, | |||
419 | struct rk_i2s_dev *i2s = to_info(cpu_dai); | 419 | struct rk_i2s_dev *i2s = to_info(cpu_dai); |
420 | int ret; | 420 | int ret; |
421 | 421 | ||
422 | if (freq == 0) | ||
423 | return 0; | ||
424 | |||
422 | ret = clk_set_rate(i2s->mclk, freq); | 425 | ret = clk_set_rate(i2s->mclk, freq); |
423 | if (ret) | 426 | if (ret) |
424 | dev_err(i2s->dev, "Fail to set mclk %d\n", ret); | 427 | dev_err(i2s->dev, "Fail to set mclk %d\n", ret); |
diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index d54f672d38d8..0097df1fae66 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c | |||
@@ -45,7 +45,6 @@ static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { | |||
45 | 45 | ||
46 | static const struct snd_soc_dapm_route rk_audio_map[] = { | 46 | static const struct snd_soc_dapm_route rk_audio_map[] = { |
47 | {"IN34", NULL, "Headset Mic"}, | 47 | {"IN34", NULL, "Headset Mic"}, |
48 | {"IN34", NULL, "MICBIAS"}, | ||
49 | {"Headset Mic", NULL, "MICBIAS"}, | 48 | {"Headset Mic", NULL, "MICBIAS"}, |
50 | {"DMICL", NULL, "Int Mic"}, | 49 | {"DMICL", NULL, "Int Mic"}, |
51 | {"Headphone", NULL, "HPL"}, | 50 | {"Headphone", NULL, "HPL"}, |
@@ -172,7 +171,7 @@ static struct snd_soc_dai_link rk_dailink = { | |||
172 | static int rk_98090_headset_init(struct snd_soc_component *component); | 171 | static int rk_98090_headset_init(struct snd_soc_component *component); |
173 | 172 | ||
174 | static struct snd_soc_aux_dev rk_98090_headset_dev = { | 173 | static struct snd_soc_aux_dev rk_98090_headset_dev = { |
175 | .name = "Headset Chip", | 174 | .dlc = COMP_EMPTY(), |
176 | .init = rk_98090_headset_init, | 175 | .init = rk_98090_headset_init, |
177 | }; | 176 | }; |
178 | 177 | ||
@@ -238,9 +237,9 @@ static int snd_rk_mc_probe(struct platform_device *pdev) | |||
238 | 237 | ||
239 | rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; | 238 | rk_dailink.platforms->of_node = rk_dailink.cpus->of_node; |
240 | 239 | ||
241 | rk_98090_headset_dev.codec_of_node = of_parse_phandle(np, | 240 | rk_98090_headset_dev.dlc.of_node = of_parse_phandle(np, |
242 | "rockchip,headset-codec", 0); | 241 | "rockchip,headset-codec", 0); |
243 | if (!rk_98090_headset_dev.codec_of_node) { | 242 | if (!rk_98090_headset_dev.dlc.of_node) { |
244 | dev_err(&pdev->dev, | 243 | dev_err(&pdev->dev, |
245 | "Property 'rockchip,headset-codec' missing/invalid\n"); | 244 | "Property 'rockchip,headset-codec' missing/invalid\n"); |
246 | return -EINVAL; | 245 | return -EINVAL; |
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 396776ffd670..38f536bafa09 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c | |||
@@ -297,8 +297,7 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
297 | 297 | ||
298 | static struct snd_soc_aux_dev neo1973_aux_devs[] = { | 298 | static struct snd_soc_aux_dev neo1973_aux_devs[] = { |
299 | { | 299 | { |
300 | .name = "dfbmcs320", | 300 | .dlc = COMP_AUX("dfbmcs320.0"), |
301 | .codec_name = "dfbmcs320.0", | ||
302 | }, | 301 | }, |
303 | }; | 302 | }; |
304 | 303 | ||
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 51e4c976c8be..9e58cbed942a 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c | |||
@@ -240,8 +240,7 @@ static int speyside_wm9081_init(struct snd_soc_component *component) | |||
240 | 240 | ||
241 | static struct snd_soc_aux_dev speyside_aux_dev[] = { | 241 | static struct snd_soc_aux_dev speyside_aux_dev[] = { |
242 | { | 242 | { |
243 | .name = "wm9081", | 243 | .dlc = COMP_AUX("wm9081.1-006c"), |
244 | .codec_name = "wm9081.1-006c", | ||
245 | .init = speyside_wm9081_init, | 244 | .init = speyside_wm9081_init, |
246 | }, | 245 | }, |
247 | }; | 246 | }; |
diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index c091033d17ad..bb9910d4cbe2 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c | |||
@@ -307,7 +307,6 @@ static struct snd_soc_aux_dev tm2_speaker_amp_dev; | |||
307 | static int tm2_late_probe(struct snd_soc_card *card) | 307 | static int tm2_late_probe(struct snd_soc_card *card) |
308 | { | 308 | { |
309 | struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); | 309 | struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); |
310 | struct snd_soc_dai_link_component dlc = { 0 }; | ||
311 | unsigned int ch_map[] = { 0, 1 }; | 310 | unsigned int ch_map[] = { 0, 1 }; |
312 | struct snd_soc_dai *amp_pdm_dai; | 311 | struct snd_soc_dai *amp_pdm_dai; |
313 | struct snd_soc_pcm_runtime *rtd; | 312 | struct snd_soc_pcm_runtime *rtd; |
@@ -334,8 +333,7 @@ static int tm2_late_probe(struct snd_soc_card *card) | |||
334 | return ret; | 333 | return ret; |
335 | } | 334 | } |
336 | 335 | ||
337 | dlc.of_node = tm2_speaker_amp_dev.codec_of_node; | 336 | amp_pdm_dai = snd_soc_find_dai(&tm2_speaker_amp_dev.dlc); |
338 | amp_pdm_dai = snd_soc_find_dai(&dlc); | ||
339 | if (!amp_pdm_dai) | 337 | if (!amp_pdm_dai) |
340 | return -ENODEV; | 338 | return -ENODEV; |
341 | 339 | ||
@@ -532,9 +530,9 @@ static int tm2_probe(struct platform_device *pdev) | |||
532 | return ret; | 530 | return ret; |
533 | } | 531 | } |
534 | 532 | ||
535 | card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node, | 533 | card->aux_dev[0].dlc.of_node = of_parse_phandle(dev->of_node, |
536 | "audio-amplifier", 0); | 534 | "audio-amplifier", 0); |
537 | if (!card->aux_dev[0].codec_of_node) { | 535 | if (!card->aux_dev[0].dlc.of_node) { |
538 | dev_err(dev, "audio-amplifier property invalid or missing\n"); | 536 | dev_err(dev, "audio-amplifier property invalid or missing\n"); |
539 | return -EINVAL; | 537 | return -EINVAL; |
540 | } | 538 | } |
@@ -623,7 +621,7 @@ dai_node_put: | |||
623 | of_node_put(cpu_dai_node[i]); | 621 | of_node_put(cpu_dai_node[i]); |
624 | } | 622 | } |
625 | 623 | ||
626 | of_node_put(card->aux_dev[0].codec_of_node); | 624 | of_node_put(card->aux_dev[0].dlc.of_node); |
627 | 625 | ||
628 | return ret; | 626 | return ret; |
629 | } | 627 | } |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 56e8dae9a15c..bda5b958d0dc 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -1421,6 +1421,20 @@ static int rsnd_hw_params(struct snd_pcm_substream *substream, | |||
1421 | params_buffer_bytes(hw_params)); | 1421 | params_buffer_bytes(hw_params)); |
1422 | } | 1422 | } |
1423 | 1423 | ||
1424 | static int rsnd_hw_free(struct snd_pcm_substream *substream) | ||
1425 | { | ||
1426 | struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); | ||
1427 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | ||
1428 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); | ||
1429 | int ret; | ||
1430 | |||
1431 | ret = rsnd_dai_call(hw_free, io, substream); | ||
1432 | if (ret) | ||
1433 | return ret; | ||
1434 | |||
1435 | return snd_pcm_lib_free_pages(substream); | ||
1436 | } | ||
1437 | |||
1424 | static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) | 1438 | static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) |
1425 | { | 1439 | { |
1426 | struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); | 1440 | struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); |
@@ -1436,7 +1450,7 @@ static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) | |||
1436 | static const struct snd_pcm_ops rsnd_pcm_ops = { | 1450 | static const struct snd_pcm_ops rsnd_pcm_ops = { |
1437 | .ioctl = snd_pcm_lib_ioctl, | 1451 | .ioctl = snd_pcm_lib_ioctl, |
1438 | .hw_params = rsnd_hw_params, | 1452 | .hw_params = rsnd_hw_params, |
1439 | .hw_free = snd_pcm_lib_free_pages, | 1453 | .hw_free = rsnd_hw_free, |
1440 | .pointer = rsnd_pointer, | 1454 | .pointer = rsnd_pointer, |
1441 | }; | 1455 | }; |
1442 | 1456 | ||
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 7727add3eb1a..ea6cbaa9743e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -327,6 +327,9 @@ struct rsnd_mod_ops { | |||
327 | int (*cleanup)(struct rsnd_mod *mod, | 327 | int (*cleanup)(struct rsnd_mod *mod, |
328 | struct rsnd_dai_stream *io, | 328 | struct rsnd_dai_stream *io, |
329 | struct rsnd_priv *priv); | 329 | struct rsnd_priv *priv); |
330 | int (*hw_free)(struct rsnd_mod *mod, | ||
331 | struct rsnd_dai_stream *io, | ||
332 | struct snd_pcm_substream *substream); | ||
330 | u32 *(*get_status)(struct rsnd_mod *mod, | 333 | u32 *(*get_status)(struct rsnd_mod *mod, |
331 | struct rsnd_dai_stream *io, | 334 | struct rsnd_dai_stream *io, |
332 | enum rsnd_mod_type type); | 335 | enum rsnd_mod_type type); |
@@ -351,12 +354,12 @@ struct rsnd_mod { | |||
351 | * | 354 | * |
352 | * B 0: init 1: quit | 355 | * B 0: init 1: quit |
353 | * C 0: start 1: stop | 356 | * C 0: start 1: stop |
357 | * D 0: hw_params 1: hw_free | ||
354 | * | 358 | * |
355 | * H is always called (see __rsnd_mod_call) | 359 | * H is always called (see __rsnd_mod_call) |
356 | * H 0: probe 1: remove | 360 | * H 0: probe 1: remove |
357 | * H 0: pcm_new | 361 | * H 0: pcm_new |
358 | * H 0: fallback | 362 | * H 0: fallback |
359 | * H 0: hw_params | ||
360 | * H 0: pointer | 363 | * H 0: pointer |
361 | * H 0: prepare | 364 | * H 0: prepare |
362 | * H 0: cleanup | 365 | * H 0: cleanup |
@@ -365,12 +368,13 @@ struct rsnd_mod { | |||
365 | #define __rsnd_mod_shift_quit 4 | 368 | #define __rsnd_mod_shift_quit 4 |
366 | #define __rsnd_mod_shift_start 8 | 369 | #define __rsnd_mod_shift_start 8 |
367 | #define __rsnd_mod_shift_stop 8 | 370 | #define __rsnd_mod_shift_stop 8 |
371 | #define __rsnd_mod_shift_hw_params 12 | ||
372 | #define __rsnd_mod_shift_hw_free 12 | ||
368 | #define __rsnd_mod_shift_probe 28 /* always called */ | 373 | #define __rsnd_mod_shift_probe 28 /* always called */ |
369 | #define __rsnd_mod_shift_remove 28 /* always called */ | 374 | #define __rsnd_mod_shift_remove 28 /* always called */ |
370 | #define __rsnd_mod_shift_irq 28 /* always called */ | 375 | #define __rsnd_mod_shift_irq 28 /* always called */ |
371 | #define __rsnd_mod_shift_pcm_new 28 /* always called */ | 376 | #define __rsnd_mod_shift_pcm_new 28 /* always called */ |
372 | #define __rsnd_mod_shift_fallback 28 /* always called */ | 377 | #define __rsnd_mod_shift_fallback 28 /* always called */ |
373 | #define __rsnd_mod_shift_hw_params 28 /* always called */ | ||
374 | #define __rsnd_mod_shift_pointer 28 /* always called */ | 378 | #define __rsnd_mod_shift_pointer 28 /* always called */ |
375 | #define __rsnd_mod_shift_prepare 28 /* always called */ | 379 | #define __rsnd_mod_shift_prepare 28 /* always called */ |
376 | #define __rsnd_mod_shift_cleanup 28 /* always called */ | 380 | #define __rsnd_mod_shift_cleanup 28 /* always called */ |
@@ -383,10 +387,11 @@ struct rsnd_mod { | |||
383 | #define __rsnd_mod_add_quit -1 | 387 | #define __rsnd_mod_add_quit -1 |
384 | #define __rsnd_mod_add_start 1 | 388 | #define __rsnd_mod_add_start 1 |
385 | #define __rsnd_mod_add_stop -1 | 389 | #define __rsnd_mod_add_stop -1 |
390 | #define __rsnd_mod_add_hw_params 1 | ||
391 | #define __rsnd_mod_add_hw_free -1 | ||
386 | #define __rsnd_mod_add_irq 0 | 392 | #define __rsnd_mod_add_irq 0 |
387 | #define __rsnd_mod_add_pcm_new 0 | 393 | #define __rsnd_mod_add_pcm_new 0 |
388 | #define __rsnd_mod_add_fallback 0 | 394 | #define __rsnd_mod_add_fallback 0 |
389 | #define __rsnd_mod_add_hw_params 0 | ||
390 | #define __rsnd_mod_add_pointer 0 | 395 | #define __rsnd_mod_add_pointer 0 |
391 | 396 | ||
392 | #define __rsnd_mod_call_probe 0 | 397 | #define __rsnd_mod_call_probe 0 |
@@ -402,6 +407,7 @@ struct rsnd_mod { | |||
402 | #define __rsnd_mod_call_fallback 0 | 407 | #define __rsnd_mod_call_fallback 0 |
403 | #define __rsnd_mod_call_hw_params 0 | 408 | #define __rsnd_mod_call_hw_params 0 |
404 | #define __rsnd_mod_call_pointer 0 | 409 | #define __rsnd_mod_call_pointer 0 |
410 | #define __rsnd_mod_call_hw_free 1 | ||
405 | 411 | ||
406 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | 412 | #define rsnd_mod_to_priv(mod) ((mod)->priv) |
407 | #define rsnd_mod_power_on(mod) clk_enable((mod)->clk) | 413 | #define rsnd_mod_power_on(mod) clk_enable((mod)->clk) |
diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c index 8bab119c753a..2af0c6f14ee6 100644 --- a/sound/soc/sirf/sirf-usp.c +++ b/sound/soc/sirf/sirf-usp.c | |||
@@ -359,7 +359,6 @@ static int sirf_usp_pcm_probe(struct platform_device *pdev) | |||
359 | int ret; | 359 | int ret; |
360 | struct sirf_usp *usp; | 360 | struct sirf_usp *usp; |
361 | void __iomem *base; | 361 | void __iomem *base; |
362 | struct resource *mem_res; | ||
363 | 362 | ||
364 | usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp), | 363 | usp = devm_kzalloc(&pdev->dev, sizeof(struct sirf_usp), |
365 | GFP_KERNEL); | 364 | GFP_KERNEL); |
@@ -368,8 +367,7 @@ static int sirf_usp_pcm_probe(struct platform_device *pdev) | |||
368 | 367 | ||
369 | platform_set_drvdata(pdev, usp); | 368 | platform_set_drvdata(pdev, usp); |
370 | 369 | ||
371 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 370 | base = devm_platform_ioremap_resource(pdev, 0); |
372 | base = devm_ioremap_resource(&pdev->dev, mem_res); | ||
373 | if (IS_ERR(base)) | 371 | if (IS_ERR(base)) |
374 | return PTR_ERR(base); | 372 | return PTR_ERR(base); |
375 | usp->regmap = devm_regmap_init_mmio(&pdev->dev, base, | 373 | usp->regmap = devm_regmap_init_mmio(&pdev->dev, base, |
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c new file mode 100644 index 000000000000..79ffc2820ba9 --- /dev/null +++ b/sound/soc/soc-component.c | |||
@@ -0,0 +1,561 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // soc-component.c | ||
4 | // | ||
5 | // Copyright (C) 2019 Renesas Electronics Corp. | ||
6 | // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
7 | // | ||
8 | #include <linux/module.h> | ||
9 | #include <sound/soc.h> | ||
10 | |||
11 | /** | ||
12 | * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. | ||
13 | * @component: COMPONENT | ||
14 | * @clk_id: DAI specific clock ID | ||
15 | * @source: Source for the clock | ||
16 | * @freq: new clock frequency in Hz | ||
17 | * @dir: new clock direction - input/output. | ||
18 | * | ||
19 | * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. | ||
20 | */ | ||
21 | int snd_soc_component_set_sysclk(struct snd_soc_component *component, | ||
22 | int clk_id, int source, unsigned int freq, | ||
23 | int dir) | ||
24 | { | ||
25 | if (component->driver->set_sysclk) | ||
26 | return component->driver->set_sysclk(component, clk_id, source, | ||
27 | freq, dir); | ||
28 | |||
29 | return -ENOTSUPP; | ||
30 | } | ||
31 | EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); | ||
32 | |||
33 | /* | ||
34 | * snd_soc_component_set_pll - configure component PLL. | ||
35 | * @component: COMPONENT | ||
36 | * @pll_id: DAI specific PLL ID | ||
37 | * @source: DAI specific source for the PLL | ||
38 | * @freq_in: PLL input clock frequency in Hz | ||
39 | * @freq_out: requested PLL output clock frequency in Hz | ||
40 | * | ||
41 | * Configures and enables PLL to generate output clock based on input clock. | ||
42 | */ | ||
43 | int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, | ||
44 | int source, unsigned int freq_in, | ||
45 | unsigned int freq_out) | ||
46 | { | ||
47 | if (component->driver->set_pll) | ||
48 | return component->driver->set_pll(component, pll_id, source, | ||
49 | freq_in, freq_out); | ||
50 | |||
51 | return -EINVAL; | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); | ||
54 | |||
55 | void snd_soc_component_seq_notifier(struct snd_soc_component *component, | ||
56 | enum snd_soc_dapm_type type, int subseq) | ||
57 | { | ||
58 | if (component->driver->seq_notifier) | ||
59 | component->driver->seq_notifier(component, type, subseq); | ||
60 | } | ||
61 | |||
62 | int snd_soc_component_stream_event(struct snd_soc_component *component, | ||
63 | int event) | ||
64 | { | ||
65 | if (component->driver->stream_event) | ||
66 | return component->driver->stream_event(component, event); | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | int snd_soc_component_set_bias_level(struct snd_soc_component *component, | ||
72 | enum snd_soc_bias_level level) | ||
73 | { | ||
74 | if (component->driver->set_bias_level) | ||
75 | return component->driver->set_bias_level(component, level); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | int snd_soc_component_enable_pin(struct snd_soc_component *component, | ||
81 | const char *pin) | ||
82 | { | ||
83 | struct snd_soc_dapm_context *dapm = | ||
84 | snd_soc_component_get_dapm(component); | ||
85 | char *full_name; | ||
86 | int ret; | ||
87 | |||
88 | if (!component->name_prefix) | ||
89 | return snd_soc_dapm_enable_pin(dapm, pin); | ||
90 | |||
91 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
92 | if (!full_name) | ||
93 | return -ENOMEM; | ||
94 | |||
95 | ret = snd_soc_dapm_enable_pin(dapm, full_name); | ||
96 | kfree(full_name); | ||
97 | |||
98 | return ret; | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); | ||
101 | |||
102 | int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, | ||
103 | const char *pin) | ||
104 | { | ||
105 | struct snd_soc_dapm_context *dapm = | ||
106 | snd_soc_component_get_dapm(component); | ||
107 | char *full_name; | ||
108 | int ret; | ||
109 | |||
110 | if (!component->name_prefix) | ||
111 | return snd_soc_dapm_enable_pin_unlocked(dapm, pin); | ||
112 | |||
113 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
114 | if (!full_name) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name); | ||
118 | kfree(full_name); | ||
119 | |||
120 | return ret; | ||
121 | } | ||
122 | EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); | ||
123 | |||
124 | int snd_soc_component_disable_pin(struct snd_soc_component *component, | ||
125 | const char *pin) | ||
126 | { | ||
127 | struct snd_soc_dapm_context *dapm = | ||
128 | snd_soc_component_get_dapm(component); | ||
129 | char *full_name; | ||
130 | int ret; | ||
131 | |||
132 | if (!component->name_prefix) | ||
133 | return snd_soc_dapm_disable_pin(dapm, pin); | ||
134 | |||
135 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
136 | if (!full_name) | ||
137 | return -ENOMEM; | ||
138 | |||
139 | ret = snd_soc_dapm_disable_pin(dapm, full_name); | ||
140 | kfree(full_name); | ||
141 | |||
142 | return ret; | ||
143 | } | ||
144 | EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); | ||
145 | |||
146 | int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, | ||
147 | const char *pin) | ||
148 | { | ||
149 | struct snd_soc_dapm_context *dapm = | ||
150 | snd_soc_component_get_dapm(component); | ||
151 | char *full_name; | ||
152 | int ret; | ||
153 | |||
154 | if (!component->name_prefix) | ||
155 | return snd_soc_dapm_disable_pin_unlocked(dapm, pin); | ||
156 | |||
157 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
158 | if (!full_name) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name); | ||
162 | kfree(full_name); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); | ||
167 | |||
168 | int snd_soc_component_nc_pin(struct snd_soc_component *component, | ||
169 | const char *pin) | ||
170 | { | ||
171 | struct snd_soc_dapm_context *dapm = | ||
172 | snd_soc_component_get_dapm(component); | ||
173 | char *full_name; | ||
174 | int ret; | ||
175 | |||
176 | if (!component->name_prefix) | ||
177 | return snd_soc_dapm_nc_pin(dapm, pin); | ||
178 | |||
179 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
180 | if (!full_name) | ||
181 | return -ENOMEM; | ||
182 | |||
183 | ret = snd_soc_dapm_nc_pin(dapm, full_name); | ||
184 | kfree(full_name); | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); | ||
189 | |||
190 | int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, | ||
191 | const char *pin) | ||
192 | { | ||
193 | struct snd_soc_dapm_context *dapm = | ||
194 | snd_soc_component_get_dapm(component); | ||
195 | char *full_name; | ||
196 | int ret; | ||
197 | |||
198 | if (!component->name_prefix) | ||
199 | return snd_soc_dapm_nc_pin_unlocked(dapm, pin); | ||
200 | |||
201 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
202 | if (!full_name) | ||
203 | return -ENOMEM; | ||
204 | |||
205 | ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name); | ||
206 | kfree(full_name); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); | ||
211 | |||
212 | int snd_soc_component_get_pin_status(struct snd_soc_component *component, | ||
213 | const char *pin) | ||
214 | { | ||
215 | struct snd_soc_dapm_context *dapm = | ||
216 | snd_soc_component_get_dapm(component); | ||
217 | char *full_name; | ||
218 | int ret; | ||
219 | |||
220 | if (!component->name_prefix) | ||
221 | return snd_soc_dapm_get_pin_status(dapm, pin); | ||
222 | |||
223 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
224 | if (!full_name) | ||
225 | return -ENOMEM; | ||
226 | |||
227 | ret = snd_soc_dapm_get_pin_status(dapm, full_name); | ||
228 | kfree(full_name); | ||
229 | |||
230 | return ret; | ||
231 | } | ||
232 | EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); | ||
233 | |||
234 | int snd_soc_component_force_enable_pin(struct snd_soc_component *component, | ||
235 | const char *pin) | ||
236 | { | ||
237 | struct snd_soc_dapm_context *dapm = | ||
238 | snd_soc_component_get_dapm(component); | ||
239 | char *full_name; | ||
240 | int ret; | ||
241 | |||
242 | if (!component->name_prefix) | ||
243 | return snd_soc_dapm_force_enable_pin(dapm, pin); | ||
244 | |||
245 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
246 | if (!full_name) | ||
247 | return -ENOMEM; | ||
248 | |||
249 | ret = snd_soc_dapm_force_enable_pin(dapm, full_name); | ||
250 | kfree(full_name); | ||
251 | |||
252 | return ret; | ||
253 | } | ||
254 | EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); | ||
255 | |||
256 | int snd_soc_component_force_enable_pin_unlocked( | ||
257 | struct snd_soc_component *component, | ||
258 | const char *pin) | ||
259 | { | ||
260 | struct snd_soc_dapm_context *dapm = | ||
261 | snd_soc_component_get_dapm(component); | ||
262 | char *full_name; | ||
263 | int ret; | ||
264 | |||
265 | if (!component->name_prefix) | ||
266 | return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); | ||
267 | |||
268 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
269 | if (!full_name) | ||
270 | return -ENOMEM; | ||
271 | |||
272 | ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name); | ||
273 | kfree(full_name); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); | ||
278 | |||
279 | /** | ||
280 | * snd_soc_component_set_jack - configure component jack. | ||
281 | * @component: COMPONENTs | ||
282 | * @jack: structure to use for the jack | ||
283 | * @data: can be used if codec driver need extra data for configuring jack | ||
284 | * | ||
285 | * Configures and enables jack detection function. | ||
286 | */ | ||
287 | int snd_soc_component_set_jack(struct snd_soc_component *component, | ||
288 | struct snd_soc_jack *jack, void *data) | ||
289 | { | ||
290 | if (component->driver->set_jack) | ||
291 | return component->driver->set_jack(component, jack, data); | ||
292 | |||
293 | return -ENOTSUPP; | ||
294 | } | ||
295 | EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); | ||
296 | |||
297 | int snd_soc_component_module_get(struct snd_soc_component *component, | ||
298 | int upon_open) | ||
299 | { | ||
300 | if (component->driver->module_get_upon_open == !!upon_open && | ||
301 | !try_module_get(component->dev->driver->owner)) | ||
302 | return -ENODEV; | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | void snd_soc_component_module_put(struct snd_soc_component *component, | ||
308 | int upon_open) | ||
309 | { | ||
310 | if (component->driver->module_get_upon_open == !!upon_open) | ||
311 | module_put(component->dev->driver->owner); | ||
312 | } | ||
313 | |||
314 | int snd_soc_component_open(struct snd_soc_component *component, | ||
315 | struct snd_pcm_substream *substream) | ||
316 | { | ||
317 | if (component->driver->ops && | ||
318 | component->driver->ops->open) | ||
319 | return component->driver->ops->open(substream); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | int snd_soc_component_close(struct snd_soc_component *component, | ||
325 | struct snd_pcm_substream *substream) | ||
326 | { | ||
327 | if (component->driver->ops && | ||
328 | component->driver->ops->close) | ||
329 | return component->driver->ops->close(substream); | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | int snd_soc_component_prepare(struct snd_soc_component *component, | ||
335 | struct snd_pcm_substream *substream) | ||
336 | { | ||
337 | if (component->driver->ops && | ||
338 | component->driver->ops->prepare) | ||
339 | return component->driver->ops->prepare(substream); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | int snd_soc_component_hw_params(struct snd_soc_component *component, | ||
345 | struct snd_pcm_substream *substream, | ||
346 | struct snd_pcm_hw_params *params) | ||
347 | { | ||
348 | if (component->driver->ops && | ||
349 | component->driver->ops->hw_params) | ||
350 | return component->driver->ops->hw_params(substream, params); | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | int snd_soc_component_hw_free(struct snd_soc_component *component, | ||
356 | struct snd_pcm_substream *substream) | ||
357 | { | ||
358 | if (component->driver->ops && | ||
359 | component->driver->ops->hw_free) | ||
360 | return component->driver->ops->hw_free(substream); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | int snd_soc_component_trigger(struct snd_soc_component *component, | ||
366 | struct snd_pcm_substream *substream, | ||
367 | int cmd) | ||
368 | { | ||
369 | if (component->driver->ops && | ||
370 | component->driver->ops->trigger) | ||
371 | return component->driver->ops->trigger(substream, cmd); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | void snd_soc_component_suspend(struct snd_soc_component *component) | ||
377 | { | ||
378 | if (component->driver->suspend) | ||
379 | component->driver->suspend(component); | ||
380 | component->suspended = 1; | ||
381 | } | ||
382 | |||
383 | void snd_soc_component_resume(struct snd_soc_component *component) | ||
384 | { | ||
385 | if (component->driver->resume) | ||
386 | component->driver->resume(component); | ||
387 | component->suspended = 0; | ||
388 | } | ||
389 | |||
390 | int snd_soc_component_is_suspended(struct snd_soc_component *component) | ||
391 | { | ||
392 | return component->suspended; | ||
393 | } | ||
394 | |||
395 | int snd_soc_component_probe(struct snd_soc_component *component) | ||
396 | { | ||
397 | if (component->driver->probe) | ||
398 | return component->driver->probe(component); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | void snd_soc_component_remove(struct snd_soc_component *component) | ||
404 | { | ||
405 | if (component->driver->remove) | ||
406 | component->driver->remove(component); | ||
407 | } | ||
408 | |||
409 | int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, | ||
410 | struct device_node *ep) | ||
411 | { | ||
412 | if (component->driver->of_xlate_dai_id) | ||
413 | return component->driver->of_xlate_dai_id(component, ep); | ||
414 | |||
415 | return -ENOTSUPP; | ||
416 | } | ||
417 | |||
418 | int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, | ||
419 | struct of_phandle_args *args, | ||
420 | const char **dai_name) | ||
421 | { | ||
422 | if (component->driver->of_xlate_dai_name) | ||
423 | return component->driver->of_xlate_dai_name(component, | ||
424 | args, dai_name); | ||
425 | return -ENOTSUPP; | ||
426 | } | ||
427 | |||
428 | int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) | ||
429 | { | ||
430 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
431 | struct snd_soc_component *component; | ||
432 | struct snd_soc_rtdcom_list *rtdcom; | ||
433 | |||
434 | for_each_rtdcom(rtd, rtdcom) { | ||
435 | component = rtdcom->component; | ||
436 | |||
437 | /* FIXME: use 1st pointer */ | ||
438 | if (component->driver->ops && | ||
439 | component->driver->ops->pointer) | ||
440 | return component->driver->ops->pointer(substream); | ||
441 | } | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, | ||
447 | unsigned int cmd, void *arg) | ||
448 | { | ||
449 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
450 | struct snd_soc_component *component; | ||
451 | struct snd_soc_rtdcom_list *rtdcom; | ||
452 | |||
453 | for_each_rtdcom(rtd, rtdcom) { | ||
454 | component = rtdcom->component; | ||
455 | |||
456 | /* FIXME: use 1st ioctl */ | ||
457 | if (component->driver->ops && | ||
458 | component->driver->ops->ioctl) | ||
459 | return component->driver->ops->ioctl(substream, | ||
460 | cmd, arg); | ||
461 | } | ||
462 | |||
463 | return snd_pcm_lib_ioctl(substream, cmd, arg); | ||
464 | } | ||
465 | |||
466 | int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, | ||
467 | int channel, unsigned long pos, | ||
468 | void __user *buf, unsigned long bytes) | ||
469 | { | ||
470 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
471 | struct snd_soc_rtdcom_list *rtdcom; | ||
472 | struct snd_soc_component *component; | ||
473 | |||
474 | for_each_rtdcom(rtd, rtdcom) { | ||
475 | component = rtdcom->component; | ||
476 | |||
477 | /* FIXME. it returns 1st copy now */ | ||
478 | if (component->driver->ops && | ||
479 | component->driver->ops->copy_user) | ||
480 | return component->driver->ops->copy_user( | ||
481 | substream, channel, pos, buf, bytes); | ||
482 | } | ||
483 | |||
484 | return -EINVAL; | ||
485 | } | ||
486 | |||
487 | struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, | ||
488 | unsigned long offset) | ||
489 | { | ||
490 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
491 | struct snd_soc_rtdcom_list *rtdcom; | ||
492 | struct snd_soc_component *component; | ||
493 | struct page *page; | ||
494 | |||
495 | for_each_rtdcom(rtd, rtdcom) { | ||
496 | component = rtdcom->component; | ||
497 | |||
498 | /* FIXME. it returns 1st page now */ | ||
499 | if (component->driver->ops && | ||
500 | component->driver->ops->page) { | ||
501 | page = component->driver->ops->page(substream, offset); | ||
502 | if (page) | ||
503 | return page; | ||
504 | } | ||
505 | } | ||
506 | |||
507 | return NULL; | ||
508 | } | ||
509 | |||
510 | int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, | ||
511 | struct vm_area_struct *vma) | ||
512 | { | ||
513 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
514 | struct snd_soc_rtdcom_list *rtdcom; | ||
515 | struct snd_soc_component *component; | ||
516 | |||
517 | for_each_rtdcom(rtd, rtdcom) { | ||
518 | component = rtdcom->component; | ||
519 | |||
520 | /* FIXME. it returns 1st mmap now */ | ||
521 | if (component->driver->ops && | ||
522 | component->driver->ops->mmap) | ||
523 | return component->driver->ops->mmap(substream, vma); | ||
524 | } | ||
525 | |||
526 | return -EINVAL; | ||
527 | } | ||
528 | |||
529 | int snd_soc_pcm_component_new(struct snd_pcm *pcm) | ||
530 | { | ||
531 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | ||
532 | struct snd_soc_rtdcom_list *rtdcom; | ||
533 | struct snd_soc_component *component; | ||
534 | int ret; | ||
535 | |||
536 | for_each_rtdcom(rtd, rtdcom) { | ||
537 | component = rtdcom->component; | ||
538 | |||
539 | if (component->driver->pcm_new) { | ||
540 | ret = component->driver->pcm_new(rtd); | ||
541 | if (ret < 0) | ||
542 | return ret; | ||
543 | } | ||
544 | } | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | void snd_soc_pcm_component_free(struct snd_pcm *pcm) | ||
550 | { | ||
551 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | ||
552 | struct snd_soc_rtdcom_list *rtdcom; | ||
553 | struct snd_soc_component *component; | ||
554 | |||
555 | for_each_rtdcom(rtd, rtdcom) { | ||
556 | component = rtdcom->component; | ||
557 | |||
558 | if (component->driver->pcm_free) | ||
559 | component->driver->pcm_free(pcm); | ||
560 | } | ||
561 | } | ||
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index ddef4ff677ce..9e54d8ae6d2c 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -80,7 +80,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) | |||
80 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 80 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
81 | int ret; | 81 | int ret; |
82 | 82 | ||
83 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 83 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
84 | 84 | ||
85 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) { | 85 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) { |
86 | ret = cpu_dai->driver->cops->startup(cstream, cpu_dai); | 86 | ret = cpu_dai->driver->cops->startup(cstream, cpu_dai); |
@@ -108,7 +108,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) | |||
108 | 108 | ||
109 | snd_soc_runtime_activate(rtd, cstream->direction); | 109 | snd_soc_runtime_activate(rtd, cstream->direction); |
110 | 110 | ||
111 | mutex_unlock(&rtd->pcm_mutex); | 111 | mutex_unlock(&rtd->card->pcm_mutex); |
112 | 112 | ||
113 | return 0; | 113 | return 0; |
114 | 114 | ||
@@ -118,7 +118,7 @@ machine_err: | |||
118 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) | 118 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown) |
119 | cpu_dai->driver->cops->shutdown(cstream, cpu_dai); | 119 | cpu_dai->driver->cops->shutdown(cstream, cpu_dai); |
120 | out: | 120 | out: |
121 | mutex_unlock(&rtd->pcm_mutex); | 121 | mutex_unlock(&rtd->card->pcm_mutex); |
122 | return ret; | 122 | return ret; |
123 | } | 123 | } |
124 | 124 | ||
@@ -224,7 +224,7 @@ static void close_delayed_work(struct work_struct *work) | |||
224 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | 224 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); |
225 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 225 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
226 | 226 | ||
227 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 227 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
228 | 228 | ||
229 | dev_dbg(rtd->dev, | 229 | dev_dbg(rtd->dev, |
230 | "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n", | 230 | "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n", |
@@ -239,7 +239,7 @@ static void close_delayed_work(struct work_struct *work) | |||
239 | SND_SOC_DAPM_STREAM_STOP); | 239 | SND_SOC_DAPM_STREAM_STOP); |
240 | } | 240 | } |
241 | 241 | ||
242 | mutex_unlock(&rtd->pcm_mutex); | 242 | mutex_unlock(&rtd->card->pcm_mutex); |
243 | } | 243 | } |
244 | 244 | ||
245 | static int soc_compr_free(struct snd_compr_stream *cstream) | 245 | static int soc_compr_free(struct snd_compr_stream *cstream) |
@@ -249,7 +249,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) | |||
249 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 249 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
250 | int stream; | 250 | int stream; |
251 | 251 | ||
252 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 252 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
253 | 253 | ||
254 | if (cstream->direction == SND_COMPRESS_PLAYBACK) | 254 | if (cstream->direction == SND_COMPRESS_PLAYBACK) |
255 | stream = SNDRV_PCM_STREAM_PLAYBACK; | 255 | stream = SNDRV_PCM_STREAM_PLAYBACK; |
@@ -292,7 +292,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) | |||
292 | SND_SOC_DAPM_STREAM_STOP); | 292 | SND_SOC_DAPM_STREAM_STOP); |
293 | } | 293 | } |
294 | 294 | ||
295 | mutex_unlock(&rtd->pcm_mutex); | 295 | mutex_unlock(&rtd->card->pcm_mutex); |
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
298 | 298 | ||
@@ -375,7 +375,7 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) | |||
375 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 375 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
376 | int ret; | 376 | int ret; |
377 | 377 | ||
378 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 378 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
379 | 379 | ||
380 | ret = soc_compr_components_trigger(cstream, cmd); | 380 | ret = soc_compr_components_trigger(cstream, cmd); |
381 | if (ret < 0) | 381 | if (ret < 0) |
@@ -394,7 +394,7 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) | |||
394 | } | 394 | } |
395 | 395 | ||
396 | out: | 396 | out: |
397 | mutex_unlock(&rtd->pcm_mutex); | 397 | mutex_unlock(&rtd->card->pcm_mutex); |
398 | return ret; | 398 | return ret; |
399 | } | 399 | } |
400 | 400 | ||
@@ -480,7 +480,7 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, | |||
480 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 480 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
481 | int ret; | 481 | int ret; |
482 | 482 | ||
483 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 483 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
484 | 484 | ||
485 | /* | 485 | /* |
486 | * First we call set_params for the CPU DAI, then the component | 486 | * First we call set_params for the CPU DAI, then the component |
@@ -514,14 +514,14 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream, | |||
514 | 514 | ||
515 | /* cancel any delayed stream shutdown that is pending */ | 515 | /* cancel any delayed stream shutdown that is pending */ |
516 | rtd->pop_wait = 0; | 516 | rtd->pop_wait = 0; |
517 | mutex_unlock(&rtd->pcm_mutex); | 517 | mutex_unlock(&rtd->card->pcm_mutex); |
518 | 518 | ||
519 | cancel_delayed_work_sync(&rtd->delayed_work); | 519 | cancel_delayed_work_sync(&rtd->delayed_work); |
520 | 520 | ||
521 | return 0; | 521 | return 0; |
522 | 522 | ||
523 | err: | 523 | err: |
524 | mutex_unlock(&rtd->pcm_mutex); | 524 | mutex_unlock(&rtd->card->pcm_mutex); |
525 | return ret; | 525 | return ret; |
526 | } | 526 | } |
527 | 527 | ||
@@ -593,7 +593,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, | |||
593 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 593 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
594 | int ret = 0; | 594 | int ret = 0; |
595 | 595 | ||
596 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 596 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
597 | 597 | ||
598 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) { | 598 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) { |
599 | ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai); | 599 | ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai); |
@@ -613,7 +613,7 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream, | |||
613 | } | 613 | } |
614 | 614 | ||
615 | err: | 615 | err: |
616 | mutex_unlock(&rtd->pcm_mutex); | 616 | mutex_unlock(&rtd->card->pcm_mutex); |
617 | return ret; | 617 | return ret; |
618 | } | 618 | } |
619 | 619 | ||
@@ -625,7 +625,7 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream, | |||
625 | struct snd_soc_rtdcom_list *rtdcom; | 625 | struct snd_soc_rtdcom_list *rtdcom; |
626 | int ret = 0; | 626 | int ret = 0; |
627 | 627 | ||
628 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 628 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
629 | 629 | ||
630 | for_each_rtdcom(rtd, rtdcom) { | 630 | for_each_rtdcom(rtd, rtdcom) { |
631 | component = rtdcom->component; | 631 | component = rtdcom->component; |
@@ -638,7 +638,7 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream, | |||
638 | break; | 638 | break; |
639 | } | 639 | } |
640 | 640 | ||
641 | mutex_unlock(&rtd->pcm_mutex); | 641 | mutex_unlock(&rtd->card->pcm_mutex); |
642 | return ret; | 642 | return ret; |
643 | } | 643 | } |
644 | 644 | ||
@@ -650,7 +650,7 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, | |||
650 | struct snd_soc_rtdcom_list *rtdcom; | 650 | struct snd_soc_rtdcom_list *rtdcom; |
651 | int ret = 0; | 651 | int ret = 0; |
652 | 652 | ||
653 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 653 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
654 | 654 | ||
655 | for_each_rtdcom(rtd, rtdcom) { | 655 | for_each_rtdcom(rtd, rtdcom) { |
656 | component = rtdcom->component; | 656 | component = rtdcom->component; |
@@ -664,7 +664,7 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, | |||
664 | break; | 664 | break; |
665 | } | 665 | } |
666 | 666 | ||
667 | mutex_unlock(&rtd->pcm_mutex); | 667 | mutex_unlock(&rtd->card->pcm_mutex); |
668 | return ret; | 668 | return ret; |
669 | } | 669 | } |
670 | 670 | ||
@@ -676,7 +676,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) | |||
676 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 676 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
677 | int ret = 0; | 677 | int ret = 0; |
678 | 678 | ||
679 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 679 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
680 | 680 | ||
681 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) { | 681 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) { |
682 | ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai); | 682 | ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai); |
@@ -697,7 +697,7 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) | |||
697 | } | 697 | } |
698 | 698 | ||
699 | err: | 699 | err: |
700 | mutex_unlock(&rtd->pcm_mutex); | 700 | mutex_unlock(&rtd->card->pcm_mutex); |
701 | return ret; | 701 | return ret; |
702 | } | 702 | } |
703 | 703 | ||
@@ -710,7 +710,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, | |||
710 | int ret = 0; | 710 | int ret = 0; |
711 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 711 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
712 | 712 | ||
713 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 713 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
714 | 714 | ||
715 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer) | 715 | if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer) |
716 | cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai); | 716 | cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai); |
@@ -726,7 +726,7 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream, | |||
726 | break; | 726 | break; |
727 | } | 727 | } |
728 | 728 | ||
729 | mutex_unlock(&rtd->pcm_mutex); | 729 | mutex_unlock(&rtd->card->pcm_mutex); |
730 | return ret; | 730 | return ret; |
731 | } | 731 | } |
732 | 732 | ||
@@ -738,7 +738,7 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, | |||
738 | struct snd_soc_rtdcom_list *rtdcom; | 738 | struct snd_soc_rtdcom_list *rtdcom; |
739 | int ret = 0; | 739 | int ret = 0; |
740 | 740 | ||
741 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 741 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
742 | 742 | ||
743 | for_each_rtdcom(rtd, rtdcom) { | 743 | for_each_rtdcom(rtd, rtdcom) { |
744 | component = rtdcom->component; | 744 | component = rtdcom->component; |
@@ -751,7 +751,7 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, | |||
751 | break; | 751 | break; |
752 | } | 752 | } |
753 | 753 | ||
754 | mutex_unlock(&rtd->pcm_mutex); | 754 | mutex_unlock(&rtd->card->pcm_mutex); |
755 | return ret; | 755 | return ret; |
756 | } | 756 | } |
757 | 757 | ||
@@ -872,14 +872,13 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | |||
872 | } | 872 | } |
873 | 873 | ||
874 | /* check client and interface hw capabilities */ | 874 | /* check client and interface hw capabilities */ |
875 | if (codec_dai->driver->playback.channels_min) | 875 | if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && |
876 | snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) | ||
876 | playback = 1; | 877 | playback = 1; |
877 | if (codec_dai->driver->capture.channels_min) | 878 | if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && |
879 | snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) | ||
878 | capture = 1; | 880 | capture = 1; |
879 | 881 | ||
880 | capture = capture && cpu_dai->driver->capture.channels_min; | ||
881 | playback = playback && cpu_dai->driver->playback.channels_min; | ||
882 | |||
883 | /* | 882 | /* |
884 | * Compress devices are unidirectional so only one of the directions | 883 | * Compress devices are unidirectional so only one of the directions |
885 | * should be set, check for that (xor) | 884 | * should be set, check for that (xor) |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 44f899b970c2..35f48e9c5ead 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -73,6 +73,7 @@ static int pmdown_time = 5000; | |||
73 | module_param(pmdown_time, int, 0); | 73 | module_param(pmdown_time, int, 0); |
74 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 74 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
75 | 75 | ||
76 | #ifdef CONFIG_DMI | ||
76 | /* | 77 | /* |
77 | * If a DMI filed contain strings in this blacklist (e.g. | 78 | * If a DMI filed contain strings in this blacklist (e.g. |
78 | * "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken | 79 | * "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken |
@@ -87,6 +88,7 @@ static const char * const dmi_blacklist[] = { | |||
87 | "Board Product Name", | 88 | "Board Product Name", |
88 | NULL, /* terminator */ | 89 | NULL, /* terminator */ |
89 | }; | 90 | }; |
91 | #endif | ||
90 | 92 | ||
91 | static ssize_t pmdown_time_show(struct device *dev, | 93 | static ssize_t pmdown_time_show(struct device *dev, |
92 | struct device_attribute *attr, char *buf) | 94 | struct device_attribute *attr, char *buf) |
@@ -165,20 +167,16 @@ static void soc_init_component_debugfs(struct snd_soc_component *component) | |||
165 | component->card->debugfs_card_root); | 167 | component->card->debugfs_card_root); |
166 | } | 168 | } |
167 | 169 | ||
168 | if (IS_ERR(component->debugfs_root)) { | ||
169 | dev_warn(component->dev, | ||
170 | "ASoC: Failed to create component debugfs directory: %ld\n", | ||
171 | PTR_ERR(component->debugfs_root)); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | snd_soc_dapm_debugfs_init(snd_soc_component_get_dapm(component), | 170 | snd_soc_dapm_debugfs_init(snd_soc_component_get_dapm(component), |
176 | component->debugfs_root); | 171 | component->debugfs_root); |
177 | } | 172 | } |
178 | 173 | ||
179 | static void soc_cleanup_component_debugfs(struct snd_soc_component *component) | 174 | static void soc_cleanup_component_debugfs(struct snd_soc_component *component) |
180 | { | 175 | { |
176 | if (!component->debugfs_root) | ||
177 | return; | ||
181 | debugfs_remove_recursive(component->debugfs_root); | 178 | debugfs_remove_recursive(component->debugfs_root); |
179 | component->debugfs_root = NULL; | ||
182 | } | 180 | } |
183 | 181 | ||
184 | static int dai_list_show(struct seq_file *m, void *v) | 182 | static int dai_list_show(struct seq_file *m, void *v) |
@@ -215,32 +213,17 @@ DEFINE_SHOW_ATTRIBUTE(component_list); | |||
215 | 213 | ||
216 | static void soc_init_card_debugfs(struct snd_soc_card *card) | 214 | static void soc_init_card_debugfs(struct snd_soc_card *card) |
217 | { | 215 | { |
218 | if (!snd_soc_debugfs_root) | ||
219 | return; | ||
220 | |||
221 | card->debugfs_card_root = debugfs_create_dir(card->name, | 216 | card->debugfs_card_root = debugfs_create_dir(card->name, |
222 | snd_soc_debugfs_root); | 217 | snd_soc_debugfs_root); |
223 | if (IS_ERR(card->debugfs_card_root)) { | ||
224 | dev_warn(card->dev, | ||
225 | "ASoC: Failed to create card debugfs directory: %ld\n", | ||
226 | PTR_ERR(card->debugfs_card_root)); | ||
227 | card->debugfs_card_root = NULL; | ||
228 | return; | ||
229 | } | ||
230 | 218 | ||
231 | card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, | 219 | debugfs_create_u32("dapm_pop_time", 0644, card->debugfs_card_root, |
232 | card->debugfs_card_root, | 220 | &card->pop_time); |
233 | &card->pop_time); | 221 | |
234 | if (IS_ERR(card->debugfs_pop_time)) | 222 | snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); |
235 | dev_warn(card->dev, | ||
236 | "ASoC: Failed to create pop time debugfs file: %ld\n", | ||
237 | PTR_ERR(card->debugfs_pop_time)); | ||
238 | } | 223 | } |
239 | 224 | ||
240 | static void soc_cleanup_card_debugfs(struct snd_soc_card *card) | 225 | static void soc_cleanup_card_debugfs(struct snd_soc_card *card) |
241 | { | 226 | { |
242 | if (!card->debugfs_card_root) | ||
243 | return; | ||
244 | debugfs_remove_recursive(card->debugfs_card_root); | 227 | debugfs_remove_recursive(card->debugfs_card_root); |
245 | card->debugfs_card_root = NULL; | 228 | card->debugfs_card_root = NULL; |
246 | } | 229 | } |
@@ -248,19 +231,12 @@ static void soc_cleanup_card_debugfs(struct snd_soc_card *card) | |||
248 | static void snd_soc_debugfs_init(void) | 231 | static void snd_soc_debugfs_init(void) |
249 | { | 232 | { |
250 | snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL); | 233 | snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL); |
251 | if (IS_ERR_OR_NULL(snd_soc_debugfs_root)) { | ||
252 | pr_warn("ASoC: Failed to create debugfs directory\n"); | ||
253 | snd_soc_debugfs_root = NULL; | ||
254 | return; | ||
255 | } | ||
256 | 234 | ||
257 | if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL, | 235 | debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL, |
258 | &dai_list_fops)) | 236 | &dai_list_fops); |
259 | pr_warn("ASoC: Failed to create DAI list debugfs file\n"); | ||
260 | 237 | ||
261 | if (!debugfs_create_file("components", 0444, snd_soc_debugfs_root, NULL, | 238 | debugfs_create_file("components", 0444, snd_soc_debugfs_root, NULL, |
262 | &component_list_fops)) | 239 | &component_list_fops); |
263 | pr_warn("ASoC: Failed to create component list debugfs file\n"); | ||
264 | } | 240 | } |
265 | 241 | ||
266 | static void snd_soc_debugfs_exit(void) | 242 | static void snd_soc_debugfs_exit(void) |
@@ -302,7 +278,6 @@ static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd, | |||
302 | struct snd_soc_component *component) | 278 | struct snd_soc_component *component) |
303 | { | 279 | { |
304 | struct snd_soc_rtdcom_list *rtdcom; | 280 | struct snd_soc_rtdcom_list *rtdcom; |
305 | struct snd_soc_rtdcom_list *new_rtdcom; | ||
306 | 281 | ||
307 | for_each_rtdcom(rtd, rtdcom) { | 282 | for_each_rtdcom(rtd, rtdcom) { |
308 | /* already connected */ | 283 | /* already connected */ |
@@ -310,14 +285,14 @@ static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd, | |||
310 | return 0; | 285 | return 0; |
311 | } | 286 | } |
312 | 287 | ||
313 | new_rtdcom = kmalloc(sizeof(*new_rtdcom), GFP_KERNEL); | 288 | rtdcom = kmalloc(sizeof(*rtdcom), GFP_KERNEL); |
314 | if (!new_rtdcom) | 289 | if (!rtdcom) |
315 | return -ENOMEM; | 290 | return -ENOMEM; |
316 | 291 | ||
317 | new_rtdcom->component = component; | 292 | rtdcom->component = component; |
318 | INIT_LIST_HEAD(&new_rtdcom->list); | 293 | INIT_LIST_HEAD(&rtdcom->list); |
319 | 294 | ||
320 | list_add_tail(&new_rtdcom->list, &rtd->component_list); | 295 | list_add_tail(&rtdcom->list, &rtd->component_list); |
321 | 296 | ||
322 | return 0; | 297 | return 0; |
323 | } | 298 | } |
@@ -340,6 +315,14 @@ struct snd_soc_component *snd_soc_rtdcom_lookup(struct snd_soc_pcm_runtime *rtd, | |||
340 | if (!driver_name) | 315 | if (!driver_name) |
341 | return NULL; | 316 | return NULL; |
342 | 317 | ||
318 | /* | ||
319 | * NOTE | ||
320 | * | ||
321 | * snd_soc_rtdcom_lookup() will find component from rtd by using | ||
322 | * specified driver name. | ||
323 | * But, if many components which have same driver name are connected | ||
324 | * to 1 rtd, this function will return 1st found component. | ||
325 | */ | ||
343 | for_each_rtdcom(rtd, rtdcom) { | 326 | for_each_rtdcom(rtd, rtdcom) { |
344 | const char *component_name = rtdcom->component->driver->name; | 327 | const char *component_name = rtdcom->component->driver->name; |
345 | 328 | ||
@@ -408,6 +391,7 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd) | |||
408 | static void soc_add_pcm_runtime(struct snd_soc_card *card, | 391 | static void soc_add_pcm_runtime(struct snd_soc_card *card, |
409 | struct snd_soc_pcm_runtime *rtd) | 392 | struct snd_soc_pcm_runtime *rtd) |
410 | { | 393 | { |
394 | /* see for_each_card_rtds */ | ||
411 | list_add_tail(&rtd->list, &card->rtd_list); | 395 | list_add_tail(&rtd->list, &card->rtd_list); |
412 | rtd->num = card->num_rtd; | 396 | rtd->num = card->num_rtd; |
413 | card->num_rtd++; | 397 | card->num_rtd++; |
@@ -447,16 +431,6 @@ static void snd_soc_flush_all_delayed_work(struct snd_soc_card *card) | |||
447 | flush_delayed_work(&rtd->delayed_work); | 431 | flush_delayed_work(&rtd->delayed_work); |
448 | } | 432 | } |
449 | 433 | ||
450 | static void codec2codec_close_delayed_work(struct work_struct *work) | ||
451 | { | ||
452 | /* | ||
453 | * Currently nothing to do for c2c links | ||
454 | * Since c2c links are internal nodes in the DAPM graph and | ||
455 | * don't interface with the outside world or application layer | ||
456 | * we don't have to do any special handling on close. | ||
457 | */ | ||
458 | } | ||
459 | |||
460 | #ifdef CONFIG_PM_SLEEP | 434 | #ifdef CONFIG_PM_SLEEP |
461 | /* powers down audio subsystem for suspend */ | 435 | /* powers down audio subsystem for suspend */ |
462 | int snd_soc_suspend(struct device *dev) | 436 | int snd_soc_suspend(struct device *dev) |
@@ -487,10 +461,9 @@ int snd_soc_suspend(struct device *dev) | |||
487 | continue; | 461 | continue; |
488 | 462 | ||
489 | for_each_rtd_codec_dai(rtd, i, dai) { | 463 | for_each_rtd_codec_dai(rtd, i, dai) { |
490 | struct snd_soc_dai_driver *drv = dai->driver; | 464 | if (dai->playback_active) |
491 | 465 | snd_soc_dai_digital_mute(dai, 1, | |
492 | if (drv->ops->digital_mute && dai->playback_active) | 466 | SNDRV_PCM_STREAM_PLAYBACK); |
493 | drv->ops->digital_mute(dai, 1); | ||
494 | } | 467 | } |
495 | } | 468 | } |
496 | 469 | ||
@@ -511,8 +484,8 @@ int snd_soc_suspend(struct device *dev) | |||
511 | if (rtd->dai_link->ignore_suspend) | 484 | if (rtd->dai_link->ignore_suspend) |
512 | continue; | 485 | continue; |
513 | 486 | ||
514 | if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control) | 487 | if (!cpu_dai->driver->bus_control) |
515 | cpu_dai->driver->suspend(cpu_dai); | 488 | snd_soc_dai_suspend(cpu_dai); |
516 | } | 489 | } |
517 | 490 | ||
518 | /* close any waiting streams */ | 491 | /* close any waiting streams */ |
@@ -545,7 +518,7 @@ int snd_soc_suspend(struct device *dev) | |||
545 | * If there are paths active then the COMPONENT will be held | 518 | * If there are paths active then the COMPONENT will be held |
546 | * with bias _ON and should not be suspended. | 519 | * with bias _ON and should not be suspended. |
547 | */ | 520 | */ |
548 | if (!component->suspended) { | 521 | if (!snd_soc_component_is_suspended(component)) { |
549 | switch (snd_soc_dapm_get_bias_level(dapm)) { | 522 | switch (snd_soc_dapm_get_bias_level(dapm)) { |
550 | case SND_SOC_BIAS_STANDBY: | 523 | case SND_SOC_BIAS_STANDBY: |
551 | /* | 524 | /* |
@@ -562,9 +535,7 @@ int snd_soc_suspend(struct device *dev) | |||
562 | /* fall through */ | 535 | /* fall through */ |
563 | 536 | ||
564 | case SND_SOC_BIAS_OFF: | 537 | case SND_SOC_BIAS_OFF: |
565 | if (component->driver->suspend) | 538 | snd_soc_component_suspend(component); |
566 | component->driver->suspend(component); | ||
567 | component->suspended = 1; | ||
568 | if (component->regmap) | 539 | if (component->regmap) |
569 | regcache_mark_dirty(component->regmap); | 540 | regcache_mark_dirty(component->regmap); |
570 | /* deactivate pins to sleep state */ | 541 | /* deactivate pins to sleep state */ |
@@ -584,8 +555,8 @@ int snd_soc_suspend(struct device *dev) | |||
584 | if (rtd->dai_link->ignore_suspend) | 555 | if (rtd->dai_link->ignore_suspend) |
585 | continue; | 556 | continue; |
586 | 557 | ||
587 | if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control) | 558 | if (cpu_dai->driver->bus_control) |
588 | cpu_dai->driver->suspend(cpu_dai); | 559 | snd_soc_dai_suspend(cpu_dai); |
589 | 560 | ||
590 | /* deactivate pins to sleep state */ | 561 | /* deactivate pins to sleep state */ |
591 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 562 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
@@ -631,16 +602,13 @@ static void soc_resume_deferred(struct work_struct *work) | |||
631 | if (rtd->dai_link->ignore_suspend) | 602 | if (rtd->dai_link->ignore_suspend) |
632 | continue; | 603 | continue; |
633 | 604 | ||
634 | if (cpu_dai->driver->resume && cpu_dai->driver->bus_control) | 605 | if (cpu_dai->driver->bus_control) |
635 | cpu_dai->driver->resume(cpu_dai); | 606 | snd_soc_dai_resume(cpu_dai); |
636 | } | 607 | } |
637 | 608 | ||
638 | for_each_card_components(card, component) { | 609 | for_each_card_components(card, component) { |
639 | if (component->suspended) { | 610 | if (snd_soc_component_is_suspended(component)) |
640 | if (component->driver->resume) | 611 | snd_soc_component_resume(component); |
641 | component->driver->resume(component); | ||
642 | component->suspended = 0; | ||
643 | } | ||
644 | } | 612 | } |
645 | 613 | ||
646 | for_each_card_rtds(card, rtd) { | 614 | for_each_card_rtds(card, rtd) { |
@@ -665,10 +633,9 @@ static void soc_resume_deferred(struct work_struct *work) | |||
665 | continue; | 633 | continue; |
666 | 634 | ||
667 | for_each_rtd_codec_dai(rtd, i, dai) { | 635 | for_each_rtd_codec_dai(rtd, i, dai) { |
668 | struct snd_soc_dai_driver *drv = dai->driver; | 636 | if (dai->playback_active) |
669 | 637 | snd_soc_dai_digital_mute(dai, 0, | |
670 | if (drv->ops->digital_mute && dai->playback_active) | 638 | SNDRV_PCM_STREAM_PLAYBACK); |
671 | drv->ops->digital_mute(dai, 0); | ||
672 | } | 639 | } |
673 | } | 640 | } |
674 | 641 | ||
@@ -678,8 +645,8 @@ static void soc_resume_deferred(struct work_struct *work) | |||
678 | if (rtd->dai_link->ignore_suspend) | 645 | if (rtd->dai_link->ignore_suspend) |
679 | continue; | 646 | continue; |
680 | 647 | ||
681 | if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control) | 648 | if (!cpu_dai->driver->bus_control) |
682 | cpu_dai->driver->resume(cpu_dai); | 649 | snd_soc_dai_resume(cpu_dai); |
683 | } | 650 | } |
684 | 651 | ||
685 | if (card->resume_post) | 652 | if (card->resume_post) |
@@ -744,9 +711,18 @@ int snd_soc_resume(struct device *dev) | |||
744 | return 0; | 711 | return 0; |
745 | } | 712 | } |
746 | EXPORT_SYMBOL_GPL(snd_soc_resume); | 713 | EXPORT_SYMBOL_GPL(snd_soc_resume); |
714 | |||
715 | static void soc_resume_init(struct snd_soc_card *card) | ||
716 | { | ||
717 | /* deferred resume work */ | ||
718 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); | ||
719 | } | ||
747 | #else | 720 | #else |
748 | #define snd_soc_suspend NULL | 721 | #define snd_soc_suspend NULL |
749 | #define snd_soc_resume NULL | 722 | #define snd_soc_resume NULL |
723 | static inline void soc_resume_init(struct snd_soc_card *card) | ||
724 | { | ||
725 | } | ||
750 | #endif | 726 | #endif |
751 | 727 | ||
752 | static const struct snd_soc_dai_ops null_dai_ops = { | 728 | static const struct snd_soc_dai_ops null_dai_ops = { |
@@ -861,11 +837,11 @@ struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card, | |||
861 | int id, const char *name, | 837 | int id, const char *name, |
862 | const char *stream_name) | 838 | const char *stream_name) |
863 | { | 839 | { |
864 | struct snd_soc_dai_link *link, *_link; | 840 | struct snd_soc_dai_link *link; |
865 | 841 | ||
866 | lockdep_assert_held(&client_mutex); | 842 | lockdep_assert_held(&client_mutex); |
867 | 843 | ||
868 | for_each_card_links_safe(card, link, _link) { | 844 | for_each_card_links(card, link) { |
869 | if (link->id != id) | 845 | if (link->id != id) |
870 | continue; | 846 | continue; |
871 | 847 | ||
@@ -962,15 +938,51 @@ _err_defer: | |||
962 | return -EPROBE_DEFER; | 938 | return -EPROBE_DEFER; |
963 | } | 939 | } |
964 | 940 | ||
941 | static void soc_set_of_name_prefix(struct snd_soc_component *component) | ||
942 | { | ||
943 | struct device_node *of_node = soc_component_to_node(component); | ||
944 | const char *str; | ||
945 | int ret; | ||
946 | |||
947 | ret = of_property_read_string(of_node, "sound-name-prefix", &str); | ||
948 | if (!ret) | ||
949 | component->name_prefix = str; | ||
950 | } | ||
951 | |||
952 | static void soc_set_name_prefix(struct snd_soc_card *card, | ||
953 | struct snd_soc_component *component) | ||
954 | { | ||
955 | int i; | ||
956 | |||
957 | for (i = 0; i < card->num_configs && card->codec_conf; i++) { | ||
958 | struct snd_soc_codec_conf *map = &card->codec_conf[i]; | ||
959 | struct device_node *of_node = soc_component_to_node(component); | ||
960 | |||
961 | if (map->of_node && of_node != map->of_node) | ||
962 | continue; | ||
963 | if (map->dev_name && strcmp(component->name, map->dev_name)) | ||
964 | continue; | ||
965 | component->name_prefix = map->name_prefix; | ||
966 | return; | ||
967 | } | ||
968 | |||
969 | /* | ||
970 | * If there is no configuration table or no match in the table, | ||
971 | * check if a prefix is provided in the node | ||
972 | */ | ||
973 | soc_set_of_name_prefix(component); | ||
974 | } | ||
975 | |||
965 | static void soc_cleanup_component(struct snd_soc_component *component) | 976 | static void soc_cleanup_component(struct snd_soc_component *component) |
966 | { | 977 | { |
978 | /* For framework level robustness */ | ||
967 | snd_soc_component_set_jack(component, NULL, NULL); | 979 | snd_soc_component_set_jack(component, NULL, NULL); |
980 | |||
968 | list_del(&component->card_list); | 981 | list_del(&component->card_list); |
969 | snd_soc_dapm_free(snd_soc_component_get_dapm(component)); | 982 | snd_soc_dapm_free(snd_soc_component_get_dapm(component)); |
970 | soc_cleanup_component_debugfs(component); | 983 | soc_cleanup_component_debugfs(component); |
971 | component->card = NULL; | 984 | component->card = NULL; |
972 | if (!component->driver->module_get_upon_open) | 985 | snd_soc_component_module_put_when_remove(component); |
973 | module_put(component->dev->driver->owner); | ||
974 | } | 986 | } |
975 | 987 | ||
976 | static void soc_remove_component(struct snd_soc_component *component) | 988 | static void soc_remove_component(struct snd_soc_component *component) |
@@ -978,12 +990,105 @@ static void soc_remove_component(struct snd_soc_component *component) | |||
978 | if (!component->card) | 990 | if (!component->card) |
979 | return; | 991 | return; |
980 | 992 | ||
981 | if (component->driver->remove) | 993 | snd_soc_component_remove(component); |
982 | component->driver->remove(component); | ||
983 | 994 | ||
984 | soc_cleanup_component(component); | 995 | soc_cleanup_component(component); |
985 | } | 996 | } |
986 | 997 | ||
998 | static int soc_probe_component(struct snd_soc_card *card, | ||
999 | struct snd_soc_component *component) | ||
1000 | { | ||
1001 | struct snd_soc_dapm_context *dapm = | ||
1002 | snd_soc_component_get_dapm(component); | ||
1003 | struct snd_soc_dai *dai; | ||
1004 | int ret; | ||
1005 | |||
1006 | if (!strcmp(component->name, "snd-soc-dummy")) | ||
1007 | return 0; | ||
1008 | |||
1009 | if (component->card) { | ||
1010 | if (component->card != card) { | ||
1011 | dev_err(component->dev, | ||
1012 | "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n", | ||
1013 | card->name, component->card->name); | ||
1014 | return -ENODEV; | ||
1015 | } | ||
1016 | return 0; | ||
1017 | } | ||
1018 | |||
1019 | ret = snd_soc_component_module_get_when_probe(component); | ||
1020 | if (ret < 0) | ||
1021 | return ret; | ||
1022 | |||
1023 | component->card = card; | ||
1024 | soc_set_name_prefix(card, component); | ||
1025 | |||
1026 | soc_init_component_debugfs(component); | ||
1027 | |||
1028 | snd_soc_dapm_init(dapm, card, component); | ||
1029 | |||
1030 | ret = snd_soc_dapm_new_controls(dapm, | ||
1031 | component->driver->dapm_widgets, | ||
1032 | component->driver->num_dapm_widgets); | ||
1033 | |||
1034 | if (ret != 0) { | ||
1035 | dev_err(component->dev, | ||
1036 | "Failed to create new controls %d\n", ret); | ||
1037 | goto err_probe; | ||
1038 | } | ||
1039 | |||
1040 | for_each_component_dais(component, dai) { | ||
1041 | ret = snd_soc_dapm_new_dai_widgets(dapm, dai); | ||
1042 | if (ret != 0) { | ||
1043 | dev_err(component->dev, | ||
1044 | "Failed to create DAI widgets %d\n", ret); | ||
1045 | goto err_probe; | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1049 | ret = snd_soc_component_probe(component); | ||
1050 | if (ret < 0) { | ||
1051 | dev_err(component->dev, | ||
1052 | "ASoC: failed to probe component %d\n", ret); | ||
1053 | goto err_probe; | ||
1054 | } | ||
1055 | WARN(dapm->idle_bias_off && | ||
1056 | dapm->bias_level != SND_SOC_BIAS_OFF, | ||
1057 | "codec %s can not start from non-off bias with idle_bias_off==1\n", | ||
1058 | component->name); | ||
1059 | |||
1060 | /* machine specific init */ | ||
1061 | if (component->init) { | ||
1062 | ret = component->init(component); | ||
1063 | if (ret < 0) { | ||
1064 | dev_err(component->dev, | ||
1065 | "Failed to do machine specific init %d\n", ret); | ||
1066 | goto err_probe; | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | ret = snd_soc_add_component_controls(component, | ||
1071 | component->driver->controls, | ||
1072 | component->driver->num_controls); | ||
1073 | if (ret < 0) | ||
1074 | goto err_probe; | ||
1075 | |||
1076 | ret = snd_soc_dapm_add_routes(dapm, | ||
1077 | component->driver->dapm_routes, | ||
1078 | component->driver->num_dapm_routes); | ||
1079 | if (ret < 0) | ||
1080 | goto err_probe; | ||
1081 | |||
1082 | /* see for_each_card_components */ | ||
1083 | list_add(&component->card_list, &card->component_dev_list); | ||
1084 | |||
1085 | err_probe: | ||
1086 | if (ret < 0) | ||
1087 | soc_cleanup_component(component); | ||
1088 | |||
1089 | return ret; | ||
1090 | } | ||
1091 | |||
987 | static void soc_remove_dai(struct snd_soc_dai *dai, int order) | 1092 | static void soc_remove_dai(struct snd_soc_dai *dai, int order) |
988 | { | 1093 | { |
989 | int err; | 1094 | int err; |
@@ -992,65 +1097,141 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order) | |||
992 | dai->driver->remove_order != order) | 1097 | dai->driver->remove_order != order) |
993 | return; | 1098 | return; |
994 | 1099 | ||
995 | if (dai->driver->remove) { | 1100 | err = snd_soc_dai_remove(dai); |
996 | err = dai->driver->remove(dai); | 1101 | if (err < 0) |
997 | if (err < 0) | 1102 | dev_err(dai->dev, |
998 | dev_err(dai->dev, | 1103 | "ASoC: failed to remove %s: %d\n", |
999 | "ASoC: failed to remove %s: %d\n", | 1104 | dai->name, err); |
1000 | dai->name, err); | 1105 | |
1001 | } | ||
1002 | dai->probed = 0; | 1106 | dai->probed = 0; |
1003 | } | 1107 | } |
1004 | 1108 | ||
1005 | static void soc_remove_link_dais(struct snd_soc_card *card, | 1109 | static int soc_probe_dai(struct snd_soc_dai *dai, int order) |
1006 | struct snd_soc_pcm_runtime *rtd, int order) | 1110 | { |
1111 | int ret; | ||
1112 | |||
1113 | if (dai->probed || | ||
1114 | dai->driver->probe_order != order) | ||
1115 | return 0; | ||
1116 | |||
1117 | ret = snd_soc_dai_probe(dai); | ||
1118 | if (ret < 0) { | ||
1119 | dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n", | ||
1120 | dai->name, ret); | ||
1121 | return ret; | ||
1122 | } | ||
1123 | |||
1124 | dai->probed = 1; | ||
1125 | |||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | static void soc_rtd_free(struct snd_soc_pcm_runtime *rtd); /* remove me */ | ||
1130 | static void soc_remove_link_dais(struct snd_soc_card *card) | ||
1007 | { | 1131 | { |
1008 | int i; | 1132 | int i; |
1009 | struct snd_soc_dai *codec_dai; | 1133 | struct snd_soc_dai *codec_dai; |
1134 | struct snd_soc_pcm_runtime *rtd; | ||
1135 | int order; | ||
1010 | 1136 | ||
1011 | /* unregister the rtd device */ | 1137 | for_each_comp_order(order) { |
1012 | if (rtd->dev_registered) { | 1138 | for_each_card_rtds(card, rtd) { |
1013 | device_unregister(rtd->dev); | 1139 | |
1014 | rtd->dev_registered = 0; | 1140 | /* finalize rtd device */ |
1141 | soc_rtd_free(rtd); | ||
1142 | |||
1143 | /* remove the CODEC DAI */ | ||
1144 | for_each_rtd_codec_dai(rtd, i, codec_dai) | ||
1145 | soc_remove_dai(codec_dai, order); | ||
1146 | |||
1147 | soc_remove_dai(rtd->cpu_dai, order); | ||
1148 | } | ||
1015 | } | 1149 | } |
1150 | } | ||
1016 | 1151 | ||
1017 | /* remove the CODEC DAI */ | 1152 | static int soc_probe_link_dais(struct snd_soc_card *card) |
1018 | for_each_rtd_codec_dai(rtd, i, codec_dai) | 1153 | { |
1019 | soc_remove_dai(codec_dai, order); | 1154 | struct snd_soc_dai *codec_dai; |
1155 | struct snd_soc_pcm_runtime *rtd; | ||
1156 | int i, order, ret; | ||
1020 | 1157 | ||
1021 | soc_remove_dai(rtd->cpu_dai, order); | 1158 | for_each_comp_order(order) { |
1159 | for_each_card_rtds(card, rtd) { | ||
1160 | |||
1161 | dev_dbg(card->dev, | ||
1162 | "ASoC: probe %s dai link %d late %d\n", | ||
1163 | card->name, rtd->num, order); | ||
1164 | |||
1165 | ret = soc_probe_dai(rtd->cpu_dai, order); | ||
1166 | if (ret) | ||
1167 | return ret; | ||
1168 | |||
1169 | /* probe the CODEC DAI */ | ||
1170 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | ||
1171 | ret = soc_probe_dai(codec_dai, order); | ||
1172 | if (ret) | ||
1173 | return ret; | ||
1174 | } | ||
1175 | } | ||
1176 | } | ||
1177 | |||
1178 | return 0; | ||
1022 | } | 1179 | } |
1023 | 1180 | ||
1024 | static void soc_remove_link_components(struct snd_soc_card *card, | 1181 | static void soc_remove_link_components(struct snd_soc_card *card) |
1025 | struct snd_soc_pcm_runtime *rtd, int order) | ||
1026 | { | 1182 | { |
1027 | struct snd_soc_component *component; | 1183 | struct snd_soc_component *component; |
1184 | struct snd_soc_pcm_runtime *rtd; | ||
1028 | struct snd_soc_rtdcom_list *rtdcom; | 1185 | struct snd_soc_rtdcom_list *rtdcom; |
1186 | int order; | ||
1029 | 1187 | ||
1030 | for_each_rtdcom(rtd, rtdcom) { | 1188 | for_each_comp_order(order) { |
1031 | component = rtdcom->component; | 1189 | for_each_card_rtds(card, rtd) { |
1190 | for_each_rtdcom(rtd, rtdcom) { | ||
1191 | component = rtdcom->component; | ||
1192 | |||
1193 | if (component->driver->remove_order != order) | ||
1194 | continue; | ||
1032 | 1195 | ||
1033 | if (component->driver->remove_order == order) | 1196 | soc_remove_component(component); |
1034 | soc_remove_component(component); | 1197 | } |
1198 | } | ||
1035 | } | 1199 | } |
1036 | } | 1200 | } |
1037 | 1201 | ||
1038 | static void soc_remove_dai_links(struct snd_soc_card *card) | 1202 | static int soc_probe_link_components(struct snd_soc_card *card) |
1039 | { | 1203 | { |
1040 | int order; | 1204 | struct snd_soc_component *component; |
1041 | struct snd_soc_pcm_runtime *rtd; | 1205 | struct snd_soc_pcm_runtime *rtd; |
1042 | struct snd_soc_dai_link *link, *_link; | 1206 | struct snd_soc_rtdcom_list *rtdcom; |
1207 | int ret, order; | ||
1043 | 1208 | ||
1044 | for_each_comp_order(order) { | 1209 | for_each_comp_order(order) { |
1045 | for_each_card_rtds(card, rtd) | 1210 | for_each_card_rtds(card, rtd) { |
1046 | soc_remove_link_dais(card, rtd, order); | 1211 | for_each_rtdcom(rtd, rtdcom) { |
1047 | } | 1212 | component = rtdcom->component; |
1048 | 1213 | ||
1049 | for_each_comp_order(order) { | 1214 | if (component->driver->probe_order != order) |
1050 | for_each_card_rtds(card, rtd) | 1215 | continue; |
1051 | soc_remove_link_components(card, rtd, order); | 1216 | |
1217 | ret = soc_probe_component(card, component); | ||
1218 | if (ret < 0) | ||
1219 | return ret; | ||
1220 | } | ||
1221 | } | ||
1052 | } | 1222 | } |
1053 | 1223 | ||
1224 | return 0; | ||
1225 | } | ||
1226 | |||
1227 | static void soc_remove_dai_links(struct snd_soc_card *card) | ||
1228 | { | ||
1229 | struct snd_soc_dai_link *link, *_link; | ||
1230 | |||
1231 | soc_remove_link_dais(card); | ||
1232 | |||
1233 | soc_remove_link_components(card); | ||
1234 | |||
1054 | for_each_card_links_safe(card, link, _link) { | 1235 | for_each_card_links_safe(card, link, _link) { |
1055 | if (link->dobj.type == SND_SOC_DOBJ_DAI_LINK) | 1236 | if (link->dobj.type == SND_SOC_DOBJ_DAI_LINK) |
1056 | dev_warn(card->dev, "Topology forgot to remove link %s?\n", | 1237 | dev_warn(card->dev, "Topology forgot to remove link %s?\n", |
@@ -1197,6 +1378,7 @@ int snd_soc_add_dai_link(struct snd_soc_card *card, | |||
1197 | if (dai_link->dobj.type && card->add_dai_link) | 1378 | if (dai_link->dobj.type && card->add_dai_link) |
1198 | card->add_dai_link(card, dai_link); | 1379 | card->add_dai_link(card, dai_link); |
1199 | 1380 | ||
1381 | /* see for_each_card_links */ | ||
1200 | list_add_tail(&dai_link->list, &card->dai_link_list); | 1382 | list_add_tail(&dai_link->list, &card->dai_link_list); |
1201 | 1383 | ||
1202 | return 0; | 1384 | return 0; |
@@ -1216,8 +1398,6 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_link); | |||
1216 | void snd_soc_remove_dai_link(struct snd_soc_card *card, | 1398 | void snd_soc_remove_dai_link(struct snd_soc_card *card, |
1217 | struct snd_soc_dai_link *dai_link) | 1399 | struct snd_soc_dai_link *dai_link) |
1218 | { | 1400 | { |
1219 | struct snd_soc_dai_link *link, *_link; | ||
1220 | |||
1221 | if (dai_link->dobj.type | 1401 | if (dai_link->dobj.type |
1222 | && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) { | 1402 | && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) { |
1223 | dev_err(card->dev, "Invalid dai link type %d\n", | 1403 | dev_err(card->dev, "Invalid dai link type %d\n", |
@@ -1233,155 +1413,25 @@ void snd_soc_remove_dai_link(struct snd_soc_card *card, | |||
1233 | if (dai_link->dobj.type && card->remove_dai_link) | 1413 | if (dai_link->dobj.type && card->remove_dai_link) |
1234 | card->remove_dai_link(card, dai_link); | 1414 | card->remove_dai_link(card, dai_link); |
1235 | 1415 | ||
1236 | for_each_card_links_safe(card, link, _link) { | 1416 | list_del(&dai_link->list); |
1237 | if (link == dai_link) { | ||
1238 | list_del(&link->list); | ||
1239 | return; | ||
1240 | } | ||
1241 | } | ||
1242 | } | 1417 | } |
1243 | EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link); | 1418 | EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link); |
1244 | 1419 | ||
1245 | static void soc_set_of_name_prefix(struct snd_soc_component *component) | 1420 | static void soc_rtd_free(struct snd_soc_pcm_runtime *rtd) |
1246 | { | 1421 | { |
1247 | struct device_node *component_of_node = soc_component_to_node(component); | 1422 | if (rtd->dev_registered) { |
1248 | const char *str; | 1423 | /* we don't need to call kfree() for rtd->dev */ |
1249 | int ret; | 1424 | device_unregister(rtd->dev); |
1250 | 1425 | rtd->dev_registered = 0; | |
1251 | ret = of_property_read_string(component_of_node, "sound-name-prefix", | ||
1252 | &str); | ||
1253 | if (!ret) | ||
1254 | component->name_prefix = str; | ||
1255 | } | ||
1256 | |||
1257 | static void soc_set_name_prefix(struct snd_soc_card *card, | ||
1258 | struct snd_soc_component *component) | ||
1259 | { | ||
1260 | int i; | ||
1261 | |||
1262 | for (i = 0; i < card->num_configs && card->codec_conf; i++) { | ||
1263 | struct snd_soc_codec_conf *map = &card->codec_conf[i]; | ||
1264 | struct device_node *component_of_node = soc_component_to_node(component); | ||
1265 | |||
1266 | if (map->of_node && component_of_node != map->of_node) | ||
1267 | continue; | ||
1268 | if (map->dev_name && strcmp(component->name, map->dev_name)) | ||
1269 | continue; | ||
1270 | component->name_prefix = map->name_prefix; | ||
1271 | return; | ||
1272 | } | ||
1273 | |||
1274 | /* | ||
1275 | * If there is no configuration table or no match in the table, | ||
1276 | * check if a prefix is provided in the node | ||
1277 | */ | ||
1278 | soc_set_of_name_prefix(component); | ||
1279 | } | ||
1280 | |||
1281 | static int soc_probe_component(struct snd_soc_card *card, | ||
1282 | struct snd_soc_component *component) | ||
1283 | { | ||
1284 | struct snd_soc_dapm_context *dapm = | ||
1285 | snd_soc_component_get_dapm(component); | ||
1286 | struct snd_soc_dai *dai; | ||
1287 | int ret; | ||
1288 | |||
1289 | if (!strcmp(component->name, "snd-soc-dummy")) | ||
1290 | return 0; | ||
1291 | |||
1292 | if (component->card) { | ||
1293 | if (component->card != card) { | ||
1294 | dev_err(component->dev, | ||
1295 | "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n", | ||
1296 | card->name, component->card->name); | ||
1297 | return -ENODEV; | ||
1298 | } | ||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | if (!component->driver->module_get_upon_open && | ||
1303 | !try_module_get(component->dev->driver->owner)) | ||
1304 | return -ENODEV; | ||
1305 | |||
1306 | component->card = card; | ||
1307 | dapm->card = card; | ||
1308 | INIT_LIST_HEAD(&component->card_list); | ||
1309 | INIT_LIST_HEAD(&dapm->list); | ||
1310 | soc_set_name_prefix(card, component); | ||
1311 | |||
1312 | soc_init_component_debugfs(component); | ||
1313 | |||
1314 | if (component->driver->dapm_widgets) { | ||
1315 | ret = snd_soc_dapm_new_controls(dapm, | ||
1316 | component->driver->dapm_widgets, | ||
1317 | component->driver->num_dapm_widgets); | ||
1318 | |||
1319 | if (ret != 0) { | ||
1320 | dev_err(component->dev, | ||
1321 | "Failed to create new controls %d\n", ret); | ||
1322 | goto err_probe; | ||
1323 | } | ||
1324 | } | ||
1325 | |||
1326 | for_each_component_dais(component, dai) { | ||
1327 | ret = snd_soc_dapm_new_dai_widgets(dapm, dai); | ||
1328 | if (ret != 0) { | ||
1329 | dev_err(component->dev, | ||
1330 | "Failed to create DAI widgets %d\n", ret); | ||
1331 | goto err_probe; | ||
1332 | } | ||
1333 | } | ||
1334 | |||
1335 | if (component->driver->probe) { | ||
1336 | ret = component->driver->probe(component); | ||
1337 | if (ret < 0) { | ||
1338 | dev_err(component->dev, | ||
1339 | "ASoC: failed to probe component %d\n", ret); | ||
1340 | goto err_probe; | ||
1341 | } | ||
1342 | } | ||
1343 | WARN(dapm->idle_bias_off && | ||
1344 | dapm->bias_level != SND_SOC_BIAS_OFF, | ||
1345 | "codec %s can not start from non-off bias with idle_bias_off==1\n", | ||
1346 | component->name); | ||
1347 | |||
1348 | /* machine specific init */ | ||
1349 | if (component->init) { | ||
1350 | ret = component->init(component); | ||
1351 | if (ret < 0) { | ||
1352 | dev_err(component->dev, | ||
1353 | "Failed to do machine specific init %d\n", ret); | ||
1354 | goto err_probe; | ||
1355 | } | ||
1356 | } | 1426 | } |
1357 | |||
1358 | if (component->driver->controls) | ||
1359 | snd_soc_add_component_controls(component, | ||
1360 | component->driver->controls, | ||
1361 | component->driver->num_controls); | ||
1362 | if (component->driver->dapm_routes) | ||
1363 | snd_soc_dapm_add_routes(dapm, | ||
1364 | component->driver->dapm_routes, | ||
1365 | component->driver->num_dapm_routes); | ||
1366 | |||
1367 | list_add(&dapm->list, &card->dapm_list); | ||
1368 | /* see for_each_card_components */ | ||
1369 | list_add(&component->card_list, &card->component_dev_list); | ||
1370 | |||
1371 | err_probe: | ||
1372 | if (ret < 0) | ||
1373 | soc_cleanup_component(component); | ||
1374 | |||
1375 | return ret; | ||
1376 | } | 1427 | } |
1377 | 1428 | ||
1378 | static void rtd_release(struct device *dev) | 1429 | static void soc_rtd_release(struct device *dev) |
1379 | { | 1430 | { |
1380 | kfree(dev); | 1431 | kfree(dev); |
1381 | } | 1432 | } |
1382 | 1433 | ||
1383 | static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | 1434 | static int soc_rtd_init(struct snd_soc_pcm_runtime *rtd, const char *name) |
1384 | const char *name) | ||
1385 | { | 1435 | { |
1386 | int ret = 0; | 1436 | int ret = 0; |
1387 | 1437 | ||
@@ -1389,18 +1439,16 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | |||
1389 | rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL); | 1439 | rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL); |
1390 | if (!rtd->dev) | 1440 | if (!rtd->dev) |
1391 | return -ENOMEM; | 1441 | return -ENOMEM; |
1392 | device_initialize(rtd->dev); | ||
1393 | rtd->dev->parent = rtd->card->dev; | 1442 | rtd->dev->parent = rtd->card->dev; |
1394 | rtd->dev->release = rtd_release; | 1443 | rtd->dev->release = soc_rtd_release; |
1395 | rtd->dev->groups = soc_dev_attr_groups; | 1444 | rtd->dev->groups = soc_dev_attr_groups; |
1396 | dev_set_name(rtd->dev, "%s", name); | 1445 | dev_set_name(rtd->dev, "%s", name); |
1397 | dev_set_drvdata(rtd->dev, rtd); | 1446 | dev_set_drvdata(rtd->dev, rtd); |
1398 | mutex_init(&rtd->pcm_mutex); | ||
1399 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients); | 1447 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients); |
1400 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients); | 1448 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients); |
1401 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients); | 1449 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients); |
1402 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients); | 1450 | INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients); |
1403 | ret = device_add(rtd->dev); | 1451 | ret = device_register(rtd->dev); |
1404 | if (ret < 0) { | 1452 | if (ret < 0) { |
1405 | /* calling put_device() here to free the rtd->dev */ | 1453 | /* calling put_device() here to free the rtd->dev */ |
1406 | put_device(rtd->dev); | 1454 | put_device(rtd->dev); |
@@ -1412,47 +1460,6 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | |||
1412 | return 0; | 1460 | return 0; |
1413 | } | 1461 | } |
1414 | 1462 | ||
1415 | static int soc_probe_link_components(struct snd_soc_card *card, | ||
1416 | struct snd_soc_pcm_runtime *rtd, int order) | ||
1417 | { | ||
1418 | struct snd_soc_component *component; | ||
1419 | struct snd_soc_rtdcom_list *rtdcom; | ||
1420 | int ret; | ||
1421 | |||
1422 | for_each_rtdcom(rtd, rtdcom) { | ||
1423 | component = rtdcom->component; | ||
1424 | |||
1425 | if (component->driver->probe_order == order) { | ||
1426 | ret = soc_probe_component(card, component); | ||
1427 | if (ret < 0) | ||
1428 | return ret; | ||
1429 | } | ||
1430 | } | ||
1431 | |||
1432 | return 0; | ||
1433 | } | ||
1434 | |||
1435 | static int soc_probe_dai(struct snd_soc_dai *dai, int order) | ||
1436 | { | ||
1437 | if (dai->probed || | ||
1438 | dai->driver->probe_order != order) | ||
1439 | return 0; | ||
1440 | |||
1441 | if (dai->driver->probe) { | ||
1442 | int ret = dai->driver->probe(dai); | ||
1443 | |||
1444 | if (ret < 0) { | ||
1445 | dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n", | ||
1446 | dai->name, ret); | ||
1447 | return ret; | ||
1448 | } | ||
1449 | } | ||
1450 | |||
1451 | dai->probed = 1; | ||
1452 | |||
1453 | return 0; | ||
1454 | } | ||
1455 | |||
1456 | static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais, | 1463 | static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais, |
1457 | struct snd_soc_pcm_runtime *rtd) | 1464 | struct snd_soc_pcm_runtime *rtd) |
1458 | { | 1465 | { |
@@ -1474,37 +1481,18 @@ static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais, | |||
1474 | return 0; | 1481 | return 0; |
1475 | } | 1482 | } |
1476 | 1483 | ||
1477 | static int soc_probe_link_dais(struct snd_soc_card *card, | 1484 | static int soc_link_init(struct snd_soc_card *card, |
1478 | struct snd_soc_pcm_runtime *rtd, int order) | 1485 | struct snd_soc_pcm_runtime *rtd) |
1479 | { | 1486 | { |
1480 | struct snd_soc_dai_link *dai_link = rtd->dai_link; | 1487 | struct snd_soc_dai_link *dai_link = rtd->dai_link; |
1481 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1488 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1482 | struct snd_soc_rtdcom_list *rtdcom; | 1489 | struct snd_soc_rtdcom_list *rtdcom; |
1483 | struct snd_soc_component *component; | 1490 | struct snd_soc_component *component; |
1484 | struct snd_soc_dai *codec_dai; | 1491 | int ret, num; |
1485 | int i, ret, num; | ||
1486 | |||
1487 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", | ||
1488 | card->name, rtd->num, order); | ||
1489 | 1492 | ||
1490 | /* set default power off timeout */ | 1493 | /* set default power off timeout */ |
1491 | rtd->pmdown_time = pmdown_time; | 1494 | rtd->pmdown_time = pmdown_time; |
1492 | 1495 | ||
1493 | ret = soc_probe_dai(cpu_dai, order); | ||
1494 | if (ret) | ||
1495 | return ret; | ||
1496 | |||
1497 | /* probe the CODEC DAI */ | ||
1498 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | ||
1499 | ret = soc_probe_dai(codec_dai, order); | ||
1500 | if (ret) | ||
1501 | return ret; | ||
1502 | } | ||
1503 | |||
1504 | /* complete DAI probe during last probe */ | ||
1505 | if (order != SND_SOC_COMP_ORDER_LAST) | ||
1506 | return 0; | ||
1507 | |||
1508 | /* do machine specific initialization */ | 1496 | /* do machine specific initialization */ |
1509 | if (dai_link->init) { | 1497 | if (dai_link->init) { |
1510 | ret = dai_link->init(rtd); | 1498 | ret = dai_link->init(rtd); |
@@ -1521,15 +1509,12 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1521 | return ret; | 1509 | return ret; |
1522 | } | 1510 | } |
1523 | 1511 | ||
1524 | ret = soc_post_component_init(rtd, dai_link->name); | 1512 | ret = soc_rtd_init(rtd, dai_link->name); |
1525 | if (ret) | 1513 | if (ret) |
1526 | return ret; | 1514 | return ret; |
1527 | 1515 | ||
1528 | #ifdef CONFIG_DEBUG_FS | ||
1529 | /* add DPCM sysfs entries */ | 1516 | /* add DPCM sysfs entries */ |
1530 | if (dai_link->dynamic) | 1517 | soc_dpcm_debugfs_add(rtd); |
1531 | soc_dpcm_debugfs_add(rtd); | ||
1532 | #endif | ||
1533 | 1518 | ||
1534 | num = rtd->num; | 1519 | num = rtd->num; |
1535 | 1520 | ||
@@ -1550,73 +1535,57 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1550 | num = rtd->dai_link->id; | 1535 | num = rtd->dai_link->id; |
1551 | } | 1536 | } |
1552 | 1537 | ||
1553 | if (cpu_dai->driver->compress_new) { | 1538 | /* create compress_device if possible */ |
1554 | /* create compress_device" */ | 1539 | ret = snd_soc_dai_compress_new(cpu_dai, rtd, num); |
1555 | ret = cpu_dai->driver->compress_new(rtd, num); | 1540 | if (ret != -ENOTSUPP) { |
1556 | if (ret < 0) { | 1541 | if (ret < 0) |
1557 | dev_err(card->dev, "ASoC: can't create compress %s\n", | 1542 | dev_err(card->dev, "ASoC: can't create compress %s\n", |
1558 | dai_link->stream_name); | 1543 | dai_link->stream_name); |
1559 | return ret; | 1544 | return ret; |
1560 | } | ||
1561 | } else if (!dai_link->params) { | ||
1562 | /* create the pcm */ | ||
1563 | ret = soc_new_pcm(rtd, num); | ||
1564 | if (ret < 0) { | ||
1565 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", | ||
1566 | dai_link->stream_name, ret); | ||
1567 | return ret; | ||
1568 | } | ||
1569 | ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); | ||
1570 | if (ret < 0) | ||
1571 | return ret; | ||
1572 | ret = soc_link_dai_pcm_new(rtd->codec_dais, | ||
1573 | rtd->num_codecs, rtd); | ||
1574 | if (ret < 0) | ||
1575 | return ret; | ||
1576 | } else { | ||
1577 | INIT_DELAYED_WORK(&rtd->delayed_work, | ||
1578 | codec2codec_close_delayed_work); | ||
1579 | } | 1545 | } |
1580 | 1546 | ||
1581 | return 0; | 1547 | /* create the pcm */ |
1548 | ret = soc_new_pcm(rtd, num); | ||
1549 | if (ret < 0) { | ||
1550 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", | ||
1551 | dai_link->stream_name, ret); | ||
1552 | return ret; | ||
1553 | } | ||
1554 | ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); | ||
1555 | if (ret < 0) | ||
1556 | return ret; | ||
1557 | ret = soc_link_dai_pcm_new(rtd->codec_dais, | ||
1558 | rtd->num_codecs, rtd); | ||
1559 | return ret; | ||
1560 | } | ||
1561 | |||
1562 | static void soc_unbind_aux_dev(struct snd_soc_card *card) | ||
1563 | { | ||
1564 | struct snd_soc_component *component, *_component; | ||
1565 | |||
1566 | for_each_card_auxs_safe(card, component, _component) { | ||
1567 | component->init = NULL; | ||
1568 | list_del(&component->card_aux_list); | ||
1569 | } | ||
1582 | } | 1570 | } |
1583 | 1571 | ||
1584 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) | 1572 | static int soc_bind_aux_dev(struct snd_soc_card *card) |
1585 | { | 1573 | { |
1586 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | ||
1587 | struct snd_soc_component *component; | 1574 | struct snd_soc_component *component; |
1588 | struct snd_soc_dai_link_component dlc; | 1575 | struct snd_soc_aux_dev *aux; |
1576 | int i; | ||
1589 | 1577 | ||
1590 | if (aux_dev->codec_of_node || aux_dev->codec_name) { | 1578 | for_each_card_pre_auxs(card, i, aux) { |
1591 | /* codecs, usually analog devices */ | 1579 | /* codecs, usually analog devices */ |
1592 | dlc.name = aux_dev->codec_name; | 1580 | component = soc_find_component(&aux->dlc); |
1593 | dlc.of_node = aux_dev->codec_of_node; | ||
1594 | component = soc_find_component(&dlc); | ||
1595 | if (!component) { | ||
1596 | if (dlc.of_node) | ||
1597 | dlc.name = of_node_full_name(dlc.of_node); | ||
1598 | goto err_defer; | ||
1599 | } | ||
1600 | } else if (aux_dev->name) { | ||
1601 | /* generic components */ | ||
1602 | dlc.name = aux_dev->name; | ||
1603 | dlc.of_node = NULL; | ||
1604 | component = soc_find_component(&dlc); | ||
1605 | if (!component) | 1581 | if (!component) |
1606 | goto err_defer; | 1582 | return -EPROBE_DEFER; |
1607 | } else { | ||
1608 | dev_err(card->dev, "ASoC: Invalid auxiliary device\n"); | ||
1609 | return -EINVAL; | ||
1610 | } | ||
1611 | |||
1612 | component->init = aux_dev->init; | ||
1613 | list_add(&component->card_aux_list, &card->aux_comp_list); | ||
1614 | 1583 | ||
1584 | component->init = aux->init; | ||
1585 | /* see for_each_card_auxs */ | ||
1586 | list_add(&component->card_aux_list, &card->aux_comp_list); | ||
1587 | } | ||
1615 | return 0; | 1588 | return 0; |
1616 | |||
1617 | err_defer: | ||
1618 | dev_err(card->dev, "ASoC: %s not registered\n", dlc.name); | ||
1619 | return -EPROBE_DEFER; | ||
1620 | } | 1589 | } |
1621 | 1590 | ||
1622 | static int soc_probe_aux_devices(struct snd_soc_card *card) | 1591 | static int soc_probe_aux_devices(struct snd_soc_card *card) |
@@ -1626,7 +1595,7 @@ static int soc_probe_aux_devices(struct snd_soc_card *card) | |||
1626 | int ret; | 1595 | int ret; |
1627 | 1596 | ||
1628 | for_each_comp_order(order) { | 1597 | for_each_comp_order(order) { |
1629 | list_for_each_entry(comp, &card->aux_comp_list, card_aux_list) { | 1598 | for_each_card_auxs(card, comp) { |
1630 | if (comp->driver->probe_order == order) { | 1599 | if (comp->driver->probe_order == order) { |
1631 | ret = soc_probe_component(card, comp); | 1600 | ret = soc_probe_component(card, comp); |
1632 | if (ret < 0) { | 1601 | if (ret < 0) { |
@@ -1648,14 +1617,9 @@ static void soc_remove_aux_devices(struct snd_soc_card *card) | |||
1648 | int order; | 1617 | int order; |
1649 | 1618 | ||
1650 | for_each_comp_order(order) { | 1619 | for_each_comp_order(order) { |
1651 | list_for_each_entry_safe(comp, _comp, | 1620 | for_each_card_auxs_safe(card, comp, _comp) { |
1652 | &card->aux_comp_list, card_aux_list) { | 1621 | if (comp->driver->remove_order == order) |
1653 | |||
1654 | if (comp->driver->remove_order == order) { | ||
1655 | soc_remove_component(comp); | 1622 | soc_remove_component(comp); |
1656 | /* remove it from the card's aux_comp_list */ | ||
1657 | list_del(&comp->card_aux_list); | ||
1658 | } | ||
1659 | } | 1623 | } |
1660 | } | 1624 | } |
1661 | } | 1625 | } |
@@ -1954,7 +1918,7 @@ match: | |||
1954 | } | 1918 | } |
1955 | } | 1919 | } |
1956 | 1920 | ||
1957 | static int soc_cleanup_card_resources(struct snd_soc_card *card) | 1921 | static void soc_cleanup_card_resources(struct snd_soc_card *card) |
1958 | { | 1922 | { |
1959 | /* free the ALSA card at first; this syncs with pending operations */ | 1923 | /* free the ALSA card at first; this syncs with pending operations */ |
1960 | if (card->snd_card) { | 1924 | if (card->snd_card) { |
@@ -1968,6 +1932,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) | |||
1968 | 1932 | ||
1969 | /* remove auxiliary devices */ | 1933 | /* remove auxiliary devices */ |
1970 | soc_remove_aux_devices(card); | 1934 | soc_remove_aux_devices(card); |
1935 | soc_unbind_aux_dev(card); | ||
1971 | 1936 | ||
1972 | snd_soc_dapm_free(&card->dapm); | 1937 | snd_soc_dapm_free(&card->dapm); |
1973 | soc_cleanup_card_debugfs(card); | 1938 | soc_cleanup_card_debugfs(card); |
@@ -1975,15 +1940,13 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) | |||
1975 | /* remove the card */ | 1940 | /* remove the card */ |
1976 | if (card->remove) | 1941 | if (card->remove) |
1977 | card->remove(card); | 1942 | card->remove(card); |
1978 | |||
1979 | return 0; | ||
1980 | } | 1943 | } |
1981 | 1944 | ||
1982 | static int snd_soc_instantiate_card(struct snd_soc_card *card) | 1945 | static int snd_soc_instantiate_card(struct snd_soc_card *card) |
1983 | { | 1946 | { |
1984 | struct snd_soc_pcm_runtime *rtd; | 1947 | struct snd_soc_pcm_runtime *rtd; |
1985 | struct snd_soc_dai_link *dai_link; | 1948 | struct snd_soc_dai_link *dai_link; |
1986 | int ret, i, order; | 1949 | int ret, i; |
1987 | 1950 | ||
1988 | mutex_lock(&client_mutex); | 1951 | mutex_lock(&client_mutex); |
1989 | for_each_card_prelinks(card, i, dai_link) { | 1952 | for_each_card_prelinks(card, i, dai_link) { |
@@ -1997,10 +1960,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1997 | } | 1960 | } |
1998 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); | 1961 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); |
1999 | 1962 | ||
2000 | card->dapm.bias_level = SND_SOC_BIAS_OFF; | 1963 | snd_soc_dapm_init(&card->dapm, card, NULL); |
2001 | card->dapm.dev = card->dev; | ||
2002 | card->dapm.card = card; | ||
2003 | list_add(&card->dapm.list, &card->dapm_list); | ||
2004 | 1964 | ||
2005 | /* check whether any platform is ignore machine FE and using topology */ | 1965 | /* check whether any platform is ignore machine FE and using topology */ |
2006 | soc_check_tplg_fes(card); | 1966 | soc_check_tplg_fes(card); |
@@ -2013,15 +1973,16 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
2013 | } | 1973 | } |
2014 | 1974 | ||
2015 | /* bind aux_devs too */ | 1975 | /* bind aux_devs too */ |
2016 | for (i = 0; i < card->num_aux_devs; i++) { | 1976 | ret = soc_bind_aux_dev(card); |
2017 | ret = soc_bind_aux_dev(card, i); | 1977 | if (ret < 0) |
2018 | if (ret != 0) | 1978 | goto probe_end; |
2019 | goto probe_end; | ||
2020 | } | ||
2021 | 1979 | ||
2022 | /* add predefined DAI links to the list */ | 1980 | /* add predefined DAI links to the list */ |
2023 | for_each_card_prelinks(card, i, dai_link) | 1981 | for_each_card_prelinks(card, i, dai_link) { |
2024 | snd_soc_add_dai_link(card, dai_link); | 1982 | ret = snd_soc_add_dai_link(card, dai_link); |
1983 | if (ret < 0) | ||
1984 | goto probe_end; | ||
1985 | } | ||
2025 | 1986 | ||
2026 | /* card bind complete so register a sound card */ | 1987 | /* card bind complete so register a sound card */ |
2027 | ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | 1988 | ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
@@ -2035,22 +1996,17 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
2035 | 1996 | ||
2036 | soc_init_card_debugfs(card); | 1997 | soc_init_card_debugfs(card); |
2037 | 1998 | ||
2038 | #ifdef CONFIG_DEBUG_FS | 1999 | soc_resume_init(card); |
2039 | snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root); | ||
2040 | #endif | ||
2041 | 2000 | ||
2042 | #ifdef CONFIG_PM_SLEEP | 2001 | ret = snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, |
2043 | /* deferred resume work */ | 2002 | card->num_dapm_widgets); |
2044 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); | 2003 | if (ret < 0) |
2045 | #endif | 2004 | goto probe_end; |
2046 | |||
2047 | if (card->dapm_widgets) | ||
2048 | snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, | ||
2049 | card->num_dapm_widgets); | ||
2050 | 2005 | ||
2051 | if (card->of_dapm_widgets) | 2006 | ret = snd_soc_dapm_new_controls(&card->dapm, card->of_dapm_widgets, |
2052 | snd_soc_dapm_new_controls(&card->dapm, card->of_dapm_widgets, | 2007 | card->num_of_dapm_widgets); |
2053 | card->num_of_dapm_widgets); | 2008 | if (ret < 0) |
2009 | goto probe_end; | ||
2054 | 2010 | ||
2055 | /* initialise the sound card only once */ | 2011 | /* initialise the sound card only once */ |
2056 | if (card->probe) { | 2012 | if (card->probe) { |
@@ -2060,16 +2016,11 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
2060 | } | 2016 | } |
2061 | 2017 | ||
2062 | /* probe all components used by DAI links on this card */ | 2018 | /* probe all components used by DAI links on this card */ |
2063 | for_each_comp_order(order) { | 2019 | ret = soc_probe_link_components(card); |
2064 | for_each_card_rtds(card, rtd) { | 2020 | if (ret < 0) { |
2065 | ret = soc_probe_link_components(card, rtd, order); | 2021 | dev_err(card->dev, |
2066 | if (ret < 0) { | 2022 | "ASoC: failed to instantiate card %d\n", ret); |
2067 | dev_err(card->dev, | 2023 | goto probe_end; |
2068 | "ASoC: failed to instantiate card %d\n", | ||
2069 | ret); | ||
2070 | goto probe_end; | ||
2071 | } | ||
2072 | } | ||
2073 | } | 2024 | } |
2074 | 2025 | ||
2075 | /* probe auxiliary components */ | 2026 | /* probe auxiliary components */ |
@@ -2094,32 +2045,33 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
2094 | } | 2045 | } |
2095 | 2046 | ||
2096 | /* probe all DAI links on this card */ | 2047 | /* probe all DAI links on this card */ |
2097 | for_each_comp_order(order) { | 2048 | ret = soc_probe_link_dais(card); |
2098 | for_each_card_rtds(card, rtd) { | 2049 | if (ret < 0) { |
2099 | ret = soc_probe_link_dais(card, rtd, order); | 2050 | dev_err(card->dev, |
2100 | if (ret < 0) { | 2051 | "ASoC: failed to instantiate card %d\n", ret); |
2101 | dev_err(card->dev, | 2052 | goto probe_end; |
2102 | "ASoC: failed to instantiate card %d\n", | ||
2103 | ret); | ||
2104 | goto probe_end; | ||
2105 | } | ||
2106 | } | ||
2107 | } | 2053 | } |
2108 | 2054 | ||
2055 | for_each_card_rtds(card, rtd) | ||
2056 | soc_link_init(card, rtd); | ||
2057 | |||
2109 | snd_soc_dapm_link_dai_widgets(card); | 2058 | snd_soc_dapm_link_dai_widgets(card); |
2110 | snd_soc_dapm_connect_dai_link_widgets(card); | 2059 | snd_soc_dapm_connect_dai_link_widgets(card); |
2111 | 2060 | ||
2112 | if (card->controls) | 2061 | ret = snd_soc_add_card_controls(card, card->controls, |
2113 | snd_soc_add_card_controls(card, card->controls, | 2062 | card->num_controls); |
2114 | card->num_controls); | 2063 | if (ret < 0) |
2064 | goto probe_end; | ||
2115 | 2065 | ||
2116 | if (card->dapm_routes) | 2066 | ret = snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, |
2117 | snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, | 2067 | card->num_dapm_routes); |
2118 | card->num_dapm_routes); | 2068 | if (ret < 0) |
2069 | goto probe_end; | ||
2119 | 2070 | ||
2120 | if (card->of_dapm_routes) | 2071 | ret = snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, |
2121 | snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, | 2072 | card->num_of_dapm_routes); |
2122 | card->num_of_dapm_routes); | 2073 | if (ret < 0) |
2074 | goto probe_end; | ||
2123 | 2075 | ||
2124 | /* try to set some sane longname if DMI is available */ | 2076 | /* try to set some sane longname if DMI is available */ |
2125 | snd_soc_set_dmi_name(card, NULL); | 2077 | snd_soc_set_dmi_name(card, NULL); |
@@ -2397,293 +2349,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai, | |||
2397 | } | 2349 | } |
2398 | EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); | 2350 | EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); |
2399 | 2351 | ||
2400 | /** | ||
2401 | * snd_soc_dai_set_sysclk - configure DAI system or master clock. | ||
2402 | * @dai: DAI | ||
2403 | * @clk_id: DAI specific clock ID | ||
2404 | * @freq: new clock frequency in Hz | ||
2405 | * @dir: new clock direction - input/output. | ||
2406 | * | ||
2407 | * Configures the DAI master (MCLK) or system (SYSCLK) clocking. | ||
2408 | */ | ||
2409 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
2410 | unsigned int freq, int dir) | ||
2411 | { | ||
2412 | if (dai->driver->ops->set_sysclk) | ||
2413 | return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); | ||
2414 | |||
2415 | return snd_soc_component_set_sysclk(dai->component, clk_id, 0, | ||
2416 | freq, dir); | ||
2417 | } | ||
2418 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | ||
2419 | |||
2420 | /** | ||
2421 | * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. | ||
2422 | * @component: COMPONENT | ||
2423 | * @clk_id: DAI specific clock ID | ||
2424 | * @source: Source for the clock | ||
2425 | * @freq: new clock frequency in Hz | ||
2426 | * @dir: new clock direction - input/output. | ||
2427 | * | ||
2428 | * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. | ||
2429 | */ | ||
2430 | int snd_soc_component_set_sysclk(struct snd_soc_component *component, | ||
2431 | int clk_id, int source, unsigned int freq, | ||
2432 | int dir) | ||
2433 | { | ||
2434 | if (component->driver->set_sysclk) | ||
2435 | return component->driver->set_sysclk(component, clk_id, source, | ||
2436 | freq, dir); | ||
2437 | |||
2438 | return -ENOTSUPP; | ||
2439 | } | ||
2440 | EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); | ||
2441 | |||
2442 | /** | ||
2443 | * snd_soc_dai_set_clkdiv - configure DAI clock dividers. | ||
2444 | * @dai: DAI | ||
2445 | * @div_id: DAI specific clock divider ID | ||
2446 | * @div: new clock divisor. | ||
2447 | * | ||
2448 | * Configures the clock dividers. This is used to derive the best DAI bit and | ||
2449 | * frame clocks from the system or master clock. It's best to set the DAI bit | ||
2450 | * and frame clocks as low as possible to save system power. | ||
2451 | */ | ||
2452 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, | ||
2453 | int div_id, int div) | ||
2454 | { | ||
2455 | if (dai->driver->ops->set_clkdiv) | ||
2456 | return dai->driver->ops->set_clkdiv(dai, div_id, div); | ||
2457 | else | ||
2458 | return -EINVAL; | ||
2459 | } | ||
2460 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); | ||
2461 | |||
2462 | /** | ||
2463 | * snd_soc_dai_set_pll - configure DAI PLL. | ||
2464 | * @dai: DAI | ||
2465 | * @pll_id: DAI specific PLL ID | ||
2466 | * @source: DAI specific source for the PLL | ||
2467 | * @freq_in: PLL input clock frequency in Hz | ||
2468 | * @freq_out: requested PLL output clock frequency in Hz | ||
2469 | * | ||
2470 | * Configures and enables PLL to generate output clock based on input clock. | ||
2471 | */ | ||
2472 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, | ||
2473 | unsigned int freq_in, unsigned int freq_out) | ||
2474 | { | ||
2475 | if (dai->driver->ops->set_pll) | ||
2476 | return dai->driver->ops->set_pll(dai, pll_id, source, | ||
2477 | freq_in, freq_out); | ||
2478 | |||
2479 | return snd_soc_component_set_pll(dai->component, pll_id, source, | ||
2480 | freq_in, freq_out); | ||
2481 | } | ||
2482 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); | ||
2483 | |||
2484 | /* | ||
2485 | * snd_soc_component_set_pll - configure component PLL. | ||
2486 | * @component: COMPONENT | ||
2487 | * @pll_id: DAI specific PLL ID | ||
2488 | * @source: DAI specific source for the PLL | ||
2489 | * @freq_in: PLL input clock frequency in Hz | ||
2490 | * @freq_out: requested PLL output clock frequency in Hz | ||
2491 | * | ||
2492 | * Configures and enables PLL to generate output clock based on input clock. | ||
2493 | */ | ||
2494 | int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, | ||
2495 | int source, unsigned int freq_in, | ||
2496 | unsigned int freq_out) | ||
2497 | { | ||
2498 | if (component->driver->set_pll) | ||
2499 | return component->driver->set_pll(component, pll_id, source, | ||
2500 | freq_in, freq_out); | ||
2501 | |||
2502 | return -EINVAL; | ||
2503 | } | ||
2504 | EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); | ||
2505 | |||
2506 | /** | ||
2507 | * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. | ||
2508 | * @dai: DAI | ||
2509 | * @ratio: Ratio of BCLK to Sample rate. | ||
2510 | * | ||
2511 | * Configures the DAI for a preset BCLK to sample rate ratio. | ||
2512 | */ | ||
2513 | int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) | ||
2514 | { | ||
2515 | if (dai->driver->ops->set_bclk_ratio) | ||
2516 | return dai->driver->ops->set_bclk_ratio(dai, ratio); | ||
2517 | else | ||
2518 | return -EINVAL; | ||
2519 | } | ||
2520 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); | ||
2521 | |||
2522 | /** | ||
2523 | * snd_soc_dai_set_fmt - configure DAI hardware audio format. | ||
2524 | * @dai: DAI | ||
2525 | * @fmt: SND_SOC_DAIFMT_* format value. | ||
2526 | * | ||
2527 | * Configures the DAI hardware format and clocking. | ||
2528 | */ | ||
2529 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
2530 | { | ||
2531 | if (dai->driver->ops->set_fmt == NULL) | ||
2532 | return -ENOTSUPP; | ||
2533 | return dai->driver->ops->set_fmt(dai, fmt); | ||
2534 | } | ||
2535 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | ||
2536 | |||
2537 | /** | ||
2538 | * snd_soc_xlate_tdm_slot - generate tx/rx slot mask. | ||
2539 | * @slots: Number of slots in use. | ||
2540 | * @tx_mask: bitmask representing active TX slots. | ||
2541 | * @rx_mask: bitmask representing active RX slots. | ||
2542 | * | ||
2543 | * Generates the TDM tx and rx slot default masks for DAI. | ||
2544 | */ | ||
2545 | static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, | ||
2546 | unsigned int *tx_mask, | ||
2547 | unsigned int *rx_mask) | ||
2548 | { | ||
2549 | if (*tx_mask || *rx_mask) | ||
2550 | return 0; | ||
2551 | |||
2552 | if (!slots) | ||
2553 | return -EINVAL; | ||
2554 | |||
2555 | *tx_mask = (1 << slots) - 1; | ||
2556 | *rx_mask = (1 << slots) - 1; | ||
2557 | |||
2558 | return 0; | ||
2559 | } | ||
2560 | |||
2561 | /** | ||
2562 | * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation | ||
2563 | * @dai: The DAI to configure | ||
2564 | * @tx_mask: bitmask representing active TX slots. | ||
2565 | * @rx_mask: bitmask representing active RX slots. | ||
2566 | * @slots: Number of slots in use. | ||
2567 | * @slot_width: Width in bits for each slot. | ||
2568 | * | ||
2569 | * This function configures the specified DAI for TDM operation. @slot contains | ||
2570 | * the total number of slots of the TDM stream and @slot_with the width of each | ||
2571 | * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the | ||
2572 | * active slots of the TDM stream for the specified DAI, i.e. which slots the | ||
2573 | * DAI should write to or read from. If a bit is set the corresponding slot is | ||
2574 | * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to | ||
2575 | * the first slot, bit 1 to the second slot and so on. The first active slot | ||
2576 | * maps to the first channel of the DAI, the second active slot to the second | ||
2577 | * channel and so on. | ||
2578 | * | ||
2579 | * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask, | ||
2580 | * @rx_mask and @slot_width will be ignored. | ||
2581 | * | ||
2582 | * Returns 0 on success, a negative error code otherwise. | ||
2583 | */ | ||
2584 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | ||
2585 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | ||
2586 | { | ||
2587 | if (dai->driver->ops->xlate_tdm_slot_mask) | ||
2588 | dai->driver->ops->xlate_tdm_slot_mask(slots, | ||
2589 | &tx_mask, &rx_mask); | ||
2590 | else | ||
2591 | snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); | ||
2592 | |||
2593 | dai->tx_mask = tx_mask; | ||
2594 | dai->rx_mask = rx_mask; | ||
2595 | |||
2596 | if (dai->driver->ops->set_tdm_slot) | ||
2597 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, | ||
2598 | slots, slot_width); | ||
2599 | else | ||
2600 | return -ENOTSUPP; | ||
2601 | } | ||
2602 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); | ||
2603 | |||
2604 | /** | ||
2605 | * snd_soc_dai_set_channel_map - configure DAI audio channel map | ||
2606 | * @dai: DAI | ||
2607 | * @tx_num: how many TX channels | ||
2608 | * @tx_slot: pointer to an array which imply the TX slot number channel | ||
2609 | * 0~num-1 uses | ||
2610 | * @rx_num: how many RX channels | ||
2611 | * @rx_slot: pointer to an array which imply the RX slot number channel | ||
2612 | * 0~num-1 uses | ||
2613 | * | ||
2614 | * configure the relationship between channel number and TDM slot number. | ||
2615 | */ | ||
2616 | int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, | ||
2617 | unsigned int tx_num, unsigned int *tx_slot, | ||
2618 | unsigned int rx_num, unsigned int *rx_slot) | ||
2619 | { | ||
2620 | if (dai->driver->ops->set_channel_map) | ||
2621 | return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, | ||
2622 | rx_num, rx_slot); | ||
2623 | else | ||
2624 | return -ENOTSUPP; | ||
2625 | } | ||
2626 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); | ||
2627 | |||
2628 | /** | ||
2629 | * snd_soc_dai_get_channel_map - Get DAI audio channel map | ||
2630 | * @dai: DAI | ||
2631 | * @tx_num: how many TX channels | ||
2632 | * @tx_slot: pointer to an array which imply the TX slot number channel | ||
2633 | * 0~num-1 uses | ||
2634 | * @rx_num: how many RX channels | ||
2635 | * @rx_slot: pointer to an array which imply the RX slot number channel | ||
2636 | * 0~num-1 uses | ||
2637 | */ | ||
2638 | int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, | ||
2639 | unsigned int *tx_num, unsigned int *tx_slot, | ||
2640 | unsigned int *rx_num, unsigned int *rx_slot) | ||
2641 | { | ||
2642 | if (dai->driver->ops->get_channel_map) | ||
2643 | return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, | ||
2644 | rx_num, rx_slot); | ||
2645 | else | ||
2646 | return -ENOTSUPP; | ||
2647 | } | ||
2648 | EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); | ||
2649 | |||
2650 | /** | ||
2651 | * snd_soc_dai_set_tristate - configure DAI system or master clock. | ||
2652 | * @dai: DAI | ||
2653 | * @tristate: tristate enable | ||
2654 | * | ||
2655 | * Tristates the DAI so that others can use it. | ||
2656 | */ | ||
2657 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) | ||
2658 | { | ||
2659 | if (dai->driver->ops->set_tristate) | ||
2660 | return dai->driver->ops->set_tristate(dai, tristate); | ||
2661 | else | ||
2662 | return -EINVAL; | ||
2663 | } | ||
2664 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); | ||
2665 | |||
2666 | /** | ||
2667 | * snd_soc_dai_digital_mute - configure DAI system or master clock. | ||
2668 | * @dai: DAI | ||
2669 | * @mute: mute enable | ||
2670 | * @direction: stream to mute | ||
2671 | * | ||
2672 | * Mutes the DAI DAC. | ||
2673 | */ | ||
2674 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, | ||
2675 | int direction) | ||
2676 | { | ||
2677 | if (dai->driver->ops->mute_stream) | ||
2678 | return dai->driver->ops->mute_stream(dai, mute, direction); | ||
2679 | else if (direction == SNDRV_PCM_STREAM_PLAYBACK && | ||
2680 | dai->driver->ops->digital_mute) | ||
2681 | return dai->driver->ops->digital_mute(dai, mute); | ||
2682 | else | ||
2683 | return -ENOTSUPP; | ||
2684 | } | ||
2685 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | ||
2686 | |||
2687 | static int snd_soc_bind_card(struct snd_soc_card *card) | 2352 | static int snd_soc_bind_card(struct snd_soc_card *card) |
2688 | { | 2353 | { |
2689 | struct snd_soc_pcm_runtime *rtd; | 2354 | struct snd_soc_pcm_runtime *rtd; |
@@ -2724,18 +2389,22 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
2724 | 2389 | ||
2725 | dev_set_drvdata(card->dev, card); | 2390 | dev_set_drvdata(card->dev, card); |
2726 | 2391 | ||
2727 | snd_soc_initialize_card_lists(card); | 2392 | INIT_LIST_HEAD(&card->widgets); |
2728 | 2393 | INIT_LIST_HEAD(&card->paths); | |
2394 | INIT_LIST_HEAD(&card->dapm_list); | ||
2395 | INIT_LIST_HEAD(&card->aux_comp_list); | ||
2396 | INIT_LIST_HEAD(&card->component_dev_list); | ||
2397 | INIT_LIST_HEAD(&card->list); | ||
2729 | INIT_LIST_HEAD(&card->dai_link_list); | 2398 | INIT_LIST_HEAD(&card->dai_link_list); |
2730 | |||
2731 | INIT_LIST_HEAD(&card->rtd_list); | 2399 | INIT_LIST_HEAD(&card->rtd_list); |
2732 | card->num_rtd = 0; | ||
2733 | |||
2734 | INIT_LIST_HEAD(&card->dapm_dirty); | 2400 | INIT_LIST_HEAD(&card->dapm_dirty); |
2735 | INIT_LIST_HEAD(&card->dobj_list); | 2401 | INIT_LIST_HEAD(&card->dobj_list); |
2402 | |||
2403 | card->num_rtd = 0; | ||
2736 | card->instantiated = 0; | 2404 | card->instantiated = 0; |
2737 | mutex_init(&card->mutex); | 2405 | mutex_init(&card->mutex); |
2738 | mutex_init(&card->dapm_mutex); | 2406 | mutex_init(&card->dapm_mutex); |
2407 | mutex_init(&card->pcm_mutex); | ||
2739 | spin_lock_init(&card->dpcm_lock); | 2408 | spin_lock_init(&card->dpcm_lock); |
2740 | 2409 | ||
2741 | return snd_soc_bind_card(card); | 2410 | return snd_soc_bind_card(card); |
@@ -2744,20 +2413,13 @@ EXPORT_SYMBOL_GPL(snd_soc_register_card); | |||
2744 | 2413 | ||
2745 | static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) | 2414 | static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) |
2746 | { | 2415 | { |
2747 | struct snd_soc_pcm_runtime *rtd; | ||
2748 | int order; | ||
2749 | |||
2750 | if (card->instantiated) { | 2416 | if (card->instantiated) { |
2751 | card->instantiated = false; | 2417 | card->instantiated = false; |
2752 | snd_soc_dapm_shutdown(card); | 2418 | snd_soc_dapm_shutdown(card); |
2753 | snd_soc_flush_all_delayed_work(card); | 2419 | snd_soc_flush_all_delayed_work(card); |
2754 | 2420 | ||
2755 | /* remove all components used by DAI links on this card */ | 2421 | /* remove all components used by DAI links on this card */ |
2756 | for_each_comp_order(order) { | 2422 | soc_remove_link_components(card); |
2757 | for_each_card_rtds(card, rtd) { | ||
2758 | soc_remove_link_components(card, rtd, order); | ||
2759 | } | ||
2760 | } | ||
2761 | 2423 | ||
2762 | soc_cleanup_card_resources(card); | 2424 | soc_cleanup_card_resources(card); |
2763 | if (!unregister) | 2425 | if (!unregister) |
@@ -2994,34 +2656,13 @@ int snd_soc_register_dai(struct snd_soc_component *component, | |||
2994 | } | 2656 | } |
2995 | EXPORT_SYMBOL_GPL(snd_soc_register_dai); | 2657 | EXPORT_SYMBOL_GPL(snd_soc_register_dai); |
2996 | 2658 | ||
2997 | static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm, | ||
2998 | enum snd_soc_dapm_type type, int subseq) | ||
2999 | { | ||
3000 | struct snd_soc_component *component = dapm->component; | ||
3001 | |||
3002 | component->driver->seq_notifier(component, type, subseq); | ||
3003 | } | ||
3004 | |||
3005 | static int snd_soc_component_stream_event(struct snd_soc_dapm_context *dapm, | ||
3006 | int event) | ||
3007 | { | ||
3008 | struct snd_soc_component *component = dapm->component; | ||
3009 | |||
3010 | return component->driver->stream_event(component, event); | ||
3011 | } | ||
3012 | |||
3013 | static int snd_soc_component_set_bias_level(struct snd_soc_dapm_context *dapm, | ||
3014 | enum snd_soc_bias_level level) | ||
3015 | { | ||
3016 | struct snd_soc_component *component = dapm->component; | ||
3017 | |||
3018 | return component->driver->set_bias_level(component, level); | ||
3019 | } | ||
3020 | |||
3021 | static int snd_soc_component_initialize(struct snd_soc_component *component, | 2659 | static int snd_soc_component_initialize(struct snd_soc_component *component, |
3022 | const struct snd_soc_component_driver *driver, struct device *dev) | 2660 | const struct snd_soc_component_driver *driver, struct device *dev) |
3023 | { | 2661 | { |
3024 | struct snd_soc_dapm_context *dapm; | 2662 | INIT_LIST_HEAD(&component->dai_list); |
2663 | INIT_LIST_HEAD(&component->dobj_list); | ||
2664 | INIT_LIST_HEAD(&component->card_list); | ||
2665 | mutex_init(&component->io_mutex); | ||
3025 | 2666 | ||
3026 | component->name = fmt_single_name(dev, &component->id); | 2667 | component->name = fmt_single_name(dev, &component->id); |
3027 | if (!component->name) { | 2668 | if (!component->name) { |
@@ -3032,22 +2673,6 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, | |||
3032 | component->dev = dev; | 2673 | component->dev = dev; |
3033 | component->driver = driver; | 2674 | component->driver = driver; |
3034 | 2675 | ||
3035 | dapm = snd_soc_component_get_dapm(component); | ||
3036 | dapm->dev = dev; | ||
3037 | dapm->component = component; | ||
3038 | dapm->bias_level = SND_SOC_BIAS_OFF; | ||
3039 | dapm->idle_bias_off = !driver->idle_bias_on; | ||
3040 | dapm->suspend_bias_off = driver->suspend_bias_off; | ||
3041 | if (driver->seq_notifier) | ||
3042 | dapm->seq_notifier = snd_soc_component_seq_notifier; | ||
3043 | if (driver->stream_event) | ||
3044 | dapm->stream_event = snd_soc_component_stream_event; | ||
3045 | if (driver->set_bias_level) | ||
3046 | dapm->set_bias_level = snd_soc_component_set_bias_level; | ||
3047 | |||
3048 | INIT_LIST_HEAD(&component->dai_list); | ||
3049 | mutex_init(&component->io_mutex); | ||
3050 | |||
3051 | return 0; | 2676 | return 0; |
3052 | } | 2677 | } |
3053 | 2678 | ||
@@ -3115,7 +2740,6 @@ static void snd_soc_component_add(struct snd_soc_component *component) | |||
3115 | 2740 | ||
3116 | /* see for_each_component */ | 2741 | /* see for_each_component */ |
3117 | list_add(&component->list, &component_list); | 2742 | list_add(&component->list, &component_list); |
3118 | INIT_LIST_HEAD(&component->dobj_list); | ||
3119 | 2743 | ||
3120 | mutex_unlock(&client_mutex); | 2744 | mutex_unlock(&client_mutex); |
3121 | } | 2745 | } |
@@ -3175,12 +2799,9 @@ static void snd_soc_try_rebind_card(void) | |||
3175 | { | 2799 | { |
3176 | struct snd_soc_card *card, *c; | 2800 | struct snd_soc_card *card, *c; |
3177 | 2801 | ||
3178 | if (!list_empty(&unbind_card_list)) { | 2802 | list_for_each_entry_safe(card, c, &unbind_card_list, list) |
3179 | list_for_each_entry_safe(card, c, &unbind_card_list, list) { | 2803 | if (!snd_soc_bind_card(card)) |
3180 | if (!snd_soc_bind_card(card)) | 2804 | list_del(&card->list); |
3181 | list_del(&card->list); | ||
3182 | } | ||
3183 | } | ||
3184 | } | 2805 | } |
3185 | 2806 | ||
3186 | int snd_soc_add_component(struct device *dev, | 2807 | int snd_soc_add_component(struct device *dev, |
@@ -3682,9 +3303,8 @@ int snd_soc_get_dai_id(struct device_node *ep) | |||
3682 | ret = -ENOTSUPP; | 3303 | ret = -ENOTSUPP; |
3683 | mutex_lock(&client_mutex); | 3304 | mutex_lock(&client_mutex); |
3684 | component = soc_find_component(&dlc); | 3305 | component = soc_find_component(&dlc); |
3685 | if (component && | 3306 | if (component) |
3686 | component->driver->of_xlate_dai_id) | 3307 | ret = snd_soc_component_of_xlate_dai_id(component, ep); |
3687 | ret = component->driver->of_xlate_dai_id(component, ep); | ||
3688 | mutex_unlock(&client_mutex); | 3308 | mutex_unlock(&client_mutex); |
3689 | 3309 | ||
3690 | of_node_put(dlc.of_node); | 3310 | of_node_put(dlc.of_node); |
@@ -3707,11 +3327,8 @@ int snd_soc_get_dai_name(struct of_phandle_args *args, | |||
3707 | if (component_of_node != args->np) | 3327 | if (component_of_node != args->np) |
3708 | continue; | 3328 | continue; |
3709 | 3329 | ||
3710 | if (pos->driver->of_xlate_dai_name) { | 3330 | ret = snd_soc_component_of_xlate_dai_name(pos, args, dai_name); |
3711 | ret = pos->driver->of_xlate_dai_name(pos, | 3331 | if (ret == -ENOTSUPP) { |
3712 | args, | ||
3713 | dai_name); | ||
3714 | } else { | ||
3715 | struct snd_soc_dai *dai; | 3332 | struct snd_soc_dai *dai; |
3716 | int id = -1; | 3333 | int id = -1; |
3717 | 3334 | ||
diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c new file mode 100644 index 000000000000..1c7f63871c1d --- /dev/null +++ b/sound/soc/soc-dai.c | |||
@@ -0,0 +1,407 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // soc-dai.c | ||
4 | // | ||
5 | // Copyright (C) 2019 Renesas Electronics Corp. | ||
6 | // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
7 | // | ||
8 | |||
9 | #include <sound/soc.h> | ||
10 | #include <sound/soc-dai.h> | ||
11 | |||
12 | /** | ||
13 | * snd_soc_dai_set_sysclk - configure DAI system or master clock. | ||
14 | * @dai: DAI | ||
15 | * @clk_id: DAI specific clock ID | ||
16 | * @freq: new clock frequency in Hz | ||
17 | * @dir: new clock direction - input/output. | ||
18 | * | ||
19 | * Configures the DAI master (MCLK) or system (SYSCLK) clocking. | ||
20 | */ | ||
21 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
22 | unsigned int freq, int dir) | ||
23 | { | ||
24 | if (dai->driver->ops->set_sysclk) | ||
25 | return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); | ||
26 | |||
27 | return snd_soc_component_set_sysclk(dai->component, clk_id, 0, | ||
28 | freq, dir); | ||
29 | } | ||
30 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | ||
31 | |||
32 | /** | ||
33 | * snd_soc_dai_set_clkdiv - configure DAI clock dividers. | ||
34 | * @dai: DAI | ||
35 | * @div_id: DAI specific clock divider ID | ||
36 | * @div: new clock divisor. | ||
37 | * | ||
38 | * Configures the clock dividers. This is used to derive the best DAI bit and | ||
39 | * frame clocks from the system or master clock. It's best to set the DAI bit | ||
40 | * and frame clocks as low as possible to save system power. | ||
41 | */ | ||
42 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, | ||
43 | int div_id, int div) | ||
44 | { | ||
45 | if (dai->driver->ops->set_clkdiv) | ||
46 | return dai->driver->ops->set_clkdiv(dai, div_id, div); | ||
47 | else | ||
48 | return -EINVAL; | ||
49 | } | ||
50 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); | ||
51 | |||
52 | /** | ||
53 | * snd_soc_dai_set_pll - configure DAI PLL. | ||
54 | * @dai: DAI | ||
55 | * @pll_id: DAI specific PLL ID | ||
56 | * @source: DAI specific source for the PLL | ||
57 | * @freq_in: PLL input clock frequency in Hz | ||
58 | * @freq_out: requested PLL output clock frequency in Hz | ||
59 | * | ||
60 | * Configures and enables PLL to generate output clock based on input clock. | ||
61 | */ | ||
62 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, | ||
63 | unsigned int freq_in, unsigned int freq_out) | ||
64 | { | ||
65 | if (dai->driver->ops->set_pll) | ||
66 | return dai->driver->ops->set_pll(dai, pll_id, source, | ||
67 | freq_in, freq_out); | ||
68 | |||
69 | return snd_soc_component_set_pll(dai->component, pll_id, source, | ||
70 | freq_in, freq_out); | ||
71 | } | ||
72 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); | ||
73 | |||
74 | /** | ||
75 | * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. | ||
76 | * @dai: DAI | ||
77 | * @ratio: Ratio of BCLK to Sample rate. | ||
78 | * | ||
79 | * Configures the DAI for a preset BCLK to sample rate ratio. | ||
80 | */ | ||
81 | int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) | ||
82 | { | ||
83 | if (dai->driver->ops->set_bclk_ratio) | ||
84 | return dai->driver->ops->set_bclk_ratio(dai, ratio); | ||
85 | else | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); | ||
89 | |||
90 | /** | ||
91 | * snd_soc_dai_set_fmt - configure DAI hardware audio format. | ||
92 | * @dai: DAI | ||
93 | * @fmt: SND_SOC_DAIFMT_* format value. | ||
94 | * | ||
95 | * Configures the DAI hardware format and clocking. | ||
96 | */ | ||
97 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
98 | { | ||
99 | if (dai->driver->ops->set_fmt == NULL) | ||
100 | return -ENOTSUPP; | ||
101 | return dai->driver->ops->set_fmt(dai, fmt); | ||
102 | } | ||
103 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | ||
104 | |||
105 | /** | ||
106 | * snd_soc_xlate_tdm_slot - generate tx/rx slot mask. | ||
107 | * @slots: Number of slots in use. | ||
108 | * @tx_mask: bitmask representing active TX slots. | ||
109 | * @rx_mask: bitmask representing active RX slots. | ||
110 | * | ||
111 | * Generates the TDM tx and rx slot default masks for DAI. | ||
112 | */ | ||
113 | static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, | ||
114 | unsigned int *tx_mask, | ||
115 | unsigned int *rx_mask) | ||
116 | { | ||
117 | if (*tx_mask || *rx_mask) | ||
118 | return 0; | ||
119 | |||
120 | if (!slots) | ||
121 | return -EINVAL; | ||
122 | |||
123 | *tx_mask = (1 << slots) - 1; | ||
124 | *rx_mask = (1 << slots) - 1; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation | ||
131 | * @dai: The DAI to configure | ||
132 | * @tx_mask: bitmask representing active TX slots. | ||
133 | * @rx_mask: bitmask representing active RX slots. | ||
134 | * @slots: Number of slots in use. | ||
135 | * @slot_width: Width in bits for each slot. | ||
136 | * | ||
137 | * This function configures the specified DAI for TDM operation. @slot contains | ||
138 | * the total number of slots of the TDM stream and @slot_with the width of each | ||
139 | * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the | ||
140 | * active slots of the TDM stream for the specified DAI, i.e. which slots the | ||
141 | * DAI should write to or read from. If a bit is set the corresponding slot is | ||
142 | * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to | ||
143 | * the first slot, bit 1 to the second slot and so on. The first active slot | ||
144 | * maps to the first channel of the DAI, the second active slot to the second | ||
145 | * channel and so on. | ||
146 | * | ||
147 | * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask, | ||
148 | * @rx_mask and @slot_width will be ignored. | ||
149 | * | ||
150 | * Returns 0 on success, a negative error code otherwise. | ||
151 | */ | ||
152 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | ||
153 | unsigned int tx_mask, unsigned int rx_mask, | ||
154 | int slots, int slot_width) | ||
155 | { | ||
156 | if (dai->driver->ops->xlate_tdm_slot_mask) | ||
157 | dai->driver->ops->xlate_tdm_slot_mask(slots, | ||
158 | &tx_mask, &rx_mask); | ||
159 | else | ||
160 | snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); | ||
161 | |||
162 | dai->tx_mask = tx_mask; | ||
163 | dai->rx_mask = rx_mask; | ||
164 | |||
165 | if (dai->driver->ops->set_tdm_slot) | ||
166 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, | ||
167 | slots, slot_width); | ||
168 | else | ||
169 | return -ENOTSUPP; | ||
170 | } | ||
171 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); | ||
172 | |||
173 | /** | ||
174 | * snd_soc_dai_set_channel_map - configure DAI audio channel map | ||
175 | * @dai: DAI | ||
176 | * @tx_num: how many TX channels | ||
177 | * @tx_slot: pointer to an array which imply the TX slot number channel | ||
178 | * 0~num-1 uses | ||
179 | * @rx_num: how many RX channels | ||
180 | * @rx_slot: pointer to an array which imply the RX slot number channel | ||
181 | * 0~num-1 uses | ||
182 | * | ||
183 | * configure the relationship between channel number and TDM slot number. | ||
184 | */ | ||
185 | int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, | ||
186 | unsigned int tx_num, unsigned int *tx_slot, | ||
187 | unsigned int rx_num, unsigned int *rx_slot) | ||
188 | { | ||
189 | if (dai->driver->ops->set_channel_map) | ||
190 | return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot, | ||
191 | rx_num, rx_slot); | ||
192 | else | ||
193 | return -ENOTSUPP; | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map); | ||
196 | |||
197 | /** | ||
198 | * snd_soc_dai_get_channel_map - Get DAI audio channel map | ||
199 | * @dai: DAI | ||
200 | * @tx_num: how many TX channels | ||
201 | * @tx_slot: pointer to an array which imply the TX slot number channel | ||
202 | * 0~num-1 uses | ||
203 | * @rx_num: how many RX channels | ||
204 | * @rx_slot: pointer to an array which imply the RX slot number channel | ||
205 | * 0~num-1 uses | ||
206 | */ | ||
207 | int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, | ||
208 | unsigned int *tx_num, unsigned int *tx_slot, | ||
209 | unsigned int *rx_num, unsigned int *rx_slot) | ||
210 | { | ||
211 | if (dai->driver->ops->get_channel_map) | ||
212 | return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot, | ||
213 | rx_num, rx_slot); | ||
214 | else | ||
215 | return -ENOTSUPP; | ||
216 | } | ||
217 | EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map); | ||
218 | |||
219 | /** | ||
220 | * snd_soc_dai_set_tristate - configure DAI system or master clock. | ||
221 | * @dai: DAI | ||
222 | * @tristate: tristate enable | ||
223 | * | ||
224 | * Tristates the DAI so that others can use it. | ||
225 | */ | ||
226 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) | ||
227 | { | ||
228 | if (dai->driver->ops->set_tristate) | ||
229 | return dai->driver->ops->set_tristate(dai, tristate); | ||
230 | else | ||
231 | return -EINVAL; | ||
232 | } | ||
233 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); | ||
234 | |||
235 | /** | ||
236 | * snd_soc_dai_digital_mute - configure DAI system or master clock. | ||
237 | * @dai: DAI | ||
238 | * @mute: mute enable | ||
239 | * @direction: stream to mute | ||
240 | * | ||
241 | * Mutes the DAI DAC. | ||
242 | */ | ||
243 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, | ||
244 | int direction) | ||
245 | { | ||
246 | if (dai->driver->ops->mute_stream) | ||
247 | return dai->driver->ops->mute_stream(dai, mute, direction); | ||
248 | else if (direction == SNDRV_PCM_STREAM_PLAYBACK && | ||
249 | dai->driver->ops->digital_mute) | ||
250 | return dai->driver->ops->digital_mute(dai, mute); | ||
251 | else | ||
252 | return -ENOTSUPP; | ||
253 | } | ||
254 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | ||
255 | |||
256 | int snd_soc_dai_hw_params(struct snd_soc_dai *dai, | ||
257 | struct snd_pcm_substream *substream, | ||
258 | struct snd_pcm_hw_params *params) | ||
259 | { | ||
260 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
261 | int ret; | ||
262 | |||
263 | /* perform any topology hw_params fixups before DAI */ | ||
264 | if (rtd->dai_link->be_hw_params_fixup) { | ||
265 | ret = rtd->dai_link->be_hw_params_fixup(rtd, params); | ||
266 | if (ret < 0) { | ||
267 | dev_err(rtd->dev, | ||
268 | "ASoC: hw_params topology fixup failed %d\n", | ||
269 | ret); | ||
270 | return ret; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | if (dai->driver->ops->hw_params) { | ||
275 | ret = dai->driver->ops->hw_params(substream, params, dai); | ||
276 | if (ret < 0) { | ||
277 | dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n", | ||
278 | dai->name, ret); | ||
279 | return ret; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | void snd_soc_dai_hw_free(struct snd_soc_dai *dai, | ||
287 | struct snd_pcm_substream *substream) | ||
288 | { | ||
289 | if (dai->driver->ops->hw_free) | ||
290 | dai->driver->ops->hw_free(substream, dai); | ||
291 | } | ||
292 | |||
293 | int snd_soc_dai_startup(struct snd_soc_dai *dai, | ||
294 | struct snd_pcm_substream *substream) | ||
295 | { | ||
296 | int ret = 0; | ||
297 | |||
298 | if (dai->driver->ops->startup) | ||
299 | ret = dai->driver->ops->startup(substream, dai); | ||
300 | |||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | void snd_soc_dai_shutdown(struct snd_soc_dai *dai, | ||
305 | struct snd_pcm_substream *substream) | ||
306 | { | ||
307 | if (dai->driver->ops->shutdown) | ||
308 | dai->driver->ops->shutdown(substream, dai); | ||
309 | } | ||
310 | |||
311 | int snd_soc_dai_prepare(struct snd_soc_dai *dai, | ||
312 | struct snd_pcm_substream *substream) | ||
313 | { | ||
314 | int ret = 0; | ||
315 | |||
316 | if (dai->driver->ops->prepare) | ||
317 | ret = dai->driver->ops->prepare(substream, dai); | ||
318 | |||
319 | return ret; | ||
320 | } | ||
321 | |||
322 | int snd_soc_dai_trigger(struct snd_soc_dai *dai, | ||
323 | struct snd_pcm_substream *substream, | ||
324 | int cmd) | ||
325 | { | ||
326 | int ret = 0; | ||
327 | |||
328 | if (dai->driver->ops->trigger) | ||
329 | ret = dai->driver->ops->trigger(substream, cmd, dai); | ||
330 | |||
331 | return ret; | ||
332 | } | ||
333 | |||
334 | int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, | ||
335 | struct snd_pcm_substream *substream, | ||
336 | int cmd) | ||
337 | { | ||
338 | int ret = 0; | ||
339 | |||
340 | if (dai->driver->ops->bespoke_trigger) | ||
341 | ret = dai->driver->ops->bespoke_trigger(substream, cmd, dai); | ||
342 | |||
343 | return ret; | ||
344 | } | ||
345 | |||
346 | snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, | ||
347 | struct snd_pcm_substream *substream) | ||
348 | { | ||
349 | int delay = 0; | ||
350 | |||
351 | if (dai->driver->ops->delay) | ||
352 | delay = dai->driver->ops->delay(substream, dai); | ||
353 | |||
354 | return delay; | ||
355 | } | ||
356 | |||
357 | void snd_soc_dai_suspend(struct snd_soc_dai *dai) | ||
358 | { | ||
359 | if (dai->driver->suspend) | ||
360 | dai->driver->suspend(dai); | ||
361 | } | ||
362 | |||
363 | void snd_soc_dai_resume(struct snd_soc_dai *dai) | ||
364 | { | ||
365 | if (dai->driver->resume) | ||
366 | dai->driver->resume(dai); | ||
367 | } | ||
368 | |||
369 | int snd_soc_dai_probe(struct snd_soc_dai *dai) | ||
370 | { | ||
371 | if (dai->driver->probe) | ||
372 | return dai->driver->probe(dai); | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | int snd_soc_dai_remove(struct snd_soc_dai *dai) | ||
377 | { | ||
378 | if (dai->driver->remove) | ||
379 | return dai->driver->remove(dai); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | int snd_soc_dai_compress_new(struct snd_soc_dai *dai, | ||
384 | struct snd_soc_pcm_runtime *rtd, int num) | ||
385 | { | ||
386 | if (dai->driver->compress_new) | ||
387 | return dai->driver->compress_new(rtd, num); | ||
388 | return -ENOTSUPP; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | * snd_soc_dai_stream_valid() - check if a DAI supports the given stream | ||
393 | * | ||
394 | * Returns true if the DAI supports the indicated stream type. | ||
395 | */ | ||
396 | bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) | ||
397 | { | ||
398 | struct snd_soc_pcm_stream *stream; | ||
399 | |||
400 | if (dir == SNDRV_PCM_STREAM_PLAYBACK) | ||
401 | stream = &dai->driver->playback; | ||
402 | else | ||
403 | stream = &dai->driver->capture; | ||
404 | |||
405 | /* If the codec specifies any channels at all, it supports the stream */ | ||
406 | return stream->channels_min; | ||
407 | } | ||
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 2790c00735f3..b6378f025836 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -684,8 +684,8 @@ int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, | |||
684 | { | 684 | { |
685 | int ret = 0; | 685 | int ret = 0; |
686 | 686 | ||
687 | if (dapm->set_bias_level) | 687 | if (dapm->component) |
688 | ret = dapm->set_bias_level(dapm, level); | 688 | ret = snd_soc_component_set_bias_level(dapm->component, level); |
689 | 689 | ||
690 | if (ret == 0) | 690 | if (ret == 0) |
691 | dapm->bias_level = level; | 691 | dapm->bias_level = level; |
@@ -1129,6 +1129,34 @@ static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list, | |||
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | /* | 1131 | /* |
1132 | * Recursively reset the cached number of inputs or outputs for the specified | ||
1133 | * widget and all widgets that can be reached via incoming or outcoming paths | ||
1134 | * from the widget. | ||
1135 | */ | ||
1136 | static void invalidate_paths_ep(struct snd_soc_dapm_widget *widget, | ||
1137 | enum snd_soc_dapm_direction dir) | ||
1138 | { | ||
1139 | enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir); | ||
1140 | struct snd_soc_dapm_path *path; | ||
1141 | |||
1142 | widget->endpoints[dir] = -1; | ||
1143 | |||
1144 | snd_soc_dapm_widget_for_each_path(widget, rdir, path) { | ||
1145 | if (path->weak || path->is_supply) | ||
1146 | continue; | ||
1147 | |||
1148 | if (path->walking) | ||
1149 | return; | ||
1150 | |||
1151 | if (path->connect) { | ||
1152 | path->walking = 1; | ||
1153 | invalidate_paths_ep(path->node[dir], dir); | ||
1154 | path->walking = 0; | ||
1155 | } | ||
1156 | } | ||
1157 | } | ||
1158 | |||
1159 | /* | ||
1132 | * Common implementation for is_connected_output_ep() and | 1160 | * Common implementation for is_connected_output_ep() and |
1133 | * is_connected_input_ep(). The function is inlined since the combined size of | 1161 | * is_connected_input_ep(). The function is inlined since the combined size of |
1134 | * the two specialized functions is only marginally larger then the size of the | 1162 | * the two specialized functions is only marginally larger then the size of the |
@@ -1257,21 +1285,17 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, | |||
1257 | 1285 | ||
1258 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 1286 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
1259 | 1287 | ||
1260 | /* | 1288 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
1261 | * For is_connected_{output,input}_ep fully discover the graph we need | 1289 | w = dai->playback_widget; |
1262 | * to reset the cached number of inputs and outputs. | 1290 | invalidate_paths_ep(w, SND_SOC_DAPM_DIR_OUT); |
1263 | */ | 1291 | paths = is_connected_output_ep(w, &widgets, |
1264 | list_for_each_entry(w, &card->widgets, list) { | ||
1265 | w->endpoints[SND_SOC_DAPM_DIR_IN] = -1; | ||
1266 | w->endpoints[SND_SOC_DAPM_DIR_OUT] = -1; | ||
1267 | } | ||
1268 | |||
1269 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
1270 | paths = is_connected_output_ep(dai->playback_widget, &widgets, | ||
1271 | custom_stop_condition); | 1292 | custom_stop_condition); |
1272 | else | 1293 | } else { |
1273 | paths = is_connected_input_ep(dai->capture_widget, &widgets, | 1294 | w = dai->capture_widget; |
1295 | invalidate_paths_ep(w, SND_SOC_DAPM_DIR_IN); | ||
1296 | paths = is_connected_input_ep(w, &widgets, | ||
1274 | custom_stop_condition); | 1297 | custom_stop_condition); |
1298 | } | ||
1275 | 1299 | ||
1276 | /* Drop starting point */ | 1300 | /* Drop starting point */ |
1277 | list_del(widgets.next); | 1301 | list_del(widgets.next); |
@@ -1611,12 +1635,12 @@ static void dapm_seq_run(struct snd_soc_card *card, | |||
1611 | if (!list_empty(&pending)) | 1635 | if (!list_empty(&pending)) |
1612 | dapm_seq_run_coalesced(card, &pending); | 1636 | dapm_seq_run_coalesced(card, &pending); |
1613 | 1637 | ||
1614 | if (cur_dapm && cur_dapm->seq_notifier) { | 1638 | if (cur_dapm && cur_dapm->component) { |
1615 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) | 1639 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) |
1616 | if (sort[i] == cur_sort) | 1640 | if (sort[i] == cur_sort) |
1617 | cur_dapm->seq_notifier(cur_dapm, | 1641 | snd_soc_component_seq_notifier( |
1618 | i, | 1642 | cur_dapm->component, |
1619 | cur_subseq); | 1643 | i, cur_subseq); |
1620 | } | 1644 | } |
1621 | 1645 | ||
1622 | if (cur_dapm && w->dapm != cur_dapm) | 1646 | if (cur_dapm && w->dapm != cur_dapm) |
@@ -1674,11 +1698,12 @@ static void dapm_seq_run(struct snd_soc_card *card, | |||
1674 | if (!list_empty(&pending)) | 1698 | if (!list_empty(&pending)) |
1675 | dapm_seq_run_coalesced(card, &pending); | 1699 | dapm_seq_run_coalesced(card, &pending); |
1676 | 1700 | ||
1677 | if (cur_dapm && cur_dapm->seq_notifier) { | 1701 | if (cur_dapm && cur_dapm->component) { |
1678 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) | 1702 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) |
1679 | if (sort[i] == cur_sort) | 1703 | if (sort[i] == cur_sort) |
1680 | cur_dapm->seq_notifier(cur_dapm, | 1704 | snd_soc_component_seq_notifier( |
1681 | i, cur_subseq); | 1705 | cur_dapm->component, |
1706 | i, cur_subseq); | ||
1682 | } | 1707 | } |
1683 | 1708 | ||
1684 | list_for_each_entry(d, &card->dapm_list, list) { | 1709 | list_for_each_entry(d, &card->dapm_list, list) { |
@@ -1912,6 +1937,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1912 | LIST_HEAD(down_list); | 1937 | LIST_HEAD(down_list); |
1913 | ASYNC_DOMAIN_EXCLUSIVE(async_domain); | 1938 | ASYNC_DOMAIN_EXCLUSIVE(async_domain); |
1914 | enum snd_soc_bias_level bias; | 1939 | enum snd_soc_bias_level bias; |
1940 | int ret; | ||
1915 | 1941 | ||
1916 | lockdep_assert_held(&card->dapm_mutex); | 1942 | lockdep_assert_held(&card->dapm_mutex); |
1917 | 1943 | ||
@@ -2028,8 +2054,12 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
2028 | 2054 | ||
2029 | /* do we need to notify any clients that DAPM event is complete */ | 2055 | /* do we need to notify any clients that DAPM event is complete */ |
2030 | list_for_each_entry(d, &card->dapm_list, list) { | 2056 | list_for_each_entry(d, &card->dapm_list, list) { |
2031 | if (d->stream_event) | 2057 | if (!d->component) |
2032 | d->stream_event(d, event); | 2058 | continue; |
2059 | |||
2060 | ret = snd_soc_component_stream_event(d->component, event); | ||
2061 | if (ret < 0) | ||
2062 | return ret; | ||
2033 | } | 2063 | } |
2034 | 2064 | ||
2035 | pop_dbg(card->dev, card->pop_time, | 2065 | pop_dbg(card->dev, card->pop_time, |
@@ -2154,50 +2184,28 @@ static const struct file_operations dapm_bias_fops = { | |||
2154 | void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, | 2184 | void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, |
2155 | struct dentry *parent) | 2185 | struct dentry *parent) |
2156 | { | 2186 | { |
2157 | struct dentry *d; | ||
2158 | |||
2159 | if (!parent || IS_ERR(parent)) | 2187 | if (!parent || IS_ERR(parent)) |
2160 | return; | 2188 | return; |
2161 | 2189 | ||
2162 | dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); | 2190 | dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); |
2163 | 2191 | ||
2164 | if (IS_ERR(dapm->debugfs_dapm)) { | 2192 | debugfs_create_file("bias_level", 0444, dapm->debugfs_dapm, dapm, |
2165 | dev_warn(dapm->dev, | 2193 | &dapm_bias_fops); |
2166 | "ASoC: Failed to create DAPM debugfs directory %ld\n", | ||
2167 | PTR_ERR(dapm->debugfs_dapm)); | ||
2168 | return; | ||
2169 | } | ||
2170 | |||
2171 | d = debugfs_create_file("bias_level", 0444, | ||
2172 | dapm->debugfs_dapm, dapm, | ||
2173 | &dapm_bias_fops); | ||
2174 | if (IS_ERR(d)) | ||
2175 | dev_warn(dapm->dev, | ||
2176 | "ASoC: Failed to create bias level debugfs file: %ld\n", | ||
2177 | PTR_ERR(d)); | ||
2178 | } | 2194 | } |
2179 | 2195 | ||
2180 | static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) | 2196 | static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) |
2181 | { | 2197 | { |
2182 | struct snd_soc_dapm_context *dapm = w->dapm; | 2198 | struct snd_soc_dapm_context *dapm = w->dapm; |
2183 | struct dentry *d; | ||
2184 | 2199 | ||
2185 | if (!dapm->debugfs_dapm || !w->name) | 2200 | if (!dapm->debugfs_dapm || !w->name) |
2186 | return; | 2201 | return; |
2187 | 2202 | ||
2188 | d = debugfs_create_file(w->name, 0444, | 2203 | debugfs_create_file(w->name, 0444, dapm->debugfs_dapm, w, |
2189 | dapm->debugfs_dapm, w, | 2204 | &dapm_widget_power_fops); |
2190 | &dapm_widget_power_fops); | ||
2191 | if (IS_ERR(d)) | ||
2192 | dev_warn(w->dapm->dev, | ||
2193 | "ASoC: Failed to create %s debugfs file: %ld\n", | ||
2194 | w->name, PTR_ERR(d)); | ||
2195 | } | 2205 | } |
2196 | 2206 | ||
2197 | static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) | 2207 | static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) |
2198 | { | 2208 | { |
2199 | if (!dapm->debugfs_dapm) | ||
2200 | return; | ||
2201 | debugfs_remove_recursive(dapm->debugfs_dapm); | 2209 | debugfs_remove_recursive(dapm->debugfs_dapm); |
2202 | dapm->debugfs_dapm = NULL; | 2210 | dapm->debugfs_dapm = NULL; |
2203 | } | 2211 | } |
@@ -3766,25 +3774,70 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, | |||
3766 | } | 3774 | } |
3767 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); | 3775 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); |
3768 | 3776 | ||
3769 | static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, | 3777 | static int |
3770 | struct snd_kcontrol *kcontrol, int event) | 3778 | snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, |
3779 | struct snd_pcm_substream *substream) | ||
3771 | { | 3780 | { |
3772 | struct snd_soc_dapm_path *path; | 3781 | struct snd_soc_dapm_path *path; |
3773 | struct snd_soc_dai *source, *sink; | 3782 | struct snd_soc_dai *source, *sink; |
3774 | struct snd_soc_pcm_runtime *rtd = w->priv; | 3783 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
3775 | const struct snd_soc_pcm_stream *config; | ||
3776 | struct snd_pcm_substream substream; | ||
3777 | struct snd_pcm_hw_params *params = NULL; | 3784 | struct snd_pcm_hw_params *params = NULL; |
3785 | const struct snd_soc_pcm_stream *config = NULL; | ||
3778 | struct snd_pcm_runtime *runtime = NULL; | 3786 | struct snd_pcm_runtime *runtime = NULL; |
3779 | unsigned int fmt; | 3787 | unsigned int fmt; |
3780 | int ret = 0; | 3788 | int ret = 0; |
3781 | 3789 | ||
3782 | config = rtd->dai_link->params + rtd->params_select; | 3790 | params = kzalloc(sizeof(*params), GFP_KERNEL); |
3791 | if (!params) | ||
3792 | return -ENOMEM; | ||
3783 | 3793 | ||
3784 | if (WARN_ON(!config) || | 3794 | runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); |
3785 | WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || | 3795 | if (!runtime) { |
3786 | list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) | 3796 | ret = -ENOMEM; |
3787 | return -EINVAL; | 3797 | goto out; |
3798 | } | ||
3799 | |||
3800 | substream->runtime = runtime; | ||
3801 | |||
3802 | substream->stream = SNDRV_PCM_STREAM_CAPTURE; | ||
3803 | snd_soc_dapm_widget_for_each_source_path(w, path) { | ||
3804 | source = path->source->priv; | ||
3805 | |||
3806 | ret = snd_soc_dai_startup(source, substream); | ||
3807 | if (ret < 0) { | ||
3808 | dev_err(source->dev, | ||
3809 | "ASoC: startup() failed: %d\n", ret); | ||
3810 | goto out; | ||
3811 | } | ||
3812 | source->active++; | ||
3813 | } | ||
3814 | |||
3815 | substream->stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
3816 | snd_soc_dapm_widget_for_each_sink_path(w, path) { | ||
3817 | sink = path->sink->priv; | ||
3818 | |||
3819 | ret = snd_soc_dai_startup(sink, substream); | ||
3820 | if (ret < 0) { | ||
3821 | dev_err(sink->dev, | ||
3822 | "ASoC: startup() failed: %d\n", ret); | ||
3823 | goto out; | ||
3824 | } | ||
3825 | sink->active++; | ||
3826 | } | ||
3827 | |||
3828 | substream->hw_opened = 1; | ||
3829 | |||
3830 | /* | ||
3831 | * Note: getting the config after .startup() gives a chance to | ||
3832 | * either party on the link to alter the configuration if | ||
3833 | * necessary | ||
3834 | */ | ||
3835 | config = rtd->dai_link->params + rtd->params_select; | ||
3836 | if (WARN_ON(!config)) { | ||
3837 | dev_err(w->dapm->dev, "ASoC: link config missing\n"); | ||
3838 | ret = -EINVAL; | ||
3839 | goto out; | ||
3840 | } | ||
3788 | 3841 | ||
3789 | /* Be a little careful as we don't want to overflow the mask array */ | 3842 | /* Be a little careful as we don't want to overflow the mask array */ |
3790 | if (config->formats) { | 3843 | if (config->formats) { |
@@ -3792,83 +3845,74 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, | |||
3792 | } else { | 3845 | } else { |
3793 | dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n", | 3846 | dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n", |
3794 | config->formats); | 3847 | config->formats); |
3795 | fmt = 0; | ||
3796 | } | ||
3797 | 3848 | ||
3798 | /* Currently very limited parameter selection */ | 3849 | ret = -EINVAL; |
3799 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
3800 | if (!params) { | ||
3801 | ret = -ENOMEM; | ||
3802 | goto out; | 3850 | goto out; |
3803 | } | 3851 | } |
3804 | snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt); | ||
3805 | 3852 | ||
3853 | snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt); | ||
3806 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = | 3854 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = |
3807 | config->rate_min; | 3855 | config->rate_min; |
3808 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max = | 3856 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max = |
3809 | config->rate_max; | 3857 | config->rate_max; |
3810 | |||
3811 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min | 3858 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min |
3812 | = config->channels_min; | 3859 | = config->channels_min; |
3813 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max | 3860 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max |
3814 | = config->channels_max; | 3861 | = config->channels_max; |
3815 | 3862 | ||
3816 | memset(&substream, 0, sizeof(substream)); | 3863 | substream->stream = SNDRV_PCM_STREAM_CAPTURE; |
3864 | snd_soc_dapm_widget_for_each_source_path(w, path) { | ||
3865 | source = path->source->priv; | ||
3817 | 3866 | ||
3818 | /* Allocate a dummy snd_pcm_runtime for startup() and other ops() */ | 3867 | ret = snd_soc_dai_hw_params(source, substream, params); |
3819 | runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); | 3868 | if (ret < 0) |
3820 | if (!runtime) { | 3869 | goto out; |
3821 | ret = -ENOMEM; | 3870 | |
3822 | goto out; | 3871 | dapm_update_dai_unlocked(substream, params, source); |
3823 | } | 3872 | } |
3824 | substream.runtime = runtime; | ||
3825 | substream.private_data = rtd; | ||
3826 | 3873 | ||
3827 | switch (event) { | 3874 | substream->stream = SNDRV_PCM_STREAM_PLAYBACK; |
3828 | case SND_SOC_DAPM_PRE_PMU: | 3875 | snd_soc_dapm_widget_for_each_sink_path(w, path) { |
3829 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; | 3876 | sink = path->sink->priv; |
3830 | snd_soc_dapm_widget_for_each_source_path(w, path) { | ||
3831 | source = path->source->priv; | ||
3832 | 3877 | ||
3833 | if (source->driver->ops->startup) { | 3878 | ret = snd_soc_dai_hw_params(sink, substream, params); |
3834 | ret = source->driver->ops->startup(&substream, | 3879 | if (ret < 0) |
3835 | source); | 3880 | goto out; |
3836 | if (ret < 0) { | ||
3837 | dev_err(source->dev, | ||
3838 | "ASoC: startup() failed: %d\n", | ||
3839 | ret); | ||
3840 | goto out; | ||
3841 | } | ||
3842 | } | ||
3843 | source->active++; | ||
3844 | ret = soc_dai_hw_params(&substream, params, source); | ||
3845 | if (ret < 0) | ||
3846 | goto out; | ||
3847 | 3881 | ||
3848 | dapm_update_dai_unlocked(&substream, params, source); | 3882 | dapm_update_dai_unlocked(substream, params, sink); |
3849 | } | 3883 | } |
3850 | 3884 | ||
3851 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; | 3885 | runtime->format = params_format(params); |
3852 | snd_soc_dapm_widget_for_each_sink_path(w, path) { | 3886 | runtime->subformat = params_subformat(params); |
3853 | sink = path->sink->priv; | 3887 | runtime->channels = params_channels(params); |
3888 | runtime->rate = params_rate(params); | ||
3854 | 3889 | ||
3855 | if (sink->driver->ops->startup) { | 3890 | out: |
3856 | ret = sink->driver->ops->startup(&substream, | 3891 | if (ret < 0) |
3857 | sink); | 3892 | kfree(runtime); |
3858 | if (ret < 0) { | 3893 | |
3859 | dev_err(sink->dev, | 3894 | kfree(params); |
3860 | "ASoC: startup() failed: %d\n", | 3895 | return ret; |
3861 | ret); | 3896 | } |
3862 | goto out; | 3897 | |
3863 | } | 3898 | static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, |
3864 | } | 3899 | struct snd_kcontrol *kcontrol, int event) |
3865 | sink->active++; | 3900 | { |
3866 | ret = soc_dai_hw_params(&substream, params, sink); | 3901 | struct snd_soc_dapm_path *path; |
3867 | if (ret < 0) | 3902 | struct snd_soc_dai *source, *sink; |
3868 | goto out; | 3903 | struct snd_pcm_substream *substream = w->priv; |
3904 | int ret = 0, saved_stream = substream->stream; | ||
3905 | |||
3906 | if (WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || | ||
3907 | list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) | ||
3908 | return -EINVAL; | ||
3909 | |||
3910 | switch (event) { | ||
3911 | case SND_SOC_DAPM_PRE_PMU: | ||
3912 | ret = snd_soc_dai_link_event_pre_pmu(w, substream); | ||
3913 | if (ret < 0) | ||
3914 | goto out; | ||
3869 | 3915 | ||
3870 | dapm_update_dai_unlocked(&substream, params, sink); | ||
3871 | } | ||
3872 | break; | 3916 | break; |
3873 | 3917 | ||
3874 | case SND_SOC_DAPM_POST_PMU: | 3918 | case SND_SOC_DAPM_POST_PMU: |
@@ -3896,41 +3940,45 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, | |||
3896 | ret = 0; | 3940 | ret = 0; |
3897 | } | 3941 | } |
3898 | 3942 | ||
3899 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; | 3943 | substream->stream = SNDRV_PCM_STREAM_CAPTURE; |
3900 | snd_soc_dapm_widget_for_each_source_path(w, path) { | 3944 | snd_soc_dapm_widget_for_each_source_path(w, path) { |
3901 | source = path->source->priv; | 3945 | source = path->source->priv; |
3946 | snd_soc_dai_hw_free(source, substream); | ||
3947 | } | ||
3902 | 3948 | ||
3903 | if (source->driver->ops->hw_free) | 3949 | substream->stream = SNDRV_PCM_STREAM_PLAYBACK; |
3904 | source->driver->ops->hw_free(&substream, | 3950 | snd_soc_dapm_widget_for_each_sink_path(w, path) { |
3905 | source); | 3951 | sink = path->sink->priv; |
3952 | snd_soc_dai_hw_free(sink, substream); | ||
3953 | } | ||
3906 | 3954 | ||
3955 | substream->stream = SNDRV_PCM_STREAM_CAPTURE; | ||
3956 | snd_soc_dapm_widget_for_each_source_path(w, path) { | ||
3957 | source = path->source->priv; | ||
3907 | source->active--; | 3958 | source->active--; |
3908 | if (source->driver->ops->shutdown) | 3959 | snd_soc_dai_shutdown(source, substream); |
3909 | source->driver->ops->shutdown(&substream, | ||
3910 | source); | ||
3911 | } | 3960 | } |
3912 | 3961 | ||
3913 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; | 3962 | substream->stream = SNDRV_PCM_STREAM_PLAYBACK; |
3914 | snd_soc_dapm_widget_for_each_sink_path(w, path) { | 3963 | snd_soc_dapm_widget_for_each_sink_path(w, path) { |
3915 | sink = path->sink->priv; | 3964 | sink = path->sink->priv; |
3916 | |||
3917 | if (sink->driver->ops->hw_free) | ||
3918 | sink->driver->ops->hw_free(&substream, sink); | ||
3919 | |||
3920 | sink->active--; | 3965 | sink->active--; |
3921 | if (sink->driver->ops->shutdown) | 3966 | snd_soc_dai_shutdown(sink, substream); |
3922 | sink->driver->ops->shutdown(&substream, sink); | ||
3923 | } | 3967 | } |
3924 | break; | 3968 | break; |
3925 | 3969 | ||
3970 | case SND_SOC_DAPM_POST_PMD: | ||
3971 | kfree(substream->runtime); | ||
3972 | break; | ||
3973 | |||
3926 | default: | 3974 | default: |
3927 | WARN(1, "Unknown event %d\n", event); | 3975 | WARN(1, "Unknown event %d\n", event); |
3928 | ret = -EINVAL; | 3976 | ret = -EINVAL; |
3929 | } | 3977 | } |
3930 | 3978 | ||
3931 | out: | 3979 | out: |
3932 | kfree(runtime); | 3980 | /* Restore the substream direction */ |
3933 | kfree(params); | 3981 | substream->stream = saved_stream; |
3934 | return ret; | 3982 | return ret; |
3935 | } | 3983 | } |
3936 | 3984 | ||
@@ -4053,10 +4101,11 @@ outfree_w_param: | |||
4053 | } | 4101 | } |
4054 | 4102 | ||
4055 | static struct snd_soc_dapm_widget * | 4103 | static struct snd_soc_dapm_widget * |
4056 | snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, | 4104 | snd_soc_dapm_new_dai(struct snd_soc_card *card, |
4057 | struct snd_soc_dapm_widget *source, | 4105 | struct snd_pcm_substream *substream, |
4058 | struct snd_soc_dapm_widget *sink) | 4106 | char *id) |
4059 | { | 4107 | { |
4108 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
4060 | struct snd_soc_dapm_widget template; | 4109 | struct snd_soc_dapm_widget template; |
4061 | struct snd_soc_dapm_widget *w; | 4110 | struct snd_soc_dapm_widget *w; |
4062 | const char **w_param_text; | 4111 | const char **w_param_text; |
@@ -4065,7 +4114,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, | |||
4065 | int ret; | 4114 | int ret; |
4066 | 4115 | ||
4067 | link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s", | 4116 | link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s", |
4068 | source->name, sink->name); | 4117 | rtd->dai_link->name, id); |
4069 | if (!link_name) | 4118 | if (!link_name) |
4070 | return ERR_PTR(-ENOMEM); | 4119 | return ERR_PTR(-ENOMEM); |
4071 | 4120 | ||
@@ -4075,7 +4124,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, | |||
4075 | template.name = link_name; | 4124 | template.name = link_name; |
4076 | template.event = snd_soc_dai_link_event; | 4125 | template.event = snd_soc_dai_link_event; |
4077 | template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 4126 | template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
4078 | SND_SOC_DAPM_PRE_PMD; | 4127 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD; |
4079 | template.kcontrol_news = NULL; | 4128 | template.kcontrol_news = NULL; |
4080 | 4129 | ||
4081 | /* allocate memory for control, only in case of multiple configs */ | 4130 | /* allocate memory for control, only in case of multiple configs */ |
@@ -4110,7 +4159,7 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, | |||
4110 | goto outfree_kcontrol_news; | 4159 | goto outfree_kcontrol_news; |
4111 | } | 4160 | } |
4112 | 4161 | ||
4113 | w->priv = rtd; | 4162 | w->priv = substream; |
4114 | 4163 | ||
4115 | return w; | 4164 | return w; |
4116 | 4165 | ||
@@ -4232,6 +4281,8 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, | |||
4232 | struct snd_soc_dai *codec_dai; | 4281 | struct snd_soc_dai *codec_dai; |
4233 | struct snd_soc_dapm_widget *playback = NULL, *capture = NULL; | 4282 | struct snd_soc_dapm_widget *playback = NULL, *capture = NULL; |
4234 | struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu; | 4283 | struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu; |
4284 | struct snd_pcm_substream *substream; | ||
4285 | struct snd_pcm_str *streams = rtd->pcm->streams; | ||
4235 | int i; | 4286 | int i; |
4236 | 4287 | ||
4237 | if (rtd->dai_link->params) { | 4288 | if (rtd->dai_link->params) { |
@@ -4245,15 +4296,14 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, | |||
4245 | } | 4296 | } |
4246 | 4297 | ||
4247 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 4298 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
4248 | |||
4249 | /* connect BE DAI playback if widgets are valid */ | 4299 | /* connect BE DAI playback if widgets are valid */ |
4250 | codec = codec_dai->playback_widget; | 4300 | codec = codec_dai->playback_widget; |
4251 | 4301 | ||
4252 | if (playback_cpu && codec) { | 4302 | if (playback_cpu && codec) { |
4253 | if (!playback) { | 4303 | if (!playback) { |
4254 | playback = snd_soc_dapm_new_dai(card, rtd, | 4304 | substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream; |
4255 | playback_cpu, | 4305 | playback = snd_soc_dapm_new_dai(card, substream, |
4256 | codec); | 4306 | "playback"); |
4257 | if (IS_ERR(playback)) { | 4307 | if (IS_ERR(playback)) { |
4258 | dev_err(rtd->dev, | 4308 | dev_err(rtd->dev, |
4259 | "ASoC: Failed to create DAI %s: %ld\n", | 4309 | "ASoC: Failed to create DAI %s: %ld\n", |
@@ -4281,9 +4331,9 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, | |||
4281 | 4331 | ||
4282 | if (codec && capture_cpu) { | 4332 | if (codec && capture_cpu) { |
4283 | if (!capture) { | 4333 | if (!capture) { |
4284 | capture = snd_soc_dapm_new_dai(card, rtd, | 4334 | substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream; |
4285 | codec, | 4335 | capture = snd_soc_dapm_new_dai(card, substream, |
4286 | capture_cpu); | 4336 | "capture"); |
4287 | if (IS_ERR(capture)) { | 4337 | if (IS_ERR(capture)) { |
4288 | dev_err(rtd->dev, | 4338 | dev_err(rtd->dev, |
4289 | "ASoC: Failed to create DAI %s: %ld\n", | 4339 | "ASoC: Failed to create DAI %s: %ld\n", |
@@ -4667,6 +4717,27 @@ void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) | |||
4667 | } | 4717 | } |
4668 | EXPORT_SYMBOL_GPL(snd_soc_dapm_free); | 4718 | EXPORT_SYMBOL_GPL(snd_soc_dapm_free); |
4669 | 4719 | ||
4720 | void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, | ||
4721 | struct snd_soc_card *card, | ||
4722 | struct snd_soc_component *component) | ||
4723 | { | ||
4724 | dapm->card = card; | ||
4725 | dapm->component = component; | ||
4726 | dapm->bias_level = SND_SOC_BIAS_OFF; | ||
4727 | |||
4728 | if (component) { | ||
4729 | dapm->dev = component->dev; | ||
4730 | dapm->idle_bias_off = !component->driver->idle_bias_on, | ||
4731 | dapm->suspend_bias_off = component->driver->suspend_bias_off; | ||
4732 | } else { | ||
4733 | dapm->dev = card->dev; | ||
4734 | } | ||
4735 | |||
4736 | INIT_LIST_HEAD(&dapm->list); | ||
4737 | list_add(&dapm->list, &card->dapm_list); | ||
4738 | } | ||
4739 | EXPORT_SYMBOL_GPL(snd_soc_dapm_init); | ||
4740 | |||
4670 | static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) | 4741 | static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) |
4671 | { | 4742 | { |
4672 | struct snd_soc_card *card = dapm->card; | 4743 | struct snd_soc_card *card = dapm->card; |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index c7b990abdbaa..a71d2340eb05 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -24,24 +24,6 @@ struct jack_gpio_tbl { | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | /** | 26 | /** |
27 | * snd_soc_component_set_jack - configure component jack. | ||
28 | * @component: COMPONENTs | ||
29 | * @jack: structure to use for the jack | ||
30 | * @data: can be used if codec driver need extra data for configuring jack | ||
31 | * | ||
32 | * Configures and enables jack detection function. | ||
33 | */ | ||
34 | int snd_soc_component_set_jack(struct snd_soc_component *component, | ||
35 | struct snd_soc_jack *jack, void *data) | ||
36 | { | ||
37 | if (component->driver->set_jack) | ||
38 | return component->driver->set_jack(component, jack, data); | ||
39 | |||
40 | return -ENOTSUPP; | ||
41 | } | ||
42 | EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); | ||
43 | |||
44 | /** | ||
45 | * snd_soc_card_jack_new - Create a new jack | 27 | * snd_soc_card_jack_new - Create a new jack |
46 | * @card: ASoC card | 28 | * @card: ASoC card |
47 | * @id: an identifying string for this jack | 29 | * @id: an identifying string for this jack |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4878d22ebd8c..e163dde5eab1 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/pinctrl/consumer.h> | 16 | #include <linux/pinctrl/consumer.h> |
17 | #include <linux/pm_runtime.h> | 17 | #include <linux/pm_runtime.h> |
18 | #include <linux/module.h> | ||
19 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
20 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
21 | #include <linux/export.h> | 20 | #include <linux/export.h> |
@@ -29,24 +28,6 @@ | |||
29 | 28 | ||
30 | #define DPCM_MAX_BE_USERS 8 | 29 | #define DPCM_MAX_BE_USERS 8 |
31 | 30 | ||
32 | /* | ||
33 | * snd_soc_dai_stream_valid() - check if a DAI supports the given stream | ||
34 | * | ||
35 | * Returns true if the DAI supports the indicated stream type. | ||
36 | */ | ||
37 | static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream) | ||
38 | { | ||
39 | struct snd_soc_pcm_stream *codec_stream; | ||
40 | |||
41 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
42 | codec_stream = &dai->driver->playback; | ||
43 | else | ||
44 | codec_stream = &dai->driver->capture; | ||
45 | |||
46 | /* If the codec specifies any channels at all, it supports the stream */ | ||
47 | return codec_stream->channels_min; | ||
48 | } | ||
49 | |||
50 | /** | 31 | /** |
51 | * snd_soc_runtime_activate() - Increment active count for PCM runtime components | 32 | * snd_soc_runtime_activate() - Increment active count for PCM runtime components |
52 | * @rtd: ASoC PCM runtime that is activated | 33 | * @rtd: ASoC PCM runtime that is activated |
@@ -55,7 +36,7 @@ static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream) | |||
55 | * Increments the active count for all the DAIs and components attached to a PCM | 36 | * Increments the active count for all the DAIs and components attached to a PCM |
56 | * runtime. Should typically be called when a stream is opened. | 37 | * runtime. Should typically be called when a stream is opened. |
57 | * | 38 | * |
58 | * Must be called with the rtd->pcm_mutex being held | 39 | * Must be called with the rtd->card->pcm_mutex being held |
59 | */ | 40 | */ |
60 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | 41 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) |
61 | { | 42 | { |
@@ -63,7 +44,7 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
63 | struct snd_soc_dai *codec_dai; | 44 | struct snd_soc_dai *codec_dai; |
64 | int i; | 45 | int i; |
65 | 46 | ||
66 | lockdep_assert_held(&rtd->pcm_mutex); | 47 | lockdep_assert_held(&rtd->card->pcm_mutex); |
67 | 48 | ||
68 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 49 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
69 | cpu_dai->playback_active++; | 50 | cpu_dai->playback_active++; |
@@ -91,7 +72,7 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
91 | * Decrements the active count for all the DAIs and components attached to a PCM | 72 | * Decrements the active count for all the DAIs and components attached to a PCM |
92 | * runtime. Should typically be called when a stream is closed. | 73 | * runtime. Should typically be called when a stream is closed. |
93 | * | 74 | * |
94 | * Must be called with the rtd->pcm_mutex being held | 75 | * Must be called with the rtd->card->pcm_mutex being held |
95 | */ | 76 | */ |
96 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | 77 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) |
97 | { | 78 | { |
@@ -99,7 +80,7 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
99 | struct snd_soc_dai *codec_dai; | 80 | struct snd_soc_dai *codec_dai; |
100 | int i; | 81 | int i; |
101 | 82 | ||
102 | lockdep_assert_held(&rtd->pcm_mutex); | 83 | lockdep_assert_held(&rtd->card->pcm_mutex); |
103 | 84 | ||
104 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 85 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
105 | cpu_dai->playback_active--; | 86 | cpu_dai->playback_active--; |
@@ -458,19 +439,15 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream, | |||
458 | component = rtdcom->component; | 439 | component = rtdcom->component; |
459 | *last = component; | 440 | *last = component; |
460 | 441 | ||
461 | if (component->driver->module_get_upon_open && | 442 | ret = snd_soc_component_module_get_when_open(component); |
462 | !try_module_get(component->dev->driver->owner)) { | 443 | if (ret < 0) { |
463 | dev_err(component->dev, | 444 | dev_err(component->dev, |
464 | "ASoC: can't get module %s\n", | 445 | "ASoC: can't get module %s\n", |
465 | component->name); | 446 | component->name); |
466 | return -ENODEV; | 447 | return ret; |
467 | } | 448 | } |
468 | 449 | ||
469 | if (!component->driver->ops || | 450 | ret = snd_soc_component_open(component, substream); |
470 | !component->driver->ops->open) | ||
471 | continue; | ||
472 | |||
473 | ret = component->driver->ops->open(substream); | ||
474 | if (ret < 0) { | 451 | if (ret < 0) { |
475 | dev_err(component->dev, | 452 | dev_err(component->dev, |
476 | "ASoC: can't open component %s: %d\n", | 453 | "ASoC: can't open component %s: %d\n", |
@@ -488,6 +465,7 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, | |||
488 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 465 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
489 | struct snd_soc_rtdcom_list *rtdcom; | 466 | struct snd_soc_rtdcom_list *rtdcom; |
490 | struct snd_soc_component *component; | 467 | struct snd_soc_component *component; |
468 | int ret = 0; | ||
491 | 469 | ||
492 | for_each_rtdcom(rtd, rtdcom) { | 470 | for_each_rtdcom(rtd, rtdcom) { |
493 | component = rtdcom->component; | 471 | component = rtdcom->component; |
@@ -495,15 +473,11 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, | |||
495 | if (component == last) | 473 | if (component == last) |
496 | break; | 474 | break; |
497 | 475 | ||
498 | if (component->driver->ops && | 476 | ret |= snd_soc_component_close(component, substream); |
499 | component->driver->ops->close) | 477 | snd_soc_component_module_put_when_close(component); |
500 | component->driver->ops->close(substream); | ||
501 | |||
502 | if (component->driver->module_get_upon_open) | ||
503 | module_put(component->dev->driver->owner); | ||
504 | } | 478 | } |
505 | 479 | ||
506 | return 0; | 480 | return ret; |
507 | } | 481 | } |
508 | 482 | ||
509 | /* | 483 | /* |
@@ -532,16 +506,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
532 | pm_runtime_get_sync(component->dev); | 506 | pm_runtime_get_sync(component->dev); |
533 | } | 507 | } |
534 | 508 | ||
535 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 509 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
536 | 510 | ||
537 | /* startup the audio subsystem */ | 511 | /* startup the audio subsystem */ |
538 | if (cpu_dai->driver->ops->startup) { | 512 | ret = snd_soc_dai_startup(cpu_dai, substream); |
539 | ret = cpu_dai->driver->ops->startup(substream, cpu_dai); | 513 | if (ret < 0) { |
540 | if (ret < 0) { | 514 | dev_err(cpu_dai->dev, "ASoC: can't open interface %s: %d\n", |
541 | dev_err(cpu_dai->dev, "ASoC: can't open interface" | 515 | cpu_dai->name, ret); |
542 | " %s: %d\n", cpu_dai->name, ret); | 516 | goto out; |
543 | goto out; | ||
544 | } | ||
545 | } | 517 | } |
546 | 518 | ||
547 | ret = soc_pcm_components_open(substream, &component); | 519 | ret = soc_pcm_components_open(substream, &component); |
@@ -549,15 +521,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
549 | goto component_err; | 521 | goto component_err; |
550 | 522 | ||
551 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 523 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
552 | if (codec_dai->driver->ops->startup) { | 524 | ret = snd_soc_dai_startup(codec_dai, substream); |
553 | ret = codec_dai->driver->ops->startup(substream, | 525 | if (ret < 0) { |
554 | codec_dai); | 526 | dev_err(codec_dai->dev, |
555 | if (ret < 0) { | 527 | "ASoC: can't open codec %s: %d\n", |
556 | dev_err(codec_dai->dev, | 528 | codec_dai->name, ret); |
557 | "ASoC: can't open codec %s: %d\n", | 529 | goto codec_dai_err; |
558 | codec_dai->name, ret); | ||
559 | goto codec_dai_err; | ||
560 | } | ||
561 | } | 530 | } |
562 | 531 | ||
563 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 532 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -635,7 +604,7 @@ dynamic: | |||
635 | 604 | ||
636 | snd_soc_runtime_activate(rtd, substream->stream); | 605 | snd_soc_runtime_activate(rtd, substream->stream); |
637 | 606 | ||
638 | mutex_unlock(&rtd->pcm_mutex); | 607 | mutex_unlock(&rtd->card->pcm_mutex); |
639 | return 0; | 608 | return 0; |
640 | 609 | ||
641 | config_err: | 610 | config_err: |
@@ -646,18 +615,15 @@ machine_err: | |||
646 | i = rtd->num_codecs; | 615 | i = rtd->num_codecs; |
647 | 616 | ||
648 | codec_dai_err: | 617 | codec_dai_err: |
649 | for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) { | 618 | for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) |
650 | if (codec_dai->driver->ops->shutdown) | 619 | snd_soc_dai_shutdown(codec_dai, substream); |
651 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
652 | } | ||
653 | 620 | ||
654 | component_err: | 621 | component_err: |
655 | soc_pcm_components_close(substream, component); | 622 | soc_pcm_components_close(substream, component); |
656 | 623 | ||
657 | if (cpu_dai->driver->ops->shutdown) | 624 | snd_soc_dai_shutdown(cpu_dai, substream); |
658 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | ||
659 | out: | 625 | out: |
660 | mutex_unlock(&rtd->pcm_mutex); | 626 | mutex_unlock(&rtd->card->pcm_mutex); |
661 | 627 | ||
662 | for_each_rtdcom(rtd, rtdcom) { | 628 | for_each_rtdcom(rtd, rtdcom) { |
663 | component = rtdcom->component; | 629 | component = rtdcom->component; |
@@ -687,7 +653,7 @@ static void close_delayed_work(struct work_struct *work) | |||
687 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | 653 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); |
688 | struct snd_soc_dai *codec_dai = rtd->codec_dais[0]; | 654 | struct snd_soc_dai *codec_dai = rtd->codec_dais[0]; |
689 | 655 | ||
690 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 656 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
691 | 657 | ||
692 | dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", | 658 | dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", |
693 | codec_dai->driver->playback.stream_name, | 659 | codec_dai->driver->playback.stream_name, |
@@ -701,7 +667,17 @@ static void close_delayed_work(struct work_struct *work) | |||
701 | SND_SOC_DAPM_STREAM_STOP); | 667 | SND_SOC_DAPM_STREAM_STOP); |
702 | } | 668 | } |
703 | 669 | ||
704 | mutex_unlock(&rtd->pcm_mutex); | 670 | mutex_unlock(&rtd->card->pcm_mutex); |
671 | } | ||
672 | |||
673 | static void codec2codec_close_delayed_work(struct work_struct *work) | ||
674 | { | ||
675 | /* | ||
676 | * Currently nothing to do for c2c links | ||
677 | * Since c2c links are internal nodes in the DAPM graph and | ||
678 | * don't interface with the outside world or application layer | ||
679 | * we don't have to do any special handling on close. | ||
680 | */ | ||
705 | } | 681 | } |
706 | 682 | ||
707 | /* | 683 | /* |
@@ -718,7 +694,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
718 | struct snd_soc_dai *codec_dai; | 694 | struct snd_soc_dai *codec_dai; |
719 | int i; | 695 | int i; |
720 | 696 | ||
721 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 697 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
722 | 698 | ||
723 | snd_soc_runtime_deactivate(rtd, substream->stream); | 699 | snd_soc_runtime_deactivate(rtd, substream->stream); |
724 | 700 | ||
@@ -733,13 +709,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
733 | 709 | ||
734 | snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); | 710 | snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); |
735 | 711 | ||
736 | if (cpu_dai->driver->ops->shutdown) | 712 | snd_soc_dai_shutdown(cpu_dai, substream); |
737 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | ||
738 | 713 | ||
739 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 714 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
740 | if (codec_dai->driver->ops->shutdown) | 715 | snd_soc_dai_shutdown(codec_dai, substream); |
741 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
742 | } | ||
743 | 716 | ||
744 | if (rtd->dai_link->ops->shutdown) | 717 | if (rtd->dai_link->ops->shutdown) |
745 | rtd->dai_link->ops->shutdown(substream); | 718 | rtd->dai_link->ops->shutdown(substream); |
@@ -765,7 +738,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
765 | SND_SOC_DAPM_STREAM_STOP); | 738 | SND_SOC_DAPM_STREAM_STOP); |
766 | } | 739 | } |
767 | 740 | ||
768 | mutex_unlock(&rtd->pcm_mutex); | 741 | mutex_unlock(&rtd->card->pcm_mutex); |
769 | 742 | ||
770 | for_each_rtdcom(rtd, rtdcom) { | 743 | for_each_rtdcom(rtd, rtdcom) { |
771 | component = rtdcom->component; | 744 | component = rtdcom->component; |
@@ -798,7 +771,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
798 | struct snd_soc_dai *codec_dai; | 771 | struct snd_soc_dai *codec_dai; |
799 | int i, ret = 0; | 772 | int i, ret = 0; |
800 | 773 | ||
801 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 774 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
802 | 775 | ||
803 | if (rtd->dai_link->ops->prepare) { | 776 | if (rtd->dai_link->ops->prepare) { |
804 | ret = rtd->dai_link->ops->prepare(substream); | 777 | ret = rtd->dai_link->ops->prepare(substream); |
@@ -812,11 +785,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
812 | for_each_rtdcom(rtd, rtdcom) { | 785 | for_each_rtdcom(rtd, rtdcom) { |
813 | component = rtdcom->component; | 786 | component = rtdcom->component; |
814 | 787 | ||
815 | if (!component->driver->ops || | 788 | ret = snd_soc_component_prepare(component, substream); |
816 | !component->driver->ops->prepare) | ||
817 | continue; | ||
818 | |||
819 | ret = component->driver->ops->prepare(substream); | ||
820 | if (ret < 0) { | 789 | if (ret < 0) { |
821 | dev_err(component->dev, | 790 | dev_err(component->dev, |
822 | "ASoC: platform prepare error: %d\n", ret); | 791 | "ASoC: platform prepare error: %d\n", ret); |
@@ -825,27 +794,22 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
825 | } | 794 | } |
826 | 795 | ||
827 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 796 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
828 | if (codec_dai->driver->ops->prepare) { | 797 | ret = snd_soc_dai_prepare(codec_dai, substream); |
829 | ret = codec_dai->driver->ops->prepare(substream, | ||
830 | codec_dai); | ||
831 | if (ret < 0) { | ||
832 | dev_err(codec_dai->dev, | ||
833 | "ASoC: codec DAI prepare error: %d\n", | ||
834 | ret); | ||
835 | goto out; | ||
836 | } | ||
837 | } | ||
838 | } | ||
839 | |||
840 | if (cpu_dai->driver->ops->prepare) { | ||
841 | ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); | ||
842 | if (ret < 0) { | 798 | if (ret < 0) { |
843 | dev_err(cpu_dai->dev, | 799 | dev_err(codec_dai->dev, |
844 | "ASoC: cpu DAI prepare error: %d\n", ret); | 800 | "ASoC: codec DAI prepare error: %d\n", |
801 | ret); | ||
845 | goto out; | 802 | goto out; |
846 | } | 803 | } |
847 | } | 804 | } |
848 | 805 | ||
806 | ret = snd_soc_dai_prepare(cpu_dai, substream); | ||
807 | if (ret < 0) { | ||
808 | dev_err(cpu_dai->dev, | ||
809 | "ASoC: cpu DAI prepare error: %d\n", ret); | ||
810 | goto out; | ||
811 | } | ||
812 | |||
849 | /* cancel any delayed stream shutdown that is pending */ | 813 | /* cancel any delayed stream shutdown that is pending */ |
850 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 814 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
851 | rtd->pop_wait) { | 815 | rtd->pop_wait) { |
@@ -862,7 +826,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
862 | snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); | 826 | snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); |
863 | 827 | ||
864 | out: | 828 | out: |
865 | mutex_unlock(&rtd->pcm_mutex); | 829 | mutex_unlock(&rtd->card->pcm_mutex); |
866 | return ret; | 830 | return ret; |
867 | } | 831 | } |
868 | 832 | ||
@@ -877,42 +841,13 @@ static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params, | |||
877 | interval->max = channels; | 841 | interval->max = channels; |
878 | } | 842 | } |
879 | 843 | ||
880 | int soc_dai_hw_params(struct snd_pcm_substream *substream, | ||
881 | struct snd_pcm_hw_params *params, | ||
882 | struct snd_soc_dai *dai) | ||
883 | { | ||
884 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
885 | int ret; | ||
886 | |||
887 | /* perform any topology hw_params fixups before DAI */ | ||
888 | if (rtd->dai_link->be_hw_params_fixup) { | ||
889 | ret = rtd->dai_link->be_hw_params_fixup(rtd, params); | ||
890 | if (ret < 0) { | ||
891 | dev_err(rtd->dev, | ||
892 | "ASoC: hw_params topology fixup failed %d\n", | ||
893 | ret); | ||
894 | return ret; | ||
895 | } | ||
896 | } | ||
897 | |||
898 | if (dai->driver->ops->hw_params) { | ||
899 | ret = dai->driver->ops->hw_params(substream, params, dai); | ||
900 | if (ret < 0) { | ||
901 | dev_err(dai->dev, "ASoC: can't set %s hw params: %d\n", | ||
902 | dai->name, ret); | ||
903 | return ret; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, | 844 | static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, |
911 | struct snd_soc_component *last) | 845 | struct snd_soc_component *last) |
912 | { | 846 | { |
913 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 847 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
914 | struct snd_soc_rtdcom_list *rtdcom; | 848 | struct snd_soc_rtdcom_list *rtdcom; |
915 | struct snd_soc_component *component; | 849 | struct snd_soc_component *component; |
850 | int ret = 0; | ||
916 | 851 | ||
917 | for_each_rtdcom(rtd, rtdcom) { | 852 | for_each_rtdcom(rtd, rtdcom) { |
918 | component = rtdcom->component; | 853 | component = rtdcom->component; |
@@ -920,14 +855,10 @@ static int soc_pcm_components_hw_free(struct snd_pcm_substream *substream, | |||
920 | if (component == last) | 855 | if (component == last) |
921 | break; | 856 | break; |
922 | 857 | ||
923 | if (!component->driver->ops || | 858 | ret |= snd_soc_component_hw_free(component, substream); |
924 | !component->driver->ops->hw_free) | ||
925 | continue; | ||
926 | |||
927 | component->driver->ops->hw_free(substream); | ||
928 | } | 859 | } |
929 | 860 | ||
930 | return 0; | 861 | return ret; |
931 | } | 862 | } |
932 | 863 | ||
933 | /* | 864 | /* |
@@ -945,7 +876,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
945 | struct snd_soc_dai *codec_dai; | 876 | struct snd_soc_dai *codec_dai; |
946 | int i, ret = 0; | 877 | int i, ret = 0; |
947 | 878 | ||
948 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 879 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
949 | if (rtd->dai_link->ops->hw_params) { | 880 | if (rtd->dai_link->ops->hw_params) { |
950 | ret = rtd->dai_link->ops->hw_params(substream, params); | 881 | ret = rtd->dai_link->ops->hw_params(substream, params); |
951 | if (ret < 0) { | 882 | if (ret < 0) { |
@@ -989,7 +920,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
989 | soc_pcm_codec_params_fixup(&codec_params, | 920 | soc_pcm_codec_params_fixup(&codec_params, |
990 | codec_dai->rx_mask); | 921 | codec_dai->rx_mask); |
991 | 922 | ||
992 | ret = soc_dai_hw_params(substream, &codec_params, codec_dai); | 923 | ret = snd_soc_dai_hw_params(codec_dai, substream, |
924 | &codec_params); | ||
993 | if(ret < 0) | 925 | if(ret < 0) |
994 | goto codec_err; | 926 | goto codec_err; |
995 | 927 | ||
@@ -1001,7 +933,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1001 | snd_soc_dapm_update_dai(substream, &codec_params, codec_dai); | 933 | snd_soc_dapm_update_dai(substream, &codec_params, codec_dai); |
1002 | } | 934 | } |
1003 | 935 | ||
1004 | ret = soc_dai_hw_params(substream, params, cpu_dai); | 936 | ret = snd_soc_dai_hw_params(cpu_dai, substream, params); |
1005 | if (ret < 0) | 937 | if (ret < 0) |
1006 | goto interface_err; | 938 | goto interface_err; |
1007 | 939 | ||
@@ -1016,11 +948,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1016 | for_each_rtdcom(rtd, rtdcom) { | 948 | for_each_rtdcom(rtd, rtdcom) { |
1017 | component = rtdcom->component; | 949 | component = rtdcom->component; |
1018 | 950 | ||
1019 | if (!component->driver->ops || | 951 | ret = snd_soc_component_hw_params(component, substream, params); |
1020 | !component->driver->ops->hw_params) | ||
1021 | continue; | ||
1022 | |||
1023 | ret = component->driver->ops->hw_params(substream, params); | ||
1024 | if (ret < 0) { | 952 | if (ret < 0) { |
1025 | dev_err(component->dev, | 953 | dev_err(component->dev, |
1026 | "ASoC: %s hw params failed: %d\n", | 954 | "ASoC: %s hw params failed: %d\n", |
@@ -1034,14 +962,13 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1034 | if (ret) | 962 | if (ret) |
1035 | goto component_err; | 963 | goto component_err; |
1036 | out: | 964 | out: |
1037 | mutex_unlock(&rtd->pcm_mutex); | 965 | mutex_unlock(&rtd->card->pcm_mutex); |
1038 | return ret; | 966 | return ret; |
1039 | 967 | ||
1040 | component_err: | 968 | component_err: |
1041 | soc_pcm_components_hw_free(substream, component); | 969 | soc_pcm_components_hw_free(substream, component); |
1042 | 970 | ||
1043 | if (cpu_dai->driver->ops->hw_free) | 971 | snd_soc_dai_hw_free(cpu_dai, substream); |
1044 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | ||
1045 | cpu_dai->rate = 0; | 972 | cpu_dai->rate = 0; |
1046 | 973 | ||
1047 | interface_err: | 974 | interface_err: |
@@ -1052,15 +979,14 @@ codec_err: | |||
1052 | if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) | 979 | if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) |
1053 | continue; | 980 | continue; |
1054 | 981 | ||
1055 | if (codec_dai->driver->ops->hw_free) | 982 | snd_soc_dai_hw_free(codec_dai, substream); |
1056 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
1057 | codec_dai->rate = 0; | 983 | codec_dai->rate = 0; |
1058 | } | 984 | } |
1059 | 985 | ||
1060 | if (rtd->dai_link->ops->hw_free) | 986 | if (rtd->dai_link->ops->hw_free) |
1061 | rtd->dai_link->ops->hw_free(substream); | 987 | rtd->dai_link->ops->hw_free(substream); |
1062 | 988 | ||
1063 | mutex_unlock(&rtd->pcm_mutex); | 989 | mutex_unlock(&rtd->card->pcm_mutex); |
1064 | return ret; | 990 | return ret; |
1065 | } | 991 | } |
1066 | 992 | ||
@@ -1075,7 +1001,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1075 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 1001 | bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
1076 | int i; | 1002 | int i; |
1077 | 1003 | ||
1078 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 1004 | mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); |
1079 | 1005 | ||
1080 | /* clear the corresponding DAIs parameters when going to be inactive */ | 1006 | /* clear the corresponding DAIs parameters when going to be inactive */ |
1081 | if (cpu_dai->active == 1) { | 1007 | if (cpu_dai->active == 1) { |
@@ -1112,14 +1038,12 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1112 | if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) | 1038 | if (!snd_soc_dai_stream_valid(codec_dai, substream->stream)) |
1113 | continue; | 1039 | continue; |
1114 | 1040 | ||
1115 | if (codec_dai->driver->ops->hw_free) | 1041 | snd_soc_dai_hw_free(codec_dai, substream); |
1116 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
1117 | } | 1042 | } |
1118 | 1043 | ||
1119 | if (cpu_dai->driver->ops->hw_free) | 1044 | snd_soc_dai_hw_free(cpu_dai, substream); |
1120 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | ||
1121 | 1045 | ||
1122 | mutex_unlock(&rtd->pcm_mutex); | 1046 | mutex_unlock(&rtd->card->pcm_mutex); |
1123 | return 0; | 1047 | return 0; |
1124 | } | 1048 | } |
1125 | 1049 | ||
@@ -1133,31 +1057,22 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1133 | int i, ret; | 1057 | int i, ret; |
1134 | 1058 | ||
1135 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 1059 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1136 | if (codec_dai->driver->ops->trigger) { | 1060 | ret = snd_soc_dai_trigger(codec_dai, substream, cmd); |
1137 | ret = codec_dai->driver->ops->trigger(substream, | 1061 | if (ret < 0) |
1138 | cmd, codec_dai); | 1062 | return ret; |
1139 | if (ret < 0) | ||
1140 | return ret; | ||
1141 | } | ||
1142 | } | 1063 | } |
1143 | 1064 | ||
1144 | for_each_rtdcom(rtd, rtdcom) { | 1065 | for_each_rtdcom(rtd, rtdcom) { |
1145 | component = rtdcom->component; | 1066 | component = rtdcom->component; |
1146 | 1067 | ||
1147 | if (!component->driver->ops || | 1068 | ret = snd_soc_component_trigger(component, substream, cmd); |
1148 | !component->driver->ops->trigger) | ||
1149 | continue; | ||
1150 | |||
1151 | ret = component->driver->ops->trigger(substream, cmd); | ||
1152 | if (ret < 0) | 1069 | if (ret < 0) |
1153 | return ret; | 1070 | return ret; |
1154 | } | 1071 | } |
1155 | 1072 | ||
1156 | if (cpu_dai->driver->ops->trigger) { | 1073 | snd_soc_dai_trigger(cpu_dai, substream, cmd); |
1157 | ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); | 1074 | if (ret < 0) |
1158 | if (ret < 0) | 1075 | return ret; |
1159 | return ret; | ||
1160 | } | ||
1161 | 1076 | ||
1162 | if (rtd->dai_link->ops->trigger) { | 1077 | if (rtd->dai_link->ops->trigger) { |
1163 | ret = rtd->dai_link->ops->trigger(substream, cmd); | 1078 | ret = rtd->dai_link->ops->trigger(substream, cmd); |
@@ -1177,19 +1092,15 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
1177 | int i, ret; | 1092 | int i, ret; |
1178 | 1093 | ||
1179 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 1094 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1180 | if (codec_dai->driver->ops->bespoke_trigger) { | 1095 | ret = snd_soc_dai_bespoke_trigger(codec_dai, substream, cmd); |
1181 | ret = codec_dai->driver->ops->bespoke_trigger(substream, | ||
1182 | cmd, codec_dai); | ||
1183 | if (ret < 0) | ||
1184 | return ret; | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | if (cpu_dai->driver->ops->bespoke_trigger) { | ||
1189 | ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai); | ||
1190 | if (ret < 0) | 1096 | if (ret < 0) |
1191 | return ret; | 1097 | return ret; |
1192 | } | 1098 | } |
1099 | |||
1100 | snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd); | ||
1101 | if (ret < 0) | ||
1102 | return ret; | ||
1103 | |||
1193 | return 0; | 1104 | return 0; |
1194 | } | 1105 | } |
1195 | /* | 1106 | /* |
@@ -1200,8 +1111,6 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
1200 | static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | 1111 | static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) |
1201 | { | 1112 | { |
1202 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1113 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1203 | struct snd_soc_component *component; | ||
1204 | struct snd_soc_rtdcom_list *rtdcom; | ||
1205 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1114 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1206 | struct snd_soc_dai *codec_dai; | 1115 | struct snd_soc_dai *codec_dai; |
1207 | struct snd_pcm_runtime *runtime = substream->runtime; | 1116 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -1213,28 +1122,16 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
1213 | /* clearing the previous total delay */ | 1122 | /* clearing the previous total delay */ |
1214 | runtime->delay = 0; | 1123 | runtime->delay = 0; |
1215 | 1124 | ||
1216 | for_each_rtdcom(rtd, rtdcom) { | 1125 | offset = snd_soc_pcm_component_pointer(substream); |
1217 | component = rtdcom->component; | ||
1218 | |||
1219 | if (!component->driver->ops || | ||
1220 | !component->driver->ops->pointer) | ||
1221 | continue; | ||
1222 | 1126 | ||
1223 | /* FIXME: use 1st pointer */ | ||
1224 | offset = component->driver->ops->pointer(substream); | ||
1225 | break; | ||
1226 | } | ||
1227 | /* base delay if assigned in pointer callback */ | 1127 | /* base delay if assigned in pointer callback */ |
1228 | delay = runtime->delay; | 1128 | delay = runtime->delay; |
1229 | 1129 | ||
1230 | if (cpu_dai->driver->ops->delay) | 1130 | delay += snd_soc_dai_delay(cpu_dai, substream); |
1231 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); | ||
1232 | 1131 | ||
1233 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 1132 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1234 | if (codec_dai->driver->ops->delay) | 1133 | codec_delay = max(codec_delay, |
1235 | codec_delay = max(codec_delay, | 1134 | snd_soc_dai_delay(codec_dai, substream)); |
1236 | codec_dai->driver->ops->delay(substream, | ||
1237 | codec_dai)); | ||
1238 | } | 1135 | } |
1239 | delay += codec_delay; | 1136 | delay += codec_delay; |
1240 | 1137 | ||
@@ -1274,9 +1171,9 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, | |||
1274 | stream ? "<-" : "->", be->dai_link->name); | 1171 | stream ? "<-" : "->", be->dai_link->name); |
1275 | 1172 | ||
1276 | #ifdef CONFIG_DEBUG_FS | 1173 | #ifdef CONFIG_DEBUG_FS |
1277 | if (fe->debugfs_dpcm_root) | 1174 | dpcm->debugfs_state = debugfs_create_dir(be->dai_link->name, |
1278 | dpcm->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644, | 1175 | fe->debugfs_dpcm_root); |
1279 | fe->debugfs_dpcm_root, &dpcm->state); | 1176 | debugfs_create_u32("state", 0644, dpcm->debugfs_state, &dpcm->state); |
1280 | #endif | 1177 | #endif |
1281 | return 1; | 1178 | return 1; |
1282 | } | 1179 | } |
@@ -1331,7 +1228,7 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) | |||
1331 | dpcm_be_reparent(fe, dpcm->be, stream); | 1228 | dpcm_be_reparent(fe, dpcm->be, stream); |
1332 | 1229 | ||
1333 | #ifdef CONFIG_DEBUG_FS | 1230 | #ifdef CONFIG_DEBUG_FS |
1334 | debugfs_remove(dpcm->debugfs_state); | 1231 | debugfs_remove_recursive(dpcm->debugfs_state); |
1335 | #endif | 1232 | #endif |
1336 | spin_lock_irqsave(&fe->card->dpcm_lock, flags); | 1233 | spin_lock_irqsave(&fe->card->dpcm_lock, flags); |
1337 | list_del(&dpcm->list_be); | 1234 | list_del(&dpcm->list_be); |
@@ -2556,27 +2453,6 @@ out: | |||
2556 | return ret; | 2453 | return ret; |
2557 | } | 2454 | } |
2558 | 2455 | ||
2559 | static int soc_pcm_ioctl(struct snd_pcm_substream *substream, | ||
2560 | unsigned int cmd, void *arg) | ||
2561 | { | ||
2562 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
2563 | struct snd_soc_component *component; | ||
2564 | struct snd_soc_rtdcom_list *rtdcom; | ||
2565 | |||
2566 | for_each_rtdcom(rtd, rtdcom) { | ||
2567 | component = rtdcom->component; | ||
2568 | |||
2569 | if (!component->driver->ops || | ||
2570 | !component->driver->ops->ioctl) | ||
2571 | continue; | ||
2572 | |||
2573 | /* FIXME: use 1st ioctl */ | ||
2574 | return component->driver->ops->ioctl(substream, cmd, arg); | ||
2575 | } | ||
2576 | |||
2577 | return snd_pcm_lib_ioctl(substream, cmd, arg); | ||
2578 | } | ||
2579 | |||
2580 | static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) | 2456 | static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) |
2581 | { | 2457 | { |
2582 | struct snd_pcm_substream *substream = | 2458 | struct snd_pcm_substream *substream = |
@@ -2749,8 +2625,8 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) | |||
2749 | new ? "new" : "old", fe->dai_link->name); | 2625 | new ? "new" : "old", fe->dai_link->name); |
2750 | 2626 | ||
2751 | /* skip if FE doesn't have playback capability */ | 2627 | /* skip if FE doesn't have playback capability */ |
2752 | if (!fe->cpu_dai->driver->playback.channels_min || | 2628 | if (!snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_PLAYBACK) || |
2753 | !fe->codec_dai->driver->playback.channels_min) | 2629 | !snd_soc_dai_stream_valid(fe->codec_dai, SNDRV_PCM_STREAM_PLAYBACK)) |
2754 | goto capture; | 2630 | goto capture; |
2755 | 2631 | ||
2756 | /* skip if FE isn't currently playing */ | 2632 | /* skip if FE isn't currently playing */ |
@@ -2780,8 +2656,8 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) | |||
2780 | 2656 | ||
2781 | capture: | 2657 | capture: |
2782 | /* skip if FE doesn't have capture capability */ | 2658 | /* skip if FE doesn't have capture capability */ |
2783 | if (!fe->cpu_dai->driver->capture.channels_min || | 2659 | if (!snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_CAPTURE) || |
2784 | !fe->codec_dai->driver->capture.channels_min) | 2660 | !snd_soc_dai_stream_valid(fe->codec_dai, SNDRV_PCM_STREAM_CAPTURE)) |
2785 | return 0; | 2661 | return 0; |
2786 | 2662 | ||
2787 | /* skip if FE isn't currently capturing */ | 2663 | /* skip if FE isn't currently capturing */ |
@@ -2929,149 +2805,10 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) | |||
2929 | static void soc_pcm_private_free(struct snd_pcm *pcm) | 2805 | static void soc_pcm_private_free(struct snd_pcm *pcm) |
2930 | { | 2806 | { |
2931 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | 2807 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; |
2932 | struct snd_soc_rtdcom_list *rtdcom; | ||
2933 | struct snd_soc_component *component; | ||
2934 | 2808 | ||
2935 | /* need to sync the delayed work before releasing resources */ | 2809 | /* need to sync the delayed work before releasing resources */ |
2936 | flush_delayed_work(&rtd->delayed_work); | 2810 | flush_delayed_work(&rtd->delayed_work); |
2937 | for_each_rtdcom(rtd, rtdcom) { | 2811 | snd_soc_pcm_component_free(pcm); |
2938 | component = rtdcom->component; | ||
2939 | |||
2940 | if (component->driver->pcm_free) | ||
2941 | component->driver->pcm_free(pcm); | ||
2942 | } | ||
2943 | } | ||
2944 | |||
2945 | static int soc_rtdcom_ack(struct snd_pcm_substream *substream) | ||
2946 | { | ||
2947 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
2948 | struct snd_soc_rtdcom_list *rtdcom; | ||
2949 | struct snd_soc_component *component; | ||
2950 | |||
2951 | for_each_rtdcom(rtd, rtdcom) { | ||
2952 | component = rtdcom->component; | ||
2953 | |||
2954 | if (!component->driver->ops || | ||
2955 | !component->driver->ops->ack) | ||
2956 | continue; | ||
2957 | |||
2958 | /* FIXME. it returns 1st ask now */ | ||
2959 | return component->driver->ops->ack(substream); | ||
2960 | } | ||
2961 | |||
2962 | return -EINVAL; | ||
2963 | } | ||
2964 | |||
2965 | static int soc_rtdcom_copy_user(struct snd_pcm_substream *substream, int channel, | ||
2966 | unsigned long pos, void __user *buf, | ||
2967 | unsigned long bytes) | ||
2968 | { | ||
2969 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
2970 | struct snd_soc_rtdcom_list *rtdcom; | ||
2971 | struct snd_soc_component *component; | ||
2972 | |||
2973 | for_each_rtdcom(rtd, rtdcom) { | ||
2974 | component = rtdcom->component; | ||
2975 | |||
2976 | if (!component->driver->ops || | ||
2977 | !component->driver->ops->copy_user) | ||
2978 | continue; | ||
2979 | |||
2980 | /* FIXME. it returns 1st copy now */ | ||
2981 | return component->driver->ops->copy_user(substream, channel, | ||
2982 | pos, buf, bytes); | ||
2983 | } | ||
2984 | |||
2985 | return -EINVAL; | ||
2986 | } | ||
2987 | |||
2988 | static int soc_rtdcom_copy_kernel(struct snd_pcm_substream *substream, int channel, | ||
2989 | unsigned long pos, void *buf, unsigned long bytes) | ||
2990 | { | ||
2991 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
2992 | struct snd_soc_rtdcom_list *rtdcom; | ||
2993 | struct snd_soc_component *component; | ||
2994 | |||
2995 | for_each_rtdcom(rtd, rtdcom) { | ||
2996 | component = rtdcom->component; | ||
2997 | |||
2998 | if (!component->driver->ops || | ||
2999 | !component->driver->ops->copy_kernel) | ||
3000 | continue; | ||
3001 | |||
3002 | /* FIXME. it returns 1st copy now */ | ||
3003 | return component->driver->ops->copy_kernel(substream, channel, | ||
3004 | pos, buf, bytes); | ||
3005 | } | ||
3006 | |||
3007 | return -EINVAL; | ||
3008 | } | ||
3009 | |||
3010 | static int soc_rtdcom_fill_silence(struct snd_pcm_substream *substream, int channel, | ||
3011 | unsigned long pos, unsigned long bytes) | ||
3012 | { | ||
3013 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
3014 | struct snd_soc_rtdcom_list *rtdcom; | ||
3015 | struct snd_soc_component *component; | ||
3016 | |||
3017 | for_each_rtdcom(rtd, rtdcom) { | ||
3018 | component = rtdcom->component; | ||
3019 | |||
3020 | if (!component->driver->ops || | ||
3021 | !component->driver->ops->fill_silence) | ||
3022 | continue; | ||
3023 | |||
3024 | /* FIXME. it returns 1st silence now */ | ||
3025 | return component->driver->ops->fill_silence(substream, channel, | ||
3026 | pos, bytes); | ||
3027 | } | ||
3028 | |||
3029 | return -EINVAL; | ||
3030 | } | ||
3031 | |||
3032 | static struct page *soc_rtdcom_page(struct snd_pcm_substream *substream, | ||
3033 | unsigned long offset) | ||
3034 | { | ||
3035 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
3036 | struct snd_soc_rtdcom_list *rtdcom; | ||
3037 | struct snd_soc_component *component; | ||
3038 | struct page *page; | ||
3039 | |||
3040 | for_each_rtdcom(rtd, rtdcom) { | ||
3041 | component = rtdcom->component; | ||
3042 | |||
3043 | if (!component->driver->ops || | ||
3044 | !component->driver->ops->page) | ||
3045 | continue; | ||
3046 | |||
3047 | /* FIXME. it returns 1st page now */ | ||
3048 | page = component->driver->ops->page(substream, offset); | ||
3049 | if (page) | ||
3050 | return page; | ||
3051 | } | ||
3052 | |||
3053 | return NULL; | ||
3054 | } | ||
3055 | |||
3056 | static int soc_rtdcom_mmap(struct snd_pcm_substream *substream, | ||
3057 | struct vm_area_struct *vma) | ||
3058 | { | ||
3059 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
3060 | struct snd_soc_rtdcom_list *rtdcom; | ||
3061 | struct snd_soc_component *component; | ||
3062 | |||
3063 | for_each_rtdcom(rtd, rtdcom) { | ||
3064 | component = rtdcom->component; | ||
3065 | |||
3066 | if (!component->driver->ops || | ||
3067 | !component->driver->ops->mmap) | ||
3068 | continue; | ||
3069 | |||
3070 | /* FIXME. it returns 1st mmap now */ | ||
3071 | return component->driver->ops->mmap(substream, vma); | ||
3072 | } | ||
3073 | |||
3074 | return -EINVAL; | ||
3075 | } | 2812 | } |
3076 | 2813 | ||
3077 | /* create a new pcm */ | 2814 | /* create a new pcm */ |
@@ -3079,7 +2816,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3079 | { | 2816 | { |
3080 | struct snd_soc_dai *codec_dai; | 2817 | struct snd_soc_dai *codec_dai; |
3081 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 2818 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
3082 | struct snd_soc_component *component; | ||
3083 | struct snd_soc_rtdcom_list *rtdcom; | 2819 | struct snd_soc_rtdcom_list *rtdcom; |
3084 | struct snd_pcm *pcm; | 2820 | struct snd_pcm *pcm; |
3085 | char new_name[64]; | 2821 | char new_name[64]; |
@@ -3090,15 +2826,23 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3090 | playback = rtd->dai_link->dpcm_playback; | 2826 | playback = rtd->dai_link->dpcm_playback; |
3091 | capture = rtd->dai_link->dpcm_capture; | 2827 | capture = rtd->dai_link->dpcm_capture; |
3092 | } else { | 2828 | } else { |
2829 | /* Adapt stream for codec2codec links */ | ||
2830 | struct snd_soc_pcm_stream *cpu_capture = rtd->dai_link->params ? | ||
2831 | &cpu_dai->driver->playback : &cpu_dai->driver->capture; | ||
2832 | struct snd_soc_pcm_stream *cpu_playback = rtd->dai_link->params ? | ||
2833 | &cpu_dai->driver->capture : &cpu_dai->driver->playback; | ||
2834 | |||
3093 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | 2835 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
3094 | if (codec_dai->driver->playback.channels_min) | 2836 | if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && |
2837 | snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) | ||
3095 | playback = 1; | 2838 | playback = 1; |
3096 | if (codec_dai->driver->capture.channels_min) | 2839 | if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && |
2840 | snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) | ||
3097 | capture = 1; | 2841 | capture = 1; |
3098 | } | 2842 | } |
3099 | 2843 | ||
3100 | capture = capture && cpu_dai->driver->capture.channels_min; | 2844 | capture = capture && cpu_capture->channels_min; |
3101 | playback = playback && cpu_dai->driver->playback.channels_min; | 2845 | playback = playback && cpu_playback->channels_min; |
3102 | } | 2846 | } |
3103 | 2847 | ||
3104 | if (rtd->dai_link->playback_only) { | 2848 | if (rtd->dai_link->playback_only) { |
@@ -3112,7 +2856,13 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3112 | } | 2856 | } |
3113 | 2857 | ||
3114 | /* create the PCM */ | 2858 | /* create the PCM */ |
3115 | if (rtd->dai_link->no_pcm) { | 2859 | if (rtd->dai_link->params) { |
2860 | snprintf(new_name, sizeof(new_name), "codec2codec(%s)", | ||
2861 | rtd->dai_link->stream_name); | ||
2862 | |||
2863 | ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, | ||
2864 | playback, capture, &pcm); | ||
2865 | } else if (rtd->dai_link->no_pcm) { | ||
3116 | snprintf(new_name, sizeof(new_name), "(%s)", | 2866 | snprintf(new_name, sizeof(new_name), "(%s)", |
3117 | rtd->dai_link->stream_name); | 2867 | rtd->dai_link->stream_name); |
3118 | 2868 | ||
@@ -3139,13 +2889,17 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3139 | dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name); | 2889 | dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name); |
3140 | 2890 | ||
3141 | /* DAPM dai link stream work */ | 2891 | /* DAPM dai link stream work */ |
3142 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); | 2892 | if (rtd->dai_link->params) |
2893 | INIT_DELAYED_WORK(&rtd->delayed_work, | ||
2894 | codec2codec_close_delayed_work); | ||
2895 | else | ||
2896 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); | ||
3143 | 2897 | ||
3144 | pcm->nonatomic = rtd->dai_link->nonatomic; | 2898 | pcm->nonatomic = rtd->dai_link->nonatomic; |
3145 | rtd->pcm = pcm; | 2899 | rtd->pcm = pcm; |
3146 | pcm->private_data = rtd; | 2900 | pcm->private_data = rtd; |
3147 | 2901 | ||
3148 | if (rtd->dai_link->no_pcm) { | 2902 | if (rtd->dai_link->no_pcm || rtd->dai_link->params) { |
3149 | if (playback) | 2903 | if (playback) |
3150 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; | 2904 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; |
3151 | if (capture) | 2905 | if (capture) |
@@ -3162,7 +2916,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3162 | rtd->ops.hw_free = dpcm_fe_dai_hw_free; | 2916 | rtd->ops.hw_free = dpcm_fe_dai_hw_free; |
3163 | rtd->ops.close = dpcm_fe_dai_close; | 2917 | rtd->ops.close = dpcm_fe_dai_close; |
3164 | rtd->ops.pointer = soc_pcm_pointer; | 2918 | rtd->ops.pointer = soc_pcm_pointer; |
3165 | rtd->ops.ioctl = soc_pcm_ioctl; | 2919 | rtd->ops.ioctl = snd_soc_pcm_component_ioctl; |
3166 | } else { | 2920 | } else { |
3167 | rtd->ops.open = soc_pcm_open; | 2921 | rtd->ops.open = soc_pcm_open; |
3168 | rtd->ops.hw_params = soc_pcm_hw_params; | 2922 | rtd->ops.hw_params = soc_pcm_hw_params; |
@@ -3171,7 +2925,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3171 | rtd->ops.hw_free = soc_pcm_hw_free; | 2925 | rtd->ops.hw_free = soc_pcm_hw_free; |
3172 | rtd->ops.close = soc_pcm_close; | 2926 | rtd->ops.close = soc_pcm_close; |
3173 | rtd->ops.pointer = soc_pcm_pointer; | 2927 | rtd->ops.pointer = soc_pcm_pointer; |
3174 | rtd->ops.ioctl = soc_pcm_ioctl; | 2928 | rtd->ops.ioctl = snd_soc_pcm_component_ioctl; |
3175 | } | 2929 | } |
3176 | 2930 | ||
3177 | for_each_rtdcom(rtd, rtdcom) { | 2931 | for_each_rtdcom(rtd, rtdcom) { |
@@ -3180,18 +2934,12 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3180 | if (!ops) | 2934 | if (!ops) |
3181 | continue; | 2935 | continue; |
3182 | 2936 | ||
3183 | if (ops->ack) | ||
3184 | rtd->ops.ack = soc_rtdcom_ack; | ||
3185 | if (ops->copy_user) | 2937 | if (ops->copy_user) |
3186 | rtd->ops.copy_user = soc_rtdcom_copy_user; | 2938 | rtd->ops.copy_user = snd_soc_pcm_component_copy_user; |
3187 | if (ops->copy_kernel) | ||
3188 | rtd->ops.copy_kernel = soc_rtdcom_copy_kernel; | ||
3189 | if (ops->fill_silence) | ||
3190 | rtd->ops.fill_silence = soc_rtdcom_fill_silence; | ||
3191 | if (ops->page) | 2939 | if (ops->page) |
3192 | rtd->ops.page = soc_rtdcom_page; | 2940 | rtd->ops.page = snd_soc_pcm_component_page; |
3193 | if (ops->mmap) | 2941 | if (ops->mmap) |
3194 | rtd->ops.mmap = soc_rtdcom_mmap; | 2942 | rtd->ops.mmap = snd_soc_pcm_component_mmap; |
3195 | } | 2943 | } |
3196 | 2944 | ||
3197 | if (playback) | 2945 | if (playback) |
@@ -3200,19 +2948,10 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3200 | if (capture) | 2948 | if (capture) |
3201 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops); | 2949 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops); |
3202 | 2950 | ||
3203 | for_each_rtdcom(rtd, rtdcom) { | 2951 | ret = snd_soc_pcm_component_new(pcm); |
3204 | component = rtdcom->component; | 2952 | if (ret < 0) { |
3205 | 2953 | dev_err(rtd->dev, "ASoC: pcm constructor failed: %d\n", ret); | |
3206 | if (!component->driver->pcm_new) | 2954 | return ret; |
3207 | continue; | ||
3208 | |||
3209 | ret = component->driver->pcm_new(rtd); | ||
3210 | if (ret < 0) { | ||
3211 | dev_err(component->dev, | ||
3212 | "ASoC: pcm constructor failed: %d\n", | ||
3213 | ret); | ||
3214 | return ret; | ||
3215 | } | ||
3216 | } | 2955 | } |
3217 | 2956 | ||
3218 | pcm->private_free = soc_pcm_private_free; | 2957 | pcm->private_free = soc_pcm_private_free; |
@@ -3436,11 +3175,11 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, | |||
3436 | if (!buf) | 3175 | if (!buf) |
3437 | return -ENOMEM; | 3176 | return -ENOMEM; |
3438 | 3177 | ||
3439 | if (fe->cpu_dai->driver->playback.channels_min) | 3178 | if (snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) |
3440 | offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK, | 3179 | offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK, |
3441 | buf + offset, out_count - offset); | 3180 | buf + offset, out_count - offset); |
3442 | 3181 | ||
3443 | if (fe->cpu_dai->driver->capture.channels_min) | 3182 | if (snd_soc_dai_stream_valid(fe->cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) |
3444 | offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE, | 3183 | offset += dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE, |
3445 | buf + offset, out_count - offset); | 3184 | buf + offset, out_count - offset); |
3446 | 3185 | ||
@@ -3461,17 +3200,14 @@ void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) | |||
3461 | if (!rtd->dai_link) | 3200 | if (!rtd->dai_link) |
3462 | return; | 3201 | return; |
3463 | 3202 | ||
3203 | if (!rtd->dai_link->dynamic) | ||
3204 | return; | ||
3205 | |||
3464 | if (!rtd->card->debugfs_card_root) | 3206 | if (!rtd->card->debugfs_card_root) |
3465 | return; | 3207 | return; |
3466 | 3208 | ||
3467 | rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name, | 3209 | rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name, |
3468 | rtd->card->debugfs_card_root); | 3210 | rtd->card->debugfs_card_root); |
3469 | if (!rtd->debugfs_dpcm_root) { | ||
3470 | dev_dbg(rtd->dev, | ||
3471 | "ASoC: Failed to create dpcm debugfs directory %s\n", | ||
3472 | rtd->dai_link->name); | ||
3473 | return; | ||
3474 | } | ||
3475 | 3211 | ||
3476 | debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root, | 3212 | debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root, |
3477 | rtd, &dpcm_state_fops); | 3213 | rtd, &dpcm_state_fops); |
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 2eca85c04a3e..aa9a1fca46fa 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c | |||
@@ -524,7 +524,7 @@ static void remove_dai(struct snd_soc_component *comp, | |||
524 | if (dobj->ops && dobj->ops->dai_unload) | 524 | if (dobj->ops && dobj->ops->dai_unload) |
525 | dobj->ops->dai_unload(comp, dobj); | 525 | dobj->ops->dai_unload(comp, dobj); |
526 | 526 | ||
527 | list_for_each_entry(dai, &comp->dai_list, list) | 527 | for_each_component_dais(comp, dai) |
528 | if (dai->driver == dai_drv) | 528 | if (dai->driver == dai_drv) |
529 | dai->driver = NULL; | 529 | dai->driver = NULL; |
530 | 530 | ||
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index e3b9dd634c6d..54dcece52b0c 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c | |||
@@ -52,205 +52,6 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params) | |||
52 | } | 52 | } |
53 | EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); | 53 | EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); |
54 | 54 | ||
55 | int snd_soc_component_enable_pin(struct snd_soc_component *component, | ||
56 | const char *pin) | ||
57 | { | ||
58 | struct snd_soc_dapm_context *dapm = | ||
59 | snd_soc_component_get_dapm(component); | ||
60 | char *full_name; | ||
61 | int ret; | ||
62 | |||
63 | if (!component->name_prefix) | ||
64 | return snd_soc_dapm_enable_pin(dapm, pin); | ||
65 | |||
66 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
67 | if (!full_name) | ||
68 | return -ENOMEM; | ||
69 | |||
70 | ret = snd_soc_dapm_enable_pin(dapm, full_name); | ||
71 | kfree(full_name); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); | ||
76 | |||
77 | int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, | ||
78 | const char *pin) | ||
79 | { | ||
80 | struct snd_soc_dapm_context *dapm = | ||
81 | snd_soc_component_get_dapm(component); | ||
82 | char *full_name; | ||
83 | int ret; | ||
84 | |||
85 | if (!component->name_prefix) | ||
86 | return snd_soc_dapm_enable_pin_unlocked(dapm, pin); | ||
87 | |||
88 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
89 | if (!full_name) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name); | ||
93 | kfree(full_name); | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); | ||
98 | |||
99 | int snd_soc_component_disable_pin(struct snd_soc_component *component, | ||
100 | const char *pin) | ||
101 | { | ||
102 | struct snd_soc_dapm_context *dapm = | ||
103 | snd_soc_component_get_dapm(component); | ||
104 | char *full_name; | ||
105 | int ret; | ||
106 | |||
107 | if (!component->name_prefix) | ||
108 | return snd_soc_dapm_disable_pin(dapm, pin); | ||
109 | |||
110 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
111 | if (!full_name) | ||
112 | return -ENOMEM; | ||
113 | |||
114 | ret = snd_soc_dapm_disable_pin(dapm, full_name); | ||
115 | kfree(full_name); | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); | ||
120 | |||
121 | int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, | ||
122 | const char *pin) | ||
123 | { | ||
124 | struct snd_soc_dapm_context *dapm = | ||
125 | snd_soc_component_get_dapm(component); | ||
126 | char *full_name; | ||
127 | int ret; | ||
128 | |||
129 | if (!component->name_prefix) | ||
130 | return snd_soc_dapm_disable_pin_unlocked(dapm, pin); | ||
131 | |||
132 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
133 | if (!full_name) | ||
134 | return -ENOMEM; | ||
135 | |||
136 | ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name); | ||
137 | kfree(full_name); | ||
138 | |||
139 | return ret; | ||
140 | } | ||
141 | EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); | ||
142 | |||
143 | int snd_soc_component_nc_pin(struct snd_soc_component *component, | ||
144 | const char *pin) | ||
145 | { | ||
146 | struct snd_soc_dapm_context *dapm = | ||
147 | snd_soc_component_get_dapm(component); | ||
148 | char *full_name; | ||
149 | int ret; | ||
150 | |||
151 | if (!component->name_prefix) | ||
152 | return snd_soc_dapm_nc_pin(dapm, pin); | ||
153 | |||
154 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
155 | if (!full_name) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | ret = snd_soc_dapm_nc_pin(dapm, full_name); | ||
159 | kfree(full_name); | ||
160 | |||
161 | return ret; | ||
162 | } | ||
163 | EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); | ||
164 | |||
165 | int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, | ||
166 | const char *pin) | ||
167 | { | ||
168 | struct snd_soc_dapm_context *dapm = | ||
169 | snd_soc_component_get_dapm(component); | ||
170 | char *full_name; | ||
171 | int ret; | ||
172 | |||
173 | if (!component->name_prefix) | ||
174 | return snd_soc_dapm_nc_pin_unlocked(dapm, pin); | ||
175 | |||
176 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
177 | if (!full_name) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name); | ||
181 | kfree(full_name); | ||
182 | |||
183 | return ret; | ||
184 | } | ||
185 | EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); | ||
186 | |||
187 | int snd_soc_component_get_pin_status(struct snd_soc_component *component, | ||
188 | const char *pin) | ||
189 | { | ||
190 | struct snd_soc_dapm_context *dapm = | ||
191 | snd_soc_component_get_dapm(component); | ||
192 | char *full_name; | ||
193 | int ret; | ||
194 | |||
195 | if (!component->name_prefix) | ||
196 | return snd_soc_dapm_get_pin_status(dapm, pin); | ||
197 | |||
198 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
199 | if (!full_name) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | ret = snd_soc_dapm_get_pin_status(dapm, full_name); | ||
203 | kfree(full_name); | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); | ||
208 | |||
209 | int snd_soc_component_force_enable_pin(struct snd_soc_component *component, | ||
210 | const char *pin) | ||
211 | { | ||
212 | struct snd_soc_dapm_context *dapm = | ||
213 | snd_soc_component_get_dapm(component); | ||
214 | char *full_name; | ||
215 | int ret; | ||
216 | |||
217 | if (!component->name_prefix) | ||
218 | return snd_soc_dapm_force_enable_pin(dapm, pin); | ||
219 | |||
220 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
221 | if (!full_name) | ||
222 | return -ENOMEM; | ||
223 | |||
224 | ret = snd_soc_dapm_force_enable_pin(dapm, full_name); | ||
225 | kfree(full_name); | ||
226 | |||
227 | return ret; | ||
228 | } | ||
229 | EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); | ||
230 | |||
231 | int snd_soc_component_force_enable_pin_unlocked( | ||
232 | struct snd_soc_component *component, | ||
233 | const char *pin) | ||
234 | { | ||
235 | struct snd_soc_dapm_context *dapm = | ||
236 | snd_soc_component_get_dapm(component); | ||
237 | char *full_name; | ||
238 | int ret; | ||
239 | |||
240 | if (!component->name_prefix) | ||
241 | return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); | ||
242 | |||
243 | full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); | ||
244 | if (!full_name) | ||
245 | return -ENOMEM; | ||
246 | |||
247 | ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name); | ||
248 | kfree(full_name); | ||
249 | |||
250 | return ret; | ||
251 | } | ||
252 | EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); | ||
253 | |||
254 | static const struct snd_pcm_hardware dummy_dma_hardware = { | 55 | static const struct snd_pcm_hardware dummy_dma_hardware = { |
255 | /* Random values to keep userspace happy when checking constraints */ | 56 | /* Random values to keep userspace happy when checking constraints */ |
256 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 57 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index fb01f0ca6027..bb8036ae567e 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig | |||
@@ -36,6 +36,16 @@ config SND_SOC_SOF_ACPI | |||
36 | Say Y if you need this option | 36 | Say Y if you need this option |
37 | If unsure select "N". | 37 | If unsure select "N". |
38 | 38 | ||
39 | config SND_SOC_SOF_OF | ||
40 | tristate "SOF OF enumeration support" | ||
41 | depends on OF || COMPILE_TEST | ||
42 | select SND_SOC_SOF | ||
43 | select SND_SOC_SOF_OPTIONS | ||
44 | help | ||
45 | This adds support for Device Tree enumeration. This option is | ||
46 | required to enable i.MX8 devices. | ||
47 | Say Y if you need this option. If unsure select "N". | ||
48 | |||
39 | config SND_SOC_SOF_OPTIONS | 49 | config SND_SOC_SOF_OPTIONS |
40 | tristate | 50 | tristate |
41 | help | 51 | help |
@@ -163,6 +173,7 @@ config SND_SOC_SOF_PROBE_WORK_QUEUE | |||
163 | When selected, the probe is handled in two steps, for example to | 173 | When selected, the probe is handled in two steps, for example to |
164 | avoid lockdeps if request_module is used in the probe. | 174 | avoid lockdeps if request_module is used in the probe. |
165 | 175 | ||
176 | source "sound/soc/sof/imx/Kconfig" | ||
166 | source "sound/soc/sof/intel/Kconfig" | 177 | source "sound/soc/sof/intel/Kconfig" |
167 | source "sound/soc/sof/xtensa/Kconfig" | 178 | source "sound/soc/sof/xtensa/Kconfig" |
168 | 179 | ||
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 8f14c9d2950b..b0a6f01bdc44 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile | |||
@@ -5,14 +5,18 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ | |||
5 | 5 | ||
6 | snd-sof-pci-objs := sof-pci-dev.o | 6 | snd-sof-pci-objs := sof-pci-dev.o |
7 | snd-sof-acpi-objs := sof-acpi-dev.o | 7 | snd-sof-acpi-objs := sof-acpi-dev.o |
8 | snd-sof-of-objs := sof-of-dev.o | ||
9 | |||
8 | snd-sof-nocodec-objs := nocodec.o | 10 | snd-sof-nocodec-objs := nocodec.o |
9 | 11 | ||
10 | obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o | 12 | obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o |
11 | obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o | 13 | obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o |
12 | 14 | ||
13 | 15 | ||
14 | obj-$(CONFIG_SND_SOC_SOF_ACPI) += sof-acpi-dev.o | 16 | obj-$(CONFIG_SND_SOC_SOF_ACPI) += snd-sof-acpi.o |
15 | obj-$(CONFIG_SND_SOC_SOF_PCI) += sof-pci-dev.o | 17 | obj-$(CONFIG_SND_SOC_SOF_OF) += snd-sof-of.o |
18 | obj-$(CONFIG_SND_SOC_SOF_PCI) += snd-sof-pci.o | ||
16 | 19 | ||
17 | obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ | 20 | obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ |
21 | obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/ | ||
18 | obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/ | 22 | obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/ |
diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 5beda47cdf9f..81f28f7ff1a0 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include "ops.h" | 17 | #include "ops.h" |
18 | 18 | ||
19 | /* SOF defaults if not provided by the platform in ms */ | 19 | /* SOF defaults if not provided by the platform in ms */ |
20 | #define TIMEOUT_DEFAULT_IPC_MS 5 | 20 | #define TIMEOUT_DEFAULT_IPC_MS 500 |
21 | #define TIMEOUT_DEFAULT_BOOT_MS 100 | 21 | #define TIMEOUT_DEFAULT_BOOT_MS 2000 |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * Generic object lookup APIs. | 24 | * Generic object lookup APIs. |
diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 2388477a965e..54cd431faab7 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c | |||
@@ -128,6 +128,7 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, | |||
128 | unsigned long ipc_duration_ms = 0; | 128 | unsigned long ipc_duration_ms = 0; |
129 | bool flood_duration_test = false; | 129 | bool flood_duration_test = false; |
130 | unsigned long ipc_count = 0; | 130 | unsigned long ipc_count = 0; |
131 | struct dentry *dentry; | ||
131 | int err; | 132 | int err; |
132 | #endif | 133 | #endif |
133 | size_t size; | 134 | size_t size; |
@@ -149,11 +150,12 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, | |||
149 | * ipc_duration_ms test floods the DSP for the time specified | 150 | * ipc_duration_ms test floods the DSP for the time specified |
150 | * in the debugfs entry. | 151 | * in the debugfs entry. |
151 | */ | 152 | */ |
152 | if (strcmp(dfse->dfsentry->d_name.name, "ipc_flood_count") && | 153 | dentry = file->f_path.dentry; |
153 | strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) | 154 | if (strcmp(dentry->d_name.name, "ipc_flood_count") && |
155 | strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) | ||
154 | return -EINVAL; | 156 | return -EINVAL; |
155 | 157 | ||
156 | if (!strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) | 158 | if (!strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) |
157 | flood_duration_test = true; | 159 | flood_duration_test = true; |
158 | 160 | ||
159 | /* test completion criterion */ | 161 | /* test completion criterion */ |
@@ -226,8 +228,11 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, | |||
226 | u8 *buf; | 228 | u8 *buf; |
227 | 229 | ||
228 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) | 230 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) |
229 | if ((!strcmp(dfse->dfsentry->d_name.name, "ipc_flood_count") || | 231 | struct dentry *dentry; |
230 | !strcmp(dfse->dfsentry->d_name.name, "ipc_flood_duration_ms")) && | 232 | |
233 | dentry = file->f_path.dentry; | ||
234 | if ((!strcmp(dentry->d_name.name, "ipc_flood_count") || | ||
235 | !strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) && | ||
231 | dfse->cache_buf) { | 236 | dfse->cache_buf) { |
232 | if (*ppos) | 237 | if (*ppos) |
233 | return 0; | 238 | return 0; |
@@ -290,8 +295,7 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, | |||
290 | if (!pm_runtime_active(sdev->dev) && | 295 | if (!pm_runtime_active(sdev->dev) && |
291 | dfse->access_type == SOF_DEBUGFS_ACCESS_D0_ONLY) { | 296 | dfse->access_type == SOF_DEBUGFS_ACCESS_D0_ONLY) { |
292 | dev_err(sdev->dev, | 297 | dev_err(sdev->dev, |
293 | "error: debugfs entry %s cannot be read in DSP D3\n", | 298 | "error: debugfs entry cannot be read in DSP D3\n"); |
294 | dfse->dfsentry->d_name.name); | ||
295 | kfree(buf); | 299 | kfree(buf); |
296 | return -EINVAL; | 300 | return -EINVAL; |
297 | } | 301 | } |
@@ -356,17 +360,11 @@ int snd_sof_debugfs_io_item(struct snd_sof_dev *sdev, | |||
356 | } | 360 | } |
357 | #endif | 361 | #endif |
358 | 362 | ||
359 | dfse->dfsentry = debugfs_create_file(name, 0444, sdev->debugfs_root, | 363 | debugfs_create_file(name, 0444, sdev->debugfs_root, dfse, |
360 | dfse, &sof_dfs_fops); | 364 | &sof_dfs_fops); |
361 | if (!dfse->dfsentry) { | ||
362 | /* can't rely on debugfs, only log error and keep going */ | ||
363 | dev_err(sdev->dev, "error: cannot create debugfs entry %s\n", | ||
364 | name); | ||
365 | } else { | ||
366 | /* add to dfsentry list */ | ||
367 | list_add(&dfse->list, &sdev->dfsentry_list); | ||
368 | 365 | ||
369 | } | 366 | /* add to dfsentry list */ |
367 | list_add(&dfse->list, &sdev->dfsentry_list); | ||
370 | 368 | ||
371 | return 0; | 369 | return 0; |
372 | } | 370 | } |
@@ -402,16 +400,10 @@ int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev, | |||
402 | return -ENOMEM; | 400 | return -ENOMEM; |
403 | #endif | 401 | #endif |
404 | 402 | ||
405 | dfse->dfsentry = debugfs_create_file(name, mode, sdev->debugfs_root, | 403 | debugfs_create_file(name, mode, sdev->debugfs_root, dfse, |
406 | dfse, &sof_dfs_fops); | 404 | &sof_dfs_fops); |
407 | if (!dfse->dfsentry) { | 405 | /* add to dfsentry list */ |
408 | /* can't rely on debugfs, only log error and keep going */ | 406 | list_add(&dfse->list, &sdev->dfsentry_list); |
409 | dev_err(sdev->dev, "error: cannot create debugfs entry %s\n", | ||
410 | name); | ||
411 | } else { | ||
412 | /* add to dfsentry list */ | ||
413 | list_add(&dfse->list, &sdev->dfsentry_list); | ||
414 | } | ||
415 | 407 | ||
416 | return 0; | 408 | return 0; |
417 | } | 409 | } |
@@ -426,10 +418,6 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) | |||
426 | 418 | ||
427 | /* use "sof" as top level debugFS dir */ | 419 | /* use "sof" as top level debugFS dir */ |
428 | sdev->debugfs_root = debugfs_create_dir("sof", NULL); | 420 | sdev->debugfs_root = debugfs_create_dir("sof", NULL); |
429 | if (IS_ERR_OR_NULL(sdev->debugfs_root)) { | ||
430 | dev_err(sdev->dev, "error: failed to create debugfs directory\n"); | ||
431 | return 0; | ||
432 | } | ||
433 | 421 | ||
434 | /* init dfsentry list */ | 422 | /* init dfsentry list */ |
435 | INIT_LIST_HEAD(&sdev->dfsentry_list); | 423 | INIT_LIST_HEAD(&sdev->dfsentry_list); |
diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig new file mode 100644 index 000000000000..5acae75f5750 --- /dev/null +++ b/sound/soc/sof/imx/Kconfig | |||
@@ -0,0 +1,23 @@ | |||
1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
2 | |||
3 | config SND_SOC_SOF_IMX_TOPLEVEL | ||
4 | bool "SOF support for NXP i.MX audio DSPs" | ||
5 | depends on ARM64|| COMPILE_TEST | ||
6 | depends on SND_SOC_SOF_OF | ||
7 | help | ||
8 | This adds support for Sound Open Firmware for NXP i.MX platforms. | ||
9 | Say Y if you have such a device. | ||
10 | If unsure select "N". | ||
11 | |||
12 | if SND_SOC_SOF_IMX_TOPLEVEL | ||
13 | |||
14 | config SND_SOC_SOF_IMX8 | ||
15 | tristate "SOF support for i.MX8" | ||
16 | depends on IMX_SCU | ||
17 | depends on IMX_DSP | ||
18 | help | ||
19 | This adds support for Sound Open Firmware for NXP i.MX8 platforms | ||
20 | Say Y if you have such a device. | ||
21 | If unsure select "N". | ||
22 | |||
23 | endif ## SND_SOC_SOF_IMX_IMX_TOPLEVEL | ||
diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile new file mode 100644 index 000000000000..6ef908e8c807 --- /dev/null +++ b/sound/soc/sof/imx/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
2 | snd-sof-imx8-objs := imx8.o | ||
3 | |||
4 | obj-$(CONFIG_SND_SOC_SOF_IMX8) += snd-sof-imx8.o | ||
diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c new file mode 100644 index 000000000000..2a22b18e5ec0 --- /dev/null +++ b/sound/soc/sof/imx/imx8.c | |||
@@ -0,0 +1,394 @@ | |||
1 | // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
2 | // | ||
3 | // Copyright 2019 NXP | ||
4 | // | ||
5 | // Author: Daniel Baluta <daniel.baluta@nxp.com> | ||
6 | // | ||
7 | // Hardware interface for audio DSP on i.MX8 | ||
8 | |||
9 | #include <linux/firmware.h> | ||
10 | #include <linux/of_platform.h> | ||
11 | #include <linux/of_address.h> | ||
12 | #include <linux/of_irq.h> | ||
13 | #include <linux/pm_domain.h> | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <sound/sof.h> | ||
17 | #include <sound/sof/xtensa.h> | ||
18 | #include <linux/firmware/imx/ipc.h> | ||
19 | #include <linux/firmware/imx/dsp.h> | ||
20 | |||
21 | #include <linux/firmware/imx/svc/misc.h> | ||
22 | #include <dt-bindings/firmware/imx/rsrc.h> | ||
23 | #include "../ops.h" | ||
24 | |||
25 | /* DSP memories */ | ||
26 | #define IRAM_OFFSET 0x10000 | ||
27 | #define IRAM_SIZE (2 * 1024) | ||
28 | #define DRAM0_OFFSET 0x0 | ||
29 | #define DRAM0_SIZE (32 * 1024) | ||
30 | #define DRAM1_OFFSET 0x8000 | ||
31 | #define DRAM1_SIZE (32 * 1024) | ||
32 | #define SYSRAM_OFFSET 0x18000 | ||
33 | #define SYSRAM_SIZE (256 * 1024) | ||
34 | #define SYSROM_OFFSET 0x58000 | ||
35 | #define SYSROM_SIZE (192 * 1024) | ||
36 | |||
37 | #define RESET_VECTOR_VADDR 0x596f8000 | ||
38 | |||
39 | #define MBOX_OFFSET 0x800000 | ||
40 | #define MBOX_SIZE 0x1000 | ||
41 | |||
42 | struct imx8_priv { | ||
43 | struct device *dev; | ||
44 | struct snd_sof_dev *sdev; | ||
45 | |||
46 | /* DSP IPC handler */ | ||
47 | struct imx_dsp_ipc *dsp_ipc; | ||
48 | struct platform_device *ipc_dev; | ||
49 | |||
50 | /* System Controller IPC handler */ | ||
51 | struct imx_sc_ipc *sc_ipc; | ||
52 | |||
53 | /* Power domain handling */ | ||
54 | int num_domains; | ||
55 | struct device **pd_dev; | ||
56 | struct device_link **link; | ||
57 | |||
58 | }; | ||
59 | |||
60 | static void imx8_get_reply(struct snd_sof_dev *sdev) | ||
61 | { | ||
62 | struct snd_sof_ipc_msg *msg = sdev->msg; | ||
63 | struct sof_ipc_reply reply; | ||
64 | int ret = 0; | ||
65 | |||
66 | if (!msg) { | ||
67 | dev_warn(sdev->dev, "unexpected ipc interrupt\n"); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | /* get reply */ | ||
72 | sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); | ||
73 | |||
74 | if (reply.error < 0) { | ||
75 | memcpy(msg->reply_data, &reply, sizeof(reply)); | ||
76 | ret = reply.error; | ||
77 | } else { | ||
78 | /* reply has correct size? */ | ||
79 | if (reply.hdr.size != msg->reply_size) { | ||
80 | dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", | ||
81 | msg->reply_size, reply.hdr.size); | ||
82 | ret = -EINVAL; | ||
83 | } | ||
84 | |||
85 | /* read the message */ | ||
86 | if (msg->reply_size > 0) | ||
87 | sof_mailbox_read(sdev, sdev->host_box.offset, | ||
88 | msg->reply_data, msg->reply_size); | ||
89 | } | ||
90 | |||
91 | msg->reply_error = ret; | ||
92 | } | ||
93 | |||
94 | static int imx8_get_mailbox_offset(struct snd_sof_dev *sdev) | ||
95 | { | ||
96 | return MBOX_OFFSET; | ||
97 | } | ||
98 | |||
99 | static int imx8_get_window_offset(struct snd_sof_dev *sdev, u32 id) | ||
100 | { | ||
101 | return MBOX_OFFSET; | ||
102 | } | ||
103 | |||
104 | static void imx8_dsp_handle_reply(struct imx_dsp_ipc *ipc) | ||
105 | { | ||
106 | struct imx8_priv *priv = imx_dsp_get_data(ipc); | ||
107 | unsigned long flags; | ||
108 | |||
109 | spin_lock_irqsave(&priv->sdev->ipc_lock, flags); | ||
110 | imx8_get_reply(priv->sdev); | ||
111 | snd_sof_ipc_reply(priv->sdev, 0); | ||
112 | spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); | ||
113 | } | ||
114 | |||
115 | static void imx8_dsp_handle_request(struct imx_dsp_ipc *ipc) | ||
116 | { | ||
117 | struct imx8_priv *priv = imx_dsp_get_data(ipc); | ||
118 | |||
119 | snd_sof_ipc_msgs_rx(priv->sdev); | ||
120 | } | ||
121 | |||
122 | struct imx_dsp_ops dsp_ops = { | ||
123 | .handle_reply = imx8_dsp_handle_reply, | ||
124 | .handle_request = imx8_dsp_handle_request, | ||
125 | }; | ||
126 | |||
127 | static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) | ||
128 | { | ||
129 | struct imx8_priv *priv = (struct imx8_priv *)sdev->private; | ||
130 | |||
131 | sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, | ||
132 | msg->msg_size); | ||
133 | imx_dsp_ring_doorbell(priv->dsp_ipc, 0); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * DSP control. | ||
140 | */ | ||
141 | static int imx8_run(struct snd_sof_dev *sdev) | ||
142 | { | ||
143 | struct imx8_priv *dsp_priv = (struct imx8_priv *)sdev->private; | ||
144 | int ret; | ||
145 | |||
146 | ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, | ||
147 | IMX_SC_C_OFS_SEL, 1); | ||
148 | if (ret < 0) { | ||
149 | dev_err(sdev->dev, "Error system address offset source select\n"); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, | ||
154 | IMX_SC_C_OFS_AUDIO, 0x80); | ||
155 | if (ret < 0) { | ||
156 | dev_err(sdev->dev, "Error system address offset of AUDIO\n"); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, | ||
161 | IMX_SC_C_OFS_PERIPH, 0x5A); | ||
162 | if (ret < 0) { | ||
163 | dev_err(sdev->dev, "Error system address offset of PERIPH %d\n", | ||
164 | ret); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, | ||
169 | IMX_SC_C_OFS_IRQ, 0x51); | ||
170 | if (ret < 0) { | ||
171 | dev_err(sdev->dev, "Error system address offset of IRQ\n"); | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | imx_sc_pm_cpu_start(dsp_priv->sc_ipc, IMX_SC_R_DSP, true, | ||
176 | RESET_VECTOR_VADDR); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static int imx8_probe(struct snd_sof_dev *sdev) | ||
182 | { | ||
183 | struct platform_device *pdev = | ||
184 | container_of(sdev->dev, struct platform_device, dev); | ||
185 | struct device_node *np = pdev->dev.of_node; | ||
186 | struct device_node *res_node; | ||
187 | struct resource *mmio; | ||
188 | struct imx8_priv *priv; | ||
189 | struct resource res; | ||
190 | u32 base, size; | ||
191 | int ret = 0; | ||
192 | int i; | ||
193 | |||
194 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
195 | if (!priv) | ||
196 | return -ENOMEM; | ||
197 | |||
198 | sdev->private = priv; | ||
199 | priv->dev = sdev->dev; | ||
200 | priv->sdev = sdev; | ||
201 | |||
202 | /* power up device associated power domains */ | ||
203 | priv->num_domains = of_count_phandle_with_args(np, "power-domains", | ||
204 | "#power-domain-cells"); | ||
205 | if (priv->num_domains < 0) { | ||
206 | dev_err(sdev->dev, "no power-domains property in %pOF\n", np); | ||
207 | return priv->num_domains; | ||
208 | } | ||
209 | |||
210 | priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains, | ||
211 | sizeof(*priv->pd_dev), GFP_KERNEL); | ||
212 | if (!priv) | ||
213 | return -ENOMEM; | ||
214 | |||
215 | priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains, | ||
216 | sizeof(*priv->link), GFP_KERNEL); | ||
217 | if (!priv->link) | ||
218 | return -ENOMEM; | ||
219 | |||
220 | for (i = 0; i < priv->num_domains; i++) { | ||
221 | priv->pd_dev[i] = dev_pm_domain_attach_by_id(&pdev->dev, i); | ||
222 | if (IS_ERR(priv->pd_dev[i])) { | ||
223 | ret = PTR_ERR(priv->pd_dev[i]); | ||
224 | goto exit_unroll_pm; | ||
225 | } | ||
226 | priv->link[i] = device_link_add(&pdev->dev, priv->pd_dev[i], | ||
227 | DL_FLAG_STATELESS | | ||
228 | DL_FLAG_PM_RUNTIME | | ||
229 | DL_FLAG_RPM_ACTIVE); | ||
230 | if (!priv->link[i]) { | ||
231 | ret = -ENOMEM; | ||
232 | dev_pm_domain_detach(priv->pd_dev[i], false); | ||
233 | goto exit_unroll_pm; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | ret = imx_scu_get_handle(&priv->sc_ipc); | ||
238 | if (ret) { | ||
239 | dev_err(sdev->dev, "Cannot obtain SCU handle (err = %d)\n", | ||
240 | ret); | ||
241 | goto exit_unroll_pm; | ||
242 | } | ||
243 | |||
244 | priv->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", | ||
245 | PLATFORM_DEVID_NONE, | ||
246 | pdev, sizeof(*pdev)); | ||
247 | if (IS_ERR(priv->ipc_dev)) { | ||
248 | ret = PTR_ERR(priv->ipc_dev); | ||
249 | goto exit_unroll_pm; | ||
250 | } | ||
251 | |||
252 | priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev); | ||
253 | if (!priv->dsp_ipc) { | ||
254 | /* DSP IPC driver not probed yet, try later */ | ||
255 | ret = -EPROBE_DEFER; | ||
256 | dev_err(sdev->dev, "Failed to get drvdata\n"); | ||
257 | goto exit_pdev_unregister; | ||
258 | } | ||
259 | |||
260 | imx_dsp_set_data(priv->dsp_ipc, priv); | ||
261 | priv->dsp_ipc->ops = &dsp_ops; | ||
262 | |||
263 | /* DSP base */ | ||
264 | mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
265 | if (mmio) { | ||
266 | base = mmio->start; | ||
267 | size = resource_size(mmio); | ||
268 | } else { | ||
269 | dev_err(sdev->dev, "error: failed to get DSP base at idx 0\n"); | ||
270 | ret = -EINVAL; | ||
271 | goto exit_pdev_unregister; | ||
272 | } | ||
273 | |||
274 | sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size); | ||
275 | if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) { | ||
276 | dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n", | ||
277 | base, size); | ||
278 | ret = -ENODEV; | ||
279 | goto exit_pdev_unregister; | ||
280 | } | ||
281 | sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM; | ||
282 | |||
283 | res_node = of_parse_phandle(np, "memory-region", 0); | ||
284 | if (!res_node) { | ||
285 | dev_err(&pdev->dev, "failed to get memory region node\n"); | ||
286 | ret = -ENODEV; | ||
287 | goto exit_pdev_unregister; | ||
288 | } | ||
289 | |||
290 | ret = of_address_to_resource(res_node, 0, &res); | ||
291 | if (ret) { | ||
292 | dev_err(&pdev->dev, "failed to get reserved region address\n"); | ||
293 | goto exit_pdev_unregister; | ||
294 | } | ||
295 | |||
296 | sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, | ||
297 | res.end - res.start + | ||
298 | 1); | ||
299 | if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { | ||
300 | dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", | ||
301 | base, size); | ||
302 | ret = -ENOMEM; | ||
303 | goto exit_pdev_unregister; | ||
304 | } | ||
305 | sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; | ||
306 | |||
307 | return 0; | ||
308 | |||
309 | exit_pdev_unregister: | ||
310 | platform_device_unregister(priv->ipc_dev); | ||
311 | exit_unroll_pm: | ||
312 | while (--i >= 0) { | ||
313 | device_link_del(priv->link[i]); | ||
314 | dev_pm_domain_detach(priv->pd_dev[i], false); | ||
315 | } | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int imx8_remove(struct snd_sof_dev *sdev) | ||
321 | { | ||
322 | struct imx8_priv *priv = (struct imx8_priv *)sdev->private; | ||
323 | int i; | ||
324 | |||
325 | platform_device_unregister(priv->ipc_dev); | ||
326 | |||
327 | for (i = 0; i < priv->num_domains; i++) { | ||
328 | device_link_del(priv->link[i]); | ||
329 | dev_pm_domain_detach(priv->pd_dev[i], false); | ||
330 | } | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | /* on i.MX8 there is 1 to 1 match between type and BAR idx */ | ||
336 | static int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type) | ||
337 | { | ||
338 | return type; | ||
339 | } | ||
340 | |||
341 | static void imx8_ipc_msg_data(struct snd_sof_dev *sdev, | ||
342 | struct snd_pcm_substream *substream, | ||
343 | void *p, size_t sz) | ||
344 | { | ||
345 | sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); | ||
346 | } | ||
347 | |||
348 | static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev, | ||
349 | struct snd_pcm_substream *substream, | ||
350 | const struct sof_ipc_pcm_params_reply *reply) | ||
351 | { | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static struct snd_soc_dai_driver imx8_dai[] = { | ||
356 | { | ||
357 | .name = "esai-port", | ||
358 | }, | ||
359 | }; | ||
360 | |||
361 | /* i.MX8 ops */ | ||
362 | struct snd_sof_dsp_ops sof_imx8_ops = { | ||
363 | /* probe and remove */ | ||
364 | .probe = imx8_probe, | ||
365 | .remove = imx8_remove, | ||
366 | /* DSP core boot */ | ||
367 | .run = imx8_run, | ||
368 | |||
369 | /* Block IO */ | ||
370 | .block_read = sof_block_read, | ||
371 | .block_write = sof_block_write, | ||
372 | |||
373 | /* ipc */ | ||
374 | .send_msg = imx8_send_msg, | ||
375 | .fw_ready = sof_fw_ready, | ||
376 | .get_mailbox_offset = imx8_get_mailbox_offset, | ||
377 | .get_window_offset = imx8_get_window_offset, | ||
378 | |||
379 | .ipc_msg_data = imx8_ipc_msg_data, | ||
380 | .ipc_pcm_params = imx8_ipc_pcm_params, | ||
381 | |||
382 | /* module loading */ | ||
383 | .load_module = snd_sof_parse_module_memcpy, | ||
384 | .get_bar_index = imx8_get_bar_index, | ||
385 | /* firmware loading */ | ||
386 | .load_firmware = snd_sof_load_firmware_memcpy, | ||
387 | |||
388 | /* DAI drivers */ | ||
389 | .drv = imx8_dai, | ||
390 | .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */ | ||
391 | }; | ||
392 | EXPORT_SYMBOL(sof_imx8_ops); | ||
393 | |||
394 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index dd14ce92fe10..479ba249e219 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig | |||
@@ -27,6 +27,8 @@ config SND_SOC_SOF_INTEL_PCI | |||
27 | select SND_SOC_SOF_ICELAKE if SND_SOC_SOF_ICELAKE_SUPPORT | 27 | select SND_SOC_SOF_ICELAKE if SND_SOC_SOF_ICELAKE_SUPPORT |
28 | select SND_SOC_SOF_COMETLAKE_LP if SND_SOC_SOF_COMETLAKE_LP_SUPPORT | 28 | select SND_SOC_SOF_COMETLAKE_LP if SND_SOC_SOF_COMETLAKE_LP_SUPPORT |
29 | select SND_SOC_SOF_COMETLAKE_H if SND_SOC_SOF_COMETLAKE_H_SUPPORT | 29 | select SND_SOC_SOF_COMETLAKE_H if SND_SOC_SOF_COMETLAKE_H_SUPPORT |
30 | select SND_SOC_SOF_TIGERLAKE if SND_SOC_SOF_TIGERLAKE_SUPPORT | ||
31 | select SND_SOC_SOF_ELKHARTLAKE if SND_SOC_SOF_ELKHARTLAKE_SUPPORT | ||
30 | help | 32 | help |
31 | This option is not user-selectable but automagically handled by | 33 | This option is not user-selectable but automagically handled by |
32 | 'select' statements at a higher level | 34 | 'select' statements at a higher level |
@@ -212,6 +214,36 @@ config SND_SOC_SOF_COMETLAKE_H_SUPPORT | |||
212 | Say Y if you have such a device. | 214 | Say Y if you have such a device. |
213 | If unsure select "N". | 215 | If unsure select "N". |
214 | 216 | ||
217 | config SND_SOC_SOF_TIGERLAKE_SUPPORT | ||
218 | bool "SOF support for Tigerlake" | ||
219 | help | ||
220 | This adds support for Sound Open Firmware for Intel(R) platforms | ||
221 | using the Tigerlake processors. | ||
222 | Say Y if you have such a device. | ||
223 | If unsure select "N". | ||
224 | |||
225 | config SND_SOC_SOF_TIGERLAKE | ||
226 | tristate | ||
227 | select SND_SOC_SOF_HDA_COMMON | ||
228 | help | ||
229 | This option is not user-selectable but automagically handled by | ||
230 | 'select' statements at a higher level | ||
231 | |||
232 | config SND_SOC_SOF_ELKHARTLAKE_SUPPORT | ||
233 | bool "SOF support for ElkhartLake" | ||
234 | help | ||
235 | This adds support for Sound Open Firmware for Intel(R) platforms | ||
236 | using the ElkhartLake processors. | ||
237 | Say Y if you have such a device. | ||
238 | If unsure select "N". | ||
239 | |||
240 | config SND_SOC_SOF_ELKHARTLAKE | ||
241 | tristate | ||
242 | select SND_SOC_SOF_HDA_COMMON | ||
243 | help | ||
244 | This option is not user-selectable but automagically handled by | ||
245 | 'select' statements at a higher level | ||
246 | |||
215 | config SND_SOC_SOF_HDA_COMMON | 247 | config SND_SOC_SOF_HDA_COMMON |
216 | tristate | 248 | tristate |
217 | select SND_SOC_SOF_INTEL_COMMON | 249 | select SND_SOC_SOF_INTEL_COMMON |
@@ -254,6 +286,7 @@ config SND_SOC_SOF_HDA | |||
254 | tristate | 286 | tristate |
255 | select SND_HDA_EXT_CORE if SND_SOC_SOF_HDA_LINK | 287 | select SND_HDA_EXT_CORE if SND_SOC_SOF_HDA_LINK |
256 | select SND_SOC_HDAC_HDA if SND_SOC_SOF_HDA_AUDIO_CODEC | 288 | select SND_SOC_HDAC_HDA if SND_SOC_SOF_HDA_AUDIO_CODEC |
289 | select SND_INTEL_NHLT if ACPI | ||
257 | help | 290 | help |
258 | This option is not user-selectable but automagically handled by | 291 | This option is not user-selectable but automagically handled by |
259 | 'select' statements at a higher level | 292 | 'select' statements at a higher level |
diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index fd2e26d79796..8dc7a5558da4 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c | |||
@@ -46,7 +46,9 @@ const struct snd_sof_dsp_ops sof_apl_ops = { | |||
46 | 46 | ||
47 | /* ipc */ | 47 | /* ipc */ |
48 | .send_msg = hda_dsp_ipc_send_msg, | 48 | .send_msg = hda_dsp_ipc_send_msg, |
49 | .fw_ready = hda_dsp_ipc_fw_ready, | 49 | .fw_ready = sof_fw_ready, |
50 | .get_mailbox_offset = hda_dsp_ipc_get_mailbox_offset, | ||
51 | .get_window_offset = hda_dsp_ipc_get_window_offset, | ||
50 | 52 | ||
51 | .ipc_msg_data = hda_ipc_msg_data, | 53 | .ipc_msg_data = hda_ipc_msg_data, |
52 | .ipc_pcm_params = hda_ipc_pcm_params, | 54 | .ipc_pcm_params = hda_ipc_pcm_params, |
diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 70d524ef9bc0..e282179263e8 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c | |||
@@ -328,153 +328,6 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) | |||
328 | } | 328 | } |
329 | 329 | ||
330 | /* | 330 | /* |
331 | * IPC Firmware ready. | ||
332 | */ | ||
333 | static void bdw_get_windows(struct snd_sof_dev *sdev) | ||
334 | { | ||
335 | struct sof_ipc_window_elem *elem; | ||
336 | u32 outbox_offset = 0; | ||
337 | u32 stream_offset = 0; | ||
338 | u32 inbox_offset = 0; | ||
339 | u32 outbox_size = 0; | ||
340 | u32 stream_size = 0; | ||
341 | u32 inbox_size = 0; | ||
342 | int i; | ||
343 | |||
344 | if (!sdev->info_window) { | ||
345 | dev_err(sdev->dev, "error: have no window info\n"); | ||
346 | return; | ||
347 | } | ||
348 | |||
349 | for (i = 0; i < sdev->info_window->num_windows; i++) { | ||
350 | elem = &sdev->info_window->window[i]; | ||
351 | |||
352 | switch (elem->type) { | ||
353 | case SOF_IPC_REGION_UPBOX: | ||
354 | inbox_offset = elem->offset + MBOX_OFFSET; | ||
355 | inbox_size = elem->size; | ||
356 | snd_sof_debugfs_io_item(sdev, | ||
357 | sdev->bar[BDW_DSP_BAR] + | ||
358 | inbox_offset, | ||
359 | elem->size, "inbox", | ||
360 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
361 | break; | ||
362 | case SOF_IPC_REGION_DOWNBOX: | ||
363 | outbox_offset = elem->offset + MBOX_OFFSET; | ||
364 | outbox_size = elem->size; | ||
365 | snd_sof_debugfs_io_item(sdev, | ||
366 | sdev->bar[BDW_DSP_BAR] + | ||
367 | outbox_offset, | ||
368 | elem->size, "outbox", | ||
369 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
370 | break; | ||
371 | case SOF_IPC_REGION_TRACE: | ||
372 | snd_sof_debugfs_io_item(sdev, | ||
373 | sdev->bar[BDW_DSP_BAR] + | ||
374 | elem->offset + | ||
375 | MBOX_OFFSET, | ||
376 | elem->size, "etrace", | ||
377 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
378 | break; | ||
379 | case SOF_IPC_REGION_DEBUG: | ||
380 | snd_sof_debugfs_io_item(sdev, | ||
381 | sdev->bar[BDW_DSP_BAR] + | ||
382 | elem->offset + | ||
383 | MBOX_OFFSET, | ||
384 | elem->size, "debug", | ||
385 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
386 | break; | ||
387 | case SOF_IPC_REGION_STREAM: | ||
388 | stream_offset = elem->offset + MBOX_OFFSET; | ||
389 | stream_size = elem->size; | ||
390 | snd_sof_debugfs_io_item(sdev, | ||
391 | sdev->bar[BDW_DSP_BAR] + | ||
392 | stream_offset, | ||
393 | elem->size, "stream", | ||
394 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
395 | break; | ||
396 | case SOF_IPC_REGION_REGS: | ||
397 | snd_sof_debugfs_io_item(sdev, | ||
398 | sdev->bar[BDW_DSP_BAR] + | ||
399 | elem->offset + | ||
400 | MBOX_OFFSET, | ||
401 | elem->size, "regs", | ||
402 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
403 | break; | ||
404 | case SOF_IPC_REGION_EXCEPTION: | ||
405 | sdev->dsp_oops_offset = elem->offset + MBOX_OFFSET; | ||
406 | snd_sof_debugfs_io_item(sdev, | ||
407 | sdev->bar[BDW_DSP_BAR] + | ||
408 | elem->offset + | ||
409 | MBOX_OFFSET, | ||
410 | elem->size, "exception", | ||
411 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
412 | break; | ||
413 | default: | ||
414 | dev_err(sdev->dev, "error: get illegal window info\n"); | ||
415 | return; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | if (outbox_size == 0 || inbox_size == 0) { | ||
420 | dev_err(sdev->dev, "error: get illegal mailbox window\n"); | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, | ||
425 | outbox_offset, outbox_size); | ||
426 | sdev->stream_box.offset = stream_offset; | ||
427 | sdev->stream_box.size = stream_size; | ||
428 | |||
429 | dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", | ||
430 | inbox_offset, inbox_size); | ||
431 | dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", | ||
432 | outbox_offset, outbox_size); | ||
433 | dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", | ||
434 | stream_offset, stream_size); | ||
435 | } | ||
436 | |||
437 | /* check for ABI compatibility and create memory windows on first boot */ | ||
438 | static int bdw_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) | ||
439 | { | ||
440 | struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; | ||
441 | u32 offset; | ||
442 | int ret; | ||
443 | |||
444 | /* mailbox must be on 4k boundary */ | ||
445 | offset = MBOX_OFFSET; | ||
446 | |||
447 | dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset %d\n", | ||
448 | msg_id, offset); | ||
449 | |||
450 | /* no need to re-check version/ABI for subsequent boots */ | ||
451 | if (!sdev->first_boot) | ||
452 | return 0; | ||
453 | |||
454 | /* copy data from the DSP FW ready offset */ | ||
455 | sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready, | ||
456 | sizeof(*fw_ready)); | ||
457 | |||
458 | snd_sof_dsp_mailbox_init(sdev, fw_ready->dspbox_offset, | ||
459 | fw_ready->dspbox_size, | ||
460 | fw_ready->hostbox_offset, | ||
461 | fw_ready->hostbox_size); | ||
462 | |||
463 | /* make sure ABI version is compatible */ | ||
464 | ret = snd_sof_ipc_valid(sdev); | ||
465 | if (ret < 0) | ||
466 | return ret; | ||
467 | |||
468 | /* now check for extended data */ | ||
469 | snd_sof_fw_parse_ext_data(sdev, sdev->mmio_bar, MBOX_OFFSET + | ||
470 | sizeof(struct sof_ipc_fw_ready)); | ||
471 | |||
472 | bdw_get_windows(sdev); | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * IPC Mailbox IO | 331 | * IPC Mailbox IO |
479 | */ | 332 | */ |
480 | 333 | ||
@@ -527,6 +380,16 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) | |||
527 | msg->reply_error = ret; | 380 | msg->reply_error = ret; |
528 | } | 381 | } |
529 | 382 | ||
383 | static int bdw_get_mailbox_offset(struct snd_sof_dev *sdev) | ||
384 | { | ||
385 | return MBOX_OFFSET; | ||
386 | } | ||
387 | |||
388 | static int bdw_get_window_offset(struct snd_sof_dev *sdev, u32 id) | ||
389 | { | ||
390 | return MBOX_OFFSET; | ||
391 | } | ||
392 | |||
530 | static void bdw_host_done(struct snd_sof_dev *sdev) | 393 | static void bdw_host_done(struct snd_sof_dev *sdev) |
531 | { | 394 | { |
532 | /* clear BUSY bit and set DONE bit - accept new messages */ | 395 | /* clear BUSY bit and set DONE bit - accept new messages */ |
@@ -613,11 +476,8 @@ static int bdw_probe(struct snd_sof_dev *sdev) | |||
613 | 476 | ||
614 | /* register our IRQ */ | 477 | /* register our IRQ */ |
615 | sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc); | 478 | sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc); |
616 | if (sdev->ipc_irq < 0) { | 479 | if (sdev->ipc_irq < 0) |
617 | dev_err(sdev->dev, "error: failed to get IRQ at index %d\n", | ||
618 | desc->irqindex_host_ipc); | ||
619 | return sdev->ipc_irq; | 480 | return sdev->ipc_irq; |
620 | } | ||
621 | 481 | ||
622 | dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq); | 482 | dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq); |
623 | ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq, | 483 | ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq, |
@@ -680,7 +540,9 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { | |||
680 | 540 | ||
681 | /* ipc */ | 541 | /* ipc */ |
682 | .send_msg = bdw_send_msg, | 542 | .send_msg = bdw_send_msg, |
683 | .fw_ready = bdw_fw_ready, | 543 | .fw_ready = sof_fw_ready, |
544 | .get_mailbox_offset = bdw_get_mailbox_offset, | ||
545 | .get_window_offset = bdw_get_window_offset, | ||
684 | 546 | ||
685 | .ipc_msg_data = intel_ipc_msg_data, | 547 | .ipc_msg_data = intel_ipc_msg_data, |
686 | .ipc_pcm_params = intel_ipc_pcm_params, | 548 | .ipc_pcm_params = intel_ipc_pcm_params, |
diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 107d711efc3f..5e7a6aaa627a 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c | |||
@@ -110,153 +110,6 @@ static void byt_dsp_done(struct snd_sof_dev *sdev); | |||
110 | static void byt_get_reply(struct snd_sof_dev *sdev); | 110 | static void byt_get_reply(struct snd_sof_dev *sdev); |
111 | 111 | ||
112 | /* | 112 | /* |
113 | * IPC Firmware ready. | ||
114 | */ | ||
115 | static void byt_get_windows(struct snd_sof_dev *sdev) | ||
116 | { | ||
117 | struct sof_ipc_window_elem *elem; | ||
118 | u32 outbox_offset = 0; | ||
119 | u32 stream_offset = 0; | ||
120 | u32 inbox_offset = 0; | ||
121 | u32 outbox_size = 0; | ||
122 | u32 stream_size = 0; | ||
123 | u32 inbox_size = 0; | ||
124 | int i; | ||
125 | |||
126 | if (!sdev->info_window) { | ||
127 | dev_err(sdev->dev, "error: have no window info\n"); | ||
128 | return; | ||
129 | } | ||
130 | |||
131 | for (i = 0; i < sdev->info_window->num_windows; i++) { | ||
132 | elem = &sdev->info_window->window[i]; | ||
133 | |||
134 | switch (elem->type) { | ||
135 | case SOF_IPC_REGION_UPBOX: | ||
136 | inbox_offset = elem->offset + MBOX_OFFSET; | ||
137 | inbox_size = elem->size; | ||
138 | snd_sof_debugfs_io_item(sdev, | ||
139 | sdev->bar[BYT_DSP_BAR] + | ||
140 | inbox_offset, | ||
141 | elem->size, "inbox", | ||
142 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
143 | break; | ||
144 | case SOF_IPC_REGION_DOWNBOX: | ||
145 | outbox_offset = elem->offset + MBOX_OFFSET; | ||
146 | outbox_size = elem->size; | ||
147 | snd_sof_debugfs_io_item(sdev, | ||
148 | sdev->bar[BYT_DSP_BAR] + | ||
149 | outbox_offset, | ||
150 | elem->size, "outbox", | ||
151 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
152 | break; | ||
153 | case SOF_IPC_REGION_TRACE: | ||
154 | snd_sof_debugfs_io_item(sdev, | ||
155 | sdev->bar[BYT_DSP_BAR] + | ||
156 | elem->offset + | ||
157 | MBOX_OFFSET, | ||
158 | elem->size, "etrace", | ||
159 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
160 | break; | ||
161 | case SOF_IPC_REGION_DEBUG: | ||
162 | snd_sof_debugfs_io_item(sdev, | ||
163 | sdev->bar[BYT_DSP_BAR] + | ||
164 | elem->offset + | ||
165 | MBOX_OFFSET, | ||
166 | elem->size, "debug", | ||
167 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
168 | break; | ||
169 | case SOF_IPC_REGION_STREAM: | ||
170 | stream_offset = elem->offset + MBOX_OFFSET; | ||
171 | stream_size = elem->size; | ||
172 | snd_sof_debugfs_io_item(sdev, | ||
173 | sdev->bar[BYT_DSP_BAR] + | ||
174 | stream_offset, | ||
175 | elem->size, "stream", | ||
176 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
177 | break; | ||
178 | case SOF_IPC_REGION_REGS: | ||
179 | snd_sof_debugfs_io_item(sdev, | ||
180 | sdev->bar[BYT_DSP_BAR] + | ||
181 | elem->offset + | ||
182 | MBOX_OFFSET, | ||
183 | elem->size, "regs", | ||
184 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
185 | break; | ||
186 | case SOF_IPC_REGION_EXCEPTION: | ||
187 | sdev->dsp_oops_offset = elem->offset + MBOX_OFFSET; | ||
188 | snd_sof_debugfs_io_item(sdev, | ||
189 | sdev->bar[BYT_DSP_BAR] + | ||
190 | elem->offset + | ||
191 | MBOX_OFFSET, | ||
192 | elem->size, "exception", | ||
193 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
194 | break; | ||
195 | default: | ||
196 | dev_err(sdev->dev, "error: get illegal window info\n"); | ||
197 | return; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | if (outbox_size == 0 || inbox_size == 0) { | ||
202 | dev_err(sdev->dev, "error: get illegal mailbox window\n"); | ||
203 | return; | ||
204 | } | ||
205 | |||
206 | snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, | ||
207 | outbox_offset, outbox_size); | ||
208 | sdev->stream_box.offset = stream_offset; | ||
209 | sdev->stream_box.size = stream_size; | ||
210 | |||
211 | dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", | ||
212 | inbox_offset, inbox_size); | ||
213 | dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", | ||
214 | outbox_offset, outbox_size); | ||
215 | dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", | ||
216 | stream_offset, stream_size); | ||
217 | } | ||
218 | |||
219 | /* check for ABI compatibility and create memory windows on first boot */ | ||
220 | static int byt_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) | ||
221 | { | ||
222 | struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; | ||
223 | u32 offset; | ||
224 | int ret; | ||
225 | |||
226 | /* mailbox must be on 4k boundary */ | ||
227 | offset = MBOX_OFFSET; | ||
228 | |||
229 | dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n", | ||
230 | msg_id, offset); | ||
231 | |||
232 | /* no need to re-check version/ABI for subsequent boots */ | ||
233 | if (!sdev->first_boot) | ||
234 | return 0; | ||
235 | |||
236 | /* copy data from the DSP FW ready offset */ | ||
237 | sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready, | ||
238 | sizeof(*fw_ready)); | ||
239 | |||
240 | snd_sof_dsp_mailbox_init(sdev, fw_ready->dspbox_offset, | ||
241 | fw_ready->dspbox_size, | ||
242 | fw_ready->hostbox_offset, | ||
243 | fw_ready->hostbox_size); | ||
244 | |||
245 | /* make sure ABI version is compatible */ | ||
246 | ret = snd_sof_ipc_valid(sdev); | ||
247 | if (ret < 0) | ||
248 | return ret; | ||
249 | |||
250 | /* now check for extended data */ | ||
251 | snd_sof_fw_parse_ext_data(sdev, sdev->mmio_bar, MBOX_OFFSET + | ||
252 | sizeof(struct sof_ipc_fw_ready)); | ||
253 | |||
254 | byt_get_windows(sdev); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Debug | 113 | * Debug |
261 | */ | 114 | */ |
262 | 115 | ||
@@ -423,6 +276,16 @@ static void byt_get_reply(struct snd_sof_dev *sdev) | |||
423 | msg->reply_error = ret; | 276 | msg->reply_error = ret; |
424 | } | 277 | } |
425 | 278 | ||
279 | static int byt_get_mailbox_offset(struct snd_sof_dev *sdev) | ||
280 | { | ||
281 | return MBOX_OFFSET; | ||
282 | } | ||
283 | |||
284 | static int byt_get_window_offset(struct snd_sof_dev *sdev, u32 id) | ||
285 | { | ||
286 | return MBOX_OFFSET; | ||
287 | } | ||
288 | |||
426 | static void byt_host_done(struct snd_sof_dev *sdev) | 289 | static void byt_host_done(struct snd_sof_dev *sdev) |
427 | { | 290 | { |
428 | /* clear BUSY bit and set DONE bit - accept new messages */ | 291 | /* clear BUSY bit and set DONE bit - accept new messages */ |
@@ -617,7 +480,9 @@ const struct snd_sof_dsp_ops sof_tng_ops = { | |||
617 | 480 | ||
618 | /* ipc */ | 481 | /* ipc */ |
619 | .send_msg = byt_send_msg, | 482 | .send_msg = byt_send_msg, |
620 | .fw_ready = byt_fw_ready, | 483 | .fw_ready = sof_fw_ready, |
484 | .get_mailbox_offset = byt_get_mailbox_offset, | ||
485 | .get_window_offset = byt_get_window_offset, | ||
621 | 486 | ||
622 | .ipc_msg_data = intel_ipc_msg_data, | 487 | .ipc_msg_data = intel_ipc_msg_data, |
623 | .ipc_pcm_params = intel_ipc_pcm_params, | 488 | .ipc_pcm_params = intel_ipc_pcm_params, |
@@ -728,11 +593,8 @@ static int byt_acpi_probe(struct snd_sof_dev *sdev) | |||
728 | irq: | 593 | irq: |
729 | /* register our IRQ */ | 594 | /* register our IRQ */ |
730 | sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc); | 595 | sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc); |
731 | if (sdev->ipc_irq < 0) { | 596 | if (sdev->ipc_irq < 0) |
732 | dev_err(sdev->dev, "error: failed to get IRQ at index %d\n", | ||
733 | desc->irqindex_host_ipc); | ||
734 | return sdev->ipc_irq; | 597 | return sdev->ipc_irq; |
735 | } | ||
736 | 598 | ||
737 | dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq); | 599 | dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq); |
738 | ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq, | 600 | ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq, |
@@ -779,7 +641,9 @@ const struct snd_sof_dsp_ops sof_byt_ops = { | |||
779 | 641 | ||
780 | /* ipc */ | 642 | /* ipc */ |
781 | .send_msg = byt_send_msg, | 643 | .send_msg = byt_send_msg, |
782 | .fw_ready = byt_fw_ready, | 644 | .fw_ready = sof_fw_ready, |
645 | .get_mailbox_offset = byt_get_mailbox_offset, | ||
646 | .get_window_offset = byt_get_window_offset, | ||
783 | 647 | ||
784 | .ipc_msg_data = intel_ipc_msg_data, | 648 | .ipc_msg_data = intel_ipc_msg_data, |
785 | .ipc_pcm_params = intel_ipc_pcm_params, | 649 | .ipc_pcm_params = intel_ipc_pcm_params, |
@@ -836,7 +700,9 @@ const struct snd_sof_dsp_ops sof_cht_ops = { | |||
836 | 700 | ||
837 | /* ipc */ | 701 | /* ipc */ |
838 | .send_msg = byt_send_msg, | 702 | .send_msg = byt_send_msg, |
839 | .fw_ready = byt_fw_ready, | 703 | .fw_ready = sof_fw_ready, |
704 | .get_mailbox_offset = byt_get_mailbox_offset, | ||
705 | .get_window_offset = byt_get_window_offset, | ||
840 | 706 | ||
841 | .ipc_msg_data = intel_ipc_msg_data, | 707 | .ipc_msg_data = intel_ipc_msg_data, |
842 | .ipc_pcm_params = intel_ipc_pcm_params, | 708 | .ipc_pcm_params = intel_ipc_pcm_params, |
diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index ffd8d4394537..4ddd73762d81 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c | |||
@@ -204,7 +204,9 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { | |||
204 | 204 | ||
205 | /* ipc */ | 205 | /* ipc */ |
206 | .send_msg = cnl_ipc_send_msg, | 206 | .send_msg = cnl_ipc_send_msg, |
207 | .fw_ready = hda_dsp_ipc_fw_ready, | 207 | .fw_ready = sof_fw_ready, |
208 | .get_mailbox_offset = hda_dsp_ipc_get_mailbox_offset, | ||
209 | .get_window_offset = hda_dsp_ipc_get_window_offset, | ||
208 | 210 | ||
209 | .ipc_msg_data = hda_ipc_msg_data, | 211 | .ipc_msg_data = hda_ipc_msg_data, |
210 | .ipc_pcm_params = hda_ipc_pcm_params, | 212 | .ipc_pcm_params = hda_ipc_pcm_params, |
@@ -293,3 +295,35 @@ const struct sof_intel_dsp_desc icl_chip_info = { | |||
293 | .ssp_base_offset = CNL_SSP_BASE_OFFSET, | 295 | .ssp_base_offset = CNL_SSP_BASE_OFFSET, |
294 | }; | 296 | }; |
295 | EXPORT_SYMBOL(icl_chip_info); | 297 | EXPORT_SYMBOL(icl_chip_info); |
298 | |||
299 | const struct sof_intel_dsp_desc tgl_chip_info = { | ||
300 | /* Tigerlake */ | ||
301 | .cores_num = 4, | ||
302 | .init_core_mask = 1, | ||
303 | .cores_mask = HDA_DSP_CORE_MASK(0), | ||
304 | .ipc_req = CNL_DSP_REG_HIPCIDR, | ||
305 | .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY, | ||
306 | .ipc_ack = CNL_DSP_REG_HIPCIDA, | ||
307 | .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, | ||
308 | .ipc_ctl = CNL_DSP_REG_HIPCCTL, | ||
309 | .rom_init_timeout = 300, | ||
310 | .ssp_count = ICL_SSP_COUNT, | ||
311 | .ssp_base_offset = CNL_SSP_BASE_OFFSET, | ||
312 | }; | ||
313 | EXPORT_SYMBOL(tgl_chip_info); | ||
314 | |||
315 | const struct sof_intel_dsp_desc ehl_chip_info = { | ||
316 | /* Elkhartlake */ | ||
317 | .cores_num = 4, | ||
318 | .init_core_mask = 1, | ||
319 | .cores_mask = HDA_DSP_CORE_MASK(0), | ||
320 | .ipc_req = CNL_DSP_REG_HIPCIDR, | ||
321 | .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY, | ||
322 | .ipc_ack = CNL_DSP_REG_HIPCIDA, | ||
323 | .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, | ||
324 | .ipc_ctl = CNL_DSP_REG_HIPCCTL, | ||
325 | .rom_init_timeout = 300, | ||
326 | .ssp_count = ICL_SSP_COUNT, | ||
327 | .ssp_base_offset = CNL_SSP_BASE_OFFSET, | ||
328 | }; | ||
329 | EXPORT_SYMBOL(ehl_chip_info); | ||
diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index a7e6d8227df6..1d2babdda9dd 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c | |||
@@ -12,82 +12,27 @@ | |||
12 | #include "../sof-priv.h" | 12 | #include "../sof-priv.h" |
13 | #include "hda.h" | 13 | #include "hda.h" |
14 | 14 | ||
15 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | 15 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) |
16 | 16 | #include "../../codecs/hdac_hda.h" | |
17 | static const struct hdac_bus_ops bus_ops = { | 17 | #define sof_hda_ext_ops snd_soc_hdac_hda_get_ops() |
18 | .command = snd_hdac_bus_send_cmd, | 18 | #else |
19 | .get_response = snd_hdac_bus_get_response, | 19 | #define sof_hda_ext_ops NULL |
20 | }; | ||
21 | |||
22 | #endif | 20 | #endif |
23 | 21 | ||
24 | static void sof_hda_writel(u32 value, u32 __iomem *addr) | ||
25 | { | ||
26 | writel(value, addr); | ||
27 | } | ||
28 | |||
29 | static u32 sof_hda_readl(u32 __iomem *addr) | ||
30 | { | ||
31 | return readl(addr); | ||
32 | } | ||
33 | |||
34 | static void sof_hda_writew(u16 value, u16 __iomem *addr) | ||
35 | { | ||
36 | writew(value, addr); | ||
37 | } | ||
38 | |||
39 | static u16 sof_hda_readw(u16 __iomem *addr) | ||
40 | { | ||
41 | return readw(addr); | ||
42 | } | ||
43 | |||
44 | static void sof_hda_writeb(u8 value, u8 __iomem *addr) | ||
45 | { | ||
46 | writeb(value, addr); | ||
47 | } | ||
48 | |||
49 | static u8 sof_hda_readb(u8 __iomem *addr) | ||
50 | { | ||
51 | return readb(addr); | ||
52 | } | ||
53 | |||
54 | static int sof_hda_dma_alloc_pages(struct hdac_bus *bus, int type, | ||
55 | size_t size, struct snd_dma_buffer *buf) | ||
56 | { | ||
57 | return snd_dma_alloc_pages(type, bus->dev, size, buf); | ||
58 | } | ||
59 | |||
60 | static void sof_hda_dma_free_pages(struct hdac_bus *bus, | ||
61 | struct snd_dma_buffer *buf) | ||
62 | { | ||
63 | snd_dma_free_pages(buf); | ||
64 | } | ||
65 | |||
66 | static const struct hdac_io_ops io_ops = { | ||
67 | .reg_writel = sof_hda_writel, | ||
68 | .reg_readl = sof_hda_readl, | ||
69 | .reg_writew = sof_hda_writew, | ||
70 | .reg_readw = sof_hda_readw, | ||
71 | .reg_writeb = sof_hda_writeb, | ||
72 | .reg_readb = sof_hda_readb, | ||
73 | .dma_alloc_pages = sof_hda_dma_alloc_pages, | ||
74 | .dma_free_pages = sof_hda_dma_free_pages, | ||
75 | }; | ||
76 | |||
77 | /* | 22 | /* |
78 | * This can be used for both with/without hda link support. | 23 | * This can be used for both with/without hda link support. |
79 | */ | 24 | */ |
80 | void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, | 25 | void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev) |
81 | const struct hdac_ext_bus_ops *ext_ops) | ||
82 | { | 26 | { |
27 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
28 | snd_hdac_ext_bus_init(bus, dev, NULL, sof_hda_ext_ops); | ||
29 | #else /* CONFIG_SND_SOC_SOF_HDA */ | ||
83 | memset(bus, 0, sizeof(*bus)); | 30 | memset(bus, 0, sizeof(*bus)); |
84 | bus->dev = dev; | 31 | bus->dev = dev; |
85 | 32 | ||
86 | bus->io_ops = &io_ops; | ||
87 | INIT_LIST_HEAD(&bus->stream_list); | 33 | INIT_LIST_HEAD(&bus->stream_list); |
88 | 34 | ||
89 | bus->irq = -1; | 35 | bus->irq = -1; |
90 | bus->ext_ops = ext_ops; | ||
91 | 36 | ||
92 | /* | 37 | /* |
93 | * There is only one HDA bus atm. keep the index as 0. | 38 | * There is only one HDA bus atm. keep the index as 0. |
@@ -96,16 +41,5 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, | |||
96 | bus->idx = 0; | 41 | bus->idx = 0; |
97 | 42 | ||
98 | spin_lock_init(&bus->reg_lock); | 43 | spin_lock_init(&bus->reg_lock); |
99 | 44 | #endif /* CONFIG_SND_SOC_SOF_HDA */ | |
100 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
101 | INIT_LIST_HEAD(&bus->codec_list); | ||
102 | INIT_LIST_HEAD(&bus->hlink_list); | ||
103 | |||
104 | mutex_init(&bus->cmd_mutex); | ||
105 | mutex_init(&bus->lock); | ||
106 | bus->ops = &bus_ops; | ||
107 | INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); | ||
108 | bus->cmd_dma_state = true; | ||
109 | #endif | ||
110 | |||
111 | } | 45 | } |
diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index b8b37f082309..3ca6795a89ba 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <sound/hdaudio_ext.h> | 12 | #include <sound/hdaudio_ext.h> |
13 | #include <sound/hda_register.h> | ||
13 | #include <sound/hda_codec.h> | 14 | #include <sound/hda_codec.h> |
14 | #include <sound/hda_i915.h> | 15 | #include <sound/hda_i915.h> |
15 | #include <sound/sof.h> | 16 | #include <sound/sof.h> |
@@ -37,16 +38,55 @@ static void hda_codec_load_module(struct hda_codec *codec) | |||
37 | static void hda_codec_load_module(struct hda_codec *codec) {} | 38 | static void hda_codec_load_module(struct hda_codec *codec) {} |
38 | #endif | 39 | #endif |
39 | 40 | ||
41 | /* enable controller wake up event for all codecs with jack connectors */ | ||
42 | void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) | ||
43 | { | ||
44 | struct hda_bus *hbus = sof_to_hbus(sdev); | ||
45 | struct hdac_bus *bus = sof_to_bus(sdev); | ||
46 | struct hda_codec *codec; | ||
47 | unsigned int mask = 0; | ||
48 | |||
49 | list_for_each_codec(codec, hbus) | ||
50 | if (codec->jacktbl.used) | ||
51 | mask |= BIT(codec->core.addr); | ||
52 | |||
53 | snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask); | ||
54 | } | ||
55 | |||
56 | /* check jack status after resuming from suspend mode */ | ||
57 | void hda_codec_jack_check(struct snd_sof_dev *sdev) | ||
58 | { | ||
59 | struct hda_bus *hbus = sof_to_hbus(sdev); | ||
60 | struct hdac_bus *bus = sof_to_bus(sdev); | ||
61 | struct hda_codec *codec; | ||
62 | |||
63 | /* disable controller Wake Up event*/ | ||
64 | snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0); | ||
65 | |||
66 | list_for_each_codec(codec, hbus) | ||
67 | /* | ||
68 | * Wake up all jack-detecting codecs regardless whether an event | ||
69 | * has been recorded in STATESTS | ||
70 | */ | ||
71 | if (codec->jacktbl.used) | ||
72 | schedule_delayed_work(&codec->jackpoll_work, | ||
73 | codec->jackpoll_interval); | ||
74 | } | ||
75 | #else | ||
76 | void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) {} | ||
77 | void hda_codec_jack_check(struct snd_sof_dev *sdev) {} | ||
40 | #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */ | 78 | #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */ |
79 | EXPORT_SYMBOL(hda_codec_jack_wake_enable); | ||
80 | EXPORT_SYMBOL(hda_codec_jack_check); | ||
41 | 81 | ||
42 | /* probe individual codec */ | 82 | /* probe individual codec */ |
43 | static int hda_codec_probe(struct snd_sof_dev *sdev, int address) | 83 | static int hda_codec_probe(struct snd_sof_dev *sdev, int address) |
44 | { | 84 | { |
45 | struct hda_bus *hbus = sof_to_hbus(sdev); | ||
46 | struct hdac_device *hdev; | ||
47 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) | 85 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) |
48 | struct hdac_hda_priv *hda_priv; | 86 | struct hdac_hda_priv *hda_priv; |
49 | #endif | 87 | #endif |
88 | struct hda_bus *hbus = sof_to_hbus(sdev); | ||
89 | struct hdac_device *hdev; | ||
50 | u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) | | 90 | u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) | |
51 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; | 91 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; |
52 | u32 resp = -1; | 92 | u32 resp = -1; |
@@ -62,8 +102,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) | |||
62 | address, resp); | 102 | address, resp); |
63 | 103 | ||
64 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) | 104 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) |
65 | /* snd_hdac_ext_bus_device_exit will use kfree to free hdev */ | 105 | hda_priv = devm_kzalloc(sdev->dev, sizeof(*hda_priv), GFP_KERNEL); |
66 | hda_priv = kzalloc(sizeof(*hda_priv), GFP_KERNEL); | ||
67 | if (!hda_priv) | 106 | if (!hda_priv) |
68 | return -ENOMEM; | 107 | return -ENOMEM; |
69 | 108 | ||
@@ -82,8 +121,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) | |||
82 | 121 | ||
83 | return 0; | 122 | return 0; |
84 | #else | 123 | #else |
85 | /* snd_hdac_ext_bus_device_exit will use kfree to free hdev */ | 124 | hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL); |
86 | hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); | ||
87 | if (!hdev) | 125 | if (!hdev) |
88 | return -ENOMEM; | 126 | return -ENOMEM; |
89 | 127 | ||
diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index ea63f83a509b..bc41028a7a01 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c | |||
@@ -164,6 +164,9 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) | |||
164 | int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) | 164 | int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) |
165 | { | 165 | { |
166 | struct hdac_bus *bus = sof_to_bus(sdev); | 166 | struct hdac_bus *bus = sof_to_bus(sdev); |
167 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
168 | struct hdac_ext_link *hlink; | ||
169 | #endif | ||
167 | struct hdac_stream *stream; | 170 | struct hdac_stream *stream; |
168 | int sd_offset, ret = 0; | 171 | int sd_offset, ret = 0; |
169 | 172 | ||
@@ -173,11 +176,6 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) | |||
173 | hda_dsp_ctrl_misc_clock_gating(sdev, false); | 176 | hda_dsp_ctrl_misc_clock_gating(sdev, false); |
174 | 177 | ||
175 | if (full_reset) { | 178 | if (full_reset) { |
176 | /* clear WAKESTS */ | ||
177 | snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, | ||
178 | SOF_HDA_WAKESTS_INT_MASK, | ||
179 | SOF_HDA_WAKESTS_INT_MASK); | ||
180 | |||
181 | /* reset HDA controller */ | 179 | /* reset HDA controller */ |
182 | ret = hda_dsp_ctrl_link_reset(sdev, true); | 180 | ret = hda_dsp_ctrl_link_reset(sdev, true); |
183 | if (ret < 0) { | 181 | if (ret < 0) { |
@@ -245,13 +243,18 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) | |||
245 | SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, | 243 | SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, |
246 | SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); | 244 | SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); |
247 | 245 | ||
248 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
249 | /* program the position buffer */ | 246 | /* program the position buffer */ |
250 | if (bus->use_posbuf && bus->posbuf.addr) { | 247 | if (bus->use_posbuf && bus->posbuf.addr) { |
251 | snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr); | 248 | snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPLBASE, |
252 | snd_hdac_chip_writel(bus, DPUBASE, | 249 | (u32)bus->posbuf.addr); |
253 | upper_32_bits(bus->posbuf.addr)); | 250 | snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_ADSP_DPUBASE, |
251 | upper_32_bits(bus->posbuf.addr)); | ||
254 | } | 252 | } |
253 | |||
254 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
255 | /* Reset stream-to-link mapping */ | ||
256 | list_for_each_entry(hlink, &bus->hlink_list, list) | ||
257 | writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); | ||
255 | #endif | 258 | #endif |
256 | 259 | ||
257 | bus->chip_init = true; | 260 | bus->chip_init = true; |
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index a514f9cf5c9a..8796f385be76 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c | |||
@@ -210,9 +210,13 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, | |||
210 | int stream_tag; | 210 | int stream_tag; |
211 | int ret; | 211 | int ret; |
212 | 212 | ||
213 | link_dev = hda_link_stream_assign(bus, substream); | 213 | /* get stored dma data if resuming from system suspend */ |
214 | if (!link_dev) | 214 | link_dev = snd_soc_dai_get_dma_data(dai, substream); |
215 | return -EBUSY; | 215 | if (!link_dev) { |
216 | link_dev = hda_link_stream_assign(bus, substream); | ||
217 | if (!link_dev) | ||
218 | return -EBUSY; | ||
219 | } | ||
216 | 220 | ||
217 | stream_tag = hdac_stream(link_dev)->stream_tag; | 221 | stream_tag = hdac_stream(link_dev)->stream_tag; |
218 | 222 | ||
@@ -226,8 +230,6 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, | |||
226 | 230 | ||
227 | snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); | 231 | snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); |
228 | 232 | ||
229 | hda_stream->hw_params_upon_resume = 0; | ||
230 | |||
231 | link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name); | 233 | link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name); |
232 | if (!link) | 234 | if (!link) |
233 | return -EINVAL; | 235 | return -EINVAL; |
@@ -267,8 +269,7 @@ static int hda_link_pcm_prepare(struct snd_pcm_substream *substream, | |||
267 | 269 | ||
268 | hda_stream = hstream_to_sof_hda_stream(link_dev); | 270 | hda_stream = hstream_to_sof_hda_stream(link_dev); |
269 | 271 | ||
270 | /* setup hw_params again only if resuming from system suspend */ | 272 | if (link_dev->link_prepared) |
271 | if (!hda_stream->hw_params_upon_resume) | ||
272 | return 0; | 273 | return 0; |
273 | 274 | ||
274 | dev_dbg(sdev->dev, "hda: prepare stream dir %d\n", substream->stream); | 275 | dev_dbg(sdev->dev, "hda: prepare stream dir %d\n", substream->stream); |
@@ -317,22 +318,25 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, | |||
317 | snd_hdac_ext_link_stream_start(link_dev); | 318 | snd_hdac_ext_link_stream_start(link_dev); |
318 | break; | 319 | break; |
319 | case SNDRV_PCM_TRIGGER_SUSPEND: | 320 | case SNDRV_PCM_TRIGGER_SUSPEND: |
321 | case SNDRV_PCM_TRIGGER_STOP: | ||
320 | /* | 322 | /* |
321 | * clear and release link DMA channel. It will be assigned when | 323 | * clear link DMA channel. It will be assigned when |
322 | * hw_params is set up again after resume. | 324 | * hw_params is set up again after resume. |
323 | */ | 325 | */ |
324 | ret = hda_link_config_ipc(hda_stream, dai->name, | 326 | ret = hda_link_config_ipc(hda_stream, dai->name, |
325 | DMA_CHAN_INVALID, substream->stream); | 327 | DMA_CHAN_INVALID, substream->stream); |
326 | if (ret < 0) | 328 | if (ret < 0) |
327 | return ret; | 329 | return ret; |
328 | stream_tag = hdac_stream(link_dev)->stream_tag; | 330 | |
329 | snd_hdac_ext_link_clear_stream_id(link, stream_tag); | 331 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
330 | snd_hdac_ext_stream_release(link_dev, | 332 | stream_tag = hdac_stream(link_dev)->stream_tag; |
331 | HDAC_EXT_STREAM_TYPE_LINK); | 333 | snd_hdac_ext_link_clear_stream_id(link, stream_tag); |
334 | } | ||
335 | |||
336 | link_dev->link_prepared = 0; | ||
332 | 337 | ||
333 | /* fallthrough */ | 338 | /* fallthrough */ |
334 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 339 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
335 | case SNDRV_PCM_TRIGGER_STOP: | ||
336 | snd_hdac_ext_link_stream_clear(link_dev); | 340 | snd_hdac_ext_link_stream_clear(link_dev); |
337 | break; | 341 | break; |
338 | default: | 342 | default: |
@@ -369,8 +373,12 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream, | |||
369 | if (!link) | 373 | if (!link) |
370 | return -EINVAL; | 374 | return -EINVAL; |
371 | 375 | ||
372 | stream_tag = hdac_stream(link_dev)->stream_tag; | 376 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
373 | snd_hdac_ext_link_clear_stream_id(link, stream_tag); | 377 | stream_tag = hdac_stream(link_dev)->stream_tag; |
378 | snd_hdac_ext_link_clear_stream_id(link, stream_tag); | ||
379 | } | ||
380 | |||
381 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
374 | snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); | 382 | snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); |
375 | link_dev->link_prepared = 0; | 383 | link_dev->link_prepared = 0; |
376 | 384 | ||
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 91de4785b6a3..fb55a3c5afd0 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c | |||
@@ -282,7 +282,7 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) | |||
282 | HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0); | 282 | HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0); |
283 | } | 283 | } |
284 | 284 | ||
285 | static int hda_suspend(struct snd_sof_dev *sdev, int state) | 285 | static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) |
286 | { | 286 | { |
287 | struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; | 287 | struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; |
288 | const struct sof_intel_dsp_desc *chip = hda->desc; | 288 | const struct sof_intel_dsp_desc *chip = hda->desc; |
@@ -295,6 +295,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, int state) | |||
295 | hda_dsp_ipc_int_disable(sdev); | 295 | hda_dsp_ipc_int_disable(sdev); |
296 | 296 | ||
297 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | 297 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) |
298 | if (runtime_suspend) | ||
299 | hda_codec_jack_wake_enable(sdev); | ||
300 | |||
298 | /* power down all hda link */ | 301 | /* power down all hda link */ |
299 | snd_hdac_ext_bus_link_power_down_all(bus); | 302 | snd_hdac_ext_bus_link_power_down_all(bus); |
300 | #endif | 303 | #endif |
@@ -329,7 +332,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, int state) | |||
329 | return 0; | 332 | return 0; |
330 | } | 333 | } |
331 | 334 | ||
332 | static int hda_resume(struct snd_sof_dev *sdev) | 335 | static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) |
333 | { | 336 | { |
334 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | 337 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) |
335 | struct hdac_bus *bus = sof_to_bus(sdev); | 338 | struct hdac_bus *bus = sof_to_bus(sdev); |
@@ -343,7 +346,6 @@ static int hda_resume(struct snd_sof_dev *sdev) | |||
343 | */ | 346 | */ |
344 | snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); | 347 | snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0); |
345 | 348 | ||
346 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
347 | /* reset and start hda controller */ | 349 | /* reset and start hda controller */ |
348 | ret = hda_dsp_ctrl_init_chip(sdev, true); | 350 | ret = hda_dsp_ctrl_init_chip(sdev, true); |
349 | if (ret < 0) { | 351 | if (ret < 0) { |
@@ -352,46 +354,11 @@ static int hda_resume(struct snd_sof_dev *sdev) | |||
352 | return ret; | 354 | return ret; |
353 | } | 355 | } |
354 | 356 | ||
355 | hda_dsp_ctrl_misc_clock_gating(sdev, false); | ||
356 | |||
357 | /* Reset stream-to-link mapping */ | ||
358 | list_for_each_entry(hlink, &bus->hlink_list, list) | ||
359 | bus->io_ops->reg_writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); | ||
360 | |||
361 | hda_dsp_ctrl_misc_clock_gating(sdev, true); | ||
362 | #else | ||
363 | |||
364 | hda_dsp_ctrl_misc_clock_gating(sdev, false); | ||
365 | |||
366 | /* reset controller */ | ||
367 | ret = hda_dsp_ctrl_link_reset(sdev, true); | ||
368 | if (ret < 0) { | ||
369 | dev_err(sdev->dev, | ||
370 | "error: failed to reset controller during resume\n"); | ||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | /* take controller out of reset */ | ||
375 | ret = hda_dsp_ctrl_link_reset(sdev, false); | ||
376 | if (ret < 0) { | ||
377 | dev_err(sdev->dev, | ||
378 | "error: failed to ready controller during resume\n"); | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | /* enable hda bus irq */ | ||
383 | snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, | ||
384 | SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, | ||
385 | SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN); | ||
386 | |||
387 | hda_dsp_ctrl_misc_clock_gating(sdev, true); | ||
388 | #endif | ||
389 | |||
390 | /* enable ppcap interrupt */ | ||
391 | hda_dsp_ctrl_ppcap_enable(sdev, true); | ||
392 | hda_dsp_ctrl_ppcap_int_enable(sdev, true); | ||
393 | |||
394 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | 357 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) |
358 | /* check jack status */ | ||
359 | if (runtime_resume) | ||
360 | hda_codec_jack_check(sdev); | ||
361 | |||
395 | /* turn off the links that were off before suspend */ | 362 | /* turn off the links that were off before suspend */ |
396 | list_for_each_entry(hlink, &bus->hlink_list, list) { | 363 | list_for_each_entry(hlink, &bus->hlink_list, list) { |
397 | if (!hlink->ref_count) | 364 | if (!hlink->ref_count) |
@@ -403,19 +370,23 @@ static int hda_resume(struct snd_sof_dev *sdev) | |||
403 | snd_hdac_bus_stop_cmd_io(bus); | 370 | snd_hdac_bus_stop_cmd_io(bus); |
404 | #endif | 371 | #endif |
405 | 372 | ||
373 | /* enable ppcap interrupt */ | ||
374 | hda_dsp_ctrl_ppcap_enable(sdev, true); | ||
375 | hda_dsp_ctrl_ppcap_int_enable(sdev, true); | ||
376 | |||
406 | return 0; | 377 | return 0; |
407 | } | 378 | } |
408 | 379 | ||
409 | int hda_dsp_resume(struct snd_sof_dev *sdev) | 380 | int hda_dsp_resume(struct snd_sof_dev *sdev) |
410 | { | 381 | { |
411 | /* init hda controller. DSP cores will be powered up during fw boot */ | 382 | /* init hda controller. DSP cores will be powered up during fw boot */ |
412 | return hda_resume(sdev); | 383 | return hda_resume(sdev, false); |
413 | } | 384 | } |
414 | 385 | ||
415 | int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) | 386 | int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) |
416 | { | 387 | { |
417 | /* init hda controller. DSP cores will be powered up during fw boot */ | 388 | /* init hda controller. DSP cores will be powered up during fw boot */ |
418 | return hda_resume(sdev); | 389 | return hda_resume(sdev, true); |
419 | } | 390 | } |
420 | 391 | ||
421 | int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) | 392 | int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) |
@@ -431,19 +402,19 @@ int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) | |||
431 | return 0; | 402 | return 0; |
432 | } | 403 | } |
433 | 404 | ||
434 | int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state) | 405 | int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) |
435 | { | 406 | { |
436 | /* stop hda controller and power dsp off */ | 407 | /* stop hda controller and power dsp off */ |
437 | return hda_suspend(sdev, state); | 408 | return hda_suspend(sdev, true); |
438 | } | 409 | } |
439 | 410 | ||
440 | int hda_dsp_suspend(struct snd_sof_dev *sdev, int state) | 411 | int hda_dsp_suspend(struct snd_sof_dev *sdev) |
441 | { | 412 | { |
442 | struct hdac_bus *bus = sof_to_bus(sdev); | 413 | struct hdac_bus *bus = sof_to_bus(sdev); |
443 | int ret; | 414 | int ret; |
444 | 415 | ||
445 | /* stop hda controller and power dsp off */ | 416 | /* stop hda controller and power dsp off */ |
446 | ret = hda_suspend(sdev, state); | 417 | ret = hda_suspend(sdev, false); |
447 | if (ret < 0) { | 418 | if (ret < 0) { |
448 | dev_err(bus->dev, "error: suspending dsp\n"); | 419 | dev_err(bus->dev, "error: suspending dsp\n"); |
449 | return ret; | 420 | return ret; |
@@ -454,30 +425,24 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state) | |||
454 | 425 | ||
455 | int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) | 426 | int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) |
456 | { | 427 | { |
457 | struct hdac_bus *bus = sof_to_bus(sdev); | ||
458 | struct sof_intel_hda_stream *hda_stream; | ||
459 | struct hdac_ext_stream *stream; | ||
460 | struct hdac_stream *s; | ||
461 | |||
462 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | 428 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) |
429 | struct hdac_bus *bus = sof_to_bus(sdev); | ||
463 | struct snd_soc_pcm_runtime *rtd; | 430 | struct snd_soc_pcm_runtime *rtd; |
431 | struct hdac_ext_stream *stream; | ||
464 | struct hdac_ext_link *link; | 432 | struct hdac_ext_link *link; |
433 | struct hdac_stream *s; | ||
465 | const char *name; | 434 | const char *name; |
466 | int stream_tag; | 435 | int stream_tag; |
467 | #endif | ||
468 | 436 | ||
469 | /* set internal flag for BE */ | 437 | /* set internal flag for BE */ |
470 | list_for_each_entry(s, &bus->stream_list, list) { | 438 | list_for_each_entry(s, &bus->stream_list, list) { |
471 | stream = stream_to_hdac_ext_stream(s); | 439 | stream = stream_to_hdac_ext_stream(s); |
472 | hda_stream = container_of(stream, struct sof_intel_hda_stream, | 440 | |
473 | hda_stream); | ||
474 | hda_stream->hw_params_upon_resume = 1; | ||
475 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
476 | /* | 441 | /* |
477 | * clear and release stream. This should already be taken care | 442 | * clear stream. This should already be taken care for running |
478 | * for running streams when the SUSPEND trigger is called. | 443 | * streams when the SUSPEND trigger is called. But paused |
479 | * But paused streams do not get suspended, so this needs to be | 444 | * streams do not get suspended, so this needs to be done |
480 | * done explicitly during suspend. | 445 | * explicitly during suspend. |
481 | */ | 446 | */ |
482 | if (stream->link_substream) { | 447 | if (stream->link_substream) { |
483 | rtd = snd_pcm_substream_chip(stream->link_substream); | 448 | rtd = snd_pcm_substream_chip(stream->link_substream); |
@@ -485,12 +450,17 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) | |||
485 | link = snd_hdac_ext_bus_get_link(bus, name); | 450 | link = snd_hdac_ext_bus_get_link(bus, name); |
486 | if (!link) | 451 | if (!link) |
487 | return -EINVAL; | 452 | return -EINVAL; |
453 | |||
454 | stream->link_prepared = 0; | ||
455 | |||
456 | if (hdac_stream(stream)->direction == | ||
457 | SNDRV_PCM_STREAM_CAPTURE) | ||
458 | continue; | ||
459 | |||
488 | stream_tag = hdac_stream(stream)->stream_tag; | 460 | stream_tag = hdac_stream(stream)->stream_tag; |
489 | snd_hdac_ext_link_clear_stream_id(link, stream_tag); | 461 | snd_hdac_ext_link_clear_stream_id(link, stream_tag); |
490 | snd_hdac_ext_stream_release(stream, | ||
491 | HDAC_EXT_STREAM_TYPE_LINK); | ||
492 | } | 462 | } |
493 | #endif | ||
494 | } | 463 | } |
464 | #endif | ||
495 | return 0; | 465 | return 0; |
496 | } | 466 | } |
diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 2ecba91f5219..6aae6f18b3dc 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c | |||
@@ -266,156 +266,14 @@ out: | |||
266 | return ret; | 266 | return ret; |
267 | } | 267 | } |
268 | 268 | ||
269 | /* IPC Firmware ready */ | 269 | int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) |
270 | |||
271 | static void ipc_get_windows(struct snd_sof_dev *sdev) | ||
272 | { | 270 | { |
273 | struct sof_ipc_window_elem *elem; | 271 | return HDA_DSP_MBOX_UPLINK_OFFSET; |
274 | u32 outbox_offset = 0; | ||
275 | u32 stream_offset = 0; | ||
276 | u32 inbox_offset = 0; | ||
277 | u32 outbox_size = 0; | ||
278 | u32 stream_size = 0; | ||
279 | u32 inbox_size = 0; | ||
280 | int i; | ||
281 | |||
282 | if (!sdev->info_window) { | ||
283 | dev_err(sdev->dev, "error: have no window info\n"); | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | for (i = 0; i < sdev->info_window->num_windows; i++) { | ||
288 | elem = &sdev->info_window->window[i]; | ||
289 | |||
290 | switch (elem->type) { | ||
291 | case SOF_IPC_REGION_UPBOX: | ||
292 | inbox_offset = | ||
293 | elem->offset + SRAM_WINDOW_OFFSET(elem->id); | ||
294 | inbox_size = elem->size; | ||
295 | snd_sof_debugfs_io_item(sdev, | ||
296 | sdev->bar[HDA_DSP_BAR] + | ||
297 | inbox_offset, | ||
298 | elem->size, "inbox", | ||
299 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
300 | break; | ||
301 | case SOF_IPC_REGION_DOWNBOX: | ||
302 | outbox_offset = | ||
303 | elem->offset + SRAM_WINDOW_OFFSET(elem->id); | ||
304 | outbox_size = elem->size; | ||
305 | snd_sof_debugfs_io_item(sdev, | ||
306 | sdev->bar[HDA_DSP_BAR] + | ||
307 | outbox_offset, | ||
308 | elem->size, "outbox", | ||
309 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
310 | break; | ||
311 | case SOF_IPC_REGION_TRACE: | ||
312 | snd_sof_debugfs_io_item(sdev, | ||
313 | sdev->bar[HDA_DSP_BAR] + | ||
314 | elem->offset + | ||
315 | SRAM_WINDOW_OFFSET | ||
316 | (elem->id), | ||
317 | elem->size, "etrace", | ||
318 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
319 | break; | ||
320 | case SOF_IPC_REGION_DEBUG: | ||
321 | snd_sof_debugfs_io_item(sdev, | ||
322 | sdev->bar[HDA_DSP_BAR] + | ||
323 | elem->offset + | ||
324 | SRAM_WINDOW_OFFSET | ||
325 | (elem->id), | ||
326 | elem->size, "debug", | ||
327 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
328 | break; | ||
329 | case SOF_IPC_REGION_STREAM: | ||
330 | stream_offset = | ||
331 | elem->offset + SRAM_WINDOW_OFFSET(elem->id); | ||
332 | stream_size = elem->size; | ||
333 | snd_sof_debugfs_io_item(sdev, | ||
334 | sdev->bar[HDA_DSP_BAR] + | ||
335 | elem->offset + | ||
336 | SRAM_WINDOW_OFFSET | ||
337 | (elem->id), | ||
338 | elem->size, "stream", | ||
339 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
340 | break; | ||
341 | case SOF_IPC_REGION_REGS: | ||
342 | snd_sof_debugfs_io_item(sdev, | ||
343 | sdev->bar[HDA_DSP_BAR] + | ||
344 | elem->offset + | ||
345 | SRAM_WINDOW_OFFSET | ||
346 | (elem->id), | ||
347 | elem->size, "regs", | ||
348 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
349 | break; | ||
350 | case SOF_IPC_REGION_EXCEPTION: | ||
351 | sdev->dsp_oops_offset = elem->offset + | ||
352 | SRAM_WINDOW_OFFSET(elem->id); | ||
353 | snd_sof_debugfs_io_item(sdev, | ||
354 | sdev->bar[HDA_DSP_BAR] + | ||
355 | elem->offset + | ||
356 | SRAM_WINDOW_OFFSET | ||
357 | (elem->id), | ||
358 | elem->size, "exception", | ||
359 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
360 | break; | ||
361 | default: | ||
362 | dev_err(sdev->dev, "error: get illegal window info\n"); | ||
363 | return; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (outbox_size == 0 || inbox_size == 0) { | ||
368 | dev_err(sdev->dev, "error: get illegal mailbox window\n"); | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, | ||
373 | outbox_offset, outbox_size); | ||
374 | sdev->stream_box.offset = stream_offset; | ||
375 | sdev->stream_box.size = stream_size; | ||
376 | |||
377 | dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", | ||
378 | inbox_offset, inbox_size); | ||
379 | dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", | ||
380 | outbox_offset, outbox_size); | ||
381 | dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", | ||
382 | stream_offset, stream_size); | ||
383 | } | 272 | } |
384 | 273 | ||
385 | /* check for ABI compatibility and create memory windows on first boot */ | 274 | int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) |
386 | int hda_dsp_ipc_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) | ||
387 | { | 275 | { |
388 | struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; | 276 | return SRAM_WINDOW_OFFSET(id); |
389 | u32 offset; | ||
390 | int ret; | ||
391 | |||
392 | /* mailbox must be on 4k boundary */ | ||
393 | offset = HDA_DSP_MBOX_UPLINK_OFFSET; | ||
394 | |||
395 | dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n", | ||
396 | msg_id, offset); | ||
397 | |||
398 | /* no need to re-check version/ABI for subsequent boots */ | ||
399 | if (!sdev->first_boot) | ||
400 | return 0; | ||
401 | |||
402 | /* copy data from the DSP FW ready offset */ | ||
403 | sof_block_read(sdev, sdev->mmio_bar, offset, fw_ready, | ||
404 | sizeof(*fw_ready)); | ||
405 | |||
406 | /* make sure ABI version is compatible */ | ||
407 | ret = snd_sof_ipc_valid(sdev); | ||
408 | if (ret < 0) | ||
409 | return ret; | ||
410 | |||
411 | /* now check for extended data */ | ||
412 | snd_sof_fw_parse_ext_data(sdev, sdev->mmio_bar, | ||
413 | HDA_DSP_MBOX_UPLINK_OFFSET + | ||
414 | sizeof(struct sof_ipc_fw_ready)); | ||
415 | |||
416 | ipc_get_windows(sdev); | ||
417 | |||
418 | return 0; | ||
419 | } | 277 | } |
420 | 278 | ||
421 | void hda_ipc_msg_data(struct snd_sof_dev *sdev, | 279 | void hda_ipc_msg_data(struct snd_sof_dev *sdev, |
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index ae50839fddfe..c72e9a09eee1 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c | |||
@@ -19,13 +19,11 @@ | |||
19 | #include <sound/hda_register.h> | 19 | #include <sound/hda_register.h> |
20 | 20 | ||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <sound/intel-nhlt.h> | ||
22 | #include <sound/sof.h> | 23 | #include <sound/sof.h> |
23 | #include <sound/sof/xtensa.h> | 24 | #include <sound/sof/xtensa.h> |
24 | #include "../ops.h" | 25 | #include "../ops.h" |
25 | #include "hda.h" | 26 | #include "hda.h" |
26 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) | ||
27 | #include "../../codecs/hdac_hda.h" | ||
28 | #endif | ||
29 | 27 | ||
30 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | 28 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) |
31 | #include <sound/soc-acpi-intel-match.h> | 29 | #include <sound/soc-acpi-intel-match.h> |
@@ -46,6 +44,18 @@ struct hda_dsp_msg_code { | |||
46 | const char *msg; | 44 | const char *msg; |
47 | }; | 45 | }; |
48 | 46 | ||
47 | static bool hda_use_msi = IS_ENABLED(CONFIG_PCI); | ||
48 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG) | ||
49 | module_param_named(use_msi, hda_use_msi, bool, 0444); | ||
50 | MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode"); | ||
51 | #endif | ||
52 | |||
53 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
54 | static int hda_dmic_num = -1; | ||
55 | module_param_named(dmic_num, hda_dmic_num, int, 0444); | ||
56 | MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number"); | ||
57 | #endif | ||
58 | |||
49 | static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = { | 59 | static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = { |
50 | {HDA_DSP_ROM_FW_MANIFEST_LOADED, "status: manifest loaded"}, | 60 | {HDA_DSP_ROM_FW_MANIFEST_LOADED, "status: manifest loaded"}, |
51 | {HDA_DSP_ROM_FW_FW_LOADED, "status: fw loaded"}, | 61 | {HDA_DSP_ROM_FW_FW_LOADED, "status: fw loaded"}, |
@@ -236,7 +246,6 @@ static int hda_init(struct snd_sof_dev *sdev) | |||
236 | { | 246 | { |
237 | struct hda_bus *hbus; | 247 | struct hda_bus *hbus; |
238 | struct hdac_bus *bus; | 248 | struct hdac_bus *bus; |
239 | struct hdac_ext_bus_ops *ext_ops = NULL; | ||
240 | struct pci_dev *pci = to_pci_dev(sdev->dev); | 249 | struct pci_dev *pci = to_pci_dev(sdev->dev); |
241 | int ret; | 250 | int ret; |
242 | 251 | ||
@@ -244,10 +253,7 @@ static int hda_init(struct snd_sof_dev *sdev) | |||
244 | bus = sof_to_bus(sdev); | 253 | bus = sof_to_bus(sdev); |
245 | 254 | ||
246 | /* HDA bus init */ | 255 | /* HDA bus init */ |
247 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) | 256 | sof_hda_bus_init(bus, &pci->dev); |
248 | ext_ops = snd_soc_hdac_hda_get_ops(); | ||
249 | #endif | ||
250 | sof_hda_bus_init(bus, &pci->dev, ext_ops); | ||
251 | 257 | ||
252 | /* Workaround for a communication error on CFL (bko#199007) and CNL */ | 258 | /* Workaround for a communication error on CFL (bko#199007) and CNL */ |
253 | if (IS_CFL(pci) || IS_CNL(pci)) | 259 | if (IS_CFL(pci) || IS_CNL(pci)) |
@@ -284,8 +290,26 @@ static int hda_init(struct snd_sof_dev *sdev) | |||
284 | 290 | ||
285 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | 291 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) |
286 | 292 | ||
293 | static int check_nhlt_dmic(struct snd_sof_dev *sdev) | ||
294 | { | ||
295 | struct nhlt_acpi_table *nhlt; | ||
296 | int dmic_num; | ||
297 | |||
298 | nhlt = intel_nhlt_init(sdev->dev); | ||
299 | if (nhlt) { | ||
300 | dmic_num = intel_nhlt_get_dmic_geo(sdev->dev, nhlt); | ||
301 | intel_nhlt_free(nhlt); | ||
302 | if (dmic_num == 2 || dmic_num == 4) | ||
303 | return dmic_num; | ||
304 | } | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
287 | static const char *fixup_tplg_name(struct snd_sof_dev *sdev, | 309 | static const char *fixup_tplg_name(struct snd_sof_dev *sdev, |
288 | const char *sof_tplg_filename) | 310 | const char *sof_tplg_filename, |
311 | const char *idisp_str, | ||
312 | const char *dmic_str) | ||
289 | { | 313 | { |
290 | const char *tplg_filename = NULL; | 314 | const char *tplg_filename = NULL; |
291 | char *filename; | 315 | char *filename; |
@@ -299,7 +323,8 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, | |||
299 | split_ext = strsep(&filename, "."); | 323 | split_ext = strsep(&filename, "."); |
300 | if (split_ext) { | 324 | if (split_ext) { |
301 | tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, | 325 | tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, |
302 | "%s-idisp.tplg", split_ext); | 326 | "%s%s%s.tplg", |
327 | split_ext, idisp_str, dmic_str); | ||
303 | if (!tplg_filename) | 328 | if (!tplg_filename) |
304 | return NULL; | 329 | return NULL; |
305 | } | 330 | } |
@@ -318,6 +343,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev) | |||
318 | struct snd_sof_pdata *pdata = sdev->pdata; | 343 | struct snd_sof_pdata *pdata = sdev->pdata; |
319 | struct snd_soc_acpi_mach *mach; | 344 | struct snd_soc_acpi_mach *mach; |
320 | const char *tplg_filename; | 345 | const char *tplg_filename; |
346 | const char *idisp_str; | ||
347 | const char *dmic_str; | ||
348 | int dmic_num; | ||
321 | int codec_num = 0; | 349 | int codec_num = 0; |
322 | int i; | 350 | int i; |
323 | #endif | 351 | #endif |
@@ -388,17 +416,39 @@ static int hda_init_caps(struct snd_sof_dev *sdev) | |||
388 | dev_info(bus->dev, "using HDA machine driver %s now\n", | 416 | dev_info(bus->dev, "using HDA machine driver %s now\n", |
389 | hda_mach->drv_name); | 417 | hda_mach->drv_name); |
390 | 418 | ||
391 | /* fixup topology file for HDMI only platforms */ | 419 | if (codec_num == 1) |
392 | if (codec_num == 1) { | 420 | idisp_str = "-idisp"; |
393 | /* use local variable for readability */ | 421 | else |
394 | tplg_filename = pdata->tplg_filename; | 422 | idisp_str = ""; |
395 | tplg_filename = fixup_tplg_name(sdev, tplg_filename); | 423 | |
396 | if (!tplg_filename) { | 424 | /* first check NHLT for DMICs */ |
397 | hda_codec_i915_exit(sdev); | 425 | dmic_num = check_nhlt_dmic(sdev); |
398 | return ret; | 426 | |
399 | } | 427 | /* allow for module parameter override */ |
400 | pdata->tplg_filename = tplg_filename; | 428 | if (hda_dmic_num != -1) |
429 | dmic_num = hda_dmic_num; | ||
430 | |||
431 | switch (dmic_num) { | ||
432 | case 2: | ||
433 | dmic_str = "-2ch"; | ||
434 | break; | ||
435 | case 4: | ||
436 | dmic_str = "-4ch"; | ||
437 | break; | ||
438 | default: | ||
439 | dmic_num = 0; | ||
440 | dmic_str = ""; | ||
441 | break; | ||
401 | } | 442 | } |
443 | |||
444 | tplg_filename = pdata->tplg_filename; | ||
445 | tplg_filename = fixup_tplg_name(sdev, tplg_filename, | ||
446 | idisp_str, dmic_str); | ||
447 | if (!tplg_filename) { | ||
448 | hda_codec_i915_exit(sdev); | ||
449 | return ret; | ||
450 | } | ||
451 | pdata->tplg_filename = tplg_filename; | ||
402 | } | 452 | } |
403 | } | 453 | } |
404 | 454 | ||
@@ -535,11 +585,18 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) | |||
535 | * register our IRQ | 585 | * register our IRQ |
536 | * let's try to enable msi firstly | 586 | * let's try to enable msi firstly |
537 | * if it fails, use legacy interrupt mode | 587 | * if it fails, use legacy interrupt mode |
538 | * TODO: support interrupt mode selection with kernel parameter | 588 | * TODO: support msi multiple vectors |
539 | * support msi multiple vectors | ||
540 | */ | 589 | */ |
541 | ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI); | 590 | if (hda_use_msi && pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) > 0) { |
542 | if (ret < 0) { | 591 | dev_info(sdev->dev, "use msi interrupt mode\n"); |
592 | hdev->irq = pci_irq_vector(pci, 0); | ||
593 | /* ipc irq number is the same of hda irq */ | ||
594 | sdev->ipc_irq = hdev->irq; | ||
595 | /* initialised to "false" by kzalloc() */ | ||
596 | sdev->msi_enabled = true; | ||
597 | } | ||
598 | |||
599 | if (!sdev->msi_enabled) { | ||
543 | dev_info(sdev->dev, "use legacy interrupt mode\n"); | 600 | dev_info(sdev->dev, "use legacy interrupt mode\n"); |
544 | /* | 601 | /* |
545 | * in IO-APIC mode, hda->irq and ipc_irq are using the same | 602 | * in IO-APIC mode, hda->irq and ipc_irq are using the same |
@@ -547,13 +604,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) | |||
547 | */ | 604 | */ |
548 | hdev->irq = pci->irq; | 605 | hdev->irq = pci->irq; |
549 | sdev->ipc_irq = pci->irq; | 606 | sdev->ipc_irq = pci->irq; |
550 | sdev->msi_enabled = 0; | ||
551 | } else { | ||
552 | dev_info(sdev->dev, "use msi interrupt mode\n"); | ||
553 | hdev->irq = pci_irq_vector(pci, 0); | ||
554 | /* ipc irq number is the same of hda irq */ | ||
555 | sdev->ipc_irq = hdev->irq; | ||
556 | sdev->msi_enabled = 1; | ||
557 | } | 607 | } |
558 | 608 | ||
559 | dev_dbg(sdev->dev, "using HDA IRQ %d\n", hdev->irq); | 609 | dev_dbg(sdev->dev, "using HDA IRQ %d\n", hdev->irq); |
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index d9c17146200b..5591841a1b6f 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h | |||
@@ -175,7 +175,7 @@ | |||
175 | #define HDA_DSP_STACK_DUMP_SIZE 32 | 175 | #define HDA_DSP_STACK_DUMP_SIZE 32 |
176 | 176 | ||
177 | /* ROM status/error values */ | 177 | /* ROM status/error values */ |
178 | #define HDA_DSP_ROM_STS_MASK 0xf | 178 | #define HDA_DSP_ROM_STS_MASK GENMASK(23, 0) |
179 | #define HDA_DSP_ROM_INIT 0x1 | 179 | #define HDA_DSP_ROM_INIT 0x1 |
180 | #define HDA_DSP_ROM_FW_MANIFEST_LOADED 0x3 | 180 | #define HDA_DSP_ROM_FW_MANIFEST_LOADED 0x3 |
181 | #define HDA_DSP_ROM_FW_FW_LOADED 0x4 | 181 | #define HDA_DSP_ROM_FW_FW_LOADED 0x4 |
@@ -418,7 +418,6 @@ struct sof_intel_hda_stream { | |||
418 | struct snd_sof_dev *sdev; | 418 | struct snd_sof_dev *sdev; |
419 | struct hdac_ext_stream hda_stream; | 419 | struct hdac_ext_stream hda_stream; |
420 | struct sof_intel_stream stream; | 420 | struct sof_intel_stream stream; |
421 | int hw_params_upon_resume; /* set up hw_params upon resume */ | ||
422 | int host_reserved; /* reserve host DMA channel */ | 421 | int host_reserved; /* reserve host DMA channel */ |
423 | }; | 422 | }; |
424 | 423 | ||
@@ -453,9 +452,9 @@ int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, | |||
453 | void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); | 452 | void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); |
454 | void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); | 453 | void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); |
455 | 454 | ||
456 | int hda_dsp_suspend(struct snd_sof_dev *sdev, int state); | 455 | int hda_dsp_suspend(struct snd_sof_dev *sdev); |
457 | int hda_dsp_resume(struct snd_sof_dev *sdev); | 456 | int hda_dsp_resume(struct snd_sof_dev *sdev); |
458 | int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state); | 457 | int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev); |
459 | int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); | 458 | int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); |
460 | int hda_dsp_runtime_idle(struct snd_sof_dev *sdev); | 459 | int hda_dsp_runtime_idle(struct snd_sof_dev *sdev); |
461 | int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); | 460 | int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); |
@@ -520,7 +519,9 @@ int hda_ipc_pcm_params(struct snd_sof_dev *sdev, | |||
520 | int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, | 519 | int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, |
521 | struct snd_sof_ipc_msg *msg); | 520 | struct snd_sof_ipc_msg *msg); |
522 | void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev); | 521 | void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev); |
523 | int hda_dsp_ipc_fw_ready(struct snd_sof_dev *sdev, u32 msg_id); | 522 | int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev); |
523 | int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id); | ||
524 | |||
524 | irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context); | 525 | irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context); |
525 | irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context); | 526 | irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context); |
526 | int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); | 527 | int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); |
@@ -549,14 +550,15 @@ void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev); | |||
549 | /* | 550 | /* |
550 | * HDA bus operations. | 551 | * HDA bus operations. |
551 | */ | 552 | */ |
552 | void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev, | 553 | void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev); |
553 | const struct hdac_ext_bus_ops *ext_ops); | ||
554 | 554 | ||
555 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | 555 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) |
556 | /* | 556 | /* |
557 | * HDA Codec operations. | 557 | * HDA Codec operations. |
558 | */ | 558 | */ |
559 | int hda_codec_probe_bus(struct snd_sof_dev *sdev); | 559 | int hda_codec_probe_bus(struct snd_sof_dev *sdev); |
560 | void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev); | ||
561 | void hda_codec_jack_check(struct snd_sof_dev *sdev); | ||
560 | 562 | ||
561 | #endif /* CONFIG_SND_SOC_SOF_HDA */ | 563 | #endif /* CONFIG_SND_SOC_SOF_HDA */ |
562 | 564 | ||
@@ -597,5 +599,7 @@ extern const struct sof_intel_dsp_desc apl_chip_info; | |||
597 | extern const struct sof_intel_dsp_desc cnl_chip_info; | 599 | extern const struct sof_intel_dsp_desc cnl_chip_info; |
598 | extern const struct sof_intel_dsp_desc skl_chip_info; | 600 | extern const struct sof_intel_dsp_desc skl_chip_info; |
599 | extern const struct sof_intel_dsp_desc icl_chip_info; | 601 | extern const struct sof_intel_dsp_desc icl_chip_info; |
602 | extern const struct sof_intel_dsp_desc tgl_chip_info; | ||
603 | extern const struct sof_intel_dsp_desc ehl_chip_info; | ||
600 | 604 | ||
601 | #endif | 605 | #endif |
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 20dfca9c93b7..b2f359d2f7e5 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c | |||
@@ -17,12 +17,6 @@ | |||
17 | #include "sof-priv.h" | 17 | #include "sof-priv.h" |
18 | #include "ops.h" | 18 | #include "ops.h" |
19 | 19 | ||
20 | /* | ||
21 | * IPC message default size and timeout (ms). | ||
22 | * TODO: allow platforms to set size and timeout. | ||
23 | */ | ||
24 | #define IPC_TIMEOUT_MS 300 | ||
25 | |||
26 | static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_id); | 20 | static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_id); |
27 | static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd); | 21 | static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd); |
28 | 22 | ||
@@ -211,7 +205,7 @@ static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg, | |||
211 | 205 | ||
212 | /* wait for DSP IPC completion */ | 206 | /* wait for DSP IPC completion */ |
213 | ret = wait_event_timeout(msg->waitq, msg->ipc_complete, | 207 | ret = wait_event_timeout(msg->waitq, msg->ipc_complete, |
214 | msecs_to_jiffies(IPC_TIMEOUT_MS)); | 208 | msecs_to_jiffies(sdev->ipc_timeout)); |
215 | 209 | ||
216 | if (ret == 0) { | 210 | if (ret == 0) { |
217 | dev_err(sdev->dev, "error: ipc timed out for 0x%x size %d\n", | 211 | dev_err(sdev->dev, "error: ipc timed out for 0x%x size %d\n", |
diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 952a19091c58..d7f32745fefe 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c | |||
@@ -87,12 +87,180 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) | |||
87 | } | 87 | } |
88 | EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); | 88 | EXPORT_SYMBOL(snd_sof_fw_parse_ext_data); |
89 | 89 | ||
90 | /* | ||
91 | * IPC Firmware ready. | ||
92 | */ | ||
93 | static void sof_get_windows(struct snd_sof_dev *sdev) | ||
94 | { | ||
95 | struct sof_ipc_window_elem *elem; | ||
96 | u32 outbox_offset = 0; | ||
97 | u32 stream_offset = 0; | ||
98 | u32 inbox_offset = 0; | ||
99 | u32 outbox_size = 0; | ||
100 | u32 stream_size = 0; | ||
101 | u32 inbox_size = 0; | ||
102 | int window_offset; | ||
103 | int bar; | ||
104 | int i; | ||
105 | |||
106 | if (!sdev->info_window) { | ||
107 | dev_err(sdev->dev, "error: have no window info\n"); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM); | ||
112 | if (bar < 0) { | ||
113 | dev_err(sdev->dev, "error: have no bar mapping\n"); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | for (i = 0; i < sdev->info_window->num_windows; i++) { | ||
118 | elem = &sdev->info_window->window[i]; | ||
119 | |||
120 | window_offset = snd_sof_dsp_get_window_offset(sdev, elem->id); | ||
121 | if (window_offset < 0) { | ||
122 | dev_warn(sdev->dev, "warn: no offset for window %d\n", | ||
123 | elem->id); | ||
124 | continue; | ||
125 | } | ||
126 | |||
127 | switch (elem->type) { | ||
128 | case SOF_IPC_REGION_UPBOX: | ||
129 | inbox_offset = window_offset + elem->offset; | ||
130 | inbox_size = elem->size; | ||
131 | snd_sof_debugfs_io_item(sdev, | ||
132 | sdev->bar[bar] + | ||
133 | inbox_offset, | ||
134 | elem->size, "inbox", | ||
135 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
136 | break; | ||
137 | case SOF_IPC_REGION_DOWNBOX: | ||
138 | outbox_offset = window_offset + elem->offset; | ||
139 | outbox_size = elem->size; | ||
140 | snd_sof_debugfs_io_item(sdev, | ||
141 | sdev->bar[bar] + | ||
142 | outbox_offset, | ||
143 | elem->size, "outbox", | ||
144 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
145 | break; | ||
146 | case SOF_IPC_REGION_TRACE: | ||
147 | snd_sof_debugfs_io_item(sdev, | ||
148 | sdev->bar[bar] + | ||
149 | window_offset + | ||
150 | elem->offset, | ||
151 | elem->size, "etrace", | ||
152 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
153 | break; | ||
154 | case SOF_IPC_REGION_DEBUG: | ||
155 | snd_sof_debugfs_io_item(sdev, | ||
156 | sdev->bar[bar] + | ||
157 | window_offset + | ||
158 | elem->offset, | ||
159 | elem->size, "debug", | ||
160 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
161 | break; | ||
162 | case SOF_IPC_REGION_STREAM: | ||
163 | stream_offset = window_offset + elem->offset; | ||
164 | stream_size = elem->size; | ||
165 | snd_sof_debugfs_io_item(sdev, | ||
166 | sdev->bar[bar] + | ||
167 | stream_offset, | ||
168 | elem->size, "stream", | ||
169 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
170 | break; | ||
171 | case SOF_IPC_REGION_REGS: | ||
172 | snd_sof_debugfs_io_item(sdev, | ||
173 | sdev->bar[bar] + | ||
174 | window_offset + | ||
175 | elem->offset, | ||
176 | elem->size, "regs", | ||
177 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
178 | break; | ||
179 | case SOF_IPC_REGION_EXCEPTION: | ||
180 | sdev->dsp_oops_offset = window_offset + elem->offset; | ||
181 | snd_sof_debugfs_io_item(sdev, | ||
182 | sdev->bar[bar] + | ||
183 | window_offset + | ||
184 | elem->offset, | ||
185 | elem->size, "exception", | ||
186 | SOF_DEBUGFS_ACCESS_D0_ONLY); | ||
187 | break; | ||
188 | default: | ||
189 | dev_err(sdev->dev, "error: get illegal window info\n"); | ||
190 | return; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | if (outbox_size == 0 || inbox_size == 0) { | ||
195 | dev_err(sdev->dev, "error: get illegal mailbox window\n"); | ||
196 | return; | ||
197 | } | ||
198 | |||
199 | snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size, | ||
200 | outbox_offset, outbox_size); | ||
201 | sdev->stream_box.offset = stream_offset; | ||
202 | sdev->stream_box.size = stream_size; | ||
203 | |||
204 | dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n", | ||
205 | inbox_offset, inbox_size); | ||
206 | dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n", | ||
207 | outbox_offset, outbox_size); | ||
208 | dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n", | ||
209 | stream_offset, stream_size); | ||
210 | } | ||
211 | |||
212 | /* check for ABI compatibility and create memory windows on first boot */ | ||
213 | int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id) | ||
214 | { | ||
215 | struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready; | ||
216 | int offset; | ||
217 | int bar; | ||
218 | int ret; | ||
219 | |||
220 | /* mailbox must be on 4k boundary */ | ||
221 | offset = snd_sof_dsp_get_mailbox_offset(sdev); | ||
222 | if (offset < 0) { | ||
223 | dev_err(sdev->dev, "error: have no mailbox offset\n"); | ||
224 | return offset; | ||
225 | } | ||
226 | |||
227 | bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM); | ||
228 | if (bar < 0) { | ||
229 | dev_err(sdev->dev, "error: have no bar mapping\n"); | ||
230 | return -EINVAL; | ||
231 | } | ||
232 | |||
233 | dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n", | ||
234 | msg_id, offset); | ||
235 | |||
236 | /* no need to re-check version/ABI for subsequent boots */ | ||
237 | if (!sdev->first_boot) | ||
238 | return 0; | ||
239 | |||
240 | /* copy data from the DSP FW ready offset */ | ||
241 | sof_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready)); | ||
242 | |||
243 | /* make sure ABI version is compatible */ | ||
244 | ret = snd_sof_ipc_valid(sdev); | ||
245 | if (ret < 0) | ||
246 | return ret; | ||
247 | |||
248 | /* now check for extended data */ | ||
249 | snd_sof_fw_parse_ext_data(sdev, bar, offset + | ||
250 | sizeof(struct sof_ipc_fw_ready)); | ||
251 | |||
252 | sof_get_windows(sdev); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | EXPORT_SYMBOL(sof_fw_ready); | ||
257 | |||
90 | /* generic module parser for mmaped DSPs */ | 258 | /* generic module parser for mmaped DSPs */ |
91 | int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, | 259 | int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, |
92 | struct snd_sof_mod_hdr *module) | 260 | struct snd_sof_mod_hdr *module) |
93 | { | 261 | { |
94 | struct snd_sof_blk_hdr *block; | 262 | struct snd_sof_blk_hdr *block; |
95 | int count; | 263 | int count, bar; |
96 | u32 offset; | 264 | u32 offset; |
97 | size_t remaining; | 265 | size_t remaining; |
98 | 266 | ||
@@ -123,11 +291,19 @@ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, | |||
123 | 291 | ||
124 | switch (block->type) { | 292 | switch (block->type) { |
125 | case SOF_FW_BLK_TYPE_RSRVD0: | 293 | case SOF_FW_BLK_TYPE_RSRVD0: |
126 | case SOF_FW_BLK_TYPE_SRAM...SOF_FW_BLK_TYPE_RSRVD14: | 294 | case SOF_FW_BLK_TYPE_ROM...SOF_FW_BLK_TYPE_RSRVD14: |
127 | continue; /* not handled atm */ | 295 | continue; /* not handled atm */ |
128 | case SOF_FW_BLK_TYPE_IRAM: | 296 | case SOF_FW_BLK_TYPE_IRAM: |
129 | case SOF_FW_BLK_TYPE_DRAM: | 297 | case SOF_FW_BLK_TYPE_DRAM: |
298 | case SOF_FW_BLK_TYPE_SRAM: | ||
130 | offset = block->offset; | 299 | offset = block->offset; |
300 | bar = snd_sof_dsp_get_bar_index(sdev, block->type); | ||
301 | if (bar < 0) { | ||
302 | dev_err(sdev->dev, | ||
303 | "error: no BAR mapping for block type 0x%x\n", | ||
304 | block->type); | ||
305 | return bar; | ||
306 | } | ||
131 | break; | 307 | break; |
132 | default: | 308 | default: |
133 | dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n", | 309 | dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n", |
@@ -145,7 +321,7 @@ int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev, | |||
145 | block->size); | 321 | block->size); |
146 | return -EINVAL; | 322 | return -EINVAL; |
147 | } | 323 | } |
148 | snd_sof_dsp_block_write(sdev, sdev->mmio_bar, offset, | 324 | snd_sof_dsp_block_write(sdev, bar, offset, |
149 | block + 1, block->size); | 325 | block + 1, block->size); |
150 | 326 | ||
151 | if (remaining < block->size) { | 327 | if (remaining < block->size) { |
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index b1c27615b805..824d36fe59fd 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h | |||
@@ -100,6 +100,43 @@ static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev) | |||
100 | return 0; | 100 | return 0; |
101 | } | 101 | } |
102 | 102 | ||
103 | /* misc */ | ||
104 | |||
105 | /** | ||
106 | * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index | ||
107 | * | ||
108 | * @sdev: sof device | ||
109 | * @type: section type as described by snd_sof_fw_blk_type | ||
110 | * | ||
111 | * Returns the corresponding BAR index (a positive integer) or -EINVAL | ||
112 | * in case there is no mapping | ||
113 | */ | ||
114 | static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type) | ||
115 | { | ||
116 | if (sof_ops(sdev)->get_bar_index) | ||
117 | return sof_ops(sdev)->get_bar_index(sdev, type); | ||
118 | |||
119 | return sdev->mmio_bar; | ||
120 | } | ||
121 | |||
122 | static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev) | ||
123 | { | ||
124 | if (sof_ops(sdev)->get_mailbox_offset) | ||
125 | return sof_ops(sdev)->get_mailbox_offset(sdev); | ||
126 | |||
127 | dev_err(sdev->dev, "error: %s not defined\n", __func__); | ||
128 | return -ENOTSUPP; | ||
129 | } | ||
130 | |||
131 | static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev, | ||
132 | u32 id) | ||
133 | { | ||
134 | if (sof_ops(sdev)->get_window_offset) | ||
135 | return sof_ops(sdev)->get_window_offset(sdev, id); | ||
136 | |||
137 | dev_err(sdev->dev, "error: %s not defined\n", __func__); | ||
138 | return -ENOTSUPP; | ||
139 | } | ||
103 | /* power management */ | 140 | /* power management */ |
104 | static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) | 141 | static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) |
105 | { | 142 | { |
@@ -109,10 +146,10 @@ static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev) | |||
109 | return 0; | 146 | return 0; |
110 | } | 147 | } |
111 | 148 | ||
112 | static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev, int state) | 149 | static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev) |
113 | { | 150 | { |
114 | if (sof_ops(sdev)->suspend) | 151 | if (sof_ops(sdev)->suspend) |
115 | return sof_ops(sdev)->suspend(sdev, state); | 152 | return sof_ops(sdev)->suspend(sdev); |
116 | 153 | ||
117 | return 0; | 154 | return 0; |
118 | } | 155 | } |
@@ -125,11 +162,10 @@ static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev) | |||
125 | return 0; | 162 | return 0; |
126 | } | 163 | } |
127 | 164 | ||
128 | static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev, | 165 | static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev) |
129 | int state) | ||
130 | { | 166 | { |
131 | if (sof_ops(sdev)->runtime_suspend) | 167 | if (sof_ops(sdev)->runtime_suspend) |
132 | return sof_ops(sdev)->runtime_suspend(sdev, state); | 168 | return sof_ops(sdev)->runtime_suspend(sdev); |
133 | 169 | ||
134 | return 0; | 170 | return 0; |
135 | } | 171 | } |
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 334e9d59b1ba..e3f6a6dc0f36 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c | |||
@@ -208,11 +208,31 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream, | |||
208 | if (ret < 0) | 208 | if (ret < 0) |
209 | return ret; | 209 | return ret; |
210 | 210 | ||
211 | spcm->prepared[substream->stream] = true; | ||
212 | |||
211 | /* save pcm hw_params */ | 213 | /* save pcm hw_params */ |
212 | memcpy(&spcm->params[substream->stream], params, sizeof(*params)); | 214 | memcpy(&spcm->params[substream->stream], params, sizeof(*params)); |
213 | 215 | ||
214 | /* clear hw_params_upon_resume flag */ | 216 | return ret; |
215 | spcm->hw_params_upon_resume[substream->stream] = 0; | 217 | } |
218 | |||
219 | static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, | ||
220 | struct snd_sof_dev *sdev, | ||
221 | struct snd_sof_pcm *spcm) | ||
222 | { | ||
223 | struct sof_ipc_stream stream; | ||
224 | struct sof_ipc_reply reply; | ||
225 | int ret; | ||
226 | |||
227 | stream.hdr.size = sizeof(stream); | ||
228 | stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; | ||
229 | stream.comp_id = spcm->stream[substream->stream].comp_id; | ||
230 | |||
231 | /* send IPC to the DSP */ | ||
232 | ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, | ||
233 | sizeof(stream), &reply, sizeof(reply)); | ||
234 | if (!ret) | ||
235 | spcm->prepared[substream->stream] = false; | ||
216 | 236 | ||
217 | return ret; | 237 | return ret; |
218 | } | 238 | } |
@@ -224,8 +244,6 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) | |||
224 | snd_soc_rtdcom_lookup(rtd, DRV_NAME); | 244 | snd_soc_rtdcom_lookup(rtd, DRV_NAME); |
225 | struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); | 245 | struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); |
226 | struct snd_sof_pcm *spcm; | 246 | struct snd_sof_pcm *spcm; |
227 | struct sof_ipc_stream stream; | ||
228 | struct sof_ipc_reply reply; | ||
229 | int ret; | 247 | int ret; |
230 | 248 | ||
231 | /* nothing to do for BE */ | 249 | /* nothing to do for BE */ |
@@ -236,16 +254,13 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) | |||
236 | if (!spcm) | 254 | if (!spcm) |
237 | return -EINVAL; | 255 | return -EINVAL; |
238 | 256 | ||
257 | if (!spcm->prepared[substream->stream]) | ||
258 | return 0; | ||
259 | |||
239 | dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, | 260 | dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, |
240 | substream->stream); | 261 | substream->stream); |
241 | 262 | ||
242 | stream.hdr.size = sizeof(stream); | 263 | ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); |
243 | stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; | ||
244 | stream.comp_id = spcm->stream[substream->stream].comp_id; | ||
245 | |||
246 | /* send IPC to the DSP */ | ||
247 | ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, | ||
248 | sizeof(stream), &reply, sizeof(reply)); | ||
249 | 264 | ||
250 | snd_pcm_lib_free_pages(substream); | 265 | snd_pcm_lib_free_pages(substream); |
251 | 266 | ||
@@ -278,11 +293,7 @@ static int sof_pcm_prepare(struct snd_pcm_substream *substream) | |||
278 | if (!spcm) | 293 | if (!spcm) |
279 | return -EINVAL; | 294 | return -EINVAL; |
280 | 295 | ||
281 | /* | 296 | if (spcm->prepared[substream->stream]) |
282 | * check if hw_params needs to be set-up again. | ||
283 | * This is only needed when resuming from system sleep. | ||
284 | */ | ||
285 | if (!spcm->hw_params_upon_resume[substream->stream]) | ||
286 | return 0; | 297 | return 0; |
287 | 298 | ||
288 | dev_dbg(sdev->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id, | 299 | dev_dbg(sdev->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id, |
@@ -311,6 +322,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
311 | struct snd_sof_pcm *spcm; | 322 | struct snd_sof_pcm *spcm; |
312 | struct sof_ipc_stream stream; | 323 | struct sof_ipc_stream stream; |
313 | struct sof_ipc_reply reply; | 324 | struct sof_ipc_reply reply; |
325 | bool reset_hw_params = false; | ||
314 | int ret; | 326 | int ret; |
315 | 327 | ||
316 | /* nothing to do for BE */ | 328 | /* nothing to do for BE */ |
@@ -351,6 +363,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
351 | case SNDRV_PCM_TRIGGER_SUSPEND: | 363 | case SNDRV_PCM_TRIGGER_SUSPEND: |
352 | case SNDRV_PCM_TRIGGER_STOP: | 364 | case SNDRV_PCM_TRIGGER_STOP: |
353 | stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; | 365 | stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; |
366 | reset_hw_params = true; | ||
354 | break; | 367 | break; |
355 | default: | 368 | default: |
356 | dev_err(sdev->dev, "error: unhandled trigger cmd %d\n", cmd); | 369 | dev_err(sdev->dev, "error: unhandled trigger cmd %d\n", cmd); |
@@ -363,21 +376,10 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
363 | ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, | 376 | ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, |
364 | sizeof(stream), &reply, sizeof(reply)); | 377 | sizeof(stream), &reply, sizeof(reply)); |
365 | 378 | ||
366 | if (ret < 0 || cmd != SNDRV_PCM_TRIGGER_SUSPEND) | 379 | if (!ret && reset_hw_params) |
367 | return ret; | 380 | ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); |
368 | 381 | ||
369 | /* | 382 | return ret; |
370 | * The hw_free op is usually called when the pcm stream is closed. | ||
371 | * Since the stream is not closed during suspend, the DSP needs to be | ||
372 | * notified explicitly to free pcm to prevent errors upon resume. | ||
373 | */ | ||
374 | stream.hdr.size = sizeof(stream); | ||
375 | stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; | ||
376 | stream.comp_id = spcm->stream[substream->stream].comp_id; | ||
377 | |||
378 | /* send IPC to the DSP */ | ||
379 | return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, | ||
380 | sizeof(stream), &reply, sizeof(reply)); | ||
381 | } | 383 | } |
382 | 384 | ||
383 | static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) | 385 | static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream) |
@@ -481,6 +483,7 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) | |||
481 | spcm->stream[substream->stream].posn.host_posn = 0; | 483 | spcm->stream[substream->stream].posn.host_posn = 0; |
482 | spcm->stream[substream->stream].posn.dai_posn = 0; | 484 | spcm->stream[substream->stream].posn.dai_posn = 0; |
483 | spcm->stream[substream->stream].substream = substream; | 485 | spcm->stream[substream->stream].substream = substream; |
486 | spcm->prepared[substream->stream] = false; | ||
484 | 487 | ||
485 | ret = snd_sof_pcm_platform_open(sdev, substream); | 488 | ret = snd_sof_pcm_platform_open(sdev, substream); |
486 | if (ret < 0) | 489 | if (ret < 0) |
@@ -672,6 +675,9 @@ static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, | |||
672 | case SOF_DAI_INTEL_HDA: | 675 | case SOF_DAI_INTEL_HDA: |
673 | /* do nothing for HDA dai_link */ | 676 | /* do nothing for HDA dai_link */ |
674 | break; | 677 | break; |
678 | case SOF_DAI_INTEL_ALH: | ||
679 | /* do nothing for ALH dai_link */ | ||
680 | break; | ||
675 | default: | 681 | default: |
676 | dev_err(sdev->dev, "error: invalid DAI type %d\n", | 682 | dev_err(sdev->dev, "error: invalid DAI type %d\n", |
677 | dai->dai_config->type); | 683 | dai->dai_config->type); |
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 278abfd10490..e23beaeefe00 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c | |||
@@ -233,7 +233,7 @@ static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) | |||
233 | 233 | ||
234 | state = substream->runtime->status->state; | 234 | state = substream->runtime->status->state; |
235 | if (state == SNDRV_PCM_STATE_SUSPENDED) | 235 | if (state == SNDRV_PCM_STATE_SUSPENDED) |
236 | spcm->hw_params_upon_resume[dir] = 1; | 236 | spcm->prepared[dir] = false; |
237 | } | 237 | } |
238 | } | 238 | } |
239 | 239 | ||
@@ -377,9 +377,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) | |||
377 | 377 | ||
378 | /* power down all DSP cores */ | 378 | /* power down all DSP cores */ |
379 | if (runtime_suspend) | 379 | if (runtime_suspend) |
380 | ret = snd_sof_dsp_runtime_suspend(sdev, 0); | 380 | ret = snd_sof_dsp_runtime_suspend(sdev); |
381 | else | 381 | else |
382 | ret = snd_sof_dsp_suspend(sdev, 0); | 382 | ret = snd_sof_dsp_suspend(sdev); |
383 | if (ret < 0) | 383 | if (ret < 0) |
384 | dev_err(sdev->dev, | 384 | dev_err(sdev->dev, |
385 | "error: failed to power down DSP during suspend %d\n", | 385 | "error: failed to power down DSP during suspend %d\n", |
diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c new file mode 100644 index 000000000000..28a9692974e5 --- /dev/null +++ b/sound/soc/sof/sof-of-dev.c | |||
@@ -0,0 +1,143 @@ | |||
1 | // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
2 | // | ||
3 | // Copyright 2019 NXP | ||
4 | // | ||
5 | // Author: Daniel Baluta <daniel.baluta@nxp.com> | ||
6 | // | ||
7 | |||
8 | #include <linux/firmware.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/pm_runtime.h> | ||
11 | #include <sound/sof.h> | ||
12 | |||
13 | #include "ops.h" | ||
14 | |||
15 | extern struct snd_sof_dsp_ops sof_imx8_ops; | ||
16 | |||
17 | /* platform specific devices */ | ||
18 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) | ||
19 | static struct sof_dev_desc sof_of_imx8qxp_desc = { | ||
20 | .default_fw_path = "imx/sof", | ||
21 | .default_tplg_path = "imx/sof-tplg", | ||
22 | .nocodec_fw_filename = "sof-imx8.ri", | ||
23 | .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", | ||
24 | .ops = &sof_imx8_ops, | ||
25 | }; | ||
26 | #endif | ||
27 | |||
28 | static const struct dev_pm_ops sof_of_pm = { | ||
29 | SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) | ||
30 | SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, | ||
31 | NULL) | ||
32 | }; | ||
33 | |||
34 | static void sof_of_probe_complete(struct device *dev) | ||
35 | { | ||
36 | /* allow runtime_pm */ | ||
37 | pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS); | ||
38 | pm_runtime_use_autosuspend(dev); | ||
39 | pm_runtime_enable(dev); | ||
40 | } | ||
41 | |||
42 | static int sof_of_probe(struct platform_device *pdev) | ||
43 | { | ||
44 | struct device *dev = &pdev->dev; | ||
45 | const struct sof_dev_desc *desc; | ||
46 | /*TODO: create a generic snd_soc_xxx_mach */ | ||
47 | struct snd_soc_acpi_mach *mach; | ||
48 | struct snd_sof_pdata *sof_pdata; | ||
49 | const struct snd_sof_dsp_ops *ops; | ||
50 | int ret; | ||
51 | |||
52 | dev_info(&pdev->dev, "DT DSP detected"); | ||
53 | |||
54 | sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL); | ||
55 | if (!sof_pdata) | ||
56 | return -ENOMEM; | ||
57 | |||
58 | desc = device_get_match_data(dev); | ||
59 | if (!desc) | ||
60 | return -ENODEV; | ||
61 | |||
62 | /* get ops for platform */ | ||
63 | ops = desc->ops; | ||
64 | if (!ops) { | ||
65 | dev_err(dev, "error: no matching DT descriptor ops\n"); | ||
66 | return -ENODEV; | ||
67 | } | ||
68 | |||
69 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE) | ||
70 | /* force nocodec mode */ | ||
71 | dev_warn(dev, "Force to use nocodec mode\n"); | ||
72 | mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL); | ||
73 | if (!mach) | ||
74 | return -ENOMEM; | ||
75 | ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | #else | ||
79 | /* TODO: implement case where we actually have a codec */ | ||
80 | return -ENODEV; | ||
81 | #endif | ||
82 | |||
83 | if (mach) | ||
84 | mach->mach_params.platform = dev_name(dev); | ||
85 | |||
86 | sof_pdata->machine = mach; | ||
87 | sof_pdata->desc = desc; | ||
88 | sof_pdata->dev = &pdev->dev; | ||
89 | sof_pdata->platform = dev_name(dev); | ||
90 | |||
91 | /* TODO: read alternate fw and tplg filenames from DT */ | ||
92 | sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path; | ||
93 | sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path; | ||
94 | |||
95 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) | ||
96 | /* set callback to enable runtime_pm */ | ||
97 | sof_pdata->sof_probe_complete = sof_of_probe_complete; | ||
98 | #endif | ||
99 | /* call sof helper for DSP hardware probe */ | ||
100 | ret = snd_sof_device_probe(dev, sof_pdata); | ||
101 | if (ret) { | ||
102 | dev_err(dev, "error: failed to probe DSP hardware\n"); | ||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) | ||
107 | sof_of_probe_complete(dev); | ||
108 | #endif | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static int sof_of_remove(struct platform_device *pdev) | ||
114 | { | ||
115 | pm_runtime_disable(&pdev->dev); | ||
116 | |||
117 | /* call sof helper for DSP hardware remove */ | ||
118 | snd_sof_device_remove(&pdev->dev); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static const struct of_device_id sof_of_ids[] = { | ||
124 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8) | ||
125 | { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc}, | ||
126 | #endif | ||
127 | { } | ||
128 | }; | ||
129 | MODULE_DEVICE_TABLE(of, sof_of_ids); | ||
130 | |||
131 | /* DT driver definition */ | ||
132 | static struct platform_driver snd_sof_of_driver = { | ||
133 | .probe = sof_of_probe, | ||
134 | .remove = sof_of_remove, | ||
135 | .driver = { | ||
136 | .name = "sof-audio-of", | ||
137 | .pm = &sof_of_pm, | ||
138 | .of_match_table = sof_of_ids, | ||
139 | }, | ||
140 | }; | ||
141 | module_platform_driver(snd_sof_of_driver); | ||
142 | |||
143 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 65d1bac4c6b8..d66412a77873 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c | |||
@@ -203,6 +203,42 @@ static const struct sof_dev_desc kbl_desc = { | |||
203 | }; | 203 | }; |
204 | #endif | 204 | #endif |
205 | 205 | ||
206 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) | ||
207 | static const struct sof_dev_desc tgl_desc = { | ||
208 | .machines = snd_soc_acpi_intel_tgl_machines, | ||
209 | .resindex_lpe_base = 0, | ||
210 | .resindex_pcicfg_base = -1, | ||
211 | .resindex_imr_base = -1, | ||
212 | .irqindex_host_ipc = -1, | ||
213 | .resindex_dma_base = -1, | ||
214 | .chip_info = &tgl_chip_info, | ||
215 | .default_fw_path = "intel/sof", | ||
216 | .default_tplg_path = "intel/sof-tplg", | ||
217 | .nocodec_fw_filename = "sof-tgl.ri", | ||
218 | .nocodec_tplg_filename = "sof-tgl-nocodec.tplg", | ||
219 | .ops = &sof_cnl_ops, | ||
220 | .arch_ops = &sof_xtensa_arch_ops | ||
221 | }; | ||
222 | #endif | ||
223 | |||
224 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) | ||
225 | static const struct sof_dev_desc ehl_desc = { | ||
226 | .machines = snd_soc_acpi_intel_ehl_machines, | ||
227 | .resindex_lpe_base = 0, | ||
228 | .resindex_pcicfg_base = -1, | ||
229 | .resindex_imr_base = -1, | ||
230 | .irqindex_host_ipc = -1, | ||
231 | .resindex_dma_base = -1, | ||
232 | .chip_info = &ehl_chip_info, | ||
233 | .default_fw_path = "intel/sof", | ||
234 | .default_tplg_path = "intel/sof-tplg", | ||
235 | .nocodec_fw_filename = "sof-ehl.ri", | ||
236 | .nocodec_tplg_filename = "sof-ehl-nocodec.tplg", | ||
237 | .ops = &sof_cnl_ops, | ||
238 | .arch_ops = &sof_xtensa_arch_ops | ||
239 | }; | ||
240 | #endif | ||
241 | |||
206 | static const struct dev_pm_ops sof_pci_pm = { | 242 | static const struct dev_pm_ops sof_pci_pm = { |
207 | SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) | 243 | SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) |
208 | SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, | 244 | SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, |
@@ -223,6 +259,9 @@ static void sof_pci_probe_complete(struct device *dev) | |||
223 | */ | 259 | */ |
224 | pm_runtime_allow(dev); | 260 | pm_runtime_allow(dev); |
225 | 261 | ||
262 | /* mark last_busy for pm_runtime to make sure not suspend immediately */ | ||
263 | pm_runtime_mark_last_busy(dev); | ||
264 | |||
226 | /* follow recommendation in pci-driver.c to decrement usage counter */ | 265 | /* follow recommendation in pci-driver.c to decrement usage counter */ |
227 | pm_runtime_put_noidle(dev); | 266 | pm_runtime_put_noidle(dev); |
228 | } | 267 | } |
@@ -382,6 +421,14 @@ static const struct pci_device_id sof_pci_ids[] = { | |||
382 | { PCI_DEVICE(0x8086, 0x06c8), | 421 | { PCI_DEVICE(0x8086, 0x06c8), |
383 | .driver_data = (unsigned long)&cml_desc}, | 422 | .driver_data = (unsigned long)&cml_desc}, |
384 | #endif | 423 | #endif |
424 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) | ||
425 | { PCI_DEVICE(0x8086, 0xa0c8), | ||
426 | .driver_data = (unsigned long)&tgl_desc}, | ||
427 | #endif | ||
428 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) | ||
429 | { PCI_DEVICE(0x8086, 0x4b55), | ||
430 | .driver_data = (unsigned long)&ehl_desc}, | ||
431 | #endif | ||
385 | { 0, } | 432 | { 0, } |
386 | }; | 433 | }; |
387 | MODULE_DEVICE_TABLE(pci, sof_pci_ids); | 434 | MODULE_DEVICE_TABLE(pci, sof_pci_ids); |
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index b8c0b2a22684..730f3259dd02 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h | |||
@@ -171,10 +171,9 @@ struct snd_sof_dsp_ops { | |||
171 | int (*post_fw_run)(struct snd_sof_dev *sof_dev); /* optional */ | 171 | int (*post_fw_run)(struct snd_sof_dev *sof_dev); /* optional */ |
172 | 172 | ||
173 | /* DSP PM */ | 173 | /* DSP PM */ |
174 | int (*suspend)(struct snd_sof_dev *sof_dev, int state); /* optional */ | 174 | int (*suspend)(struct snd_sof_dev *sof_dev); /* optional */ |
175 | int (*resume)(struct snd_sof_dev *sof_dev); /* optional */ | 175 | int (*resume)(struct snd_sof_dev *sof_dev); /* optional */ |
176 | int (*runtime_suspend)(struct snd_sof_dev *sof_dev, | 176 | int (*runtime_suspend)(struct snd_sof_dev *sof_dev); /* optional */ |
177 | int state); /* optional */ | ||
178 | int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */ | 177 | int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */ |
179 | int (*runtime_idle)(struct snd_sof_dev *sof_dev); /* optional */ | 178 | int (*runtime_idle)(struct snd_sof_dev *sof_dev); /* optional */ |
180 | int (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ | 179 | int (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ |
@@ -196,6 +195,13 @@ struct snd_sof_dsp_ops { | |||
196 | int (*trace_trigger)(struct snd_sof_dev *sdev, | 195 | int (*trace_trigger)(struct snd_sof_dev *sdev, |
197 | int cmd); /* optional */ | 196 | int cmd); /* optional */ |
198 | 197 | ||
198 | /* misc */ | ||
199 | int (*get_bar_index)(struct snd_sof_dev *sdev, | ||
200 | u32 type); /* optional */ | ||
201 | int (*get_mailbox_offset)(struct snd_sof_dev *sdev);/* mandatory for common loader code */ | ||
202 | int (*get_window_offset)(struct snd_sof_dev *sdev, | ||
203 | u32 id);/* mandatory for common loader code */ | ||
204 | |||
199 | /* DAI ops */ | 205 | /* DAI ops */ |
200 | struct snd_soc_dai_driver *drv; | 206 | struct snd_soc_dai_driver *drv; |
201 | int num_drv; | 207 | int num_drv; |
@@ -228,7 +234,6 @@ enum sof_debugfs_access_type { | |||
228 | 234 | ||
229 | /* FS entry for debug files that can expose DSP memories, registers */ | 235 | /* FS entry for debug files that can expose DSP memories, registers */ |
230 | struct snd_sof_dfsentry { | 236 | struct snd_sof_dfsentry { |
231 | struct dentry *dfsentry; | ||
232 | size_t size; | 237 | size_t size; |
233 | enum sof_dfsentry_type type; | 238 | enum sof_dfsentry_type type; |
234 | /* | 239 | /* |
@@ -297,7 +302,7 @@ struct snd_sof_pcm { | |||
297 | struct snd_sof_pcm_stream stream[2]; | 302 | struct snd_sof_pcm_stream stream[2]; |
298 | struct list_head list; /* list in sdev pcm list */ | 303 | struct list_head list; /* list in sdev pcm list */ |
299 | struct snd_pcm_hw_params params[2]; | 304 | struct snd_pcm_hw_params params[2]; |
300 | int hw_params_upon_resume[2]; /* set up hw_params upon resume */ | 305 | bool prepared[2]; /* PCM_PARAMS set successfully */ |
301 | }; | 306 | }; |
302 | 307 | ||
303 | /* ALSA SOF Kcontrol device */ | 308 | /* ALSA SOF Kcontrol device */ |
@@ -433,7 +438,7 @@ struct snd_sof_dev { | |||
433 | u32 dtrace_error; | 438 | u32 dtrace_error; |
434 | u32 dtrace_draining; | 439 | u32 dtrace_draining; |
435 | 440 | ||
436 | u32 msi_enabled; | 441 | bool msi_enabled; |
437 | 442 | ||
438 | void *private; /* core does not touch this */ | 443 | void *private; /* core does not touch this */ |
439 | }; | 444 | }; |
@@ -637,6 +642,8 @@ void sof_block_write(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *src, | |||
637 | void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest, | 642 | void sof_block_read(struct snd_sof_dev *sdev, u32 bar, u32 offset, void *dest, |
638 | size_t size); | 643 | size_t size); |
639 | 644 | ||
645 | int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id); | ||
646 | |||
640 | void intel_ipc_msg_data(struct snd_sof_dev *sdev, | 647 | void intel_ipc_msg_data(struct snd_sof_dev *sdev, |
641 | struct snd_pcm_substream *substream, | 648 | struct snd_pcm_substream *substream, |
642 | void *p, size_t sz); | 649 | void *p, size_t sz); |
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 432ae343f960..fc85efbad378 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c | |||
@@ -42,6 +42,13 @@ | |||
42 | /* size of tplg abi in byte */ | 42 | /* size of tplg abi in byte */ |
43 | #define SOF_TPLG_ABI_SIZE 3 | 43 | #define SOF_TPLG_ABI_SIZE 3 |
44 | 44 | ||
45 | struct sof_widget_data { | ||
46 | int ctrl_type; | ||
47 | int ipc_cmd; | ||
48 | struct sof_abi_hdr *pdata; | ||
49 | struct snd_sof_control *control; | ||
50 | }; | ||
51 | |||
45 | /* send pcm params ipc */ | 52 | /* send pcm params ipc */ |
46 | static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir) | 53 | static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir) |
47 | { | 54 | { |
@@ -339,6 +346,9 @@ static const struct sof_dai_types sof_dais[] = { | |||
339 | {"SSP", SOF_DAI_INTEL_SSP}, | 346 | {"SSP", SOF_DAI_INTEL_SSP}, |
340 | {"HDA", SOF_DAI_INTEL_HDA}, | 347 | {"HDA", SOF_DAI_INTEL_HDA}, |
341 | {"DMIC", SOF_DAI_INTEL_DMIC}, | 348 | {"DMIC", SOF_DAI_INTEL_DMIC}, |
349 | {"ALH", SOF_DAI_INTEL_ALH}, | ||
350 | {"SAI", SOF_DAI_IMX_SAI}, | ||
351 | {"ESAI", SOF_DAI_IMX_ESAI}, | ||
342 | }; | 352 | }; |
343 | 353 | ||
344 | static enum sof_ipc_dai_type find_dai(const char *name) | 354 | static enum sof_ipc_dai_type find_dai(const char *name) |
@@ -748,6 +758,9 @@ static const struct sof_topology_token ssp_tokens[] = { | |||
748 | get_token_u16, | 758 | get_token_u16, |
749 | offsetof(struct sof_ipc_dai_ssp_params, | 759 | offsetof(struct sof_ipc_dai_ssp_params, |
750 | tdm_per_slot_padding_flag), 0}, | 760 | tdm_per_slot_padding_flag), 0}, |
761 | {SOF_TKN_INTEL_SSP_BCLK_DELAY, SND_SOC_TPLG_TUPLE_TYPE_WORD, | ||
762 | get_token_u32, | ||
763 | offsetof(struct sof_ipc_dai_ssp_params, bclk_delay), 0}, | ||
751 | 764 | ||
752 | }; | 765 | }; |
753 | 766 | ||
@@ -1739,51 +1752,34 @@ err: | |||
1739 | return ret; | 1752 | return ret; |
1740 | } | 1753 | } |
1741 | 1754 | ||
1742 | static int sof_process_load(struct snd_soc_component *scomp, int index, | 1755 | static int sof_get_control_data(struct snd_sof_dev *sdev, |
1743 | struct snd_sof_widget *swidget, | 1756 | struct snd_soc_dapm_widget *widget, |
1744 | struct snd_soc_tplg_dapm_widget *tw, | 1757 | struct sof_widget_data *wdata, |
1745 | struct sof_ipc_comp_reply *r, | 1758 | size_t *size) |
1746 | int type) | ||
1747 | { | 1759 | { |
1748 | struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); | ||
1749 | struct snd_soc_tplg_private *private = &tw->priv; | ||
1750 | struct snd_soc_dapm_widget *widget = swidget->widget; | ||
1751 | const struct snd_kcontrol_new *kc; | 1760 | const struct snd_kcontrol_new *kc; |
1752 | struct soc_bytes_ext *sbe; | ||
1753 | struct soc_mixer_control *sm; | 1761 | struct soc_mixer_control *sm; |
1762 | struct soc_bytes_ext *sbe; | ||
1754 | struct soc_enum *se; | 1763 | struct soc_enum *se; |
1755 | struct snd_sof_control *scontrol = NULL; | 1764 | int i; |
1756 | struct sof_abi_hdr *pdata = NULL; | ||
1757 | struct sof_ipc_comp_process *process; | ||
1758 | size_t ipc_size, ipc_data_size = 0; | ||
1759 | int ret, i, offset = 0; | ||
1760 | 1765 | ||
1761 | if (type == SOF_COMP_NONE) { | 1766 | *size = 0; |
1762 | dev_err(sdev->dev, "error: invalid process comp type %d\n", | ||
1763 | type); | ||
1764 | return -EINVAL; | ||
1765 | } | ||
1766 | 1767 | ||
1767 | /* | ||
1768 | * get possible component controls - get size of all pdata, | ||
1769 | * then memcpy with headers | ||
1770 | */ | ||
1771 | for (i = 0; i < widget->num_kcontrols; i++) { | 1768 | for (i = 0; i < widget->num_kcontrols; i++) { |
1772 | |||
1773 | kc = &widget->kcontrol_news[i]; | 1769 | kc = &widget->kcontrol_news[i]; |
1774 | 1770 | ||
1775 | switch (widget->dobj.widget.kcontrol_type) { | 1771 | switch (widget->dobj.widget.kcontrol_type) { |
1776 | case SND_SOC_TPLG_TYPE_MIXER: | 1772 | case SND_SOC_TPLG_TYPE_MIXER: |
1777 | sm = (struct soc_mixer_control *)kc->private_value; | 1773 | sm = (struct soc_mixer_control *)kc->private_value; |
1778 | scontrol = sm->dobj.private; | 1774 | wdata[i].control = sm->dobj.private; |
1779 | break; | 1775 | break; |
1780 | case SND_SOC_TPLG_TYPE_BYTES: | 1776 | case SND_SOC_TPLG_TYPE_BYTES: |
1781 | sbe = (struct soc_bytes_ext *)kc->private_value; | 1777 | sbe = (struct soc_bytes_ext *)kc->private_value; |
1782 | scontrol = sbe->dobj.private; | 1778 | wdata[i].control = sbe->dobj.private; |
1783 | break; | 1779 | break; |
1784 | case SND_SOC_TPLG_TYPE_ENUM: | 1780 | case SND_SOC_TPLG_TYPE_ENUM: |
1785 | se = (struct soc_enum *)kc->private_value; | 1781 | se = (struct soc_enum *)kc->private_value; |
1786 | scontrol = se->dobj.private; | 1782 | wdata[i].control = se->dobj.private; |
1787 | break; | 1783 | break; |
1788 | default: | 1784 | default: |
1789 | dev_err(sdev->dev, "error: unknown kcontrol type %d in widget %s\n", | 1785 | dev_err(sdev->dev, "error: unknown kcontrol type %d in widget %s\n", |
@@ -1792,31 +1788,97 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, | |||
1792 | return -EINVAL; | 1788 | return -EINVAL; |
1793 | } | 1789 | } |
1794 | 1790 | ||
1795 | if (!scontrol) { | 1791 | if (!wdata[i].control) { |
1796 | dev_err(sdev->dev, "error: no scontrol for widget %s\n", | 1792 | dev_err(sdev->dev, "error: no scontrol for widget %s\n", |
1797 | widget->name); | 1793 | widget->name); |
1798 | return -EINVAL; | 1794 | return -EINVAL; |
1799 | } | 1795 | } |
1800 | 1796 | ||
1801 | /* don't include if no private data */ | 1797 | wdata[i].pdata = wdata[i].control->control_data->data; |
1802 | pdata = scontrol->control_data->data; | 1798 | if (!wdata[i].pdata) |
1803 | if (!pdata) | 1799 | return -EINVAL; |
1804 | continue; | ||
1805 | 1800 | ||
1806 | /* make sure data is valid - data can be updated at runtime */ | 1801 | /* make sure data is valid - data can be updated at runtime */ |
1807 | if (pdata->magic != SOF_ABI_MAGIC) | 1802 | if (wdata[i].pdata->magic != SOF_ABI_MAGIC) |
1808 | continue; | 1803 | return -EINVAL; |
1804 | |||
1805 | *size += wdata[i].pdata->size; | ||
1806 | |||
1807 | /* get data type */ | ||
1808 | switch (wdata[i].control->cmd) { | ||
1809 | case SOF_CTRL_CMD_VOLUME: | ||
1810 | case SOF_CTRL_CMD_ENUM: | ||
1811 | case SOF_CTRL_CMD_SWITCH: | ||
1812 | wdata[i].ipc_cmd = SOF_IPC_COMP_SET_VALUE; | ||
1813 | wdata[i].ctrl_type = SOF_CTRL_TYPE_VALUE_CHAN_SET; | ||
1814 | break; | ||
1815 | case SOF_CTRL_CMD_BINARY: | ||
1816 | wdata[i].ipc_cmd = SOF_IPC_COMP_SET_DATA; | ||
1817 | wdata[i].ctrl_type = SOF_CTRL_TYPE_DATA_SET; | ||
1818 | break; | ||
1819 | default: | ||
1820 | break; | ||
1821 | } | ||
1822 | } | ||
1823 | |||
1824 | return 0; | ||
1825 | } | ||
1826 | |||
1827 | static int sof_process_load(struct snd_soc_component *scomp, int index, | ||
1828 | struct snd_sof_widget *swidget, | ||
1829 | struct snd_soc_tplg_dapm_widget *tw, | ||
1830 | struct sof_ipc_comp_reply *r, | ||
1831 | int type) | ||
1832 | { | ||
1833 | struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); | ||
1834 | struct snd_soc_dapm_widget *widget = swidget->widget; | ||
1835 | struct snd_soc_tplg_private *private = &tw->priv; | ||
1836 | struct sof_ipc_comp_process *process = NULL; | ||
1837 | struct sof_widget_data *wdata = NULL; | ||
1838 | size_t ipc_data_size = 0; | ||
1839 | size_t ipc_size; | ||
1840 | int offset = 0; | ||
1841 | int ret = 0; | ||
1842 | int i; | ||
1809 | 1843 | ||
1810 | ipc_data_size += pdata->size; | 1844 | if (type == SOF_COMP_NONE) { |
1845 | dev_err(sdev->dev, "error: invalid process comp type %d\n", | ||
1846 | type); | ||
1847 | return -EINVAL; | ||
1848 | } | ||
1849 | |||
1850 | /* allocate struct for widget control data sizes and types */ | ||
1851 | if (widget->num_kcontrols) { | ||
1852 | wdata = kcalloc(widget->num_kcontrols, | ||
1853 | sizeof(*wdata), | ||
1854 | GFP_KERNEL); | ||
1855 | |||
1856 | if (!wdata) | ||
1857 | return -ENOMEM; | ||
1858 | |||
1859 | /* get possible component controls and get size of all pdata */ | ||
1860 | ret = sof_get_control_data(sdev, widget, wdata, | ||
1861 | &ipc_data_size); | ||
1862 | |||
1863 | if (ret < 0) | ||
1864 | goto out; | ||
1811 | } | 1865 | } |
1812 | 1866 | ||
1813 | ipc_size = sizeof(struct sof_ipc_comp_process) + | 1867 | ipc_size = sizeof(struct sof_ipc_comp_process) + |
1814 | le32_to_cpu(private->size) + | 1868 | le32_to_cpu(private->size) + |
1815 | ipc_data_size; | 1869 | ipc_data_size; |
1816 | 1870 | ||
1871 | /* we are exceeding max ipc size, config needs to be sent separately */ | ||
1872 | if (ipc_size > SOF_IPC_MSG_MAX_SIZE) { | ||
1873 | ipc_size -= ipc_data_size; | ||
1874 | ipc_data_size = 0; | ||
1875 | } | ||
1876 | |||
1817 | process = kzalloc(ipc_size, GFP_KERNEL); | 1877 | process = kzalloc(ipc_size, GFP_KERNEL); |
1818 | if (!process) | 1878 | if (!process) { |
1819 | return -ENOMEM; | 1879 | ret = -ENOMEM; |
1880 | goto out; | ||
1881 | } | ||
1820 | 1882 | ||
1821 | /* configure iir IPC message */ | 1883 | /* configure iir IPC message */ |
1822 | process->comp.hdr.size = ipc_size; | 1884 | process->comp.hdr.size = ipc_size; |
@@ -1842,40 +1904,13 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, | |||
1842 | * get possible component controls - get size of all pdata, | 1904 | * get possible component controls - get size of all pdata, |
1843 | * then memcpy with headers | 1905 | * then memcpy with headers |
1844 | */ | 1906 | */ |
1845 | for (i = 0; i < widget->num_kcontrols; i++) { | 1907 | if (ipc_data_size) { |
1846 | kc = &widget->kcontrol_news[i]; | 1908 | for (i = 0; i < widget->num_kcontrols; i++) { |
1847 | 1909 | memcpy(&process->data + offset, | |
1848 | switch (widget->dobj.widget.kcontrol_type) { | 1910 | wdata[i].pdata->data, |
1849 | case SND_SOC_TPLG_TYPE_MIXER: | 1911 | wdata[i].pdata->size); |
1850 | sm = (struct soc_mixer_control *)kc->private_value; | 1912 | offset += wdata[i].pdata->size; |
1851 | scontrol = sm->dobj.private; | ||
1852 | break; | ||
1853 | case SND_SOC_TPLG_TYPE_BYTES: | ||
1854 | sbe = (struct soc_bytes_ext *)kc->private_value; | ||
1855 | scontrol = sbe->dobj.private; | ||
1856 | break; | ||
1857 | case SND_SOC_TPLG_TYPE_ENUM: | ||
1858 | se = (struct soc_enum *)kc->private_value; | ||
1859 | scontrol = se->dobj.private; | ||
1860 | break; | ||
1861 | default: | ||
1862 | dev_err(sdev->dev, "error: unknown kcontrol type %d in widget %s\n", | ||
1863 | widget->dobj.widget.kcontrol_type, | ||
1864 | widget->name); | ||
1865 | return -EINVAL; | ||
1866 | } | 1913 | } |
1867 | |||
1868 | /* don't include if no private data */ | ||
1869 | pdata = scontrol->control_data->data; | ||
1870 | if (!pdata) | ||
1871 | continue; | ||
1872 | |||
1873 | /* make sure data is valid - data can be updated at runtime */ | ||
1874 | if (pdata->magic != SOF_ABI_MAGIC) | ||
1875 | continue; | ||
1876 | |||
1877 | memcpy(&process->data + offset, pdata->data, pdata->size); | ||
1878 | offset += pdata->size; | ||
1879 | } | 1914 | } |
1880 | 1915 | ||
1881 | process->size = ipc_data_size; | 1916 | process->size = ipc_data_size; |
@@ -1883,10 +1918,35 @@ static int sof_process_load(struct snd_soc_component *scomp, int index, | |||
1883 | 1918 | ||
1884 | ret = sof_ipc_tx_message(sdev->ipc, process->comp.hdr.cmd, process, | 1919 | ret = sof_ipc_tx_message(sdev->ipc, process->comp.hdr.cmd, process, |
1885 | ipc_size, r, sizeof(*r)); | 1920 | ipc_size, r, sizeof(*r)); |
1886 | if (ret >= 0) | 1921 | |
1887 | return ret; | 1922 | if (ret < 0) { |
1923 | dev_err(sdev->dev, "error: create process failed\n"); | ||
1924 | goto err; | ||
1925 | } | ||
1926 | |||
1927 | /* we sent the data in single message so return */ | ||
1928 | if (ipc_data_size) | ||
1929 | goto out; | ||
1930 | |||
1931 | /* send control data with large message supported method */ | ||
1932 | for (i = 0; i < widget->num_kcontrols; i++) { | ||
1933 | wdata[i].control->readback_offset = 0; | ||
1934 | ret = snd_sof_ipc_set_get_comp_data(sdev->ipc, wdata[i].control, | ||
1935 | wdata[i].ipc_cmd, | ||
1936 | wdata[i].ctrl_type, | ||
1937 | wdata[i].control->cmd, | ||
1938 | true); | ||
1939 | if (ret != 0) { | ||
1940 | dev_err(sdev->dev, "error: send control failed\n"); | ||
1941 | break; | ||
1942 | } | ||
1943 | } | ||
1944 | |||
1888 | err: | 1945 | err: |
1889 | kfree(process); | 1946 | if (ret < 0) |
1947 | kfree(process); | ||
1948 | out: | ||
1949 | kfree(wdata); | ||
1890 | return ret; | 1950 | return ret; |
1891 | } | 1951 | } |
1892 | 1952 | ||
@@ -2457,6 +2517,26 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, | |||
2457 | return ret; | 2517 | return ret; |
2458 | } | 2518 | } |
2459 | 2519 | ||
2520 | static int sof_link_sai_load(struct snd_soc_component *scomp, int index, | ||
2521 | struct snd_soc_dai_link *link, | ||
2522 | struct snd_soc_tplg_link_config *cfg, | ||
2523 | struct snd_soc_tplg_hw_config *hw_config, | ||
2524 | struct sof_ipc_dai_config *config) | ||
2525 | { | ||
2526 | /*TODO: Add implementation */ | ||
2527 | return 0; | ||
2528 | } | ||
2529 | |||
2530 | static int sof_link_esai_load(struct snd_soc_component *scomp, int index, | ||
2531 | struct snd_soc_dai_link *link, | ||
2532 | struct snd_soc_tplg_link_config *cfg, | ||
2533 | struct snd_soc_tplg_hw_config *hw_config, | ||
2534 | struct sof_ipc_dai_config *config) | ||
2535 | { | ||
2536 | /*TODO: Add implementation */ | ||
2537 | return 0; | ||
2538 | } | ||
2539 | |||
2460 | static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, | 2540 | static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, |
2461 | struct snd_soc_dai_link *link, | 2541 | struct snd_soc_dai_link *link, |
2462 | struct snd_soc_tplg_link_config *cfg, | 2542 | struct snd_soc_tplg_link_config *cfg, |
@@ -2685,6 +2765,40 @@ static int sof_link_hda_load(struct snd_soc_component *scomp, int index, | |||
2685 | return ret; | 2765 | return ret; |
2686 | } | 2766 | } |
2687 | 2767 | ||
2768 | static int sof_link_alh_load(struct snd_soc_component *scomp, int index, | ||
2769 | struct snd_soc_dai_link *link, | ||
2770 | struct snd_soc_tplg_link_config *cfg, | ||
2771 | struct snd_soc_tplg_hw_config *hw_config, | ||
2772 | struct sof_ipc_dai_config *config) | ||
2773 | { | ||
2774 | struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); | ||
2775 | struct sof_ipc_reply reply; | ||
2776 | u32 size = sizeof(*config); | ||
2777 | int ret; | ||
2778 | |||
2779 | /* init IPC */ | ||
2780 | config->hdr.size = size; | ||
2781 | |||
2782 | /* send message to DSP */ | ||
2783 | ret = sof_ipc_tx_message(sdev->ipc, | ||
2784 | config->hdr.cmd, config, size, &reply, | ||
2785 | sizeof(reply)); | ||
2786 | |||
2787 | if (ret < 0) { | ||
2788 | dev_err(sdev->dev, "error: failed to set DAI config for ALH %d\n", | ||
2789 | config->dai_index); | ||
2790 | return ret; | ||
2791 | } | ||
2792 | |||
2793 | /* set config for all DAI's with name matching the link name */ | ||
2794 | ret = sof_set_dai_config(sdev, size, link, config); | ||
2795 | if (ret < 0) | ||
2796 | dev_err(sdev->dev, "error: failed to save DAI config for ALH %d\n", | ||
2797 | config->dai_index); | ||
2798 | |||
2799 | return ret; | ||
2800 | } | ||
2801 | |||
2688 | /* DAI link - used for any driver specific init */ | 2802 | /* DAI link - used for any driver specific init */ |
2689 | static int sof_link_load(struct snd_soc_component *scomp, int index, | 2803 | static int sof_link_load(struct snd_soc_component *scomp, int index, |
2690 | struct snd_soc_dai_link *link, | 2804 | struct snd_soc_dai_link *link, |
@@ -2781,6 +2895,18 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, | |||
2781 | ret = sof_link_hda_load(scomp, index, link, cfg, hw_config, | 2895 | ret = sof_link_hda_load(scomp, index, link, cfg, hw_config, |
2782 | &config); | 2896 | &config); |
2783 | break; | 2897 | break; |
2898 | case SOF_DAI_INTEL_ALH: | ||
2899 | ret = sof_link_alh_load(scomp, index, link, cfg, hw_config, | ||
2900 | &config); | ||
2901 | break; | ||
2902 | case SOF_DAI_IMX_SAI: | ||
2903 | ret = sof_link_sai_load(scomp, index, link, cfg, hw_config, | ||
2904 | &config); | ||
2905 | break; | ||
2906 | case SOF_DAI_IMX_ESAI: | ||
2907 | ret = sof_link_esai_load(scomp, index, link, cfg, hw_config, | ||
2908 | &config); | ||
2909 | break; | ||
2784 | default: | 2910 | default: |
2785 | dev_err(sdev->dev, "error: invalid DAI type %d\n", config.type); | 2911 | dev_err(sdev->dev, "error: invalid DAI type %d\n", config.type); |
2786 | ret = -EINVAL; | 2912 | ret = -EINVAL; |
@@ -2838,7 +2964,8 @@ found: | |||
2838 | switch (sof_dai->dai_config->type) { | 2964 | switch (sof_dai->dai_config->type) { |
2839 | case SOF_DAI_INTEL_SSP: | 2965 | case SOF_DAI_INTEL_SSP: |
2840 | case SOF_DAI_INTEL_DMIC: | 2966 | case SOF_DAI_INTEL_DMIC: |
2841 | /* no resource needs to be released for SSP and DMIC */ | 2967 | case SOF_DAI_INTEL_ALH: |
2968 | /* no resource needs to be released for SSP, DMIC and ALH */ | ||
2842 | break; | 2969 | break; |
2843 | case SOF_DAI_INTEL_HDA: | 2970 | case SOF_DAI_INTEL_HDA: |
2844 | ret = sof_link_hda_unload(sdev, link); | 2971 | ret = sof_link_hda_unload(sdev, link); |
diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index befed975161c..4c3cff031fd6 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c | |||
@@ -148,13 +148,8 @@ static int trace_debugfs_create(struct snd_sof_dev *sdev) | |||
148 | dfse->size = sdev->dmatb.bytes; | 148 | dfse->size = sdev->dmatb.bytes; |
149 | dfse->sdev = sdev; | 149 | dfse->sdev = sdev; |
150 | 150 | ||
151 | dfse->dfsentry = debugfs_create_file("trace", 0444, sdev->debugfs_root, | 151 | debugfs_create_file("trace", 0444, sdev->debugfs_root, dfse, |
152 | dfse, &sof_dfs_trace_fops); | 152 | &sof_dfs_trace_fops); |
153 | if (!dfse->dfsentry) { | ||
154 | /* can't rely on debugfs, only log error and keep going */ | ||
155 | dev_err(sdev->dev, | ||
156 | "error: cannot create debugfs entry for trace\n"); | ||
157 | } | ||
158 | 153 | ||
159 | return 0; | 154 | return 0; |
160 | } | 155 | } |
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c index 78a6a360b4a6..4b68d6ee75da 100644 --- a/sound/soc/spear/spdif_in.c +++ b/sound/soc/spear/spdif_in.c | |||
@@ -202,12 +202,11 @@ static int spdif_in_probe(struct platform_device *pdev) | |||
202 | { | 202 | { |
203 | struct spdif_in_dev *host; | 203 | struct spdif_in_dev *host; |
204 | struct spear_spdif_platform_data *pdata; | 204 | struct spear_spdif_platform_data *pdata; |
205 | struct resource *res, *res_fifo; | 205 | struct resource *res_fifo; |
206 | void __iomem *io_base; | 206 | void __iomem *io_base; |
207 | int ret; | 207 | int ret; |
208 | 208 | ||
209 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 209 | io_base = devm_platform_ioremap_resource(pdev, 0); |
210 | io_base = devm_ioremap_resource(&pdev->dev, res); | ||
211 | if (IS_ERR(io_base)) | 210 | if (IS_ERR(io_base)) |
212 | return PTR_ERR(io_base); | 211 | return PTR_ERR(io_base); |
213 | 212 | ||
diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c index 7448015a4935..f439e5503a3c 100644 --- a/sound/soc/sprd/sprd-mcdt.c +++ b/sound/soc/sprd/sprd-mcdt.c | |||
@@ -959,10 +959,8 @@ static int sprd_mcdt_probe(struct platform_device *pdev) | |||
959 | platform_set_drvdata(pdev, mcdt); | 959 | platform_set_drvdata(pdev, mcdt); |
960 | 960 | ||
961 | irq = platform_get_irq(pdev, 0); | 961 | irq = platform_get_irq(pdev, 0); |
962 | if (irq < 0) { | 962 | if (irq < 0) |
963 | dev_err(&pdev->dev, "Failed to get MCDT interrupt\n"); | ||
964 | return irq; | 963 | return irq; |
965 | } | ||
966 | 964 | ||
967 | ret = devm_request_irq(&pdev->dev, irq, sprd_mcdt_irq_handler, | 965 | ret = devm_request_irq(&pdev->dev, irq, sprd_mcdt_irq_handler, |
968 | 0, "sprd-mcdt", mcdt); | 966 | 0, "sprd-mcdt", mcdt); |
diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c index 645bcbe91601..ee4a0151e63e 100644 --- a/sound/soc/sti/sti_uniperif.c +++ b/sound/soc/sti/sti_uniperif.c | |||
@@ -426,10 +426,8 @@ static int sti_uniperiph_cpu_dai_of(struct device_node *node, | |||
426 | UNIPERIF_FIFO_DATA_OFFSET(uni); | 426 | UNIPERIF_FIFO_DATA_OFFSET(uni); |
427 | 427 | ||
428 | uni->irq = platform_get_irq(priv->pdev, 0); | 428 | uni->irq = platform_get_irq(priv->pdev, 0); |
429 | if (uni->irq < 0) { | 429 | if (uni->irq < 0) |
430 | dev_err(dev, "Failed to get IRQ resource\n"); | ||
431 | return -ENXIO; | 430 | return -ENXIO; |
432 | } | ||
433 | 431 | ||
434 | uni->type = dev_data->type; | 432 | uni->type = dev_data->type; |
435 | 433 | ||
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index ba6452dab69b..3e7226a53e53 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c | |||
@@ -855,11 +855,8 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, | |||
855 | 855 | ||
856 | /* Get irqs */ | 856 | /* Get irqs */ |
857 | irq = platform_get_irq(pdev, 0); | 857 | irq = platform_get_irq(pdev, 0); |
858 | if (irq < 0) { | 858 | if (irq < 0) |
859 | if (irq != -EPROBE_DEFER) | ||
860 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); | ||
861 | return irq; | 859 | return irq; |
862 | } | ||
863 | 860 | ||
864 | ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, IRQF_ONESHOT, | 861 | ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, IRQF_ONESHOT, |
865 | dev_name(&pdev->dev), i2s); | 862 | dev_name(&pdev->dev), i2s); |
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 63f68e663676..ef4273361d0d 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c | |||
@@ -152,7 +152,6 @@ static int stm32_sai_probe(struct platform_device *pdev) | |||
152 | { | 152 | { |
153 | struct stm32_sai_data *sai; | 153 | struct stm32_sai_data *sai; |
154 | struct reset_control *rst; | 154 | struct reset_control *rst; |
155 | struct resource *res; | ||
156 | const struct of_device_id *of_id; | 155 | const struct of_device_id *of_id; |
157 | u32 val; | 156 | u32 val; |
158 | int ret; | 157 | int ret; |
@@ -161,8 +160,7 @@ static int stm32_sai_probe(struct platform_device *pdev) | |||
161 | if (!sai) | 160 | if (!sai) |
162 | return -ENOMEM; | 161 | return -ENOMEM; |
163 | 162 | ||
164 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 163 | sai->base = devm_platform_ioremap_resource(pdev, 0); |
165 | sai->base = devm_ioremap_resource(&pdev->dev, res); | ||
166 | if (IS_ERR(sai->base)) | 164 | if (IS_ERR(sai->base)) |
167 | return PTR_ERR(sai->base); | 165 | return PTR_ERR(sai->base); |
168 | 166 | ||
@@ -195,10 +193,8 @@ static int stm32_sai_probe(struct platform_device *pdev) | |||
195 | 193 | ||
196 | /* init irqs */ | 194 | /* init irqs */ |
197 | sai->irq = platform_get_irq(pdev, 0); | 195 | sai->irq = platform_get_irq(pdev, 0); |
198 | if (sai->irq < 0) { | 196 | if (sai->irq < 0) |
199 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); | ||
200 | return sai->irq; | 197 | return sai->irq; |
201 | } | ||
202 | 198 | ||
203 | /* reset */ | 199 | /* reset */ |
204 | rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); | 200 | rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index ee71b898897b..cd4b235fce57 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c | |||
@@ -909,10 +909,8 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev, | |||
909 | } | 909 | } |
910 | 910 | ||
911 | spdifrx->irq = platform_get_irq(pdev, 0); | 911 | spdifrx->irq = platform_get_irq(pdev, 0); |
912 | if (spdifrx->irq < 0) { | 912 | if (spdifrx->irq < 0) |
913 | dev_err(&pdev->dev, "No irq for node %s\n", pdev->name); | ||
914 | return spdifrx->irq; | 913 | return spdifrx->irq; |
915 | } | ||
916 | 914 | ||
917 | return 0; | 915 | return 0; |
918 | } | 916 | } |
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 619073e7d972..ee448d5e07a6 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c | |||
@@ -1424,7 +1424,7 @@ static const struct snd_soc_dapm_route sun8i_codec_card_routes[] = { | |||
1424 | }; | 1424 | }; |
1425 | 1425 | ||
1426 | static struct snd_soc_aux_dev aux_dev = { | 1426 | static struct snd_soc_aux_dev aux_dev = { |
1427 | .name = "Codec Analog Controls", | 1427 | .dlc = COMP_EMPTY(), |
1428 | }; | 1428 | }; |
1429 | 1429 | ||
1430 | static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev) | 1430 | static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev) |
@@ -1436,10 +1436,10 @@ static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev) | |||
1436 | if (!card) | 1436 | if (!card) |
1437 | return ERR_PTR(-ENOMEM); | 1437 | return ERR_PTR(-ENOMEM); |
1438 | 1438 | ||
1439 | aux_dev.codec_of_node = of_parse_phandle(dev->of_node, | 1439 | aux_dev.dlc.of_node = of_parse_phandle(dev->of_node, |
1440 | "allwinner,codec-analog-controls", | 1440 | "allwinner,codec-analog-controls", |
1441 | 0); | 1441 | 0); |
1442 | if (!aux_dev.codec_of_node) { | 1442 | if (!aux_dev.dlc.of_node) { |
1443 | dev_err(dev, "Can't find analog controls for codec.\n"); | 1443 | dev_err(dev, "Can't find analog controls for codec.\n"); |
1444 | return ERR_PTR(-EINVAL); | 1444 | return ERR_PTR(-EINVAL); |
1445 | }; | 1445 | }; |
@@ -1474,10 +1474,10 @@ static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev) | |||
1474 | if (!card) | 1474 | if (!card) |
1475 | return ERR_PTR(-ENOMEM); | 1475 | return ERR_PTR(-ENOMEM); |
1476 | 1476 | ||
1477 | aux_dev.codec_of_node = of_parse_phandle(dev->of_node, | 1477 | aux_dev.dlc.of_node = of_parse_phandle(dev->of_node, |
1478 | "allwinner,codec-analog-controls", | 1478 | "allwinner,codec-analog-controls", |
1479 | 0); | 1479 | 0); |
1480 | if (!aux_dev.codec_of_node) { | 1480 | if (!aux_dev.dlc.of_node) { |
1481 | dev_err(dev, "Can't find analog controls for codec.\n"); | 1481 | dev_err(dev, "Can't find analog controls for codec.\n"); |
1482 | return ERR_PTR(-EINVAL); | 1482 | return ERR_PTR(-EINVAL); |
1483 | }; | 1483 | }; |
@@ -1512,10 +1512,10 @@ static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev) | |||
1512 | if (!card) | 1512 | if (!card) |
1513 | return ERR_PTR(-ENOMEM); | 1513 | return ERR_PTR(-ENOMEM); |
1514 | 1514 | ||
1515 | aux_dev.codec_of_node = of_parse_phandle(dev->of_node, | 1515 | aux_dev.dlc.of_node = of_parse_phandle(dev->of_node, |
1516 | "allwinner,codec-analog-controls", | 1516 | "allwinner,codec-analog-controls", |
1517 | 0); | 1517 | 0); |
1518 | if (!aux_dev.codec_of_node) { | 1518 | if (!aux_dev.dlc.of_node) { |
1519 | dev_err(dev, "Can't find analog controls for codec.\n"); | 1519 | dev_err(dev, "Can't find analog controls for codec.\n"); |
1520 | return ERR_PTR(-EINVAL); | 1520 | return ERR_PTR(-EINVAL); |
1521 | }; | 1521 | }; |
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 85c3b2c8cd77..d0a8d5810c0a 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c | |||
@@ -46,8 +46,6 @@ | |||
46 | #define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0) | 46 | #define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0) |
47 | #define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0) | 47 | #define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0) |
48 | #define SUN4I_I2S_FMT0_FMT_I2S (0 << 0) | 48 | #define SUN4I_I2S_FMT0_FMT_I2S (0 << 0) |
49 | #define SUN4I_I2S_FMT0_POLARITY_INVERTED (1) | ||
50 | #define SUN4I_I2S_FMT0_POLARITY_NORMAL (0) | ||
51 | 49 | ||
52 | #define SUN4I_I2S_FMT1_REG 0x08 | 50 | #define SUN4I_I2S_FMT1_REG 0x08 |
53 | #define SUN4I_I2S_FIFO_TX_REG 0x0c | 51 | #define SUN4I_I2S_FIFO_TX_REG 0x0c |
@@ -76,10 +74,11 @@ | |||
76 | #define SUN4I_I2S_CLK_DIV_MCLK_MASK GENMASK(3, 0) | 74 | #define SUN4I_I2S_CLK_DIV_MCLK_MASK GENMASK(3, 0) |
77 | #define SUN4I_I2S_CLK_DIV_MCLK(mclk) ((mclk) << 0) | 75 | #define SUN4I_I2S_CLK_DIV_MCLK(mclk) ((mclk) << 0) |
78 | 76 | ||
79 | #define SUN4I_I2S_RX_CNT_REG 0x28 | 77 | #define SUN4I_I2S_TX_CNT_REG 0x28 |
80 | #define SUN4I_I2S_TX_CNT_REG 0x2c | 78 | #define SUN4I_I2S_RX_CNT_REG 0x2c |
81 | 79 | ||
82 | #define SUN4I_I2S_TX_CHAN_SEL_REG 0x30 | 80 | #define SUN4I_I2S_TX_CHAN_SEL_REG 0x30 |
81 | #define SUN4I_I2S_CHAN_SEL_MASK GENMASK(2, 0) | ||
83 | #define SUN4I_I2S_CHAN_SEL(num_chan) (((num_chan) - 1) << 0) | 82 | #define SUN4I_I2S_CHAN_SEL(num_chan) (((num_chan) - 1) << 0) |
84 | 83 | ||
85 | #define SUN4I_I2S_TX_CHAN_MAP_REG 0x34 | 84 | #define SUN4I_I2S_TX_CHAN_MAP_REG 0x34 |
@@ -92,8 +91,19 @@ | |||
92 | #define SUN8I_I2S_CTRL_BCLK_OUT BIT(18) | 91 | #define SUN8I_I2S_CTRL_BCLK_OUT BIT(18) |
93 | #define SUN8I_I2S_CTRL_LRCK_OUT BIT(17) | 92 | #define SUN8I_I2S_CTRL_LRCK_OUT BIT(17) |
94 | 93 | ||
94 | #define SUN8I_I2S_CTRL_MODE_MASK GENMASK(5, 4) | ||
95 | #define SUN8I_I2S_CTRL_MODE_RIGHT (2 << 4) | ||
96 | #define SUN8I_I2S_CTRL_MODE_LEFT (1 << 4) | ||
97 | #define SUN8I_I2S_CTRL_MODE_PCM (0 << 4) | ||
98 | |||
99 | #define SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK BIT(19) | ||
100 | #define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 19) | ||
101 | #define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 19) | ||
95 | #define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8) | 102 | #define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8) |
96 | #define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8) | 103 | #define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8) |
104 | #define SUN8I_I2S_FMT0_BCLK_POLARITY_MASK BIT(7) | ||
105 | #define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 7) | ||
106 | #define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 7) | ||
97 | 107 | ||
98 | #define SUN8I_I2S_INT_STA_REG 0x0c | 108 | #define SUN8I_I2S_INT_STA_REG 0x0c |
99 | #define SUN8I_I2S_FIFO_TX_REG 0x20 | 109 | #define SUN8I_I2S_FIFO_TX_REG 0x20 |
@@ -120,52 +130,33 @@ struct sun4i_i2s; | |||
120 | * struct sun4i_i2s_quirks - Differences between SoC variants. | 130 | * struct sun4i_i2s_quirks - Differences between SoC variants. |
121 | * | 131 | * |
122 | * @has_reset: SoC needs reset deasserted. | 132 | * @has_reset: SoC needs reset deasserted. |
123 | * @has_slave_select_bit: SoC has a bit to enable slave mode. | ||
124 | * @has_fmt_set_lrck_period: SoC requires lrclk period to be set. | ||
125 | * @has_chcfg: tx and rx slot number need to be set. | ||
126 | * @has_chsel_tx_chen: SoC requires that the tx channels are enabled. | ||
127 | * @has_chsel_offset: SoC uses offset for selecting dai operational mode. | ||
128 | * @reg_offset_txdata: offset of the tx fifo. | 133 | * @reg_offset_txdata: offset of the tx fifo. |
129 | * @sun4i_i2s_regmap: regmap config to use. | 134 | * @sun4i_i2s_regmap: regmap config to use. |
130 | * @mclk_offset: Value by which mclkdiv needs to be adjusted. | ||
131 | * @bclk_offset: Value by which bclkdiv needs to be adjusted. | ||
132 | * @field_clkdiv_mclk_en: regmap field to enable mclk output. | 135 | * @field_clkdiv_mclk_en: regmap field to enable mclk output. |
133 | * @field_fmt_wss: regmap field to set word select size. | 136 | * @field_fmt_wss: regmap field to set word select size. |
134 | * @field_fmt_sr: regmap field to set sample resolution. | 137 | * @field_fmt_sr: regmap field to set sample resolution. |
135 | * @field_fmt_bclk: regmap field to set clk polarity. | ||
136 | * @field_fmt_lrclk: regmap field to set frame polarity. | ||
137 | * @field_fmt_mode: regmap field to set the operational mode. | ||
138 | * @field_txchanmap: location of the tx channel mapping register. | ||
139 | * @field_rxchanmap: location of the rx channel mapping register. | ||
140 | * @field_txchansel: location of the tx channel select bit fields. | ||
141 | * @field_rxchansel: location of the rx channel select bit fields. | ||
142 | */ | 138 | */ |
143 | struct sun4i_i2s_quirks { | 139 | struct sun4i_i2s_quirks { |
144 | bool has_reset; | 140 | bool has_reset; |
145 | bool has_slave_select_bit; | ||
146 | bool has_fmt_set_lrck_period; | ||
147 | bool has_chcfg; | ||
148 | bool has_chsel_tx_chen; | ||
149 | bool has_chsel_offset; | ||
150 | unsigned int reg_offset_txdata; /* TX FIFO */ | 141 | unsigned int reg_offset_txdata; /* TX FIFO */ |
151 | const struct regmap_config *sun4i_i2s_regmap; | 142 | const struct regmap_config *sun4i_i2s_regmap; |
152 | unsigned int mclk_offset; | ||
153 | unsigned int bclk_offset; | ||
154 | 143 | ||
155 | /* Register fields for i2s */ | 144 | /* Register fields for i2s */ |
156 | struct reg_field field_clkdiv_mclk_en; | 145 | struct reg_field field_clkdiv_mclk_en; |
157 | struct reg_field field_fmt_wss; | 146 | struct reg_field field_fmt_wss; |
158 | struct reg_field field_fmt_sr; | 147 | struct reg_field field_fmt_sr; |
159 | struct reg_field field_fmt_bclk; | ||
160 | struct reg_field field_fmt_lrclk; | ||
161 | struct reg_field field_fmt_mode; | ||
162 | struct reg_field field_txchanmap; | ||
163 | struct reg_field field_rxchanmap; | ||
164 | struct reg_field field_txchansel; | ||
165 | struct reg_field field_rxchansel; | ||
166 | 148 | ||
149 | const struct sun4i_i2s_clk_div *bclk_dividers; | ||
150 | unsigned int num_bclk_dividers; | ||
151 | const struct sun4i_i2s_clk_div *mclk_dividers; | ||
152 | unsigned int num_mclk_dividers; | ||
153 | |||
154 | unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *); | ||
167 | s8 (*get_sr)(const struct sun4i_i2s *, int); | 155 | s8 (*get_sr)(const struct sun4i_i2s *, int); |
168 | s8 (*get_wss)(const struct sun4i_i2s *, int); | 156 | s8 (*get_wss)(const struct sun4i_i2s *, int); |
157 | int (*set_chan_cfg)(const struct sun4i_i2s *, | ||
158 | const struct snd_pcm_hw_params *); | ||
159 | int (*set_fmt)(const struct sun4i_i2s *, unsigned int); | ||
169 | }; | 160 | }; |
170 | 161 | ||
171 | struct sun4i_i2s { | 162 | struct sun4i_i2s { |
@@ -174,7 +165,10 @@ struct sun4i_i2s { | |||
174 | struct regmap *regmap; | 165 | struct regmap *regmap; |
175 | struct reset_control *rst; | 166 | struct reset_control *rst; |
176 | 167 | ||
168 | unsigned int format; | ||
177 | unsigned int mclk_freq; | 169 | unsigned int mclk_freq; |
170 | unsigned int slots; | ||
171 | unsigned int slot_width; | ||
178 | 172 | ||
179 | struct snd_dmaengine_dai_dma_data capture_dma_data; | 173 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
180 | struct snd_dmaengine_dai_dma_data playback_dma_data; | 174 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
@@ -183,13 +177,6 @@ struct sun4i_i2s { | |||
183 | struct regmap_field *field_clkdiv_mclk_en; | 177 | struct regmap_field *field_clkdiv_mclk_en; |
184 | struct regmap_field *field_fmt_wss; | 178 | struct regmap_field *field_fmt_wss; |
185 | struct regmap_field *field_fmt_sr; | 179 | struct regmap_field *field_fmt_sr; |
186 | struct regmap_field *field_fmt_bclk; | ||
187 | struct regmap_field *field_fmt_lrclk; | ||
188 | struct regmap_field *field_fmt_mode; | ||
189 | struct regmap_field *field_txchanmap; | ||
190 | struct regmap_field *field_rxchanmap; | ||
191 | struct regmap_field *field_txchansel; | ||
192 | struct regmap_field *field_rxchansel; | ||
193 | 180 | ||
194 | const struct sun4i_i2s_quirks *variant; | 181 | const struct sun4i_i2s_quirks *variant; |
195 | }; | 182 | }; |
@@ -221,15 +208,46 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = { | |||
221 | /* TODO - extend divide ratio supported by newer SoCs */ | 208 | /* TODO - extend divide ratio supported by newer SoCs */ |
222 | }; | 209 | }; |
223 | 210 | ||
211 | static const struct sun4i_i2s_clk_div sun8i_i2s_clk_div[] = { | ||
212 | { .div = 1, .val = 1 }, | ||
213 | { .div = 2, .val = 2 }, | ||
214 | { .div = 4, .val = 3 }, | ||
215 | { .div = 6, .val = 4 }, | ||
216 | { .div = 8, .val = 5 }, | ||
217 | { .div = 12, .val = 6 }, | ||
218 | { .div = 16, .val = 7 }, | ||
219 | { .div = 24, .val = 8 }, | ||
220 | { .div = 32, .val = 9 }, | ||
221 | { .div = 48, .val = 10 }, | ||
222 | { .div = 64, .val = 11 }, | ||
223 | { .div = 96, .val = 12 }, | ||
224 | { .div = 128, .val = 13 }, | ||
225 | { .div = 176, .val = 14 }, | ||
226 | { .div = 192, .val = 15 }, | ||
227 | }; | ||
228 | |||
229 | static unsigned long sun4i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s) | ||
230 | { | ||
231 | return i2s->mclk_freq; | ||
232 | } | ||
233 | |||
234 | static unsigned long sun8i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s) | ||
235 | { | ||
236 | return clk_get_rate(i2s->mod_clk); | ||
237 | } | ||
238 | |||
224 | static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, | 239 | static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, |
225 | unsigned int oversample_rate, | 240 | unsigned long parent_rate, |
241 | unsigned int sampling_rate, | ||
242 | unsigned int channels, | ||
226 | unsigned int word_size) | 243 | unsigned int word_size) |
227 | { | 244 | { |
228 | int div = oversample_rate / word_size / 2; | 245 | const struct sun4i_i2s_clk_div *dividers = i2s->variant->bclk_dividers; |
246 | int div = parent_rate / sampling_rate / word_size / channels; | ||
229 | int i; | 247 | int i; |
230 | 248 | ||
231 | for (i = 0; i < ARRAY_SIZE(sun4i_i2s_bclk_div); i++) { | 249 | for (i = 0; i < i2s->variant->num_bclk_dividers; i++) { |
232 | const struct sun4i_i2s_clk_div *bdiv = &sun4i_i2s_bclk_div[i]; | 250 | const struct sun4i_i2s_clk_div *bdiv = ÷rs[i]; |
233 | 251 | ||
234 | if (bdiv->div == div) | 252 | if (bdiv->div == div) |
235 | return bdiv->val; | 253 | return bdiv->val; |
@@ -239,15 +257,15 @@ static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, | |||
239 | } | 257 | } |
240 | 258 | ||
241 | static int sun4i_i2s_get_mclk_div(struct sun4i_i2s *i2s, | 259 | static int sun4i_i2s_get_mclk_div(struct sun4i_i2s *i2s, |
242 | unsigned int oversample_rate, | 260 | unsigned long parent_rate, |
243 | unsigned int module_rate, | 261 | unsigned long mclk_rate) |
244 | unsigned int sampling_rate) | ||
245 | { | 262 | { |
246 | int div = module_rate / sampling_rate / oversample_rate; | 263 | const struct sun4i_i2s_clk_div *dividers = i2s->variant->mclk_dividers; |
264 | int div = parent_rate / mclk_rate; | ||
247 | int i; | 265 | int i; |
248 | 266 | ||
249 | for (i = 0; i < ARRAY_SIZE(sun4i_i2s_mclk_div); i++) { | 267 | for (i = 0; i < i2s->variant->num_mclk_dividers; i++) { |
250 | const struct sun4i_i2s_clk_div *mdiv = &sun4i_i2s_mclk_div[i]; | 268 | const struct sun4i_i2s_clk_div *mdiv = ÷rs[i]; |
251 | 269 | ||
252 | if (mdiv->div == div) | 270 | if (mdiv->div == div) |
253 | return mdiv->val; | 271 | return mdiv->val; |
@@ -270,10 +288,11 @@ static bool sun4i_i2s_oversample_is_valid(unsigned int oversample) | |||
270 | 288 | ||
271 | static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, | 289 | static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, |
272 | unsigned int rate, | 290 | unsigned int rate, |
273 | unsigned int word_size) | 291 | unsigned int slots, |
292 | unsigned int slot_width) | ||
274 | { | 293 | { |
275 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 294 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
276 | unsigned int oversample_rate, clk_rate; | 295 | unsigned int oversample_rate, clk_rate, bclk_parent_rate; |
277 | int bclk_div, mclk_div; | 296 | int bclk_div, mclk_div; |
278 | int ret; | 297 | int ret; |
279 | 298 | ||
@@ -315,36 +334,26 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, | |||
315 | return -EINVAL; | 334 | return -EINVAL; |
316 | } | 335 | } |
317 | 336 | ||
318 | bclk_div = sun4i_i2s_get_bclk_div(i2s, oversample_rate, | 337 | bclk_parent_rate = i2s->variant->get_bclk_parent_rate(i2s); |
319 | word_size); | 338 | bclk_div = sun4i_i2s_get_bclk_div(i2s, bclk_parent_rate, |
339 | rate, slots, slot_width); | ||
320 | if (bclk_div < 0) { | 340 | if (bclk_div < 0) { |
321 | dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div); | 341 | dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div); |
322 | return -EINVAL; | 342 | return -EINVAL; |
323 | } | 343 | } |
324 | 344 | ||
325 | mclk_div = sun4i_i2s_get_mclk_div(i2s, oversample_rate, | 345 | mclk_div = sun4i_i2s_get_mclk_div(i2s, clk_rate, i2s->mclk_freq); |
326 | clk_rate, rate); | ||
327 | if (mclk_div < 0) { | 346 | if (mclk_div < 0) { |
328 | dev_err(dai->dev, "Unsupported MCLK divider: %d\n", mclk_div); | 347 | dev_err(dai->dev, "Unsupported MCLK divider: %d\n", mclk_div); |
329 | return -EINVAL; | 348 | return -EINVAL; |
330 | } | 349 | } |
331 | 350 | ||
332 | /* Adjust the clock division values if needed */ | ||
333 | bclk_div += i2s->variant->bclk_offset; | ||
334 | mclk_div += i2s->variant->mclk_offset; | ||
335 | |||
336 | regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG, | 351 | regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG, |
337 | SUN4I_I2S_CLK_DIV_BCLK(bclk_div) | | 352 | SUN4I_I2S_CLK_DIV_BCLK(bclk_div) | |
338 | SUN4I_I2S_CLK_DIV_MCLK(mclk_div)); | 353 | SUN4I_I2S_CLK_DIV_MCLK(mclk_div)); |
339 | 354 | ||
340 | regmap_field_write(i2s->field_clkdiv_mclk_en, 1); | 355 | regmap_field_write(i2s->field_clkdiv_mclk_en, 1); |
341 | 356 | ||
342 | /* Set sync period */ | ||
343 | if (i2s->variant->has_fmt_set_lrck_period) | ||
344 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, | ||
345 | SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, | ||
346 | SUN8I_I2S_FMT0_LRCK_PERIOD(32)); | ||
347 | |||
348 | return 0; | 357 | return 0; |
349 | } | 358 | } |
350 | 359 | ||
@@ -381,45 +390,105 @@ static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width) | |||
381 | return (width - 8) / 4 + 1; | 390 | return (width - 8) / 4 + 1; |
382 | } | 391 | } |
383 | 392 | ||
384 | static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | 393 | static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, |
385 | struct snd_pcm_hw_params *params, | 394 | const struct snd_pcm_hw_params *params) |
386 | struct snd_soc_dai *dai) | ||
387 | { | 395 | { |
388 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 396 | unsigned int channels = params_channels(params); |
389 | int sr, wss, channels; | ||
390 | u32 width; | ||
391 | 397 | ||
392 | channels = params_channels(params); | 398 | /* Map the channels for playback and capture */ |
393 | if (channels != 2) { | 399 | regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210); |
394 | dev_err(dai->dev, "Unsupported number of channels: %d\n", | 400 | regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210); |
395 | channels); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | 401 | ||
399 | if (i2s->variant->has_chcfg) { | 402 | /* Configure the channels */ |
400 | regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, | 403 | regmap_update_bits(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG, |
401 | SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, | 404 | SUN4I_I2S_CHAN_SEL_MASK, |
402 | SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels)); | 405 | SUN4I_I2S_CHAN_SEL(channels)); |
403 | regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, | 406 | regmap_update_bits(i2s->regmap, SUN4I_I2S_RX_CHAN_SEL_REG, |
404 | SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, | 407 | SUN4I_I2S_CHAN_SEL_MASK, |
405 | SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); | 408 | SUN4I_I2S_CHAN_SEL(channels)); |
406 | } | 409 | |
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, | ||
414 | const struct snd_pcm_hw_params *params) | ||
415 | { | ||
416 | unsigned int channels = params_channels(params); | ||
417 | unsigned int slots = channels; | ||
418 | unsigned int lrck_period; | ||
419 | |||
420 | if (i2s->slots) | ||
421 | slots = i2s->slots; | ||
407 | 422 | ||
408 | /* Map the channels for playback and capture */ | 423 | /* Map the channels for playback and capture */ |
409 | regmap_field_write(i2s->field_txchanmap, 0x76543210); | 424 | regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210); |
410 | regmap_field_write(i2s->field_rxchanmap, 0x00003210); | 425 | regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210); |
411 | 426 | ||
412 | /* Configure the channels */ | 427 | /* Configure the channels */ |
413 | regmap_field_write(i2s->field_txchansel, | 428 | regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, |
414 | SUN4I_I2S_CHAN_SEL(params_channels(params))); | 429 | SUN4I_I2S_CHAN_SEL_MASK, |
430 | SUN4I_I2S_CHAN_SEL(channels)); | ||
431 | regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, | ||
432 | SUN4I_I2S_CHAN_SEL_MASK, | ||
433 | SUN4I_I2S_CHAN_SEL(channels)); | ||
434 | |||
435 | regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, | ||
436 | SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, | ||
437 | SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels)); | ||
438 | regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, | ||
439 | SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK, | ||
440 | SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels)); | ||
441 | |||
442 | switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
443 | case SND_SOC_DAIFMT_DSP_A: | ||
444 | case SND_SOC_DAIFMT_DSP_B: | ||
445 | case SND_SOC_DAIFMT_LEFT_J: | ||
446 | case SND_SOC_DAIFMT_RIGHT_J: | ||
447 | lrck_period = params_physical_width(params) * slots; | ||
448 | break; | ||
449 | |||
450 | case SND_SOC_DAIFMT_I2S: | ||
451 | lrck_period = params_physical_width(params); | ||
452 | break; | ||
453 | |||
454 | default: | ||
455 | return -EINVAL; | ||
456 | } | ||
457 | |||
458 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, | ||
459 | SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, | ||
460 | SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); | ||
461 | |||
462 | regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, | ||
463 | SUN8I_I2S_TX_CHAN_EN_MASK, | ||
464 | SUN8I_I2S_TX_CHAN_EN(channels)); | ||
465 | |||
466 | return 0; | ||
467 | } | ||
415 | 468 | ||
416 | regmap_field_write(i2s->field_rxchansel, | 469 | static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, |
417 | SUN4I_I2S_CHAN_SEL(params_channels(params))); | 470 | struct snd_pcm_hw_params *params, |
471 | struct snd_soc_dai *dai) | ||
472 | { | ||
473 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
474 | unsigned int word_size = params_width(params); | ||
475 | unsigned int slot_width = params_physical_width(params); | ||
476 | unsigned int channels = params_channels(params); | ||
477 | unsigned int slots = channels; | ||
478 | int ret, sr, wss; | ||
479 | u32 width; | ||
480 | |||
481 | if (i2s->slots) | ||
482 | slots = i2s->slots; | ||
483 | |||
484 | if (i2s->slot_width) | ||
485 | slot_width = i2s->slot_width; | ||
418 | 486 | ||
419 | if (i2s->variant->has_chsel_tx_chen) | 487 | ret = i2s->variant->set_chan_cfg(i2s, params); |
420 | regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, | 488 | if (ret < 0) { |
421 | SUN8I_I2S_TX_CHAN_EN_MASK, | 489 | dev_err(dai->dev, "Invalid channel configuration\n"); |
422 | SUN8I_I2S_TX_CHAN_EN(channels)); | 490 | return ret; |
491 | } | ||
423 | 492 | ||
424 | switch (params_physical_width(params)) { | 493 | switch (params_physical_width(params)) { |
425 | case 16: | 494 | case 16: |
@@ -432,11 +501,11 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | |||
432 | } | 501 | } |
433 | i2s->playback_dma_data.addr_width = width; | 502 | i2s->playback_dma_data.addr_width = width; |
434 | 503 | ||
435 | sr = i2s->variant->get_sr(i2s, params_width(params)); | 504 | sr = i2s->variant->get_sr(i2s, word_size); |
436 | if (sr < 0) | 505 | if (sr < 0) |
437 | return -EINVAL; | 506 | return -EINVAL; |
438 | 507 | ||
439 | wss = i2s->variant->get_wss(i2s, params_width(params)); | 508 | wss = i2s->variant->get_wss(i2s, slot_width); |
440 | if (wss < 0) | 509 | if (wss < 0) |
441 | return -EINVAL; | 510 | return -EINVAL; |
442 | 511 | ||
@@ -444,126 +513,193 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, | |||
444 | regmap_field_write(i2s->field_fmt_sr, sr); | 513 | regmap_field_write(i2s->field_fmt_sr, sr); |
445 | 514 | ||
446 | return sun4i_i2s_set_clk_rate(dai, params_rate(params), | 515 | return sun4i_i2s_set_clk_rate(dai, params_rate(params), |
447 | params_width(params)); | 516 | slots, slot_width); |
448 | } | 517 | } |
449 | 518 | ||
450 | static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 519 | static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, |
520 | unsigned int fmt) | ||
451 | { | 521 | { |
452 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
453 | u32 val; | 522 | u32 val; |
454 | u32 offset = 0; | 523 | |
455 | u32 bclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL; | 524 | /* DAI clock polarity */ |
456 | u32 lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL; | 525 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
526 | case SND_SOC_DAIFMT_IB_IF: | ||
527 | /* Invert both clocks */ | ||
528 | val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED | | ||
529 | SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED; | ||
530 | break; | ||
531 | case SND_SOC_DAIFMT_IB_NF: | ||
532 | /* Invert bit clock */ | ||
533 | val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED; | ||
534 | break; | ||
535 | case SND_SOC_DAIFMT_NB_IF: | ||
536 | /* Invert frame clock */ | ||
537 | val = SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED; | ||
538 | break; | ||
539 | case SND_SOC_DAIFMT_NB_NF: | ||
540 | val = 0; | ||
541 | break; | ||
542 | default: | ||
543 | return -EINVAL; | ||
544 | } | ||
545 | |||
546 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, | ||
547 | SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK | | ||
548 | SUN4I_I2S_FMT0_BCLK_POLARITY_MASK, | ||
549 | val); | ||
457 | 550 | ||
458 | /* DAI Mode */ | 551 | /* DAI Mode */ |
459 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 552 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
460 | case SND_SOC_DAIFMT_I2S: | 553 | case SND_SOC_DAIFMT_I2S: |
461 | val = SUN4I_I2S_FMT0_FMT_I2S; | 554 | val = SUN4I_I2S_FMT0_FMT_I2S; |
462 | offset = 1; | ||
463 | break; | 555 | break; |
556 | |||
464 | case SND_SOC_DAIFMT_LEFT_J: | 557 | case SND_SOC_DAIFMT_LEFT_J: |
465 | val = SUN4I_I2S_FMT0_FMT_LEFT_J; | 558 | val = SUN4I_I2S_FMT0_FMT_LEFT_J; |
466 | break; | 559 | break; |
560 | |||
467 | case SND_SOC_DAIFMT_RIGHT_J: | 561 | case SND_SOC_DAIFMT_RIGHT_J: |
468 | val = SUN4I_I2S_FMT0_FMT_RIGHT_J; | 562 | val = SUN4I_I2S_FMT0_FMT_RIGHT_J; |
469 | break; | 563 | break; |
564 | |||
470 | default: | 565 | default: |
471 | dev_err(dai->dev, "Unsupported format: %d\n", | ||
472 | fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
473 | return -EINVAL; | 566 | return -EINVAL; |
474 | } | 567 | } |
475 | 568 | ||
476 | if (i2s->variant->has_chsel_offset) { | 569 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, |
477 | /* | 570 | SUN4I_I2S_FMT0_FMT_MASK, val); |
478 | * offset being set indicates that we're connected to an i2s | ||
479 | * device, however offset is only used on the sun8i block and | ||
480 | * i2s shares the same setting with the LJ format. Increment | ||
481 | * val so that the bit to value to write is correct. | ||
482 | */ | ||
483 | if (offset > 0) | ||
484 | val++; | ||
485 | /* blck offset determines whether i2s or LJ */ | ||
486 | regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, | ||
487 | SUN8I_I2S_TX_CHAN_OFFSET_MASK, | ||
488 | SUN8I_I2S_TX_CHAN_OFFSET(offset)); | ||
489 | |||
490 | regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, | ||
491 | SUN8I_I2S_TX_CHAN_OFFSET_MASK, | ||
492 | SUN8I_I2S_TX_CHAN_OFFSET(offset)); | ||
493 | } | ||
494 | 571 | ||
495 | regmap_field_write(i2s->field_fmt_mode, val); | 572 | /* DAI clock master masks */ |
573 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
574 | case SND_SOC_DAIFMT_CBS_CFS: | ||
575 | /* BCLK and LRCLK master */ | ||
576 | val = SUN4I_I2S_CTRL_MODE_MASTER; | ||
577 | break; | ||
496 | 578 | ||
497 | /* DAI clock polarity */ | 579 | case SND_SOC_DAIFMT_CBM_CFM: |
580 | /* BCLK and LRCLK slave */ | ||
581 | val = SUN4I_I2S_CTRL_MODE_SLAVE; | ||
582 | break; | ||
583 | |||
584 | default: | ||
585 | return -EINVAL; | ||
586 | } | ||
587 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
588 | SUN4I_I2S_CTRL_MODE_MASK, val); | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, | ||
593 | unsigned int fmt) | ||
594 | { | ||
595 | u32 mode, val; | ||
596 | u8 offset; | ||
597 | |||
598 | /* | ||
599 | * DAI clock polarity | ||
600 | * | ||
601 | * The setup for LRCK contradicts the datasheet, but under a | ||
602 | * scope it's clear that the LRCK polarity is reversed | ||
603 | * compared to the expected polarity on the bus. | ||
604 | */ | ||
498 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 605 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
499 | case SND_SOC_DAIFMT_IB_IF: | 606 | case SND_SOC_DAIFMT_IB_IF: |
500 | /* Invert both clocks */ | 607 | /* Invert both clocks */ |
501 | bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; | 608 | val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED; |
502 | lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; | ||
503 | break; | 609 | break; |
504 | case SND_SOC_DAIFMT_IB_NF: | 610 | case SND_SOC_DAIFMT_IB_NF: |
505 | /* Invert bit clock */ | 611 | /* Invert bit clock */ |
506 | bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; | 612 | val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED | |
613 | SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED; | ||
507 | break; | 614 | break; |
508 | case SND_SOC_DAIFMT_NB_IF: | 615 | case SND_SOC_DAIFMT_NB_IF: |
509 | /* Invert frame clock */ | 616 | /* Invert frame clock */ |
510 | lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED; | 617 | val = 0; |
511 | break; | 618 | break; |
512 | case SND_SOC_DAIFMT_NB_NF: | 619 | case SND_SOC_DAIFMT_NB_NF: |
620 | val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED; | ||
513 | break; | 621 | break; |
514 | default: | 622 | default: |
515 | dev_err(dai->dev, "Unsupported clock polarity: %d\n", | ||
516 | fmt & SND_SOC_DAIFMT_INV_MASK); | ||
517 | return -EINVAL; | 623 | return -EINVAL; |
518 | } | 624 | } |
519 | 625 | ||
520 | regmap_field_write(i2s->field_fmt_bclk, bclk_polarity); | 626 | regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG, |
521 | regmap_field_write(i2s->field_fmt_lrclk, lrclk_polarity); | 627 | SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK | |
522 | 628 | SUN8I_I2S_FMT0_BCLK_POLARITY_MASK, | |
523 | if (i2s->variant->has_slave_select_bit) { | 629 | val); |
524 | /* DAI clock master masks */ | 630 | |
525 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 631 | /* DAI Mode */ |
526 | case SND_SOC_DAIFMT_CBS_CFS: | 632 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
527 | /* BCLK and LRCLK master */ | 633 | case SND_SOC_DAIFMT_DSP_A: |
528 | val = SUN4I_I2S_CTRL_MODE_MASTER; | 634 | mode = SUN8I_I2S_CTRL_MODE_PCM; |
529 | break; | 635 | offset = 1; |
530 | case SND_SOC_DAIFMT_CBM_CFM: | 636 | break; |
531 | /* BCLK and LRCLK slave */ | 637 | |
532 | val = SUN4I_I2S_CTRL_MODE_SLAVE; | 638 | case SND_SOC_DAIFMT_DSP_B: |
533 | break; | 639 | mode = SUN8I_I2S_CTRL_MODE_PCM; |
534 | default: | 640 | offset = 0; |
535 | dev_err(dai->dev, "Unsupported slave setting: %d\n", | 641 | break; |
536 | fmt & SND_SOC_DAIFMT_MASTER_MASK); | 642 | |
537 | return -EINVAL; | 643 | case SND_SOC_DAIFMT_I2S: |
538 | } | 644 | mode = SUN8I_I2S_CTRL_MODE_LEFT; |
539 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | 645 | offset = 1; |
540 | SUN4I_I2S_CTRL_MODE_MASK, | 646 | break; |
541 | val); | 647 | |
542 | } else { | 648 | case SND_SOC_DAIFMT_LEFT_J: |
543 | /* | 649 | mode = SUN8I_I2S_CTRL_MODE_LEFT; |
544 | * The newer i2s block does not have a slave select bit, | 650 | offset = 0; |
545 | * instead the clk pins are configured as inputs. | 651 | break; |
546 | */ | 652 | |
547 | /* DAI clock master masks */ | 653 | case SND_SOC_DAIFMT_RIGHT_J: |
548 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 654 | mode = SUN8I_I2S_CTRL_MODE_RIGHT; |
549 | case SND_SOC_DAIFMT_CBS_CFS: | 655 | offset = 0; |
550 | /* BCLK and LRCLK master */ | 656 | break; |
551 | val = SUN8I_I2S_CTRL_BCLK_OUT | | 657 | |
552 | SUN8I_I2S_CTRL_LRCK_OUT; | 658 | default: |
553 | break; | 659 | return -EINVAL; |
554 | case SND_SOC_DAIFMT_CBM_CFM: | 660 | } |
555 | /* BCLK and LRCLK slave */ | 661 | |
556 | val = 0; | 662 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, |
557 | break; | 663 | SUN8I_I2S_CTRL_MODE_MASK, mode); |
558 | default: | 664 | regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, |
559 | dev_err(dai->dev, "Unsupported slave setting: %d\n", | 665 | SUN8I_I2S_TX_CHAN_OFFSET_MASK, |
560 | fmt & SND_SOC_DAIFMT_MASTER_MASK); | 666 | SUN8I_I2S_TX_CHAN_OFFSET(offset)); |
561 | return -EINVAL; | 667 | regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, |
562 | } | 668 | SUN8I_I2S_TX_CHAN_OFFSET_MASK, |
563 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | 669 | SUN8I_I2S_TX_CHAN_OFFSET(offset)); |
564 | SUN8I_I2S_CTRL_BCLK_OUT | | 670 | |
565 | SUN8I_I2S_CTRL_LRCK_OUT, | 671 | /* DAI clock master masks */ |
566 | val); | 672 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
673 | case SND_SOC_DAIFMT_CBS_CFS: | ||
674 | /* BCLK and LRCLK master */ | ||
675 | val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT; | ||
676 | break; | ||
677 | |||
678 | case SND_SOC_DAIFMT_CBM_CFM: | ||
679 | /* BCLK and LRCLK slave */ | ||
680 | val = 0; | ||
681 | break; | ||
682 | |||
683 | default: | ||
684 | return -EINVAL; | ||
685 | } | ||
686 | |||
687 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
688 | SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT, | ||
689 | val); | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
695 | { | ||
696 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
697 | int ret; | ||
698 | |||
699 | ret = i2s->variant->set_fmt(i2s, fmt); | ||
700 | if (ret) { | ||
701 | dev_err(dai->dev, "Unsupported format configuration\n"); | ||
702 | return ret; | ||
567 | } | 703 | } |
568 | 704 | ||
569 | /* Set significant bits in our FIFOs */ | 705 | /* Set significant bits in our FIFOs */ |
@@ -572,6 +708,9 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
572 | SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK, | 708 | SUN4I_I2S_FIFO_CTRL_RX_MODE_MASK, |
573 | SUN4I_I2S_FIFO_CTRL_TX_MODE(1) | | 709 | SUN4I_I2S_FIFO_CTRL_TX_MODE(1) | |
574 | SUN4I_I2S_FIFO_CTRL_RX_MODE(1)); | 710 | SUN4I_I2S_FIFO_CTRL_RX_MODE(1)); |
711 | |||
712 | i2s->format = fmt; | ||
713 | |||
575 | return 0; | 714 | return 0; |
576 | } | 715 | } |
577 | 716 | ||
@@ -687,10 +826,26 @@ static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
687 | return 0; | 826 | return 0; |
688 | } | 827 | } |
689 | 828 | ||
829 | static int sun4i_i2s_set_tdm_slot(struct snd_soc_dai *dai, | ||
830 | unsigned int tx_mask, unsigned int rx_mask, | ||
831 | int slots, int slot_width) | ||
832 | { | ||
833 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
834 | |||
835 | if (slots > 8) | ||
836 | return -EINVAL; | ||
837 | |||
838 | i2s->slots = slots; | ||
839 | i2s->slot_width = slot_width; | ||
840 | |||
841 | return 0; | ||
842 | } | ||
843 | |||
690 | static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { | 844 | static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { |
691 | .hw_params = sun4i_i2s_hw_params, | 845 | .hw_params = sun4i_i2s_hw_params, |
692 | .set_fmt = sun4i_i2s_set_fmt, | 846 | .set_fmt = sun4i_i2s_set_fmt, |
693 | .set_sysclk = sun4i_i2s_set_sysclk, | 847 | .set_sysclk = sun4i_i2s_set_sysclk, |
848 | .set_tdm_slot = sun4i_i2s_set_tdm_slot, | ||
694 | .trigger = sun4i_i2s_trigger, | 849 | .trigger = sun4i_i2s_trigger, |
695 | }; | 850 | }; |
696 | 851 | ||
@@ -711,15 +866,15 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = { | |||
711 | .probe = sun4i_i2s_dai_probe, | 866 | .probe = sun4i_i2s_dai_probe, |
712 | .capture = { | 867 | .capture = { |
713 | .stream_name = "Capture", | 868 | .stream_name = "Capture", |
714 | .channels_min = 2, | 869 | .channels_min = 1, |
715 | .channels_max = 2, | 870 | .channels_max = 8, |
716 | .rates = SNDRV_PCM_RATE_8000_192000, | 871 | .rates = SNDRV_PCM_RATE_8000_192000, |
717 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 872 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
718 | }, | 873 | }, |
719 | .playback = { | 874 | .playback = { |
720 | .stream_name = "Playback", | 875 | .stream_name = "Playback", |
721 | .channels_min = 2, | 876 | .channels_min = 1, |
722 | .channels_max = 2, | 877 | .channels_max = 8, |
723 | .rates = SNDRV_PCM_RATE_8000_192000, | 878 | .rates = SNDRV_PCM_RATE_8000_192000, |
724 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 879 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
725 | }, | 880 | }, |
@@ -913,16 +1068,15 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { | |||
913 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), | 1068 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), |
914 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), | 1069 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), |
915 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), | 1070 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), |
916 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), | 1071 | .bclk_dividers = sun4i_i2s_bclk_div, |
917 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | 1072 | .num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div), |
918 | .has_slave_select_bit = true, | 1073 | .mclk_dividers = sun4i_i2s_mclk_div, |
919 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), | 1074 | .num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div), |
920 | .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), | 1075 | .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate, |
921 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | ||
922 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
923 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
924 | .get_sr = sun4i_i2s_get_sr, | 1076 | .get_sr = sun4i_i2s_get_sr, |
925 | .get_wss = sun4i_i2s_get_wss, | 1077 | .get_wss = sun4i_i2s_get_wss, |
1078 | .set_chan_cfg = sun4i_i2s_set_chan_cfg, | ||
1079 | .set_fmt = sun4i_i2s_set_soc_fmt, | ||
926 | }; | 1080 | }; |
927 | 1081 | ||
928 | static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { | 1082 | static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { |
@@ -932,18 +1086,22 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { | |||
932 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), | 1086 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), |
933 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), | 1087 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), |
934 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), | 1088 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), |
935 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), | 1089 | .bclk_dividers = sun4i_i2s_bclk_div, |
936 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | 1090 | .num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div), |
937 | .has_slave_select_bit = true, | 1091 | .mclk_dividers = sun4i_i2s_mclk_div, |
938 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), | 1092 | .num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div), |
939 | .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), | 1093 | .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate, |
940 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | ||
941 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
942 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
943 | .get_sr = sun4i_i2s_get_sr, | 1094 | .get_sr = sun4i_i2s_get_sr, |
944 | .get_wss = sun4i_i2s_get_wss, | 1095 | .get_wss = sun4i_i2s_get_wss, |
1096 | .set_chan_cfg = sun4i_i2s_set_chan_cfg, | ||
1097 | .set_fmt = sun4i_i2s_set_soc_fmt, | ||
945 | }; | 1098 | }; |
946 | 1099 | ||
1100 | /* | ||
1101 | * This doesn't describe the TDM controller documented in the A83t | ||
1102 | * datasheet, but the three undocumented I2S controller that use the | ||
1103 | * older design. | ||
1104 | */ | ||
947 | static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { | 1105 | static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { |
948 | .has_reset = true, | 1106 | .has_reset = true, |
949 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, | 1107 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, |
@@ -951,59 +1109,51 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { | |||
951 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), | 1109 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), |
952 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), | 1110 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), |
953 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), | 1111 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), |
954 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), | 1112 | .bclk_dividers = sun4i_i2s_bclk_div, |
955 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | 1113 | .num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div), |
956 | .has_slave_select_bit = true, | 1114 | .mclk_dividers = sun4i_i2s_mclk_div, |
957 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), | 1115 | .num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div), |
958 | .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), | 1116 | .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate, |
959 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | 1117 | .get_sr = sun4i_i2s_get_sr, |
960 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | 1118 | .get_wss = sun4i_i2s_get_wss, |
961 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | 1119 | .set_chan_cfg = sun4i_i2s_set_chan_cfg, |
962 | .get_sr = sun8i_i2s_get_sr_wss, | 1120 | .set_fmt = sun4i_i2s_set_soc_fmt, |
963 | .get_wss = sun8i_i2s_get_sr_wss, | ||
964 | }; | 1121 | }; |
965 | 1122 | ||
966 | static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { | 1123 | static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { |
967 | .has_reset = true, | 1124 | .has_reset = true, |
968 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, | 1125 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, |
969 | .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, | 1126 | .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, |
970 | .mclk_offset = 1, | ||
971 | .bclk_offset = 2, | ||
972 | .has_fmt_set_lrck_period = true, | ||
973 | .has_chcfg = true, | ||
974 | .has_chsel_tx_chen = true, | ||
975 | .has_chsel_offset = true, | ||
976 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), | 1127 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), |
977 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), | 1128 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), |
978 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), | 1129 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), |
979 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | 1130 | .bclk_dividers = sun8i_i2s_clk_div, |
980 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19), | 1131 | .num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), |
981 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_CTRL_REG, 4, 5), | 1132 | .mclk_dividers = sun8i_i2s_clk_div, |
982 | .field_txchanmap = REG_FIELD(SUN8I_I2S_TX_CHAN_MAP_REG, 0, 31), | 1133 | .num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), |
983 | .field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31), | 1134 | .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate, |
984 | .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
985 | .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
986 | .get_sr = sun8i_i2s_get_sr_wss, | 1135 | .get_sr = sun8i_i2s_get_sr_wss, |
987 | .get_wss = sun8i_i2s_get_sr_wss, | 1136 | .get_wss = sun8i_i2s_get_sr_wss, |
1137 | .set_chan_cfg = sun8i_i2s_set_chan_cfg, | ||
1138 | .set_fmt = sun8i_i2s_set_soc_fmt, | ||
988 | }; | 1139 | }; |
989 | 1140 | ||
990 | static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { | 1141 | static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { |
991 | .has_reset = true, | 1142 | .has_reset = true, |
992 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, | 1143 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, |
993 | .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, | 1144 | .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, |
994 | .has_slave_select_bit = true, | ||
995 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), | 1145 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), |
996 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), | 1146 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), |
997 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), | 1147 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), |
998 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), | 1148 | .bclk_dividers = sun4i_i2s_bclk_div, |
999 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | 1149 | .num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div), |
1000 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), | 1150 | .mclk_dividers = sun4i_i2s_mclk_div, |
1001 | .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), | 1151 | .num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div), |
1002 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | 1152 | .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate, |
1003 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
1004 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
1005 | .get_sr = sun4i_i2s_get_sr, | 1153 | .get_sr = sun4i_i2s_get_sr, |
1006 | .get_wss = sun4i_i2s_get_wss, | 1154 | .get_wss = sun4i_i2s_get_wss, |
1155 | .set_chan_cfg = sun4i_i2s_set_chan_cfg, | ||
1156 | .set_fmt = sun4i_i2s_set_soc_fmt, | ||
1007 | }; | 1157 | }; |
1008 | 1158 | ||
1009 | static int sun4i_i2s_init_regmap_fields(struct device *dev, | 1159 | static int sun4i_i2s_init_regmap_fields(struct device *dev, |
@@ -1027,46 +1177,7 @@ static int sun4i_i2s_init_regmap_fields(struct device *dev, | |||
1027 | if (IS_ERR(i2s->field_fmt_sr)) | 1177 | if (IS_ERR(i2s->field_fmt_sr)) |
1028 | return PTR_ERR(i2s->field_fmt_sr); | 1178 | return PTR_ERR(i2s->field_fmt_sr); |
1029 | 1179 | ||
1030 | i2s->field_fmt_bclk = | 1180 | return 0; |
1031 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
1032 | i2s->variant->field_fmt_bclk); | ||
1033 | if (IS_ERR(i2s->field_fmt_bclk)) | ||
1034 | return PTR_ERR(i2s->field_fmt_bclk); | ||
1035 | |||
1036 | i2s->field_fmt_lrclk = | ||
1037 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
1038 | i2s->variant->field_fmt_lrclk); | ||
1039 | if (IS_ERR(i2s->field_fmt_lrclk)) | ||
1040 | return PTR_ERR(i2s->field_fmt_lrclk); | ||
1041 | |||
1042 | i2s->field_fmt_mode = | ||
1043 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
1044 | i2s->variant->field_fmt_mode); | ||
1045 | if (IS_ERR(i2s->field_fmt_mode)) | ||
1046 | return PTR_ERR(i2s->field_fmt_mode); | ||
1047 | |||
1048 | i2s->field_txchanmap = | ||
1049 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
1050 | i2s->variant->field_txchanmap); | ||
1051 | if (IS_ERR(i2s->field_txchanmap)) | ||
1052 | return PTR_ERR(i2s->field_txchanmap); | ||
1053 | |||
1054 | i2s->field_rxchanmap = | ||
1055 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
1056 | i2s->variant->field_rxchanmap); | ||
1057 | if (IS_ERR(i2s->field_rxchanmap)) | ||
1058 | return PTR_ERR(i2s->field_rxchanmap); | ||
1059 | |||
1060 | i2s->field_txchansel = | ||
1061 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
1062 | i2s->variant->field_txchansel); | ||
1063 | if (IS_ERR(i2s->field_txchansel)) | ||
1064 | return PTR_ERR(i2s->field_txchansel); | ||
1065 | |||
1066 | i2s->field_rxchansel = | ||
1067 | devm_regmap_field_alloc(dev, i2s->regmap, | ||
1068 | i2s->variant->field_rxchansel); | ||
1069 | return PTR_ERR_OR_ZERO(i2s->field_rxchansel); | ||
1070 | } | 1181 | } |
1071 | 1182 | ||
1072 | static int sun4i_i2s_probe(struct platform_device *pdev) | 1183 | static int sun4i_i2s_probe(struct platform_device *pdev) |
@@ -1087,10 +1198,8 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
1087 | return PTR_ERR(regs); | 1198 | return PTR_ERR(regs); |
1088 | 1199 | ||
1089 | irq = platform_get_irq(pdev, 0); | 1200 | irq = platform_get_irq(pdev, 0); |
1090 | if (irq < 0) { | 1201 | if (irq < 0) |
1091 | dev_err(&pdev->dev, "Can't retrieve our interrupt\n"); | ||
1092 | return irq; | 1202 | return irq; |
1093 | } | ||
1094 | 1203 | ||
1095 | i2s->variant = of_device_get_match_data(&pdev->dev); | 1204 | i2s->variant = of_device_get_match_data(&pdev->dev); |
1096 | if (!i2s->variant) { | 1205 | if (!i2s->variant) { |
@@ -1154,7 +1263,7 @@ static int sun4i_i2s_probe(struct platform_device *pdev) | |||
1154 | goto err_suspend; | 1263 | goto err_suspend; |
1155 | } | 1264 | } |
1156 | 1265 | ||
1157 | ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | 1266 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); |
1158 | if (ret) { | 1267 | if (ret) { |
1159 | dev_err(&pdev->dev, "Could not register PCM\n"); | 1268 | dev_err(&pdev->dev, "Could not register PCM\n"); |
1160 | goto err_suspend; | 1269 | goto err_suspend; |
@@ -1185,8 +1294,6 @@ static int sun4i_i2s_remove(struct platform_device *pdev) | |||
1185 | { | 1294 | { |
1186 | struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev); | 1295 | struct sun4i_i2s *i2s = dev_get_drvdata(&pdev->dev); |
1187 | 1296 | ||
1188 | snd_dmaengine_pcm_unregister(&pdev->dev); | ||
1189 | |||
1190 | pm_runtime_disable(&pdev->dev); | 1297 | pm_runtime_disable(&pdev->dev); |
1191 | if (!pm_runtime_status_suspended(&pdev->dev)) | 1298 | if (!pm_runtime_status_suspended(&pdev->dev)) |
1192 | sun4i_i2s_runtime_suspend(&pdev->dev); | 1299 | sun4i_i2s_runtime_suspend(&pdev->dev); |
diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index 6d1de565350e..f5b7069bcca2 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c | |||
@@ -459,12 +459,10 @@ MODULE_DEVICE_TABLE(of, sun50i_codec_analog_of_match); | |||
459 | 459 | ||
460 | static int sun50i_codec_analog_probe(struct platform_device *pdev) | 460 | static int sun50i_codec_analog_probe(struct platform_device *pdev) |
461 | { | 461 | { |
462 | struct resource *res; | ||
463 | struct regmap *regmap; | 462 | struct regmap *regmap; |
464 | void __iomem *base; | 463 | void __iomem *base; |
465 | 464 | ||
466 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 465 | base = devm_platform_ioremap_resource(pdev, 0); |
467 | base = devm_ioremap_resource(&pdev->dev, res); | ||
468 | if (IS_ERR(base)) { | 466 | if (IS_ERR(base)) { |
469 | dev_err(&pdev->dev, "Failed to map the registers\n"); | 467 | dev_err(&pdev->dev, "Failed to map the registers\n"); |
470 | return PTR_ERR(base); | 468 | return PTR_ERR(base); |
diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c index e92aeedd6feb..be872eefa61e 100644 --- a/sound/soc/sunxi/sun8i-codec-analog.c +++ b/sound/soc/sunxi/sun8i-codec-analog.c | |||
@@ -819,12 +819,10 @@ MODULE_DEVICE_TABLE(of, sun8i_codec_analog_of_match); | |||
819 | 819 | ||
820 | static int sun8i_codec_analog_probe(struct platform_device *pdev) | 820 | static int sun8i_codec_analog_probe(struct platform_device *pdev) |
821 | { | 821 | { |
822 | struct resource *res; | ||
823 | struct regmap *regmap; | 822 | struct regmap *regmap; |
824 | void __iomem *base; | 823 | void __iomem *base; |
825 | 824 | ||
826 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 825 | base = devm_platform_ioremap_resource(pdev, 0); |
827 | base = devm_ioremap_resource(&pdev->dev, res); | ||
828 | if (IS_ERR(base)) { | 826 | if (IS_ERR(base)) { |
829 | dev_err(&pdev->dev, "Failed to map the registers\n"); | 827 | dev_err(&pdev->dev, "Failed to map the registers\n"); |
830 | return PTR_ERR(base); | 828 | return PTR_ERR(base); |
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 0e0e8ebaa571..55798bc8eae2 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c | |||
@@ -533,7 +533,6 @@ static const struct regmap_config sun8i_codec_regmap_config = { | |||
533 | 533 | ||
534 | static int sun8i_codec_probe(struct platform_device *pdev) | 534 | static int sun8i_codec_probe(struct platform_device *pdev) |
535 | { | 535 | { |
536 | struct resource *res_base; | ||
537 | struct sun8i_codec *scodec; | 536 | struct sun8i_codec *scodec; |
538 | void __iomem *base; | 537 | void __iomem *base; |
539 | int ret; | 538 | int ret; |
@@ -556,8 +555,7 @@ static int sun8i_codec_probe(struct platform_device *pdev) | |||
556 | return PTR_ERR(scodec->clk_bus); | 555 | return PTR_ERR(scodec->clk_bus); |
557 | } | 556 | } |
558 | 557 | ||
559 | res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 558 | base = devm_platform_ioremap_resource(pdev, 0); |
560 | base = devm_ioremap_resource(&pdev->dev, res_base); | ||
561 | if (IS_ERR(base)) { | 559 | if (IS_ERR(base)) { |
562 | dev_err(&pdev->dev, "Failed to map the registers\n"); | 560 | dev_err(&pdev->dev, "Failed to map the registers\n"); |
563 | return PTR_ERR(base); | 561 | return PTR_ERR(base); |
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index 10f9c3b19c88..1070b2710d5e 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c | |||
@@ -120,7 +120,6 @@ static const struct regmap_config tegra20_das_regmap_config = { | |||
120 | 120 | ||
121 | static int tegra20_das_probe(struct platform_device *pdev) | 121 | static int tegra20_das_probe(struct platform_device *pdev) |
122 | { | 122 | { |
123 | struct resource *res; | ||
124 | void __iomem *regs; | 123 | void __iomem *regs; |
125 | int ret = 0; | 124 | int ret = 0; |
126 | 125 | ||
@@ -134,8 +133,7 @@ static int tegra20_das_probe(struct platform_device *pdev) | |||
134 | } | 133 | } |
135 | das->dev = &pdev->dev; | 134 | das->dev = &pdev->dev; |
136 | 135 | ||
137 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 136 | regs = devm_platform_ioremap_resource(pdev, 0); |
138 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
139 | if (IS_ERR(regs)) { | 137 | if (IS_ERR(regs)) { |
140 | ret = PTR_ERR(regs); | 138 | ret = PTR_ERR(regs); |
141 | goto err; | 139 | goto err; |
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 952381260dc3..635eacbd28d4 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c | |||
@@ -511,7 +511,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev) | |||
511 | const struct tegra30_ahub_soc_data *soc_data; | 511 | const struct tegra30_ahub_soc_data *soc_data; |
512 | struct reset_control *rst; | 512 | struct reset_control *rst; |
513 | int i; | 513 | int i; |
514 | struct resource *res0, *res1; | 514 | struct resource *res0; |
515 | void __iomem *regs_apbif, *regs_ahub; | 515 | void __iomem *regs_apbif, *regs_ahub; |
516 | int ret = 0; | 516 | int ret = 0; |
517 | 517 | ||
@@ -587,8 +587,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev) | |||
587 | } | 587 | } |
588 | regcache_cache_only(ahub->regmap_apbif, true); | 588 | regcache_cache_only(ahub->regmap_apbif, true); |
589 | 589 | ||
590 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 590 | regs_ahub = devm_platform_ioremap_resource(pdev, 1); |
591 | regs_ahub = devm_ioremap_resource(&pdev->dev, res1); | ||
592 | if (IS_ERR(regs_ahub)) | 591 | if (IS_ERR(regs_ahub)) |
593 | return PTR_ERR(regs_ahub); | 592 | return PTR_ERR(regs_ahub); |
594 | 593 | ||
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index ac6983c6bd72..e6d548fa980b 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
@@ -368,7 +368,6 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) | |||
368 | struct tegra30_i2s *i2s; | 368 | struct tegra30_i2s *i2s; |
369 | const struct of_device_id *match; | 369 | const struct of_device_id *match; |
370 | u32 cif_ids[2]; | 370 | u32 cif_ids[2]; |
371 | struct resource *mem; | ||
372 | void __iomem *regs; | 371 | void __iomem *regs; |
373 | int ret; | 372 | int ret; |
374 | 373 | ||
@@ -406,8 +405,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) | |||
406 | goto err; | 405 | goto err; |
407 | } | 406 | } |
408 | 407 | ||
409 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 408 | regs = devm_platform_ioremap_resource(pdev, 0); |
410 | regs = devm_ioremap_resource(&pdev->dev, mem); | ||
411 | if (IS_ERR(regs)) { | 409 | if (IS_ERR(regs)) { |
412 | ret = PTR_ERR(regs); | 410 | ret = PTR_ERR(regs); |
413 | goto err_clk_put; | 411 | goto err_clk_put; |
diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig index 2197f3e1eaed..87a9b9dd4e98 100644 --- a/sound/soc/ti/Kconfig +++ b/sound/soc/ti/Kconfig | |||
@@ -12,7 +12,7 @@ config SND_SOC_TI_SDMA_PCM | |||
12 | 12 | ||
13 | comment "Texas Instruments DAI support for:" | 13 | comment "Texas Instruments DAI support for:" |
14 | config SND_SOC_DAVINCI_ASP | 14 | config SND_SOC_DAVINCI_ASP |
15 | tristate "daVinci Audio Serial Port (ASP) or McBSP suport" | 15 | tristate "daVinci Audio Serial Port (ASP) or McBSP support" |
16 | depends on ARCH_DAVINCI || COMPILE_TEST | 16 | depends on ARCH_DAVINCI || COMPILE_TEST |
17 | select SND_SOC_TI_EDMA_PCM | 17 | select SND_SOC_TI_EDMA_PCM |
18 | help | 18 | help |
@@ -33,7 +33,7 @@ config SND_SOC_DAVINCI_MCASP | |||
33 | - Keystone devices | 33 | - Keystone devices |
34 | 34 | ||
35 | config SND_SOC_DAVINCI_VCIF | 35 | config SND_SOC_DAVINCI_VCIF |
36 | tristate "daVinci Voice Interface (VCIF) suport" | 36 | tristate "daVinci Voice Interface (VCIF) support" |
37 | depends on ARCH_DAVINCI || COMPILE_TEST | 37 | depends on ARCH_DAVINCI || COMPILE_TEST |
38 | select SND_SOC_TI_EDMA_PCM | 38 | select SND_SOC_TI_EDMA_PCM |
39 | help | 39 | help |
diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c index bfd8d1a03ba7..686b23d7a90d 100644 --- a/sound/soc/ti/davinci-evm.c +++ b/sound/soc/ti/davinci-evm.c | |||
@@ -68,7 +68,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream, | |||
68 | 68 | ||
69 | /* set the CPU system clock */ | 69 | /* set the CPU system clock */ |
70 | ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT); | 70 | ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT); |
71 | if (ret < 0) | 71 | if (ret < 0 && ret != -ENOTSUPP) |
72 | return ret; | 72 | return ret; |
73 | 73 | ||
74 | return 0; | 74 | return 0; |
diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 27afdbb9adf3..d89b5c928c4d 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c | |||
@@ -598,6 +598,8 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, | |||
598 | } | 598 | } |
599 | 599 | ||
600 | #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 | 600 | #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 |
601 | #define DAVINCI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
602 | SNDRV_PCM_FMTBIT_S32_LE) | ||
601 | 603 | ||
602 | static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { | 604 | static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { |
603 | .shutdown = davinci_i2s_shutdown, | 605 | .shutdown = davinci_i2s_shutdown, |
@@ -625,12 +627,14 @@ static struct snd_soc_dai_driver davinci_i2s_dai = { | |||
625 | .channels_min = 2, | 627 | .channels_min = 2, |
626 | .channels_max = 2, | 628 | .channels_max = 2, |
627 | .rates = DAVINCI_I2S_RATES, | 629 | .rates = DAVINCI_I2S_RATES, |
628 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 630 | .formats = DAVINCI_I2S_FORMATS, |
631 | }, | ||
629 | .capture = { | 632 | .capture = { |
630 | .channels_min = 2, | 633 | .channels_min = 2, |
631 | .channels_max = 2, | 634 | .channels_max = 2, |
632 | .rates = DAVINCI_I2S_RATES, | 635 | .rates = DAVINCI_I2S_RATES, |
633 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 636 | .formats = DAVINCI_I2S_FORMATS, |
637 | }, | ||
634 | .ops = &davinci_i2s_dai_ops, | 638 | .ops = &davinci_i2s_dai_ops, |
635 | 639 | ||
636 | }; | 640 | }; |
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index bc7bf15ed7a4..7aa3c32e4a49 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c | |||
@@ -109,6 +109,8 @@ struct davinci_mcasp { | |||
109 | 109 | ||
110 | /* Used for comstraint setting on the second stream */ | 110 | /* Used for comstraint setting on the second stream */ |
111 | u32 channels; | 111 | u32 channels; |
112 | int max_format_width; | ||
113 | u8 active_serializers[2]; | ||
112 | 114 | ||
113 | #ifdef CONFIG_GPIOLIB | 115 | #ifdef CONFIG_GPIOLIB |
114 | struct gpio_chip gpio_chip; | 116 | struct gpio_chip gpio_chip; |
@@ -466,6 +468,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
466 | /* FS need to be inverted */ | 468 | /* FS need to be inverted */ |
467 | inv_fs = true; | 469 | inv_fs = true; |
468 | break; | 470 | break; |
471 | case SND_SOC_DAIFMT_RIGHT_J: | ||
469 | case SND_SOC_DAIFMT_LEFT_J: | 472 | case SND_SOC_DAIFMT_LEFT_J: |
470 | /* configure a full-word SYNC pulse (LRCLK) */ | 473 | /* configure a full-word SYNC pulse (LRCLK) */ |
471 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); | 474 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); |
@@ -759,34 +762,30 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, | |||
759 | int sample_width) | 762 | int sample_width) |
760 | { | 763 | { |
761 | u32 fmt; | 764 | u32 fmt; |
762 | u32 tx_rotate = (sample_width / 4) & 0x7; | 765 | u32 tx_rotate, rx_rotate, slot_width; |
763 | u32 mask = (1ULL << sample_width) - 1; | 766 | u32 mask = (1ULL << sample_width) - 1; |
764 | u32 slot_width = sample_width; | ||
765 | |||
766 | /* | ||
767 | * For captured data we should not rotate, inversion and masking is | ||
768 | * enoguh to get the data to the right position: | ||
769 | * Format data from bus after reverse (XRBUF) | ||
770 | * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB| | ||
771 | * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| | ||
772 | * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| | ||
773 | * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB| | ||
774 | */ | ||
775 | u32 rx_rotate = 0; | ||
776 | 767 | ||
768 | if (mcasp->slot_width) | ||
769 | slot_width = mcasp->slot_width; | ||
770 | else if (mcasp->max_format_width) | ||
771 | slot_width = mcasp->max_format_width; | ||
772 | else | ||
773 | slot_width = sample_width; | ||
777 | /* | 774 | /* |
778 | * Setting the tdm slot width either with set_clkdiv() or | 775 | * TX rotation: |
779 | * set_tdm_slot() allows us to for example send 32 bits per | 776 | * right aligned formats: rotate w/ slot_width |
780 | * channel to the codec, while only 16 of them carry audio | 777 | * left aligned formats: rotate w/ sample_width |
781 | * payload. | 778 | * |
779 | * RX rotation: | ||
780 | * right aligned formats: no rotation needed | ||
781 | * left aligned formats: rotate w/ (slot_width - sample_width) | ||
782 | */ | 782 | */ |
783 | if (mcasp->slot_width) { | 783 | if ((mcasp->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) == |
784 | /* | 784 | SND_SOC_DAIFMT_RIGHT_J) { |
785 | * When we have more bclk then it is needed for the | 785 | tx_rotate = (slot_width / 4) & 0x7; |
786 | * data, we need to use the rotation to move the | 786 | rx_rotate = 0; |
787 | * received samples to have correct alignment. | 787 | } else { |
788 | */ | 788 | tx_rotate = (sample_width / 4) & 0x7; |
789 | slot_width = mcasp->slot_width; | ||
790 | rx_rotate = (slot_width - sample_width) / 4; | 789 | rx_rotate = (slot_width - sample_width) / 4; |
791 | } | 790 | } |
792 | 791 | ||
@@ -819,6 +818,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, | |||
819 | u8 rx_ser = 0; | 818 | u8 rx_ser = 0; |
820 | u8 slots = mcasp->tdm_slots; | 819 | u8 slots = mcasp->tdm_slots; |
821 | u8 max_active_serializers = (channels + slots - 1) / slots; | 820 | u8 max_active_serializers = (channels + slots - 1) / slots; |
821 | u8 max_rx_serializers, max_tx_serializers; | ||
822 | int active_serializers, numevt; | 822 | int active_serializers, numevt; |
823 | u32 reg; | 823 | u32 reg; |
824 | /* Default configuration */ | 824 | /* Default configuration */ |
@@ -828,22 +828,28 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, | |||
828 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 828 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
829 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); | 829 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); |
830 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); | 830 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); |
831 | max_tx_serializers = max_active_serializers; | ||
832 | max_rx_serializers = | ||
833 | mcasp->active_serializers[SNDRV_PCM_STREAM_CAPTURE]; | ||
831 | } else { | 834 | } else { |
832 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); | 835 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); |
833 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS); | 836 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS); |
837 | max_tx_serializers = | ||
838 | mcasp->active_serializers[SNDRV_PCM_STREAM_PLAYBACK]; | ||
839 | max_rx_serializers = max_active_serializers; | ||
834 | } | 840 | } |
835 | 841 | ||
836 | for (i = 0; i < mcasp->num_serializer; i++) { | 842 | for (i = 0; i < mcasp->num_serializer; i++) { |
837 | mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), | 843 | mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), |
838 | mcasp->serial_dir[i]); | 844 | mcasp->serial_dir[i]); |
839 | if (mcasp->serial_dir[i] == TX_MODE && | 845 | if (mcasp->serial_dir[i] == TX_MODE && |
840 | tx_ser < max_active_serializers) { | 846 | tx_ser < max_tx_serializers) { |
841 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), | 847 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), |
842 | mcasp->dismod, DISMOD_MASK); | 848 | mcasp->dismod, DISMOD_MASK); |
843 | set_bit(PIN_BIT_AXR(i), &mcasp->pdir); | 849 | set_bit(PIN_BIT_AXR(i), &mcasp->pdir); |
844 | tx_ser++; | 850 | tx_ser++; |
845 | } else if (mcasp->serial_dir[i] == RX_MODE && | 851 | } else if (mcasp->serial_dir[i] == RX_MODE && |
846 | rx_ser < max_active_serializers) { | 852 | rx_ser < max_rx_serializers) { |
847 | clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); | 853 | clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); |
848 | rx_ser++; | 854 | rx_ser++; |
849 | } else { | 855 | } else { |
@@ -890,7 +896,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, | |||
890 | } else { | 896 | } else { |
891 | dma_data->maxburst = 0; | 897 | dma_data->maxburst = 0; |
892 | } | 898 | } |
893 | return 0; | 899 | |
900 | goto out; | ||
894 | } | 901 | } |
895 | 902 | ||
896 | if (period_words % active_serializers) { | 903 | if (period_words % active_serializers) { |
@@ -920,6 +927,9 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, | |||
920 | numevt = 0; | 927 | numevt = 0; |
921 | dma_data->maxburst = numevt; | 928 | dma_data->maxburst = numevt; |
922 | 929 | ||
930 | out: | ||
931 | mcasp->active_serializers[stream] = active_serializers; | ||
932 | |||
923 | return 0; | 933 | return 0; |
924 | } | 934 | } |
925 | 935 | ||
@@ -1159,6 +1169,37 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
1159 | int period_size = params_period_size(params); | 1169 | int period_size = params_period_size(params); |
1160 | int ret; | 1170 | int ret; |
1161 | 1171 | ||
1172 | switch (params_format(params)) { | ||
1173 | case SNDRV_PCM_FORMAT_U8: | ||
1174 | case SNDRV_PCM_FORMAT_S8: | ||
1175 | word_length = 8; | ||
1176 | break; | ||
1177 | |||
1178 | case SNDRV_PCM_FORMAT_U16_LE: | ||
1179 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1180 | word_length = 16; | ||
1181 | break; | ||
1182 | |||
1183 | case SNDRV_PCM_FORMAT_U24_3LE: | ||
1184 | case SNDRV_PCM_FORMAT_S24_3LE: | ||
1185 | word_length = 24; | ||
1186 | break; | ||
1187 | |||
1188 | case SNDRV_PCM_FORMAT_U24_LE: | ||
1189 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1190 | word_length = 24; | ||
1191 | break; | ||
1192 | |||
1193 | case SNDRV_PCM_FORMAT_U32_LE: | ||
1194 | case SNDRV_PCM_FORMAT_S32_LE: | ||
1195 | word_length = 32; | ||
1196 | break; | ||
1197 | |||
1198 | default: | ||
1199 | printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); | ||
1200 | return -EINVAL; | ||
1201 | } | ||
1202 | |||
1162 | ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt); | 1203 | ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt); |
1163 | if (ret) | 1204 | if (ret) |
1164 | return ret; | 1205 | return ret; |
@@ -1193,41 +1234,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
1193 | if (ret) | 1234 | if (ret) |
1194 | return ret; | 1235 | return ret; |
1195 | 1236 | ||
1196 | switch (params_format(params)) { | ||
1197 | case SNDRV_PCM_FORMAT_U8: | ||
1198 | case SNDRV_PCM_FORMAT_S8: | ||
1199 | word_length = 8; | ||
1200 | break; | ||
1201 | |||
1202 | case SNDRV_PCM_FORMAT_U16_LE: | ||
1203 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1204 | word_length = 16; | ||
1205 | break; | ||
1206 | |||
1207 | case SNDRV_PCM_FORMAT_U24_3LE: | ||
1208 | case SNDRV_PCM_FORMAT_S24_3LE: | ||
1209 | word_length = 24; | ||
1210 | break; | ||
1211 | |||
1212 | case SNDRV_PCM_FORMAT_U24_LE: | ||
1213 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1214 | word_length = 24; | ||
1215 | break; | ||
1216 | |||
1217 | case SNDRV_PCM_FORMAT_U32_LE: | ||
1218 | case SNDRV_PCM_FORMAT_S32_LE: | ||
1219 | word_length = 32; | ||
1220 | break; | ||
1221 | |||
1222 | default: | ||
1223 | printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); | ||
1224 | return -EINVAL; | ||
1225 | } | ||
1226 | |||
1227 | davinci_config_channel_size(mcasp, word_length); | 1237 | davinci_config_channel_size(mcasp, word_length); |
1228 | 1238 | ||
1229 | if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) | 1239 | if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { |
1230 | mcasp->channels = channels; | 1240 | mcasp->channels = channels; |
1241 | if (!mcasp->max_format_width) | ||
1242 | mcasp->max_format_width = word_length; | ||
1243 | } | ||
1231 | 1244 | ||
1232 | return 0; | 1245 | return 0; |
1233 | } | 1246 | } |
@@ -1279,6 +1292,28 @@ static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params, | |||
1279 | return snd_mask_refine(fmt, &nfmt); | 1292 | return snd_mask_refine(fmt, &nfmt); |
1280 | } | 1293 | } |
1281 | 1294 | ||
1295 | static int davinci_mcasp_hw_rule_format_width(struct snd_pcm_hw_params *params, | ||
1296 | struct snd_pcm_hw_rule *rule) | ||
1297 | { | ||
1298 | struct davinci_mcasp_ruledata *rd = rule->private; | ||
1299 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
1300 | struct snd_mask nfmt; | ||
1301 | int i, format_width; | ||
1302 | |||
1303 | snd_mask_none(&nfmt); | ||
1304 | format_width = rd->mcasp->max_format_width; | ||
1305 | |||
1306 | for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { | ||
1307 | if (snd_mask_test(fmt, i)) { | ||
1308 | if (snd_pcm_format_width(i) == format_width) { | ||
1309 | snd_mask_set(&nfmt, i); | ||
1310 | } | ||
1311 | } | ||
1312 | } | ||
1313 | |||
1314 | return snd_mask_refine(fmt, &nfmt); | ||
1315 | } | ||
1316 | |||
1282 | static const unsigned int davinci_mcasp_dai_rates[] = { | 1317 | static const unsigned int davinci_mcasp_dai_rates[] = { |
1283 | 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, | 1318 | 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, |
1284 | 88200, 96000, 176400, 192000, | 1319 | 88200, 96000, 176400, 192000, |
@@ -1433,12 +1468,13 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | |||
1433 | max_channels *= tdm_slots; | 1468 | max_channels *= tdm_slots; |
1434 | /* | 1469 | /* |
1435 | * If the already active stream has less channels than the calculated | 1470 | * If the already active stream has less channels than the calculated |
1436 | * limnit based on the seirializers * tdm_slots, we need to use that as | 1471 | * limit based on the seirializers * tdm_slots, and only one serializer |
1437 | * a constraint for the second stream. | 1472 | * is in use we need to use that as a constraint for the second stream. |
1438 | * Otherwise (first stream or less allowed channels) we use the | 1473 | * Otherwise (first stream or less allowed channels or more than one |
1439 | * calculated constraint. | 1474 | * serializer in use) we use the calculated constraint. |
1440 | */ | 1475 | */ |
1441 | if (mcasp->channels && mcasp->channels < max_channels) | 1476 | if (mcasp->channels && mcasp->channels < max_channels && |
1477 | ruledata->serializers == 1) | ||
1442 | max_channels = mcasp->channels; | 1478 | max_channels = mcasp->channels; |
1443 | /* | 1479 | /* |
1444 | * But we can always allow channels upto the amount of | 1480 | * But we can always allow channels upto the amount of |
@@ -1455,7 +1491,20 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | |||
1455 | 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 1491 | 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
1456 | &mcasp->chconstr[substream->stream]); | 1492 | &mcasp->chconstr[substream->stream]); |
1457 | 1493 | ||
1458 | if (mcasp->slot_width) { | 1494 | if (mcasp->max_format_width) { |
1495 | /* | ||
1496 | * Only allow formats which require same amount of bits on the | ||
1497 | * bus as the currently running stream | ||
1498 | */ | ||
1499 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, | ||
1500 | SNDRV_PCM_HW_PARAM_FORMAT, | ||
1501 | davinci_mcasp_hw_rule_format_width, | ||
1502 | ruledata, | ||
1503 | SNDRV_PCM_HW_PARAM_FORMAT, -1); | ||
1504 | if (ret) | ||
1505 | return ret; | ||
1506 | } | ||
1507 | else if (mcasp->slot_width) { | ||
1459 | /* Only allow formats require <= slot_width bits on the bus */ | 1508 | /* Only allow formats require <= slot_width bits on the bus */ |
1460 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, | 1509 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, |
1461 | SNDRV_PCM_HW_PARAM_FORMAT, | 1510 | SNDRV_PCM_HW_PARAM_FORMAT, |
@@ -1501,12 +1550,15 @@ static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream, | |||
1501 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); | 1550 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); |
1502 | 1551 | ||
1503 | mcasp->substreams[substream->stream] = NULL; | 1552 | mcasp->substreams[substream->stream] = NULL; |
1553 | mcasp->active_serializers[substream->stream] = 0; | ||
1504 | 1554 | ||
1505 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) | 1555 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) |
1506 | return; | 1556 | return; |
1507 | 1557 | ||
1508 | if (!cpu_dai->active) | 1558 | if (!cpu_dai->active) { |
1509 | mcasp->channels = 0; | 1559 | mcasp->channels = 0; |
1560 | mcasp->max_format_width = 0; | ||
1561 | } | ||
1510 | } | 1562 | } |
1511 | 1563 | ||
1512 | static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { | 1564 | static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { |
@@ -1562,7 +1614,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
1562 | }, | 1614 | }, |
1563 | .ops = &davinci_mcasp_dai_ops, | 1615 | .ops = &davinci_mcasp_dai_ops, |
1564 | 1616 | ||
1565 | .symmetric_samplebits = 1, | ||
1566 | .symmetric_rates = 1, | 1617 | .symmetric_rates = 1, |
1567 | }, | 1618 | }, |
1568 | { | 1619 | { |
diff --git a/sound/soc/ti/edma-pcm.c b/sound/soc/ti/edma-pcm.c index 3ebea1bd15cb..634b040b65f0 100644 --- a/sound/soc/ti/edma-pcm.c +++ b/sound/soc/ti/edma-pcm.c | |||
@@ -39,7 +39,22 @@ static const struct snd_dmaengine_pcm_config edma_dmaengine_pcm_config = { | |||
39 | 39 | ||
40 | int edma_pcm_platform_register(struct device *dev) | 40 | int edma_pcm_platform_register(struct device *dev) |
41 | { | 41 | { |
42 | return devm_snd_dmaengine_pcm_register(dev, &edma_dmaengine_pcm_config, 0); | 42 | struct snd_dmaengine_pcm_config *config; |
43 | |||
44 | if (dev->of_node) | ||
45 | return devm_snd_dmaengine_pcm_register(dev, | ||
46 | &edma_dmaengine_pcm_config, 0); | ||
47 | |||
48 | config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL); | ||
49 | if (!config) | ||
50 | return -ENOMEM; | ||
51 | |||
52 | *config = edma_dmaengine_pcm_config; | ||
53 | |||
54 | config->chan_names[0] = "tx"; | ||
55 | config->chan_names[1] = "rx"; | ||
56 | |||
57 | return devm_snd_dmaengine_pcm_register(dev, config, 0); | ||
43 | } | 58 | } |
44 | EXPORT_SYMBOL_GPL(edma_pcm_platform_register); | 59 | EXPORT_SYMBOL_GPL(edma_pcm_platform_register); |
45 | 60 | ||
diff --git a/sound/soc/ti/n810.c b/sound/soc/ti/n810.c index 2c3f2a4c1700..3ad2b6daf31e 100644 --- a/sound/soc/ti/n810.c +++ b/sound/soc/ti/n810.c | |||
@@ -46,6 +46,7 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) | |||
46 | switch (n810_jack_func) { | 46 | switch (n810_jack_func) { |
47 | case N810_JACK_HS: | 47 | case N810_JACK_HS: |
48 | line1l = 1; | 48 | line1l = 1; |
49 | /* fall through */ | ||
49 | case N810_JACK_HP: | 50 | case N810_JACK_HP: |
50 | hp = 1; | 51 | hp = 1; |
51 | break; | 52 | break; |
diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index bc6046534fa5..588f680a9c24 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c | |||
@@ -55,6 +55,7 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) | |||
55 | break; | 55 | break; |
56 | case RX51_JACK_HS: | 56 | case RX51_JACK_HS: |
57 | hs = 1; | 57 | hs = 1; |
58 | /* fall through */ | ||
58 | case RX51_JACK_HP: | 59 | case RX51_JACK_HP: |
59 | hp = 1; | 60 | hp = 1; |
60 | break; | 61 | break; |
@@ -318,12 +319,10 @@ static struct snd_soc_dai_link rx51_dai[] = { | |||
318 | 319 | ||
319 | static struct snd_soc_aux_dev rx51_aux_dev[] = { | 320 | static struct snd_soc_aux_dev rx51_aux_dev[] = { |
320 | { | 321 | { |
321 | .name = "TLV320AIC34b", | 322 | .dlc = COMP_AUX("tlv320aic3x-codec.2-0019"), |
322 | .codec_name = "tlv320aic3x-codec.2-0019", | ||
323 | }, | 323 | }, |
324 | { | 324 | { |
325 | .name = "TPA61320A2", | 325 | .dlc = COMP_AUX("tpa6130a2.2-0060"), |
326 | .codec_name = "tpa6130a2.2-0060", | ||
327 | }, | 326 | }, |
328 | }; | 327 | }; |
329 | 328 | ||
@@ -396,8 +395,8 @@ static int rx51_soc_probe(struct platform_device *pdev) | |||
396 | dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n"); | 395 | dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n"); |
397 | return -EINVAL; | 396 | return -EINVAL; |
398 | } | 397 | } |
399 | rx51_aux_dev[0].codec_name = NULL; | 398 | rx51_aux_dev[0].dlc.name = NULL; |
400 | rx51_aux_dev[0].codec_of_node = dai_node; | 399 | rx51_aux_dev[0].dlc.of_node = dai_node; |
401 | rx51_codec_conf[0].dev_name = NULL; | 400 | rx51_codec_conf[0].dev_name = NULL; |
402 | rx51_codec_conf[0].of_node = dai_node; | 401 | rx51_codec_conf[0].of_node = dai_node; |
403 | 402 | ||
@@ -406,8 +405,8 @@ static int rx51_soc_probe(struct platform_device *pdev) | |||
406 | dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); | 405 | dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); |
407 | return -EINVAL; | 406 | return -EINVAL; |
408 | } | 407 | } |
409 | rx51_aux_dev[1].codec_name = NULL; | 408 | rx51_aux_dev[1].dlc.name = NULL; |
410 | rx51_aux_dev[1].codec_of_node = dai_node; | 409 | rx51_aux_dev[1].dlc.of_node = dai_node; |
411 | rx51_codec_conf[1].dev_name = NULL; | 410 | rx51_codec_conf[1].dev_name = NULL; |
412 | rx51_codec_conf[1].of_node = dai_node; | 411 | rx51_codec_conf[1].of_node = dai_node; |
413 | } | 412 | } |
diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c index fa001d3c1a88..e8446cc4e8f8 100644 --- a/sound/soc/uniphier/aio-dma.c +++ b/sound/soc/uniphier/aio-dma.c | |||
@@ -276,12 +276,10 @@ int uniphier_aiodma_soc_register_platform(struct platform_device *pdev) | |||
276 | { | 276 | { |
277 | struct uniphier_aio_chip *chip = platform_get_drvdata(pdev); | 277 | struct uniphier_aio_chip *chip = platform_get_drvdata(pdev); |
278 | struct device *dev = &pdev->dev; | 278 | struct device *dev = &pdev->dev; |
279 | struct resource *res; | ||
280 | void __iomem *preg; | 279 | void __iomem *preg; |
281 | int irq, ret; | 280 | int irq, ret; |
282 | 281 | ||
283 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 282 | preg = devm_platform_ioremap_resource(pdev, 0); |
284 | preg = devm_ioremap_resource(dev, res); | ||
285 | if (IS_ERR(preg)) | 283 | if (IS_ERR(preg)) |
286 | return PTR_ERR(preg); | 284 | return PTR_ERR(preg); |
287 | 285 | ||
@@ -291,10 +289,8 @@ int uniphier_aiodma_soc_register_platform(struct platform_device *pdev) | |||
291 | return PTR_ERR(chip->regmap); | 289 | return PTR_ERR(chip->regmap); |
292 | 290 | ||
293 | irq = platform_get_irq(pdev, 0); | 291 | irq = platform_get_irq(pdev, 0); |
294 | if (irq < 0) { | 292 | if (irq < 0) |
295 | dev_err(dev, "Could not get irq.\n"); | ||
296 | return irq; | 293 | return irq; |
297 | } | ||
298 | 294 | ||
299 | ret = devm_request_irq(dev, irq, aiodma_irq, | 295 | ret = devm_request_irq(dev, irq, aiodma_irq, |
300 | IRQF_SHARED, dev_name(dev), pdev); | 296 | IRQF_SHARED, dev_name(dev), pdev); |
diff --git a/sound/soc/uniphier/evea.c b/sound/soc/uniphier/evea.c index f9c10165fbc1..d27e9ca07856 100644 --- a/sound/soc/uniphier/evea.c +++ b/sound/soc/uniphier/evea.c | |||
@@ -451,7 +451,6 @@ static const struct regmap_config evea_regmap_config = { | |||
451 | static int evea_probe(struct platform_device *pdev) | 451 | static int evea_probe(struct platform_device *pdev) |
452 | { | 452 | { |
453 | struct evea_priv *evea; | 453 | struct evea_priv *evea; |
454 | struct resource *res; | ||
455 | void __iomem *preg; | 454 | void __iomem *preg; |
456 | int ret; | 455 | int ret; |
457 | 456 | ||
@@ -475,8 +474,7 @@ static int evea_probe(struct platform_device *pdev) | |||
475 | if (IS_ERR(evea->rst_exiv)) | 474 | if (IS_ERR(evea->rst_exiv)) |
476 | return PTR_ERR(evea->rst_exiv); | 475 | return PTR_ERR(evea->rst_exiv); |
477 | 476 | ||
478 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 477 | preg = devm_platform_ioremap_resource(pdev, 0); |
479 | preg = devm_ioremap_resource(&pdev->dev, res); | ||
480 | if (IS_ERR(preg)) | 478 | if (IS_ERR(preg)) |
481 | return PTR_ERR(preg); | 479 | return PTR_ERR(preg); |
482 | 480 | ||
diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c index dc8721f4f56b..48970efe7838 100644 --- a/sound/soc/xilinx/xlnx_formatter_pcm.c +++ b/sound/soc/xilinx/xlnx_formatter_pcm.c | |||
@@ -613,7 +613,6 @@ static int xlnx_formatter_pcm_probe(struct platform_device *pdev) | |||
613 | aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev, | 613 | aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev, |
614 | "irq_mm2s"); | 614 | "irq_mm2s"); |
615 | if (aud_drv_data->mm2s_irq < 0) { | 615 | if (aud_drv_data->mm2s_irq < 0) { |
616 | dev_err(dev, "xlnx audio mm2s irq resource failed\n"); | ||
617 | ret = aud_drv_data->mm2s_irq; | 616 | ret = aud_drv_data->mm2s_irq; |
618 | goto clk_err; | 617 | goto clk_err; |
619 | } | 618 | } |
@@ -640,7 +639,6 @@ static int xlnx_formatter_pcm_probe(struct platform_device *pdev) | |||
640 | aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev, | 639 | aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev, |
641 | "irq_s2mm"); | 640 | "irq_s2mm"); |
642 | if (aud_drv_data->s2mm_irq < 0) { | 641 | if (aud_drv_data->s2mm_irq < 0) { |
643 | dev_err(dev, "xlnx audio s2mm irq resource failed\n"); | ||
644 | ret = aud_drv_data->s2mm_irq; | 642 | ret = aud_drv_data->s2mm_irq; |
645 | goto clk_err; | 643 | goto clk_err; |
646 | } | 644 | } |
diff --git a/sound/soc/xilinx/xlnx_i2s.c b/sound/soc/xilinx/xlnx_i2s.c index 8b353166ad44..cc641e582c82 100644 --- a/sound/soc/xilinx/xlnx_i2s.c +++ b/sound/soc/xilinx/xlnx_i2s.c | |||
@@ -95,7 +95,6 @@ MODULE_DEVICE_TABLE(of, xlnx_i2s_of_match); | |||
95 | 95 | ||
96 | static int xlnx_i2s_probe(struct platform_device *pdev) | 96 | static int xlnx_i2s_probe(struct platform_device *pdev) |
97 | { | 97 | { |
98 | struct resource *res; | ||
99 | void __iomem *base; | 98 | void __iomem *base; |
100 | struct snd_soc_dai_driver *dai_drv; | 99 | struct snd_soc_dai_driver *dai_drv; |
101 | int ret; | 100 | int ret; |
@@ -107,8 +106,7 @@ static int xlnx_i2s_probe(struct platform_device *pdev) | |||
107 | if (!dai_drv) | 106 | if (!dai_drv) |
108 | return -ENOMEM; | 107 | return -ENOMEM; |
109 | 108 | ||
110 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 109 | base = devm_platform_ioremap_resource(pdev, 0); |
111 | base = devm_ioremap_resource(&pdev->dev, res); | ||
112 | if (IS_ERR(base)) | 110 | if (IS_ERR(base)) |
113 | return PTR_ERR(base); | 111 | return PTR_ERR(base); |
114 | 112 | ||
diff --git a/sound/soc/xilinx/xlnx_spdif.c b/sound/soc/xilinx/xlnx_spdif.c index 3b9000fd8c49..e2ca087adee6 100644 --- a/sound/soc/xilinx/xlnx_spdif.c +++ b/sound/soc/xilinx/xlnx_spdif.c | |||
@@ -260,8 +260,7 @@ static int xlnx_spdif_probe(struct platform_device *pdev) | |||
260 | return ret; | 260 | return ret; |
261 | } | 261 | } |
262 | 262 | ||
263 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 263 | ctx->base = devm_platform_ioremap_resource(pdev, 0); |
264 | ctx->base = devm_ioremap_resource(dev, res); | ||
265 | if (IS_ERR(ctx->base)) { | 264 | if (IS_ERR(ctx->base)) { |
266 | ret = PTR_ERR(ctx->base); | 265 | ret = PTR_ERR(ctx->base); |
267 | goto clk_err; | 266 | goto clk_err; |
diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index 9ce2c75186b9..efd374f114a0 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c | |||
@@ -531,7 +531,6 @@ static int xtfpga_i2s_runtime_resume(struct device *dev) | |||
531 | static int xtfpga_i2s_probe(struct platform_device *pdev) | 531 | static int xtfpga_i2s_probe(struct platform_device *pdev) |
532 | { | 532 | { |
533 | struct xtfpga_i2s *i2s; | 533 | struct xtfpga_i2s *i2s; |
534 | struct resource *mem; | ||
535 | int err, irq; | 534 | int err, irq; |
536 | 535 | ||
537 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); | 536 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); |
@@ -543,8 +542,7 @@ static int xtfpga_i2s_probe(struct platform_device *pdev) | |||
543 | i2s->dev = &pdev->dev; | 542 | i2s->dev = &pdev->dev; |
544 | dev_dbg(&pdev->dev, "dev: %p, i2s: %p\n", &pdev->dev, i2s); | 543 | dev_dbg(&pdev->dev, "dev: %p, i2s: %p\n", &pdev->dev, i2s); |
545 | 544 | ||
546 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 545 | i2s->regs = devm_platform_ioremap_resource(pdev, 0); |
547 | i2s->regs = devm_ioremap_resource(&pdev->dev, mem); | ||
548 | if (IS_ERR(i2s->regs)) { | 546 | if (IS_ERR(i2s->regs)) { |
549 | err = PTR_ERR(i2s->regs); | 547 | err = PTR_ERR(i2s->regs); |
550 | goto err; | 548 | goto err; |
@@ -572,7 +570,6 @@ static int xtfpga_i2s_probe(struct platform_device *pdev) | |||
572 | 570 | ||
573 | irq = platform_get_irq(pdev, 0); | 571 | irq = platform_get_irq(pdev, 0); |
574 | if (irq < 0) { | 572 | if (irq < 0) { |
575 | dev_err(&pdev->dev, "No IRQ resource\n"); | ||
576 | err = irq; | 573 | err = irq; |
577 | goto err; | 574 | goto err; |
578 | } | 575 | } |
diff --git a/sound/soc/zte/zx-tdm.c b/sound/soc/zte/zx-tdm.c index 5e877fe9ba7b..0e5a05b25a77 100644 --- a/sound/soc/zte/zx-tdm.c +++ b/sound/soc/zte/zx-tdm.c | |||
@@ -211,7 +211,6 @@ static int zx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
211 | ts_width = 1; | 211 | ts_width = 1; |
212 | break; | 212 | break; |
213 | default: | 213 | default: |
214 | ts_width = 0; | ||
215 | dev_err(socdai->dev, "Unknown data format\n"); | 214 | dev_err(socdai->dev, "Unknown data format\n"); |
216 | return -EINVAL; | 215 | return -EINVAL; |
217 | } | 216 | } |