aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-09-11 06:17:14 -0400
committerMark Brown <broonie@linaro.org>2013-09-11 06:17:14 -0400
commit29dc5dd229dc3130b51df0932e59946fc09d3bd4 (patch)
tree51fbe8eb543fc4fd3f8ee6582bdc72ea0bccee6f
parent6e4664525b1db28f8c4e1130957f70a94c19213e (diff)
parente011143454606de70eba1db5d99454eec0017fdb (diff)
Merge remote-tracking branch 'asoc/fix/atmel' into asoc-linus
-rw-r--r--Documentation/devicetree/bindings/misc/atmel-ssc.txt23
-rw-r--r--Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt65
-rw-r--r--Documentation/devicetree/bindings/sound/ak4554.c11
-rw-r--r--Documentation/devicetree/bindings/sound/alc5632.txt19
-rw-r--r--Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt35
-rw-r--r--Documentation/devicetree/bindings/sound/atmel-wm8904.txt55
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,spdif.txt54
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,ssi.txt (renamed from Documentation/devicetree/bindings/powerpc/fsl/ssi.txt)12
-rw-r--r--Documentation/devicetree/bindings/sound/imx-audmux.txt9
-rw-r--r--Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt28
-rw-r--r--Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt15
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt24
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt26
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt27
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt24
-rw-r--r--Documentation/devicetree/bindings/sound/pcm1792a.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/rt5640.txt20
-rw-r--r--Documentation/devicetree/bindings/sound/samsung-i2s.txt22
-rw-r--r--Documentation/devicetree/bindings/sound/soc-ac97link.txt28
-rw-r--r--Documentation/devicetree/bindings/sound/ti,pcm1681.txt15
-rw-r--r--Documentation/devicetree/bindings/sound/tlv320aic3x.txt9
-rw-r--r--Documentation/devicetree/bindings/sound/wm8731.txt9
-rw-r--r--Documentation/devicetree/bindings/sound/wm8753.txt24
-rw-r--r--Documentation/devicetree/bindings/sound/wm8903.txt19
-rw-r--r--Documentation/devicetree/bindings/sound/wm8994.txt4
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi9
-rw-r--r--arch/arm/mach-dove/common.c4
-rw-r--r--arch/arm/mach-kirkwood/common.c24
-rw-r--r--arch/arm/plat-pxa/ssp.c171
-rw-r--r--include/dt-bindings/sound/fsl-imx-audmux.h56
-rw-r--r--include/linux/atmel-ssc.h2
-rw-r--r--include/linux/mfd/arizona/gpio.h96
-rw-r--r--include/linux/platform_data/asoc-s3c.h1
-rw-r--r--include/linux/platform_data/omap-abe-twl6040.h49
-rw-r--r--include/linux/pxa2xx_ssp.h11
-rw-r--r--include/sound/pxa2xx-lib.h7
-rw-r--r--include/sound/rcar_snd.h84
-rw-r--r--include/sound/soc-dapm.h199
-rw-r--r--include/sound/soc-dpcm.h2
-rw-r--r--include/sound/soc.h39
-rw-r--r--sound/arm/pxa2xx-ac97.c26
-rw-r--r--sound/arm/pxa2xx-pcm-lib.c52
-rw-r--r--sound/arm/pxa2xx-pcm.c5
-rw-r--r--sound/arm/pxa2xx-pcm.h6
-rw-r--r--sound/core/Kconfig3
-rw-r--r--sound/core/Makefile3
-rw-r--r--sound/core/pcm_dmaengine.c (renamed from sound/soc/soc-dmaengine-pcm.c)0
-rw-r--r--sound/soc/Kconfig5
-rw-r--r--sound/soc/Makefile4
-rw-r--r--sound/soc/atmel/Kconfig21
-rw-r--r--sound/soc/atmel/Makefile4
-rw-r--r--sound/soc/atmel/atmel-pcm-dma.c118
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c36
-rw-r--r--sound/soc/atmel/atmel_wm8904.c254
-rw-r--r--sound/soc/atmel/sam9x5_wm8731.c208
-rw-r--r--sound/soc/au1x/db1200.c4
-rw-r--r--sound/soc/au1x/psc-ac97.c3
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.h1
-rw-r--r--sound/soc/cirrus/ep93xx-ac97.c3
-rw-r--r--sound/soc/cirrus/ep93xx-i2s.c3
-rw-r--r--sound/soc/codecs/Kconfig19
-rw-r--r--sound/soc/codecs/Makefile8
-rw-r--r--sound/soc/codecs/ac97.c15
-rw-r--r--sound/soc/codecs/ad1980.c43
-rw-r--r--sound/soc/codecs/ad73311.c22
-rw-r--r--sound/soc/codecs/adau1701.c25
-rw-r--r--sound/soc/codecs/adav80x.c13
-rw-r--r--sound/soc/codecs/ads117x.c29
-rw-r--r--sound/soc/codecs/ak4104.c34
-rw-r--r--sound/soc/codecs/ak4554.c106
-rw-r--r--sound/soc/codecs/ak5386.c17
-rw-r--r--sound/soc/codecs/arizona.c69
-rw-r--r--sound/soc/codecs/arizona.h5
-rw-r--r--sound/soc/codecs/bt-sco.c22
-rw-r--r--sound/soc/codecs/cs4270.c20
-rw-r--r--sound/soc/codecs/cs4271.c30
-rw-r--r--sound/soc/codecs/hdmi.c30
-rw-r--r--sound/soc/codecs/lm4857.c107
-rw-r--r--sound/soc/codecs/max9768.c16
-rw-r--r--sound/soc/codecs/max98090.c10
-rw-r--r--sound/soc/codecs/max9877.c294
-rw-r--r--sound/soc/codecs/mc13783.c1
-rw-r--r--sound/soc/codecs/pcm1681.c339
-rw-r--r--sound/soc/codecs/pcm1792a.c257
-rw-r--r--sound/soc/codecs/pcm1792a.h26
-rw-r--r--sound/soc/codecs/pcm3008.c150
-rw-r--r--sound/soc/codecs/rt5640.c26
-rw-r--r--sound/soc/codecs/sgtl5000.c10
-rw-r--r--sound/soc/codecs/si476x.c14
-rw-r--r--sound/soc/codecs/spdif_receiver.c17
-rw-r--r--sound/soc/codecs/spdif_transmitter.c18
-rw-r--r--sound/soc/codecs/sta32x.c10
-rw-r--r--sound/soc/codecs/tlv320aic26.c51
-rw-r--r--sound/soc/codecs/tlv320aic3x.c56
-rw-r--r--sound/soc/codecs/twl4030.c2
-rw-r--r--sound/soc/codecs/twl6040.c7
-rw-r--r--sound/soc/codecs/uda134x.c88
-rw-r--r--sound/soc/codecs/wl1273.c17
-rw-r--r--sound/soc/codecs/wm0010.c12
-rw-r--r--sound/soc/codecs/wm5102.c53
-rw-r--r--sound/soc/codecs/wm5110.c35
-rw-r--r--sound/soc/codecs/wm8350.c6
-rw-r--r--sound/soc/codecs/wm8727.c17
-rw-r--r--sound/soc/codecs/wm8731.c60
-rw-r--r--sound/soc/codecs/wm8753.c5
-rw-r--r--sound/soc/codecs/wm8782.c17
-rw-r--r--sound/soc/codecs/wm8903.c4
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/codecs/wm8960.c10
-rw-r--r--sound/soc/codecs/wm8962.c7
-rw-r--r--sound/soc/codecs/wm8994.c39
-rw-r--r--sound/soc/codecs/wm8995.c5
-rw-r--r--sound/soc/codecs/wm8997.c1175
-rw-r--r--sound/soc/codecs/wm8997.h23
-rw-r--r--sound/soc/codecs/wm_adsp.c124
-rw-r--r--sound/soc/codecs/wm_adsp.h3
-rw-r--r--sound/soc/codecs/wm_hubs.c8
-rw-r--r--sound/soc/fsl/Kconfig13
-rw-r--r--sound/soc/fsl/Makefile2
-rw-r--r--sound/soc/fsl/fsl_spdif.c1236
-rw-r--r--sound/soc/fsl/fsl_spdif.h191
-rw-r--r--sound/soc/fsl/fsl_ssi.c500
-rw-r--r--sound/soc/fsl/imx-audmux.c78
-rw-r--r--sound/soc/fsl/imx-audmux.h52
-rw-r--r--sound/soc/fsl/imx-mc13783.c1
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c4
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c20
-rw-r--r--sound/soc/fsl/imx-pcm.h26
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c4
-rw-r--r--sound/soc/fsl/imx-ssi.c11
-rw-r--r--sound/soc/fsl/imx-ssi.h1
-rw-r--r--sound/soc/fsl/imx-wm8962.c3
-rw-r--r--sound/soc/kirkwood/Kconfig11
-rw-r--r--sound/soc/kirkwood/Makefile4
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c108
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c67
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c6
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c6
-rw-r--r--sound/soc/kirkwood/kirkwood.h11
-rw-r--r--sound/soc/mxs/Kconfig3
-rw-r--r--sound/soc/mxs/mxs-saif.c1
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c30
-rw-r--r--sound/soc/nuc900/nuc900-ac97.c3
-rw-r--r--sound/soc/omap/Kconfig8
-rw-r--r--sound/soc/omap/omap-abe-twl6040.c133
-rw-r--r--sound/soc/omap/omap-dmic.c9
-rw-r--r--sound/soc/omap/omap-mcbsp.c5
-rw-r--r--sound/soc/omap/omap-mcpdm.c3
-rw-r--r--sound/soc/pxa/Kconfig2
-rw-r--r--sound/soc/pxa/brownstone.c1
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c7
-rw-r--r--sound/soc/pxa/mmp-pcm.c7
-rw-r--r--sound/soc/pxa/mmp-sspa.c15
-rw-r--r--sound/soc/pxa/pxa-ssp.c76
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c67
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c28
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c21
-rw-r--r--sound/soc/pxa/ttc-dkb.c1
-rw-r--r--sound/soc/s6000/s6105-ipcam.c2
-rw-r--r--sound/soc/samsung/ac97.c11
-rw-r--r--sound/soc/samsung/dma.c12
-rw-r--r--sound/soc/samsung/dma.h4
-rw-r--r--sound/soc/samsung/i2s-regs.h51
-rw-r--r--sound/soc/samsung/i2s.c193
-rw-r--r--sound/soc/samsung/pcm.c4
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c4
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c4
-rw-r--r--sound/soc/samsung/smdk_wm8994.c58
-rw-r--r--sound/soc/samsung/spdif.c12
-rw-r--r--sound/soc/sh/Kconfig7
-rw-r--r--sound/soc/sh/Makefile3
-rw-r--r--sound/soc/sh/rcar/Makefile2
-rw-r--r--sound/soc/sh/rcar/adg.c234
-rw-r--r--sound/soc/sh/rcar/core.c861
-rw-r--r--sound/soc/sh/rcar/gen.c280
-rw-r--r--sound/soc/sh/rcar/rsnd.h302
-rw-r--r--sound/soc/sh/rcar/scu.c236
-rw-r--r--sound/soc/sh/rcar/ssi.c728
-rw-r--r--sound/soc/soc-compress.c13
-rw-r--r--sound/soc/soc-core.c236
-rw-r--r--sound/soc/soc-dapm.c810
-rw-r--r--sound/soc/soc-jack.c2
-rw-r--r--sound/soc/soc-pcm.c15
-rw-r--r--sound/soc/spear/Kconfig2
-rw-r--r--sound/soc/tegra/Kconfig14
-rw-r--r--sound/soc/tegra/tegra20_ac97.c8
-rw-r--r--sound/soc/tegra/tegra_alc5632.c2
-rw-r--r--sound/soc/tegra/tegra_rt5640.c1
-rw-r--r--sound/soc/tegra/tegra_wm8753.c2
-rw-r--r--sound/soc/tegra/trimslice.c2
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c3
-rw-r--r--sound/soc/ux500/mop500.c1
193 files changed, 10275 insertions, 2357 deletions
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
index 38e51ad2e07e..a45ae08c8ed1 100644
--- a/Documentation/devicetree/bindings/misc/atmel-ssc.txt
+++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
@@ -7,9 +7,30 @@ Required properties:
7- reg: Should contain SSC registers location and length 7- reg: Should contain SSC registers location and length
8- interrupts: Should contain SSC interrupt 8- interrupts: Should contain SSC interrupt
9 9
10Example: 10
11Required properties for devices compatible with "atmel,at91sam9g45-ssc":
12- dmas: DMA specifier, consisting of a phandle to DMA controller node,
13 the memory interface and SSC DMA channel ID (for tx and rx).
14 See Documentation/devicetree/bindings/dma/atmel-dma.txt for details.
15- dma-names: Must be "tx", "rx".
16
17Examples:
18- PDC transfer:
11ssc0: ssc@fffbc000 { 19ssc0: ssc@fffbc000 {
12 compatible = "atmel,at91rm9200-ssc"; 20 compatible = "atmel,at91rm9200-ssc";
13 reg = <0xfffbc000 0x4000>; 21 reg = <0xfffbc000 0x4000>;
14 interrupts = <14 4 5>; 22 interrupts = <14 4 5>;
15}; 23};
24
25- DMA transfer:
26ssc0: ssc@f0010000 {
27 compatible = "atmel,at91sam9g45-ssc";
28 reg = <0xf0010000 0x4000>;
29 interrupts = <28 4 5>;
30 dmas = <&dma0 1 13>,
31 <&dma0 1 14>;
32 dma-names = "tx", "rx";
33 pinctrl-names = "default";
34 pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
35 status = "disabled";
36};
diff --git a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
new file mode 100644
index 000000000000..669b8140dd79
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
@@ -0,0 +1,65 @@
1Device tree bindings for Marvell PXA SSP ports
2
3Required properties:
4
5 - compatible: Must be one of
6 mrvl,pxa25x-ssp
7 mvrl,pxa25x-nssp
8 mrvl,pxa27x-ssp
9 mrvl,pxa3xx-ssp
10 mvrl,pxa168-ssp
11 mrvl,pxa910-ssp
12 mrvl,ce4100-ssp
13 mrvl,lpss-ssp
14
15 - reg: The memory base
16 - dmas: Two dma phandles, one for rx, one for tx
17 - dma-names: Must be "rx", "tx"
18
19
20Example for PXA3xx:
21
22 ssp0: ssp@41000000 {
23 compatible = "mrvl,pxa3xx-ssp";
24 reg = <0x41000000 0x40>;
25 ssp-id = <1>;
26 interrupts = <24>;
27 clock-names = "pxa27x-ssp.0";
28 dmas = <&dma 13
29 &dma 14>;
30 dma-names = "rx", "tx";
31 };
32
33 ssp1: ssp@41700000 {
34 compatible = "mrvl,pxa3xx-ssp";
35 reg = <0x41700000 0x40>;
36 ssp-id = <2>;
37 interrupts = <16>;
38 clock-names = "pxa27x-ssp.1";
39 dmas = <&dma 15
40 &dma 16>;
41 dma-names = "rx", "tx";
42 };
43
44 ssp2: ssp@41900000 {
45 compatibl3 = "mrvl,pxa3xx-ssp";
46 reg = <0x41900000 0x40>;
47 ssp-id = <3>;
48 interrupts = <0>;
49 clock-names = "pxa27x-ssp.2";
50 dmas = <&dma 66
51 &dma 67>;
52 dma-names = "rx", "tx";
53 };
54
55 ssp3: ssp@41a00000 {
56 compatible = "mrvl,pxa3xx-ssp";
57 reg = <0x41a00000 0x40>;
58 ssp-id = <4>;
59 interrupts = <13>;
60 clock-names = "pxa27x-ssp.3";
61 dmas = <&dma 2
62 &dma 3>;
63 dma-names = "rx", "tx";
64 };
65
diff --git a/Documentation/devicetree/bindings/sound/ak4554.c b/Documentation/devicetree/bindings/sound/ak4554.c
new file mode 100644
index 000000000000..934fa02754b3
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ak4554.c
@@ -0,0 +1,11 @@
1AK4554 ADC/DAC
2
3Required properties:
4
5 - compatible : "asahi-kasei,ak4554"
6
7Example:
8
9ak4554-adc-dac {
10 compatible = "asahi-kasei,ak4554";
11};
diff --git a/Documentation/devicetree/bindings/sound/alc5632.txt b/Documentation/devicetree/bindings/sound/alc5632.txt
index 8608f747dcfe..ffd886d110bd 100644
--- a/Documentation/devicetree/bindings/sound/alc5632.txt
+++ b/Documentation/devicetree/bindings/sound/alc5632.txt
@@ -13,6 +13,25 @@ Required properties:
13 - #gpio-cells : Should be two. The first cell is the pin number and the 13 - #gpio-cells : Should be two. The first cell is the pin number and the
14 second cell is used to specify optional parameters (currently unused). 14 second cell is used to specify optional parameters (currently unused).
15 15
16Pins on the device (for linking into audio routes):
17
18 * SPK_OUTP
19 * SPK_OUTN
20 * HP_OUT_L
21 * HP_OUT_R
22 * AUX_OUT_P
23 * AUX_OUT_N
24 * LINE_IN_L
25 * LINE_IN_R
26 * PHONE_P
27 * PHONE_N
28 * MIC1_P
29 * MIC1_N
30 * MIC2_P
31 * MIC2_N
32 * MICBIAS1
33 * DMICDAT
34
16Example: 35Example:
17 36
18alc5632: alc5632@1e { 37alc5632: alc5632@1e {
diff --git a/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt
new file mode 100644
index 000000000000..0720857089a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt
@@ -0,0 +1,35 @@
1* Atmel at91sam9x5ek wm8731 audio complex
2
3Required properties:
4 - compatible: "atmel,sam9x5-wm8731-audio"
5 - atmel,model: The user-visible name of this sound complex.
6 - atmel,ssc-controller: The phandle of the SSC controller
7 - atmel,audio-codec: The phandle of the WM8731 audio codec
8 - atmel,audio-routing: A list of the connections between audio components.
9 Each entry is a pair of strings, the first being the connection's sink,
10 the second being the connection's source.
11
12Available audio endpoints for the audio-routing table:
13
14Board connectors:
15 * Headphone Jack
16 * Line In Jack
17
18wm8731 pins:
19cf Documentation/devicetree/bindings/sound/wm8731.txt
20
21Example:
22sound {
23 compatible = "atmel,sam9x5-wm8731-audio";
24
25 atmel,model = "wm8731 @ AT91SAM9X5EK";
26
27 atmel,audio-routing =
28 "Headphone Jack", "RHPOUT",
29 "Headphone Jack", "LHPOUT",
30 "LLINEIN", "Line In Jack",
31 "RLINEIN", "Line In Jack";
32
33 atmel,ssc-controller = <&ssc0>;
34 atmel,audio-codec = <&wm8731>;
35};
diff --git a/Documentation/devicetree/bindings/sound/atmel-wm8904.txt b/Documentation/devicetree/bindings/sound/atmel-wm8904.txt
new file mode 100644
index 000000000000..8bbe50c884b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-wm8904.txt
@@ -0,0 +1,55 @@
1Atmel ASoC driver with wm8904 audio codec complex
2
3Required properties:
4 - compatible: "atmel,asoc-wm8904"
5 - atmel,model: The user-visible name of this sound complex.
6 - atmel,audio-routing: A list of the connections between audio components.
7 Each entry is a pair of strings, the first being the connection's sink,
8 the second being the connection's source. Valid names for sources and
9 sinks are the WM8904's pins, and the jacks on the board:
10
11 WM8904 pins:
12
13 * IN1L
14 * IN1R
15 * IN2L
16 * IN2R
17 * IN3L
18 * IN3R
19 * HPOUTL
20 * HPOUTR
21 * LINEOUTL
22 * LINEOUTR
23 * MICBIAS
24
25 Board connectors:
26
27 * Headphone Jack
28 * Line In Jack
29 * Mic
30
31 - atmel,ssc-controller: The phandle of the SSC controller
32 - atmel,audio-codec: The phandle of the WM8904 audio codec
33
34Optional properties:
35 - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
36
37Example:
38sound {
39 compatible = "atmel,asoc-wm8904";
40 pinctrl-names = "default";
41 pinctrl-0 = <&pinctrl_pck0_as_mck>;
42
43 atmel,model = "wm8904 @ AT91SAM9N12EK";
44
45 atmel,audio-routing =
46 "Headphone Jack", "HPOUTL",
47 "Headphone Jack", "HPOUTR",
48 "IN2L", "Line In Jack",
49 "IN2R", "Line In Jack",
50 "Mic", "MICBIAS",
51 "IN1L", "Mic";
52
53 atmel,ssc-controller = <&ssc0>;
54 atmel,audio-codec = <&wm8904>;
55};
diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
new file mode 100644
index 000000000000..f2ae335670f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
@@ -0,0 +1,54 @@
1Freescale Sony/Philips Digital Interface Format (S/PDIF) Controller
2
3The Freescale S/PDIF audio block is a stereo transceiver that allows the
4processor to receive and transmit digital audio via an coaxial cable or
5a fibre cable.
6
7Required properties:
8
9 - compatible : Compatible list, must contain "fsl,imx35-spdif".
10
11 - reg : Offset and length of the register set for the device.
12
13 - interrupts : Contains the spdif interrupt.
14
15 - dmas : Generic dma devicetree binding as described in
16 Documentation/devicetree/bindings/dma/dma.txt.
17
18 - dma-names : Two dmas have to be defined, "tx" and "rx".
19
20 - clocks : Contains an entry for each entry in clock-names.
21
22 - clock-names : Includes the following entries:
23 "core" The core clock of spdif controller
24 "rxtx<0-7>" Clock source list for tx and rx clock.
25 This clock list should be identical to
26 the source list connecting to the spdif
27 clock mux in "SPDIF Transceiver Clock
28 Diagram" of SoC reference manual. It
29 can also be referred to TxClk_Source
30 bit of register SPDIF_STC.
31
32Example:
33
34spdif: spdif@02004000 {
35 compatible = "fsl,imx35-spdif";
36 reg = <0x02004000 0x4000>;
37 interrupts = <0 52 0x04>;
38 dmas = <&sdma 14 18 0>,
39 <&sdma 15 18 0>;
40 dma-names = "rx", "tx";
41
42 clocks = <&clks 197>, <&clks 3>,
43 <&clks 197>, <&clks 107>,
44 <&clks 0>, <&clks 118>,
45 <&clks 62>, <&clks 139>,
46 <&clks 0>;
47 clock-names = "core", "rxtx0",
48 "rxtx1", "rxtx2",
49 "rxtx3", "rxtx4",
50 "rxtx5", "rxtx6",
51 "rxtx7";
52
53 status = "okay";
54};
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt
index 5ff76c9c57d2..4303b6ab6208 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/ssi.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,ssi.txt
@@ -43,10 +43,22 @@ Required properties:
43 together. This would still allow different sample sizes, 43 together. This would still allow different sample sizes,
44 but not different sample rates. 44 but not different sample rates.
45 45
46Required are also ac97 link bindings if ac97 is used. See
47Documentation/devicetree/bindings/sound/soc-ac97link.txt for the necessary
48bindings.
49
46Optional properties: 50Optional properties:
47- codec-handle: Phandle to a 'codec' node that defines an audio 51- codec-handle: Phandle to a 'codec' node that defines an audio
48 codec connected to this SSI. This node is typically 52 codec connected to this SSI. This node is typically
49 a child of an I2C or other control node. 53 a child of an I2C or other control node.
54- fsl,fiq-stream-filter: Bool property. Disabled DMA and use FIQ instead to
55 filter the codec stream. This is necessary for some boards
56 where an incompatible codec is connected to this SSI, e.g.
57 on pca100 and pcm043.
58- dmas: Generic dma devicetree binding as described in
59 Documentation/devicetree/bindings/dma/dma.txt.
60- dma-names: Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq
61 is not defined.
50 62
51Child 'codec' node required properties: 63Child 'codec' node required properties:
52- compatible: Compatible list, contains the name of the codec 64- compatible: Compatible list, contains the name of the codec
diff --git a/Documentation/devicetree/bindings/sound/imx-audmux.txt b/Documentation/devicetree/bindings/sound/imx-audmux.txt
index 215aa9817213..f88a00e54c63 100644
--- a/Documentation/devicetree/bindings/sound/imx-audmux.txt
+++ b/Documentation/devicetree/bindings/sound/imx-audmux.txt
@@ -5,6 +5,15 @@ Required properties:
5 or "fsl,imx31-audmux" for the version firstly used on i.MX31. 5 or "fsl,imx31-audmux" for the version firstly used on i.MX31.
6- reg : Should contain AUDMUX registers location and length 6- reg : Should contain AUDMUX registers location and length
7 7
8An initial configuration can be setup using child nodes.
9
10Required properties of optional child nodes:
11- fsl,audmux-port : Integer of the audmux port that is configured by this
12 child node.
13- fsl,port-config : List of configuration options for the specific port. For
14 imx31-audmux and above, it is a list of tuples <ptcr pdcr>. For
15 imx21-audmux it is a list of pcr values.
16
8Example: 17Example:
9 18
10audmux@021d8000 { 19audmux@021d8000 {
diff --git a/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
new file mode 100644
index 000000000000..74c9ba6c2823
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
@@ -0,0 +1,28 @@
1Marvell PXA SSP CPU DAI bindings
2
3Required properties:
4
5 compatible Must be "mrvl,pxa-ssp-dai"
6 port A phandle reference to a PXA ssp upstream device
7
8Example:
9
10 /* upstream device */
11
12 ssp0: ssp@41000000 {
13 compatible = "mrvl,pxa3xx-ssp";
14 reg = <0x41000000 0x40>;
15 interrupts = <24>;
16 clock-names = "pxa27x-ssp.0";
17 dmas = <&dma 13
18 &dma 14>;
19 dma-names = "rx", "tx";
20 };
21
22 /* DAI as user */
23
24 ssp_dai0: ssp_dai@0 {
25 compatible = "mrvl,pxa-ssp-dai";
26 port = <&ssp0>;
27 };
28
diff --git a/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt b/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
new file mode 100644
index 000000000000..551fbb8348c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
@@ -0,0 +1,15 @@
1DT bindings for ARM PXA2xx PCM platform driver
2
3This is just a dummy driver that registers the PXA ASoC platform driver.
4It does not have any resources assigned.
5
6Required properties:
7
8 - compatible 'mrvl,pxa-pcm-audio'
9
10Example:
11
12 pxa_pcm_audio: snd_soc_pxa_audio {
13 compatible = "mrvl,pxa-pcm-audio";
14 };
15
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt
index 05ffecb57103..8b8903ef0800 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt
@@ -11,28 +11,8 @@ Required properties:
11- nvidia,audio-routing : A list of the connections between audio components. 11- nvidia,audio-routing : A list of the connections between audio components.
12 Each entry is a pair of strings, the first being the connection's sink, 12 Each entry is a pair of strings, the first being the connection's sink,
13 the second being the connection's source. Valid names for sources and 13 the second being the connection's source. Valid names for sources and
14 sinks are the ALC5632's pins: 14 sinks are the ALC5632's pins as documented in the binding for the device
15 15 and:
16 ALC5632 pins:
17
18 * SPK_OUTP
19 * SPK_OUTN
20 * HP_OUT_L
21 * HP_OUT_R
22 * AUX_OUT_P
23 * AUX_OUT_N
24 * LINE_IN_L
25 * LINE_IN_R
26 * PHONE_P
27 * PHONE_N
28 * MIC1_P
29 * MIC1_N
30 * MIC2_P
31 * MIC2_N
32 * MICBIAS1
33 * DMICDAT
34
35 Board connectors:
36 16
37 * Headset Stereophone 17 * Headset Stereophone
38 * Int Spk 18 * Int Spk
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt
index d130818700b2..dc6224994d69 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt
@@ -11,32 +11,12 @@ Required properties:
11- nvidia,audio-routing : A list of the connections between audio components. 11- nvidia,audio-routing : A list of the connections between audio components.
12 Each entry is a pair of strings, the first being the connection's sink, 12 Each entry is a pair of strings, the first being the connection's sink,
13 the second being the connection's source. Valid names for sources and 13 the second being the connection's source. Valid names for sources and
14 sinks are the RT5640's pins, and the jacks on the board: 14 sinks are the RT5640's pins (as documented in its binding), and the jacks
15 15 on the board:
16 RT5640 pins:
17
18 * DMIC1
19 * DMIC2
20 * MICBIAS1
21 * IN1P
22 * IN1R
23 * IN2P
24 * IN2R
25 * HPOL
26 * HPOR
27 * LOUTL
28 * LOUTR
29 * MONOP
30 * MONON
31 * SPOLP
32 * SPOLN
33 * SPORP
34 * SPORN
35
36 Board connectors:
37 16
38 * Headphones 17 * Headphones
39 * Speakers 18 * Speakers
19 * Mic Jack
40 20
41- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's 21- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
42 connected to the CODEC. 22 connected to the CODEC.
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt
index d14510613a7f..aab6ce0ad2fc 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt
@@ -11,31 +11,8 @@ Required properties:
11- nvidia,audio-routing : A list of the connections between audio components. 11- nvidia,audio-routing : A list of the connections between audio components.
12 Each entry is a pair of strings, the first being the connection's sink, 12 Each entry is a pair of strings, the first being the connection's sink,
13 the second being the connection's source. Valid names for sources and 13 the second being the connection's source. Valid names for sources and
14 sinks are the WM8753's pins, and the jacks on the board: 14 sinks are the WM8753's pins as documented in the binding for the WM8753,
15 15 and the jacks on the board:
16 WM8753 pins:
17
18 * LOUT1
19 * LOUT2
20 * ROUT1
21 * ROUT2
22 * MONO1
23 * MONO2
24 * OUT3
25 * OUT4
26 * LINE1
27 * LINE2
28 * RXP
29 * RXN
30 * ACIN
31 * ACOP
32 * MIC1N
33 * MIC1
34 * MIC2N
35 * MIC2
36 * Mic Bias
37
38 Board connectors:
39 16
40 * Headphone Jack 17 * Headphone Jack
41 * Mic Jack 18 * Mic Jack
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
index 3bf722deb722..4b44dfb6ca0d 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
@@ -11,28 +11,8 @@ Required properties:
11- nvidia,audio-routing : A list of the connections between audio components. 11- nvidia,audio-routing : A list of the connections between audio components.
12 Each entry is a pair of strings, the first being the connection's sink, 12 Each entry is a pair of strings, the first being the connection's sink,
13 the second being the connection's source. Valid names for sources and 13 the second being the connection's source. Valid names for sources and
14 sinks are the WM8903's pins, and the jacks on the board: 14 sinks are the WM8903's pins (documented in the WM8903 binding document),
15 15 and the jacks on the board:
16 WM8903 pins:
17
18 * IN1L
19 * IN1R
20 * IN2L
21 * IN2R
22 * IN3L
23 * IN3R
24 * DMICDAT
25 * HPOUTL
26 * HPOUTR
27 * LINEOUTL
28 * LINEOUTR
29 * LOP
30 * LON
31 * ROP
32 * RON
33 * MICBIAS
34
35 Board connectors:
36 16
37 * Headphone Jack 17 * Headphone Jack
38 * Int Spk 18 * Int Spk
diff --git a/Documentation/devicetree/bindings/sound/pcm1792a.txt b/Documentation/devicetree/bindings/sound/pcm1792a.txt
new file mode 100644
index 000000000000..970ba1ed576f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/pcm1792a.txt
@@ -0,0 +1,18 @@
1Texas Instruments pcm1792a DT bindings
2
3This driver supports the SPI bus.
4
5Required properties:
6
7 - compatible: "ti,pcm1792a"
8
9For required properties on SPI, please consult
10Documentation/devicetree/bindings/spi/spi-bus.txt
11
12Examples:
13
14 codec_spi: 1792a@0 {
15 compatible = "ti,pcm1792a";
16 spi-max-frequency = <600000>;
17 };
18
diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt b/Documentation/devicetree/bindings/sound/rt5640.txt
index 005bcb24d72d..068a1141b06f 100644
--- a/Documentation/devicetree/bindings/sound/rt5640.txt
+++ b/Documentation/devicetree/bindings/sound/rt5640.txt
@@ -18,6 +18,26 @@ Optional properties:
18 18
19- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. 19- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
20 20
21Pins on the device (for linking into audio routes):
22
23 * DMIC1
24 * DMIC2
25 * MICBIAS1
26 * IN1P
27 * IN1R
28 * IN2P
29 * IN2R
30 * HPOL
31 * HPOR
32 * LOUTL
33 * LOUTR
34 * MONOP
35 * MONON
36 * SPOLP
37 * SPOLN
38 * SPORP
39 * SPORN
40
21Example: 41Example:
22 42
23rt5640 { 43rt5640 {
diff --git a/Documentation/devicetree/bindings/sound/samsung-i2s.txt b/Documentation/devicetree/bindings/sound/samsung-i2s.txt
index 025e66b85a43..7386d444ada1 100644
--- a/Documentation/devicetree/bindings/sound/samsung-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/samsung-i2s.txt
@@ -2,7 +2,15 @@
2 2
3Required SoC Specific Properties: 3Required SoC Specific Properties:
4 4
5- compatible : "samsung,i2s-v5" 5- compatible : should be one of the following.
6 - samsung,s3c6410-i2s: for 8/16/24bit stereo I2S.
7 - samsung,s5pv210-i2s: for 8/16/24bit multichannel(5.1) I2S with
8 secondary fifo, s/w reset control and internal mux for root clk src.
9 - samsung,exynos5420-i2s: for 8/16/24bit multichannel(7.1) I2S with
10 secondary fifo, s/w reset control, internal mux for root clk src and
11 TDM support. TDM (Time division multiplexing) is to allow transfer of
12 multiple channel audio data on single data line.
13
6- reg: physical base address of the controller and length of memory mapped 14- reg: physical base address of the controller and length of memory mapped
7 region. 15 region.
8- dmas: list of DMA controller phandle and DMA request line ordered pairs. 16- dmas: list of DMA controller phandle and DMA request line ordered pairs.
@@ -21,13 +29,6 @@ Required SoC Specific Properties:
21 29
22Optional SoC Specific Properties: 30Optional SoC Specific Properties:
23 31
24- samsung,supports-6ch: If the I2S Primary sound source has 5.1 Channel
25 support, this flag is enabled.
26- samsung,supports-rstclr: This flag should be set if I2S software reset bit
27 control is required. When this flag is set I2S software reset bit will be
28 enabled or disabled based on need.
29- samsung,supports-secdai:If I2S block has a secondary FIFO and internal DMA,
30 then this flag is enabled.
31- samsung,idma-addr: Internal DMA register base address of the audio 32- samsung,idma-addr: Internal DMA register base address of the audio
32 sub system(used in secondary sound source). 33 sub system(used in secondary sound source).
33- pinctrl-0: Should specify pin control groups used for this controller. 34- pinctrl-0: Should specify pin control groups used for this controller.
@@ -36,7 +37,7 @@ Optional SoC Specific Properties:
36Example: 37Example:
37 38
38i2s0: i2s@03830000 { 39i2s0: i2s@03830000 {
39 compatible = "samsung,i2s-v5"; 40 compatible = "samsung,s5pv210-i2s";
40 reg = <0x03830000 0x100>; 41 reg = <0x03830000 0x100>;
41 dmas = <&pdma0 10 42 dmas = <&pdma0 10
42 &pdma0 9 43 &pdma0 9
@@ -46,9 +47,6 @@ i2s0: i2s@03830000 {
46 <&clock_audss EXYNOS_I2S_BUS>, 47 <&clock_audss EXYNOS_I2S_BUS>,
47 <&clock_audss EXYNOS_SCLK_I2S>; 48 <&clock_audss EXYNOS_SCLK_I2S>;
48 clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; 49 clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
49 samsung,supports-6ch;
50 samsung,supports-rstclr;
51 samsung,supports-secdai;
52 samsung,idma-addr = <0x03000000>; 50 samsung,idma-addr = <0x03000000>;
53 pinctrl-names = "default"; 51 pinctrl-names = "default";
54 pinctrl-0 = <&i2s0_bus>; 52 pinctrl-0 = <&i2s0_bus>;
diff --git a/Documentation/devicetree/bindings/sound/soc-ac97link.txt b/Documentation/devicetree/bindings/sound/soc-ac97link.txt
new file mode 100644
index 000000000000..80152a87f239
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/soc-ac97link.txt
@@ -0,0 +1,28 @@
1AC97 link bindings
2
3These bindings can be included within any other device node.
4
5Required properties:
6 - pinctrl-names: Has to contain following states to setup the correct
7 pinmuxing for the used gpios:
8 "ac97-running": AC97-link is active
9 "ac97-reset": AC97-link reset state
10 "ac97-warm-reset": AC97-link warm reset state
11 - ac97-gpios: List of gpio phandles with args in the order ac97-sync,
12 ac97-sdata, ac97-reset
13
14
15Example:
16
17ssi {
18 ...
19
20 pinctrl-names = "default", "ac97-running", "ac97-reset", "ac97-warm-reset";
21 pinctrl-0 = <&ac97link_running>;
22 pinctrl-1 = <&ac97link_running>;
23 pinctrl-2 = <&ac97link_reset>;
24 pinctrl-3 = <&ac97link_warm_reset>;
25 ac97-gpios = <&gpio3 20 0 &gpio3 22 0 &gpio3 28 0>;
26
27 ...
28};
diff --git a/Documentation/devicetree/bindings/sound/ti,pcm1681.txt b/Documentation/devicetree/bindings/sound/ti,pcm1681.txt
new file mode 100644
index 000000000000..4df17185ab80
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ti,pcm1681.txt
@@ -0,0 +1,15 @@
1Texas Instruments PCM1681 8-channel PWM Processor
2
3Required properties:
4
5 - compatible: Should contain "ti,pcm1681".
6 - reg: The i2c address. Should contain <0x4c>.
7
8Examples:
9
10 i2c_bus {
11 pcm1681@4c {
12 compatible = "ti,pcm1681";
13 reg = <0x4c>;
14 };
15 };
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
index f47c3f589fd0..705a6b156c6c 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
@@ -3,7 +3,14 @@ Texas Instruments - tlv320aic3x Codec module
3The tlv320aic3x serial control bus communicates through I2C protocols 3The tlv320aic3x serial control bus communicates through I2C protocols
4 4
5Required properties: 5Required properties:
6- compatible - "string" - "ti,tlv320aic3x" 6
7- compatible - "string" - One of:
8 "ti,tlv320aic3x" - Generic TLV320AIC3x device
9 "ti,tlv320aic33" - TLV320AIC33
10 "ti,tlv320aic3007" - TLV320AIC3007
11 "ti,tlv320aic3106" - TLV320AIC3106
12
13
7- reg - <int> - I2C slave address 14- reg - <int> - I2C slave address
8 15
9 16
diff --git a/Documentation/devicetree/bindings/sound/wm8731.txt b/Documentation/devicetree/bindings/sound/wm8731.txt
index 15f70048469b..236690e99b87 100644
--- a/Documentation/devicetree/bindings/sound/wm8731.txt
+++ b/Documentation/devicetree/bindings/sound/wm8731.txt
@@ -16,3 +16,12 @@ codec: wm8731@1a {
16 compatible = "wlf,wm8731"; 16 compatible = "wlf,wm8731";
17 reg = <0x1a>; 17 reg = <0x1a>;
18}; 18};
19
20Available audio endpoints for an audio-routing table:
21 * LOUT: Left Channel Line Output
22 * ROUT: Right Channel Line Output
23 * LHPOUT: Left Channel Headphone Output
24 * RHPOUT: Right Channel Headphone Output
25 * LLINEIN: Left Channel Line Input
26 * RLINEIN: Right Channel Line Input
27 * MICIN: Microphone Input
diff --git a/Documentation/devicetree/bindings/sound/wm8753.txt b/Documentation/devicetree/bindings/sound/wm8753.txt
index e65277a0fb60..8eee61282105 100644
--- a/Documentation/devicetree/bindings/sound/wm8753.txt
+++ b/Documentation/devicetree/bindings/sound/wm8753.txt
@@ -10,9 +10,31 @@ Required properties:
10 - reg : the I2C address of the device for I2C, the chip select 10 - reg : the I2C address of the device for I2C, the chip select
11 number for SPI. 11 number for SPI.
12 12
13Pins on the device (for linking into audio routes):
14
15 * LOUT1
16 * LOUT2
17 * ROUT1
18 * ROUT2
19 * MONO1
20 * MONO2
21 * OUT3
22 * OUT4
23 * LINE1
24 * LINE2
25 * RXP
26 * RXN
27 * ACIN
28 * ACOP
29 * MIC1N
30 * MIC1
31 * MIC2N
32 * MIC2
33 * Mic Bias
34
13Example: 35Example:
14 36
15codec: wm8737@1a { 37codec: wm8753@1a {
16 compatible = "wlf,wm8753"; 38 compatible = "wlf,wm8753";
17 reg = <0x1a>; 39 reg = <0x1a>;
18}; 40};
diff --git a/Documentation/devicetree/bindings/sound/wm8903.txt b/Documentation/devicetree/bindings/sound/wm8903.txt
index f102cbc42694..94ec32c194bb 100644
--- a/Documentation/devicetree/bindings/sound/wm8903.txt
+++ b/Documentation/devicetree/bindings/sound/wm8903.txt
@@ -28,6 +28,25 @@ Optional properties:
28 performed. If any entry has the value 0xffffffff, that GPIO's 28 performed. If any entry has the value 0xffffffff, that GPIO's
29 configuration will not be modified. 29 configuration will not be modified.
30 30
31Pins on the device (for linking into audio routes):
32
33 * IN1L
34 * IN1R
35 * IN2L
36 * IN2R
37 * IN3L
38 * IN3R
39 * DMICDAT
40 * HPOUTL
41 * HPOUTR
42 * LINEOUTL
43 * LINEOUTR
44 * LOP
45 * LON
46 * ROP
47 * RON
48 * MICBIAS
49
31Example: 50Example:
32 51
33codec: wm8903@1a { 52codec: wm8903@1a {
diff --git a/Documentation/devicetree/bindings/sound/wm8994.txt b/Documentation/devicetree/bindings/sound/wm8994.txt
index f2f3e80934d2..e045e90a0924 100644
--- a/Documentation/devicetree/bindings/sound/wm8994.txt
+++ b/Documentation/devicetree/bindings/sound/wm8994.txt
@@ -32,6 +32,10 @@ Optional properties:
32 The second cell is the flags, encoded as the trigger masks from 32 The second cell is the flags, encoded as the trigger masks from
33 Documentation/devicetree/bindings/interrupts.txt 33 Documentation/devicetree/bindings/interrupts.txt
34 34
35 - clocks : A list of up to two phandle and clock specifier pairs
36 - clock-names : A list of clock names sorted in the same order as clocks.
37 Valid clock names are "MCLK1" and "MCLK2".
38
35 - wlf,gpio-cfg : A list of GPIO configuration register values. If absent, 39 - wlf,gpio-cfg : A list of GPIO configuration register values. If absent,
36 no configuration of these registers is performed. If any value is 40 no configuration of these registers is performed. If any value is
37 over 0xffff then the register will be left as default. If present 11 41 over 0xffff then the register will be left as default. If present 11
diff --git a/MAINTAINERS b/MAINTAINERS
index b140c8123098..b5e09128898f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -595,6 +595,7 @@ S: Supported
595F: sound/soc/codecs/adau* 595F: sound/soc/codecs/adau*
596F: sound/soc/codecs/adav* 596F: sound/soc/codecs/adav*
597F: sound/soc/codecs/ad1* 597F: sound/soc/codecs/ad1*
598F: sound/soc/codecs/ad7*
598F: sound/soc/codecs/ssm* 599F: sound/soc/codecs/ssm*
599F: sound/soc/codecs/sigmadsp.* 600F: sound/soc/codecs/sigmadsp.*
600 601
@@ -7682,6 +7683,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
7682L: alsa-devel@alsa-project.org (moderated for non-subscribers) 7683L: alsa-devel@alsa-project.org (moderated for non-subscribers)
7683W: http://alsa-project.org/main/index.php/ASoC 7684W: http://alsa-project.org/main/index.php/ASoC
7684S: Supported 7685S: Supported
7686F: Documentation/sound/alsa/soc/
7685F: sound/soc/ 7687F: sound/soc/
7686F: include/sound/soc* 7688F: include/sound/soc*
7687 7689
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index ef57277fc38f..376090f07231 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -405,7 +405,7 @@
405 }; 405 };
406 406
407 i2s0: i2s@03830000 { 407 i2s0: i2s@03830000 {
408 compatible = "samsung,i2s-v5"; 408 compatible = "samsung,s5pv210-i2s";
409 reg = <0x03830000 0x100>; 409 reg = <0x03830000 0x100>;
410 dmas = <&pdma0 10 410 dmas = <&pdma0 10
411 &pdma0 9 411 &pdma0 9
@@ -415,16 +415,13 @@
415 <&clock_audss EXYNOS_I2S_BUS>, 415 <&clock_audss EXYNOS_I2S_BUS>,
416 <&clock_audss EXYNOS_SCLK_I2S>; 416 <&clock_audss EXYNOS_SCLK_I2S>;
417 clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; 417 clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
418 samsung,supports-6ch;
419 samsung,supports-rstclr;
420 samsung,supports-secdai;
421 samsung,idma-addr = <0x03000000>; 418 samsung,idma-addr = <0x03000000>;
422 pinctrl-names = "default"; 419 pinctrl-names = "default";
423 pinctrl-0 = <&i2s0_bus>; 420 pinctrl-0 = <&i2s0_bus>;
424 }; 421 };
425 422
426 i2s1: i2s@12D60000 { 423 i2s1: i2s@12D60000 {
427 compatible = "samsung,i2s-v5"; 424 compatible = "samsung,s3c6410-i2s";
428 reg = <0x12D60000 0x100>; 425 reg = <0x12D60000 0x100>;
429 dmas = <&pdma1 12 426 dmas = <&pdma1 12
430 &pdma1 11>; 427 &pdma1 11>;
@@ -436,7 +433,7 @@
436 }; 433 };
437 434
438 i2s2: i2s@12D70000 { 435 i2s2: i2s@12D70000 {
439 compatible = "samsung,i2s-v5"; 436 compatible = "samsung,s3c6410-i2s";
440 reg = <0x12D70000 0x100>; 437 reg = <0x12D70000 0x100>;
441 dmas = <&pdma0 12 438 dmas = <&pdma0 12
442 &pdma0 11>; 439 &pdma0 11>;
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 00247c771313..304f069ebf50 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -108,8 +108,8 @@ static void __init dove_clk_init(void)
108 orion_clkdev_add(NULL, "sdhci-dove.1", sdio1); 108 orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
109 orion_clkdev_add(NULL, "orion_nand", nand); 109 orion_clkdev_add(NULL, "orion_nand", nand);
110 orion_clkdev_add(NULL, "cafe1000-ccic.0", camera); 110 orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
111 orion_clkdev_add(NULL, "kirkwood-i2s.0", i2s0); 111 orion_clkdev_add(NULL, "mvebu-audio.0", i2s0);
112 orion_clkdev_add(NULL, "kirkwood-i2s.1", i2s1); 112 orion_clkdev_add(NULL, "mvebu-audio.1", i2s1);
113 orion_clkdev_add(NULL, "mv_crypto", crypto); 113 orion_clkdev_add(NULL, "mv_crypto", crypto);
114 orion_clkdev_add(NULL, "dove-ac97", ac97); 114 orion_clkdev_add(NULL, "dove-ac97", ac97);
115 orion_clkdev_add(NULL, "dove-pdma", pdma); 115 orion_clkdev_add(NULL, "dove-pdma", pdma);
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index e9238b5567ee..1663de090984 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -264,7 +264,7 @@ void __init kirkwood_clk_init(void)
264 orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1); 264 orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1);
265 orion_clkdev_add("0", "pcie", pex0); 265 orion_clkdev_add("0", "pcie", pex0);
266 orion_clkdev_add("1", "pcie", pex1); 266 orion_clkdev_add("1", "pcie", pex1);
267 orion_clkdev_add(NULL, "kirkwood-i2s", audio); 267 orion_clkdev_add(NULL, "mvebu-audio", audio);
268 orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit); 268 orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit);
269 orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit); 269 orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit);
270 270
@@ -560,7 +560,7 @@ void __init kirkwood_timer_init(void)
560/***************************************************************************** 560/*****************************************************************************
561 * Audio 561 * Audio
562 ****************************************************************************/ 562 ****************************************************************************/
563static struct resource kirkwood_i2s_resources[] = { 563static struct resource kirkwood_audio_resources[] = {
564 [0] = { 564 [0] = {
565 .start = AUDIO_PHYS_BASE, 565 .start = AUDIO_PHYS_BASE,
566 .end = AUDIO_PHYS_BASE + SZ_16K - 1, 566 .end = AUDIO_PHYS_BASE + SZ_16K - 1,
@@ -573,29 +573,23 @@ static struct resource kirkwood_i2s_resources[] = {
573 }, 573 },
574}; 574};
575 575
576static struct kirkwood_asoc_platform_data kirkwood_i2s_data = { 576static struct kirkwood_asoc_platform_data kirkwood_audio_data = {
577 .burst = 128, 577 .burst = 128,
578}; 578};
579 579
580static struct platform_device kirkwood_i2s_device = { 580static struct platform_device kirkwood_audio_device = {
581 .name = "kirkwood-i2s", 581 .name = "mvebu-audio",
582 .id = -1, 582 .id = -1,
583 .num_resources = ARRAY_SIZE(kirkwood_i2s_resources), 583 .num_resources = ARRAY_SIZE(kirkwood_audio_resources),
584 .resource = kirkwood_i2s_resources, 584 .resource = kirkwood_audio_resources,
585 .dev = { 585 .dev = {
586 .platform_data = &kirkwood_i2s_data, 586 .platform_data = &kirkwood_audio_data,
587 }, 587 },
588}; 588};
589 589
590static struct platform_device kirkwood_pcm_device = {
591 .name = "kirkwood-pcm-audio",
592 .id = -1,
593};
594
595void __init kirkwood_audio_init(void) 590void __init kirkwood_audio_init(void)
596{ 591{
597 platform_device_register(&kirkwood_i2s_device); 592 platform_device_register(&kirkwood_audio_device);
598 platform_device_register(&kirkwood_pcm_device);
599} 593}
600 594
601/***************************************************************************** 595/*****************************************************************************
diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index 8e11e96eab5e..c83f27b6bdda 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -30,6 +30,8 @@
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/spi/pxa2xx_spi.h> 31#include <linux/spi/pxa2xx_spi.h>
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/of.h>
34#include <linux/of_device.h>
33 35
34#include <asm/irq.h> 36#include <asm/irq.h>
35#include <mach/hardware.h> 37#include <mach/hardware.h>
@@ -60,6 +62,30 @@ struct ssp_device *pxa_ssp_request(int port, const char *label)
60} 62}
61EXPORT_SYMBOL(pxa_ssp_request); 63EXPORT_SYMBOL(pxa_ssp_request);
62 64
65struct ssp_device *pxa_ssp_request_of(const struct device_node *of_node,
66 const char *label)
67{
68 struct ssp_device *ssp = NULL;
69
70 mutex_lock(&ssp_lock);
71
72 list_for_each_entry(ssp, &ssp_list, node) {
73 if (ssp->of_node == of_node && ssp->use_count == 0) {
74 ssp->use_count++;
75 ssp->label = label;
76 break;
77 }
78 }
79
80 mutex_unlock(&ssp_lock);
81
82 if (&ssp->node == &ssp_list)
83 return NULL;
84
85 return ssp;
86}
87EXPORT_SYMBOL(pxa_ssp_request_of);
88
63void pxa_ssp_free(struct ssp_device *ssp) 89void pxa_ssp_free(struct ssp_device *ssp)
64{ 90{
65 mutex_lock(&ssp_lock); 91 mutex_lock(&ssp_lock);
@@ -72,96 +98,126 @@ void pxa_ssp_free(struct ssp_device *ssp)
72} 98}
73EXPORT_SYMBOL(pxa_ssp_free); 99EXPORT_SYMBOL(pxa_ssp_free);
74 100
101#ifdef CONFIG_OF
102static const struct of_device_id pxa_ssp_of_ids[] = {
103 { .compatible = "mrvl,pxa25x-ssp", .data = (void *) PXA25x_SSP },
104 { .compatible = "mvrl,pxa25x-nssp", .data = (void *) PXA25x_NSSP },
105 { .compatible = "mrvl,pxa27x-ssp", .data = (void *) PXA27x_SSP },
106 { .compatible = "mrvl,pxa3xx-ssp", .data = (void *) PXA3xx_SSP },
107 { .compatible = "mvrl,pxa168-ssp", .data = (void *) PXA168_SSP },
108 { .compatible = "mrvl,pxa910-ssp", .data = (void *) PXA910_SSP },
109 { .compatible = "mrvl,ce4100-ssp", .data = (void *) CE4100_SSP },
110 { .compatible = "mrvl,lpss-ssp", .data = (void *) LPSS_SSP },
111 { },
112};
113MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
114#endif
115
75static int pxa_ssp_probe(struct platform_device *pdev) 116static int pxa_ssp_probe(struct platform_device *pdev)
76{ 117{
77 const struct platform_device_id *id = platform_get_device_id(pdev);
78 struct resource *res; 118 struct resource *res;
79 struct ssp_device *ssp; 119 struct ssp_device *ssp;
80 int ret = 0; 120 struct device *dev = &pdev->dev;
81 121
82 ssp = kzalloc(sizeof(struct ssp_device), GFP_KERNEL); 122 ssp = devm_kzalloc(dev, sizeof(struct ssp_device), GFP_KERNEL);
83 if (ssp == NULL) { 123 if (ssp == NULL)
84 dev_err(&pdev->dev, "failed to allocate memory");
85 return -ENOMEM; 124 return -ENOMEM;
86 }
87 ssp->pdev = pdev;
88 125
89 ssp->clk = clk_get(&pdev->dev, NULL); 126 ssp->pdev = pdev;
90 if (IS_ERR(ssp->clk)) {
91 ret = PTR_ERR(ssp->clk);
92 goto err_free;
93 }
94 127
95 res = platform_get_resource(pdev, IORESOURCE_DMA, 0); 128 ssp->clk = devm_clk_get(dev, NULL);
96 if (res == NULL) { 129 if (IS_ERR(ssp->clk))
97 dev_err(&pdev->dev, "no SSP RX DRCMR defined\n"); 130 return PTR_ERR(ssp->clk);
98 ret = -ENODEV; 131
99 goto err_free_clk; 132 if (dev->of_node) {
100 } 133 struct of_phandle_args dma_spec;
101 ssp->drcmr_rx = res->start; 134 struct device_node *np = dev->of_node;
135
136 /*
137 * FIXME: we should allocate the DMA channel from this
138 * context and pass the channel down to the ssp users.
139 * For now, we lookup the rx and tx indices manually
140 */
141
142 /* rx */
143 of_parse_phandle_with_args(np, "dmas", "#dma-cells",
144 0, &dma_spec);
145 ssp->drcmr_rx = dma_spec.args[0];
146 of_node_put(dma_spec.np);
147
148 /* tx */
149 of_parse_phandle_with_args(np, "dmas", "#dma-cells",
150 1, &dma_spec);
151 ssp->drcmr_tx = dma_spec.args[0];
152 of_node_put(dma_spec.np);
153 } else {
154 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
155 if (res == NULL) {
156 dev_err(dev, "no SSP RX DRCMR defined\n");
157 return -ENODEV;
158 }
159 ssp->drcmr_rx = res->start;
102 160
103 res = platform_get_resource(pdev, IORESOURCE_DMA, 1); 161 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
104 if (res == NULL) { 162 if (res == NULL) {
105 dev_err(&pdev->dev, "no SSP TX DRCMR defined\n"); 163 dev_err(dev, "no SSP TX DRCMR defined\n");
106 ret = -ENODEV; 164 return -ENODEV;
107 goto err_free_clk; 165 }
166 ssp->drcmr_tx = res->start;
108 } 167 }
109 ssp->drcmr_tx = res->start;
110 168
111 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 169 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
112 if (res == NULL) { 170 if (res == NULL) {
113 dev_err(&pdev->dev, "no memory resource defined\n"); 171 dev_err(dev, "no memory resource defined\n");
114 ret = -ENODEV; 172 return -ENODEV;
115 goto err_free_clk;
116 } 173 }
117 174
118 res = request_mem_region(res->start, resource_size(res), 175 res = devm_request_mem_region(dev, res->start, resource_size(res),
119 pdev->name); 176 pdev->name);
120 if (res == NULL) { 177 if (res == NULL) {
121 dev_err(&pdev->dev, "failed to request memory resource\n"); 178 dev_err(dev, "failed to request memory resource\n");
122 ret = -EBUSY; 179 return -EBUSY;
123 goto err_free_clk;
124 } 180 }
125 181
126 ssp->phys_base = res->start; 182 ssp->phys_base = res->start;
127 183
128 ssp->mmio_base = ioremap(res->start, resource_size(res)); 184 ssp->mmio_base = devm_ioremap(dev, res->start, resource_size(res));
129 if (ssp->mmio_base == NULL) { 185 if (ssp->mmio_base == NULL) {
130 dev_err(&pdev->dev, "failed to ioremap() registers\n"); 186 dev_err(dev, "failed to ioremap() registers\n");
131 ret = -ENODEV; 187 return -ENODEV;
132 goto err_free_mem;
133 } 188 }
134 189
135 ssp->irq = platform_get_irq(pdev, 0); 190 ssp->irq = platform_get_irq(pdev, 0);
136 if (ssp->irq < 0) { 191 if (ssp->irq < 0) {
137 dev_err(&pdev->dev, "no IRQ resource defined\n"); 192 dev_err(dev, "no IRQ resource defined\n");
138 ret = -ENODEV; 193 return -ENODEV;
139 goto err_free_io; 194 }
195
196 if (dev->of_node) {
197 const struct of_device_id *id =
198 of_match_device(of_match_ptr(pxa_ssp_of_ids), dev);
199 ssp->type = (int) id->data;
200 } else {
201 const struct platform_device_id *id =
202 platform_get_device_id(pdev);
203 ssp->type = (int) id->driver_data;
204
205 /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
206 * starts from 0, do a translation here
207 */
208 ssp->port_id = pdev->id + 1;
140 } 209 }
141 210
142 /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
143 * starts from 0, do a translation here
144 */
145 ssp->port_id = pdev->id + 1;
146 ssp->use_count = 0; 211 ssp->use_count = 0;
147 ssp->type = (int)id->driver_data; 212 ssp->of_node = dev->of_node;
148 213
149 mutex_lock(&ssp_lock); 214 mutex_lock(&ssp_lock);
150 list_add(&ssp->node, &ssp_list); 215 list_add(&ssp->node, &ssp_list);
151 mutex_unlock(&ssp_lock); 216 mutex_unlock(&ssp_lock);
152 217
153 platform_set_drvdata(pdev, ssp); 218 platform_set_drvdata(pdev, ssp);
154 return 0;
155 219
156err_free_io: 220 return 0;
157 iounmap(ssp->mmio_base);
158err_free_mem:
159 release_mem_region(res->start, resource_size(res));
160err_free_clk:
161 clk_put(ssp->clk);
162err_free:
163 kfree(ssp);
164 return ret;
165} 221}
166 222
167static int pxa_ssp_remove(struct platform_device *pdev) 223static int pxa_ssp_remove(struct platform_device *pdev)
@@ -201,8 +257,9 @@ static struct platform_driver pxa_ssp_driver = {
201 .probe = pxa_ssp_probe, 257 .probe = pxa_ssp_probe,
202 .remove = pxa_ssp_remove, 258 .remove = pxa_ssp_remove,
203 .driver = { 259 .driver = {
204 .owner = THIS_MODULE, 260 .owner = THIS_MODULE,
205 .name = "pxa2xx-ssp", 261 .name = "pxa2xx-ssp",
262 .of_match_table = of_match_ptr(pxa_ssp_of_ids),
206 }, 263 },
207 .id_table = ssp_id_table, 264 .id_table = ssp_id_table,
208}; 265};
diff --git a/include/dt-bindings/sound/fsl-imx-audmux.h b/include/dt-bindings/sound/fsl-imx-audmux.h
new file mode 100644
index 000000000000..50b09e96f247
--- /dev/null
+++ b/include/dt-bindings/sound/fsl-imx-audmux.h
@@ -0,0 +1,56 @@
1#ifndef __DT_FSL_IMX_AUDMUX_H
2#define __DT_FSL_IMX_AUDMUX_H
3
4#define MX27_AUDMUX_HPCR1_SSI0 0
5#define MX27_AUDMUX_HPCR2_SSI1 1
6#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2
7#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3
8#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4
9#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5
10
11#define MX31_AUDMUX_PORT1_SSI0 0
12#define MX31_AUDMUX_PORT2_SSI1 1
13#define MX31_AUDMUX_PORT3_SSI_PINS_3 2
14#define MX31_AUDMUX_PORT4_SSI_PINS_4 3
15#define MX31_AUDMUX_PORT5_SSI_PINS_5 4
16#define MX31_AUDMUX_PORT6_SSI_PINS_6 5
17#define MX31_AUDMUX_PORT7_SSI_PINS_7 6
18
19#define MX51_AUDMUX_PORT1_SSI0 0
20#define MX51_AUDMUX_PORT2_SSI1 1
21#define MX51_AUDMUX_PORT3 2
22#define MX51_AUDMUX_PORT4 3
23#define MX51_AUDMUX_PORT5 4
24#define MX51_AUDMUX_PORT6 5
25#define MX51_AUDMUX_PORT7 6
26
27/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
28#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff)
29#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8)
30#define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10)
31#define IMX_AUDMUX_V1_PCR_SYN (1 << 12)
32#define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13)
33#define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20)
34#define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24)
35#define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25)
36#define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26)
37#define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30)
38#define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31)
39
40/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
41#define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31)
42#define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27)
43#define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26)
44#define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22)
45#define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21)
46#define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17)
47#define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16)
48#define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12)
49#define IMX_AUDMUX_V2_PTCR_SYN (1 << 11)
50
51#define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13)
52#define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12)
53#define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8)
54#define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff)
55
56#endif /* __DT_FSL_IMX_AUDMUX_H */
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index deb0ae58b99b..66a0e5384edd 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -11,7 +11,7 @@ struct atmel_ssc_platform_data {
11 11
12struct ssc_device { 12struct ssc_device {
13 struct list_head list; 13 struct list_head list;
14 resource_size_t phybase; 14 dma_addr_t phybase;
15 void __iomem *regs; 15 void __iomem *regs;
16 struct platform_device *pdev; 16 struct platform_device *pdev;
17 struct atmel_ssc_platform_data *pdata; 17 struct atmel_ssc_platform_data *pdata;
diff --git a/include/linux/mfd/arizona/gpio.h b/include/linux/mfd/arizona/gpio.h
new file mode 100644
index 000000000000..d2146bb74f89
--- /dev/null
+++ b/include/linux/mfd/arizona/gpio.h
@@ -0,0 +1,96 @@
1/*
2 * GPIO configuration for Arizona devices
3 *
4 * Copyright 2013 Wolfson Microelectronics. PLC.
5 *
6 * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _ARIZONA_GPIO_H
14#define _ARIZONA_GPIO_H
15
16#define ARIZONA_GP_FN_TXLRCLK 0x00
17#define ARIZONA_GP_FN_GPIO 0x01
18#define ARIZONA_GP_FN_IRQ1 0x02
19#define ARIZONA_GP_FN_IRQ2 0x03
20#define ARIZONA_GP_FN_OPCLK 0x04
21#define ARIZONA_GP_FN_FLL1_OUT 0x05
22#define ARIZONA_GP_FN_FLL2_OUT 0x06
23#define ARIZONA_GP_FN_PWM1 0x08
24#define ARIZONA_GP_FN_PWM2 0x09
25#define ARIZONA_GP_FN_SYSCLK_UNDERCLOCKED 0x0A
26#define ARIZONA_GP_FN_ASYNCCLK_UNDERCLOCKED 0x0B
27#define ARIZONA_GP_FN_FLL1_LOCK 0x0C
28#define ARIZONA_GP_FN_FLL2_LOCK 0x0D
29#define ARIZONA_GP_FN_FLL1_CLOCK_OK 0x0F
30#define ARIZONA_GP_FN_FLL2_CLOCK_OK 0x10
31#define ARIZONA_GP_FN_HEADPHONE_DET 0x12
32#define ARIZONA_GP_FN_MIC_DET 0x13
33#define ARIZONA_GP_FN_WSEQ_STATUS 0x15
34#define ARIZONA_GP_FN_CIF_ADDRESS_ERROR 0x16
35#define ARIZONA_GP_FN_ASRC1_LOCK 0x1A
36#define ARIZONA_GP_FN_ASRC2_LOCK 0x1B
37#define ARIZONA_GP_FN_ASRC_CONFIG_ERROR 0x1C
38#define ARIZONA_GP_FN_DRC1_SIGNAL_DETECT 0x1D
39#define ARIZONA_GP_FN_DRC1_ANTICLIP 0x1E
40#define ARIZONA_GP_FN_DRC1_DECAY 0x1F
41#define ARIZONA_GP_FN_DRC1_NOISE 0x20
42#define ARIZONA_GP_FN_DRC1_QUICK_RELEASE 0x21
43#define ARIZONA_GP_FN_DRC2_SIGNAL_DETECT 0x22
44#define ARIZONA_GP_FN_DRC2_ANTICLIP 0x23
45#define ARIZONA_GP_FN_DRC2_DECAY 0x24
46#define ARIZONA_GP_FN_DRC2_NOISE 0x25
47#define ARIZONA_GP_FN_DRC2_QUICK_RELEASE 0x26
48#define ARIZONA_GP_FN_MIXER_DROPPED_SAMPLE 0x27
49#define ARIZONA_GP_FN_AIF1_CONFIG_ERROR 0x28
50#define ARIZONA_GP_FN_AIF2_CONFIG_ERROR 0x29
51#define ARIZONA_GP_FN_AIF3_CONFIG_ERROR 0x2A
52#define ARIZONA_GP_FN_SPK_TEMP_SHUTDOWN 0x2B
53#define ARIZONA_GP_FN_SPK_TEMP_WARNING 0x2C
54#define ARIZONA_GP_FN_UNDERCLOCKED 0x2D
55#define ARIZONA_GP_FN_OVERCLOCKED 0x2E
56#define ARIZONA_GP_FN_DSP_IRQ1 0x35
57#define ARIZONA_GP_FN_DSP_IRQ2 0x36
58#define ARIZONA_GP_FN_ASYNC_OPCLK 0x3D
59#define ARIZONA_GP_FN_BOOT_DONE 0x44
60#define ARIZONA_GP_FN_DSP1_RAM_READY 0x45
61#define ARIZONA_GP_FN_SYSCLK_ENA_STATUS 0x4B
62#define ARIZONA_GP_FN_ASYNCCLK_ENA_STATUS 0x4C
63
64#define ARIZONA_GPN_DIR 0x8000 /* GPN_DIR */
65#define ARIZONA_GPN_DIR_MASK 0x8000 /* GPN_DIR */
66#define ARIZONA_GPN_DIR_SHIFT 15 /* GPN_DIR */
67#define ARIZONA_GPN_DIR_WIDTH 1 /* GPN_DIR */
68#define ARIZONA_GPN_PU 0x4000 /* GPN_PU */
69#define ARIZONA_GPN_PU_MASK 0x4000 /* GPN_PU */
70#define ARIZONA_GPN_PU_SHIFT 14 /* GPN_PU */
71#define ARIZONA_GPN_PU_WIDTH 1 /* GPN_PU */
72#define ARIZONA_GPN_PD 0x2000 /* GPN_PD */
73#define ARIZONA_GPN_PD_MASK 0x2000 /* GPN_PD */
74#define ARIZONA_GPN_PD_SHIFT 13 /* GPN_PD */
75#define ARIZONA_GPN_PD_WIDTH 1 /* GPN_PD */
76#define ARIZONA_GPN_LVL 0x0800 /* GPN_LVL */
77#define ARIZONA_GPN_LVL_MASK 0x0800 /* GPN_LVL */
78#define ARIZONA_GPN_LVL_SHIFT 11 /* GPN_LVL */
79#define ARIZONA_GPN_LVL_WIDTH 1 /* GPN_LVL */
80#define ARIZONA_GPN_POL 0x0400 /* GPN_POL */
81#define ARIZONA_GPN_POL_MASK 0x0400 /* GPN_POL */
82#define ARIZONA_GPN_POL_SHIFT 10 /* GPN_POL */
83#define ARIZONA_GPN_POL_WIDTH 1 /* GPN_POL */
84#define ARIZONA_GPN_OP_CFG 0x0200 /* GPN_OP_CFG */
85#define ARIZONA_GPN_OP_CFG_MASK 0x0200 /* GPN_OP_CFG */
86#define ARIZONA_GPN_OP_CFG_SHIFT 9 /* GPN_OP_CFG */
87#define ARIZONA_GPN_OP_CFG_WIDTH 1 /* GPN_OP_CFG */
88#define ARIZONA_GPN_DB 0x0100 /* GPN_DB */
89#define ARIZONA_GPN_DB_MASK 0x0100 /* GPN_DB */
90#define ARIZONA_GPN_DB_SHIFT 8 /* GPN_DB */
91#define ARIZONA_GPN_DB_WIDTH 1 /* GPN_DB */
92#define ARIZONA_GPN_FN_MASK 0x007F /* GPN_DB */
93#define ARIZONA_GPN_FN_SHIFT 0 /* GPN_DB */
94#define ARIZONA_GPN_FN_WIDTH 7 /* GPN_DB */
95
96#endif
diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h
index 88272591a895..9efc04dd255a 100644
--- a/include/linux/platform_data/asoc-s3c.h
+++ b/include/linux/platform_data/asoc-s3c.h
@@ -36,6 +36,7 @@ struct samsung_i2s {
36 */ 36 */
37#define QUIRK_NO_MUXPSR (1 << 2) 37#define QUIRK_NO_MUXPSR (1 << 2)
38#define QUIRK_NEED_RSTCLR (1 << 3) 38#define QUIRK_NEED_RSTCLR (1 << 3)
39#define QUIRK_SUPPORTS_TDM (1 << 4)
39 /* Quirks of the I2S controller */ 40 /* Quirks of the I2S controller */
40 u32 quirks; 41 u32 quirks;
41 dma_addr_t idma_addr; 42 dma_addr_t idma_addr;
diff --git a/include/linux/platform_data/omap-abe-twl6040.h b/include/linux/platform_data/omap-abe-twl6040.h
deleted file mode 100644
index 5d298ac10fc2..000000000000
--- a/include/linux/platform_data/omap-abe-twl6040.h
+++ /dev/null
@@ -1,49 +0,0 @@
1/**
2 * omap-abe-twl6040.h - ASoC machine driver OMAP4+ devices, header.
3 *
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
5 * All rights reserved.
6 *
7 * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 */
23
24#ifndef _OMAP_ABE_TWL6040_H_
25#define _OMAP_ABE_TWL6040_H_
26
27/* To select if only one channel is connected in a stereo port */
28#define ABE_TWL6040_LEFT (1 << 0)
29#define ABE_TWL6040_RIGHT (1 << 1)
30
31struct omap_abe_twl6040_data {
32 char *card_name;
33 /* Feature flags for connected audio pins */
34 u8 has_hs;
35 u8 has_hf;
36 bool has_ep;
37 u8 has_aux;
38 u8 has_vibra;
39 bool has_dmic;
40 bool has_hsmic;
41 bool has_mainmic;
42 bool has_submic;
43 u8 has_afm;
44 /* Other features */
45 bool jack_detection; /* board can detect jack events */
46 int mclk_freq; /* MCLK frequency speed for twl6040 */
47};
48
49#endif /* _OMAP_ABE_TWL6040_H_ */
diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h
index 467cc6307b62..49444203328a 100644
--- a/include/linux/pxa2xx_ssp.h
+++ b/include/linux/pxa2xx_ssp.h
@@ -21,6 +21,8 @@
21 21
22#include <linux/list.h> 22#include <linux/list.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/of.h>
25
24 26
25/* 27/*
26 * SSP Serial Port Registers 28 * SSP Serial Port Registers
@@ -190,6 +192,8 @@ struct ssp_device {
190 int irq; 192 int irq;
191 int drcmr_rx; 193 int drcmr_rx;
192 int drcmr_tx; 194 int drcmr_tx;
195
196 struct device_node *of_node;
193}; 197};
194 198
195/** 199/**
@@ -218,11 +222,18 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
218#ifdef CONFIG_ARCH_PXA 222#ifdef CONFIG_ARCH_PXA
219struct ssp_device *pxa_ssp_request(int port, const char *label); 223struct ssp_device *pxa_ssp_request(int port, const char *label);
220void pxa_ssp_free(struct ssp_device *); 224void pxa_ssp_free(struct ssp_device *);
225struct ssp_device *pxa_ssp_request_of(const struct device_node *of_node,
226 const char *label);
221#else 227#else
222static inline struct ssp_device *pxa_ssp_request(int port, const char *label) 228static inline struct ssp_device *pxa_ssp_request(int port, const char *label)
223{ 229{
224 return NULL; 230 return NULL;
225} 231}
232static inline struct ssp_device *pxa_ssp_request_of(const struct device_node *n,
233 const char *name)
234{
235 return NULL;
236}
226static inline void pxa_ssp_free(struct ssp_device *ssp) {} 237static inline void pxa_ssp_free(struct ssp_device *ssp) {}
227#endif 238#endif
228 239
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 2fd3d251d9a5..56e818e4a1cb 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -6,13 +6,6 @@
6 6
7/* PCM */ 7/* PCM */
8 8
9struct pxa2xx_pcm_dma_params {
10 char *name; /* stream identifier */
11 u32 dcmd; /* DMA descriptor dcmd field */
12 volatile u32 *drcmr; /* the DMA request channel to use */
13 u32 dev_addr; /* device physical address for DMA */
14};
15
16extern int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, 9extern int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
17 struct snd_pcm_hw_params *params); 10 struct snd_pcm_hw_params *params);
18extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream); 11extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h
new file mode 100644
index 000000000000..d35412ae03b3
--- /dev/null
+++ b/include/sound/rcar_snd.h
@@ -0,0 +1,84 @@
1/*
2 * Renesas R-Car SRU/SCU/SSIU/SSI support
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * 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
12#ifndef RCAR_SND_H
13#define RCAR_SND_H
14
15#include <linux/sh_clk.h>
16
17#define RSND_GEN1_SRU 0
18#define RSND_GEN1_ADG 1
19#define RSND_GEN1_SSI 2
20
21#define RSND_GEN2_SRU 0
22#define RSND_GEN2_ADG 1
23#define RSND_GEN2_SSIU 2
24#define RSND_GEN2_SSI 3
25
26#define RSND_BASE_MAX 4
27
28/*
29 * flags
30 *
31 * 0xAB000000
32 *
33 * A : clock sharing settings
34 * B : SSI direction
35 */
36#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
37#define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */
38#define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */
39#define RSND_SSI_DEPENDENT (1 << 28) /* SSI needs SRU/SCU */
40
41#define RSND_SSI_PLAY (1 << 24)
42
43#define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \
44{ .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
45#define RSND_SSI_UNUSED \
46{ .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 }
47
48struct rsnd_ssi_platform_info {
49 int dai_id;
50 int dma_id;
51 int pio_irq;
52 u32 flags;
53};
54
55/*
56 * flags
57 */
58#define RSND_SCU_USB_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */
59
60struct rsnd_scu_platform_info {
61 u32 flags;
62};
63
64/*
65 * flags
66 *
67 * 0x0000000A
68 *
69 * A : generation
70 */
71#define RSND_GEN1 (1 << 0) /* fixme */
72#define RSND_GEN2 (2 << 0) /* fixme */
73
74struct rcar_snd_info {
75 u32 flags;
76 struct rsnd_ssi_platform_info *ssi_info;
77 int ssi_info_nr;
78 struct rsnd_scu_platform_info *scu_info;
79 int scu_info_nr;
80 int (*start)(int id);
81 int (*stop)(int id);
82};
83
84#endif
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 3e479f4e15f5..c728d28ae9a5 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -70,121 +70,144 @@ struct device;
70 .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ 70 .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
71 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} 71 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
72 72
73#define SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) \
74 .reg = wreg, .mask = 1, .shift = wshift, \
75 .on_val = winvert ? 0 : 1, .off_val = winvert ? 1 : 0
76
73/* path domain */ 77/* path domain */
74#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\ 78#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
75 wcontrols, wncontrols) \ 79 wcontrols, wncontrols) \
76{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 80{ .id = snd_soc_dapm_pga, .name = wname, \
77 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} 81 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
82 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
78#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\ 83#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\
79 wcontrols, wncontrols) \ 84 wcontrols, wncontrols) \
80{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \ 85{ .id = snd_soc_dapm_out_drv, .name = wname, \
81 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} 86 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
87 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
82#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \ 88#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
83 wcontrols, wncontrols)\ 89 wcontrols, wncontrols)\
84{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 90{ .id = snd_soc_dapm_mixer, .name = wname, \
85 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} 91 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
92 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
86#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \ 93#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
87 wcontrols, wncontrols)\ 94 wcontrols, wncontrols)\
88{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \ 95{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
89 .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ 96 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
90 .num_kcontrols = wncontrols} 97 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
91#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ 98#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
92{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ 99{ .id = snd_soc_dapm_micbias, .name = wname, \
93 .invert = winvert, .kcontrol_news = NULL, .num_kcontrols = 0} 100 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
101 .kcontrol_news = NULL, .num_kcontrols = 0}
94#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \ 102#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
95{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \ 103{ .id = snd_soc_dapm_switch, .name = wname, \
96 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} 104 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
105 .kcontrol_news = wcontrols, .num_kcontrols = 1}
97#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \ 106#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
98{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \ 107{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
99 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} 108 .kcontrol_news = wcontrols, .num_kcontrols = 1}
100#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \ 109#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
101{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \ 110{ .id = snd_soc_dapm_virt_mux, .name = wname, \
102 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} 111 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
112 .kcontrol_news = wcontrols, .num_kcontrols = 1}
103#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ 113#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
104{ .id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \ 114{ .id = snd_soc_dapm_value_mux, .name = wname, \
105 .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ 115 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
106 .num_kcontrols = 1} 116 .kcontrol_news = wcontrols, .num_kcontrols = 1}
107 117
108/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ 118/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
109#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ 119#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
110 wcontrols) \ 120 wcontrols) \
111{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 121{ .id = snd_soc_dapm_pga, .name = wname, \
112 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} 122 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
123 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
113#define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \ 124#define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \
114 wcontrols)\ 125 wcontrols)\
115{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 126{ .id = snd_soc_dapm_mixer, .name = wname, \
116 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} 127 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
128 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
117#define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \ 129#define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \
118 wcontrols)\ 130 wcontrols)\
119{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \ 131{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
120 .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ 132 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
121 .num_kcontrols = ARRAY_SIZE(wcontrols)} 133 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
122 134
123/* path domain with event - event handler must return 0 for success */ 135/* path domain with event - event handler must return 0 for success */
124#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \ 136#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
125 wncontrols, wevent, wflags) \ 137 wncontrols, wevent, wflags) \
126{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 138{ .id = snd_soc_dapm_pga, .name = wname, \
127 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ 139 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
140 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
128 .event = wevent, .event_flags = wflags} 141 .event = wevent, .event_flags = wflags}
129#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \ 142#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
130 wncontrols, wevent, wflags) \ 143 wncontrols, wevent, wflags) \
131{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \ 144{ .id = snd_soc_dapm_out_drv, .name = wname, \
132 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ 145 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
146 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
133 .event = wevent, .event_flags = wflags} 147 .event = wevent, .event_flags = wflags}
134#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \ 148#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
135 wncontrols, wevent, wflags) \ 149 wncontrols, wevent, wflags) \
136{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 150{ .id = snd_soc_dapm_mixer, .name = wname, \
137 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ 151 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
152 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
138 .event = wevent, .event_flags = wflags} 153 .event = wevent, .event_flags = wflags}
139#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \ 154#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
140 wcontrols, wncontrols, wevent, wflags) \ 155 wcontrols, wncontrols, wevent, wflags) \
141{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 156{ .id = snd_soc_dapm_mixer, .name = wname, \
142 .invert = winvert, .kcontrol_news = wcontrols, \ 157 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
158 .kcontrol_news = wcontrols, \
143 .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags} 159 .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
144#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \ 160#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
145 wevent, wflags) \ 161 wevent, wflags) \
146{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \ 162{ .id = snd_soc_dapm_switch, .name = wname, \
147 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ 163 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
164 .kcontrol_news = wcontrols, .num_kcontrols = 1, \
148 .event = wevent, .event_flags = wflags} 165 .event = wevent, .event_flags = wflags}
149#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ 166#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
150 wevent, wflags) \ 167 wevent, wflags) \
151{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \ 168{ .id = snd_soc_dapm_mux, .name = wname, \
152 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ 169 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
170 .kcontrol_news = wcontrols, .num_kcontrols = 1, \
153 .event = wevent, .event_flags = wflags} 171 .event = wevent, .event_flags = wflags}
154#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ 172#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
155 wevent, wflags) \ 173 wevent, wflags) \
156{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \ 174{ .id = snd_soc_dapm_virt_mux, .name = wname, \
157 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ 175 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
176 .kcontrol_news = wcontrols, .num_kcontrols = 1, \
158 .event = wevent, .event_flags = wflags} 177 .event = wevent, .event_flags = wflags}
159 178
160/* additional sequencing control within an event type */ 179/* additional sequencing control within an event type */
161#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ 180#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
162 wevent, wflags) \ 181 wevent, wflags) \
163{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 182{ .id = snd_soc_dapm_pga, .name = wname, \
164 .invert = winvert, .event = wevent, .event_flags = wflags, \ 183 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
184 .event = wevent, .event_flags = wflags, \
165 .subseq = wsubseq} 185 .subseq = wsubseq}
166#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \ 186#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
167 wflags) \ 187 wflags) \
168{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ 188{ .id = snd_soc_dapm_supply, .name = wname, \
169 .shift = wshift, .invert = winvert, .event = wevent, \ 189 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
170 .event_flags = wflags, .subseq = wsubseq} 190 .event = wevent, .event_flags = wflags, .subseq = wsubseq}
171 191
172/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ 192/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
173#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ 193#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
174 wevent, wflags) \ 194 wevent, wflags) \
175{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 195{ .id = snd_soc_dapm_pga, .name = wname, \
176 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ 196 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
197 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
177 .event = wevent, .event_flags = wflags} 198 .event = wevent, .event_flags = wflags}
178#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ 199#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
179 wevent, wflags) \ 200 wevent, wflags) \
180{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 201{ .id = snd_soc_dapm_mixer, .name = wname, \
181 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ 202 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
203 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
182 .event = wevent, .event_flags = wflags} 204 .event = wevent, .event_flags = wflags}
183#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \ 205#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \
184 wcontrols, wevent, wflags) \ 206 wcontrols, wevent, wflags) \
185{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 207{ .id = snd_soc_dapm_mixer, .name = wname, \
186 .invert = winvert, .kcontrol_news = wcontrols, \ 208 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
187 .num_kcontrols = ARRAY_SIZE(wcontrols), .event = wevent, .event_flags = wflags} 209 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
210 .event = wevent, .event_flags = wflags}
188 211
189/* events that are pre and post DAPM */ 212/* events that are pre and post DAPM */
190#define SND_SOC_DAPM_PRE(wname, wevent) \ 213#define SND_SOC_DAPM_PRE(wname, wevent) \
@@ -199,35 +222,36 @@ struct device;
199/* stream domain */ 222/* stream domain */
200#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \ 223#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
201{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ 224{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
202 .reg = wreg, .shift = wshift, .invert = winvert } 225 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
203#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \ 226#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
204 wevent, wflags) \ 227 wevent, wflags) \
205{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ 228{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
206 .reg = wreg, .shift = wshift, .invert = winvert, \ 229 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
207 .event = wevent, .event_flags = wflags } 230 .event = wevent, .event_flags = wflags }
208#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \ 231#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
209{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ 232{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
210 .reg = wreg, .shift = wshift, .invert = winvert } 233 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
211#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \ 234#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
212 wevent, wflags) \ 235 wevent, wflags) \
213{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ 236{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
214 .reg = wreg, .shift = wshift, .invert = winvert, \ 237 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
215 .event = wevent, .event_flags = wflags } 238 .event = wevent, .event_flags = wflags }
216#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ 239#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
217{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ 240{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
218 .shift = wshift, .invert = winvert} 241 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) }
219#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \ 242#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
220 wevent, wflags) \ 243 wevent, wflags) \
221{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ 244{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
222 .shift = wshift, .invert = winvert, \ 245 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
223 .event = wevent, .event_flags = wflags} 246 .event = wevent, .event_flags = wflags}
247
224#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \ 248#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
225{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ 249{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
226 .shift = wshift, .invert = winvert} 250 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
227#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \ 251#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
228 wevent, wflags) \ 252 wevent, wflags) \
229{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ 253{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
230 .shift = wshift, .invert = winvert, \ 254 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
231 .event = wevent, .event_flags = wflags} 255 .event = wevent, .event_flags = wflags}
232#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \ 256#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
233{ .id = snd_soc_dapm_clock_supply, .name = wname, \ 257{ .id = snd_soc_dapm_clock_supply, .name = wname, \
@@ -241,14 +265,14 @@ struct device;
241 .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \ 265 .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
242 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} 266 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
243#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \ 267#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
244{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ 268{ .id = snd_soc_dapm_supply, .name = wname, \
245 .shift = wshift, .invert = winvert, .event = wevent, \ 269 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
246 .event_flags = wflags} 270 .event = wevent, .event_flags = wflags}
247#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ 271#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \
248{ .id = snd_soc_dapm_regulator_supply, .name = wname, \ 272{ .id = snd_soc_dapm_regulator_supply, .name = wname, \
249 .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ 273 .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
250 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ 274 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \
251 .invert = wflags} 275 .on_val = wflags}
252 276
253 277
254/* dapm kcontrol types */ 278/* dapm kcontrol types */
@@ -256,14 +280,26 @@ struct device;
256{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 280{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
257 .info = snd_soc_info_volsw, \ 281 .info = snd_soc_info_volsw, \
258 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ 282 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
259 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 283 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
284#define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \
285{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
286 .info = snd_soc_info_volsw, \
287 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
288 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
260#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ 289#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
261{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 290{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
262 .info = snd_soc_info_volsw, \ 291 .info = snd_soc_info_volsw, \
263 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ 292 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
264 .tlv.p = (tlv_array), \ 293 .tlv.p = (tlv_array), \
265 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ 294 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
266 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 295 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
296#define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \
297{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
298 .info = snd_soc_info_volsw, \
299 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
300 .tlv.p = (tlv_array), \
301 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
302 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
267#define SOC_DAPM_ENUM(xname, xenum) \ 303#define SOC_DAPM_ENUM(xname, xenum) \
268{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 304{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
269 .info = snd_soc_info_enum_double, \ 305 .info = snd_soc_info_enum_double, \
@@ -333,6 +369,7 @@ struct snd_soc_dapm_route;
333struct snd_soc_dapm_context; 369struct snd_soc_dapm_context;
334struct regulator; 370struct regulator;
335struct snd_soc_dapm_widget_list; 371struct snd_soc_dapm_widget_list;
372struct snd_soc_dapm_update;
336 373
337int dapm_reg_event(struct snd_soc_dapm_widget *w, 374int dapm_reg_event(struct snd_soc_dapm_widget *w,
338 struct snd_kcontrol *kcontrol, int event); 375 struct snd_kcontrol *kcontrol, int event);
@@ -391,10 +428,12 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
391void snd_soc_dapm_shutdown(struct snd_soc_card *card); 428void snd_soc_dapm_shutdown(struct snd_soc_card *card);
392 429
393/* external DAPM widget events */ 430/* external DAPM widget events */
394int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 431int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
395 struct snd_kcontrol *kcontrol, int connect); 432 struct snd_kcontrol *kcontrol, int connect,
396int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 433 struct snd_soc_dapm_update *update);
397 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e); 434int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
435 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
436 struct snd_soc_dapm_update *update);
398 437
399/* dapm sys fs - used by the core */ 438/* dapm sys fs - used by the core */
400int snd_soc_dapm_sys_add(struct device *dev); 439int snd_soc_dapm_sys_add(struct device *dev);
@@ -424,6 +463,8 @@ void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
424int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, 463int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
425 struct snd_soc_dapm_widget_list **list); 464 struct snd_soc_dapm_widget_list **list);
426 465
466struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
467
427/* dapm widget types */ 468/* dapm widget types */
428enum snd_soc_dapm_type { 469enum snd_soc_dapm_type {
429 snd_soc_dapm_input = 0, /* input pin */ 470 snd_soc_dapm_input = 0, /* input pin */
@@ -455,6 +496,7 @@ enum snd_soc_dapm_type {
455 snd_soc_dapm_dai_in, /* link to DAI structure */ 496 snd_soc_dapm_dai_in, /* link to DAI structure */
456 snd_soc_dapm_dai_out, 497 snd_soc_dapm_dai_out,
457 snd_soc_dapm_dai_link, /* link between two DAI structures */ 498 snd_soc_dapm_dai_link, /* link between two DAI structures */
499 snd_soc_dapm_kcontrol, /* Auto-disabled kcontrol */
458}; 500};
459 501
460enum snd_soc_dapm_subclass { 502enum snd_soc_dapm_subclass {
@@ -485,7 +527,6 @@ struct snd_soc_dapm_path {
485 /* source (input) and sink (output) widgets */ 527 /* source (input) and sink (output) widgets */
486 struct snd_soc_dapm_widget *source; 528 struct snd_soc_dapm_widget *source;
487 struct snd_soc_dapm_widget *sink; 529 struct snd_soc_dapm_widget *sink;
488 struct snd_kcontrol *kcontrol;
489 530
490 /* status */ 531 /* status */
491 u32 connect:1; /* source and sink widgets are connected */ 532 u32 connect:1; /* source and sink widgets are connected */
@@ -498,6 +539,7 @@ struct snd_soc_dapm_path {
498 539
499 struct list_head list_source; 540 struct list_head list_source;
500 struct list_head list_sink; 541 struct list_head list_sink;
542 struct list_head list_kcontrol;
501 struct list_head list; 543 struct list_head list;
502}; 544};
503 545
@@ -518,12 +560,10 @@ struct snd_soc_dapm_widget {
518 /* dapm control */ 560 /* dapm control */
519 int reg; /* negative reg = no direct dapm */ 561 int reg; /* negative reg = no direct dapm */
520 unsigned char shift; /* bits to shift */ 562 unsigned char shift; /* bits to shift */
521 unsigned int value; /* widget current value */
522 unsigned int mask; /* non-shifted mask */ 563 unsigned int mask; /* non-shifted mask */
523 unsigned int on_val; /* on state value */ 564 unsigned int on_val; /* on state value */
524 unsigned int off_val; /* off state value */ 565 unsigned int off_val; /* off state value */
525 unsigned char power:1; /* block power status */ 566 unsigned char power:1; /* block power status */
526 unsigned char invert:1; /* invert the power bit */
527 unsigned char active:1; /* active stream on DAC, ADC's */ 567 unsigned char active:1; /* active stream on DAC, ADC's */
528 unsigned char connected:1; /* connected codec pin */ 568 unsigned char connected:1; /* connected codec pin */
529 unsigned char new:1; /* cnew complete */ 569 unsigned char new:1; /* cnew complete */
@@ -559,7 +599,6 @@ struct snd_soc_dapm_widget {
559}; 599};
560 600
561struct snd_soc_dapm_update { 601struct snd_soc_dapm_update {
562 struct snd_soc_dapm_widget *widget;
563 struct snd_kcontrol *kcontrol; 602 struct snd_kcontrol *kcontrol;
564 int reg; 603 int reg;
565 int mask; 604 int mask;
@@ -573,8 +612,6 @@ struct snd_soc_dapm_context {
573 struct delayed_work delayed_work; 612 struct delayed_work delayed_work;
574 unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ 613 unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
575 614
576 struct snd_soc_dapm_update *update;
577
578 void (*seq_notifier)(struct snd_soc_dapm_context *, 615 void (*seq_notifier)(struct snd_soc_dapm_context *,
579 enum snd_soc_dapm_type, int); 616 enum snd_soc_dapm_type, int);
580 617
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
index 04598f1efd77..047d657c331c 100644
--- a/include/sound/soc-dpcm.h
+++ b/include/sound/soc-dpcm.h
@@ -133,6 +133,6 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
133/* internal use only */ 133/* internal use only */
134int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); 134int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
135int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); 135int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
136int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *); 136int soc_dpcm_runtime_update(struct snd_soc_card *);
137 137
138#endif 138#endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 6eabee7ec15a..8e2ad52078b6 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -30,13 +30,13 @@
30/* 30/*
31 * Convenience kcontrol builders 31 * Convenience kcontrol builders
32 */ 32 */
33#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \ 33#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \
34 ((unsigned long)&(struct soc_mixer_control) \ 34 ((unsigned long)&(struct soc_mixer_control) \
35 {.reg = xreg, .rreg = xreg, .shift = shift_left, \ 35 {.reg = xreg, .rreg = xreg, .shift = shift_left, \
36 .rshift = shift_right, .max = xmax, .platform_max = xmax, \ 36 .rshift = shift_right, .max = xmax, .platform_max = xmax, \
37 .invert = xinvert}) 37 .invert = xinvert, .autodisable = xautodisable})
38#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ 38#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \
39 SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert) 39 SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable)
40#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ 40#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
41 ((unsigned long)&(struct soc_mixer_control) \ 41 ((unsigned long)&(struct soc_mixer_control) \
42 {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert}) 42 {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
@@ -52,7 +52,7 @@
52{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 52{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
53 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ 53 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
54 .put = snd_soc_put_volsw, \ 54 .put = snd_soc_put_volsw, \
55 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 55 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
56#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ 56#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
57{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 57{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
58 .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ 58 .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
@@ -68,7 +68,7 @@
68 .tlv.p = (tlv_array), \ 68 .tlv.p = (tlv_array), \
69 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ 69 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
70 .put = snd_soc_put_volsw, \ 70 .put = snd_soc_put_volsw, \
71 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 71 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
72#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \ 72#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
73{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 73{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
74 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 74 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@@ -97,7 +97,7 @@
97 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ 97 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
98 .put = snd_soc_put_volsw, \ 98 .put = snd_soc_put_volsw, \
99 .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ 99 .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
100 max, invert) } 100 max, invert, 0) }
101#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ 101#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
102{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 102{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
103 .info = snd_soc_info_volsw, \ 103 .info = snd_soc_info_volsw, \
@@ -119,7 +119,7 @@
119 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ 119 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
120 .put = snd_soc_put_volsw, \ 120 .put = snd_soc_put_volsw, \
121 .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ 121 .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
122 max, invert) } 122 max, invert, 0) }
123#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ 123#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
124{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 124{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
125 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ 125 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -190,14 +190,14 @@
190{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 190{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
191 .info = snd_soc_info_volsw, \ 191 .info = snd_soc_info_volsw, \
192 .get = xhandler_get, .put = xhandler_put, \ 192 .get = xhandler_get, .put = xhandler_put, \
193 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } 193 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
194#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\ 194#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
195 xhandler_get, xhandler_put) \ 195 xhandler_get, xhandler_put) \
196{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 196{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
197 .info = snd_soc_info_volsw, \ 197 .info = snd_soc_info_volsw, \
198 .get = xhandler_get, .put = xhandler_put, \ 198 .get = xhandler_get, .put = xhandler_put, \
199 .private_value = \ 199 .private_value = \
200 SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) } 200 SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) }
201#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ 201#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
202 xhandler_get, xhandler_put, tlv_array) \ 202 xhandler_get, xhandler_put, tlv_array) \
203{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 203{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -206,7 +206,7 @@
206 .tlv.p = (tlv_array), \ 206 .tlv.p = (tlv_array), \
207 .info = snd_soc_info_volsw, \ 207 .info = snd_soc_info_volsw, \
208 .get = xhandler_get, .put = xhandler_put, \ 208 .get = xhandler_get, .put = xhandler_put, \
209 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } 209 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
210#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ 210#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
211 xhandler_get, xhandler_put, tlv_array) \ 211 xhandler_get, xhandler_put, tlv_array) \
212{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 212{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -216,7 +216,7 @@
216 .info = snd_soc_info_volsw, \ 216 .info = snd_soc_info_volsw, \
217 .get = xhandler_get, .put = xhandler_put, \ 217 .get = xhandler_get, .put = xhandler_put, \
218 .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ 218 .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
219 xmax, xinvert) } 219 xmax, xinvert, 0) }
220#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ 220#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
221 xhandler_get, xhandler_put, tlv_array) \ 221 xhandler_get, xhandler_put, tlv_array) \
222{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 222{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -234,7 +234,7 @@
234 .private_value = xdata } 234 .private_value = xdata }
235#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \ 235#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
236{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 236{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
237 .info = snd_soc_info_enum_ext, \ 237 .info = snd_soc_info_enum_double, \
238 .get = xhandler_get, .put = xhandler_put, \ 238 .get = xhandler_get, .put = xhandler_put, \
239 .private_value = (unsigned long)&xenum } 239 .private_value = (unsigned long)&xenum }
240 240
@@ -468,6 +468,8 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
468void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); 468void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
469 469
470int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); 470int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
471int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
472 struct platform_device *pdev);
471 473
472/* 474/*
473 *Controls 475 *Controls
@@ -475,6 +477,8 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
475struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, 477struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
476 void *data, const char *long_name, 478 void *data, const char *long_name,
477 const char *prefix); 479 const char *prefix);
480struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
481 const char *name);
478int snd_soc_add_codec_controls(struct snd_soc_codec *codec, 482int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
479 const struct snd_kcontrol_new *controls, int num_controls); 483 const struct snd_kcontrol_new *controls, int num_controls);
480int snd_soc_add_platform_controls(struct snd_soc_platform *platform, 484int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
@@ -485,8 +489,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
485 const struct snd_kcontrol_new *controls, int num_controls); 489 const struct snd_kcontrol_new *controls, int num_controls);
486int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, 490int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
487 struct snd_ctl_elem_info *uinfo); 491 struct snd_ctl_elem_info *uinfo);
488int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
489 struct snd_ctl_elem_info *uinfo);
490int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, 492int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
491 struct snd_ctl_elem_value *ucontrol); 493 struct snd_ctl_elem_value *ucontrol);
492int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, 494int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
@@ -497,8 +499,6 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
497 struct snd_ctl_elem_value *ucontrol); 499 struct snd_ctl_elem_value *ucontrol);
498int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, 500int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
499 struct snd_ctl_elem_info *uinfo); 501 struct snd_ctl_elem_info *uinfo);
500int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
501 struct snd_ctl_elem_info *uinfo);
502#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info 502#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
503int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, 503int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
504 struct snd_ctl_elem_value *ucontrol); 504 struct snd_ctl_elem_value *ucontrol);
@@ -1042,6 +1042,7 @@ struct snd_soc_card {
1042 /* Generic DAPM context for the card */ 1042 /* Generic DAPM context for the card */
1043 struct snd_soc_dapm_context dapm; 1043 struct snd_soc_dapm_context dapm;
1044 struct snd_soc_dapm_stats dapm_stats; 1044 struct snd_soc_dapm_stats dapm_stats;
1045 struct snd_soc_dapm_update *update;
1045 1046
1046#ifdef CONFIG_DEBUG_FS 1047#ifdef CONFIG_DEBUG_FS
1047 struct dentry *debugfs_card_root; 1048 struct dentry *debugfs_card_root;
@@ -1087,7 +1088,9 @@ struct snd_soc_pcm_runtime {
1087/* mixer control */ 1088/* mixer control */
1088struct soc_mixer_control { 1089struct soc_mixer_control {
1089 int min, max, platform_max; 1090 int min, max, platform_max;
1090 unsigned int reg, rreg, shift, rshift, invert; 1091 unsigned int reg, rreg, shift, rshift;
1092 unsigned int invert:1;
1093 unsigned int autodisable:1;
1091}; 1094};
1092 1095
1093struct soc_bytes { 1096struct soc_bytes {
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index ce431e6e07cf..5066a3768b28 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -14,12 +14,14 @@
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/dmaengine.h>
17 18
18#include <sound/core.h> 19#include <sound/core.h>
19#include <sound/pcm.h> 20#include <sound/pcm.h>
20#include <sound/ac97_codec.h> 21#include <sound/ac97_codec.h>
21#include <sound/initval.h> 22#include <sound/initval.h>
22#include <sound/pxa2xx-lib.h> 23#include <sound/pxa2xx-lib.h>
24#include <sound/dmaengine_pcm.h>
23 25
24#include <mach/regs-ac97.h> 26#include <mach/regs-ac97.h>
25#include <mach/audio.h> 27#include <mach/audio.h>
@@ -41,20 +43,20 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
41 .reset = pxa2xx_ac97_reset, 43 .reset = pxa2xx_ac97_reset,
42}; 44};
43 45
44static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = { 46static unsigned long pxa2xx_ac97_pcm_out_req = 12;
45 .name = "AC97 PCM out", 47static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_out = {
46 .dev_addr = __PREG(PCDR), 48 .addr = __PREG(PCDR),
47 .drcmr = &DRCMR(12), 49 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
48 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 50 .maxburst = 32,
49 DCMD_BURST32 | DCMD_WIDTH4, 51 .filter_data = &pxa2xx_ac97_pcm_out_req,
50}; 52};
51 53
52static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = { 54static unsigned long pxa2xx_ac97_pcm_in_req = 11;
53 .name = "AC97 PCM in", 55static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_in = {
54 .dev_addr = __PREG(PCDR), 56 .addr = __PREG(PCDR),
55 .drcmr = &DRCMR(11), 57 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
56 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 58 .maxburst = 32,
57 DCMD_BURST32 | DCMD_WIDTH4, 59 .filter_data = &pxa2xx_ac97_pcm_in_req,
58}; 60};
59 61
60static struct snd_pcm *pxa2xx_ac97_pcm; 62static struct snd_pcm *pxa2xx_ac97_pcm;
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index 823359ed95e1..a61d7a9a995e 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -7,11 +7,13 @@
7#include <linux/slab.h> 7#include <linux/slab.h>
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/dma-mapping.h> 9#include <linux/dma-mapping.h>
10#include <linux/dmaengine.h>
10 11
11#include <sound/core.h> 12#include <sound/core.h>
12#include <sound/pcm.h> 13#include <sound/pcm.h>
13#include <sound/pcm_params.h> 14#include <sound/pcm_params.h>
14#include <sound/pxa2xx-lib.h> 15#include <sound/pxa2xx-lib.h>
16#include <sound/dmaengine_pcm.h>
15 17
16#include <mach/dma.h> 18#include <mach/dma.h>
17 19
@@ -43,6 +45,35 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
43 size_t period = params_period_bytes(params); 45 size_t period = params_period_bytes(params);
44 pxa_dma_desc *dma_desc; 46 pxa_dma_desc *dma_desc;
45 dma_addr_t dma_buff_phys, next_desc_phys; 47 dma_addr_t dma_buff_phys, next_desc_phys;
48 u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
49
50 /* temporary transition hack */
51 switch (rtd->params->addr_width) {
52 case DMA_SLAVE_BUSWIDTH_1_BYTE:
53 dcmd |= DCMD_WIDTH1;
54 break;
55 case DMA_SLAVE_BUSWIDTH_2_BYTES:
56 dcmd |= DCMD_WIDTH2;
57 break;
58 case DMA_SLAVE_BUSWIDTH_4_BYTES:
59 dcmd |= DCMD_WIDTH4;
60 break;
61 default:
62 /* can't happen */
63 break;
64 }
65
66 switch (rtd->params->maxburst) {
67 case 8:
68 dcmd |= DCMD_BURST8;
69 break;
70 case 16:
71 dcmd |= DCMD_BURST16;
72 break;
73 case 32:
74 dcmd |= DCMD_BURST32;
75 break;
76 }
46 77
47 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 78 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
48 runtime->dma_bytes = totsize; 79 runtime->dma_bytes = totsize;
@@ -55,14 +86,14 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
55 dma_desc->ddadr = next_desc_phys; 86 dma_desc->ddadr = next_desc_phys;
56 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 87 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
57 dma_desc->dsadr = dma_buff_phys; 88 dma_desc->dsadr = dma_buff_phys;
58 dma_desc->dtadr = rtd->params->dev_addr; 89 dma_desc->dtadr = rtd->params->addr;
59 } else { 90 } else {
60 dma_desc->dsadr = rtd->params->dev_addr; 91 dma_desc->dsadr = rtd->params->addr;
61 dma_desc->dtadr = dma_buff_phys; 92 dma_desc->dtadr = dma_buff_phys;
62 } 93 }
63 if (period > totsize) 94 if (period > totsize)
64 period = totsize; 95 period = totsize;
65 dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN; 96 dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN;
66 dma_desc++; 97 dma_desc++;
67 dma_buff_phys += period; 98 dma_buff_phys += period;
68 } while (totsize -= period); 99 } while (totsize -= period);
@@ -76,8 +107,10 @@ int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
76{ 107{
77 struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; 108 struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
78 109
79 if (rtd && rtd->params && rtd->params->drcmr) 110 if (rtd && rtd->params && rtd->params->filter_data) {
80 *rtd->params->drcmr = 0; 111 unsigned long req = *(unsigned long *) rtd->params->filter_data;
112 DRCMR(req) = 0;
113 }
81 114
82 snd_pcm_set_runtime_buffer(substream, NULL); 115 snd_pcm_set_runtime_buffer(substream, NULL);
83 return 0; 116 return 0;
@@ -136,6 +169,7 @@ EXPORT_SYMBOL(pxa2xx_pcm_pointer);
136int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) 169int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
137{ 170{
138 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 171 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
172 unsigned long req;
139 173
140 if (!prtd || !prtd->params) 174 if (!prtd || !prtd->params)
141 return 0; 175 return 0;
@@ -146,7 +180,8 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
146 DCSR(prtd->dma_ch) &= ~DCSR_RUN; 180 DCSR(prtd->dma_ch) &= ~DCSR_RUN;
147 DCSR(prtd->dma_ch) = 0; 181 DCSR(prtd->dma_ch) = 0;
148 DCMD(prtd->dma_ch) = 0; 182 DCMD(prtd->dma_ch) = 0;
149 *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD; 183 req = *(unsigned long *) prtd->params->filter_data;
184 DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD;
150 185
151 return 0; 186 return 0;
152} 187}
@@ -155,7 +190,6 @@ EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
155void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) 190void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
156{ 191{
157 struct snd_pcm_substream *substream = dev_id; 192 struct snd_pcm_substream *substream = dev_id;
158 struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
159 int dcsr; 193 int dcsr;
160 194
161 dcsr = DCSR(dma_ch); 195 dcsr = DCSR(dma_ch);
@@ -164,8 +198,8 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
164 if (dcsr & DCSR_ENDINTR) { 198 if (dcsr & DCSR_ENDINTR) {
165 snd_pcm_period_elapsed(substream); 199 snd_pcm_period_elapsed(substream);
166 } else { 200 } else {
167 printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", 201 printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
168 rtd->params->name, dma_ch, dcsr); 202 dma_ch, dcsr);
169 snd_pcm_stream_lock(substream); 203 snd_pcm_stream_lock(substream);
170 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); 204 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
171 snd_pcm_stream_unlock(substream); 205 snd_pcm_stream_unlock(substream);
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index 26422a3584ea..69a2455b4472 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -11,8 +11,11 @@
11 */ 11 */
12 12
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/dmaengine.h>
15
14#include <sound/core.h> 16#include <sound/core.h>
15#include <sound/pxa2xx-lib.h> 17#include <sound/pxa2xx-lib.h>
18#include <sound/dmaengine_pcm.h>
16 19
17#include "pxa2xx-pcm.h" 20#include "pxa2xx-pcm.h"
18 21
@@ -40,7 +43,7 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
40 43
41 rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 44 rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
42 client->playback_params : client->capture_params; 45 client->playback_params : client->capture_params;
43 ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW, 46 ret = pxa_request_dma("dma", DMA_PRIO_LOW,
44 pxa2xx_pcm_dma_irq, substream); 47 pxa2xx_pcm_dma_irq, substream);
45 if (ret < 0) 48 if (ret < 0)
46 goto err2; 49 goto err2;
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h
index 65f86b56ba42..2a8fc08d52a1 100644
--- a/sound/arm/pxa2xx-pcm.h
+++ b/sound/arm/pxa2xx-pcm.h
@@ -13,14 +13,14 @@
13 13
14struct pxa2xx_runtime_data { 14struct pxa2xx_runtime_data {
15 int dma_ch; 15 int dma_ch;
16 struct pxa2xx_pcm_dma_params *params; 16 struct snd_dmaengine_dai_dma_data *params;
17 pxa_dma_desc *dma_desc_array; 17 pxa_dma_desc *dma_desc_array;
18 dma_addr_t dma_desc_array_phys; 18 dma_addr_t dma_desc_array_phys;
19}; 19};
20 20
21struct pxa2xx_pcm_client { 21struct pxa2xx_pcm_client {
22 struct pxa2xx_pcm_dma_params *playback_params; 22 struct snd_dmaengine_dai_dma_data *playback_params;
23 struct pxa2xx_pcm_dma_params *capture_params; 23 struct snd_dmaengine_dai_dma_data *capture_params;
24 int (*startup)(struct snd_pcm_substream *); 24 int (*startup)(struct snd_pcm_substream *);
25 void (*shutdown)(struct snd_pcm_substream *); 25 void (*shutdown)(struct snd_pcm_substream *);
26 int (*prepare)(struct snd_pcm_substream *); 26 int (*prepare)(struct snd_pcm_substream *);
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index c0c2f57a0d6f..313f22e9d929 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -6,6 +6,9 @@ config SND_PCM
6 tristate 6 tristate
7 select SND_TIMER 7 select SND_TIMER
8 8
9config SND_DMAENGINE_PCM
10 tristate
11
9config SND_HWDEP 12config SND_HWDEP
10 tristate 13 tristate
11 14
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 43d4117428ac..5e890cfed423 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -13,6 +13,8 @@ snd-$(CONFIG_SND_JACK) += jack.o
13snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ 13snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
14 pcm_memory.o 14 pcm_memory.o
15 15
16snd-pcm-dmaengine-objs := pcm_dmaengine.o
17
16snd-page-alloc-y := memalloc.o 18snd-page-alloc-y := memalloc.o
17snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o 19snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
18 20
@@ -30,6 +32,7 @@ obj-$(CONFIG_SND_TIMER) += snd-timer.o
30obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o 32obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
31obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o 33obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
32obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o 34obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o
35obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o
33obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o 36obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
34 37
35obj-$(CONFIG_SND_OSSEMUL) += oss/ 38obj-$(CONFIG_SND_OSSEMUL) += oss/
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/core/pcm_dmaengine.c
index aa924d9b7986..aa924d9b7986 100644
--- a/sound/soc/soc-dmaengine-pcm.c
+++ b/sound/core/pcm_dmaengine.c
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 45eeaa9f7fec..5138b8493051 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -26,12 +26,9 @@ if SND_SOC
26config SND_SOC_AC97_BUS 26config SND_SOC_AC97_BUS
27 bool 27 bool
28 28
29config SND_SOC_DMAENGINE_PCM
30 bool
31
32config SND_SOC_GENERIC_DMAENGINE_PCM 29config SND_SOC_GENERIC_DMAENGINE_PCM
33 bool 30 bool
34 select SND_SOC_DMAENGINE_PCM 31 select SND_DMAENGINE_PCM
35 32
36# All the supported SoCs 33# All the supported SoCs
37source "sound/soc/atmel/Kconfig" 34source "sound/soc/atmel/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index bc0261476d7a..61a64d281905 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,10 +1,6 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o 1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
2snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o 2snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o
3 3
4ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
5snd-soc-core-objs += soc-dmaengine-pcm.o
6endif
7
8ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) 4ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
9snd-soc-core-objs += soc-generic-dmaengine-pcm.o 5snd-soc-core-objs += soc-generic-dmaengine-pcm.o
10endif 6endif
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 3fdd87fa18a9..e48d38a1b95c 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -13,6 +13,7 @@ config SND_ATMEL_SOC_PDC
13config SND_ATMEL_SOC_DMA 13config SND_ATMEL_SOC_DMA
14 tristate 14 tristate
15 depends on SND_ATMEL_SOC 15 depends on SND_ATMEL_SOC
16 select SND_SOC_GENERIC_DMAENGINE_PCM
16 17
17config SND_ATMEL_SOC_SSC 18config SND_ATMEL_SOC_SSC
18 tristate 19 tristate
@@ -32,6 +33,26 @@ config SND_AT91_SOC_SAM9G20_WM8731
32 Say Y if you want to add support for SoC audio on WM8731-based 33 Say Y if you want to add support for SoC audio on WM8731-based
33 AT91sam9g20 evaluation board. 34 AT91sam9g20 evaluation board.
34 35
36config SND_ATMEL_SOC_WM8904
37 tristate "Atmel ASoC driver for boards using WM8904 codec"
38 depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC
39 select SND_ATMEL_SOC_SSC
40 select SND_ATMEL_SOC_DMA
41 select SND_SOC_WM8904
42 help
43 Say Y if you want to add support for Atmel ASoC driver for boards using
44 WM8904 codec.
45
46config SND_AT91_SOC_SAM9X5_WM8731
47 tristate "SoC Audio support for WM8731-based at91sam9x5 board"
48 depends on ATMEL_SSC && SND_ATMEL_SOC && SOC_AT91SAM9X5
49 select SND_ATMEL_SOC_SSC
50 select SND_ATMEL_SOC_DMA
51 select SND_SOC_WM8731
52 help
53 Say Y if you want to add support for audio SoC on an
54 at91sam9x5 based board that is using WM8731 codec.
55
35config SND_AT91_SOC_AFEB9260 56config SND_AT91_SOC_AFEB9260
36 tristate "SoC Audio support for AFEB9260 board" 57 tristate "SoC Audio support for AFEB9260 board"
37 depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC 58 depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index 41967ccb6f41..5baabc8bde3a 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -11,6 +11,10 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
11 11
12# AT91 Machine Support 12# AT91 Machine Support
13snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o 13snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
14snd-atmel-soc-wm8904-objs := atmel_wm8904.o
15snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o
14 16
15obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o 17obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
18obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o
19obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o
16obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o 20obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
index d12826526798..06082e5e5dcb 100644
--- a/sound/soc/atmel/atmel-pcm-dma.c
+++ b/sound/soc/atmel/atmel-pcm-dma.c
@@ -91,138 +91,52 @@ static void atmel_pcm_dma_irq(u32 ssc_sr,
91 } 91 }
92} 92}
93 93
94/*--------------------------------------------------------------------------*\
95 * DMAENGINE operations
96\*--------------------------------------------------------------------------*/
97static bool filter(struct dma_chan *chan, void *slave)
98{
99 struct at_dma_slave *sl = slave;
100
101 if (sl->dma_dev == chan->device->dev) {
102 chan->private = sl;
103 return true;
104 } else {
105 return false;
106 }
107}
108
109static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, 94static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
110 struct snd_pcm_hw_params *params, struct atmel_pcm_dma_params *prtd) 95 struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config)
111{ 96{
97 struct snd_soc_pcm_runtime *rtd = substream->private_data;
98 struct atmel_pcm_dma_params *prtd;
112 struct ssc_device *ssc; 99 struct ssc_device *ssc;
113 struct dma_chan *dma_chan;
114 struct dma_slave_config slave_config;
115 int ret; 100 int ret;
116 101
102 prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
117 ssc = prtd->ssc; 103 ssc = prtd->ssc;
118 104
119 ret = snd_hwparams_to_dma_slave_config(substream, params, 105 ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
120 &slave_config);
121 if (ret) { 106 if (ret) {
122 pr_err("atmel-pcm: hwparams to dma slave configure failed\n"); 107 pr_err("atmel-pcm: hwparams to dma slave configure failed\n");
123 return ret; 108 return ret;
124 } 109 }
125 110
126 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 111 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
127 slave_config.dst_addr = (dma_addr_t)ssc->phybase + SSC_THR; 112 slave_config->dst_addr = ssc->phybase + SSC_THR;
128 slave_config.dst_maxburst = 1; 113 slave_config->dst_maxburst = 1;
129 } else { 114 } else {
130 slave_config.src_addr = (dma_addr_t)ssc->phybase + SSC_RHR; 115 slave_config->src_addr = ssc->phybase + SSC_RHR;
131 slave_config.src_maxburst = 1; 116 slave_config->src_maxburst = 1;
132 }
133
134 dma_chan = snd_dmaengine_pcm_get_chan(substream);
135 if (dmaengine_slave_config(dma_chan, &slave_config)) {
136 pr_err("atmel-pcm: failed to configure dma channel\n");
137 ret = -EBUSY;
138 return ret;
139 }
140
141 return 0;
142}
143
144static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
145 struct snd_pcm_hw_params *params)
146{
147 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct atmel_pcm_dma_params *prtd;
149 struct ssc_device *ssc;
150 struct at_dma_slave *sdata = NULL;
151 int ret;
152
153 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
154
155 prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
156 ssc = prtd->ssc;
157 if (ssc->pdev)
158 sdata = ssc->pdev->dev.platform_data;
159
160 ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
161 if (ret) {
162 pr_err("atmel-pcm: dmaengine pcm open failed\n");
163 return -EINVAL;
164 }
165
166 ret = atmel_pcm_configure_dma(substream, params, prtd);
167 if (ret) {
168 pr_err("atmel-pcm: failed to configure dmai\n");
169 goto err;
170 } 117 }
171 118
172 prtd->dma_intr_handler = atmel_pcm_dma_irq; 119 prtd->dma_intr_handler = atmel_pcm_dma_irq;
173 120
174 return 0; 121 return 0;
175err:
176 snd_dmaengine_pcm_close_release_chan(substream);
177 return ret;
178} 122}
179 123
180static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream) 124static const struct snd_dmaengine_pcm_config atmel_dmaengine_pcm_config = {
181{ 125 .prepare_slave_config = atmel_pcm_configure_dma,
182 struct snd_soc_pcm_runtime *rtd = substream->private_data; 126 .pcm_hardware = &atmel_pcm_dma_hardware,
183 struct atmel_pcm_dma_params *prtd; 127 .prealloc_buffer_size = ATMEL_SSC_DMABUF_SIZE,
184
185 prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
186
187 ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
188 ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
189
190 return 0;
191}
192
193static int atmel_pcm_open(struct snd_pcm_substream *substream)
194{
195 snd_soc_set_runtime_hwparams(substream, &atmel_pcm_dma_hardware);
196
197 return 0;
198}
199
200static struct snd_pcm_ops atmel_pcm_ops = {
201 .open = atmel_pcm_open,
202 .close = snd_dmaengine_pcm_close_release_chan,
203 .ioctl = snd_pcm_lib_ioctl,
204 .hw_params = atmel_pcm_hw_params,
205 .prepare = atmel_pcm_dma_prepare,
206 .trigger = snd_dmaengine_pcm_trigger,
207 .pointer = snd_dmaengine_pcm_pointer_no_residue,
208 .mmap = atmel_pcm_mmap,
209};
210
211static struct snd_soc_platform_driver atmel_soc_platform = {
212 .ops = &atmel_pcm_ops,
213 .pcm_new = atmel_pcm_new,
214 .pcm_free = atmel_pcm_free,
215}; 128};
216 129
217int atmel_pcm_dma_platform_register(struct device *dev) 130int atmel_pcm_dma_platform_register(struct device *dev)
218{ 131{
219 return snd_soc_register_platform(dev, &atmel_soc_platform); 132 return snd_dmaengine_pcm_register(dev, &atmel_dmaengine_pcm_config,
133 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
220} 134}
221EXPORT_SYMBOL(atmel_pcm_dma_platform_register); 135EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
222 136
223void atmel_pcm_dma_platform_unregister(struct device *dev) 137void atmel_pcm_dma_platform_unregister(struct device *dev)
224{ 138{
225 snd_soc_unregister_platform(dev); 139 snd_dmaengine_pcm_unregister(dev);
226} 140}
227EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister); 141EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister);
228 142
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index f3fdfa07fcb9..bb53dea85b17 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -73,6 +73,7 @@ static struct atmel_ssc_mask ssc_tx_mask = {
73 .ssc_disable = SSC_BIT(CR_TXDIS), 73 .ssc_disable = SSC_BIT(CR_TXDIS),
74 .ssc_endx = SSC_BIT(SR_ENDTX), 74 .ssc_endx = SSC_BIT(SR_ENDTX),
75 .ssc_endbuf = SSC_BIT(SR_TXBUFE), 75 .ssc_endbuf = SSC_BIT(SR_TXBUFE),
76 .ssc_error = SSC_BIT(SR_OVRUN),
76 .pdc_enable = ATMEL_PDC_TXTEN, 77 .pdc_enable = ATMEL_PDC_TXTEN,
77 .pdc_disable = ATMEL_PDC_TXTDIS, 78 .pdc_disable = ATMEL_PDC_TXTDIS,
78}; 79};
@@ -82,6 +83,7 @@ static struct atmel_ssc_mask ssc_rx_mask = {
82 .ssc_disable = SSC_BIT(CR_RXDIS), 83 .ssc_disable = SSC_BIT(CR_RXDIS),
83 .ssc_endx = SSC_BIT(SR_ENDRX), 84 .ssc_endx = SSC_BIT(SR_ENDRX),
84 .ssc_endbuf = SSC_BIT(SR_RXBUFF), 85 .ssc_endbuf = SSC_BIT(SR_RXBUFF),
86 .ssc_error = SSC_BIT(SR_OVRUN),
85 .pdc_enable = ATMEL_PDC_RXTEN, 87 .pdc_enable = ATMEL_PDC_RXTEN,
86 .pdc_disable = ATMEL_PDC_RXTDIS, 88 .pdc_disable = ATMEL_PDC_RXTDIS,
87}; 89};
@@ -196,15 +198,27 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
196 struct snd_soc_dai *dai) 198 struct snd_soc_dai *dai)
197{ 199{
198 struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; 200 struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
199 int dir_mask; 201 struct atmel_pcm_dma_params *dma_params;
202 int dir, dir_mask;
200 203
201 pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", 204 pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
202 ssc_readl(ssc_p->ssc->regs, SR)); 205 ssc_readl(ssc_p->ssc->regs, SR));
203 206
204 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 207 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
208 dir = 0;
205 dir_mask = SSC_DIR_MASK_PLAYBACK; 209 dir_mask = SSC_DIR_MASK_PLAYBACK;
206 else 210 } else {
211 dir = 1;
207 dir_mask = SSC_DIR_MASK_CAPTURE; 212 dir_mask = SSC_DIR_MASK_CAPTURE;
213 }
214
215 dma_params = &ssc_dma_params[dai->id][dir];
216 dma_params->ssc = ssc_p->ssc;
217 dma_params->substream = substream;
218
219 ssc_p->dma_params[dir] = dma_params;
220
221 snd_soc_dai_set_dma_data(dai, substream, dma_params);
208 222
209 spin_lock_irq(&ssc_p->lock); 223 spin_lock_irq(&ssc_p->lock);
210 if (ssc_p->dir_mask & dir_mask) { 224 if (ssc_p->dir_mask & dir_mask) {
@@ -325,7 +339,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
325 struct snd_pcm_hw_params *params, 339 struct snd_pcm_hw_params *params,
326 struct snd_soc_dai *dai) 340 struct snd_soc_dai *dai)
327{ 341{
328 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
329 int id = dai->id; 342 int id = dai->id;
330 struct atmel_ssc_info *ssc_p = &ssc_info[id]; 343 struct atmel_ssc_info *ssc_p = &ssc_info[id];
331 struct atmel_pcm_dma_params *dma_params; 344 struct atmel_pcm_dma_params *dma_params;
@@ -344,19 +357,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
344 else 357 else
345 dir = 1; 358 dir = 1;
346 359
347 dma_params = &ssc_dma_params[id][dir]; 360 dma_params = ssc_p->dma_params[dir];
348 dma_params->ssc = ssc_p->ssc;
349 dma_params->substream = substream;
350
351 ssc_p->dma_params[dir] = dma_params;
352
353 /*
354 * The snd_soc_pcm_stream->dma_data field is only used to communicate
355 * the appropriate DMA parameters to the pcm driver hw_params()
356 * function. It should not be used for other purposes
357 * as it is common to all substreams.
358 */
359 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params);
360 361
361 channels = params_channels(params); 362 channels = params_channels(params);
362 363
@@ -648,6 +649,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
648 dma_params = ssc_p->dma_params[dir]; 649 dma_params = ssc_p->dma_params[dir];
649 650
650 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); 651 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
652 ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
651 653
652 pr_debug("%s enabled SSC_SR=0x%08x\n", 654 pr_debug("%s enabled SSC_SR=0x%08x\n",
653 dir ? "receive" : "transmit", 655 dir ? "receive" : "transmit",
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c
new file mode 100644
index 000000000000..7222380131ea
--- /dev/null
+++ b/sound/soc/atmel/atmel_wm8904.c
@@ -0,0 +1,254 @@
1/*
2 * atmel_wm8904 - Atmel ASoC driver for boards with WM8904 codec.
3 *
4 * Copyright (C) 2012 Atmel
5 *
6 * Author: Bo Shen <voice.shen@atmel.com>
7 *
8 * GPLv2 or later
9 */
10
11#include <linux/clk.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <linux/pinctrl/consumer.h>
16
17#include <sound/soc.h>
18
19#include "../codecs/wm8904.h"
20#include "atmel_ssc_dai.h"
21
22#define MCLK_RATE 32768
23
24static struct clk *mclk;
25
26static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = {
27 SND_SOC_DAPM_HP("Headphone Jack", NULL),
28 SND_SOC_DAPM_MIC("Mic", NULL),
29 SND_SOC_DAPM_LINE("Line In Jack", NULL),
30};
31
32static int atmel_asoc_wm8904_hw_params(struct snd_pcm_substream *substream,
33 struct snd_pcm_hw_params *params)
34{
35 struct snd_soc_pcm_runtime *rtd = substream->private_data;
36 struct snd_soc_dai *codec_dai = rtd->codec_dai;
37 int ret;
38
39 ret = snd_soc_dai_set_pll(codec_dai, WM8904_FLL_MCLK, WM8904_FLL_MCLK,
40 32768, params_rate(params) * 256);
41 if (ret < 0) {
42 pr_err("%s - failed to set wm8904 codec PLL.", __func__);
43 return ret;
44 }
45
46 /*
47 * As here wm8904 use FLL output as its system clock
48 * so calling set_sysclk won't care freq parameter
49 * then we pass 0
50 */
51 ret = snd_soc_dai_set_sysclk(codec_dai, WM8904_CLK_FLL,
52 0, SND_SOC_CLOCK_IN);
53 if (ret < 0) {
54 pr_err("%s -failed to set wm8904 SYSCLK\n", __func__);
55 return ret;
56 }
57
58 return 0;
59}
60
61static struct snd_soc_ops atmel_asoc_wm8904_ops = {
62 .hw_params = atmel_asoc_wm8904_hw_params,
63};
64
65static int atmel_set_bias_level(struct snd_soc_card *card,
66 struct snd_soc_dapm_context *dapm,
67 enum snd_soc_bias_level level)
68{
69 if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
70 switch (level) {
71 case SND_SOC_BIAS_PREPARE:
72 clk_prepare_enable(mclk);
73 break;
74 case SND_SOC_BIAS_OFF:
75 clk_disable_unprepare(mclk);
76 break;
77 default:
78 break;
79 }
80 }
81
82 return 0;
83};
84
85static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
86 .name = "WM8904",
87 .stream_name = "WM8904 PCM",
88 .codec_dai_name = "wm8904-hifi",
89 .dai_fmt = SND_SOC_DAIFMT_I2S
90 | SND_SOC_DAIFMT_NB_NF
91 | SND_SOC_DAIFMT_CBM_CFM,
92 .ops = &atmel_asoc_wm8904_ops,
93};
94
95static struct snd_soc_card atmel_asoc_wm8904_card = {
96 .name = "atmel_asoc_wm8904",
97 .owner = THIS_MODULE,
98 .set_bias_level = atmel_set_bias_level,
99 .dai_link = &atmel_asoc_wm8904_dailink,
100 .num_links = 1,
101 .dapm_widgets = atmel_asoc_wm8904_dapm_widgets,
102 .num_dapm_widgets = ARRAY_SIZE(atmel_asoc_wm8904_dapm_widgets),
103 .fully_routed = true,
104};
105
106static int atmel_asoc_wm8904_dt_init(struct platform_device *pdev)
107{
108 struct device_node *np = pdev->dev.of_node;
109 struct device_node *codec_np, *cpu_np;
110 struct snd_soc_card *card = &atmel_asoc_wm8904_card;
111 struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
112 int ret;
113
114 if (!np) {
115 dev_err(&pdev->dev, "only device tree supported\n");
116 return -EINVAL;
117 }
118
119 ret = snd_soc_of_parse_card_name(card, "atmel,model");
120 if (ret) {
121 dev_err(&pdev->dev, "failed to parse card name\n");
122 return ret;
123 }
124
125 ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing");
126 if (ret) {
127 dev_err(&pdev->dev, "failed to parse audio routing\n");
128 return ret;
129 }
130
131 cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
132 if (!cpu_np) {
133 dev_err(&pdev->dev, "failed to get dai and pcm info\n");
134 ret = -EINVAL;
135 return ret;
136 }
137 dailink->cpu_of_node = cpu_np;
138 dailink->platform_of_node = cpu_np;
139 of_node_put(cpu_np);
140
141 codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
142 if (!codec_np) {
143 dev_err(&pdev->dev, "failed to get codec info\n");
144 ret = -EINVAL;
145 return ret;
146 }
147 dailink->codec_of_node = codec_np;
148 of_node_put(codec_np);
149
150 return 0;
151}
152
153static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
154{
155 struct snd_soc_card *card = &atmel_asoc_wm8904_card;
156 struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
157 struct clk *clk_src;
158 struct pinctrl *pinctrl;
159 int id, ret;
160
161 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
162 if (IS_ERR(pinctrl)) {
163 dev_err(&pdev->dev, "failed to request pinctrl\n");
164 return PTR_ERR(pinctrl);
165 }
166
167 card->dev = &pdev->dev;
168 ret = atmel_asoc_wm8904_dt_init(pdev);
169 if (ret) {
170 dev_err(&pdev->dev, "failed to init dt info\n");
171 return ret;
172 }
173
174 id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc");
175 ret = atmel_ssc_set_audio(id);
176 if (ret != 0) {
177 dev_err(&pdev->dev, "failed to set SSC %d for audio\n", id);
178 return ret;
179 }
180
181 mclk = clk_get(NULL, "pck0");
182 if (IS_ERR(mclk)) {
183 dev_err(&pdev->dev, "failed to get pck0\n");
184 ret = PTR_ERR(mclk);
185 goto err_set_audio;
186 }
187
188 clk_src = clk_get(NULL, "clk32k");
189 if (IS_ERR(clk_src)) {
190 dev_err(&pdev->dev, "failed to get clk32k\n");
191 ret = PTR_ERR(clk_src);
192 goto err_set_audio;
193 }
194
195 ret = clk_set_parent(mclk, clk_src);
196 clk_put(clk_src);
197 if (ret != 0) {
198 dev_err(&pdev->dev, "failed to set MCLK parent\n");
199 goto err_set_audio;
200 }
201
202 dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE);
203 clk_set_rate(mclk, MCLK_RATE);
204
205 ret = snd_soc_register_card(card);
206 if (ret) {
207 dev_err(&pdev->dev, "snd_soc_register_card failed\n");
208 goto err_set_audio;
209 }
210
211 return 0;
212
213err_set_audio:
214 atmel_ssc_put_audio(id);
215 return ret;
216}
217
218static int atmel_asoc_wm8904_remove(struct platform_device *pdev)
219{
220 struct snd_soc_card *card = platform_get_drvdata(pdev);
221 struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
222 int id;
223
224 id = of_alias_get_id((struct device_node *)dailink->cpu_of_node, "ssc");
225
226 snd_soc_unregister_card(card);
227 atmel_ssc_put_audio(id);
228
229 return 0;
230}
231
232#ifdef CONFIG_OF
233static const struct of_device_id atmel_asoc_wm8904_dt_ids[] = {
234 { .compatible = "atmel,asoc-wm8904", },
235 { }
236};
237#endif
238
239static struct platform_driver atmel_asoc_wm8904_driver = {
240 .driver = {
241 .name = "atmel-wm8904-audio",
242 .owner = THIS_MODULE,
243 .of_match_table = of_match_ptr(atmel_asoc_wm8904_dt_ids),
244 },
245 .probe = atmel_asoc_wm8904_probe,
246 .remove = atmel_asoc_wm8904_remove,
247};
248
249module_platform_driver(atmel_asoc_wm8904_driver);
250
251/* Module information */
252MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
253MODULE_DESCRIPTION("ALSA SoC machine driver for Atmel EK with WM8904 codec");
254MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c
new file mode 100644
index 000000000000..992ae38d5a15
--- /dev/null
+++ b/sound/soc/atmel/sam9x5_wm8731.c
@@ -0,0 +1,208 @@
1/*
2 * sam9x5_wm8731 -- SoC audio for AT91SAM9X5-based boards
3 * that are using WM8731 as codec.
4 *
5 * Copyright (C) 2011 Atmel,
6 * Nicolas Ferre <nicolas.ferre@atmel.com>
7 *
8 * Copyright (C) 2013 Paratronic,
9 * Richard Genoud <richard.genoud@gmail.com>
10 *
11 * Based on sam9g20_wm8731.c by:
12 * Sedji Gaouaou <sedji.gaouaou@atmel.com>
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
18 *
19 */
20#include <linux/of.h>
21#include <linux/export.h>
22#include <linux/module.h>
23#include <linux/mod_devicetable.h>
24#include <linux/platform_device.h>
25#include <linux/device.h>
26
27#include <sound/soc.h>
28#include <sound/soc-dai.h>
29#include <sound/soc-dapm.h>
30
31#include "../codecs/wm8731.h"
32#include "atmel_ssc_dai.h"
33
34
35#define MCLK_RATE 12288000
36
37#define DRV_NAME "sam9x5-snd-wm8731"
38
39struct sam9x5_drvdata {
40 int ssc_id;
41};
42
43/*
44 * Logic for a wm8731 as connected on a at91sam9x5ek based board.
45 */
46static int sam9x5_wm8731_init(struct snd_soc_pcm_runtime *rtd)
47{
48 struct snd_soc_dai *codec_dai = rtd->codec_dai;
49 struct device *dev = rtd->dev;
50 int ret;
51
52 dev_dbg(dev, "ASoC: %s called\n", __func__);
53
54 /* set the codec system clock for DAC and ADC */
55 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
56 MCLK_RATE, SND_SOC_CLOCK_IN);
57 if (ret < 0) {
58 dev_err(dev, "ASoC: Failed to set WM8731 SYSCLK: %d\n", ret);
59 return ret;
60 }
61
62 return 0;
63}
64
65/*
66 * Audio paths on at91sam9x5ek board:
67 *
68 * |A| ------------> | | ---R----> Headphone Jack
69 * |T| <----\ | WM | ---L--/
70 * |9| ---> CLK <--> | 8731 | <--R----- Line In Jack
71 * |1| <------------ | | <--L--/
72 */
73static const struct snd_soc_dapm_widget sam9x5_dapm_widgets[] = {
74 SND_SOC_DAPM_HP("Headphone Jack", NULL),
75 SND_SOC_DAPM_LINE("Line In Jack", NULL),
76};
77
78static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
79{
80 struct device_node *np = pdev->dev.of_node;
81 struct device_node *codec_np, *cpu_np;
82 struct snd_soc_card *card;
83 struct snd_soc_dai_link *dai;
84 struct sam9x5_drvdata *priv;
85 int ret;
86
87 if (!np) {
88 dev_err(&pdev->dev, "No device node supplied\n");
89 return -EINVAL;
90 }
91
92 card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
93 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
94 dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL);
95 if (!dai || !card || !priv) {
96 ret = -ENOMEM;
97 goto out;
98 }
99
100 card->dev = &pdev->dev;
101 card->owner = THIS_MODULE;
102 card->dai_link = dai;
103 card->num_links = 1;
104 card->dapm_widgets = sam9x5_dapm_widgets;
105 card->num_dapm_widgets = ARRAY_SIZE(sam9x5_dapm_widgets);
106 dai->name = "WM8731";
107 dai->stream_name = "WM8731 PCM";
108 dai->codec_dai_name = "wm8731-hifi";
109 dai->init = sam9x5_wm8731_init;
110 dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
111 | SND_SOC_DAIFMT_CBM_CFM;
112
113 ret = snd_soc_of_parse_card_name(card, "atmel,model");
114 if (ret) {
115 dev_err(&pdev->dev, "atmel,model node missing\n");
116 goto out;
117 }
118
119 ret = snd_soc_of_parse_audio_routing(card, "atmel,audio-routing");
120 if (ret) {
121 dev_err(&pdev->dev, "atmel,audio-routing node missing\n");
122 goto out;
123 }
124
125 codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
126 if (!codec_np) {
127 dev_err(&pdev->dev, "atmel,audio-codec node missing\n");
128 ret = -EINVAL;
129 goto out;
130 }
131
132 dai->codec_of_node = codec_np;
133
134 cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
135 if (!cpu_np) {
136 dev_err(&pdev->dev, "atmel,ssc-controller node missing\n");
137 ret = -EINVAL;
138 goto out;
139 }
140 dai->cpu_of_node = cpu_np;
141 dai->platform_of_node = cpu_np;
142
143 priv->ssc_id = of_alias_get_id(cpu_np, "ssc");
144
145 ret = atmel_ssc_set_audio(priv->ssc_id);
146 if (ret != 0) {
147 dev_err(&pdev->dev,
148 "ASoC: Failed to set SSC %d for audio: %d\n",
149 ret, priv->ssc_id);
150 goto out;
151 }
152
153 of_node_put(codec_np);
154 of_node_put(cpu_np);
155
156 platform_set_drvdata(pdev, card);
157
158 ret = snd_soc_register_card(card);
159 if (ret) {
160 dev_err(&pdev->dev,
161 "ASoC: Platform device allocation failed\n");
162 goto out_put_audio;
163 }
164
165 dev_dbg(&pdev->dev, "ASoC: %s ok\n", __func__);
166
167 return ret;
168
169out_put_audio:
170 atmel_ssc_put_audio(priv->ssc_id);
171out:
172 return ret;
173}
174
175static int sam9x5_wm8731_driver_remove(struct platform_device *pdev)
176{
177 struct snd_soc_card *card = platform_get_drvdata(pdev);
178 struct sam9x5_drvdata *priv = card->drvdata;
179
180 snd_soc_unregister_card(card);
181 atmel_ssc_put_audio(priv->ssc_id);
182
183 return 0;
184}
185
186static const struct of_device_id sam9x5_wm8731_of_match[] = {
187 { .compatible = "atmel,sam9x5-wm8731-audio", },
188 {},
189};
190MODULE_DEVICE_TABLE(of, sam9x5_wm8731_of_match);
191
192static struct platform_driver sam9x5_wm8731_driver = {
193 .driver = {
194 .name = DRV_NAME,
195 .owner = THIS_MODULE,
196 .of_match_table = of_match_ptr(sam9x5_wm8731_of_match),
197 },
198 .probe = sam9x5_wm8731_driver_probe,
199 .remove = sam9x5_wm8731_driver_remove,
200};
201module_platform_driver(sam9x5_wm8731_driver);
202
203/* Module information */
204MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
205MODULE_AUTHOR("Richard Genoud <richard.genoud@gmail.com>");
206MODULE_DESCRIPTION("ALSA SoC machine driver for AT91SAM9x5 - WM8731");
207MODULE_LICENSE("GPL");
208MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c
index a497a0cfeba1..decba87a074c 100644
--- a/sound/soc/au1x/db1200.c
+++ b/sound/soc/au1x/db1200.c
@@ -73,12 +73,14 @@ static struct snd_soc_dai_link db1300_ac97_dai = {
73 73
74static struct snd_soc_card db1300_ac97_machine = { 74static struct snd_soc_card db1300_ac97_machine = {
75 .name = "DB1300_AC97", 75 .name = "DB1300_AC97",
76 .owner = THIS_MODULE,
76 .dai_link = &db1300_ac97_dai, 77 .dai_link = &db1300_ac97_dai,
77 .num_links = 1, 78 .num_links = 1,
78}; 79};
79 80
80static struct snd_soc_card db1550_ac97_machine = { 81static struct snd_soc_card db1550_ac97_machine = {
81 .name = "DB1550_AC97", 82 .name = "DB1550_AC97",
83 .owner = THIS_MODULE,
82 .dai_link = &db1200_ac97_dai, 84 .dai_link = &db1200_ac97_dai,
83 .num_links = 1, 85 .num_links = 1,
84}; 86};
@@ -145,6 +147,7 @@ static struct snd_soc_dai_link db1300_i2s_dai = {
145 147
146static struct snd_soc_card db1300_i2s_machine = { 148static struct snd_soc_card db1300_i2s_machine = {
147 .name = "DB1300_I2S", 149 .name = "DB1300_I2S",
150 .owner = THIS_MODULE,
148 .dai_link = &db1300_i2s_dai, 151 .dai_link = &db1300_i2s_dai,
149 .num_links = 1, 152 .num_links = 1,
150}; 153};
@@ -161,6 +164,7 @@ static struct snd_soc_dai_link db1550_i2s_dai = {
161 164
162static struct snd_soc_card db1550_i2s_machine = { 165static struct snd_soc_card db1550_i2s_machine = {
163 .name = "DB1550_I2S", 166 .name = "DB1550_I2S",
167 .owner = THIS_MODULE,
164 .dai_link = &db1550_i2s_dai, 168 .dai_link = &db1550_i2s_dai,
165 .num_links = 1, 169 .num_links = 1,
166}; 170};
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index a822ab822bb7..986dcec79fa0 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -379,9 +379,6 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
379 mutex_init(&wd->lock); 379 mutex_init(&wd->lock);
380 380
381 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 381 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
382 if (!iores)
383 return -ENODEV;
384
385 wd->mmio = devm_ioremap_resource(&pdev->dev, iores); 382 wd->mmio = devm_ioremap_resource(&pdev->dev, iores);
386 if (IS_ERR(wd->mmio)) 383 if (IS_ERR(wd->mmio))
387 return PTR_ERR(wd->mmio); 384 return PTR_ERR(wd->mmio);
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h
index 0c3e22d90a8d..a680fdc9bb42 100644
--- a/sound/soc/blackfin/bf5xx-ac97.h
+++ b/sound/soc/blackfin/bf5xx-ac97.h
@@ -9,7 +9,6 @@
9#ifndef _BF5XX_AC97_H 9#ifndef _BF5XX_AC97_H
10#define _BF5XX_AC97_H 10#define _BF5XX_AC97_H
11 11
12extern struct snd_ac97 *ac97;
13/* Frame format in memory, only support stereo currently */ 12/* Frame format in memory, only support stereo currently */
14struct ac97_frame { 13struct ac97_frame {
15 u16 ac97_tag; /* slot 0 */ 14 u16 ac97_tag; /* slot 0 */
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c
index 04491f0e8d1b..efa75b5086a4 100644
--- a/sound/soc/cirrus/ep93xx-ac97.c
+++ b/sound/soc/cirrus/ep93xx-ac97.c
@@ -363,9 +363,6 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
363 return -ENOMEM; 363 return -ENOMEM;
364 364
365 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 365 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
366 if (!res)
367 return -ENODEV;
368
369 info->regs = devm_ioremap_resource(&pdev->dev, res); 366 info->regs = devm_ioremap_resource(&pdev->dev, res);
370 if (IS_ERR(info->regs)) 367 if (IS_ERR(info->regs))
371 return PTR_ERR(info->regs); 368 return PTR_ERR(info->regs);
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index 17ad70bca9fe..f23f331e9a97 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -376,9 +376,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
376 return -ENOMEM; 376 return -ENOMEM;
377 377
378 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 378 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
379 if (!res)
380 return -ENODEV;
381
382 info->regs = devm_ioremap_resource(&pdev->dev, res); 379 info->regs = devm_ioremap_resource(&pdev->dev, res);
383 if (IS_ERR(info->regs)) 380 if (IS_ERR(info->regs))
384 return PTR_ERR(info->regs); 381 return PTR_ERR(info->regs);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index badb6fbacaa6..15106c045478 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI
10 10
11config SND_SOC_ALL_CODECS 11config SND_SOC_ALL_CODECS
12 tristate "Build all ASoC CODEC drivers" 12 tristate "Build all ASoC CODEC drivers"
13 depends on COMPILE_TEST
13 select SND_SOC_88PM860X if MFD_88PM860X 14 select SND_SOC_88PM860X if MFD_88PM860X
14 select SND_SOC_L3 15 select SND_SOC_L3
15 select SND_SOC_AB8500_CODEC if ABX500_CORE 16 select SND_SOC_AB8500_CODEC if ABX500_CORE
@@ -20,6 +21,7 @@ config SND_SOC_ALL_CODECS
20 select SND_SOC_AD73311 21 select SND_SOC_AD73311
21 select SND_SOC_ADAU1373 if I2C 22 select SND_SOC_ADAU1373 if I2C
22 select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI 23 select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
24 select SND_SOC_ADAU1701 if I2C
23 select SND_SOC_ADS117X 25 select SND_SOC_ADS117X
24 select SND_SOC_AK4104 if SPI_MASTER 26 select SND_SOC_AK4104 if SPI_MASTER
25 select SND_SOC_AK4535 if I2C 27 select SND_SOC_AK4535 if I2C
@@ -54,6 +56,8 @@ config SND_SOC_ALL_CODECS
54 select SND_SOC_MC13783 if MFD_MC13XXX 56 select SND_SOC_MC13783 if MFD_MC13XXX
55 select SND_SOC_ML26124 if I2C 57 select SND_SOC_ML26124 if I2C
56 select SND_SOC_HDMI_CODEC 58 select SND_SOC_HDMI_CODEC
59 select SND_SOC_PCM1681 if I2C
60 select SND_SOC_PCM1792A if SPI_MASTER
57 select SND_SOC_PCM3008 61 select SND_SOC_PCM3008
58 select SND_SOC_RT5631 if I2C 62 select SND_SOC_RT5631 if I2C
59 select SND_SOC_RT5640 if I2C 63 select SND_SOC_RT5640 if I2C
@@ -122,6 +126,7 @@ config SND_SOC_ALL_CODECS
122 select SND_SOC_WM8994 if MFD_WM8994 126 select SND_SOC_WM8994 if MFD_WM8994
123 select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI 127 select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
124 select SND_SOC_WM8996 if I2C 128 select SND_SOC_WM8996 if I2C
129 select SND_SOC_WM8997 if MFD_WM8997
125 select SND_SOC_WM9081 if I2C 130 select SND_SOC_WM9081 if I2C
126 select SND_SOC_WM9090 if I2C 131 select SND_SOC_WM9090 if I2C
127 select SND_SOC_WM9705 if SND_SOC_AC97_BUS 132 select SND_SOC_WM9705 if SND_SOC_AC97_BUS
@@ -145,8 +150,10 @@ config SND_SOC_ARIZONA
145 tristate 150 tristate
146 default y if SND_SOC_WM5102=y 151 default y if SND_SOC_WM5102=y
147 default y if SND_SOC_WM5110=y 152 default y if SND_SOC_WM5110=y
153 default y if SND_SOC_WM8997=y
148 default m if SND_SOC_WM5102=m 154 default m if SND_SOC_WM5102=m
149 default m if SND_SOC_WM5110=m 155 default m if SND_SOC_WM5110=m
156 default m if SND_SOC_WM8997=m
150 157
151config SND_SOC_WM_HUBS 158config SND_SOC_WM_HUBS
152 tristate 159 tristate
@@ -198,6 +205,9 @@ config SND_SOC_AK4104
198config SND_SOC_AK4535 205config SND_SOC_AK4535
199 tristate 206 tristate
200 207
208config SND_SOC_AK4554
209 tristate
210
201config SND_SOC_AK4641 211config SND_SOC_AK4641
202 tristate 212 tristate
203 213
@@ -292,6 +302,12 @@ config SND_SOC_MAX9850
292config SND_SOC_HDMI_CODEC 302config SND_SOC_HDMI_CODEC
293 tristate 303 tristate
294 304
305config SND_SOC_PCM1681
306 tristate
307
308config SND_SOC_PCM1792A
309 tristate
310
295config SND_SOC_PCM3008 311config SND_SOC_PCM3008
296 tristate 312 tristate
297 313
@@ -500,6 +516,9 @@ config SND_SOC_WM8995
500config SND_SOC_WM8996 516config SND_SOC_WM8996
501 tristate 517 tristate
502 518
519config SND_SOC_WM8997
520 tristate
521
503config SND_SOC_WM9081 522config SND_SOC_WM9081
504 tristate 523 tristate
505 524
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 70fd8066f546..bc126764a44d 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -11,6 +11,7 @@ snd-soc-adav80x-objs := adav80x.o
11snd-soc-ads117x-objs := ads117x.o 11snd-soc-ads117x-objs := ads117x.o
12snd-soc-ak4104-objs := ak4104.o 12snd-soc-ak4104-objs := ak4104.o
13snd-soc-ak4535-objs := ak4535.o 13snd-soc-ak4535-objs := ak4535.o
14snd-soc-ak4554-objs := ak4554.o
14snd-soc-ak4641-objs := ak4641.o 15snd-soc-ak4641-objs := ak4641.o
15snd-soc-ak4642-objs := ak4642.o 16snd-soc-ak4642-objs := ak4642.o
16snd-soc-ak4671-objs := ak4671.o 17snd-soc-ak4671-objs := ak4671.o
@@ -42,6 +43,8 @@ snd-soc-max9850-objs := max9850.o
42snd-soc-mc13783-objs := mc13783.o 43snd-soc-mc13783-objs := mc13783.o
43snd-soc-ml26124-objs := ml26124.o 44snd-soc-ml26124-objs := ml26124.o
44snd-soc-hdmi-codec-objs := hdmi.o 45snd-soc-hdmi-codec-objs := hdmi.o
46snd-soc-pcm1681-objs := pcm1681.o
47snd-soc-pcm1792a-codec-objs := pcm1792a.o
45snd-soc-pcm3008-objs := pcm3008.o 48snd-soc-pcm3008-objs := pcm3008.o
46snd-soc-rt5631-objs := rt5631.o 49snd-soc-rt5631-objs := rt5631.o
47snd-soc-rt5640-objs := rt5640.o 50snd-soc-rt5640-objs := rt5640.o
@@ -114,6 +117,7 @@ snd-soc-wm8991-objs := wm8991.o
114snd-soc-wm8993-objs := wm8993.o 117snd-soc-wm8993-objs := wm8993.o
115snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o 118snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o
116snd-soc-wm8995-objs := wm8995.o 119snd-soc-wm8995-objs := wm8995.o
120snd-soc-wm8997-objs := wm8997.o
117snd-soc-wm9081-objs := wm9081.o 121snd-soc-wm9081-objs := wm9081.o
118snd-soc-wm9090-objs := wm9090.o 122snd-soc-wm9090-objs := wm9090.o
119snd-soc-wm9705-objs := wm9705.o 123snd-soc-wm9705-objs := wm9705.o
@@ -138,6 +142,7 @@ obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o
138obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o 142obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
139obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o 143obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
140obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 144obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
145obj-$(CONFIG_SND_SOC_AK4554) += snd-soc-ak4554.o
141obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o 146obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o
142obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 147obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
143obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o 148obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
@@ -171,6 +176,8 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
171obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o 176obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
172obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o 177obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
173obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o 178obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
179obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
180obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
174obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 181obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
175obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o 182obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
176obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o 183obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
@@ -239,6 +246,7 @@ obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
239obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o 246obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
240obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o 247obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
241obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o 248obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o
249obj-$(CONFIG_SND_SOC_WM8997) += snd-soc-wm8997.o
242obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o 250obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
243obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o 251obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
244obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o 252obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index ec7351803c24..8d9ba4ba4bfe 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -23,6 +23,16 @@
23#include <sound/initval.h> 23#include <sound/initval.h>
24#include <sound/soc.h> 24#include <sound/soc.h>
25 25
26static const struct snd_soc_dapm_widget ac97_widgets[] = {
27 SND_SOC_DAPM_INPUT("RX"),
28 SND_SOC_DAPM_OUTPUT("TX"),
29};
30
31static const struct snd_soc_dapm_route ac97_routes[] = {
32 { "AC97 Capture", NULL, "RX" },
33 { "TX", NULL, "AC97 Playback" },
34};
35
26static int ac97_prepare(struct snd_pcm_substream *substream, 36static int ac97_prepare(struct snd_pcm_substream *substream,
27 struct snd_soc_dai *dai) 37 struct snd_soc_dai *dai)
28{ 38{
@@ -117,6 +127,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
117 .probe = ac97_soc_probe, 127 .probe = ac97_soc_probe,
118 .suspend = ac97_soc_suspend, 128 .suspend = ac97_soc_suspend,
119 .resume = ac97_soc_resume, 129 .resume = ac97_soc_resume,
130
131 .dapm_widgets = ac97_widgets,
132 .num_dapm_widgets = ARRAY_SIZE(ac97_widgets),
133 .dapm_routes = ac97_routes,
134 .num_dapm_routes = ARRAY_SIZE(ac97_routes),
120}; 135};
121 136
122static int ac97_probe(struct platform_device *pdev) 137static int ac97_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 89fcf7d6e7b8..7257a8885f42 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -96,6 +96,44 @@ SOC_ENUM("Capture Source", ad1980_cap_src),
96SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), 96SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
97}; 97};
98 98
99static const struct snd_soc_dapm_widget ad1980_dapm_widgets[] = {
100SND_SOC_DAPM_INPUT("MIC1"),
101SND_SOC_DAPM_INPUT("MIC2"),
102SND_SOC_DAPM_INPUT("CD_L"),
103SND_SOC_DAPM_INPUT("CD_R"),
104SND_SOC_DAPM_INPUT("AUX_L"),
105SND_SOC_DAPM_INPUT("AUX_R"),
106SND_SOC_DAPM_INPUT("LINE_IN_L"),
107SND_SOC_DAPM_INPUT("LINE_IN_R"),
108
109SND_SOC_DAPM_OUTPUT("LFE_OUT"),
110SND_SOC_DAPM_OUTPUT("CENTER_OUT"),
111SND_SOC_DAPM_OUTPUT("LINE_OUT_L"),
112SND_SOC_DAPM_OUTPUT("LINE_OUT_R"),
113SND_SOC_DAPM_OUTPUT("MONO_OUT"),
114SND_SOC_DAPM_OUTPUT("HP_OUT_L"),
115SND_SOC_DAPM_OUTPUT("HP_OUT_R"),
116};
117
118static const struct snd_soc_dapm_route ad1980_dapm_routes[] = {
119 { "Capture", NULL, "MIC1" },
120 { "Capture", NULL, "MIC2" },
121 { "Capture", NULL, "CD_L" },
122 { "Capture", NULL, "CD_R" },
123 { "Capture", NULL, "AUX_L" },
124 { "Capture", NULL, "AUX_R" },
125 { "Capture", NULL, "LINE_IN_L" },
126 { "Capture", NULL, "LINE_IN_R" },
127
128 { "LFE_OUT", NULL, "Playback" },
129 { "CENTER_OUT", NULL, "Playback" },
130 { "LINE_OUT_L", NULL, "Playback" },
131 { "LINE_OUT_R", NULL, "Playback" },
132 { "MONO_OUT", NULL, "Playback" },
133 { "HP_OUT_L", NULL, "Playback" },
134 { "HP_OUT_R", NULL, "Playback" },
135};
136
99static unsigned int ac97_read(struct snd_soc_codec *codec, 137static unsigned int ac97_read(struct snd_soc_codec *codec,
100 unsigned int reg) 138 unsigned int reg)
101{ 139{
@@ -253,6 +291,11 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
253 .reg_cache_step = 2, 291 .reg_cache_step = 2,
254 .write = ac97_write, 292 .write = ac97_write,
255 .read = ac97_read, 293 .read = ac97_read,
294
295 .dapm_widgets = ad1980_dapm_widgets,
296 .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets),
297 .dapm_routes = ad1980_dapm_routes,
298 .num_dapm_routes = ARRAY_SIZE(ad1980_dapm_routes),
256}; 299};
257 300
258static int ad1980_probe(struct platform_device *pdev) 301static int ad1980_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index b1f2baf42b48..5fac8adbc136 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -23,6 +23,21 @@
23 23
24#include "ad73311.h" 24#include "ad73311.h"
25 25
26static const struct snd_soc_dapm_widget ad73311_dapm_widgets[] = {
27SND_SOC_DAPM_INPUT("VINP"),
28SND_SOC_DAPM_INPUT("VINN"),
29SND_SOC_DAPM_OUTPUT("VOUTN"),
30SND_SOC_DAPM_OUTPUT("VOUTP"),
31};
32
33static const struct snd_soc_dapm_route ad73311_dapm_routes[] = {
34 { "Capture", NULL, "VINP" },
35 { "Capture", NULL, "VINN" },
36
37 { "VOUTN", NULL, "Playback" },
38 { "VOUTP", NULL, "Playback" },
39};
40
26static struct snd_soc_dai_driver ad73311_dai = { 41static struct snd_soc_dai_driver ad73311_dai = {
27 .name = "ad73311-hifi", 42 .name = "ad73311-hifi",
28 .playback = { 43 .playback = {
@@ -39,7 +54,12 @@ static struct snd_soc_dai_driver ad73311_dai = {
39 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 54 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
40}; 55};
41 56
42static struct snd_soc_codec_driver soc_codec_dev_ad73311; 57static struct snd_soc_codec_driver soc_codec_dev_ad73311 = {
58 .dapm_widgets = ad73311_dapm_widgets,
59 .num_dapm_widgets = ARRAY_SIZE(ad73311_dapm_widgets),
60 .dapm_routes = ad73311_dapm_routes,
61 .num_dapm_routes = ARRAY_SIZE(ad73311_dapm_routes),
62};
43 63
44static int ad73311_probe(struct platform_device *pdev) 64static int ad73311_probe(struct platform_device *pdev)
45{ 65{
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index d1124a5b3471..ebff1128be59 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -91,7 +91,7 @@
91#define ADAU1701_OSCIPOW_OPD 0x04 91#define ADAU1701_OSCIPOW_OPD 0x04
92#define ADAU1701_DACSET_DACINIT 1 92#define ADAU1701_DACSET_DACINIT 1
93 93
94#define ADAU1707_CLKDIV_UNSET (-1UL) 94#define ADAU1707_CLKDIV_UNSET (-1U)
95 95
96#define ADAU1701_FIRMWARE "adau1701.bin" 96#define ADAU1701_FIRMWARE "adau1701.bin"
97 97
@@ -247,21 +247,21 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
247 gpio_is_valid(adau1701->gpio_pll_mode[1])) { 247 gpio_is_valid(adau1701->gpio_pll_mode[1])) {
248 switch (clkdiv) { 248 switch (clkdiv) {
249 case 64: 249 case 64:
250 gpio_set_value(adau1701->gpio_pll_mode[0], 0); 250 gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 0);
251 gpio_set_value(adau1701->gpio_pll_mode[1], 0); 251 gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 0);
252 break; 252 break;
253 case 256: 253 case 256:
254 gpio_set_value(adau1701->gpio_pll_mode[0], 0); 254 gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 0);
255 gpio_set_value(adau1701->gpio_pll_mode[1], 1); 255 gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 1);
256 break; 256 break;
257 case 384: 257 case 384:
258 gpio_set_value(adau1701->gpio_pll_mode[0], 1); 258 gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 1);
259 gpio_set_value(adau1701->gpio_pll_mode[1], 0); 259 gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 0);
260 break; 260 break;
261 case 0: /* fallback */ 261 case 0: /* fallback */
262 case 512: 262 case 512:
263 gpio_set_value(adau1701->gpio_pll_mode[0], 1); 263 gpio_set_value_cansleep(adau1701->gpio_pll_mode[0], 1);
264 gpio_set_value(adau1701->gpio_pll_mode[1], 1); 264 gpio_set_value_cansleep(adau1701->gpio_pll_mode[1], 1);
265 break; 265 break;
266 } 266 }
267 } 267 }
@@ -269,10 +269,10 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
269 adau1701->pll_clkdiv = clkdiv; 269 adau1701->pll_clkdiv = clkdiv;
270 270
271 if (gpio_is_valid(adau1701->gpio_nreset)) { 271 if (gpio_is_valid(adau1701->gpio_nreset)) {
272 gpio_set_value(adau1701->gpio_nreset, 0); 272 gpio_set_value_cansleep(adau1701->gpio_nreset, 0);
273 /* minimum reset time is 20ns */ 273 /* minimum reset time is 20ns */
274 udelay(1); 274 udelay(1);
275 gpio_set_value(adau1701->gpio_nreset, 1); 275 gpio_set_value_cansleep(adau1701->gpio_nreset, 1);
276 /* power-up time may be as long as 85ms */ 276 /* power-up time may be as long as 85ms */
277 mdelay(85); 277 mdelay(85);
278 } 278 }
@@ -734,7 +734,10 @@ static int adau1701_i2c_remove(struct i2c_client *client)
734} 734}
735 735
736static const struct i2c_device_id adau1701_i2c_id[] = { 736static const struct i2c_device_id adau1701_i2c_id[] = {
737 { "adau1401", 0 },
738 { "adau1401a", 0 },
737 { "adau1701", 0 }, 739 { "adau1701", 0 },
740 { "adau1702", 0 },
738 { } 741 { }
739}; 742};
740MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); 743MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index 3c839cc4e00e..15b012d0f226 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -868,6 +868,12 @@ static int adav80x_bus_remove(struct device *dev)
868} 868}
869 869
870#if defined(CONFIG_SPI_MASTER) 870#if defined(CONFIG_SPI_MASTER)
871static const struct spi_device_id adav80x_spi_id[] = {
872 { "adav801", 0 },
873 { }
874};
875MODULE_DEVICE_TABLE(spi, adav80x_spi_id);
876
871static int adav80x_spi_probe(struct spi_device *spi) 877static int adav80x_spi_probe(struct spi_device *spi)
872{ 878{
873 return adav80x_bus_probe(&spi->dev, SND_SOC_SPI); 879 return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
@@ -885,15 +891,16 @@ static struct spi_driver adav80x_spi_driver = {
885 }, 891 },
886 .probe = adav80x_spi_probe, 892 .probe = adav80x_spi_probe,
887 .remove = adav80x_spi_remove, 893 .remove = adav80x_spi_remove,
894 .id_table = adav80x_spi_id,
888}; 895};
889#endif 896#endif
890 897
891#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 898#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
892static const struct i2c_device_id adav80x_id[] = { 899static const struct i2c_device_id adav80x_i2c_id[] = {
893 { "adav803", 0 }, 900 { "adav803", 0 },
894 { } 901 { }
895}; 902};
896MODULE_DEVICE_TABLE(i2c, adav80x_id); 903MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id);
897 904
898static int adav80x_i2c_probe(struct i2c_client *client, 905static int adav80x_i2c_probe(struct i2c_client *client,
899 const struct i2c_device_id *id) 906 const struct i2c_device_id *id)
@@ -913,7 +920,7 @@ static struct i2c_driver adav80x_i2c_driver = {
913 }, 920 },
914 .probe = adav80x_i2c_probe, 921 .probe = adav80x_i2c_probe,
915 .remove = adav80x_i2c_remove, 922 .remove = adav80x_i2c_remove,
916 .id_table = adav80x_id, 923 .id_table = adav80x_i2c_id,
917}; 924};
918#endif 925#endif
919 926
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index 506d474c4d22..8f388edff586 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -23,6 +23,28 @@
23#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) 23#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
24#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) 24#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
25 25
26static const struct snd_soc_dapm_widget ads117x_dapm_widgets[] = {
27SND_SOC_DAPM_INPUT("Input1"),
28SND_SOC_DAPM_INPUT("Input2"),
29SND_SOC_DAPM_INPUT("Input3"),
30SND_SOC_DAPM_INPUT("Input4"),
31SND_SOC_DAPM_INPUT("Input5"),
32SND_SOC_DAPM_INPUT("Input6"),
33SND_SOC_DAPM_INPUT("Input7"),
34SND_SOC_DAPM_INPUT("Input8"),
35};
36
37static const struct snd_soc_dapm_route ads117x_dapm_routes[] = {
38 { "Capture", NULL, "Input1" },
39 { "Capture", NULL, "Input2" },
40 { "Capture", NULL, "Input3" },
41 { "Capture", NULL, "Input4" },
42 { "Capture", NULL, "Input5" },
43 { "Capture", NULL, "Input6" },
44 { "Capture", NULL, "Input7" },
45 { "Capture", NULL, "Input8" },
46};
47
26static struct snd_soc_dai_driver ads117x_dai = { 48static struct snd_soc_dai_driver ads117x_dai = {
27/* ADC */ 49/* ADC */
28 .name = "ads117x-hifi", 50 .name = "ads117x-hifi",
@@ -34,7 +56,12 @@ static struct snd_soc_dai_driver ads117x_dai = {
34 .formats = ADS117X_FORMATS,}, 56 .formats = ADS117X_FORMATS,},
35}; 57};
36 58
37static struct snd_soc_codec_driver soc_codec_dev_ads117x; 59static struct snd_soc_codec_driver soc_codec_dev_ads117x = {
60 .dapm_widgets = ads117x_dapm_widgets,
61 .num_dapm_widgets = ARRAY_SIZE(ads117x_dapm_widgets),
62 .dapm_routes = ads117x_dapm_routes,
63 .num_dapm_routes = ARRAY_SIZE(ads117x_dapm_routes),
64};
38 65
39static int ads117x_probe(struct platform_device *pdev) 66static int ads117x_probe(struct platform_device *pdev)
40{ 67{
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index c7cfdf957e4d..71059c07ae7b 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -51,6 +51,17 @@ struct ak4104_private {
51 struct regmap *regmap; 51 struct regmap *regmap;
52}; 52};
53 53
54static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = {
55SND_SOC_DAPM_PGA("TXE", AK4104_REG_TX, AK4104_TX_TXE, 0, NULL, 0),
56
57SND_SOC_DAPM_OUTPUT("TX"),
58};
59
60static const struct snd_soc_dapm_route ak4104_dapm_routes[] = {
61 { "TXE", NULL, "Playback" },
62 { "TX", NULL, "TXE" },
63};
64
54static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai, 65static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
55 unsigned int format) 66 unsigned int format)
56{ 67{
@@ -138,29 +149,11 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
138 if (ret < 0) 149 if (ret < 0)
139 return ret; 150 return ret;
140 151
141 /* enable transmitter */
142 ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
143 AK4104_TX_TXE, AK4104_TX_TXE);
144 if (ret < 0)
145 return ret;
146
147 return 0; 152 return 0;
148} 153}
149 154
150static int ak4104_hw_free(struct snd_pcm_substream *substream,
151 struct snd_soc_dai *dai)
152{
153 struct snd_soc_codec *codec = dai->codec;
154 struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
155
156 /* disable transmitter */
157 return regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
158 AK4104_TX_TXE, 0);
159}
160
161static const struct snd_soc_dai_ops ak4101_dai_ops = { 155static const struct snd_soc_dai_ops ak4101_dai_ops = {
162 .hw_params = ak4104_hw_params, 156 .hw_params = ak4104_hw_params,
163 .hw_free = ak4104_hw_free,
164 .set_fmt = ak4104_set_dai_fmt, 157 .set_fmt = ak4104_set_dai_fmt,
165}; 158};
166 159
@@ -214,6 +207,11 @@ static int ak4104_remove(struct snd_soc_codec *codec)
214static struct snd_soc_codec_driver soc_codec_device_ak4104 = { 207static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
215 .probe = ak4104_probe, 208 .probe = ak4104_probe,
216 .remove = ak4104_remove, 209 .remove = ak4104_remove,
210
211 .dapm_widgets = ak4104_dapm_widgets,
212 .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets),
213 .dapm_routes = ak4104_dapm_routes,
214 .num_dapm_routes = ARRAY_SIZE(ak4104_dapm_routes),
217}; 215};
218 216
219static const struct regmap_config ak4104_regmap = { 217static const struct regmap_config ak4104_regmap = {
diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c
new file mode 100644
index 000000000000..79e9555766c0
--- /dev/null
+++ b/sound/soc/codecs/ak4554.c
@@ -0,0 +1,106 @@
1/*
2 * ak4554.c
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * 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
12#include <linux/module.h>
13#include <sound/soc.h>
14
15/*
16 * ak4554 is very simple DA/AD converter which has no setting register.
17 *
18 * CAUTION
19 *
20 * ak4554 playback format is SND_SOC_DAIFMT_RIGHT_J,
21 * and, capture format is SND_SOC_DAIFMT_LEFT_J
22 * on same bit clock, LR clock.
23 * But, this driver doesn't have snd_soc_dai_ops :: set_fmt
24 *
25 * CPU/Codec DAI image
26 *
27 * CPU-DAI1 (plaback only fmt = RIGHT_J) --+-- ak4554
28 * |
29 * CPU-DAI2 (capture only fmt = LEFT_J) ---+
30 */
31
32static const struct snd_soc_dapm_widget ak4554_dapm_widgets[] = {
33SND_SOC_DAPM_INPUT("AINL"),
34SND_SOC_DAPM_INPUT("AINR"),
35
36SND_SOC_DAPM_OUTPUT("AOUTL"),
37SND_SOC_DAPM_OUTPUT("AOUTR"),
38};
39
40static const struct snd_soc_dapm_route ak4554_dapm_routes[] = {
41 { "Capture", NULL, "AINL" },
42 { "Capture", NULL, "AINR" },
43
44 { "AOUTL", NULL, "Playback" },
45 { "AOUTR", NULL, "Playback" },
46};
47
48static struct snd_soc_dai_driver ak4554_dai = {
49 .name = "ak4554-hifi",
50 .playback = {
51 .stream_name = "Playback",
52 .channels_min = 2,
53 .channels_max = 2,
54 .rates = SNDRV_PCM_RATE_8000_48000,
55 .formats = SNDRV_PCM_FMTBIT_S16_LE,
56 },
57 .capture = {
58 .stream_name = "Capture",
59 .channels_min = 2,
60 .channels_max = 2,
61 .rates = SNDRV_PCM_RATE_8000_48000,
62 .formats = SNDRV_PCM_FMTBIT_S16_LE,
63 },
64 .symmetric_rates = 1,
65};
66
67static struct snd_soc_codec_driver soc_codec_dev_ak4554 = {
68 .dapm_widgets = ak4554_dapm_widgets,
69 .num_dapm_widgets = ARRAY_SIZE(ak4554_dapm_widgets),
70 .dapm_routes = ak4554_dapm_routes,
71 .num_dapm_routes = ARRAY_SIZE(ak4554_dapm_routes),
72};
73
74static int ak4554_soc_probe(struct platform_device *pdev)
75{
76 return snd_soc_register_codec(&pdev->dev,
77 &soc_codec_dev_ak4554,
78 &ak4554_dai, 1);
79}
80
81static int ak4554_soc_remove(struct platform_device *pdev)
82{
83 snd_soc_unregister_codec(&pdev->dev);
84 return 0;
85}
86
87static struct of_device_id ak4554_of_match[] = {
88 { .compatible = "asahi-kasei,ak4554" },
89 {},
90};
91MODULE_DEVICE_TABLE(of, ak4554_of_match);
92
93static struct platform_driver ak4554_driver = {
94 .driver = {
95 .name = "ak4554-adc-dac",
96 .owner = THIS_MODULE,
97 .of_match_table = ak4554_of_match,
98 },
99 .probe = ak4554_soc_probe,
100 .remove = ak4554_soc_remove,
101};
102module_platform_driver(ak4554_driver);
103
104MODULE_LICENSE("GPL");
105MODULE_DESCRIPTION("SoC AK4554 driver");
106MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c
index 1f303983ae02..72e953b2cb41 100644
--- a/sound/soc/codecs/ak5386.c
+++ b/sound/soc/codecs/ak5386.c
@@ -22,7 +22,22 @@ struct ak5386_priv {
22 int reset_gpio; 22 int reset_gpio;
23}; 23};
24 24
25static struct snd_soc_codec_driver soc_codec_ak5386; 25static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
26SND_SOC_DAPM_INPUT("AINL"),
27SND_SOC_DAPM_INPUT("AINR"),
28};
29
30static const struct snd_soc_dapm_route ak5386_dapm_routes[] = {
31 { "Capture", NULL, "AINL" },
32 { "Capture", NULL, "AINR" },
33};
34
35static struct snd_soc_codec_driver soc_codec_ak5386 = {
36 .dapm_widgets = ak5386_dapm_widgets,
37 .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
38 .dapm_routes = ak5386_dapm_routes,
39 .num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes),
40};
26 41
27static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai, 42static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai,
28 unsigned int format) 43 unsigned int format)
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index de625813c0e6..657808ba1418 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -19,6 +19,7 @@
19#include <sound/tlv.h> 19#include <sound/tlv.h>
20 20
21#include <linux/mfd/arizona/core.h> 21#include <linux/mfd/arizona/core.h>
22#include <linux/mfd/arizona/gpio.h>
22#include <linux/mfd/arizona/registers.h> 23#include <linux/mfd/arizona/registers.h>
23 24
24#include "arizona.h" 25#include "arizona.h"
@@ -199,9 +200,16 @@ int arizona_init_spk(struct snd_soc_codec *codec)
199 if (ret != 0) 200 if (ret != 0)
200 return ret; 201 return ret;
201 202
202 ret = snd_soc_dapm_new_controls(&codec->dapm, &arizona_spkr, 1); 203 switch (arizona->type) {
203 if (ret != 0) 204 case WM8997:
204 return ret; 205 break;
206 default:
207 ret = snd_soc_dapm_new_controls(&codec->dapm,
208 &arizona_spkr, 1);
209 if (ret != 0)
210 return ret;
211 break;
212 }
205 213
206 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN, 214 ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_SHUTDOWN_WARN,
207 "Thermal warning", arizona_thermal_warn, 215 "Thermal warning", arizona_thermal_warn,
@@ -223,6 +231,41 @@ int arizona_init_spk(struct snd_soc_codec *codec)
223} 231}
224EXPORT_SYMBOL_GPL(arizona_init_spk); 232EXPORT_SYMBOL_GPL(arizona_init_spk);
225 233
234int arizona_init_gpio(struct snd_soc_codec *codec)
235{
236 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
237 struct arizona *arizona = priv->arizona;
238 int i;
239
240 switch (arizona->type) {
241 case WM5110:
242 snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity");
243 break;
244 default:
245 break;
246 }
247
248 snd_soc_dapm_disable_pin(&codec->dapm, "DRC1 Signal Activity");
249
250 for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
251 switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
252 case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
253 snd_soc_dapm_enable_pin(&codec->dapm,
254 "DRC1 Signal Activity");
255 break;
256 case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
257 snd_soc_dapm_enable_pin(&codec->dapm,
258 "DRC2 Signal Activity");
259 break;
260 default:
261 break;
262 }
263 }
264
265 return 0;
266}
267EXPORT_SYMBOL_GPL(arizona_init_gpio);
268
226const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { 269const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
227 "None", 270 "None",
228 "Tone Generator 1", 271 "Tone Generator 1",
@@ -517,6 +560,26 @@ const struct soc_enum arizona_ng_hold =
517 4, arizona_ng_hold_text); 560 4, arizona_ng_hold_text);
518EXPORT_SYMBOL_GPL(arizona_ng_hold); 561EXPORT_SYMBOL_GPL(arizona_ng_hold);
519 562
563static const char * const arizona_in_dmic_osr_text[] = {
564 "1.536MHz", "3.072MHz", "6.144MHz",
565};
566
567const struct soc_enum arizona_in_dmic_osr[] = {
568 SOC_ENUM_SINGLE(ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT,
569 ARRAY_SIZE(arizona_in_dmic_osr_text),
570 arizona_in_dmic_osr_text),
571 SOC_ENUM_SINGLE(ARIZONA_IN2L_CONTROL, ARIZONA_IN2_OSR_SHIFT,
572 ARRAY_SIZE(arizona_in_dmic_osr_text),
573 arizona_in_dmic_osr_text),
574 SOC_ENUM_SINGLE(ARIZONA_IN3L_CONTROL, ARIZONA_IN3_OSR_SHIFT,
575 ARRAY_SIZE(arizona_in_dmic_osr_text),
576 arizona_in_dmic_osr_text),
577 SOC_ENUM_SINGLE(ARIZONA_IN4L_CONTROL, ARIZONA_IN4_OSR_SHIFT,
578 ARRAY_SIZE(arizona_in_dmic_osr_text),
579 arizona_in_dmic_osr_text),
580};
581EXPORT_SYMBOL_GPL(arizona_in_dmic_osr);
582
520static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena) 583static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
521{ 584{
522 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); 585 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index b60b08ccc1d0..9e81b6392692 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -150,7 +150,8 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
150 ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \ 150 ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
151 ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux) 151 ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
152 152
153#define ARIZONA_MUX_ROUTES(name) \ 153#define ARIZONA_MUX_ROUTES(widget, name) \
154 { widget, NULL, name " Input" }, \
154 ARIZONA_MIXER_INPUT_ROUTES(name " Input") 155 ARIZONA_MIXER_INPUT_ROUTES(name " Input")
155 156
156#define ARIZONA_MIXER_ROUTES(widget, name) \ 157#define ARIZONA_MIXER_ROUTES(widget, name) \
@@ -198,6 +199,7 @@ extern const struct soc_enum arizona_lhpf3_mode;
198extern const struct soc_enum arizona_lhpf4_mode; 199extern const struct soc_enum arizona_lhpf4_mode;
199 200
200extern const struct soc_enum arizona_ng_hold; 201extern const struct soc_enum arizona_ng_hold;
202extern const struct soc_enum arizona_in_dmic_osr[];
201 203
202extern int arizona_in_ev(struct snd_soc_dapm_widget *w, 204extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
203 struct snd_kcontrol *kcontrol, 205 struct snd_kcontrol *kcontrol,
@@ -242,6 +244,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source,
242 unsigned int Fref, unsigned int Fout); 244 unsigned int Fref, unsigned int Fout);
243 245
244extern int arizona_init_spk(struct snd_soc_codec *codec); 246extern int arizona_init_spk(struct snd_soc_codec *codec);
247extern int arizona_init_gpio(struct snd_soc_codec *codec);
245 248
246extern int arizona_init_dai(struct arizona_priv *priv, int dai); 249extern int arizona_init_dai(struct arizona_priv *priv, int dai);
247 250
diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c
index a081d9fcb166..c4cf0699e77f 100644
--- a/sound/soc/codecs/bt-sco.c
+++ b/sound/soc/codecs/bt-sco.c
@@ -15,15 +15,27 @@
15 15
16#include <sound/soc.h> 16#include <sound/soc.h>
17 17
18static const struct snd_soc_dapm_widget bt_sco_widgets[] = {
19 SND_SOC_DAPM_INPUT("RX"),
20 SND_SOC_DAPM_OUTPUT("TX"),
21};
22
23static const struct snd_soc_dapm_route bt_sco_routes[] = {
24 { "Capture", NULL, "RX" },
25 { "TX", NULL, "Playback" },
26};
27
18static struct snd_soc_dai_driver bt_sco_dai = { 28static struct snd_soc_dai_driver bt_sco_dai = {
19 .name = "bt-sco-pcm", 29 .name = "bt-sco-pcm",
20 .playback = { 30 .playback = {
31 .stream_name = "Playback",
21 .channels_min = 1, 32 .channels_min = 1,
22 .channels_max = 1, 33 .channels_max = 1,
23 .rates = SNDRV_PCM_RATE_8000, 34 .rates = SNDRV_PCM_RATE_8000,
24 .formats = SNDRV_PCM_FMTBIT_S16_LE, 35 .formats = SNDRV_PCM_FMTBIT_S16_LE,
25 }, 36 },
26 .capture = { 37 .capture = {
38 .stream_name = "Capture",
27 .channels_min = 1, 39 .channels_min = 1,
28 .channels_max = 1, 40 .channels_max = 1,
29 .rates = SNDRV_PCM_RATE_8000, 41 .rates = SNDRV_PCM_RATE_8000,
@@ -31,7 +43,12 @@ static struct snd_soc_dai_driver bt_sco_dai = {
31 }, 43 },
32}; 44};
33 45
34static struct snd_soc_codec_driver soc_codec_dev_bt_sco; 46static struct snd_soc_codec_driver soc_codec_dev_bt_sco = {
47 .dapm_widgets = bt_sco_widgets,
48 .num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets),
49 .dapm_routes = bt_sco_routes,
50 .num_dapm_routes = ARRAY_SIZE(bt_sco_routes),
51};
35 52
36static int bt_sco_probe(struct platform_device *pdev) 53static int bt_sco_probe(struct platform_device *pdev)
37{ 54{
@@ -50,6 +67,9 @@ static struct platform_device_id bt_sco_driver_ids[] = {
50 { 67 {
51 .name = "dfbmcs320", 68 .name = "dfbmcs320",
52 }, 69 },
70 {
71 .name = "bt-sco",
72 },
53 {}, 73 {},
54}; 74};
55MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids); 75MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids);
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 8e4779812b96..83c835d9fd88 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -139,6 +139,22 @@ struct cs4270_private {
139 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 139 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
140}; 140};
141 141
142static const struct snd_soc_dapm_widget cs4270_dapm_widgets[] = {
143SND_SOC_DAPM_INPUT("AINL"),
144SND_SOC_DAPM_INPUT("AINR"),
145
146SND_SOC_DAPM_OUTPUT("AOUTL"),
147SND_SOC_DAPM_OUTPUT("AOUTR"),
148};
149
150static const struct snd_soc_dapm_route cs4270_dapm_routes[] = {
151 { "Capture", NULL, "AINA" },
152 { "Capture", NULL, "AINB" },
153
154 { "AOUTA", NULL, "Playback" },
155 { "AOUTB", NULL, "Playback" },
156};
157
142/** 158/**
143 * struct cs4270_mode_ratios - clock ratio tables 159 * struct cs4270_mode_ratios - clock ratio tables
144 * @ratio: the ratio of MCLK to the sample rate 160 * @ratio: the ratio of MCLK to the sample rate
@@ -612,6 +628,10 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = {
612 628
613 .controls = cs4270_snd_controls, 629 .controls = cs4270_snd_controls,
614 .num_controls = ARRAY_SIZE(cs4270_snd_controls), 630 .num_controls = ARRAY_SIZE(cs4270_snd_controls),
631 .dapm_widgets = cs4270_dapm_widgets,
632 .num_dapm_widgets = ARRAY_SIZE(cs4270_dapm_widgets),
633 .dapm_routes = cs4270_dapm_routes,
634 .num_dapm_routes = ARRAY_SIZE(cs4270_dapm_routes),
615}; 635};
616 636
617/* 637/*
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 03036b326732..a20f1bb8f071 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -173,6 +173,26 @@ struct cs4271_private {
173 bool enable_soft_reset; 173 bool enable_soft_reset;
174}; 174};
175 175
176static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = {
177SND_SOC_DAPM_INPUT("AINA"),
178SND_SOC_DAPM_INPUT("AINB"),
179
180SND_SOC_DAPM_OUTPUT("AOUTA+"),
181SND_SOC_DAPM_OUTPUT("AOUTA-"),
182SND_SOC_DAPM_OUTPUT("AOUTB+"),
183SND_SOC_DAPM_OUTPUT("AOUTB-"),
184};
185
186static const struct snd_soc_dapm_route cs4271_dapm_routes[] = {
187 { "Capture", NULL, "AINA" },
188 { "Capture", NULL, "AINB" },
189
190 { "AOUTA+", NULL, "Playback" },
191 { "AOUTA-", NULL, "Playback" },
192 { "AOUTB+", NULL, "Playback" },
193 { "AOUTB-", NULL, "Playback" },
194};
195
176/* 196/*
177 * @freq is the desired MCLK rate 197 * @freq is the desired MCLK rate
178 * MCLK rate should (c) be the sample rate, multiplied by one of the 198 * MCLK rate should (c) be the sample rate, multiplied by one of the
@@ -576,8 +596,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
576 CS4271_MODE2_MUTECAEQUB, 596 CS4271_MODE2_MUTECAEQUB,
577 CS4271_MODE2_MUTECAEQUB); 597 CS4271_MODE2_MUTECAEQUB);
578 598
579 return snd_soc_add_codec_controls(codec, cs4271_snd_controls, 599 return 0;
580 ARRAY_SIZE(cs4271_snd_controls));
581} 600}
582 601
583static int cs4271_remove(struct snd_soc_codec *codec) 602static int cs4271_remove(struct snd_soc_codec *codec)
@@ -596,6 +615,13 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
596 .remove = cs4271_remove, 615 .remove = cs4271_remove,
597 .suspend = cs4271_soc_suspend, 616 .suspend = cs4271_soc_suspend,
598 .resume = cs4271_soc_resume, 617 .resume = cs4271_soc_resume,
618
619 .controls = cs4271_snd_controls,
620 .num_controls = ARRAY_SIZE(cs4271_snd_controls),
621 .dapm_widgets = cs4271_dapm_widgets,
622 .num_dapm_widgets = ARRAY_SIZE(cs4271_dapm_widgets),
623 .dapm_routes = cs4271_dapm_routes,
624 .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes),
599}; 625};
600 626
601#if defined(CONFIG_SPI_MASTER) 627#if defined(CONFIG_SPI_MASTER)
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c
index 2bcae2b40c92..68342b121c96 100644
--- a/sound/soc/codecs/hdmi.c
+++ b/sound/soc/codecs/hdmi.c
@@ -23,11 +23,20 @@
23 23
24#define DRV_NAME "hdmi-audio-codec" 24#define DRV_NAME "hdmi-audio-codec"
25 25
26static struct snd_soc_codec_driver hdmi_codec; 26static const struct snd_soc_dapm_widget hdmi_widgets[] = {
27 SND_SOC_DAPM_INPUT("RX"),
28 SND_SOC_DAPM_OUTPUT("TX"),
29};
30
31static const struct snd_soc_dapm_route hdmi_routes[] = {
32 { "Capture", NULL, "RX" },
33 { "TX", NULL, "Playback" },
34};
27 35
28static struct snd_soc_dai_driver hdmi_codec_dai = { 36static struct snd_soc_dai_driver hdmi_codec_dai = {
29 .name = "hdmi-hifi", 37 .name = "hdmi-hifi",
30 .playback = { 38 .playback = {
39 .stream_name = "Playback",
31 .channels_min = 2, 40 .channels_min = 2,
32 .channels_max = 8, 41 .channels_max = 8,
33 .rates = SNDRV_PCM_RATE_32000 | 42 .rates = SNDRV_PCM_RATE_32000 |
@@ -37,6 +46,25 @@ static struct snd_soc_dai_driver hdmi_codec_dai = {
37 .formats = SNDRV_PCM_FMTBIT_S16_LE | 46 .formats = SNDRV_PCM_FMTBIT_S16_LE |
38 SNDRV_PCM_FMTBIT_S24_LE, 47 SNDRV_PCM_FMTBIT_S24_LE,
39 }, 48 },
49 .capture = {
50 .stream_name = "Capture",
51 .channels_min = 2,
52 .channels_max = 2,
53 .rates = SNDRV_PCM_RATE_32000 |
54 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
55 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
56 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
57 .formats = SNDRV_PCM_FMTBIT_S16_LE |
58 SNDRV_PCM_FMTBIT_S24_LE,
59 },
60
61};
62
63static struct snd_soc_codec_driver hdmi_codec = {
64 .dapm_widgets = hdmi_widgets,
65 .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
66 .dapm_routes = hdmi_routes,
67 .num_dapm_routes = ARRAY_SIZE(hdmi_routes),
40}; 68};
41 69
42static int hdmi_codec_probe(struct platform_device *pdev) 70static int hdmi_codec_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 9f9f59573f72..0e5743ea79df 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/i2c.h> 18#include <linux/i2c.h>
19#include <linux/regmap.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
20 21
21#include <sound/core.h> 22#include <sound/core.h>
@@ -23,12 +24,15 @@
23#include <sound/tlv.h> 24#include <sound/tlv.h>
24 25
25struct lm4857 { 26struct lm4857 {
26 struct i2c_client *i2c; 27 struct regmap *regmap;
27 uint8_t mode; 28 uint8_t mode;
28}; 29};
29 30
30static const uint8_t lm4857_default_regs[] = { 31static const struct reg_default lm4857_default_regs[] = {
31 0x00, 0x00, 0x00, 0x00, 32 { 0x0, 0x00 },
33 { 0x1, 0x00 },
34 { 0x2, 0x00 },
35 { 0x3, 0x00 },
32}; 36};
33 37
34/* The register offsets in the cache array */ 38/* The register offsets in the cache array */
@@ -42,39 +46,6 @@ static const uint8_t lm4857_default_regs[] = {
42#define LM4857_WAKEUP 5 46#define LM4857_WAKEUP 5
43#define LM4857_EPGAIN 4 47#define LM4857_EPGAIN 4
44 48
45static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg,
46 unsigned int value)
47{
48 uint8_t data;
49 int ret;
50
51 ret = snd_soc_cache_write(codec, reg, value);
52 if (ret < 0)
53 return ret;
54
55 data = (reg << 6) | value;
56 ret = i2c_master_send(codec->control_data, &data, 1);
57 if (ret != 1) {
58 dev_err(codec->dev, "Failed to write register: %d\n", ret);
59 return ret;
60 }
61
62 return 0;
63}
64
65static unsigned int lm4857_read(struct snd_soc_codec *codec,
66 unsigned int reg)
67{
68 unsigned int val;
69 int ret;
70
71 ret = snd_soc_cache_read(codec, reg, &val);
72 if (ret)
73 return -1;
74
75 return val;
76}
77
78static int lm4857_get_mode(struct snd_kcontrol *kcontrol, 49static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
79 struct snd_ctl_elem_value *ucontrol) 50 struct snd_ctl_elem_value *ucontrol)
80{ 51{
@@ -96,7 +67,7 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
96 lm4857->mode = value; 67 lm4857->mode = value;
97 68
98 if (codec->dapm.bias_level == SND_SOC_BIAS_ON) 69 if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
99 snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6); 70 regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, value + 6);
100 71
101 return 1; 72 return 1;
102} 73}
@@ -108,10 +79,11 @@ static int lm4857_set_bias_level(struct snd_soc_codec *codec,
108 79
109 switch (level) { 80 switch (level) {
110 case SND_SOC_BIAS_ON: 81 case SND_SOC_BIAS_ON:
111 snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6); 82 regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F,
83 lm4857->mode + 6);
112 break; 84 break;
113 case SND_SOC_BIAS_STANDBY: 85 case SND_SOC_BIAS_STANDBY:
114 snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0); 86 regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, 0);
115 break; 87 break;
116 default: 88 default:
117 break; 89 break;
@@ -171,49 +143,32 @@ static const struct snd_soc_dapm_route lm4857_routes[] = {
171 {"EP", NULL, "IN"}, 143 {"EP", NULL, "IN"},
172}; 144};
173 145
174static int lm4857_probe(struct snd_soc_codec *codec) 146static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
175{ 147 .set_bias_level = lm4857_set_bias_level,
176 struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
177 struct snd_soc_dapm_context *dapm = &codec->dapm;
178 int ret;
179
180 codec->control_data = lm4857->i2c;
181
182 ret = snd_soc_add_codec_controls(codec, lm4857_controls,
183 ARRAY_SIZE(lm4857_controls));
184 if (ret)
185 return ret;
186
187 ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets,
188 ARRAY_SIZE(lm4857_dapm_widgets));
189 if (ret)
190 return ret;
191 148
192 ret = snd_soc_dapm_add_routes(dapm, lm4857_routes, 149 .controls = lm4857_controls,
193 ARRAY_SIZE(lm4857_routes)); 150 .num_controls = ARRAY_SIZE(lm4857_controls),
194 if (ret) 151 .dapm_widgets = lm4857_dapm_widgets,
195 return ret; 152 .num_dapm_widgets = ARRAY_SIZE(lm4857_dapm_widgets),
153 .dapm_routes = lm4857_routes,
154 .num_dapm_routes = ARRAY_SIZE(lm4857_routes),
155};
196 156
197 snd_soc_dapm_new_widgets(dapm); 157static const struct regmap_config lm4857_regmap_config = {
158 .val_bits = 6,
159 .reg_bits = 2,
198 160
199 return 0; 161 .max_register = LM4857_CTRL,
200}
201 162
202static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { 163 .cache_type = REGCACHE_FLAT,
203 .write = lm4857_write, 164 .reg_defaults = lm4857_default_regs,
204 .read = lm4857_read, 165 .num_reg_defaults = ARRAY_SIZE(lm4857_default_regs),
205 .probe = lm4857_probe,
206 .reg_cache_size = ARRAY_SIZE(lm4857_default_regs),
207 .reg_word_size = sizeof(uint8_t),
208 .reg_cache_default = lm4857_default_regs,
209 .set_bias_level = lm4857_set_bias_level,
210}; 166};
211 167
212static int lm4857_i2c_probe(struct i2c_client *i2c, 168static int lm4857_i2c_probe(struct i2c_client *i2c,
213 const struct i2c_device_id *id) 169 const struct i2c_device_id *id)
214{ 170{
215 struct lm4857 *lm4857; 171 struct lm4857 *lm4857;
216 int ret;
217 172
218 lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL); 173 lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL);
219 if (!lm4857) 174 if (!lm4857)
@@ -221,11 +176,11 @@ static int lm4857_i2c_probe(struct i2c_client *i2c,
221 176
222 i2c_set_clientdata(i2c, lm4857); 177 i2c_set_clientdata(i2c, lm4857);
223 178
224 lm4857->i2c = i2c; 179 lm4857->regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config);
225 180 if (IS_ERR(lm4857->regmap))
226 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); 181 return PTR_ERR(lm4857->regmap);
227 182
228 return ret; 183 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
229} 184}
230 185
231static int lm4857_i2c_remove(struct i2c_client *i2c) 186static int lm4857_i2c_remove(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index a6ac2313047d..31f91560e9f6 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -118,6 +118,18 @@ static const struct snd_kcontrol_new max9768_mute[] = {
118 SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio), 118 SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio),
119}; 119};
120 120
121static const struct snd_soc_dapm_widget max9768_dapm_widgets[] = {
122SND_SOC_DAPM_INPUT("IN"),
123
124SND_SOC_DAPM_OUTPUT("OUT+"),
125SND_SOC_DAPM_OUTPUT("OUT-"),
126};
127
128static const struct snd_soc_dapm_route max9768_dapm_routes[] = {
129 { "OUT+", NULL, "IN" },
130 { "OUT-", NULL, "IN" },
131};
132
121static int max9768_probe(struct snd_soc_codec *codec) 133static int max9768_probe(struct snd_soc_codec *codec)
122{ 134{
123 struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); 135 struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
@@ -148,6 +160,10 @@ static struct snd_soc_codec_driver max9768_codec_driver = {
148 .probe = max9768_probe, 160 .probe = max9768_probe,
149 .controls = max9768_volume, 161 .controls = max9768_volume,
150 .num_controls = ARRAY_SIZE(max9768_volume), 162 .num_controls = ARRAY_SIZE(max9768_volume),
163 .dapm_widgets = max9768_dapm_widgets,
164 .num_dapm_widgets = ARRAY_SIZE(max9768_dapm_widgets),
165 .dapm_routes = max9768_dapm_routes,
166 .num_dapm_routes = ARRAY_SIZE(max9768_dapm_routes),
151}; 167};
152 168
153static const struct regmap_config max9768_i2c_regmap_config = { 169static const struct regmap_config max9768_i2c_regmap_config = {
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index ad5313f98f28..0569a4c3ae00 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -2084,8 +2084,9 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
2084 2084
2085 pm_wakeup_event(codec->dev, 100); 2085 pm_wakeup_event(codec->dev, 100);
2086 2086
2087 schedule_delayed_work(&max98090->jack_work, 2087 queue_delayed_work(system_power_efficient_wq,
2088 msecs_to_jiffies(100)); 2088 &max98090->jack_work,
2089 msecs_to_jiffies(100));
2089 } 2090 }
2090 2091
2091 if (active & M98090_DRCACT_MASK) 2092 if (active & M98090_DRCACT_MASK)
@@ -2132,8 +2133,9 @@ int max98090_mic_detect(struct snd_soc_codec *codec,
2132 snd_soc_jack_report(max98090->jack, 0, 2133 snd_soc_jack_report(max98090->jack, 0,
2133 SND_JACK_HEADSET | SND_JACK_BTN_0); 2134 SND_JACK_HEADSET | SND_JACK_BTN_0);
2134 2135
2135 schedule_delayed_work(&max98090->jack_work, 2136 queue_delayed_work(system_power_efficient_wq,
2136 msecs_to_jiffies(100)); 2137 &max98090->jack_work,
2138 msecs_to_jiffies(100));
2137 2139
2138 return 0; 2140 return 0;
2139} 2141}
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index 6b6c74cd83e2..29549cdbf4c1 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -14,170 +14,21 @@
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/i2c.h> 16#include <linux/i2c.h>
17#include <linux/regmap.h>
17#include <sound/soc.h> 18#include <sound/soc.h>
18#include <sound/tlv.h> 19#include <sound/tlv.h>
19 20
20#include "max9877.h" 21#include "max9877.h"
21 22
22static struct i2c_client *i2c; 23static struct regmap *regmap;
23 24
24static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 }; 25static struct reg_default max9877_regs[] = {
25 26 { 0, 0x40 },
26static void max9877_write_regs(void) 27 { 1, 0x00 },
27{ 28 { 2, 0x00 },
28 unsigned int i; 29 { 3, 0x00 },
29 u8 data[6]; 30 { 4, 0x49 },
30 31};
31 data[0] = MAX9877_INPUT_MODE;
32 for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
33 data[i + 1] = max9877_regs[i];
34
35 if (i2c_master_send(i2c, data, 6) != 6)
36 dev_err(&i2c->dev, "i2c write failed\n");
37}
38
39static int max9877_get_reg(struct snd_kcontrol *kcontrol,
40 struct snd_ctl_elem_value *ucontrol)
41{
42 struct soc_mixer_control *mc =
43 (struct soc_mixer_control *)kcontrol->private_value;
44 unsigned int reg = mc->reg;
45 unsigned int shift = mc->shift;
46 unsigned int mask = mc->max;
47 unsigned int invert = mc->invert;
48
49 ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
50
51 if (invert)
52 ucontrol->value.integer.value[0] =
53 mask - ucontrol->value.integer.value[0];
54
55 return 0;
56}
57
58static int max9877_set_reg(struct snd_kcontrol *kcontrol,
59 struct snd_ctl_elem_value *ucontrol)
60{
61 struct soc_mixer_control *mc =
62 (struct soc_mixer_control *)kcontrol->private_value;
63 unsigned int reg = mc->reg;
64 unsigned int shift = mc->shift;
65 unsigned int mask = mc->max;
66 unsigned int invert = mc->invert;
67 unsigned int val = (ucontrol->value.integer.value[0] & mask);
68
69 if (invert)
70 val = mask - val;
71
72 if (((max9877_regs[reg] >> shift) & mask) == val)
73 return 0;
74
75 max9877_regs[reg] &= ~(mask << shift);
76 max9877_regs[reg] |= val << shift;
77 max9877_write_regs();
78
79 return 1;
80}
81
82static int max9877_get_2reg(struct snd_kcontrol *kcontrol,
83 struct snd_ctl_elem_value *ucontrol)
84{
85 struct soc_mixer_control *mc =
86 (struct soc_mixer_control *)kcontrol->private_value;
87 unsigned int reg = mc->reg;
88 unsigned int reg2 = mc->rreg;
89 unsigned int shift = mc->shift;
90 unsigned int mask = mc->max;
91
92 ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
93 ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask;
94
95 return 0;
96}
97
98static int max9877_set_2reg(struct snd_kcontrol *kcontrol,
99 struct snd_ctl_elem_value *ucontrol)
100{
101 struct soc_mixer_control *mc =
102 (struct soc_mixer_control *)kcontrol->private_value;
103 unsigned int reg = mc->reg;
104 unsigned int reg2 = mc->rreg;
105 unsigned int shift = mc->shift;
106 unsigned int mask = mc->max;
107 unsigned int val = (ucontrol->value.integer.value[0] & mask);
108 unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
109 unsigned int change = 0;
110
111 if (((max9877_regs[reg] >> shift) & mask) != val)
112 change = 1;
113
114 if (((max9877_regs[reg2] >> shift) & mask) != val2)
115 change = 1;
116
117 if (change) {
118 max9877_regs[reg] &= ~(mask << shift);
119 max9877_regs[reg] |= val << shift;
120 max9877_regs[reg2] &= ~(mask << shift);
121 max9877_regs[reg2] |= val2 << shift;
122 max9877_write_regs();
123 }
124
125 return change;
126}
127
128static int max9877_get_out_mode(struct snd_kcontrol *kcontrol,
129 struct snd_ctl_elem_value *ucontrol)
130{
131 u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK;
132
133 if (value)
134 value -= 1;
135
136 ucontrol->value.integer.value[0] = value;
137 return 0;
138}
139
140static int max9877_set_out_mode(struct snd_kcontrol *kcontrol,
141 struct snd_ctl_elem_value *ucontrol)
142{
143 u8 value = ucontrol->value.integer.value[0];
144
145 value += 1;
146
147 if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value)
148 return 0;
149
150 max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK;
151 max9877_regs[MAX9877_OUTPUT_MODE] |= value;
152 max9877_write_regs();
153 return 1;
154}
155
156static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol,
157 struct snd_ctl_elem_value *ucontrol)
158{
159 u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK);
160
161 value = value >> MAX9877_OSC_OFFSET;
162
163 ucontrol->value.integer.value[0] = value;
164 return 0;
165}
166
167static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol,
168 struct snd_ctl_elem_value *ucontrol)
169{
170 u8 value = ucontrol->value.integer.value[0];
171
172 value = value << MAX9877_OSC_OFFSET;
173 if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value)
174 return 0;
175
176 max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK;
177 max9877_regs[MAX9877_OUTPUT_MODE] |= value;
178 max9877_write_regs();
179 return 1;
180}
181 32
182static const unsigned int max9877_pgain_tlv[] = { 33static const unsigned int max9877_pgain_tlv[] = {
183 TLV_DB_RANGE_HEAD(2), 34 TLV_DB_RANGE_HEAD(2),
@@ -212,65 +63,104 @@ static const char *max9877_osc_mode[] = {
212}; 63};
213 64
214static const struct soc_enum max9877_enum[] = { 65static const struct soc_enum max9877_enum[] = {
215 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode), 66 SOC_ENUM_SINGLE(MAX9877_OUTPUT_MODE, 0, ARRAY_SIZE(max9877_out_mode),
216 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode), 67 max9877_out_mode),
68 SOC_ENUM_SINGLE(MAX9877_OUTPUT_MODE, MAX9877_OSC_OFFSET,
69 ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode),
217}; 70};
218 71
219static const struct snd_kcontrol_new max9877_controls[] = { 72static const struct snd_kcontrol_new max9877_controls[] = {
220 SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume", 73 SOC_SINGLE_TLV("MAX9877 PGAINA Playback Volume",
221 MAX9877_INPUT_MODE, 0, 2, 0, 74 MAX9877_INPUT_MODE, 0, 2, 0, max9877_pgain_tlv),
222 max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), 75 SOC_SINGLE_TLV("MAX9877 PGAINB Playback Volume",
223 SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume", 76 MAX9877_INPUT_MODE, 2, 2, 0, max9877_pgain_tlv),
224 MAX9877_INPUT_MODE, 2, 2, 0, 77 SOC_SINGLE_TLV("MAX9877 Amp Speaker Playback Volume",
225 max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), 78 MAX9877_SPK_VOLUME, 0, 31, 0, max9877_output_tlv),
226 SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume", 79 SOC_DOUBLE_R_TLV("MAX9877 Amp HP Playback Volume",
227 MAX9877_SPK_VOLUME, 0, 31, 0, 80 MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0,
228 max9877_get_reg, max9877_set_reg, max9877_output_tlv), 81 max9877_output_tlv),
229 SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume", 82 SOC_SINGLE("MAX9877 INB Stereo Switch",
230 MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0, 83 MAX9877_INPUT_MODE, 4, 1, 1),
231 max9877_get_2reg, max9877_set_2reg, max9877_output_tlv), 84 SOC_SINGLE("MAX9877 INA Stereo Switch",
232 SOC_SINGLE_EXT("MAX9877 INB Stereo Switch", 85 MAX9877_INPUT_MODE, 5, 1, 1),
233 MAX9877_INPUT_MODE, 4, 1, 1, 86 SOC_SINGLE("MAX9877 Zero-crossing detection Switch",
234 max9877_get_reg, max9877_set_reg), 87 MAX9877_INPUT_MODE, 6, 1, 0),
235 SOC_SINGLE_EXT("MAX9877 INA Stereo Switch", 88 SOC_SINGLE("MAX9877 Bypass Mode Switch",
236 MAX9877_INPUT_MODE, 5, 1, 1, 89 MAX9877_OUTPUT_MODE, 6, 1, 0),
237 max9877_get_reg, max9877_set_reg), 90 SOC_ENUM("MAX9877 Output Mode", max9877_enum[0]),
238 SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch", 91 SOC_ENUM("MAX9877 Oscillator Mode", max9877_enum[1]),
239 MAX9877_INPUT_MODE, 6, 1, 0,
240 max9877_get_reg, max9877_set_reg),
241 SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch",
242 MAX9877_OUTPUT_MODE, 6, 1, 0,
243 max9877_get_reg, max9877_set_reg),
244 SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch",
245 MAX9877_OUTPUT_MODE, 7, 1, 1,
246 max9877_get_reg, max9877_set_reg),
247 SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0],
248 max9877_get_out_mode, max9877_set_out_mode),
249 SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1],
250 max9877_get_osc_mode, max9877_set_osc_mode),
251}; 92};
252 93
253/* This function is called from ASoC machine driver */ 94static const struct snd_soc_dapm_widget max9877_dapm_widgets[] = {
254int max9877_add_controls(struct snd_soc_codec *codec) 95SND_SOC_DAPM_INPUT("INA1"),
255{ 96SND_SOC_DAPM_INPUT("INA2"),
256 return snd_soc_add_codec_controls(codec, max9877_controls, 97SND_SOC_DAPM_INPUT("INB1"),
257 ARRAY_SIZE(max9877_controls)); 98SND_SOC_DAPM_INPUT("INB2"),
258} 99SND_SOC_DAPM_INPUT("RXIN+"),
259EXPORT_SYMBOL_GPL(max9877_add_controls); 100SND_SOC_DAPM_INPUT("RXIN-"),
101
102SND_SOC_DAPM_PGA("SHDN", MAX9877_OUTPUT_MODE, 7, 1, NULL, 0),
103
104SND_SOC_DAPM_OUTPUT("OUT+"),
105SND_SOC_DAPM_OUTPUT("OUT-"),
106SND_SOC_DAPM_OUTPUT("HPL"),
107SND_SOC_DAPM_OUTPUT("HPR"),
108};
109
110static const struct snd_soc_dapm_route max9877_dapm_routes[] = {
111 { "SHDN", NULL, "INA1" },
112 { "SHDN", NULL, "INA2" },
113 { "SHDN", NULL, "INB1" },
114 { "SHDN", NULL, "INB2" },
115
116 { "OUT+", NULL, "RXIN+" },
117 { "OUT+", NULL, "SHDN" },
118
119 { "OUT-", NULL, "SHDN" },
120 { "OUT-", NULL, "RXIN-" },
121
122 { "HPL", NULL, "SHDN" },
123 { "HPR", NULL, "SHDN" },
124};
125
126static const struct snd_soc_codec_driver max9877_codec = {
127 .controls = max9877_controls,
128 .num_controls = ARRAY_SIZE(max9877_controls),
129
130 .dapm_widgets = max9877_dapm_widgets,
131 .num_dapm_widgets = ARRAY_SIZE(max9877_dapm_widgets),
132 .dapm_routes = max9877_dapm_routes,
133 .num_dapm_routes = ARRAY_SIZE(max9877_dapm_routes),
134};
135
136static const struct regmap_config max9877_regmap = {
137 .reg_bits = 8,
138 .val_bits = 8,
139
140 .reg_defaults = max9877_regs,
141 .num_reg_defaults = ARRAY_SIZE(max9877_regs),
142 .cache_type = REGCACHE_RBTREE,
143};
260 144
261static int max9877_i2c_probe(struct i2c_client *client, 145static int max9877_i2c_probe(struct i2c_client *client,
262 const struct i2c_device_id *id) 146 const struct i2c_device_id *id)
263{ 147{
264 i2c = client; 148 int i;
265 149
266 max9877_write_regs(); 150 regmap = devm_regmap_init_i2c(client, &max9877_regmap);
151 if (IS_ERR(regmap))
152 return PTR_ERR(regmap);
267 153
268 return 0; 154 /* Ensure the device is in reset state */
155 for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
156 regmap_write(regmap, max9877_regs[i].reg, max9877_regs[i].def);
157
158 return snd_soc_register_codec(&client->dev, &max9877_codec, NULL, 0);
269} 159}
270 160
271static int max9877_i2c_remove(struct i2c_client *client) 161static int max9877_i2c_remove(struct i2c_client *client)
272{ 162{
273 i2c = NULL; 163 snd_soc_unregister_codec(&client->dev);
274 164
275 return 0; 165 return 0;
276} 166}
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 5402dfbbb716..4d3c8fd8c5db 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -94,7 +94,6 @@
94#define AUDIO_DAC_CFS_DLY_B (1 << 10) 94#define AUDIO_DAC_CFS_DLY_B (1 << 10)
95 95
96struct mc13783_priv { 96struct mc13783_priv {
97 struct snd_soc_codec codec;
98 struct mc13xxx *mc13xxx; 97 struct mc13xxx *mc13xxx;
99 98
100 enum mc13783_ssi_port adc_ssi_port; 99 enum mc13783_ssi_port adc_ssi_port;
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
new file mode 100644
index 000000000000..651ce0923675
--- /dev/null
+++ b/sound/soc/codecs/pcm1681.c
@@ -0,0 +1,339 @@
1/*
2 * PCM1681 ASoC codec driver
3 *
4 * Copyright (c) StreamUnlimited GmbH 2013
5 * Marek Belisko <marek.belisko@streamunlimited.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/delay.h>
21#include <linux/gpio.h>
22#include <linux/i2c.h>
23#include <linux/regmap.h>
24#include <linux/of_device.h>
25#include <linux/of_gpio.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/soc.h>
29#include <sound/tlv.h>
30
31#define PCM1681_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
32 SNDRV_PCM_FMTBIT_S24_LE)
33
34#define PCM1681_PCM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
35 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
36 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
37 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
38
39#define PCM1681_SOFT_MUTE_ALL 0xff
40#define PCM1681_DEEMPH_RATE_MASK 0x18
41#define PCM1681_DEEMPH_MASK 0x01
42
43#define PCM1681_ATT_CONTROL(X) (X <= 6 ? X : X + 9) /* Attenuation level */
44#define PCM1681_SOFT_MUTE 0x07 /* Soft mute control register */
45#define PCM1681_DAC_CONTROL 0x08 /* DAC operation control */
46#define PCM1681_FMT_CONTROL 0x09 /* Audio interface data format */
47#define PCM1681_DEEMPH_CONTROL 0x0a /* De-emphasis control */
48#define PCM1681_ZERO_DETECT_STATUS 0x0e /* Zero detect status reg */
49
50static const struct reg_default pcm1681_reg_defaults[] = {
51 { 0x01, 0xff },
52 { 0x02, 0xff },
53 { 0x03, 0xff },
54 { 0x04, 0xff },
55 { 0x05, 0xff },
56 { 0x06, 0xff },
57 { 0x07, 0x00 },
58 { 0x08, 0x00 },
59 { 0x09, 0x06 },
60 { 0x0A, 0x00 },
61 { 0x0B, 0xff },
62 { 0x0C, 0x0f },
63 { 0x0D, 0x00 },
64 { 0x10, 0xff },
65 { 0x11, 0xff },
66 { 0x12, 0x00 },
67 { 0x13, 0x00 },
68};
69
70static bool pcm1681_accessible_reg(struct device *dev, unsigned int reg)
71{
72 return !((reg == 0x00) || (reg == 0x0f));
73}
74
75static bool pcm1681_writeable_reg(struct device *dev, unsigned register reg)
76{
77 return pcm1681_accessible_reg(dev, reg) &&
78 (reg != PCM1681_ZERO_DETECT_STATUS);
79}
80
81struct pcm1681_private {
82 struct regmap *regmap;
83 unsigned int format;
84 /* Current deemphasis status */
85 unsigned int deemph;
86 /* Current rate for deemphasis control */
87 unsigned int rate;
88};
89
90static const int pcm1681_deemph[] = { 44100, 48000, 32000 };
91
92static int pcm1681_set_deemph(struct snd_soc_codec *codec)
93{
94 struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
95 int i = 0, val = -1, enable = 0;
96
97 if (priv->deemph)
98 for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++)
99 if (pcm1681_deemph[i] == priv->rate)
100 val = i;
101
102 if (val != -1) {
103 regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
104 PCM1681_DEEMPH_RATE_MASK, val);
105 enable = 1;
106 } else
107 enable = 0;
108
109 /* enable/disable deemphasis functionality */
110 return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
111 PCM1681_DEEMPH_MASK, enable);
112}
113
114static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
115 struct snd_ctl_elem_value *ucontrol)
116{
117 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
118 struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
119
120 ucontrol->value.enumerated.item[0] = priv->deemph;
121
122 return 0;
123}
124
125static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol,
126 struct snd_ctl_elem_value *ucontrol)
127{
128 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
129 struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
130
131 priv->deemph = ucontrol->value.enumerated.item[0];
132
133 return pcm1681_set_deemph(codec);
134}
135
136static int pcm1681_set_dai_fmt(struct snd_soc_dai *codec_dai,
137 unsigned int format)
138{
139 struct snd_soc_codec *codec = codec_dai->codec;
140 struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
141
142 /* The PCM1681 can only be slave to all clocks */
143 if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
144 dev_err(codec->dev, "Invalid clocking mode\n");
145 return -EINVAL;
146 }
147
148 priv->format = format;
149
150 return 0;
151}
152
153static int pcm1681_digital_mute(struct snd_soc_dai *dai, int mute)
154{
155 struct snd_soc_codec *codec = dai->codec;
156 struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
157 int val;
158
159 if (mute)
160 val = PCM1681_SOFT_MUTE_ALL;
161 else
162 val = 0;
163
164 return regmap_write(priv->regmap, PCM1681_SOFT_MUTE, val);
165}
166
167static int pcm1681_hw_params(struct snd_pcm_substream *substream,
168 struct snd_pcm_hw_params *params,
169 struct snd_soc_dai *dai)
170{
171 struct snd_soc_codec *codec = dai->codec;
172 struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
173 int val = 0, ret;
174 int pcm_format = params_format(params);
175
176 priv->rate = params_rate(params);
177
178 switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
179 case SND_SOC_DAIFMT_RIGHT_J:
180 if (pcm_format == SNDRV_PCM_FORMAT_S24_LE)
181 val = 0x00;
182 else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
183 val = 0x03;
184 break;
185 case SND_SOC_DAIFMT_I2S:
186 val = 0x04;
187 break;
188 case SND_SOC_DAIFMT_LEFT_J:
189 val = 0x05;
190 break;
191 default:
192 dev_err(codec->dev, "Invalid DAI format\n");
193 return -EINVAL;
194 }
195
196 ret = regmap_update_bits(priv->regmap, PCM1681_FMT_CONTROL, 0x0f, val);
197 if (ret < 0)
198 return ret;
199
200 return pcm1681_set_deemph(codec);
201}
202
203static const struct snd_soc_dai_ops pcm1681_dai_ops = {
204 .set_fmt = pcm1681_set_dai_fmt,
205 .hw_params = pcm1681_hw_params,
206 .digital_mute = pcm1681_digital_mute,
207};
208
209static const struct snd_soc_dapm_widget pcm1681_dapm_widgets[] = {
210SND_SOC_DAPM_OUTPUT("VOUT1"),
211SND_SOC_DAPM_OUTPUT("VOUT2"),
212SND_SOC_DAPM_OUTPUT("VOUT3"),
213SND_SOC_DAPM_OUTPUT("VOUT4"),
214SND_SOC_DAPM_OUTPUT("VOUT5"),
215SND_SOC_DAPM_OUTPUT("VOUT6"),
216SND_SOC_DAPM_OUTPUT("VOUT7"),
217SND_SOC_DAPM_OUTPUT("VOUT8"),
218};
219
220static const struct snd_soc_dapm_route pcm1681_dapm_routes[] = {
221 { "VOUT1", NULL, "Playback" },
222 { "VOUT2", NULL, "Playback" },
223 { "VOUT3", NULL, "Playback" },
224 { "VOUT4", NULL, "Playback" },
225 { "VOUT5", NULL, "Playback" },
226 { "VOUT6", NULL, "Playback" },
227 { "VOUT7", NULL, "Playback" },
228 { "VOUT8", NULL, "Playback" },
229};
230
231static const DECLARE_TLV_DB_SCALE(pcm1681_dac_tlv, -6350, 50, 1);
232
233static const struct snd_kcontrol_new pcm1681_controls[] = {
234 SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume",
235 PCM1681_ATT_CONTROL(1), PCM1681_ATT_CONTROL(2), 0,
236 0x7f, 0, pcm1681_dac_tlv),
237 SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume",
238 PCM1681_ATT_CONTROL(3), PCM1681_ATT_CONTROL(4), 0,
239 0x7f, 0, pcm1681_dac_tlv),
240 SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume",
241 PCM1681_ATT_CONTROL(5), PCM1681_ATT_CONTROL(6), 0,
242 0x7f, 0, pcm1681_dac_tlv),
243 SOC_DOUBLE_R_TLV("Channel 7/8 Playback Volume",
244 PCM1681_ATT_CONTROL(7), PCM1681_ATT_CONTROL(8), 0,
245 0x7f, 0, pcm1681_dac_tlv),
246 SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
247 pcm1681_get_deemph, pcm1681_put_deemph),
248};
249
250static struct snd_soc_dai_driver pcm1681_dai = {
251 .name = "pcm1681-hifi",
252 .playback = {
253 .stream_name = "Playback",
254 .channels_min = 2,
255 .channels_max = 8,
256 .rates = PCM1681_PCM_RATES,
257 .formats = PCM1681_PCM_FORMATS,
258 },
259 .ops = &pcm1681_dai_ops,
260};
261
262#ifdef CONFIG_OF
263static const struct of_device_id pcm1681_dt_ids[] = {
264 { .compatible = "ti,pcm1681", },
265 { }
266};
267MODULE_DEVICE_TABLE(of, pcm1681_dt_ids);
268#endif
269
270static const struct regmap_config pcm1681_regmap = {
271 .reg_bits = 8,
272 .val_bits = 8,
273 .max_register = ARRAY_SIZE(pcm1681_reg_defaults) + 1,
274 .reg_defaults = pcm1681_reg_defaults,
275 .num_reg_defaults = ARRAY_SIZE(pcm1681_reg_defaults),
276 .writeable_reg = pcm1681_writeable_reg,
277 .readable_reg = pcm1681_accessible_reg,
278};
279
280static struct snd_soc_codec_driver soc_codec_dev_pcm1681 = {
281 .controls = pcm1681_controls,
282 .num_controls = ARRAY_SIZE(pcm1681_controls),
283 .dapm_widgets = pcm1681_dapm_widgets,
284 .num_dapm_widgets = ARRAY_SIZE(pcm1681_dapm_widgets),
285 .dapm_routes = pcm1681_dapm_routes,
286 .num_dapm_routes = ARRAY_SIZE(pcm1681_dapm_routes),
287};
288
289static const struct i2c_device_id pcm1681_i2c_id[] = {
290 {"pcm1681", 0},
291 {}
292};
293MODULE_DEVICE_TABLE(i2c, pcm1681_i2c_id);
294
295static int pcm1681_i2c_probe(struct i2c_client *client,
296 const struct i2c_device_id *id)
297{
298 int ret;
299 struct pcm1681_private *priv;
300
301 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
302 if (!priv)
303 return -ENOMEM;
304
305 priv->regmap = devm_regmap_init_i2c(client, &pcm1681_regmap);
306 if (IS_ERR(priv->regmap)) {
307 ret = PTR_ERR(priv->regmap);
308 dev_err(&client->dev, "Failed to create regmap: %d\n", ret);
309 return ret;
310 }
311
312 i2c_set_clientdata(client, priv);
313
314 return snd_soc_register_codec(&client->dev, &soc_codec_dev_pcm1681,
315 &pcm1681_dai, 1);
316}
317
318static int pcm1681_i2c_remove(struct i2c_client *client)
319{
320 snd_soc_unregister_codec(&client->dev);
321 return 0;
322}
323
324static struct i2c_driver pcm1681_i2c_driver = {
325 .driver = {
326 .name = "pcm1681",
327 .owner = THIS_MODULE,
328 .of_match_table = of_match_ptr(pcm1681_dt_ids),
329 },
330 .id_table = pcm1681_i2c_id,
331 .probe = pcm1681_i2c_probe,
332 .remove = pcm1681_i2c_remove,
333};
334
335module_i2c_driver(pcm1681_i2c_driver);
336
337MODULE_DESCRIPTION("Texas Instruments PCM1681 ALSA SoC Codec Driver");
338MODULE_AUTHOR("Marek Belisko <marek.belisko@streamunlimited.com>");
339MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c
new file mode 100644
index 000000000000..2a8eccf64c76
--- /dev/null
+++ b/sound/soc/codecs/pcm1792a.c
@@ -0,0 +1,257 @@
1/*
2 * PCM1792A ASoC codec driver
3 *
4 * Copyright (c) Amarula Solutions B.V. 2013
5 *
6 * Michael Trimarchi <michael@amarulasolutions.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/module.h>
20#include <linux/slab.h>
21#include <linux/kernel.h>
22#include <linux/device.h>
23#include <linux/spi/spi.h>
24
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/initval.h>
29#include <sound/soc.h>
30#include <sound/tlv.h>
31#include <linux/of_device.h>
32
33#include "pcm1792a.h"
34
35#define PCM1792A_DAC_VOL_LEFT 0x10
36#define PCM1792A_DAC_VOL_RIGHT 0x11
37#define PCM1792A_FMT_CONTROL 0x12
38#define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL
39
40#define PCM1792A_FMT_MASK 0x70
41#define PCM1792A_FMT_SHIFT 4
42#define PCM1792A_MUTE_MASK 0x01
43#define PCM1792A_MUTE_SHIFT 0
44#define PCM1792A_ATLD_ENABLE (1 << 7)
45
46static const struct reg_default pcm1792a_reg_defaults[] = {
47 { 0x10, 0xff },
48 { 0x11, 0xff },
49 { 0x12, 0x50 },
50 { 0x13, 0x00 },
51 { 0x14, 0x00 },
52 { 0x15, 0x01 },
53 { 0x16, 0x00 },
54 { 0x17, 0x00 },
55};
56
57static bool pcm1792a_accessible_reg(struct device *dev, unsigned int reg)
58{
59 return reg >= 0x10 && reg <= 0x17;
60}
61
62static bool pcm1792a_writeable_reg(struct device *dev, unsigned register reg)
63{
64 bool accessible;
65
66 accessible = pcm1792a_accessible_reg(dev, reg);
67
68 return accessible && reg != 0x16 && reg != 0x17;
69}
70
71struct pcm1792a_private {
72 struct regmap *regmap;
73 unsigned int format;
74 unsigned int rate;
75};
76
77static int pcm1792a_set_dai_fmt(struct snd_soc_dai *codec_dai,
78 unsigned int format)
79{
80 struct snd_soc_codec *codec = codec_dai->codec;
81 struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
82
83 priv->format = format;
84
85 return 0;
86}
87
88static int pcm1792a_digital_mute(struct snd_soc_dai *dai, int mute)
89{
90 struct snd_soc_codec *codec = dai->codec;
91 struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
92 int ret;
93
94 ret = regmap_update_bits(priv->regmap, PCM1792A_SOFT_MUTE,
95 PCM1792A_MUTE_MASK, !!mute);
96 if (ret < 0)
97 return ret;
98
99 return 0;
100}
101
102static int pcm1792a_hw_params(struct snd_pcm_substream *substream,
103 struct snd_pcm_hw_params *params,
104 struct snd_soc_dai *dai)
105{
106 struct snd_soc_codec *codec = dai->codec;
107 struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
108 int val = 0, ret;
109 int pcm_format = params_format(params);
110
111 priv->rate = params_rate(params);
112
113 switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
114 case SND_SOC_DAIFMT_RIGHT_J:
115 if (pcm_format == SNDRV_PCM_FORMAT_S24_LE ||
116 pcm_format == SNDRV_PCM_FORMAT_S32_LE)
117 val = 0x02;
118 else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
119 val = 0x00;
120 break;
121 case SND_SOC_DAIFMT_I2S:
122 if (pcm_format == SNDRV_PCM_FORMAT_S24_LE ||
123 pcm_format == SNDRV_PCM_FORMAT_S32_LE)
124 val = 0x05;
125 else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE)
126 val = 0x04;
127 break;
128 default:
129 dev_err(codec->dev, "Invalid DAI format\n");
130 return -EINVAL;
131 }
132
133 val = val << PCM1792A_FMT_SHIFT | PCM1792A_ATLD_ENABLE;
134
135 ret = regmap_update_bits(priv->regmap, PCM1792A_FMT_CONTROL,
136 PCM1792A_FMT_MASK | PCM1792A_ATLD_ENABLE, val);
137 if (ret < 0)
138 return ret;
139
140 return 0;
141}
142
143static const struct snd_soc_dai_ops pcm1792a_dai_ops = {
144 .set_fmt = pcm1792a_set_dai_fmt,
145 .hw_params = pcm1792a_hw_params,
146 .digital_mute = pcm1792a_digital_mute,
147};
148
149static const DECLARE_TLV_DB_SCALE(pcm1792a_dac_tlv, -12000, 50, 1);
150
151static const struct snd_kcontrol_new pcm1792a_controls[] = {
152 SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT,
153 PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
154 pcm1792a_dac_tlv),
155};
156
157static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = {
158SND_SOC_DAPM_OUTPUT("IOUTL+"),
159SND_SOC_DAPM_OUTPUT("IOUTL-"),
160SND_SOC_DAPM_OUTPUT("IOUTR+"),
161SND_SOC_DAPM_OUTPUT("IOUTR-"),
162};
163
164static const struct snd_soc_dapm_route pcm1792a_dapm_routes[] = {
165 { "IOUTL+", NULL, "Playback" },
166 { "IOUTL-", NULL, "Playback" },
167 { "IOUTR+", NULL, "Playback" },
168 { "IOUTR-", NULL, "Playback" },
169};
170
171static struct snd_soc_dai_driver pcm1792a_dai = {
172 .name = "pcm1792a-hifi",
173 .playback = {
174 .stream_name = "Playback",
175 .channels_min = 2,
176 .channels_max = 2,
177 .rates = PCM1792A_RATES,
178 .formats = PCM1792A_FORMATS, },
179 .ops = &pcm1792a_dai_ops,
180};
181
182static const struct of_device_id pcm1792a_of_match[] = {
183 { .compatible = "ti,pcm1792a", },
184 { }
185};
186MODULE_DEVICE_TABLE(of, pcm1792a_of_match);
187
188static const struct regmap_config pcm1792a_regmap = {
189 .reg_bits = 8,
190 .val_bits = 8,
191 .max_register = 24,
192 .reg_defaults = pcm1792a_reg_defaults,
193 .num_reg_defaults = ARRAY_SIZE(pcm1792a_reg_defaults),
194 .writeable_reg = pcm1792a_writeable_reg,
195 .readable_reg = pcm1792a_accessible_reg,
196};
197
198static struct snd_soc_codec_driver soc_codec_dev_pcm1792a = {
199 .controls = pcm1792a_controls,
200 .num_controls = ARRAY_SIZE(pcm1792a_controls),
201 .dapm_widgets = pcm1792a_dapm_widgets,
202 .num_dapm_widgets = ARRAY_SIZE(pcm1792a_dapm_widgets),
203 .dapm_routes = pcm1792a_dapm_routes,
204 .num_dapm_routes = ARRAY_SIZE(pcm1792a_dapm_routes),
205};
206
207static int pcm1792a_spi_probe(struct spi_device *spi)
208{
209 struct pcm1792a_private *pcm1792a;
210 int ret;
211
212 pcm1792a = devm_kzalloc(&spi->dev, sizeof(struct pcm1792a_private),
213 GFP_KERNEL);
214 if (!pcm1792a)
215 return -ENOMEM;
216
217 spi_set_drvdata(spi, pcm1792a);
218
219 pcm1792a->regmap = devm_regmap_init_spi(spi, &pcm1792a_regmap);
220 if (IS_ERR(pcm1792a->regmap)) {
221 ret = PTR_ERR(pcm1792a->regmap);
222 dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
223 return ret;
224 }
225
226 return snd_soc_register_codec(&spi->dev,
227 &soc_codec_dev_pcm1792a, &pcm1792a_dai, 1);
228}
229
230static int pcm1792a_spi_remove(struct spi_device *spi)
231{
232 snd_soc_unregister_codec(&spi->dev);
233 return 0;
234}
235
236static const struct spi_device_id pcm1792a_spi_ids[] = {
237 { "pcm1792a", 0 },
238 { },
239};
240MODULE_DEVICE_TABLE(spi, pcm1792a_spi_ids);
241
242static struct spi_driver pcm1792a_codec_driver = {
243 .driver = {
244 .name = "pcm1792a",
245 .owner = THIS_MODULE,
246 .of_match_table = of_match_ptr(pcm1792a_of_match),
247 },
248 .id_table = pcm1792a_spi_ids,
249 .probe = pcm1792a_spi_probe,
250 .remove = pcm1792a_spi_remove,
251};
252
253module_spi_driver(pcm1792a_codec_driver);
254
255MODULE_DESCRIPTION("ASoC PCM1792A driver");
256MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
257MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm1792a.h b/sound/soc/codecs/pcm1792a.h
new file mode 100644
index 000000000000..7a83d1fc102a
--- /dev/null
+++ b/sound/soc/codecs/pcm1792a.h
@@ -0,0 +1,26 @@
1/*
2 * definitions for PCM1792A
3 *
4 * Copyright 2013 Amarula Solutions
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#ifndef __PCM1792A_H__
18#define __PCM1792A_H__
19
20#define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \
21 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
22
23#define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
24 SNDRV_PCM_FMTBIT_S16_LE)
25
26#endif
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index f2a6282b41f4..b6618c4a7597 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -28,7 +28,54 @@
28 28
29#include "pcm3008.h" 29#include "pcm3008.h"
30 30
31#define PCM3008_VERSION "0.2" 31static int pcm3008_dac_ev(struct snd_soc_dapm_widget *w,
32 struct snd_kcontrol *kcontrol,
33 int event)
34{
35 struct snd_soc_codec *codec = w->codec;
36 struct pcm3008_setup_data *setup = codec->dev->platform_data;
37
38 gpio_set_value_cansleep(setup->pdda_pin,
39 SND_SOC_DAPM_EVENT_ON(event));
40
41 return 0;
42}
43
44static int pcm3008_adc_ev(struct snd_soc_dapm_widget *w,
45 struct snd_kcontrol *kcontrol,
46 int event)
47{
48 struct snd_soc_codec *codec = w->codec;
49 struct pcm3008_setup_data *setup = codec->dev->platform_data;
50
51 gpio_set_value_cansleep(setup->pdad_pin,
52 SND_SOC_DAPM_EVENT_ON(event));
53
54 return 0;
55}
56
57static const struct snd_soc_dapm_widget pcm3008_dapm_widgets[] = {
58SND_SOC_DAPM_INPUT("VINL"),
59SND_SOC_DAPM_INPUT("VINR"),
60
61SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, pcm3008_dac_ev,
62 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
63SND_SOC_DAPM_ADC_E("ADC", NULL, SND_SOC_NOPM, 0, 0, pcm3008_adc_ev,
64 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
65
66SND_SOC_DAPM_OUTPUT("VOUTL"),
67SND_SOC_DAPM_OUTPUT("VOUTR"),
68};
69
70static const struct snd_soc_dapm_route pcm3008_dapm_routes[] = {
71 { "PCM3008 Capture", NULL, "ADC" },
72 { "ADC", NULL, "VINL" },
73 { "ADC", NULL, "VINR" },
74
75 { "DAC", NULL, "PCM3008 Playback" },
76 { "VOUTL", NULL, "DAC" },
77 { "VOUTR", NULL, "DAC" },
78};
32 79
33#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 80#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
34 SNDRV_PCM_RATE_48000) 81 SNDRV_PCM_RATE_48000)
@@ -51,20 +98,20 @@ static struct snd_soc_dai_driver pcm3008_dai = {
51 }, 98 },
52}; 99};
53 100
54static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) 101static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
55{ 102 .dapm_widgets = pcm3008_dapm_widgets,
56 gpio_free(setup->dem0_pin); 103 .num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets),
57 gpio_free(setup->dem1_pin); 104 .dapm_routes = pcm3008_dapm_routes,
58 gpio_free(setup->pdad_pin); 105 .num_dapm_routes = ARRAY_SIZE(pcm3008_dapm_routes),
59 gpio_free(setup->pdda_pin); 106};
60}
61 107
62static int pcm3008_soc_probe(struct snd_soc_codec *codec) 108static int pcm3008_codec_probe(struct platform_device *pdev)
63{ 109{
64 struct pcm3008_setup_data *setup = codec->dev->platform_data; 110 struct pcm3008_setup_data *setup = pdev->dev.platform_data;
65 int ret = 0; 111 int ret;
66 112
67 printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); 113 if (!setup)
114 return -EINVAL;
68 115
69 /* DEM1 DEM0 DE-EMPHASIS_MODE 116 /* DEM1 DEM0 DE-EMPHASIS_MODE
70 * Low Low De-emphasis 44.1 kHz ON 117 * Low Low De-emphasis 44.1 kHz ON
@@ -74,83 +121,29 @@ static int pcm3008_soc_probe(struct snd_soc_codec *codec)
74 */ 121 */
75 122
76 /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */ 123 /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
77 ret = gpio_request(setup->dem0_pin, "codec_dem0"); 124 ret = devm_gpio_request_one(&pdev->dev, setup->dem0_pin,
78 if (ret == 0) 125 GPIOF_OUT_INIT_HIGH, "codec_dem0");
79 ret = gpio_direction_output(setup->dem0_pin, 1);
80 if (ret != 0) 126 if (ret != 0)
81 goto gpio_err; 127 return ret;
82 128
83 /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */ 129 /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
84 ret = gpio_request(setup->dem1_pin, "codec_dem1"); 130 ret = devm_gpio_request_one(&pdev->dev, setup->dem1_pin,
85 if (ret == 0) 131 GPIOF_OUT_INIT_LOW, "codec_dem1");
86 ret = gpio_direction_output(setup->dem1_pin, 0);
87 if (ret != 0) 132 if (ret != 0)
88 goto gpio_err; 133 return ret;
89 134
90 /* Configure PDAD GPIO. */ 135 /* Configure PDAD GPIO. */
91 ret = gpio_request(setup->pdad_pin, "codec_pdad"); 136 ret = devm_gpio_request_one(&pdev->dev, setup->pdad_pin,
92 if (ret == 0) 137 GPIOF_OUT_INIT_LOW, "codec_pdad");
93 ret = gpio_direction_output(setup->pdad_pin, 1);
94 if (ret != 0) 138 if (ret != 0)
95 goto gpio_err; 139 return ret;
96 140
97 /* Configure PDDA GPIO. */ 141 /* Configure PDDA GPIO. */
98 ret = gpio_request(setup->pdda_pin, "codec_pdda"); 142 ret = devm_gpio_request_one(&pdev->dev, setup->pdda_pin,
99 if (ret == 0) 143 GPIOF_OUT_INIT_LOW, "codec_pdda");
100 ret = gpio_direction_output(setup->pdda_pin, 1);
101 if (ret != 0) 144 if (ret != 0)
102 goto gpio_err; 145 return ret;
103
104 return ret;
105
106gpio_err:
107 pcm3008_gpio_free(setup);
108 146
109 return ret;
110}
111
112static int pcm3008_soc_remove(struct snd_soc_codec *codec)
113{
114 struct pcm3008_setup_data *setup = codec->dev->platform_data;
115
116 pcm3008_gpio_free(setup);
117 return 0;
118}
119
120#ifdef CONFIG_PM
121static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
122{
123 struct pcm3008_setup_data *setup = codec->dev->platform_data;
124
125 gpio_set_value(setup->pdad_pin, 0);
126 gpio_set_value(setup->pdda_pin, 0);
127
128 return 0;
129}
130
131static int pcm3008_soc_resume(struct snd_soc_codec *codec)
132{
133 struct pcm3008_setup_data *setup = codec->dev->platform_data;
134
135 gpio_set_value(setup->pdad_pin, 1);
136 gpio_set_value(setup->pdda_pin, 1);
137
138 return 0;
139}
140#else
141#define pcm3008_soc_suspend NULL
142#define pcm3008_soc_resume NULL
143#endif
144
145static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
146 .probe = pcm3008_soc_probe,
147 .remove = pcm3008_soc_remove,
148 .suspend = pcm3008_soc_suspend,
149 .resume = pcm3008_soc_resume,
150};
151
152static int pcm3008_codec_probe(struct platform_device *pdev)
153{
154 return snd_soc_register_codec(&pdev->dev, 147 return snd_soc_register_codec(&pdev->dev,
155 &soc_codec_dev_pcm3008, &pcm3008_dai, 1); 148 &soc_codec_dev_pcm3008, &pcm3008_dai, 1);
156} 149}
@@ -158,6 +151,7 @@ static int pcm3008_codec_probe(struct platform_device *pdev)
158static int pcm3008_codec_remove(struct platform_device *pdev) 151static int pcm3008_codec_remove(struct platform_device *pdev)
159{ 152{
160 snd_soc_unregister_codec(&pdev->dev); 153 snd_soc_unregister_codec(&pdev->dev);
154
161 return 0; 155 return 0;
162} 156}
163 157
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index ce585e37e38a..4db7314baabc 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -737,29 +737,6 @@ static const struct snd_kcontrol_new rt5640_mono_mix[] = {
737 RT5640_M_BST1_MM_SFT, 1, 1), 737 RT5640_M_BST1_MM_SFT, 1, 1),
738}; 738};
739 739
740/* INL/R source */
741static const char * const rt5640_inl_src[] = {
742 "IN2P", "MONOP"
743};
744
745static const SOC_ENUM_SINGLE_DECL(
746 rt5640_inl_enum, RT5640_INL_INR_VOL,
747 RT5640_INL_SEL_SFT, rt5640_inl_src);
748
749static const struct snd_kcontrol_new rt5640_inl_mux =
750 SOC_DAPM_ENUM("INL source", rt5640_inl_enum);
751
752static const char * const rt5640_inr_src[] = {
753 "IN2N", "MONON"
754};
755
756static const SOC_ENUM_SINGLE_DECL(
757 rt5640_inr_enum, RT5640_INL_INR_VOL,
758 RT5640_INR_SEL_SFT, rt5640_inr_src);
759
760static const struct snd_kcontrol_new rt5640_inr_mux =
761 SOC_DAPM_ENUM("INR source", rt5640_inr_enum);
762
763/* Stereo ADC source */ 740/* Stereo ADC source */
764static const char * const rt5640_stereo_adc1_src[] = { 741static const char * const rt5640_stereo_adc1_src[] = {
765 "DIG MIX", "ADC" 742 "DIG MIX", "ADC"
@@ -1005,9 +982,6 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
1005 RT5640_PWR_IN_L_BIT, 0, NULL, 0), 982 RT5640_PWR_IN_L_BIT, 0, NULL, 0),
1006 SND_SOC_DAPM_PGA("INR VOL", RT5640_PWR_VOL, 983 SND_SOC_DAPM_PGA("INR VOL", RT5640_PWR_VOL,
1007 RT5640_PWR_IN_R_BIT, 0, NULL, 0), 984 RT5640_PWR_IN_R_BIT, 0, NULL, 0),
1008 /* IN Mux */
1009 SND_SOC_DAPM_MUX("INL Mux", SND_SOC_NOPM, 0, 0, &rt5640_inl_mux),
1010 SND_SOC_DAPM_MUX("INR Mux", SND_SOC_NOPM, 0, 0, &rt5640_inr_mux),
1011 /* REC Mixer */ 985 /* REC Mixer */
1012 SND_SOC_DAPM_MIXER("RECMIXL", RT5640_PWR_MIXER, RT5640_PWR_RM_L_BIT, 0, 986 SND_SOC_DAPM_MIXER("RECMIXL", RT5640_PWR_MIXER, RT5640_PWR_RM_L_BIT, 0,
1013 rt5640_rec_l_mix, ARRAY_SIZE(rt5640_rec_l_mix)), 987 rt5640_rec_l_mix, ARRAY_SIZE(rt5640_rec_l_mix)),
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 760e8bfeacaa..1f4093f3f3a1 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -654,16 +654,19 @@ static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate)
654 snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, 654 snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
655 SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, 655 SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
656 SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP); 656 SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP);
657
658 /* if using pll, clk_ctrl must be set after pll power up */
659 snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
657 } else { 660 } else {
661 /* otherwise, clk_ctrl must be set before pll power down */
662 snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
663
658 /* power down pll */ 664 /* power down pll */
659 snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, 665 snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
660 SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, 666 SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
661 0); 667 0);
662 } 668 }
663 669
664 /* if using pll, clk_ctrl must be set after pll power up */
665 snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
666
667 return 0; 670 return 0;
668} 671}
669 672
@@ -1480,6 +1483,7 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
1480static const struct regmap_config sgtl5000_regmap = { 1483static const struct regmap_config sgtl5000_regmap = {
1481 .reg_bits = 16, 1484 .reg_bits = 16,
1482 .val_bits = 16, 1485 .val_bits = 16,
1486 .reg_stride = 2,
1483 1487
1484 .max_register = SGTL5000_MAX_REG_OFFSET, 1488 .max_register = SGTL5000_MAX_REG_OFFSET,
1485 .volatile_reg = sgtl5000_volatile, 1489 .volatile_reg = sgtl5000_volatile,
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 73e205c892a0..38f3b105c17d 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -102,6 +102,16 @@ static int si476x_codec_write(struct snd_soc_codec *codec,
102 return err; 102 return err;
103} 103}
104 104
105static const struct snd_soc_dapm_widget si476x_dapm_widgets[] = {
106SND_SOC_DAPM_OUTPUT("LOUT"),
107SND_SOC_DAPM_OUTPUT("ROUT"),
108};
109
110static const struct snd_soc_dapm_route si476x_dapm_routes[] = {
111 { "Capture", NULL, "LOUT" },
112 { "Capture", NULL, "ROUT" },
113};
114
105static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, 115static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
106 unsigned int fmt) 116 unsigned int fmt)
107{ 117{
@@ -260,6 +270,10 @@ static struct snd_soc_codec_driver soc_codec_dev_si476x = {
260 .probe = si476x_codec_probe, 270 .probe = si476x_codec_probe,
261 .read = si476x_codec_read, 271 .read = si476x_codec_read,
262 .write = si476x_codec_write, 272 .write = si476x_codec_write,
273 .dapm_widgets = si476x_dapm_widgets,
274 .num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets),
275 .dapm_routes = si476x_dapm_routes,
276 .num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes),
263}; 277};
264 278
265static int si476x_platform_probe(struct platform_device *pdev) 279static int si476x_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c
index e9d7881ed2c8..e3501f40c7b3 100644
--- a/sound/soc/codecs/spdif_receiver.c
+++ b/sound/soc/codecs/spdif_receiver.c
@@ -23,11 +23,26 @@
23#include <sound/initval.h> 23#include <sound/initval.h>
24#include <linux/of.h> 24#include <linux/of.h>
25 25
26static const struct snd_soc_dapm_widget dir_widgets[] = {
27 SND_SOC_DAPM_INPUT("spdif-in"),
28};
29
30static const struct snd_soc_dapm_route dir_routes[] = {
31 { "Capture", NULL, "spdif-in" },
32};
33
26#define STUB_RATES SNDRV_PCM_RATE_8000_192000 34#define STUB_RATES SNDRV_PCM_RATE_8000_192000
27#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 35#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
36 SNDRV_PCM_FMTBIT_S20_3LE | \
37 SNDRV_PCM_FMTBIT_S24_LE | \
28 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) 38 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
29 39
30static struct snd_soc_codec_driver soc_codec_spdif_dir; 40static struct snd_soc_codec_driver soc_codec_spdif_dir = {
41 .dapm_widgets = dir_widgets,
42 .num_dapm_widgets = ARRAY_SIZE(dir_widgets),
43 .dapm_routes = dir_routes,
44 .num_dapm_routes = ARRAY_SIZE(dir_routes),
45};
31 46
32static struct snd_soc_dai_driver dir_stub_dai = { 47static struct snd_soc_dai_driver dir_stub_dai = {
33 .name = "dir-hifi", 48 .name = "dir-hifi",
diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c
index 18280499fd55..a078aa31052a 100644
--- a/sound/soc/codecs/spdif_transmitter.c
+++ b/sound/soc/codecs/spdif_transmitter.c
@@ -25,10 +25,24 @@
25#define DRV_NAME "spdif-dit" 25#define DRV_NAME "spdif-dit"
26 26
27#define STUB_RATES SNDRV_PCM_RATE_8000_96000 27#define STUB_RATES SNDRV_PCM_RATE_8000_96000
28#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE 28#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
29 SNDRV_PCM_FMTBIT_S20_3LE | \
30 SNDRV_PCM_FMTBIT_S24_LE)
29 31
32static const struct snd_soc_dapm_widget dit_widgets[] = {
33 SND_SOC_DAPM_OUTPUT("spdif-out"),
34};
35
36static const struct snd_soc_dapm_route dit_routes[] = {
37 { "spdif-out", NULL, "Playback" },
38};
30 39
31static struct snd_soc_codec_driver soc_codec_spdif_dit; 40static struct snd_soc_codec_driver soc_codec_spdif_dit = {
41 .dapm_widgets = dit_widgets,
42 .num_dapm_widgets = ARRAY_SIZE(dit_widgets),
43 .dapm_routes = dit_routes,
44 .num_dapm_routes = ARRAY_SIZE(dit_routes),
45};
32 46
33static struct snd_soc_dai_driver dit_stub_dai = { 47static struct snd_soc_dai_driver dit_stub_dai = {
34 .name = "dit-hifi", 48 .name = "dit-hifi",
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index cfb55fe35e98..06edb396e733 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -363,16 +363,18 @@ static void sta32x_watchdog(struct work_struct *work)
363 } 363 }
364 364
365 if (!sta32x->shutdown) 365 if (!sta32x->shutdown)
366 schedule_delayed_work(&sta32x->watchdog_work, 366 queue_delayed_work(system_power_efficient_wq,
367 round_jiffies_relative(HZ)); 367 &sta32x->watchdog_work,
368 round_jiffies_relative(HZ));
368} 369}
369 370
370static void sta32x_watchdog_start(struct sta32x_priv *sta32x) 371static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
371{ 372{
372 if (sta32x->pdata->needs_esd_watchdog) { 373 if (sta32x->pdata->needs_esd_watchdog) {
373 sta32x->shutdown = 0; 374 sta32x->shutdown = 0;
374 schedule_delayed_work(&sta32x->watchdog_work, 375 queue_delayed_work(system_power_efficient_wq,
375 round_jiffies_relative(HZ)); 376 &sta32x->watchdog_work,
377 round_jiffies_relative(HZ));
376 } 378 }
377} 379}
378 380
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index b1f6982c7c9c..7b8f3d965f43 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -29,7 +29,7 @@ MODULE_LICENSE("GPL");
29/* AIC26 driver private data */ 29/* AIC26 driver private data */
30struct aic26 { 30struct aic26 {
31 struct spi_device *spi; 31 struct spi_device *spi;
32 struct snd_soc_codec codec; 32 struct snd_soc_codec *codec;
33 int master; 33 int master;
34 int datfm; 34 int datfm;
35 int mclk; 35 int mclk;
@@ -119,6 +119,22 @@ static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
119 return 0; 119 return 0;
120} 120}
121 121
122static const struct snd_soc_dapm_widget tlv320aic26_dapm_widgets[] = {
123SND_SOC_DAPM_INPUT("MICIN"),
124SND_SOC_DAPM_INPUT("AUX"),
125
126SND_SOC_DAPM_OUTPUT("HPL"),
127SND_SOC_DAPM_OUTPUT("HPR"),
128};
129
130static const struct snd_soc_dapm_route tlv320aic26_dapm_routes[] = {
131 { "Capture", NULL, "MICIN" },
132 { "Capture", NULL, "AUX" },
133
134 { "HPL", NULL, "Playback" },
135 { "HPR", NULL, "Playback" },
136};
137
122/* --------------------------------------------------------------------- 138/* ---------------------------------------------------------------------
123 * Digital Audio Interface Operations 139 * Digital Audio Interface Operations
124 */ 140 */
@@ -174,9 +190,9 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
174 dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval); 190 dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval);
175 qval = 0; 191 qval = 0;
176 reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; 192 reg = 0x8000 | qval << 11 | pval << 8 | jval << 2;
177 aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); 193 snd_soc_write(codec, AIC26_REG_PLL_PROG1, reg);
178 reg = dval << 2; 194 reg = dval << 2;
179 aic26_reg_write(codec, AIC26_REG_PLL_PROG2, reg); 195 snd_soc_write(codec, AIC26_REG_PLL_PROG2, reg);
180 196
181 /* Audio Control 3 (master mode, fsref rate) */ 197 /* Audio Control 3 (master mode, fsref rate) */
182 reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3); 198 reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3);
@@ -185,13 +201,13 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
185 reg |= 0x0800; 201 reg |= 0x0800;
186 if (fsref == 48000) 202 if (fsref == 48000)
187 reg |= 0x2000; 203 reg |= 0x2000;
188 aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); 204 snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
189 205
190 /* Audio Control 1 (FSref divisor) */ 206 /* Audio Control 1 (FSref divisor) */
191 reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1); 207 reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1);
192 reg &= ~0x0fff; 208 reg &= ~0x0fff;
193 reg |= wlen | aic26->datfm | (divisor << 3) | divisor; 209 reg |= wlen | aic26->datfm | (divisor << 3) | divisor;
194 aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL1, reg); 210 snd_soc_write(codec, AIC26_REG_AUDIO_CTRL1, reg);
195 211
196 return 0; 212 return 0;
197} 213}
@@ -212,7 +228,7 @@ static int aic26_mute(struct snd_soc_dai *dai, int mute)
212 reg |= 0x8080; 228 reg |= 0x8080;
213 else 229 else
214 reg &= ~0x8080; 230 reg &= ~0x8080;
215 aic26_reg_write(codec, AIC26_REG_DAC_GAIN, reg); 231 snd_soc_write(codec, AIC26_REG_DAC_GAIN, reg);
216 232
217 return 0; 233 return 0;
218} 234}
@@ -330,7 +346,7 @@ static ssize_t aic26_keyclick_show(struct device *dev,
330 struct aic26 *aic26 = dev_get_drvdata(dev); 346 struct aic26 *aic26 = dev_get_drvdata(dev);
331 int val, amp, freq, len; 347 int val, amp, freq, len;
332 348
333 val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2); 349 val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
334 amp = (val >> 12) & 0x7; 350 amp = (val >> 12) & 0x7;
335 freq = (125 << ((val >> 8) & 0x7)) >> 1; 351 freq = (125 << ((val >> 8) & 0x7)) >> 1;
336 len = 2 * (1 + ((val >> 4) & 0xf)); 352 len = 2 * (1 + ((val >> 4) & 0xf));
@@ -346,9 +362,9 @@ static ssize_t aic26_keyclick_set(struct device *dev,
346 struct aic26 *aic26 = dev_get_drvdata(dev); 362 struct aic26 *aic26 = dev_get_drvdata(dev);
347 int val; 363 int val;
348 364
349 val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2); 365 val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
350 val |= 0x8000; 366 val |= 0x8000;
351 aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL2, val); 367 snd_soc_write(aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
352 368
353 return count; 369 return count;
354} 370}
@@ -360,25 +376,26 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
360 */ 376 */
361static int aic26_probe(struct snd_soc_codec *codec) 377static int aic26_probe(struct snd_soc_codec *codec)
362{ 378{
379 struct aic26 *aic26 = dev_get_drvdata(codec->dev);
363 int ret, err, i, reg; 380 int ret, err, i, reg;
364 381
365 dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n"); 382 aic26->codec = codec;
366 383
367 /* Reset the codec to power on defaults */ 384 /* Reset the codec to power on defaults */
368 aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00); 385 snd_soc_write(codec, AIC26_REG_RESET, 0xBB00);
369 386
370 /* Power up CODEC */ 387 /* Power up CODEC */
371 aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0); 388 snd_soc_write(codec, AIC26_REG_POWER_CTRL, 0);
372 389
373 /* Audio Control 3 (master mode, fsref rate) */ 390 /* Audio Control 3 (master mode, fsref rate) */
374 reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3); 391 reg = snd_soc_read(codec, AIC26_REG_AUDIO_CTRL3);
375 reg &= ~0xf800; 392 reg &= ~0xf800;
376 reg |= 0x0800; /* set master mode */ 393 reg |= 0x0800; /* set master mode */
377 aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); 394 snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
378 395
379 /* Fill register cache */ 396 /* Fill register cache */
380 for (i = 0; i < codec->driver->reg_cache_size; i++) 397 for (i = 0; i < codec->driver->reg_cache_size; i++)
381 aic26_reg_read(codec, i); 398 snd_soc_read(codec, i);
382 399
383 /* Register the sysfs files for debugging */ 400 /* Register the sysfs files for debugging */
384 /* Create SysFS files */ 401 /* Create SysFS files */
@@ -401,6 +418,10 @@ static struct snd_soc_codec_driver aic26_soc_codec_dev = {
401 .write = aic26_reg_write, 418 .write = aic26_reg_write,
402 .reg_cache_size = AIC26_NUM_REGS, 419 .reg_cache_size = AIC26_NUM_REGS,
403 .reg_word_size = sizeof(u16), 420 .reg_word_size = sizeof(u16),
421 .dapm_widgets = tlv320aic26_dapm_widgets,
422 .num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets),
423 .dapm_routes = tlv320aic26_dapm_routes,
424 .num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes),
404}; 425};
405 426
406/* --------------------------------------------------------------------- 427/* ---------------------------------------------------------------------
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index e5b926883131..6e3f269243e0 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -138,8 +138,7 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
138static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, 138static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
139 struct snd_ctl_elem_value *ucontrol) 139 struct snd_ctl_elem_value *ucontrol)
140{ 140{
141 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 141 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
142 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
143 struct soc_mixer_control *mc = 142 struct soc_mixer_control *mc =
144 (struct soc_mixer_control *)kcontrol->private_value; 143 (struct soc_mixer_control *)kcontrol->private_value;
145 unsigned int reg = mc->reg; 144 unsigned int reg = mc->reg;
@@ -147,10 +146,9 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
147 int max = mc->max; 146 int max = mc->max;
148 unsigned int mask = (1 << fls(max)) - 1; 147 unsigned int mask = (1 << fls(max)) - 1;
149 unsigned int invert = mc->invert; 148 unsigned int invert = mc->invert;
150 unsigned short val, val_mask; 149 unsigned short val;
151 int ret; 150 struct snd_soc_dapm_update update;
152 struct snd_soc_dapm_path *path; 151 int connect, change;
153 int found = 0;
154 152
155 val = (ucontrol->value.integer.value[0] & mask); 153 val = (ucontrol->value.integer.value[0] & mask);
156 154
@@ -158,42 +156,26 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
158 if (val) 156 if (val)
159 val = mask; 157 val = mask;
160 158
159 connect = !!val;
160
161 if (invert) 161 if (invert)
162 val = mask - val; 162 val = mask - val;
163 val_mask = mask << shift;
164 val = val << shift;
165
166 mutex_lock(&widget->codec->mutex);
167 163
168 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { 164 mask <<= shift;
169 /* find dapm widget path assoc with kcontrol */ 165 val <<= shift;
170 list_for_each_entry(path, &widget->dapm->card->paths, list) {
171 if (path->kcontrol != kcontrol)
172 continue;
173 166
174 /* found, now check type */ 167 change = snd_soc_test_bits(codec, val, mask, reg);
175 found = 1; 168 if (change) {
176 if (val) 169 update.kcontrol = kcontrol;
177 /* new connection */ 170 update.reg = reg;
178 path->connect = invert ? 0 : 1; 171 update.mask = mask;
179 else 172 update.val = val;
180 /* old connection must be powered down */
181 path->connect = invert ? 1 : 0;
182 173
183 dapm_mark_dirty(path->source, "tlv320aic3x source"); 174 snd_soc_dapm_mixer_update_power(&codec->dapm, kcontrol, connect,
184 dapm_mark_dirty(path->sink, "tlv320aic3x sink"); 175 &update);
185
186 break;
187 }
188 } 176 }
189 177
190 mutex_unlock(&widget->codec->mutex); 178 return change;
191
192 if (found)
193 snd_soc_dapm_sync(widget->dapm);
194
195 ret = snd_soc_update_bits_locked(widget->codec, reg, val_mask, val);
196 return ret;
197} 179}
198 180
199/* 181/*
@@ -1492,6 +1474,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
1492 { "tlv320aic3x", AIC3X_MODEL_3X }, 1474 { "tlv320aic3x", AIC3X_MODEL_3X },
1493 { "tlv320aic33", AIC3X_MODEL_33 }, 1475 { "tlv320aic33", AIC3X_MODEL_33 },
1494 { "tlv320aic3007", AIC3X_MODEL_3007 }, 1476 { "tlv320aic3007", AIC3X_MODEL_3007 },
1477 { "tlv320aic3106", AIC3X_MODEL_3X },
1495 { } 1478 { }
1496}; 1479};
1497MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); 1480MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@@ -1582,6 +1565,9 @@ static int aic3x_i2c_remove(struct i2c_client *client)
1582#if defined(CONFIG_OF) 1565#if defined(CONFIG_OF)
1583static const struct of_device_id tlv320aic3x_of_match[] = { 1566static const struct of_device_id tlv320aic3x_of_match[] = {
1584 { .compatible = "ti,tlv320aic3x", }, 1567 { .compatible = "ti,tlv320aic3x", },
1568 { .compatible = "ti,tlv320aic33" },
1569 { .compatible = "ti,tlv320aic3007" },
1570 { .compatible = "ti,tlv320aic3106" },
1585 {}, 1571 {},
1586}; 1572};
1587MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); 1573MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 8e6e5b016021..1e3884d6b3fb 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -137,8 +137,6 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
137 137
138/* codec private data */ 138/* codec private data */
139struct twl4030_priv { 139struct twl4030_priv {
140 struct snd_soc_codec codec;
141
142 unsigned int codec_powered; 140 unsigned int codec_powered;
143 141
144 /* reference counts of AIF/APLL users */ 142 /* reference counts of AIF/APLL users */
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 44621ddc332d..3c79dbb6c323 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -429,7 +429,8 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
429 struct snd_soc_codec *codec = data; 429 struct snd_soc_codec *codec = data;
430 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 430 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
431 431
432 schedule_delayed_work(&priv->hs_jack.work, msecs_to_jiffies(200)); 432 queue_delayed_work(system_power_efficient_wq,
433 &priv->hs_jack.work, msecs_to_jiffies(200));
433 434
434 return IRQ_HANDLED; 435 return IRQ_HANDLED;
435} 436}
@@ -437,9 +438,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
437static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, 438static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
438 struct snd_ctl_elem_value *ucontrol) 439 struct snd_ctl_elem_value *ucontrol)
439{ 440{
440 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 441 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
441 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
442 struct snd_soc_codec *codec = widget->codec;
443 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 442 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
444 unsigned int val; 443 unsigned int val;
445 444
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 6d0aa44c3757..c94d4c1e3dac 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -325,7 +325,6 @@ static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
325static int uda134x_set_bias_level(struct snd_soc_codec *codec, 325static int uda134x_set_bias_level(struct snd_soc_codec *codec,
326 enum snd_soc_bias_level level) 326 enum snd_soc_bias_level level)
327{ 327{
328 u8 reg;
329 struct uda134x_platform_data *pd = codec->control_data; 328 struct uda134x_platform_data *pd = codec->control_data;
330 int i; 329 int i;
331 u8 *cache = codec->reg_cache; 330 u8 *cache = codec->reg_cache;
@@ -334,23 +333,6 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
334 333
335 switch (level) { 334 switch (level) {
336 case SND_SOC_BIAS_ON: 335 case SND_SOC_BIAS_ON:
337 /* ADC, DAC on */
338 switch (pd->model) {
339 case UDA134X_UDA1340:
340 case UDA134X_UDA1344:
341 case UDA134X_UDA1345:
342 reg = uda134x_read_reg_cache(codec, UDA134X_DATA011);
343 uda134x_write(codec, UDA134X_DATA011, reg | 0x03);
344 break;
345 case UDA134X_UDA1341:
346 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
347 uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
348 break;
349 default:
350 printk(KERN_ERR "UDA134X SoC codec: "
351 "unsupported model %d\n", pd->model);
352 return -EINVAL;
353 }
354 break; 336 break;
355 case SND_SOC_BIAS_PREPARE: 337 case SND_SOC_BIAS_PREPARE:
356 /* power on */ 338 /* power on */
@@ -362,23 +344,6 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
362 } 344 }
363 break; 345 break;
364 case SND_SOC_BIAS_STANDBY: 346 case SND_SOC_BIAS_STANDBY:
365 /* ADC, DAC power off */
366 switch (pd->model) {
367 case UDA134X_UDA1340:
368 case UDA134X_UDA1344:
369 case UDA134X_UDA1345:
370 reg = uda134x_read_reg_cache(codec, UDA134X_DATA011);
371 uda134x_write(codec, UDA134X_DATA011, reg & ~(0x03));
372 break;
373 case UDA134X_UDA1341:
374 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
375 uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
376 break;
377 default:
378 printk(KERN_ERR "UDA134X SoC codec: "
379 "unsupported model %d\n", pd->model);
380 return -EINVAL;
381 }
382 break; 347 break;
383 case SND_SOC_BIAS_OFF: 348 case SND_SOC_BIAS_OFF:
384 /* power off */ 349 /* power off */
@@ -450,6 +415,37 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
450SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), 415SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
451}; 416};
452 417
418/* UDA1341 has the DAC/ADC power down in STATUS1 */
419static const struct snd_soc_dapm_widget uda1341_dapm_widgets[] = {
420 SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_STATUS1, 0, 0),
421 SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_STATUS1, 1, 0),
422};
423
424/* UDA1340/4/5 has the DAC/ADC pwoer down in DATA0 11 */
425static const struct snd_soc_dapm_widget uda1340_dapm_widgets[] = {
426 SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_DATA011, 0, 0),
427 SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_DATA011, 1, 0),
428};
429
430/* Common DAPM widgets */
431static const struct snd_soc_dapm_widget uda134x_dapm_widgets[] = {
432 SND_SOC_DAPM_INPUT("VINL1"),
433 SND_SOC_DAPM_INPUT("VINR1"),
434 SND_SOC_DAPM_INPUT("VINL2"),
435 SND_SOC_DAPM_INPUT("VINR2"),
436 SND_SOC_DAPM_OUTPUT("VOUTL"),
437 SND_SOC_DAPM_OUTPUT("VOUTR"),
438};
439
440static const struct snd_soc_dapm_route uda134x_dapm_routes[] = {
441 { "ADC", NULL, "VINL1" },
442 { "ADC", NULL, "VINR1" },
443 { "ADC", NULL, "VINL2" },
444 { "ADC", NULL, "VINR2" },
445 { "VOUTL", NULL, "DAC" },
446 { "VOUTR", NULL, "DAC" },
447};
448
453static const struct snd_soc_dai_ops uda134x_dai_ops = { 449static const struct snd_soc_dai_ops uda134x_dai_ops = {
454 .startup = uda134x_startup, 450 .startup = uda134x_startup,
455 .shutdown = uda134x_shutdown, 451 .shutdown = uda134x_shutdown,
@@ -485,6 +481,8 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
485{ 481{
486 struct uda134x_priv *uda134x; 482 struct uda134x_priv *uda134x;
487 struct uda134x_platform_data *pd = codec->card->dev->platform_data; 483 struct uda134x_platform_data *pd = codec->card->dev->platform_data;
484 const struct snd_soc_dapm_widget *widgets;
485 unsigned num_widgets;
488 486
489 int ret; 487 int ret;
490 488
@@ -526,6 +524,22 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
526 else 524 else
527 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 525 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
528 526
527 if (pd->model == UDA134X_UDA1341) {
528 widgets = uda1341_dapm_widgets;
529 num_widgets = ARRAY_SIZE(uda1341_dapm_widgets);
530 } else {
531 widgets = uda1340_dapm_widgets;
532 num_widgets = ARRAY_SIZE(uda1340_dapm_widgets);
533 }
534
535 ret = snd_soc_dapm_new_controls(&codec->dapm, widgets, num_widgets);
536 if (ret) {
537 printk(KERN_ERR "%s failed to register dapm controls: %d",
538 __func__, ret);
539 kfree(uda134x);
540 return ret;
541 }
542
529 switch (pd->model) { 543 switch (pd->model) {
530 case UDA134X_UDA1340: 544 case UDA134X_UDA1340:
531 case UDA134X_UDA1344: 545 case UDA134X_UDA1344:
@@ -599,6 +613,10 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
599 .read = uda134x_read_reg_cache, 613 .read = uda134x_read_reg_cache,
600 .write = uda134x_write, 614 .write = uda134x_write,
601 .set_bias_level = uda134x_set_bias_level, 615 .set_bias_level = uda134x_set_bias_level,
616 .dapm_widgets = uda134x_dapm_widgets,
617 .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets),
618 .dapm_routes = uda134x_dapm_routes,
619 .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
602}; 620};
603 621
604static int uda134x_codec_probe(struct platform_device *pdev) 622static int uda134x_codec_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 54cd3da09abd..b7ab2ef567c8 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -290,6 +290,18 @@ static const struct snd_kcontrol_new wl1273_controls[] = {
290 snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put), 290 snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put),
291}; 291};
292 292
293static const struct snd_soc_dapm_widget wl1273_dapm_widgets[] = {
294 SND_SOC_DAPM_INPUT("RX"),
295
296 SND_SOC_DAPM_OUTPUT("TX"),
297};
298
299static const struct snd_soc_dapm_route wl1273_dapm_routes[] = {
300 { "Capture", NULL, "RX" },
301
302 { "TX", NULL, "Playback" },
303};
304
293static int wl1273_startup(struct snd_pcm_substream *substream, 305static int wl1273_startup(struct snd_pcm_substream *substream,
294 struct snd_soc_dai *dai) 306 struct snd_soc_dai *dai)
295{ 307{
@@ -483,6 +495,11 @@ static int wl1273_remove(struct snd_soc_codec *codec)
483static struct snd_soc_codec_driver soc_codec_dev_wl1273 = { 495static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
484 .probe = wl1273_probe, 496 .probe = wl1273_probe,
485 .remove = wl1273_remove, 497 .remove = wl1273_remove,
498
499 .dapm_widgets = wl1273_dapm_widgets,
500 .num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets),
501 .dapm_routes = wl1273_dapm_routes,
502 .num_dapm_routes = ARRAY_SIZE(wl1273_dapm_routes),
486}; 503};
487 504
488static int wl1273_platform_probe(struct platform_device *pdev) 505static int wl1273_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index 10adc4145d46..d5ebcb00019b 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -420,7 +420,7 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
420 xfer->codec = codec; 420 xfer->codec = codec;
421 list_add_tail(&xfer->list, &xfer_list); 421 list_add_tail(&xfer->list, &xfer_list);
422 422
423 out = kzalloc(len, GFP_KERNEL); 423 out = kzalloc(len, GFP_KERNEL | GFP_DMA);
424 if (!out) { 424 if (!out) {
425 dev_err(codec->dev, 425 dev_err(codec->dev,
426 "Failed to allocate RX buffer\n"); 426 "Failed to allocate RX buffer\n");
@@ -429,7 +429,7 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_codec *codec)
429 } 429 }
430 xfer->t.rx_buf = out; 430 xfer->t.rx_buf = out;
431 431
432 img = kzalloc(len, GFP_KERNEL); 432 img = kzalloc(len, GFP_KERNEL | GFP_DMA);
433 if (!img) { 433 if (!img) {
434 dev_err(codec->dev, 434 dev_err(codec->dev,
435 "Failed to allocate image buffer\n"); 435 "Failed to allocate image buffer\n");
@@ -523,14 +523,14 @@ static int wm0010_stage2_load(struct snd_soc_codec *codec)
523 dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); 523 dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size);
524 524
525 /* Copy to local buffer first as vmalloc causes problems for dma */ 525 /* Copy to local buffer first as vmalloc causes problems for dma */
526 img = kzalloc(fw->size, GFP_KERNEL); 526 img = kzalloc(fw->size, GFP_KERNEL | GFP_DMA);
527 if (!img) { 527 if (!img) {
528 dev_err(codec->dev, "Failed to allocate image buffer\n"); 528 dev_err(codec->dev, "Failed to allocate image buffer\n");
529 ret = -ENOMEM; 529 ret = -ENOMEM;
530 goto abort2; 530 goto abort2;
531 } 531 }
532 532
533 out = kzalloc(fw->size, GFP_KERNEL); 533 out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA);
534 if (!out) { 534 if (!out) {
535 dev_err(codec->dev, "Failed to allocate output buffer\n"); 535 dev_err(codec->dev, "Failed to allocate output buffer\n");
536 ret = -ENOMEM; 536 ret = -ENOMEM;
@@ -670,14 +670,14 @@ static int wm0010_boot(struct snd_soc_codec *codec)
670 670
671 ret = -ENOMEM; 671 ret = -ENOMEM;
672 len = pll_rec.length + 8; 672 len = pll_rec.length + 8;
673 out = kzalloc(len, GFP_KERNEL); 673 out = kzalloc(len, GFP_KERNEL | GFP_DMA);
674 if (!out) { 674 if (!out) {
675 dev_err(codec->dev, 675 dev_err(codec->dev,
676 "Failed to allocate RX buffer\n"); 676 "Failed to allocate RX buffer\n");
677 goto abort; 677 goto abort;
678 } 678 }
679 679
680 img_swap = kzalloc(len, GFP_KERNEL); 680 img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA);
681 if (!img_swap) { 681 if (!img_swap) {
682 dev_err(codec->dev, 682 dev_err(codec->dev,
683 "Failed to allocate image buffer\n"); 683 "Failed to allocate image buffer\n");
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 282fd232cdf7..8bbddc151aa8 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -998,6 +998,8 @@ SND_SOC_DAPM_INPUT("IN2R"),
998SND_SOC_DAPM_INPUT("IN3L"), 998SND_SOC_DAPM_INPUT("IN3L"),
999SND_SOC_DAPM_INPUT("IN3R"), 999SND_SOC_DAPM_INPUT("IN3R"),
1000 1000
1001SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),
1002
1001SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, 1003SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
1002 0, NULL, 0, arizona_in_ev, 1004 0, NULL, 0, arizona_in_ev,
1003 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | 1005 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
@@ -1421,9 +1423,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
1421 { "Tone Generator 1", NULL, "TONE" }, 1423 { "Tone Generator 1", NULL, "TONE" },
1422 { "Tone Generator 2", NULL, "TONE" }, 1424 { "Tone Generator 2", NULL, "TONE" },
1423 1425
1424 { "Mic Mute Mixer", NULL, "Noise Mixer" },
1425 { "Mic Mute Mixer", NULL, "Mic Mixer" },
1426
1427 { "AIF1 Capture", NULL, "AIF1TX1" }, 1426 { "AIF1 Capture", NULL, "AIF1TX1" },
1428 { "AIF1 Capture", NULL, "AIF1TX2" }, 1427 { "AIF1 Capture", NULL, "AIF1TX2" },
1429 { "AIF1 Capture", NULL, "AIF1TX3" }, 1428 { "AIF1 Capture", NULL, "AIF1TX3" },
@@ -1499,23 +1498,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
1499 { "IN3L PGA", NULL, "IN3L" }, 1498 { "IN3L PGA", NULL, "IN3L" },
1500 { "IN3R PGA", NULL, "IN3R" }, 1499 { "IN3R PGA", NULL, "IN3R" },
1501 1500
1502 { "ASRC1L", NULL, "ASRC1L Input" },
1503 { "ASRC1R", NULL, "ASRC1R Input" },
1504 { "ASRC2L", NULL, "ASRC2L Input" },
1505 { "ASRC2R", NULL, "ASRC2R Input" },
1506
1507 { "ISRC1DEC1", NULL, "ISRC1DEC1 Input" },
1508 { "ISRC1DEC2", NULL, "ISRC1DEC2 Input" },
1509
1510 { "ISRC1INT1", NULL, "ISRC1INT1 Input" },
1511 { "ISRC1INT2", NULL, "ISRC1INT2 Input" },
1512
1513 { "ISRC2DEC1", NULL, "ISRC2DEC1 Input" },
1514 { "ISRC2DEC2", NULL, "ISRC2DEC2 Input" },
1515
1516 { "ISRC2INT1", NULL, "ISRC2INT1 Input" },
1517 { "ISRC2INT2", NULL, "ISRC2INT2 Input" },
1518
1519 ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), 1501 ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
1520 ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), 1502 ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
1521 ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), 1503 ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
@@ -1567,22 +1549,25 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
1567 ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), 1549 ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
1568 ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), 1550 ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
1569 1551
1570 ARIZONA_MUX_ROUTES("ASRC1L"), 1552 ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Noise"),
1571 ARIZONA_MUX_ROUTES("ASRC1R"), 1553 ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Mic"),
1572 ARIZONA_MUX_ROUTES("ASRC2L"),
1573 ARIZONA_MUX_ROUTES("ASRC2R"),
1574 1554
1575 ARIZONA_MUX_ROUTES("ISRC1INT1"), 1555 ARIZONA_MUX_ROUTES("ASRC1L", "ASRC1L"),
1576 ARIZONA_MUX_ROUTES("ISRC1INT2"), 1556 ARIZONA_MUX_ROUTES("ASRC1R", "ASRC1R"),
1557 ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"),
1558 ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"),
1577 1559
1578 ARIZONA_MUX_ROUTES("ISRC1DEC1"), 1560 ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"),
1579 ARIZONA_MUX_ROUTES("ISRC1DEC2"), 1561 ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"),
1580 1562
1581 ARIZONA_MUX_ROUTES("ISRC2INT1"), 1563 ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"),
1582 ARIZONA_MUX_ROUTES("ISRC2INT2"), 1564 ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"),
1583 1565
1584 ARIZONA_MUX_ROUTES("ISRC2DEC1"), 1566 ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"),
1585 ARIZONA_MUX_ROUTES("ISRC2DEC2"), 1567 ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"),
1568
1569 ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"),
1570 ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"),
1586 1571
1587 ARIZONA_DSP_ROUTES("DSP1"), 1572 ARIZONA_DSP_ROUTES("DSP1"),
1588 1573
@@ -1614,6 +1599,9 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
1614 { "SPKDAT1R", NULL, "OUT5R" }, 1599 { "SPKDAT1R", NULL, "OUT5R" },
1615 1600
1616 { "MICSUPP", NULL, "SYSCLK" }, 1601 { "MICSUPP", NULL, "SYSCLK" },
1602
1603 { "DRC1 Signal Activity", NULL, "DRC1L" },
1604 { "DRC1 Signal Activity", NULL, "DRC1R" },
1617}; 1605};
1618 1606
1619static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, 1607static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
@@ -1781,6 +1769,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
1781 return ret; 1769 return ret;
1782 1770
1783 arizona_init_spk(codec); 1771 arizona_init_spk(codec);
1772 arizona_init_gpio(codec);
1784 1773
1785 snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); 1774 snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
1786 1775
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 2e7cb4ba161a..bbd64384ca1c 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -58,14 +58,10 @@ static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
58 SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0) 58 SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0)
59 59
60static const struct snd_kcontrol_new wm5110_snd_controls[] = { 60static const struct snd_kcontrol_new wm5110_snd_controls[] = {
61SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, 61SOC_ENUM("IN1 OSR", arizona_in_dmic_osr[0]),
62 ARIZONA_IN1_OSR_SHIFT, 1, 0), 62SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]),
63SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL, 63SOC_ENUM("IN3 OSR", arizona_in_dmic_osr[2]),
64 ARIZONA_IN2_OSR_SHIFT, 1, 0), 64SOC_ENUM("IN4 OSR", arizona_in_dmic_osr[3]),
65SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL,
66 ARIZONA_IN3_OSR_SHIFT, 1, 0),
67SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL,
68 ARIZONA_IN4_OSR_SHIFT, 1, 0),
69 65
70SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL, 66SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL,
71 ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), 67 ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
@@ -432,6 +428,9 @@ SND_SOC_DAPM_INPUT("IN3R"),
432SND_SOC_DAPM_INPUT("IN4L"), 428SND_SOC_DAPM_INPUT("IN4L"),
433SND_SOC_DAPM_INPUT("IN4R"), 429SND_SOC_DAPM_INPUT("IN4R"),
434 430
431SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),
432SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
433
435SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, 434SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
436 0, NULL, 0, arizona_in_ev, 435 0, NULL, 0, arizona_in_ev,
437 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | 436 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
@@ -842,9 +841,6 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
842 { "Tone Generator 1", NULL, "TONE" }, 841 { "Tone Generator 1", NULL, "TONE" },
843 { "Tone Generator 2", NULL, "TONE" }, 842 { "Tone Generator 2", NULL, "TONE" },
844 843
845 { "Mic Mute Mixer", NULL, "Noise Mixer" },
846 { "Mic Mute Mixer", NULL, "Mic Mixer" },
847
848 { "AIF1 Capture", NULL, "AIF1TX1" }, 844 { "AIF1 Capture", NULL, "AIF1TX1" },
849 { "AIF1 Capture", NULL, "AIF1TX2" }, 845 { "AIF1 Capture", NULL, "AIF1TX2" },
850 { "AIF1 Capture", NULL, "AIF1TX3" }, 846 { "AIF1 Capture", NULL, "AIF1TX3" },
@@ -979,10 +975,13 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
979 ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), 975 ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
980 ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), 976 ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
981 977
982 ARIZONA_MUX_ROUTES("ASRC1L"), 978 ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Noise"),
983 ARIZONA_MUX_ROUTES("ASRC1R"), 979 ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Mic"),
984 ARIZONA_MUX_ROUTES("ASRC2L"), 980
985 ARIZONA_MUX_ROUTES("ASRC2R"), 981 ARIZONA_MUX_ROUTES("ASRC1L", "ASRC1L"),
982 ARIZONA_MUX_ROUTES("ASRC1R", "ASRC1R"),
983 ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"),
984 ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"),
986 985
987 { "HPOUT1L", NULL, "OUT1L" }, 986 { "HPOUT1L", NULL, "OUT1L" },
988 { "HPOUT1R", NULL, "OUT1R" }, 987 { "HPOUT1R", NULL, "OUT1R" },
@@ -1006,6 +1005,11 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
1006 { "SPKDAT2R", NULL, "OUT6R" }, 1005 { "SPKDAT2R", NULL, "OUT6R" },
1007 1006
1008 { "MICSUPP", NULL, "SYSCLK" }, 1007 { "MICSUPP", NULL, "SYSCLK" },
1008
1009 { "DRC1 Signal Activity", NULL, "DRC1L" },
1010 { "DRC1 Signal Activity", NULL, "DRC1R" },
1011 { "DRC2 Signal Activity", NULL, "DRC2L" },
1012 { "DRC2 Signal Activity", NULL, "DRC2R" },
1009}; 1013};
1010 1014
1011static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, 1015static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
@@ -1170,6 +1174,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
1170 return ret; 1174 return ret;
1171 1175
1172 arizona_init_spk(codec); 1176 arizona_init_spk(codec);
1177 arizona_init_gpio(codec);
1173 1178
1174 snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); 1179 snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
1175 1180
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 0e8b3aaf6c8d..af1318ddb062 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1301,7 +1301,8 @@ static irqreturn_t wm8350_hpl_jack_handler(int irq, void *data)
1301 if (device_may_wakeup(wm8350->dev)) 1301 if (device_may_wakeup(wm8350->dev))
1302 pm_wakeup_event(wm8350->dev, 250); 1302 pm_wakeup_event(wm8350->dev, 250);
1303 1303
1304 schedule_delayed_work(&priv->hpl.work, msecs_to_jiffies(200)); 1304 queue_delayed_work(system_power_efficient_wq,
1305 &priv->hpl.work, msecs_to_jiffies(200));
1305 1306
1306 return IRQ_HANDLED; 1307 return IRQ_HANDLED;
1307} 1308}
@@ -1318,7 +1319,8 @@ static irqreturn_t wm8350_hpr_jack_handler(int irq, void *data)
1318 if (device_may_wakeup(wm8350->dev)) 1319 if (device_may_wakeup(wm8350->dev))
1319 pm_wakeup_event(wm8350->dev, 250); 1320 pm_wakeup_event(wm8350->dev, 250);
1320 1321
1321 schedule_delayed_work(&priv->hpr.work, msecs_to_jiffies(200)); 1322 queue_delayed_work(system_power_efficient_wq,
1323 &priv->hpr.work, msecs_to_jiffies(200));
1322 1324
1323 return IRQ_HANDLED; 1325 return IRQ_HANDLED;
1324} 1326}
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
index 462f5e4d5c05..7b1a6d5c11c6 100644
--- a/sound/soc/codecs/wm8727.c
+++ b/sound/soc/codecs/wm8727.c
@@ -23,6 +23,16 @@
23#include <sound/initval.h> 23#include <sound/initval.h>
24#include <sound/soc.h> 24#include <sound/soc.h>
25 25
26static const struct snd_soc_dapm_widget wm8727_dapm_widgets[] = {
27SND_SOC_DAPM_OUTPUT("VOUTL"),
28SND_SOC_DAPM_OUTPUT("VOUTR"),
29};
30
31static const struct snd_soc_dapm_route wm8727_dapm_routes[] = {
32 { "VOUTL", NULL, "Playback" },
33 { "VOUTR", NULL, "Playback" },
34};
35
26/* 36/*
27 * Note this is a simple chip with no configuration interface, sample rate is 37 * Note this is a simple chip with no configuration interface, sample rate is
28 * determined automatically by examining the Master clock and Bit clock ratios 38 * determined automatically by examining the Master clock and Bit clock ratios
@@ -43,7 +53,12 @@ static struct snd_soc_dai_driver wm8727_dai = {
43 }, 53 },
44}; 54};
45 55
46static struct snd_soc_codec_driver soc_codec_dev_wm8727; 56static struct snd_soc_codec_driver soc_codec_dev_wm8727 = {
57 .dapm_widgets = wm8727_dapm_widgets,
58 .num_dapm_widgets = ARRAY_SIZE(wm8727_dapm_widgets),
59 .dapm_routes = wm8727_dapm_routes,
60 .num_dapm_routes = ARRAY_SIZE(wm8727_dapm_routes),
61};
47 62
48static int wm8727_probe(struct platform_device *pdev) 63static int wm8727_probe(struct platform_device *pdev)
49{ 64{
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 5276062d6c79..456bb8c6d759 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -45,6 +45,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
45struct wm8731_priv { 45struct wm8731_priv {
46 struct regmap *regmap; 46 struct regmap *regmap;
47 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; 47 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
48 const struct snd_pcm_hw_constraint_list *constraints;
48 unsigned int sysclk; 49 unsigned int sysclk;
49 int sysclk_type; 50 int sysclk_type;
50 int playback_fs; 51 int playback_fs;
@@ -290,6 +291,36 @@ static const struct _coeff_div coeff_div[] = {
290 {12000000, 88200, 136, 0xf, 0x1, 0x1}, 291 {12000000, 88200, 136, 0xf, 0x1, 0x1},
291}; 292};
292 293
294/* rates constraints */
295static const unsigned int wm8731_rates_12000000[] = {
296 8000, 32000, 44100, 48000, 96000, 88200,
297};
298
299static const unsigned int wm8731_rates_12288000_18432000[] = {
300 8000, 32000, 48000, 96000,
301};
302
303static const unsigned int wm8731_rates_11289600_16934400[] = {
304 8000, 44100, 88200,
305};
306
307static const struct snd_pcm_hw_constraint_list wm8731_constraints_12000000 = {
308 .list = wm8731_rates_12000000,
309 .count = ARRAY_SIZE(wm8731_rates_12000000),
310};
311
312static const
313struct snd_pcm_hw_constraint_list wm8731_constraints_12288000_18432000 = {
314 .list = wm8731_rates_12288000_18432000,
315 .count = ARRAY_SIZE(wm8731_rates_12288000_18432000),
316};
317
318static const
319struct snd_pcm_hw_constraint_list wm8731_constraints_11289600_16934400 = {
320 .list = wm8731_rates_11289600_16934400,
321 .count = ARRAY_SIZE(wm8731_rates_11289600_16934400),
322};
323
293static inline int get_coeff(int mclk, int rate) 324static inline int get_coeff(int mclk, int rate)
294{ 325{
295 int i; 326 int i;
@@ -362,17 +393,26 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
362 } 393 }
363 394
364 switch (freq) { 395 switch (freq) {
365 case 11289600: 396 case 0:
397 wm8731->constraints = NULL;
398 break;
366 case 12000000: 399 case 12000000:
400 wm8731->constraints = &wm8731_constraints_12000000;
401 break;
367 case 12288000: 402 case 12288000:
368 case 16934400:
369 case 18432000: 403 case 18432000:
370 wm8731->sysclk = freq; 404 wm8731->constraints = &wm8731_constraints_12288000_18432000;
405 break;
406 case 16934400:
407 case 11289600:
408 wm8731->constraints = &wm8731_constraints_11289600_16934400;
371 break; 409 break;
372 default: 410 default:
373 return -EINVAL; 411 return -EINVAL;
374 } 412 }
375 413
414 wm8731->sysclk = freq;
415
376 snd_soc_dapm_sync(&codec->dapm); 416 snd_soc_dapm_sync(&codec->dapm);
377 417
378 return 0; 418 return 0;
@@ -475,12 +515,26 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
475 return 0; 515 return 0;
476} 516}
477 517
518static int wm8731_startup(struct snd_pcm_substream *substream,
519 struct snd_soc_dai *dai)
520{
521 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(dai->codec);
522
523 if (wm8731->constraints)
524 snd_pcm_hw_constraint_list(substream->runtime, 0,
525 SNDRV_PCM_HW_PARAM_RATE,
526 wm8731->constraints);
527
528 return 0;
529}
530
478#define WM8731_RATES SNDRV_PCM_RATE_8000_96000 531#define WM8731_RATES SNDRV_PCM_RATE_8000_96000
479 532
480#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 533#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
481 SNDRV_PCM_FMTBIT_S24_LE) 534 SNDRV_PCM_FMTBIT_S24_LE)
482 535
483static const struct snd_soc_dai_ops wm8731_dai_ops = { 536static const struct snd_soc_dai_ops wm8731_dai_ops = {
537 .startup = wm8731_startup,
484 .hw_params = wm8731_hw_params, 538 .hw_params = wm8731_hw_params,
485 .digital_mute = wm8731_mute, 539 .digital_mute = wm8731_mute,
486 .set_sysclk = wm8731_set_dai_sysclk, 540 .set_sysclk = wm8731_set_dai_sysclk,
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 0a4ab4c423d1..d96ebf52d953 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1456,8 +1456,9 @@ static int wm8753_resume(struct snd_soc_codec *codec)
1456 if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { 1456 if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
1457 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); 1457 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1458 codec->dapm.bias_level = SND_SOC_BIAS_ON; 1458 codec->dapm.bias_level = SND_SOC_BIAS_ON;
1459 schedule_delayed_work(&codec->dapm.delayed_work, 1459 queue_delayed_work(system_power_efficient_wq,
1460 msecs_to_jiffies(caps_charge)); 1460 &codec->dapm.delayed_work,
1461 msecs_to_jiffies(caps_charge));
1461 } 1462 }
1462 1463
1463 return 0; 1464 return 0;
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c
index f1fdbf63abb4..8092495605ce 100644
--- a/sound/soc/codecs/wm8782.c
+++ b/sound/soc/codecs/wm8782.c
@@ -26,6 +26,16 @@
26#include <sound/initval.h> 26#include <sound/initval.h>
27#include <sound/soc.h> 27#include <sound/soc.h>
28 28
29static const struct snd_soc_dapm_widget wm8782_dapm_widgets[] = {
30SND_SOC_DAPM_INPUT("AINL"),
31SND_SOC_DAPM_INPUT("AINR"),
32};
33
34static const struct snd_soc_dapm_route wm8782_dapm_routes[] = {
35 { "Capture", NULL, "AINL" },
36 { "Capture", NULL, "AINR" },
37};
38
29static struct snd_soc_dai_driver wm8782_dai = { 39static struct snd_soc_dai_driver wm8782_dai = {
30 .name = "wm8782", 40 .name = "wm8782",
31 .capture = { 41 .capture = {
@@ -40,7 +50,12 @@ static struct snd_soc_dai_driver wm8782_dai = {
40 }, 50 },
41}; 51};
42 52
43static struct snd_soc_codec_driver soc_codec_dev_wm8782; 53static struct snd_soc_codec_driver soc_codec_dev_wm8782 = {
54 .dapm_widgets = wm8782_dapm_widgets,
55 .num_dapm_widgets = ARRAY_SIZE(wm8782_dapm_widgets),
56 .dapm_routes = wm8782_dapm_routes,
57 .num_dapm_routes = ARRAY_SIZE(wm8782_dapm_routes),
58};
44 59
45static int wm8782_probe(struct platform_device *pdev) 60static int wm8782_probe(struct platform_device *pdev)
46{ 61{
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index fa24cedee687..eebcb1da3b7b 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -364,9 +364,7 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm,
364static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, 364static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
365 struct snd_ctl_elem_value *ucontrol) 365 struct snd_ctl_elem_value *ucontrol)
366{ 366{
367 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 367 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
368 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
369 struct snd_soc_codec *codec = widget->codec;
370 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 368 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
371 u16 reg; 369 u16 reg;
372 int ret; 370 int ret;
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 4c9fb142cb2d..91dfbfeda6f8 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1012,7 +1012,7 @@ static const struct soc_enum liner_enum =
1012 SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text); 1012 SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text);
1013 1013
1014static const struct snd_kcontrol_new liner_mux = 1014static const struct snd_kcontrol_new liner_mux =
1015 SOC_DAPM_ENUM("LINEL Mux", liner_enum); 1015 SOC_DAPM_ENUM("LINER Mux", liner_enum);
1016 1016
1017static const char *sidetone_text[] = { 1017static const char *sidetone_text[] = {
1018 "None", "Left", "Right" 1018 "None", "Left", "Right"
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 0a4ffdd1d2a7..f156010e52bc 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -263,8 +263,8 @@ SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0),
263SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0), 263SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0),
264SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0), 264SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0),
265 265
266SOC_DOUBLE_R("ADC PCM Capture Volume", WM8960_LINPATH, WM8960_RINPATH, 266SOC_DOUBLE_R_TLV("ADC PCM Capture Volume", WM8960_LADC, WM8960_RADC,
267 0, 127, 0), 267 0, 255, 0, adc_tlv),
268 268
269SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume", 269SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume",
270 WM8960_BYPASS1, 4, 7, 1, bypass_tlv), 270 WM8960_BYPASS1, 4, 7, 1, bypass_tlv),
@@ -857,9 +857,9 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
857 if (pll_div.k) { 857 if (pll_div.k) {
858 reg |= 0x20; 858 reg |= 0x20;
859 859
860 snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); 860 snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 16) & 0xff);
861 snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); 861 snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 8) & 0xff);
862 snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); 862 snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0xff);
863 } 863 }
864 snd_soc_write(codec, WM8960_PLL1, reg); 864 snd_soc_write(codec, WM8960_PLL1, reg);
865 865
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index e2de9ecfd641..36782f067cc5 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2621,8 +2621,6 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
2621 2621
2622 wm8962->sysclk_rate = freq; 2622 wm8962->sysclk_rate = freq;
2623 2623
2624 wm8962_configure_bclk(codec);
2625
2626 return 0; 2624 return 0;
2627} 2625}
2628 2626
@@ -3046,8 +3044,9 @@ static irqreturn_t wm8962_irq(int irq, void *data)
3046 3044
3047 pm_wakeup_event(dev, 300); 3045 pm_wakeup_event(dev, 300);
3048 3046
3049 schedule_delayed_work(&wm8962->mic_work, 3047 queue_delayed_work(system_power_efficient_wq,
3050 msecs_to_jiffies(250)); 3048 &wm8962->mic_work,
3049 msecs_to_jiffies(250));
3051 } 3050 }
3052 3051
3053 return IRQ_HANDLED; 3052 return IRQ_HANDLED;
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index ba832b77c543..86426a117b07 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -819,8 +819,9 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
819 * don't want false reports. 819 * don't want false reports.
820 */ 820 */
821 if (wm8994->jackdet && !wm8994->clk_has_run) { 821 if (wm8994->jackdet && !wm8994->clk_has_run) {
822 schedule_delayed_work(&wm8994->jackdet_bootstrap, 822 queue_delayed_work(system_power_efficient_wq,
823 msecs_to_jiffies(1000)); 823 &wm8994->jackdet_bootstrap,
824 msecs_to_jiffies(1000));
824 wm8994->clk_has_run = true; 825 wm8994->clk_has_run = true;
825 } 826 }
826 break; 827 break;
@@ -1432,14 +1433,12 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
1432 1433
1433#define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ 1434#define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \
1434 SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ 1435 SOC_SINGLE_EXT(xname, reg, shift, max, invert, \
1435 snd_soc_get_volsw, wm8994_put_class_w) 1436 snd_soc_dapm_get_volsw, wm8994_put_class_w)
1436 1437
1437static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, 1438static int wm8994_put_class_w(struct snd_kcontrol *kcontrol,
1438 struct snd_ctl_elem_value *ucontrol) 1439 struct snd_ctl_elem_value *ucontrol)
1439{ 1440{
1440 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 1441 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
1441 struct snd_soc_dapm_widget *w = wlist->widgets[0];
1442 struct snd_soc_codec *codec = w->codec;
1443 int ret; 1442 int ret;
1444 1443
1445 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); 1444 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
@@ -3487,7 +3486,8 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
3487 3486
3488 pm_wakeup_event(codec->dev, 300); 3487 pm_wakeup_event(codec->dev, 300);
3489 3488
3490 schedule_delayed_work(&priv->mic_work, msecs_to_jiffies(250)); 3489 queue_delayed_work(system_power_efficient_wq,
3490 &priv->mic_work, msecs_to_jiffies(250));
3491 3491
3492 return IRQ_HANDLED; 3492 return IRQ_HANDLED;
3493} 3493}
@@ -3575,8 +3575,9 @@ static void wm8958_mic_id(void *data, u16 status)
3575 /* If nothing present then clear our statuses */ 3575 /* If nothing present then clear our statuses */
3576 dev_dbg(codec->dev, "Detected open circuit\n"); 3576 dev_dbg(codec->dev, "Detected open circuit\n");
3577 3577
3578 schedule_delayed_work(&wm8994->open_circuit_work, 3578 queue_delayed_work(system_power_efficient_wq,
3579 msecs_to_jiffies(2500)); 3579 &wm8994->open_circuit_work,
3580 msecs_to_jiffies(2500));
3580 return; 3581 return;
3581 } 3582 }
3582 3583
@@ -3690,8 +3691,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
3690 WM1811_JACKDET_DB, 0); 3691 WM1811_JACKDET_DB, 0);
3691 3692
3692 delay = control->pdata.micdet_delay; 3693 delay = control->pdata.micdet_delay;
3693 schedule_delayed_work(&wm8994->mic_work, 3694 queue_delayed_work(system_power_efficient_wq,
3694 msecs_to_jiffies(delay)); 3695 &wm8994->mic_work,
3696 msecs_to_jiffies(delay));
3695 } else { 3697 } else {
3696 dev_dbg(codec->dev, "Jack not detected\n"); 3698 dev_dbg(codec->dev, "Jack not detected\n");
3697 3699
@@ -3936,8 +3938,9 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
3936 id_delay = wm8994->wm8994->pdata.mic_id_delay; 3938 id_delay = wm8994->wm8994->pdata.mic_id_delay;
3937 3939
3938 if (wm8994->mic_detecting) 3940 if (wm8994->mic_detecting)
3939 schedule_delayed_work(&wm8994->mic_complete_work, 3941 queue_delayed_work(system_power_efficient_wq,
3940 msecs_to_jiffies(id_delay)); 3942 &wm8994->mic_complete_work,
3943 msecs_to_jiffies(id_delay));
3941 else 3944 else
3942 wm8958_button_det(codec, reg); 3945 wm8958_button_det(codec, reg);
3943 3946
@@ -4010,9 +4013,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
4010 4013
4011 wm8994->micdet_irq = control->pdata.micdet_irq; 4014 wm8994->micdet_irq = control->pdata.micdet_irq;
4012 4015
4013 pm_runtime_enable(codec->dev);
4014 pm_runtime_idle(codec->dev);
4015
4016 /* By default use idle_bias_off, will override for WM8994 */ 4016 /* By default use idle_bias_off, will override for WM8994 */
4017 codec->dapm.idle_bias_off = 1; 4017 codec->dapm.idle_bias_off = 1;
4018 4018
@@ -4385,8 +4385,6 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
4385 4385
4386 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); 4386 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
4387 4387
4388 pm_runtime_disable(codec->dev);
4389
4390 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) 4388 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
4391 wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i, 4389 wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i,
4392 &wm8994->fll_locked[i]); 4390 &wm8994->fll_locked[i]);
@@ -4445,6 +4443,9 @@ static int wm8994_probe(struct platform_device *pdev)
4445 4443
4446 wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); 4444 wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
4447 4445
4446 pm_runtime_enable(&pdev->dev);
4447 pm_runtime_idle(&pdev->dev);
4448
4448 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, 4449 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
4449 wm8994_dai, ARRAY_SIZE(wm8994_dai)); 4450 wm8994_dai, ARRAY_SIZE(wm8994_dai));
4450} 4451}
@@ -4452,6 +4453,8 @@ static int wm8994_probe(struct platform_device *pdev)
4452static int wm8994_remove(struct platform_device *pdev) 4453static int wm8994_remove(struct platform_device *pdev)
4453{ 4454{
4454 snd_soc_unregister_codec(&pdev->dev); 4455 snd_soc_unregister_codec(&pdev->dev);
4456 pm_runtime_disable(&pdev->dev);
4457
4455 return 0; 4458 return 0;
4456} 4459}
4457 4460
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 90a65c427541..da2899e6c401 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -549,12 +549,9 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source,
549static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, 549static int wm8995_put_class_w(struct snd_kcontrol *kcontrol,
550 struct snd_ctl_elem_value *ucontrol) 550 struct snd_ctl_elem_value *ucontrol)
551{ 551{
552 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 552 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
553 struct snd_soc_dapm_widget *w = wlist->widgets[0];
554 struct snd_soc_codec *codec;
555 int ret; 553 int ret;
556 554
557 codec = w->codec;
558 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); 555 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
559 wm8995_update_class_w(codec); 556 wm8995_update_class_w(codec);
560 return ret; 557 return ret;
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
new file mode 100644
index 000000000000..6ec3de3efa4f
--- /dev/null
+++ b/sound/soc/codecs/wm8997.c
@@ -0,0 +1,1175 @@
1/*
2 * wm8997.c -- WM8997 ALSA SoC Audio driver
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/pm_runtime.h>
19#include <linux/regmap.h>
20#include <linux/slab.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/jack.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28
29#include <linux/mfd/arizona/core.h>
30#include <linux/mfd/arizona/registers.h>
31
32#include "arizona.h"
33#include "wm8997.h"
34
35struct wm8997_priv {
36 struct arizona_priv core;
37 struct arizona_fll fll[2];
38};
39
40static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
41static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
42static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
43static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
44static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
45
46static const struct reg_default wm8997_sysclk_reva_patch[] = {
47 { 0x301D, 0x7B15 },
48 { 0x301B, 0x0050 },
49 { 0x305D, 0x7B17 },
50 { 0x305B, 0x0050 },
51 { 0x3001, 0x08FE },
52 { 0x3003, 0x00F4 },
53 { 0x3041, 0x08FF },
54 { 0x3043, 0x0005 },
55 { 0x3020, 0x0225 },
56 { 0x3021, 0x0A00 },
57 { 0x3022, 0xE24D },
58 { 0x3023, 0x0800 },
59 { 0x3024, 0xE24D },
60 { 0x3025, 0xF000 },
61 { 0x3060, 0x0226 },
62 { 0x3061, 0x0A00 },
63 { 0x3062, 0xE252 },
64 { 0x3063, 0x0800 },
65 { 0x3064, 0xE252 },
66 { 0x3065, 0xF000 },
67 { 0x3116, 0x022B },
68 { 0x3117, 0xFA00 },
69 { 0x3110, 0x246C },
70 { 0x3111, 0x0A03 },
71 { 0x3112, 0x246E },
72 { 0x3113, 0x0A03 },
73 { 0x3114, 0x2470 },
74 { 0x3115, 0x0A03 },
75 { 0x3126, 0x246C },
76 { 0x3127, 0x0A02 },
77 { 0x3128, 0x246E },
78 { 0x3129, 0x0A02 },
79 { 0x312A, 0x2470 },
80 { 0x312B, 0xFA02 },
81 { 0x3125, 0x0800 },
82};
83
84static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w,
85 struct snd_kcontrol *kcontrol, int event)
86{
87 struct snd_soc_codec *codec = w->codec;
88 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
89 struct regmap *regmap = codec->control_data;
90 const struct reg_default *patch = NULL;
91 int i, patch_size;
92
93 switch (arizona->rev) {
94 case 0:
95 patch = wm8997_sysclk_reva_patch;
96 patch_size = ARRAY_SIZE(wm8997_sysclk_reva_patch);
97 break;
98 default:
99 break;
100 }
101
102 switch (event) {
103 case SND_SOC_DAPM_POST_PMU:
104 if (patch)
105 for (i = 0; i < patch_size; i++)
106 regmap_write(regmap, patch[i].reg,
107 patch[i].def);
108 break;
109 default:
110 break;
111 }
112
113 return 0;
114}
115
116static const char *wm8997_osr_text[] = {
117 "Low power", "Normal", "High performance",
118};
119
120static const unsigned int wm8997_osr_val[] = {
121 0x0, 0x3, 0x5,
122};
123
124static const struct soc_enum wm8997_hpout_osr[] = {
125 SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
126 ARIZONA_OUT1_OSR_SHIFT, 0x7, 3,
127 wm8997_osr_text, wm8997_osr_val),
128 SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
129 ARIZONA_OUT3_OSR_SHIFT, 0x7, 3,
130 wm8997_osr_text, wm8997_osr_val),
131};
132
133#define WM8997_NG_SRC(name, base) \
134 SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \
135 SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \
136 SOC_SINGLE(name " NG EPOUT Switch", base, 4, 1, 0), \
137 SOC_SINGLE(name " NG SPKOUT Switch", base, 6, 1, 0), \
138 SOC_SINGLE(name " NG SPKDAT1L Switch", base, 8, 1, 0), \
139 SOC_SINGLE(name " NG SPKDAT1R Switch", base, 9, 1, 0)
140
141static const struct snd_kcontrol_new wm8997_snd_controls[] = {
142SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
143 ARIZONA_IN1_OSR_SHIFT, 1, 0),
144SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL,
145 ARIZONA_IN2_OSR_SHIFT, 1, 0),
146
147SOC_SINGLE_RANGE_TLV("IN1L Volume", ARIZONA_IN1L_CONTROL,
148 ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
149SOC_SINGLE_RANGE_TLV("IN1R Volume", ARIZONA_IN1R_CONTROL,
150 ARIZONA_IN1R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
151SOC_SINGLE_RANGE_TLV("IN2L Volume", ARIZONA_IN2L_CONTROL,
152 ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
153SOC_SINGLE_RANGE_TLV("IN2R Volume", ARIZONA_IN2R_CONTROL,
154 ARIZONA_IN2R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
155
156SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L,
157 ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
158SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R,
159 ARIZONA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
160SOC_SINGLE_TLV("IN2L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L,
161 ARIZONA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
162SOC_SINGLE_TLV("IN2R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2R,
163 ARIZONA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
164
165SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
166SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
167
168ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
169ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
170ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
171ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
172
173SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
174 ARIZONA_EQ1_ENA_MASK),
175SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
176 ARIZONA_EQ2_ENA_MASK),
177SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
178 ARIZONA_EQ3_ENA_MASK),
179SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
180 ARIZONA_EQ4_ENA_MASK),
181
182SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
183 24, 0, eq_tlv),
184SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
185 24, 0, eq_tlv),
186SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT,
187 24, 0, eq_tlv),
188SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
189 24, 0, eq_tlv),
190SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
191 24, 0, eq_tlv),
192
193SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
194 24, 0, eq_tlv),
195SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
196 24, 0, eq_tlv),
197SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT,
198 24, 0, eq_tlv),
199SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
200 24, 0, eq_tlv),
201SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
202 24, 0, eq_tlv),
203
204SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
205 24, 0, eq_tlv),
206SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
207 24, 0, eq_tlv),
208SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT,
209 24, 0, eq_tlv),
210SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
211 24, 0, eq_tlv),
212SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
213 24, 0, eq_tlv),
214
215SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
216 24, 0, eq_tlv),
217SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
218 24, 0, eq_tlv),
219SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT,
220 24, 0, eq_tlv),
221SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT,
222 24, 0, eq_tlv),
223SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT,
224 24, 0, eq_tlv),
225
226ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE),
227ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE),
228
229SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5,
230 ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA),
231
232ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE),
233ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
234ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
235ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
236
237SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
238SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
239SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
240SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
241
242SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
243SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
244SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
245SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
246
247SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
248SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
249
250ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
251ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
252
253SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR,
254 ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv),
255
256ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE),
257ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE),
258ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE),
259ARIZONA_MIXER_CONTROLS("SPKOUT", ARIZONA_OUT4LMIX_INPUT_1_SOURCE),
260ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
261ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
262
263SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
264 ARIZONA_OUT4_OSR_SHIFT, 1, 0),
265SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
266 ARIZONA_OUT5_OSR_SHIFT, 1, 0),
267
268SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
269 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
270SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
271 ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
272SOC_SINGLE("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
273 ARIZONA_OUT4L_MUTE_SHIFT, 1, 1),
274SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L,
275 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1),
276
277SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
278 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT,
279 0xbf, 0, digital_tlv),
280SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
281 ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv),
282SOC_SINGLE_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
283 ARIZONA_OUT4L_VOL_SHIFT, 0xbf, 0, digital_tlv),
284SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
285 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
286 0xbf, 0, digital_tlv),
287
288SOC_VALUE_ENUM("HPOUT1 OSR", wm8997_hpout_osr[0]),
289SOC_VALUE_ENUM("EPOUT OSR", wm8997_hpout_osr[1]),
290
291SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
292SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
293
294SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
295 ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
296
297SOC_SINGLE("Noise Gate Switch", ARIZONA_NOISE_GATE_CONTROL,
298 ARIZONA_NGATE_ENA_SHIFT, 1, 0),
299SOC_SINGLE_TLV("Noise Gate Threshold Volume", ARIZONA_NOISE_GATE_CONTROL,
300 ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv),
301SOC_ENUM("Noise Gate Hold", arizona_ng_hold),
302
303WM8997_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L),
304WM8997_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R),
305WM8997_NG_SRC("EPOUT", ARIZONA_NOISE_GATE_SELECT_3L),
306WM8997_NG_SRC("SPKOUT", ARIZONA_NOISE_GATE_SELECT_4L),
307WM8997_NG_SRC("SPKDAT1L", ARIZONA_NOISE_GATE_SELECT_5L),
308WM8997_NG_SRC("SPKDAT1R", ARIZONA_NOISE_GATE_SELECT_5R),
309
310ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
311ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
312ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
313ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE),
314ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE),
315ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE),
316ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE),
317ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE),
318
319ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE),
320ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
321
322ARIZONA_MIXER_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE),
323ARIZONA_MIXER_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE),
324ARIZONA_MIXER_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE),
325ARIZONA_MIXER_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE),
326ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE),
327ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE),
328ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE),
329ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE),
330};
331
332ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
333ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
334ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
335ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE);
336
337ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE);
338ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE);
339
340ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE);
341ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE);
342ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE);
343ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE);
344
345ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE);
346ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE);
347
348ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE);
349ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE);
350
351ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE);
352ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE);
353ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE);
354ARIZONA_MIXER_ENUMS(SPKOUT, ARIZONA_OUT4LMIX_INPUT_1_SOURCE);
355ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE);
356ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE);
357
358ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE);
359ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE);
360ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE);
361ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE);
362ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE);
363ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE);
364ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE);
365ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE);
366
367ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE);
368ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
369
370ARIZONA_MIXER_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE);
371ARIZONA_MIXER_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE);
372ARIZONA_MIXER_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE);
373ARIZONA_MIXER_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE);
374ARIZONA_MIXER_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE);
375ARIZONA_MIXER_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE);
376ARIZONA_MIXER_ENUMS(SLIMTX7, ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE);
377ARIZONA_MIXER_ENUMS(SLIMTX8, ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE);
378
379ARIZONA_MUX_ENUMS(ISRC1INT1, ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE);
380ARIZONA_MUX_ENUMS(ISRC1INT2, ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE);
381
382ARIZONA_MUX_ENUMS(ISRC1DEC1, ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE);
383ARIZONA_MUX_ENUMS(ISRC1DEC2, ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE);
384
385ARIZONA_MUX_ENUMS(ISRC2INT1, ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE);
386ARIZONA_MUX_ENUMS(ISRC2INT2, ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE);
387
388ARIZONA_MUX_ENUMS(ISRC2DEC1, ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE);
389ARIZONA_MUX_ENUMS(ISRC2DEC2, ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE);
390
391static const char *wm8997_aec_loopback_texts[] = {
392 "HPOUT1L", "HPOUT1R", "EPOUT", "SPKOUT", "SPKDAT1L", "SPKDAT1R",
393};
394
395static const unsigned int wm8997_aec_loopback_values[] = {
396 0, 1, 4, 6, 8, 9,
397};
398
399static const struct soc_enum wm8997_aec_loopback =
400 SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1,
401 ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
402 ARRAY_SIZE(wm8997_aec_loopback_texts),
403 wm8997_aec_loopback_texts,
404 wm8997_aec_loopback_values);
405
406static const struct snd_kcontrol_new wm8997_aec_loopback_mux =
407 SOC_DAPM_VALUE_ENUM("AEC Loopback", wm8997_aec_loopback);
408
409static const struct snd_soc_dapm_widget wm8997_dapm_widgets[] = {
410SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
411 0, wm8997_sysclk_ev, SND_SOC_DAPM_POST_PMU),
412SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
413 ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
414SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
415 ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0),
416SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK,
417 ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0),
418
419SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0),
420SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0),
421SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS),
422SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDD", 0, 0),
423
424SND_SOC_DAPM_SIGGEN("TONE"),
425SND_SOC_DAPM_SIGGEN("NOISE"),
426SND_SOC_DAPM_SIGGEN("HAPTICS"),
427
428SND_SOC_DAPM_INPUT("IN1L"),
429SND_SOC_DAPM_INPUT("IN1R"),
430SND_SOC_DAPM_INPUT("IN2L"),
431SND_SOC_DAPM_INPUT("IN2R"),
432
433SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
434 0, NULL, 0, arizona_in_ev,
435 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
436 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
437SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
438 0, NULL, 0, arizona_in_ev,
439 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
440 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
441SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
442 0, NULL, 0, arizona_in_ev,
443 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
444 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
445SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
446 0, NULL, 0, arizona_in_ev,
447 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
448 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
449
450SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
451 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
452SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
453 ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0),
454SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
455 ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0),
456
457SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
458 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
459
460SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1,
461 ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0),
462SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1,
463 ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0),
464
465SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1,
466 ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0),
467
468SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0),
469SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0),
470SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0),
471SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0),
472
473SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0,
474 NULL, 0),
475SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0,
476 NULL, 0),
477
478SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0,
479 NULL, 0),
480SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0,
481 NULL, 0),
482SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0,
483 NULL, 0),
484SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0,
485 NULL, 0),
486
487SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT,
488 0, NULL, 0),
489SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT,
490 0, NULL, 0),
491
492SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
493 ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
494SND_SOC_DAPM_PGA("ISRC1INT2", ARIZONA_ISRC_1_CTRL_3,
495 ARIZONA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0),
496
497SND_SOC_DAPM_PGA("ISRC1DEC1", ARIZONA_ISRC_1_CTRL_3,
498 ARIZONA_ISRC1_DEC0_ENA_SHIFT, 0, NULL, 0),
499SND_SOC_DAPM_PGA("ISRC1DEC2", ARIZONA_ISRC_1_CTRL_3,
500 ARIZONA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0),
501
502SND_SOC_DAPM_PGA("ISRC2INT1", ARIZONA_ISRC_2_CTRL_3,
503 ARIZONA_ISRC2_INT0_ENA_SHIFT, 0, NULL, 0),
504SND_SOC_DAPM_PGA("ISRC2INT2", ARIZONA_ISRC_2_CTRL_3,
505 ARIZONA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0),
506
507SND_SOC_DAPM_PGA("ISRC2DEC1", ARIZONA_ISRC_2_CTRL_3,
508 ARIZONA_ISRC2_DEC0_ENA_SHIFT, 0, NULL, 0),
509SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3,
510 ARIZONA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0),
511
512SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
513 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
514SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
515 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
516SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
517 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
518SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
519 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
520SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
521 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
522SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
523 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
524SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
525 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
526SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
527 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
528
529SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
530 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
531SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
532 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
533SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
534 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
535SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
536 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
537SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
538 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
539SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
540 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
541SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
542 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
543SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
544 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
545
546SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
547 ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
548SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
549 ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
550
551SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
552 ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
553SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
554 ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
555
556SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0,
557 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
558 ARIZONA_SLIMTX1_ENA_SHIFT, 0),
559SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0,
560 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
561 ARIZONA_SLIMTX2_ENA_SHIFT, 0),
562SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0,
563 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
564 ARIZONA_SLIMTX3_ENA_SHIFT, 0),
565SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0,
566 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
567 ARIZONA_SLIMTX4_ENA_SHIFT, 0),
568SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0,
569 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
570 ARIZONA_SLIMTX5_ENA_SHIFT, 0),
571SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0,
572 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
573 ARIZONA_SLIMTX6_ENA_SHIFT, 0),
574SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0,
575 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
576 ARIZONA_SLIMTX7_ENA_SHIFT, 0),
577SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0,
578 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
579 ARIZONA_SLIMTX8_ENA_SHIFT, 0),
580
581SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0,
582 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
583 ARIZONA_SLIMRX1_ENA_SHIFT, 0),
584SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0,
585 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
586 ARIZONA_SLIMRX2_ENA_SHIFT, 0),
587SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0,
588 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
589 ARIZONA_SLIMRX3_ENA_SHIFT, 0),
590SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0,
591 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
592 ARIZONA_SLIMRX4_ENA_SHIFT, 0),
593SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0,
594 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
595 ARIZONA_SLIMRX5_ENA_SHIFT, 0),
596SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0,
597 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
598 ARIZONA_SLIMRX6_ENA_SHIFT, 0),
599SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0,
600 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
601 ARIZONA_SLIMRX7_ENA_SHIFT, 0),
602SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
603 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
604 ARIZONA_SLIMRX8_ENA_SHIFT, 0),
605
606SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
607 ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
608 &wm8997_aec_loopback_mux),
609
610SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
611 ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
612 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
613SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
614 ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
615 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
616SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
617 ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
618 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
619SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
620 ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
621 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
622SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1,
623 ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
624 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
625
626ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"),
627ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"),
628ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"),
629ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"),
630
631ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"),
632ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"),
633
634ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"),
635ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"),
636ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"),
637ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"),
638
639ARIZONA_MIXER_WIDGETS(Mic, "Mic"),
640ARIZONA_MIXER_WIDGETS(Noise, "Noise"),
641
642ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"),
643ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"),
644
645ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"),
646ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"),
647ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"),
648ARIZONA_MIXER_WIDGETS(SPKOUT, "SPKOUT"),
649ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
650ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
651
652ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
653ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
654ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
655ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
656ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
657ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
658ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
659ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
660
661ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
662ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
663
664ARIZONA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"),
665ARIZONA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"),
666ARIZONA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"),
667ARIZONA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"),
668ARIZONA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"),
669ARIZONA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"),
670ARIZONA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"),
671ARIZONA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"),
672
673ARIZONA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"),
674ARIZONA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"),
675
676ARIZONA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"),
677ARIZONA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"),
678
679ARIZONA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"),
680ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
681
682ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
683ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
684
685SND_SOC_DAPM_OUTPUT("HPOUT1L"),
686SND_SOC_DAPM_OUTPUT("HPOUT1R"),
687SND_SOC_DAPM_OUTPUT("EPOUTN"),
688SND_SOC_DAPM_OUTPUT("EPOUTP"),
689SND_SOC_DAPM_OUTPUT("SPKOUTN"),
690SND_SOC_DAPM_OUTPUT("SPKOUTP"),
691SND_SOC_DAPM_OUTPUT("SPKDAT1L"),
692SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
693
694SND_SOC_DAPM_OUTPUT("MICSUPP"),
695};
696
697#define ARIZONA_MIXER_INPUT_ROUTES(name) \
698 { name, "Noise Generator", "Noise Generator" }, \
699 { name, "Tone Generator 1", "Tone Generator 1" }, \
700 { name, "Tone Generator 2", "Tone Generator 2" }, \
701 { name, "Haptics", "HAPTICS" }, \
702 { name, "AEC", "AEC Loopback" }, \
703 { name, "IN1L", "IN1L PGA" }, \
704 { name, "IN1R", "IN1R PGA" }, \
705 { name, "IN2L", "IN2L PGA" }, \
706 { name, "IN2R", "IN2R PGA" }, \
707 { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \
708 { name, "AIF1RX1", "AIF1RX1" }, \
709 { name, "AIF1RX2", "AIF1RX2" }, \
710 { name, "AIF1RX3", "AIF1RX3" }, \
711 { name, "AIF1RX4", "AIF1RX4" }, \
712 { name, "AIF1RX5", "AIF1RX5" }, \
713 { name, "AIF1RX6", "AIF1RX6" }, \
714 { name, "AIF1RX7", "AIF1RX7" }, \
715 { name, "AIF1RX8", "AIF1RX8" }, \
716 { name, "AIF2RX1", "AIF2RX1" }, \
717 { name, "AIF2RX2", "AIF2RX2" }, \
718 { name, "SLIMRX1", "SLIMRX1" }, \
719 { name, "SLIMRX2", "SLIMRX2" }, \
720 { name, "SLIMRX3", "SLIMRX3" }, \
721 { name, "SLIMRX4", "SLIMRX4" }, \
722 { name, "SLIMRX5", "SLIMRX5" }, \
723 { name, "SLIMRX6", "SLIMRX6" }, \
724 { name, "SLIMRX7", "SLIMRX7" }, \
725 { name, "SLIMRX8", "SLIMRX8" }, \
726 { name, "EQ1", "EQ1" }, \
727 { name, "EQ2", "EQ2" }, \
728 { name, "EQ3", "EQ3" }, \
729 { name, "EQ4", "EQ4" }, \
730 { name, "DRC1L", "DRC1L" }, \
731 { name, "DRC1R", "DRC1R" }, \
732 { name, "LHPF1", "LHPF1" }, \
733 { name, "LHPF2", "LHPF2" }, \
734 { name, "LHPF3", "LHPF3" }, \
735 { name, "LHPF4", "LHPF4" }, \
736 { name, "ISRC1DEC1", "ISRC1DEC1" }, \
737 { name, "ISRC1DEC2", "ISRC1DEC2" }, \
738 { name, "ISRC1INT1", "ISRC1INT1" }, \
739 { name, "ISRC1INT2", "ISRC1INT2" }, \
740 { name, "ISRC2DEC1", "ISRC2DEC1" }, \
741 { name, "ISRC2DEC2", "ISRC2DEC2" }, \
742 { name, "ISRC2INT1", "ISRC2INT1" }, \
743 { name, "ISRC2INT2", "ISRC2INT2" }
744
745static const struct snd_soc_dapm_route wm8997_dapm_routes[] = {
746 { "AIF2 Capture", NULL, "DBVDD2" },
747 { "AIF2 Playback", NULL, "DBVDD2" },
748
749 { "OUT1L", NULL, "CPVDD" },
750 { "OUT1R", NULL, "CPVDD" },
751 { "OUT3L", NULL, "CPVDD" },
752
753 { "OUT4L", NULL, "SPKVDD" },
754
755 { "OUT1L", NULL, "SYSCLK" },
756 { "OUT1R", NULL, "SYSCLK" },
757 { "OUT3L", NULL, "SYSCLK" },
758 { "OUT4L", NULL, "SYSCLK" },
759
760 { "IN1L", NULL, "SYSCLK" },
761 { "IN1R", NULL, "SYSCLK" },
762 { "IN2L", NULL, "SYSCLK" },
763 { "IN2R", NULL, "SYSCLK" },
764
765 { "MICBIAS1", NULL, "MICVDD" },
766 { "MICBIAS2", NULL, "MICVDD" },
767 { "MICBIAS3", NULL, "MICVDD" },
768
769 { "Noise Generator", NULL, "SYSCLK" },
770 { "Tone Generator 1", NULL, "SYSCLK" },
771 { "Tone Generator 2", NULL, "SYSCLK" },
772
773 { "Noise Generator", NULL, "NOISE" },
774 { "Tone Generator 1", NULL, "TONE" },
775 { "Tone Generator 2", NULL, "TONE" },
776
777 { "AIF1 Capture", NULL, "AIF1TX1" },
778 { "AIF1 Capture", NULL, "AIF1TX2" },
779 { "AIF1 Capture", NULL, "AIF1TX3" },
780 { "AIF1 Capture", NULL, "AIF1TX4" },
781 { "AIF1 Capture", NULL, "AIF1TX5" },
782 { "AIF1 Capture", NULL, "AIF1TX6" },
783 { "AIF1 Capture", NULL, "AIF1TX7" },
784 { "AIF1 Capture", NULL, "AIF1TX8" },
785
786 { "AIF1RX1", NULL, "AIF1 Playback" },
787 { "AIF1RX2", NULL, "AIF1 Playback" },
788 { "AIF1RX3", NULL, "AIF1 Playback" },
789 { "AIF1RX4", NULL, "AIF1 Playback" },
790 { "AIF1RX5", NULL, "AIF1 Playback" },
791 { "AIF1RX6", NULL, "AIF1 Playback" },
792 { "AIF1RX7", NULL, "AIF1 Playback" },
793 { "AIF1RX8", NULL, "AIF1 Playback" },
794
795 { "AIF2 Capture", NULL, "AIF2TX1" },
796 { "AIF2 Capture", NULL, "AIF2TX2" },
797
798 { "AIF2RX1", NULL, "AIF2 Playback" },
799 { "AIF2RX2", NULL, "AIF2 Playback" },
800
801 { "Slim1 Capture", NULL, "SLIMTX1" },
802 { "Slim1 Capture", NULL, "SLIMTX2" },
803 { "Slim1 Capture", NULL, "SLIMTX3" },
804 { "Slim1 Capture", NULL, "SLIMTX4" },
805
806 { "SLIMRX1", NULL, "Slim1 Playback" },
807 { "SLIMRX2", NULL, "Slim1 Playback" },
808 { "SLIMRX3", NULL, "Slim1 Playback" },
809 { "SLIMRX4", NULL, "Slim1 Playback" },
810
811 { "Slim2 Capture", NULL, "SLIMTX5" },
812 { "Slim2 Capture", NULL, "SLIMTX6" },
813
814 { "SLIMRX5", NULL, "Slim2 Playback" },
815 { "SLIMRX6", NULL, "Slim2 Playback" },
816
817 { "Slim3 Capture", NULL, "SLIMTX7" },
818 { "Slim3 Capture", NULL, "SLIMTX8" },
819
820 { "SLIMRX7", NULL, "Slim3 Playback" },
821 { "SLIMRX8", NULL, "Slim3 Playback" },
822
823 { "AIF1 Playback", NULL, "SYSCLK" },
824 { "AIF2 Playback", NULL, "SYSCLK" },
825 { "Slim1 Playback", NULL, "SYSCLK" },
826 { "Slim2 Playback", NULL, "SYSCLK" },
827 { "Slim3 Playback", NULL, "SYSCLK" },
828
829 { "AIF1 Capture", NULL, "SYSCLK" },
830 { "AIF2 Capture", NULL, "SYSCLK" },
831 { "Slim1 Capture", NULL, "SYSCLK" },
832 { "Slim2 Capture", NULL, "SYSCLK" },
833 { "Slim3 Capture", NULL, "SYSCLK" },
834
835 { "IN1L PGA", NULL, "IN1L" },
836 { "IN1R PGA", NULL, "IN1R" },
837
838 { "IN2L PGA", NULL, "IN2L" },
839 { "IN2R PGA", NULL, "IN2R" },
840
841 ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
842 ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
843 ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"),
844
845 ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUT"),
846 ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
847 ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
848
849 ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"),
850 ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"),
851
852 ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
853 ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
854 ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
855 ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
856 ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
857 ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
858 ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
859 ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
860
861 ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
862 ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
863
864 ARIZONA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"),
865 ARIZONA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"),
866 ARIZONA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"),
867 ARIZONA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"),
868 ARIZONA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"),
869 ARIZONA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"),
870 ARIZONA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"),
871 ARIZONA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"),
872
873 ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
874 ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
875 ARIZONA_MIXER_ROUTES("EQ3", "EQ3"),
876 ARIZONA_MIXER_ROUTES("EQ4", "EQ4"),
877
878 ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"),
879 ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"),
880
881 ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"),
882 ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"),
883 ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
884 ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
885
886 ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Noise"),
887 ARIZONA_MIXER_ROUTES("Mic Mute Mixer", "Mic"),
888
889 ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"),
890 ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC2INT2"),
891
892 ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"),
893 ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"),
894
895 ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"),
896 ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"),
897
898 ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"),
899 ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"),
900
901 { "AEC Loopback", "HPOUT1L", "OUT1L" },
902 { "AEC Loopback", "HPOUT1R", "OUT1R" },
903 { "HPOUT1L", NULL, "OUT1L" },
904 { "HPOUT1R", NULL, "OUT1R" },
905
906 { "AEC Loopback", "EPOUT", "OUT3L" },
907 { "EPOUTN", NULL, "OUT3L" },
908 { "EPOUTP", NULL, "OUT3L" },
909
910 { "AEC Loopback", "SPKOUT", "OUT4L" },
911 { "SPKOUTN", NULL, "OUT4L" },
912 { "SPKOUTP", NULL, "OUT4L" },
913
914 { "AEC Loopback", "SPKDAT1L", "OUT5L" },
915 { "AEC Loopback", "SPKDAT1R", "OUT5R" },
916 { "SPKDAT1L", NULL, "OUT5L" },
917 { "SPKDAT1R", NULL, "OUT5R" },
918
919 { "MICSUPP", NULL, "SYSCLK" },
920};
921
922static int wm8997_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
923 unsigned int Fref, unsigned int Fout)
924{
925 struct wm8997_priv *wm8997 = snd_soc_codec_get_drvdata(codec);
926
927 switch (fll_id) {
928 case WM8997_FLL1:
929 return arizona_set_fll(&wm8997->fll[0], source, Fref, Fout);
930 case WM8997_FLL2:
931 return arizona_set_fll(&wm8997->fll[1], source, Fref, Fout);
932 case WM8997_FLL1_REFCLK:
933 return arizona_set_fll_refclk(&wm8997->fll[0], source, Fref,
934 Fout);
935 case WM8997_FLL2_REFCLK:
936 return arizona_set_fll_refclk(&wm8997->fll[1], source, Fref,
937 Fout);
938 default:
939 return -EINVAL;
940 }
941}
942
943#define WM8997_RATES SNDRV_PCM_RATE_8000_192000
944
945#define WM8997_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
946 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
947
948static struct snd_soc_dai_driver wm8997_dai[] = {
949 {
950 .name = "wm8997-aif1",
951 .id = 1,
952 .base = ARIZONA_AIF1_BCLK_CTRL,
953 .playback = {
954 .stream_name = "AIF1 Playback",
955 .channels_min = 1,
956 .channels_max = 8,
957 .rates = WM8997_RATES,
958 .formats = WM8997_FORMATS,
959 },
960 .capture = {
961 .stream_name = "AIF1 Capture",
962 .channels_min = 1,
963 .channels_max = 8,
964 .rates = WM8997_RATES,
965 .formats = WM8997_FORMATS,
966 },
967 .ops = &arizona_dai_ops,
968 .symmetric_rates = 1,
969 },
970 {
971 .name = "wm8997-aif2",
972 .id = 2,
973 .base = ARIZONA_AIF2_BCLK_CTRL,
974 .playback = {
975 .stream_name = "AIF2 Playback",
976 .channels_min = 1,
977 .channels_max = 2,
978 .rates = WM8997_RATES,
979 .formats = WM8997_FORMATS,
980 },
981 .capture = {
982 .stream_name = "AIF2 Capture",
983 .channels_min = 1,
984 .channels_max = 2,
985 .rates = WM8997_RATES,
986 .formats = WM8997_FORMATS,
987 },
988 .ops = &arizona_dai_ops,
989 .symmetric_rates = 1,
990 },
991 {
992 .name = "wm8997-slim1",
993 .id = 3,
994 .playback = {
995 .stream_name = "Slim1 Playback",
996 .channels_min = 1,
997 .channels_max = 4,
998 .rates = WM8997_RATES,
999 .formats = WM8997_FORMATS,
1000 },
1001 .capture = {
1002 .stream_name = "Slim1 Capture",
1003 .channels_min = 1,
1004 .channels_max = 4,
1005 .rates = WM8997_RATES,
1006 .formats = WM8997_FORMATS,
1007 },
1008 .ops = &arizona_simple_dai_ops,
1009 },
1010 {
1011 .name = "wm8997-slim2",
1012 .id = 4,
1013 .playback = {
1014 .stream_name = "Slim2 Playback",
1015 .channels_min = 1,
1016 .channels_max = 2,
1017 .rates = WM8997_RATES,
1018 .formats = WM8997_FORMATS,
1019 },
1020 .capture = {
1021 .stream_name = "Slim2 Capture",
1022 .channels_min = 1,
1023 .channels_max = 2,
1024 .rates = WM8997_RATES,
1025 .formats = WM8997_FORMATS,
1026 },
1027 .ops = &arizona_simple_dai_ops,
1028 },
1029 {
1030 .name = "wm8997-slim3",
1031 .id = 5,
1032 .playback = {
1033 .stream_name = "Slim3 Playback",
1034 .channels_min = 1,
1035 .channels_max = 2,
1036 .rates = WM8997_RATES,
1037 .formats = WM8997_FORMATS,
1038 },
1039 .capture = {
1040 .stream_name = "Slim3 Capture",
1041 .channels_min = 1,
1042 .channels_max = 2,
1043 .rates = WM8997_RATES,
1044 .formats = WM8997_FORMATS,
1045 },
1046 .ops = &arizona_simple_dai_ops,
1047 },
1048};
1049
1050static int wm8997_codec_probe(struct snd_soc_codec *codec)
1051{
1052 struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec);
1053 int ret;
1054
1055 codec->control_data = priv->core.arizona->regmap;
1056
1057 ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
1058 if (ret != 0)
1059 return ret;
1060
1061 arizona_init_spk(codec);
1062
1063 snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
1064
1065 priv->core.arizona->dapm = &codec->dapm;
1066
1067 return 0;
1068}
1069
1070static int wm8997_codec_remove(struct snd_soc_codec *codec)
1071{
1072 struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec);
1073
1074 priv->core.arizona->dapm = NULL;
1075
1076 return 0;
1077}
1078
1079#define WM8997_DIG_VU 0x0200
1080
1081static unsigned int wm8997_digital_vu[] = {
1082 ARIZONA_DAC_DIGITAL_VOLUME_1L,
1083 ARIZONA_DAC_DIGITAL_VOLUME_1R,
1084 ARIZONA_DAC_DIGITAL_VOLUME_3L,
1085 ARIZONA_DAC_DIGITAL_VOLUME_4L,
1086 ARIZONA_DAC_DIGITAL_VOLUME_5L,
1087 ARIZONA_DAC_DIGITAL_VOLUME_5R,
1088};
1089
1090static struct snd_soc_codec_driver soc_codec_dev_wm8997 = {
1091 .probe = wm8997_codec_probe,
1092 .remove = wm8997_codec_remove,
1093
1094 .idle_bias_off = true,
1095
1096 .set_sysclk = arizona_set_sysclk,
1097 .set_pll = wm8997_set_fll,
1098
1099 .controls = wm8997_snd_controls,
1100 .num_controls = ARRAY_SIZE(wm8997_snd_controls),
1101 .dapm_widgets = wm8997_dapm_widgets,
1102 .num_dapm_widgets = ARRAY_SIZE(wm8997_dapm_widgets),
1103 .dapm_routes = wm8997_dapm_routes,
1104 .num_dapm_routes = ARRAY_SIZE(wm8997_dapm_routes),
1105};
1106
1107static int wm8997_probe(struct platform_device *pdev)
1108{
1109 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
1110 struct wm8997_priv *wm8997;
1111 int i;
1112
1113 wm8997 = devm_kzalloc(&pdev->dev, sizeof(struct wm8997_priv),
1114 GFP_KERNEL);
1115 if (wm8997 == NULL)
1116 return -ENOMEM;
1117 platform_set_drvdata(pdev, wm8997);
1118
1119 wm8997->core.arizona = arizona;
1120 wm8997->core.num_inputs = 4;
1121
1122 for (i = 0; i < ARRAY_SIZE(wm8997->fll); i++)
1123 wm8997->fll[i].vco_mult = 1;
1124
1125 arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1,
1126 ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK,
1127 &wm8997->fll[0]);
1128 arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1,
1129 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
1130 &wm8997->fll[1]);
1131
1132 /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */
1133 regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2,
1134 ARIZONA_SAMPLE_RATE_2_MASK, 0x11);
1135 regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3,
1136 ARIZONA_SAMPLE_RATE_3_MASK, 0x12);
1137
1138 for (i = 0; i < ARRAY_SIZE(wm8997_dai); i++)
1139 arizona_init_dai(&wm8997->core, i);
1140
1141 /* Latch volume update bits */
1142 for (i = 0; i < ARRAY_SIZE(wm8997_digital_vu); i++)
1143 regmap_update_bits(arizona->regmap, wm8997_digital_vu[i],
1144 WM8997_DIG_VU, WM8997_DIG_VU);
1145
1146 pm_runtime_enable(&pdev->dev);
1147 pm_runtime_idle(&pdev->dev);
1148
1149 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8997,
1150 wm8997_dai, ARRAY_SIZE(wm8997_dai));
1151}
1152
1153static int wm8997_remove(struct platform_device *pdev)
1154{
1155 snd_soc_unregister_codec(&pdev->dev);
1156 pm_runtime_disable(&pdev->dev);
1157
1158 return 0;
1159}
1160
1161static struct platform_driver wm8997_codec_driver = {
1162 .driver = {
1163 .name = "wm8997-codec",
1164 .owner = THIS_MODULE,
1165 },
1166 .probe = wm8997_probe,
1167 .remove = wm8997_remove,
1168};
1169
1170module_platform_driver(wm8997_codec_driver);
1171
1172MODULE_DESCRIPTION("ASoC WM8997 driver");
1173MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.wolfsonmicro.com>");
1174MODULE_LICENSE("GPL");
1175MODULE_ALIAS("platform:wm8997-codec");
diff --git a/sound/soc/codecs/wm8997.h b/sound/soc/codecs/wm8997.h
new file mode 100644
index 000000000000..5e91c6a7d567
--- /dev/null
+++ b/sound/soc/codecs/wm8997.h
@@ -0,0 +1,23 @@
1/*
2 * wm8997.h -- WM8997 ALSA SoC Audio driver
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _WM8997_H
14#define _WM8997_H
15
16#include "arizona.h"
17
18#define WM8997_FLL1 1
19#define WM8997_FLL2 2
20#define WM8997_FLL1_REFCLK 3
21#define WM8997_FLL2_REFCLK 4
22
23#endif
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 05252ac936a3..b38f3506418f 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -225,15 +225,8 @@ struct wm_coeff_ctl_ops {
225 struct snd_ctl_elem_info *uinfo); 225 struct snd_ctl_elem_info *uinfo);
226}; 226};
227 227
228struct wm_coeff {
229 struct device *dev;
230 struct list_head ctl_list;
231 struct regmap *regmap;
232};
233
234struct wm_coeff_ctl { 228struct wm_coeff_ctl {
235 const char *name; 229 const char *name;
236 struct snd_card *card;
237 struct wm_adsp_alg_region region; 230 struct wm_adsp_alg_region region;
238 struct wm_coeff_ctl_ops ops; 231 struct wm_coeff_ctl_ops ops;
239 struct wm_adsp *adsp; 232 struct wm_adsp *adsp;
@@ -378,7 +371,6 @@ static int wm_coeff_info(struct snd_kcontrol *kcontrol,
378static int wm_coeff_write_control(struct snd_kcontrol *kcontrol, 371static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
379 const void *buf, size_t len) 372 const void *buf, size_t len)
380{ 373{
381 struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
382 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; 374 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
383 struct wm_adsp_alg_region *region = &ctl->region; 375 struct wm_adsp_alg_region *region = &ctl->region;
384 const struct wm_adsp_region *mem; 376 const struct wm_adsp_region *mem;
@@ -401,7 +393,7 @@ static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
401 if (!scratch) 393 if (!scratch)
402 return -ENOMEM; 394 return -ENOMEM;
403 395
404 ret = regmap_raw_write(wm_coeff->regmap, reg, scratch, 396 ret = regmap_raw_write(adsp->regmap, reg, scratch,
405 ctl->len); 397 ctl->len);
406 if (ret) { 398 if (ret) {
407 adsp_err(adsp, "Failed to write %zu bytes to %x\n", 399 adsp_err(adsp, "Failed to write %zu bytes to %x\n",
@@ -434,7 +426,6 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol,
434static int wm_coeff_read_control(struct snd_kcontrol *kcontrol, 426static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
435 void *buf, size_t len) 427 void *buf, size_t len)
436{ 428{
437 struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
438 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; 429 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
439 struct wm_adsp_alg_region *region = &ctl->region; 430 struct wm_adsp_alg_region *region = &ctl->region;
440 const struct wm_adsp_region *mem; 431 const struct wm_adsp_region *mem;
@@ -457,7 +448,7 @@ static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
457 if (!scratch) 448 if (!scratch)
458 return -ENOMEM; 449 return -ENOMEM;
459 450
460 ret = regmap_raw_read(wm_coeff->regmap, reg, scratch, ctl->len); 451 ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len);
461 if (ret) { 452 if (ret) {
462 adsp_err(adsp, "Failed to read %zu bytes from %x\n", 453 adsp_err(adsp, "Failed to read %zu bytes from %x\n",
463 ctl->len, reg); 454 ctl->len, reg);
@@ -481,37 +472,18 @@ static int wm_coeff_get(struct snd_kcontrol *kcontrol,
481 return 0; 472 return 0;
482} 473}
483 474
484static int wm_coeff_add_kcontrol(struct wm_coeff *wm_coeff,
485 struct wm_coeff_ctl *ctl,
486 const struct snd_kcontrol_new *kctl)
487{
488 int ret;
489 struct snd_kcontrol *kcontrol;
490
491 kcontrol = snd_ctl_new1(kctl, wm_coeff);
492 ret = snd_ctl_add(ctl->card, kcontrol);
493 if (ret < 0) {
494 dev_err(wm_coeff->dev, "Failed to add %s: %d\n",
495 kctl->name, ret);
496 return ret;
497 }
498 ctl->kcontrol = kcontrol;
499 return 0;
500}
501
502struct wmfw_ctl_work { 475struct wmfw_ctl_work {
503 struct wm_coeff *wm_coeff; 476 struct wm_adsp *adsp;
504 struct wm_coeff_ctl *ctl; 477 struct wm_coeff_ctl *ctl;
505 struct work_struct work; 478 struct work_struct work;
506}; 479};
507 480
508static int wmfw_add_ctl(struct wm_coeff *wm_coeff, 481static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl)
509 struct wm_coeff_ctl *ctl)
510{ 482{
511 struct snd_kcontrol_new *kcontrol; 483 struct snd_kcontrol_new *kcontrol;
512 int ret; 484 int ret;
513 485
514 if (!wm_coeff || !ctl || !ctl->name || !ctl->card) 486 if (!ctl || !ctl->name)
515 return -EINVAL; 487 return -EINVAL;
516 488
517 kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); 489 kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
@@ -525,14 +497,17 @@ static int wmfw_add_ctl(struct wm_coeff *wm_coeff,
525 kcontrol->put = wm_coeff_put; 497 kcontrol->put = wm_coeff_put;
526 kcontrol->private_value = (unsigned long)ctl; 498 kcontrol->private_value = (unsigned long)ctl;
527 499
528 ret = wm_coeff_add_kcontrol(wm_coeff, 500 ret = snd_soc_add_card_controls(adsp->card,
529 ctl, kcontrol); 501 kcontrol, 1);
530 if (ret < 0) 502 if (ret < 0)
531 goto err_kcontrol; 503 goto err_kcontrol;
532 504
533 kfree(kcontrol); 505 kfree(kcontrol);
534 506
535 list_add(&ctl->list, &wm_coeff->ctl_list); 507 ctl->kcontrol = snd_soc_card_get_kcontrol(adsp->card,
508 ctl->name);
509
510 list_add(&ctl->list, &adsp->ctl_list);
536 return 0; 511 return 0;
537 512
538err_kcontrol: 513err_kcontrol:
@@ -753,13 +728,12 @@ out:
753 return ret; 728 return ret;
754} 729}
755 730
756static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff) 731static int wm_coeff_init_control_caches(struct wm_adsp *adsp)
757{ 732{
758 struct wm_coeff_ctl *ctl; 733 struct wm_coeff_ctl *ctl;
759 int ret; 734 int ret;
760 735
761 list_for_each_entry(ctl, &wm_coeff->ctl_list, 736 list_for_each_entry(ctl, &adsp->ctl_list, list) {
762 list) {
763 if (!ctl->enabled || ctl->set) 737 if (!ctl->enabled || ctl->set)
764 continue; 738 continue;
765 ret = wm_coeff_read_control(ctl->kcontrol, 739 ret = wm_coeff_read_control(ctl->kcontrol,
@@ -772,13 +746,12 @@ static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff)
772 return 0; 746 return 0;
773} 747}
774 748
775static int wm_coeff_sync_controls(struct wm_coeff *wm_coeff) 749static int wm_coeff_sync_controls(struct wm_adsp *adsp)
776{ 750{
777 struct wm_coeff_ctl *ctl; 751 struct wm_coeff_ctl *ctl;
778 int ret; 752 int ret;
779 753
780 list_for_each_entry(ctl, &wm_coeff->ctl_list, 754 list_for_each_entry(ctl, &adsp->ctl_list, list) {
781 list) {
782 if (!ctl->enabled) 755 if (!ctl->enabled)
783 continue; 756 continue;
784 if (ctl->set) { 757 if (ctl->set) {
@@ -799,15 +772,14 @@ static void wm_adsp_ctl_work(struct work_struct *work)
799 struct wmfw_ctl_work, 772 struct wmfw_ctl_work,
800 work); 773 work);
801 774
802 wmfw_add_ctl(ctl_work->wm_coeff, ctl_work->ctl); 775 wmfw_add_ctl(ctl_work->adsp, ctl_work->ctl);
803 kfree(ctl_work); 776 kfree(ctl_work);
804} 777}
805 778
806static int wm_adsp_create_control(struct snd_soc_codec *codec, 779static int wm_adsp_create_control(struct wm_adsp *dsp,
807 const struct wm_adsp_alg_region *region) 780 const struct wm_adsp_alg_region *region)
808 781
809{ 782{
810 struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
811 struct wm_coeff_ctl *ctl; 783 struct wm_coeff_ctl *ctl;
812 struct wmfw_ctl_work *ctl_work; 784 struct wmfw_ctl_work *ctl_work;
813 char *name; 785 char *name;
@@ -842,7 +814,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
842 snprintf(name, PAGE_SIZE, "DSP%d %s %x", 814 snprintf(name, PAGE_SIZE, "DSP%d %s %x",
843 dsp->num, region_name, region->alg); 815 dsp->num, region_name, region->alg);
844 816
845 list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, 817 list_for_each_entry(ctl, &dsp->ctl_list,
846 list) { 818 list) {
847 if (!strcmp(ctl->name, name)) { 819 if (!strcmp(ctl->name, name)) {
848 if (!ctl->enabled) 820 if (!ctl->enabled)
@@ -866,7 +838,6 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
866 ctl->set = 0; 838 ctl->set = 0;
867 ctl->ops.xget = wm_coeff_get; 839 ctl->ops.xget = wm_coeff_get;
868 ctl->ops.xput = wm_coeff_put; 840 ctl->ops.xput = wm_coeff_put;
869 ctl->card = codec->card->snd_card;
870 ctl->adsp = dsp; 841 ctl->adsp = dsp;
871 842
872 ctl->len = region->len; 843 ctl->len = region->len;
@@ -882,7 +853,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
882 goto err_ctl_cache; 853 goto err_ctl_cache;
883 } 854 }
884 855
885 ctl_work->wm_coeff = dsp->wm_coeff; 856 ctl_work->adsp = dsp;
886 ctl_work->ctl = ctl; 857 ctl_work->ctl = ctl;
887 INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); 858 INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
888 schedule_work(&ctl_work->work); 859 schedule_work(&ctl_work->work);
@@ -903,7 +874,7 @@ err_name:
903 return ret; 874 return ret;
904} 875}
905 876
906static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) 877static int wm_adsp_setup_algs(struct wm_adsp *dsp)
907{ 878{
908 struct regmap *regmap = dsp->regmap; 879 struct regmap *regmap = dsp->regmap;
909 struct wmfw_adsp1_id_hdr adsp1_id; 880 struct wmfw_adsp1_id_hdr adsp1_id;
@@ -1091,7 +1062,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
1091 if (i + 1 < algs) { 1062 if (i + 1 < algs) {
1092 region->len = be32_to_cpu(adsp1_alg[i + 1].dm); 1063 region->len = be32_to_cpu(adsp1_alg[i + 1].dm);
1093 region->len -= be32_to_cpu(adsp1_alg[i].dm); 1064 region->len -= be32_to_cpu(adsp1_alg[i].dm);
1094 wm_adsp_create_control(codec, region); 1065 wm_adsp_create_control(dsp, region);
1095 } else { 1066 } else {
1096 adsp_warn(dsp, "Missing length info for region DM with ID %x\n", 1067 adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
1097 be32_to_cpu(adsp1_alg[i].alg.id)); 1068 be32_to_cpu(adsp1_alg[i].alg.id));
@@ -1108,7 +1079,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
1108 if (i + 1 < algs) { 1079 if (i + 1 < algs) {
1109 region->len = be32_to_cpu(adsp1_alg[i + 1].zm); 1080 region->len = be32_to_cpu(adsp1_alg[i + 1].zm);
1110 region->len -= be32_to_cpu(adsp1_alg[i].zm); 1081 region->len -= be32_to_cpu(adsp1_alg[i].zm);
1111 wm_adsp_create_control(codec, region); 1082 wm_adsp_create_control(dsp, region);
1112 } else { 1083 } else {
1113 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 1084 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1114 be32_to_cpu(adsp1_alg[i].alg.id)); 1085 be32_to_cpu(adsp1_alg[i].alg.id));
@@ -1137,7 +1108,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
1137 if (i + 1 < algs) { 1108 if (i + 1 < algs) {
1138 region->len = be32_to_cpu(adsp2_alg[i + 1].xm); 1109 region->len = be32_to_cpu(adsp2_alg[i + 1].xm);
1139 region->len -= be32_to_cpu(adsp2_alg[i].xm); 1110 region->len -= be32_to_cpu(adsp2_alg[i].xm);
1140 wm_adsp_create_control(codec, region); 1111 wm_adsp_create_control(dsp, region);
1141 } else { 1112 } else {
1142 adsp_warn(dsp, "Missing length info for region XM with ID %x\n", 1113 adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
1143 be32_to_cpu(adsp2_alg[i].alg.id)); 1114 be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1154,7 +1125,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
1154 if (i + 1 < algs) { 1125 if (i + 1 < algs) {
1155 region->len = be32_to_cpu(adsp2_alg[i + 1].ym); 1126 region->len = be32_to_cpu(adsp2_alg[i + 1].ym);
1156 region->len -= be32_to_cpu(adsp2_alg[i].ym); 1127 region->len -= be32_to_cpu(adsp2_alg[i].ym);
1157 wm_adsp_create_control(codec, region); 1128 wm_adsp_create_control(dsp, region);
1158 } else { 1129 } else {
1159 adsp_warn(dsp, "Missing length info for region YM with ID %x\n", 1130 adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
1160 be32_to_cpu(adsp2_alg[i].alg.id)); 1131 be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1171,7 +1142,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
1171 if (i + 1 < algs) { 1142 if (i + 1 < algs) {
1172 region->len = be32_to_cpu(adsp2_alg[i + 1].zm); 1143 region->len = be32_to_cpu(adsp2_alg[i + 1].zm);
1173 region->len -= be32_to_cpu(adsp2_alg[i].zm); 1144 region->len -= be32_to_cpu(adsp2_alg[i].zm);
1174 wm_adsp_create_control(codec, region); 1145 wm_adsp_create_control(dsp, region);
1175 } else { 1146 } else {
1176 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", 1147 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1177 be32_to_cpu(adsp2_alg[i].alg.id)); 1148 be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1391,6 +1362,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
1391 int ret; 1362 int ret;
1392 int val; 1363 int val;
1393 1364
1365 dsp->card = codec->card;
1366
1394 switch (event) { 1367 switch (event) {
1395 case SND_SOC_DAPM_POST_PMU: 1368 case SND_SOC_DAPM_POST_PMU:
1396 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1369 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
@@ -1425,7 +1398,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
1425 if (ret != 0) 1398 if (ret != 0)
1426 goto err; 1399 goto err;
1427 1400
1428 ret = wm_adsp_setup_algs(dsp, codec); 1401 ret = wm_adsp_setup_algs(dsp);
1429 if (ret != 0) 1402 if (ret != 0)
1430 goto err; 1403 goto err;
1431 1404
@@ -1434,12 +1407,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
1434 goto err; 1407 goto err;
1435 1408
1436 /* Initialize caches for enabled and unset controls */ 1409 /* Initialize caches for enabled and unset controls */
1437 ret = wm_coeff_init_control_caches(dsp->wm_coeff); 1410 ret = wm_coeff_init_control_caches(dsp);
1438 if (ret != 0) 1411 if (ret != 0)
1439 goto err; 1412 goto err;
1440 1413
1441 /* Sync set controls */ 1414 /* Sync set controls */
1442 ret = wm_coeff_sync_controls(dsp->wm_coeff); 1415 ret = wm_coeff_sync_controls(dsp);
1443 if (ret != 0) 1416 if (ret != 0)
1444 goto err; 1417 goto err;
1445 1418
@@ -1460,10 +1433,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
1460 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1433 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1461 ADSP1_SYS_ENA, 0); 1434 ADSP1_SYS_ENA, 0);
1462 1435
1463 list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, 1436 list_for_each_entry(ctl, &dsp->ctl_list, list)
1464 list) {
1465 ctl->enabled = 0; 1437 ctl->enabled = 0;
1466 }
1467 break; 1438 break;
1468 1439
1469 default: 1440 default:
@@ -1520,6 +1491,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1520 unsigned int val; 1491 unsigned int val;
1521 int ret; 1492 int ret;
1522 1493
1494 dsp->card = codec->card;
1495
1523 switch (event) { 1496 switch (event) {
1524 case SND_SOC_DAPM_POST_PMU: 1497 case SND_SOC_DAPM_POST_PMU:
1525 /* 1498 /*
@@ -1582,7 +1555,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1582 if (ret != 0) 1555 if (ret != 0)
1583 goto err; 1556 goto err;
1584 1557
1585 ret = wm_adsp_setup_algs(dsp, codec); 1558 ret = wm_adsp_setup_algs(dsp);
1586 if (ret != 0) 1559 if (ret != 0)
1587 goto err; 1560 goto err;
1588 1561
@@ -1591,12 +1564,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1591 goto err; 1564 goto err;
1592 1565
1593 /* Initialize caches for enabled and unset controls */ 1566 /* Initialize caches for enabled and unset controls */
1594 ret = wm_coeff_init_control_caches(dsp->wm_coeff); 1567 ret = wm_coeff_init_control_caches(dsp);
1595 if (ret != 0) 1568 if (ret != 0)
1596 goto err; 1569 goto err;
1597 1570
1598 /* Sync set controls */ 1571 /* Sync set controls */
1599 ret = wm_coeff_sync_controls(dsp->wm_coeff); 1572 ret = wm_coeff_sync_controls(dsp);
1600 if (ret != 0) 1573 if (ret != 0)
1601 goto err; 1574 goto err;
1602 1575
@@ -1637,10 +1610,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1637 ret); 1610 ret);
1638 } 1611 }
1639 1612
1640 list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, 1613 list_for_each_entry(ctl, &dsp->ctl_list, list)
1641 list) {
1642 ctl->enabled = 0; 1614 ctl->enabled = 0;
1643 }
1644 1615
1645 while (!list_empty(&dsp->alg_regions)) { 1616 while (!list_empty(&dsp->alg_regions)) {
1646 alg_region = list_first_entry(&dsp->alg_regions, 1617 alg_region = list_first_entry(&dsp->alg_regions,
@@ -1679,49 +1650,38 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
1679 } 1650 }
1680 1651
1681 INIT_LIST_HEAD(&adsp->alg_regions); 1652 INIT_LIST_HEAD(&adsp->alg_regions);
1682 1653 INIT_LIST_HEAD(&adsp->ctl_list);
1683 adsp->wm_coeff = kzalloc(sizeof(*adsp->wm_coeff),
1684 GFP_KERNEL);
1685 if (!adsp->wm_coeff)
1686 return -ENOMEM;
1687 adsp->wm_coeff->regmap = adsp->regmap;
1688 adsp->wm_coeff->dev = adsp->dev;
1689 INIT_LIST_HEAD(&adsp->wm_coeff->ctl_list);
1690 1654
1691 if (dvfs) { 1655 if (dvfs) {
1692 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); 1656 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
1693 if (IS_ERR(adsp->dvfs)) { 1657 if (IS_ERR(adsp->dvfs)) {
1694 ret = PTR_ERR(adsp->dvfs); 1658 ret = PTR_ERR(adsp->dvfs);
1695 dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); 1659 dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
1696 goto out_coeff; 1660 return ret;
1697 } 1661 }
1698 1662
1699 ret = regulator_enable(adsp->dvfs); 1663 ret = regulator_enable(adsp->dvfs);
1700 if (ret != 0) { 1664 if (ret != 0) {
1701 dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", 1665 dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
1702 ret); 1666 ret);
1703 goto out_coeff; 1667 return ret;
1704 } 1668 }
1705 1669
1706 ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); 1670 ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
1707 if (ret != 0) { 1671 if (ret != 0) {
1708 dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", 1672 dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
1709 ret); 1673 ret);
1710 goto out_coeff; 1674 return ret;
1711 } 1675 }
1712 1676
1713 ret = regulator_disable(adsp->dvfs); 1677 ret = regulator_disable(adsp->dvfs);
1714 if (ret != 0) { 1678 if (ret != 0) {
1715 dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", 1679 dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
1716 ret); 1680 ret);
1717 goto out_coeff; 1681 return ret;
1718 } 1682 }
1719 } 1683 }
1720 1684
1721 return 0; 1685 return 0;
1722
1723out_coeff:
1724 kfree(adsp->wm_coeff);
1725 return ret;
1726} 1686}
1727EXPORT_SYMBOL_GPL(wm_adsp2_init); 1687EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index 9f922c82536c..d018dea6254d 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -39,6 +39,7 @@ struct wm_adsp {
39 int type; 39 int type;
40 struct device *dev; 40 struct device *dev;
41 struct regmap *regmap; 41 struct regmap *regmap;
42 struct snd_soc_card *card;
42 43
43 int base; 44 int base;
44 int sysclk_reg; 45 int sysclk_reg;
@@ -57,7 +58,7 @@ struct wm_adsp {
57 58
58 struct regulator *dvfs; 59 struct regulator *dvfs;
59 60
60 struct wm_coeff *wm_coeff; 61 struct list_head ctl_list;
61}; 62};
62 63
63#define WM_ADSP1(wname, num) \ 64#define WM_ADSP1(wname, num) \
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 2d9e099415a5..8b50e5958de5 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -699,9 +699,7 @@ EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
699static int class_w_put_volsw(struct snd_kcontrol *kcontrol, 699static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
700 struct snd_ctl_elem_value *ucontrol) 700 struct snd_ctl_elem_value *ucontrol)
701{ 701{
702 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 702 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
703 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
704 struct snd_soc_codec *codec = widget->codec;
705 int ret; 703 int ret;
706 704
707 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); 705 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
@@ -721,9 +719,7 @@ static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
721static int class_w_put_double(struct snd_kcontrol *kcontrol, 719static int class_w_put_double(struct snd_kcontrol *kcontrol,
722 struct snd_ctl_elem_value *ucontrol) 720 struct snd_ctl_elem_value *ucontrol)
723{ 721{
724 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 722 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
725 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
726 struct snd_soc_codec *codec = widget->codec;
727 int ret; 723 int ret;
728 724
729 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); 725 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index aa438546c912..cd088cc8c866 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,6 +1,9 @@
1config SND_SOC_FSL_SSI 1config SND_SOC_FSL_SSI
2 tristate 2 tristate
3 3
4config SND_SOC_FSL_SPDIF
5 tristate
6
4config SND_SOC_FSL_UTILS 7config SND_SOC_FSL_UTILS
5 tristate 8 tristate
6 9
@@ -98,7 +101,7 @@ endif # SND_POWERPC_SOC
98 101
99menuconfig SND_IMX_SOC 102menuconfig SND_IMX_SOC
100 tristate "SoC Audio for Freescale i.MX CPUs" 103 tristate "SoC Audio for Freescale i.MX CPUs"
101 depends on ARCH_MXC 104 depends on ARCH_MXC || COMPILE_TEST
102 help 105 help
103 Say Y or M if you want to add support for codecs attached to 106 Say Y or M if you want to add support for codecs attached to
104 the i.MX CPUs. 107 the i.MX CPUs.
@@ -109,11 +112,11 @@ config SND_SOC_IMX_SSI
109 tristate 112 tristate
110 113
111config SND_SOC_IMX_PCM_FIQ 114config SND_SOC_IMX_PCM_FIQ
112 bool 115 tristate
113 select FIQ 116 select FIQ
114 117
115config SND_SOC_IMX_PCM_DMA 118config SND_SOC_IMX_PCM_DMA
116 bool 119 tristate
117 select SND_SOC_GENERIC_DMAENGINE_PCM 120 select SND_SOC_GENERIC_DMAENGINE_PCM
118 121
119config SND_SOC_IMX_AUDMUX 122config SND_SOC_IMX_AUDMUX
@@ -175,7 +178,6 @@ config SND_SOC_IMX_WM8962
175 select SND_SOC_IMX_PCM_DMA 178 select SND_SOC_IMX_PCM_DMA
176 select SND_SOC_IMX_AUDMUX 179 select SND_SOC_IMX_AUDMUX
177 select SND_SOC_FSL_SSI 180 select SND_SOC_FSL_SSI
178 select SND_SOC_FSL_UTILS
179 help 181 help
180 Say Y if you want to add support for SoC audio on an i.MX board with 182 Say Y if you want to add support for SoC audio on an i.MX board with
181 a wm8962 codec. 183 a wm8962 codec.
@@ -187,14 +189,13 @@ config SND_SOC_IMX_SGTL5000
187 select SND_SOC_IMX_PCM_DMA 189 select SND_SOC_IMX_PCM_DMA
188 select SND_SOC_IMX_AUDMUX 190 select SND_SOC_IMX_AUDMUX
189 select SND_SOC_FSL_SSI 191 select SND_SOC_FSL_SSI
190 select SND_SOC_FSL_UTILS
191 help 192 help
192 Say Y if you want to add support for SoC audio on an i.MX board with 193 Say Y if you want to add support for SoC audio on an i.MX board with
193 a sgtl5000 codec. 194 a sgtl5000 codec.
194 195
195config SND_SOC_IMX_MC13783 196config SND_SOC_IMX_MC13783
196 tristate "SoC Audio support for I.MX boards with mc13783" 197 tristate "SoC Audio support for I.MX boards with mc13783"
197 depends on MFD_MC13783 198 depends on MFD_MC13783 && ARM
198 select SND_SOC_IMX_SSI 199 select SND_SOC_IMX_SSI
199 select SND_SOC_IMX_AUDMUX 200 select SND_SOC_IMX_AUDMUX
200 select SND_SOC_MC13783 201 select SND_SOC_MC13783
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index d4b4aa8b5649..4b5970e014dd 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -12,9 +12,11 @@ obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
12 12
13# Freescale PowerPC SSI/DMA Platform Support 13# Freescale PowerPC SSI/DMA Platform Support
14snd-soc-fsl-ssi-objs := fsl_ssi.o 14snd-soc-fsl-ssi-objs := fsl_ssi.o
15snd-soc-fsl-spdif-objs := fsl_spdif.o
15snd-soc-fsl-utils-objs := fsl_utils.o 16snd-soc-fsl-utils-objs := fsl_utils.o
16snd-soc-fsl-dma-objs := fsl_dma.o 17snd-soc-fsl-dma-objs := fsl_dma.o
17obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o 18obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
19obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
18obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o 20obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
19obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o 21obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
20 22
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
new file mode 100644
index 000000000000..42a43820d993
--- /dev/null
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -0,0 +1,1236 @@
1/*
2 * Freescale S/PDIF ALSA SoC Digital Audio Interface (DAI) driver
3 *
4 * Copyright (C) 2013 Freescale Semiconductor, Inc.
5 *
6 * Based on stmp3xxx_spdif_dai.c
7 * Vladimir Barinov <vbarinov@embeddedalley.com>
8 * Copyright 2008 SigmaTel, Inc
9 * Copyright 2008 Embedded Alley Solutions, Inc
10 *
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
14 */
15
16#include <linux/module.h>
17#include <linux/clk.h>
18#include <linux/clk-private.h>
19#include <linux/bitrev.h>
20#include <linux/regmap.h>
21#include <linux/of_address.h>
22#include <linux/of_device.h>
23#include <linux/of_irq.h>
24
25#include <sound/asoundef.h>
26#include <sound/soc.h>
27#include <sound/dmaengine_pcm.h>
28
29#include "fsl_spdif.h"
30#include "imx-pcm.h"
31
32#define FSL_SPDIF_TXFIFO_WML 0x8
33#define FSL_SPDIF_RXFIFO_WML 0x8
34
35#define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC)
36#define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL | INT_URX_OV|\
37 INT_QRX_FUL | INT_QRX_OV | INT_UQ_SYNC | INT_UQ_ERR |\
38 INT_RXFIFO_RESYNC | INT_LOSS_LOCK | INT_DPLL_LOCKED)
39
40/* Index list for the values that has if (DPLL Locked) condition */
41static u8 srpc_dpll_locked[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0xa, 0xb };
42#define SRPC_NODPLL_START1 0x5
43#define SRPC_NODPLL_START2 0xc
44
45#define DEFAULT_RXCLK_SRC 1
46
47/*
48 * SPDIF control structure
49 * Defines channel status, subcode and Q sub
50 */
51struct spdif_mixer_control {
52 /* spinlock to access control data */
53 spinlock_t ctl_lock;
54
55 /* IEC958 channel tx status bit */
56 unsigned char ch_status[4];
57
58 /* User bits */
59 unsigned char subcode[2 * SPDIF_UBITS_SIZE];
60
61 /* Q subcode part of user bits */
62 unsigned char qsub[2 * SPDIF_QSUB_SIZE];
63
64 /* Buffer offset for U/Q */
65 u32 upos;
66 u32 qpos;
67
68 /* Ready buffer index of the two buffers */
69 u32 ready_buf;
70};
71
72struct fsl_spdif_priv {
73 struct spdif_mixer_control fsl_spdif_control;
74 struct snd_soc_dai_driver cpu_dai_drv;
75 struct platform_device *pdev;
76 struct regmap *regmap;
77 bool dpll_locked;
78 u8 txclk_div[SPDIF_TXRATE_MAX];
79 u8 txclk_src[SPDIF_TXRATE_MAX];
80 u8 rxclk_src;
81 struct clk *txclk[SPDIF_TXRATE_MAX];
82 struct clk *rxclk;
83 struct snd_dmaengine_dai_dma_data dma_params_tx;
84 struct snd_dmaengine_dai_dma_data dma_params_rx;
85
86 /* The name space will be allocated dynamically */
87 char name[0];
88};
89
90
91/* DPLL locked and lock loss interrupt handler */
92static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv)
93{
94 struct regmap *regmap = spdif_priv->regmap;
95 struct platform_device *pdev = spdif_priv->pdev;
96 u32 locked;
97
98 regmap_read(regmap, REG_SPDIF_SRPC, &locked);
99 locked &= SRPC_DPLL_LOCKED;
100
101 dev_dbg(&pdev->dev, "isr: Rx dpll %s \n",
102 locked ? "locked" : "loss lock");
103
104 spdif_priv->dpll_locked = locked ? true : false;
105}
106
107/* Receiver found illegal symbol interrupt handler */
108static void spdif_irq_sym_error(struct fsl_spdif_priv *spdif_priv)
109{
110 struct regmap *regmap = spdif_priv->regmap;
111 struct platform_device *pdev = spdif_priv->pdev;
112
113 dev_dbg(&pdev->dev, "isr: receiver found illegal symbol\n");
114
115 if (!spdif_priv->dpll_locked) {
116 /* DPLL unlocked seems no audio stream */
117 regmap_update_bits(regmap, REG_SPDIF_SIE, INT_SYM_ERR, 0);
118 }
119}
120
121/* U/Q Channel receive register full */
122static void spdif_irq_uqrx_full(struct fsl_spdif_priv *spdif_priv, char name)
123{
124 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
125 struct regmap *regmap = spdif_priv->regmap;
126 struct platform_device *pdev = spdif_priv->pdev;
127 u32 *pos, size, val, reg;
128
129 switch (name) {
130 case 'U':
131 pos = &ctrl->upos;
132 size = SPDIF_UBITS_SIZE;
133 reg = REG_SPDIF_SRU;
134 break;
135 case 'Q':
136 pos = &ctrl->qpos;
137 size = SPDIF_QSUB_SIZE;
138 reg = REG_SPDIF_SRQ;
139 break;
140 default:
141 dev_err(&pdev->dev, "unsupported channel name\n");
142 return;
143 }
144
145 dev_dbg(&pdev->dev, "isr: %c Channel receive register full\n", name);
146
147 if (*pos >= size * 2) {
148 *pos = 0;
149 } else if (unlikely((*pos % size) + 3 > size)) {
150 dev_err(&pdev->dev, "User bit receivce buffer overflow\n");
151 return;
152 }
153
154 regmap_read(regmap, reg, &val);
155 ctrl->subcode[*pos++] = val >> 16;
156 ctrl->subcode[*pos++] = val >> 8;
157 ctrl->subcode[*pos++] = val;
158}
159
160/* U/Q Channel sync found */
161static void spdif_irq_uq_sync(struct fsl_spdif_priv *spdif_priv)
162{
163 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
164 struct platform_device *pdev = spdif_priv->pdev;
165
166 dev_dbg(&pdev->dev, "isr: U/Q Channel sync found\n");
167
168 /* U/Q buffer reset */
169 if (ctrl->qpos == 0)
170 return;
171
172 /* Set ready to this buffer */
173 ctrl->ready_buf = (ctrl->qpos - 1) / SPDIF_QSUB_SIZE + 1;
174}
175
176/* U/Q Channel framing error */
177static void spdif_irq_uq_err(struct fsl_spdif_priv *spdif_priv)
178{
179 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
180 struct regmap *regmap = spdif_priv->regmap;
181 struct platform_device *pdev = spdif_priv->pdev;
182 u32 val;
183
184 dev_dbg(&pdev->dev, "isr: U/Q Channel framing error\n");
185
186 /* Read U/Q data to clear the irq and do buffer reset */
187 regmap_read(regmap, REG_SPDIF_SRU, &val);
188 regmap_read(regmap, REG_SPDIF_SRQ, &val);
189
190 /* Drop this U/Q buffer */
191 ctrl->ready_buf = 0;
192 ctrl->upos = 0;
193 ctrl->qpos = 0;
194}
195
196/* Get spdif interrupt status and clear the interrupt */
197static u32 spdif_intr_status_clear(struct fsl_spdif_priv *spdif_priv)
198{
199 struct regmap *regmap = spdif_priv->regmap;
200 u32 val, val2;
201
202 regmap_read(regmap, REG_SPDIF_SIS, &val);
203 regmap_read(regmap, REG_SPDIF_SIE, &val2);
204
205 regmap_write(regmap, REG_SPDIF_SIC, val & val2);
206
207 return val;
208}
209
210static irqreturn_t spdif_isr(int irq, void *devid)
211{
212 struct fsl_spdif_priv *spdif_priv = (struct fsl_spdif_priv *)devid;
213 struct platform_device *pdev = spdif_priv->pdev;
214 u32 sis;
215
216 sis = spdif_intr_status_clear(spdif_priv);
217
218 if (sis & INT_DPLL_LOCKED)
219 spdif_irq_dpll_lock(spdif_priv);
220
221 if (sis & INT_TXFIFO_UNOV)
222 dev_dbg(&pdev->dev, "isr: Tx FIFO under/overrun\n");
223
224 if (sis & INT_TXFIFO_RESYNC)
225 dev_dbg(&pdev->dev, "isr: Tx FIFO resync\n");
226
227 if (sis & INT_CNEW)
228 dev_dbg(&pdev->dev, "isr: cstatus new\n");
229
230 if (sis & INT_VAL_NOGOOD)
231 dev_dbg(&pdev->dev, "isr: validity flag no good\n");
232
233 if (sis & INT_SYM_ERR)
234 spdif_irq_sym_error(spdif_priv);
235
236 if (sis & INT_BIT_ERR)
237 dev_dbg(&pdev->dev, "isr: receiver found parity bit error\n");
238
239 if (sis & INT_URX_FUL)
240 spdif_irq_uqrx_full(spdif_priv, 'U');
241
242 if (sis & INT_URX_OV)
243 dev_dbg(&pdev->dev, "isr: U Channel receive register overrun\n");
244
245 if (sis & INT_QRX_FUL)
246 spdif_irq_uqrx_full(spdif_priv, 'Q');
247
248 if (sis & INT_QRX_OV)
249 dev_dbg(&pdev->dev, "isr: Q Channel receive register overrun\n");
250
251 if (sis & INT_UQ_SYNC)
252 spdif_irq_uq_sync(spdif_priv);
253
254 if (sis & INT_UQ_ERR)
255 spdif_irq_uq_err(spdif_priv);
256
257 if (sis & INT_RXFIFO_UNOV)
258 dev_dbg(&pdev->dev, "isr: Rx FIFO under/overrun\n");
259
260 if (sis & INT_RXFIFO_RESYNC)
261 dev_dbg(&pdev->dev, "isr: Rx FIFO resync\n");
262
263 if (sis & INT_LOSS_LOCK)
264 spdif_irq_dpll_lock(spdif_priv);
265
266 /* FIXME: Write Tx FIFO to clear TxEm */
267 if (sis & INT_TX_EM)
268 dev_dbg(&pdev->dev, "isr: Tx FIFO empty\n");
269
270 /* FIXME: Read Rx FIFO to clear RxFIFOFul */
271 if (sis & INT_RXFIFO_FUL)
272 dev_dbg(&pdev->dev, "isr: Rx FIFO full\n");
273
274 return IRQ_HANDLED;
275}
276
277static int spdif_softreset(struct fsl_spdif_priv *spdif_priv)
278{
279 struct regmap *regmap = spdif_priv->regmap;
280 u32 val, cycle = 1000;
281
282 regmap_write(regmap, REG_SPDIF_SCR, SCR_SOFT_RESET);
283
284 /*
285 * RESET bit would be cleared after finishing its reset procedure,
286 * which typically lasts 8 cycles. 1000 cycles will keep it safe.
287 */
288 do {
289 regmap_read(regmap, REG_SPDIF_SCR, &val);
290 } while ((val & SCR_SOFT_RESET) && cycle--);
291
292 if (cycle)
293 return 0;
294 else
295 return -EBUSY;
296}
297
298static void spdif_set_cstatus(struct spdif_mixer_control *ctrl,
299 u8 mask, u8 cstatus)
300{
301 ctrl->ch_status[3] &= ~mask;
302 ctrl->ch_status[3] |= cstatus & mask;
303}
304
305static void spdif_write_channel_status(struct fsl_spdif_priv *spdif_priv)
306{
307 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
308 struct regmap *regmap = spdif_priv->regmap;
309 struct platform_device *pdev = spdif_priv->pdev;
310 u32 ch_status;
311
312 ch_status = (bitrev8(ctrl->ch_status[0]) << 16) |
313 (bitrev8(ctrl->ch_status[1]) << 8) |
314 bitrev8(ctrl->ch_status[2]);
315 regmap_write(regmap, REG_SPDIF_STCSCH, ch_status);
316
317 dev_dbg(&pdev->dev, "STCSCH: 0x%06x\n", ch_status);
318
319 ch_status = bitrev8(ctrl->ch_status[3]) << 16;
320 regmap_write(regmap, REG_SPDIF_STCSCL, ch_status);
321
322 dev_dbg(&pdev->dev, "STCSCL: 0x%06x\n", ch_status);
323}
324
325/* Set SPDIF PhaseConfig register for rx clock */
326static int spdif_set_rx_clksrc(struct fsl_spdif_priv *spdif_priv,
327 enum spdif_gainsel gainsel, int dpll_locked)
328{
329 struct regmap *regmap = spdif_priv->regmap;
330 u8 clksrc = spdif_priv->rxclk_src;
331
332 if (clksrc >= SRPC_CLKSRC_MAX || gainsel >= GAINSEL_MULTI_MAX)
333 return -EINVAL;
334
335 regmap_update_bits(regmap, REG_SPDIF_SRPC,
336 SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK,
337 SRPC_CLKSRC_SEL_SET(clksrc) | SRPC_GAINSEL_SET(gainsel));
338
339 return 0;
340}
341
342static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
343 int sample_rate)
344{
345 struct snd_soc_pcm_runtime *rtd = substream->private_data;
346 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
347 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
348 struct regmap *regmap = spdif_priv->regmap;
349 struct platform_device *pdev = spdif_priv->pdev;
350 unsigned long csfs = 0;
351 u32 stc, mask, rate;
352 u8 clk, div;
353 int ret;
354
355 switch (sample_rate) {
356 case 32000:
357 rate = SPDIF_TXRATE_32000;
358 csfs = IEC958_AES3_CON_FS_32000;
359 break;
360 case 44100:
361 rate = SPDIF_TXRATE_44100;
362 csfs = IEC958_AES3_CON_FS_44100;
363 break;
364 case 48000:
365 rate = SPDIF_TXRATE_48000;
366 csfs = IEC958_AES3_CON_FS_48000;
367 break;
368 default:
369 dev_err(&pdev->dev, "unsupported sample rate %d\n", sample_rate);
370 return -EINVAL;
371 }
372
373 clk = spdif_priv->txclk_src[rate];
374 if (clk >= STC_TXCLK_SRC_MAX) {
375 dev_err(&pdev->dev, "tx clock source is out of range\n");
376 return -EINVAL;
377 }
378
379 div = spdif_priv->txclk_div[rate];
380 if (div == 0) {
381 dev_err(&pdev->dev, "the divisor can't be zero\n");
382 return -EINVAL;
383 }
384
385 /*
386 * The S/PDIF block needs a clock of 64 * fs * div. The S/PDIF block
387 * will divide by (div). So request 64 * fs * (div+1) which will
388 * get rounded.
389 */
390 ret = clk_set_rate(spdif_priv->txclk[rate], 64 * sample_rate * (div + 1));
391 if (ret) {
392 dev_err(&pdev->dev, "failed to set tx clock rate\n");
393 return ret;
394 }
395
396 dev_dbg(&pdev->dev, "expected clock rate = %d\n",
397 (64 * sample_rate * div));
398 dev_dbg(&pdev->dev, "actual clock rate = %ld\n",
399 clk_get_rate(spdif_priv->txclk[rate]));
400
401 /* set fs field in consumer channel status */
402 spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs);
403
404 /* select clock source and divisor */
405 stc = STC_TXCLK_ALL_EN | STC_TXCLK_SRC_SET(clk) | STC_TXCLK_DIV(div);
406 mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | STC_TXCLK_DIV_MASK;
407 regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc);
408
409 dev_dbg(&pdev->dev, "set sample rate to %d\n", sample_rate);
410
411 return 0;
412}
413
414int fsl_spdif_startup(struct snd_pcm_substream *substream,
415 struct snd_soc_dai *cpu_dai)
416{
417 struct snd_soc_pcm_runtime *rtd = substream->private_data;
418 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
419 struct platform_device *pdev = spdif_priv->pdev;
420 struct regmap *regmap = spdif_priv->regmap;
421 u32 scr, mask, i;
422 int ret;
423
424 /* Reset module and interrupts only for first initialization */
425 if (!cpu_dai->active) {
426 ret = spdif_softreset(spdif_priv);
427 if (ret) {
428 dev_err(&pdev->dev, "failed to soft reset\n");
429 return ret;
430 }
431
432 /* Disable all the interrupts */
433 regmap_update_bits(regmap, REG_SPDIF_SIE, 0xffffff, 0);
434 }
435
436 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
437 scr = SCR_TXFIFO_AUTOSYNC | SCR_TXFIFO_CTRL_NORMAL |
438 SCR_TXSEL_NORMAL | SCR_USRC_SEL_CHIP |
439 SCR_TXFIFO_FSEL_IF8;
440 mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
441 SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
442 SCR_TXFIFO_FSEL_MASK;
443 for (i = 0; i < SPDIF_TXRATE_MAX; i++)
444 clk_prepare_enable(spdif_priv->txclk[i]);
445 } else {
446 scr = SCR_RXFIFO_FSEL_IF8 | SCR_RXFIFO_AUTOSYNC;
447 mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|
448 SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK;
449 clk_prepare_enable(spdif_priv->rxclk);
450 }
451 regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr);
452
453 /* Power up SPDIF module */
454 regmap_update_bits(regmap, REG_SPDIF_SCR, SCR_LOW_POWER, 0);
455
456 return 0;
457}
458
459static void fsl_spdif_shutdown(struct snd_pcm_substream *substream,
460 struct snd_soc_dai *cpu_dai)
461{
462 struct snd_soc_pcm_runtime *rtd = substream->private_data;
463 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
464 struct regmap *regmap = spdif_priv->regmap;
465 u32 scr, mask, i;
466
467 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
468 scr = 0;
469 mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
470 SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
471 SCR_TXFIFO_FSEL_MASK;
472 for (i = 0; i < SPDIF_TXRATE_MAX; i++)
473 clk_disable_unprepare(spdif_priv->txclk[i]);
474 } else {
475 scr = SCR_RXFIFO_OFF | SCR_RXFIFO_CTL_ZERO;
476 mask = SCR_RXFIFO_FSEL_MASK | SCR_RXFIFO_AUTOSYNC_MASK|
477 SCR_RXFIFO_CTL_MASK | SCR_RXFIFO_OFF_MASK;
478 clk_disable_unprepare(spdif_priv->rxclk);
479 }
480 regmap_update_bits(regmap, REG_SPDIF_SCR, mask, scr);
481
482 /* Power down SPDIF module only if tx&rx are both inactive */
483 if (!cpu_dai->active) {
484 spdif_intr_status_clear(spdif_priv);
485 regmap_update_bits(regmap, REG_SPDIF_SCR,
486 SCR_LOW_POWER, SCR_LOW_POWER);
487 }
488}
489
490static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
491 struct snd_pcm_hw_params *params,
492 struct snd_soc_dai *dai)
493{
494 struct snd_soc_pcm_runtime *rtd = substream->private_data;
495 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
496 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
497 struct platform_device *pdev = spdif_priv->pdev;
498 u32 sample_rate = params_rate(params);
499 int ret = 0;
500
501 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
502 ret = spdif_set_sample_rate(substream, sample_rate);
503 if (ret) {
504 dev_err(&pdev->dev, "%s: set sample rate failed: %d\n",
505 __func__, sample_rate);
506 return ret;
507 }
508 spdif_set_cstatus(ctrl, IEC958_AES3_CON_CLOCK,
509 IEC958_AES3_CON_CLOCK_1000PPM);
510 spdif_write_channel_status(spdif_priv);
511 } else {
512 /* Setup rx clock source */
513 ret = spdif_set_rx_clksrc(spdif_priv, SPDIF_DEFAULT_GAINSEL, 1);
514 }
515
516 return ret;
517}
518
519static int fsl_spdif_trigger(struct snd_pcm_substream *substream,
520 int cmd, struct snd_soc_dai *dai)
521{
522 struct snd_soc_pcm_runtime *rtd = substream->private_data;
523 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
524 struct regmap *regmap = spdif_priv->regmap;
525 int is_playack = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
526 u32 intr = is_playack ? INTR_FOR_PLAYBACK : INTR_FOR_CAPTURE;
527 u32 dmaen = is_playack ? SCR_DMA_TX_EN : SCR_DMA_RX_EN;;
528
529 switch (cmd) {
530 case SNDRV_PCM_TRIGGER_START:
531 case SNDRV_PCM_TRIGGER_RESUME:
532 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
533 regmap_update_bits(regmap, REG_SPDIF_SIE, intr, intr);
534 regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, dmaen);
535 break;
536 case SNDRV_PCM_TRIGGER_STOP:
537 case SNDRV_PCM_TRIGGER_SUSPEND:
538 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
539 regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, 0);
540 regmap_update_bits(regmap, REG_SPDIF_SIE, intr, 0);
541 break;
542 default:
543 return -EINVAL;
544 }
545
546 return 0;
547}
548
549struct snd_soc_dai_ops fsl_spdif_dai_ops = {
550 .startup = fsl_spdif_startup,
551 .hw_params = fsl_spdif_hw_params,
552 .trigger = fsl_spdif_trigger,
553 .shutdown = fsl_spdif_shutdown,
554};
555
556
557/*
558 * ============================================
559 * FSL SPDIF IEC958 controller(mixer) functions
560 *
561 * Channel status get/put control
562 * User bit value get/put control
563 * Valid bit value get control
564 * DPLL lock status get control
565 * User bit sync mode selection control
566 * ============================================
567 */
568
569static int fsl_spdif_info(struct snd_kcontrol *kcontrol,
570 struct snd_ctl_elem_info *uinfo)
571{
572 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
573 uinfo->count = 1;
574
575 return 0;
576}
577
578static int fsl_spdif_pb_get(struct snd_kcontrol *kcontrol,
579 struct snd_ctl_elem_value *uvalue)
580{
581 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
582 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
583 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
584
585 uvalue->value.iec958.status[0] = ctrl->ch_status[0];
586 uvalue->value.iec958.status[1] = ctrl->ch_status[1];
587 uvalue->value.iec958.status[2] = ctrl->ch_status[2];
588 uvalue->value.iec958.status[3] = ctrl->ch_status[3];
589
590 return 0;
591}
592
593static int fsl_spdif_pb_put(struct snd_kcontrol *kcontrol,
594 struct snd_ctl_elem_value *uvalue)
595{
596 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
597 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
598 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
599
600 ctrl->ch_status[0] = uvalue->value.iec958.status[0];
601 ctrl->ch_status[1] = uvalue->value.iec958.status[1];
602 ctrl->ch_status[2] = uvalue->value.iec958.status[2];
603 ctrl->ch_status[3] = uvalue->value.iec958.status[3];
604
605 spdif_write_channel_status(spdif_priv);
606
607 return 0;
608}
609
610/* Get channel status from SPDIF_RX_CCHAN register */
611static int fsl_spdif_capture_get(struct snd_kcontrol *kcontrol,
612 struct snd_ctl_elem_value *ucontrol)
613{
614 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
615 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
616 struct regmap *regmap = spdif_priv->regmap;
617 u32 cstatus, val;
618
619 regmap_read(regmap, REG_SPDIF_SIS, &val);
620 if (!(val & INT_CNEW)) {
621 return -EAGAIN;
622 }
623
624 regmap_read(regmap, REG_SPDIF_SRCSH, &cstatus);
625 ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF;
626 ucontrol->value.iec958.status[1] = (cstatus >> 8) & 0xFF;
627 ucontrol->value.iec958.status[2] = cstatus & 0xFF;
628
629 regmap_read(regmap, REG_SPDIF_SRCSL, &cstatus);
630 ucontrol->value.iec958.status[3] = (cstatus >> 16) & 0xFF;
631 ucontrol->value.iec958.status[4] = (cstatus >> 8) & 0xFF;
632 ucontrol->value.iec958.status[5] = cstatus & 0xFF;
633
634 /* Clear intr */
635 regmap_write(regmap, REG_SPDIF_SIC, INT_CNEW);
636
637 return 0;
638}
639
640/*
641 * Get User bits (subcode) from chip value which readed out
642 * in UChannel register.
643 */
644static int fsl_spdif_subcode_get(struct snd_kcontrol *kcontrol,
645 struct snd_ctl_elem_value *ucontrol)
646{
647 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
648 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
649 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
650 unsigned long flags;
651 int ret = 0;
652
653 spin_lock_irqsave(&ctrl->ctl_lock, flags);
654 if (ctrl->ready_buf) {
655 int idx = (ctrl->ready_buf - 1) * SPDIF_UBITS_SIZE;
656 memcpy(&ucontrol->value.iec958.subcode[0],
657 &ctrl->subcode[idx], SPDIF_UBITS_SIZE);
658 } else {
659 ret = -EAGAIN;
660 }
661 spin_unlock_irqrestore(&ctrl->ctl_lock, flags);
662
663 return ret;
664}
665
666/* Q-subcode infomation. The byte size is SPDIF_UBITS_SIZE/8 */
667static int fsl_spdif_qinfo(struct snd_kcontrol *kcontrol,
668 struct snd_ctl_elem_info *uinfo)
669{
670 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
671 uinfo->count = SPDIF_QSUB_SIZE;
672
673 return 0;
674}
675
676/* Get Q subcode from chip value which readed out in QChannel register */
677static int fsl_spdif_qget(struct snd_kcontrol *kcontrol,
678 struct snd_ctl_elem_value *ucontrol)
679{
680 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
681 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
682 struct spdif_mixer_control *ctrl = &spdif_priv->fsl_spdif_control;
683 unsigned long flags;
684 int ret = 0;
685
686 spin_lock_irqsave(&ctrl->ctl_lock, flags);
687 if (ctrl->ready_buf) {
688 int idx = (ctrl->ready_buf - 1) * SPDIF_QSUB_SIZE;
689 memcpy(&ucontrol->value.bytes.data[0],
690 &ctrl->qsub[idx], SPDIF_QSUB_SIZE);
691 } else {
692 ret = -EAGAIN;
693 }
694 spin_unlock_irqrestore(&ctrl->ctl_lock, flags);
695
696 return ret;
697}
698
699/* Valid bit infomation */
700static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol,
701 struct snd_ctl_elem_info *uinfo)
702{
703 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
704 uinfo->count = 1;
705 uinfo->value.integer.min = 0;
706 uinfo->value.integer.max = 1;
707
708 return 0;
709}
710
711/* Get valid good bit from interrupt status register */
712static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol,
713 struct snd_ctl_elem_value *ucontrol)
714{
715 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
716 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
717 struct regmap *regmap = spdif_priv->regmap;
718 u32 val;
719
720 val = regmap_read(regmap, REG_SPDIF_SIS, &val);
721 ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0;
722 regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD);
723
724 return 0;
725}
726
727/* DPLL lock infomation */
728static int fsl_spdif_rxrate_info(struct snd_kcontrol *kcontrol,
729 struct snd_ctl_elem_info *uinfo)
730{
731 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
732 uinfo->count = 1;
733 uinfo->value.integer.min = 16000;
734 uinfo->value.integer.max = 96000;
735
736 return 0;
737}
738
739static u32 gainsel_multi[GAINSEL_MULTI_MAX] = {
740 24, 16, 12, 8, 6, 4, 3,
741};
742
743/* Get RX data clock rate given the SPDIF bus_clk */
744static int spdif_get_rxclk_rate(struct fsl_spdif_priv *spdif_priv,
745 enum spdif_gainsel gainsel)
746{
747 struct regmap *regmap = spdif_priv->regmap;
748 struct platform_device *pdev = spdif_priv->pdev;
749 u64 tmpval64, busclk_freq = 0;
750 u32 freqmeas, phaseconf;
751 u8 clksrc;
752
753 regmap_read(regmap, REG_SPDIF_SRFM, &freqmeas);
754 regmap_read(regmap, REG_SPDIF_SRPC, &phaseconf);
755
756 clksrc = (phaseconf >> SRPC_CLKSRC_SEL_OFFSET) & 0xf;
757 if (srpc_dpll_locked[clksrc] && (phaseconf & SRPC_DPLL_LOCKED)) {
758 /* Get bus clock from system */
759 busclk_freq = clk_get_rate(spdif_priv->rxclk);
760 }
761
762 /* FreqMeas_CLK = (BUS_CLK * FreqMeas) / 2 ^ 10 / GAINSEL / 128 */
763 tmpval64 = (u64) busclk_freq * freqmeas;
764 do_div(tmpval64, gainsel_multi[gainsel] * 1024);
765 do_div(tmpval64, 128 * 1024);
766
767 dev_dbg(&pdev->dev, "FreqMeas: %d\n", freqmeas);
768 dev_dbg(&pdev->dev, "BusclkFreq: %lld\n", busclk_freq);
769 dev_dbg(&pdev->dev, "RxRate: %lld\n", tmpval64);
770
771 return (int)tmpval64;
772}
773
774/*
775 * Get DPLL lock or not info from stable interrupt status register.
776 * User application must use this control to get locked,
777 * then can do next PCM operation
778 */
779static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol,
780 struct snd_ctl_elem_value *ucontrol)
781{
782 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
783 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
784 int rate = spdif_get_rxclk_rate(spdif_priv, SPDIF_DEFAULT_GAINSEL);
785
786 if (spdif_priv->dpll_locked)
787 ucontrol->value.integer.value[0] = rate;
788 else
789 ucontrol->value.integer.value[0] = 0;
790
791 return 0;
792}
793
794/* User bit sync mode info */
795static int fsl_spdif_usync_info(struct snd_kcontrol *kcontrol,
796 struct snd_ctl_elem_info *uinfo)
797{
798 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
799 uinfo->count = 1;
800 uinfo->value.integer.min = 0;
801 uinfo->value.integer.max = 1;
802
803 return 0;
804}
805
806/*
807 * User bit sync mode:
808 * 1 CD User channel subcode
809 * 0 Non-CD data
810 */
811static int fsl_spdif_usync_get(struct snd_kcontrol *kcontrol,
812 struct snd_ctl_elem_value *ucontrol)
813{
814 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
815 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
816 struct regmap *regmap = spdif_priv->regmap;
817 u32 val;
818
819 regmap_read(regmap, REG_SPDIF_SRCD, &val);
820 ucontrol->value.integer.value[0] = (val & SRCD_CD_USER) != 0;
821
822 return 0;
823}
824
825/*
826 * User bit sync mode:
827 * 1 CD User channel subcode
828 * 0 Non-CD data
829 */
830static int fsl_spdif_usync_put(struct snd_kcontrol *kcontrol,
831 struct snd_ctl_elem_value *ucontrol)
832{
833 struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
834 struct fsl_spdif_priv *spdif_priv = snd_soc_dai_get_drvdata(cpu_dai);
835 struct regmap *regmap = spdif_priv->regmap;
836 u32 val = ucontrol->value.integer.value[0] << SRCD_CD_USER_OFFSET;
837
838 regmap_update_bits(regmap, REG_SPDIF_SRCD, SRCD_CD_USER, val);
839
840 return 0;
841}
842
843/* FSL SPDIF IEC958 controller defines */
844static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
845 /* Status cchanel controller */
846 {
847 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
848 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
849 .access = SNDRV_CTL_ELEM_ACCESS_READ |
850 SNDRV_CTL_ELEM_ACCESS_WRITE |
851 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
852 .info = fsl_spdif_info,
853 .get = fsl_spdif_pb_get,
854 .put = fsl_spdif_pb_put,
855 },
856 {
857 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
858 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
859 .access = SNDRV_CTL_ELEM_ACCESS_READ |
860 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
861 .info = fsl_spdif_info,
862 .get = fsl_spdif_capture_get,
863 },
864 /* User bits controller */
865 {
866 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
867 .name = "IEC958 Subcode Capture Default",
868 .access = SNDRV_CTL_ELEM_ACCESS_READ |
869 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
870 .info = fsl_spdif_info,
871 .get = fsl_spdif_subcode_get,
872 },
873 {
874 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
875 .name = "IEC958 Q-subcode Capture Default",
876 .access = SNDRV_CTL_ELEM_ACCESS_READ |
877 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
878 .info = fsl_spdif_qinfo,
879 .get = fsl_spdif_qget,
880 },
881 /* Valid bit error controller */
882 {
883 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
884 .name = "IEC958 V-Bit Errors",
885 .access = SNDRV_CTL_ELEM_ACCESS_READ |
886 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
887 .info = fsl_spdif_vbit_info,
888 .get = fsl_spdif_vbit_get,
889 },
890 /* DPLL lock info get controller */
891 {
892 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
893 .name = "RX Sample Rate",
894 .access = SNDRV_CTL_ELEM_ACCESS_READ |
895 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
896 .info = fsl_spdif_rxrate_info,
897 .get = fsl_spdif_rxrate_get,
898 },
899 /* User bit sync mode set/get controller */
900 {
901 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
902 .name = "IEC958 USyncMode CDText",
903 .access = SNDRV_CTL_ELEM_ACCESS_READ |
904 SNDRV_CTL_ELEM_ACCESS_WRITE |
905 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
906 .info = fsl_spdif_usync_info,
907 .get = fsl_spdif_usync_get,
908 .put = fsl_spdif_usync_put,
909 },
910};
911
912static int fsl_spdif_dai_probe(struct snd_soc_dai *dai)
913{
914 struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai);
915
916 dai->playback_dma_data = &spdif_private->dma_params_tx;
917 dai->capture_dma_data = &spdif_private->dma_params_rx;
918
919 snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls));
920
921 return 0;
922}
923
924struct snd_soc_dai_driver fsl_spdif_dai = {
925 .probe = &fsl_spdif_dai_probe,
926 .playback = {
927 .channels_min = 2,
928 .channels_max = 2,
929 .rates = FSL_SPDIF_RATES_PLAYBACK,
930 .formats = FSL_SPDIF_FORMATS_PLAYBACK,
931 },
932 .capture = {
933 .channels_min = 2,
934 .channels_max = 2,
935 .rates = FSL_SPDIF_RATES_CAPTURE,
936 .formats = FSL_SPDIF_FORMATS_CAPTURE,
937 },
938 .ops = &fsl_spdif_dai_ops,
939};
940
941static const struct snd_soc_component_driver fsl_spdif_component = {
942 .name = "fsl-spdif",
943};
944
945/*
946 * ================
947 * FSL SPDIF REGMAP
948 * ================
949 */
950
951static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
952{
953 switch (reg) {
954 case REG_SPDIF_SCR:
955 case REG_SPDIF_SRCD:
956 case REG_SPDIF_SRPC:
957 case REG_SPDIF_SIE:
958 case REG_SPDIF_SIS:
959 case REG_SPDIF_SRL:
960 case REG_SPDIF_SRR:
961 case REG_SPDIF_SRCSH:
962 case REG_SPDIF_SRCSL:
963 case REG_SPDIF_SRU:
964 case REG_SPDIF_SRQ:
965 case REG_SPDIF_STCSCH:
966 case REG_SPDIF_STCSCL:
967 case REG_SPDIF_SRFM:
968 case REG_SPDIF_STC:
969 return true;
970 default:
971 return false;
972 };
973}
974
975static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
976{
977 switch (reg) {
978 case REG_SPDIF_SCR:
979 case REG_SPDIF_SRCD:
980 case REG_SPDIF_SRPC:
981 case REG_SPDIF_SIE:
982 case REG_SPDIF_SIC:
983 case REG_SPDIF_STL:
984 case REG_SPDIF_STR:
985 case REG_SPDIF_STCSCH:
986 case REG_SPDIF_STCSCL:
987 case REG_SPDIF_STC:
988 return true;
989 default:
990 return false;
991 };
992}
993
994static const struct regmap_config fsl_spdif_regmap_config = {
995 .reg_bits = 32,
996 .reg_stride = 4,
997 .val_bits = 32,
998
999 .max_register = REG_SPDIF_STC,
1000 .readable_reg = fsl_spdif_readable_reg,
1001 .writeable_reg = fsl_spdif_writeable_reg,
1002};
1003
1004static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
1005 struct clk *clk, u64 savesub,
1006 enum spdif_txrate index)
1007{
1008 const u32 rate[] = { 32000, 44100, 48000 };
1009 u64 rate_ideal, rate_actual, sub;
1010 u32 div, arate;
1011
1012 for (div = 1; div <= 128; div++) {
1013 rate_ideal = rate[index] * (div + 1) * 64;
1014 rate_actual = clk_round_rate(clk, rate_ideal);
1015
1016 arate = rate_actual / 64;
1017 arate /= div;
1018
1019 if (arate == rate[index]) {
1020 /* We are lucky */
1021 savesub = 0;
1022 spdif_priv->txclk_div[index] = div;
1023 break;
1024 } else if (arate / rate[index] == 1) {
1025 /* A little bigger than expect */
1026 sub = (arate - rate[index]) * 100000;
1027 do_div(sub, rate[index]);
1028 if (sub < savesub) {
1029 savesub = sub;
1030 spdif_priv->txclk_div[index] = div;
1031 }
1032 } else if (rate[index] / arate == 1) {
1033 /* A little smaller than expect */
1034 sub = (rate[index] - arate) * 100000;
1035 do_div(sub, rate[index]);
1036 if (sub < savesub) {
1037 savesub = sub;
1038 spdif_priv->txclk_div[index] = div;
1039 }
1040 }
1041 }
1042
1043 return savesub;
1044}
1045
1046static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
1047 enum spdif_txrate index)
1048{
1049 const u32 rate[] = { 32000, 44100, 48000 };
1050 struct platform_device *pdev = spdif_priv->pdev;
1051 struct device *dev = &pdev->dev;
1052 u64 savesub = 100000, ret;
1053 struct clk *clk;
1054 char tmp[16];
1055 int i;
1056
1057 for (i = 0; i < STC_TXCLK_SRC_MAX; i++) {
1058 sprintf(tmp, "rxtx%d", i);
1059 clk = devm_clk_get(&pdev->dev, tmp);
1060 if (IS_ERR(clk)) {
1061 dev_err(dev, "no rxtx%d clock in devicetree\n", i);
1062 return PTR_ERR(clk);
1063 }
1064 if (!clk_get_rate(clk))
1065 continue;
1066
1067 ret = fsl_spdif_txclk_caldiv(spdif_priv, clk, savesub, index);
1068 if (savesub == ret)
1069 continue;
1070
1071 savesub = ret;
1072 spdif_priv->txclk[index] = clk;
1073 spdif_priv->txclk_src[index] = i;
1074
1075 /* To quick catch a divisor, we allow a 0.1% deviation */
1076 if (savesub < 100)
1077 break;
1078 }
1079
1080 dev_dbg(&pdev->dev, "use rxtx%d as tx clock source for %dHz sample rate",
1081 spdif_priv->txclk_src[index], rate[index]);
1082 dev_dbg(&pdev->dev, "use divisor %d for %dHz sample rate",
1083 spdif_priv->txclk_div[index], rate[index]);
1084
1085 return 0;
1086}
1087
1088static int fsl_spdif_probe(struct platform_device *pdev)
1089{
1090 struct device_node *np = pdev->dev.of_node;
1091 struct fsl_spdif_priv *spdif_priv;
1092 struct spdif_mixer_control *ctrl;
1093 struct resource *res;
1094 void __iomem *regs;
1095 int irq, ret, i;
1096
1097 if (!np)
1098 return -ENODEV;
1099
1100 spdif_priv = devm_kzalloc(&pdev->dev,
1101 sizeof(struct fsl_spdif_priv) + strlen(np->name) + 1,
1102 GFP_KERNEL);
1103 if (!spdif_priv)
1104 return -ENOMEM;
1105
1106 strcpy(spdif_priv->name, np->name);
1107
1108 spdif_priv->pdev = pdev;
1109
1110 /* Initialize this copy of the CPU DAI driver structure */
1111 memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai));
1112 spdif_priv->cpu_dai_drv.name = spdif_priv->name;
1113
1114 /* Get the addresses and IRQ */
1115 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1116 if (IS_ERR(res)) {
1117 dev_err(&pdev->dev, "could not determine device resources\n");
1118 return PTR_ERR(res);
1119 }
1120
1121 regs = devm_ioremap_resource(&pdev->dev, res);
1122 if (IS_ERR(regs)) {
1123 dev_err(&pdev->dev, "could not map device resources\n");
1124 return PTR_ERR(regs);
1125 }
1126
1127 spdif_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
1128 "core", regs, &fsl_spdif_regmap_config);
1129 if (IS_ERR(spdif_priv->regmap)) {
1130 dev_err(&pdev->dev, "regmap init failed\n");
1131 return PTR_ERR(spdif_priv->regmap);
1132 }
1133
1134 irq = platform_get_irq(pdev, 0);
1135 if (irq < 0) {
1136 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
1137 return irq;
1138 }
1139
1140 ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0,
1141 spdif_priv->name, spdif_priv);
1142 if (ret) {
1143 dev_err(&pdev->dev, "could not claim irq %u\n", irq);
1144 return ret;
1145 }
1146
1147 /* Select clock source for rx/tx clock */
1148 spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1");
1149 if (IS_ERR(spdif_priv->rxclk)) {
1150 dev_err(&pdev->dev, "no rxtx1 clock in devicetree\n");
1151 return PTR_ERR(spdif_priv->rxclk);
1152 }
1153 spdif_priv->rxclk_src = DEFAULT_RXCLK_SRC;
1154
1155 for (i = 0; i < SPDIF_TXRATE_MAX; i++) {
1156 ret = fsl_spdif_probe_txclk(spdif_priv, i);
1157 if (ret)
1158 return ret;
1159 }
1160
1161 /* Initial spinlock for control data */
1162 ctrl = &spdif_priv->fsl_spdif_control;
1163 spin_lock_init(&ctrl->ctl_lock);
1164
1165 /* Init tx channel status default value */
1166 ctrl->ch_status[0] =
1167 IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_5015;
1168 ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID;
1169 ctrl->ch_status[2] = 0x00;
1170 ctrl->ch_status[3] =
1171 IEC958_AES3_CON_FS_44100 | IEC958_AES3_CON_CLOCK_1000PPM;
1172
1173 spdif_priv->dpll_locked = false;
1174
1175 spdif_priv->dma_params_tx.maxburst = FSL_SPDIF_TXFIFO_WML;
1176 spdif_priv->dma_params_rx.maxburst = FSL_SPDIF_RXFIFO_WML;
1177 spdif_priv->dma_params_tx.addr = res->start + REG_SPDIF_STL;
1178 spdif_priv->dma_params_rx.addr = res->start + REG_SPDIF_SRL;
1179
1180 /* Register with ASoC */
1181 dev_set_drvdata(&pdev->dev, spdif_priv);
1182
1183 ret = snd_soc_register_component(&pdev->dev, &fsl_spdif_component,
1184 &spdif_priv->cpu_dai_drv, 1);
1185 if (ret) {
1186 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
1187 goto error_dev;
1188 }
1189
1190 ret = imx_pcm_dma_init(pdev);
1191 if (ret) {
1192 dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
1193 goto error_component;
1194 }
1195
1196 return ret;
1197
1198error_component:
1199 snd_soc_unregister_component(&pdev->dev);
1200error_dev:
1201 dev_set_drvdata(&pdev->dev, NULL);
1202
1203 return ret;
1204}
1205
1206static int fsl_spdif_remove(struct platform_device *pdev)
1207{
1208 imx_pcm_dma_exit(pdev);
1209 snd_soc_unregister_component(&pdev->dev);
1210 dev_set_drvdata(&pdev->dev, NULL);
1211
1212 return 0;
1213}
1214
1215static const struct of_device_id fsl_spdif_dt_ids[] = {
1216 { .compatible = "fsl,imx35-spdif", },
1217 {}
1218};
1219MODULE_DEVICE_TABLE(of, fsl_spdif_dt_ids);
1220
1221static struct platform_driver fsl_spdif_driver = {
1222 .driver = {
1223 .name = "fsl-spdif-dai",
1224 .owner = THIS_MODULE,
1225 .of_match_table = fsl_spdif_dt_ids,
1226 },
1227 .probe = fsl_spdif_probe,
1228 .remove = fsl_spdif_remove,
1229};
1230
1231module_platform_driver(fsl_spdif_driver);
1232
1233MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1234MODULE_DESCRIPTION("Freescale S/PDIF CPU DAI Driver");
1235MODULE_LICENSE("GPL v2");
1236MODULE_ALIAS("platform:fsl-spdif-dai");
diff --git a/sound/soc/fsl/fsl_spdif.h b/sound/soc/fsl/fsl_spdif.h
new file mode 100644
index 000000000000..b1266790d117
--- /dev/null
+++ b/sound/soc/fsl/fsl_spdif.h
@@ -0,0 +1,191 @@
1/*
2 * fsl_spdif.h - ALSA S/PDIF interface for the Freescale i.MX SoC
3 *
4 * Copyright (C) 2013 Freescale Semiconductor, Inc.
5 *
6 * Author: Nicolin Chen <b42378@freescale.com>
7 *
8 * Based on fsl_ssi.h
9 * Author: Timur Tabi <timur@freescale.com>
10 * Copyright 2007-2008 Freescale Semiconductor, Inc.
11 *
12 * This file is licensed under the terms of the GNU General Public License
13 * version 2. This program is licensed "as is" without any warranty of any
14 * kind, whether express or implied.
15 */
16
17#ifndef _FSL_SPDIF_DAI_H
18#define _FSL_SPDIF_DAI_H
19
20/* S/PDIF Register Map */
21#define REG_SPDIF_SCR 0x0 /* SPDIF Configuration Register */
22#define REG_SPDIF_SRCD 0x4 /* CDText Control Register */
23#define REG_SPDIF_SRPC 0x8 /* PhaseConfig Register */
24#define REG_SPDIF_SIE 0xc /* InterruptEn Register */
25#define REG_SPDIF_SIS 0x10 /* InterruptStat Register */
26#define REG_SPDIF_SIC 0x10 /* InterruptClear Register */
27#define REG_SPDIF_SRL 0x14 /* SPDIFRxLeft Register */
28#define REG_SPDIF_SRR 0x18 /* SPDIFRxRight Register */
29#define REG_SPDIF_SRCSH 0x1c /* SPDIFRxCChannel_h Register */
30#define REG_SPDIF_SRCSL 0x20 /* SPDIFRxCChannel_l Register */
31#define REG_SPDIF_SRU 0x24 /* UchannelRx Register */
32#define REG_SPDIF_SRQ 0x28 /* QchannelRx Register */
33#define REG_SPDIF_STL 0x2C /* SPDIFTxLeft Register */
34#define REG_SPDIF_STR 0x30 /* SPDIFTxRight Register */
35#define REG_SPDIF_STCSCH 0x34 /* SPDIFTxCChannelCons_h Register */
36#define REG_SPDIF_STCSCL 0x38 /* SPDIFTxCChannelCons_l Register */
37#define REG_SPDIF_SRFM 0x44 /* FreqMeas Register */
38#define REG_SPDIF_STC 0x50 /* SPDIFTxClk Register */
39
40
41/* SPDIF Configuration register */
42#define SCR_RXFIFO_CTL_OFFSET 23
43#define SCR_RXFIFO_CTL_MASK (1 << SCR_RXFIFO_CTL_OFFSET)
44#define SCR_RXFIFO_CTL_ZERO (1 << SCR_RXFIFO_CTL_OFFSET)
45#define SCR_RXFIFO_OFF_OFFSET 22
46#define SCR_RXFIFO_OFF_MASK (1 << SCR_RXFIFO_OFF_OFFSET)
47#define SCR_RXFIFO_OFF (1 << SCR_RXFIFO_OFF_OFFSET)
48#define SCR_RXFIFO_RST_OFFSET 21
49#define SCR_RXFIFO_RST_MASK (1 << SCR_RXFIFO_RST_OFFSET)
50#define SCR_RXFIFO_RST (1 << SCR_RXFIFO_RST_OFFSET)
51#define SCR_RXFIFO_FSEL_OFFSET 19
52#define SCR_RXFIFO_FSEL_MASK (0x3 << SCR_RXFIFO_FSEL_OFFSET)
53#define SCR_RXFIFO_FSEL_IF0 (0x0 << SCR_RXFIFO_FSEL_OFFSET)
54#define SCR_RXFIFO_FSEL_IF4 (0x1 << SCR_RXFIFO_FSEL_OFFSET)
55#define SCR_RXFIFO_FSEL_IF8 (0x2 << SCR_RXFIFO_FSEL_OFFSET)
56#define SCR_RXFIFO_FSEL_IF12 (0x3 << SCR_RXFIFO_FSEL_OFFSET)
57#define SCR_RXFIFO_AUTOSYNC_OFFSET 18
58#define SCR_RXFIFO_AUTOSYNC_MASK (1 << SCR_RXFIFO_AUTOSYNC_OFFSET)
59#define SCR_RXFIFO_AUTOSYNC (1 << SCR_RXFIFO_AUTOSYNC_OFFSET)
60#define SCR_TXFIFO_AUTOSYNC_OFFSET 17
61#define SCR_TXFIFO_AUTOSYNC_MASK (1 << SCR_TXFIFO_AUTOSYNC_OFFSET)
62#define SCR_TXFIFO_AUTOSYNC (1 << SCR_TXFIFO_AUTOSYNC_OFFSET)
63#define SCR_TXFIFO_FSEL_OFFSET 15
64#define SCR_TXFIFO_FSEL_MASK (0x3 << SCR_TXFIFO_FSEL_OFFSET)
65#define SCR_TXFIFO_FSEL_IF0 (0x0 << SCR_TXFIFO_FSEL_OFFSET)
66#define SCR_TXFIFO_FSEL_IF4 (0x1 << SCR_TXFIFO_FSEL_OFFSET)
67#define SCR_TXFIFO_FSEL_IF8 (0x2 << SCR_TXFIFO_FSEL_OFFSET)
68#define SCR_TXFIFO_FSEL_IF12 (0x3 << SCR_TXFIFO_FSEL_OFFSET)
69#define SCR_LOW_POWER (1 << 13)
70#define SCR_SOFT_RESET (1 << 12)
71#define SCR_TXFIFO_CTRL_OFFSET 10
72#define SCR_TXFIFO_CTRL_MASK (0x3 << SCR_TXFIFO_CTRL_OFFSET)
73#define SCR_TXFIFO_CTRL_ZERO (0x0 << SCR_TXFIFO_CTRL_OFFSET)
74#define SCR_TXFIFO_CTRL_NORMAL (0x1 << SCR_TXFIFO_CTRL_OFFSET)
75#define SCR_TXFIFO_CTRL_ONESAMPLE (0x2 << SCR_TXFIFO_CTRL_OFFSET)
76#define SCR_DMA_RX_EN_OFFSET 9
77#define SCR_DMA_RX_EN_MASK (1 << SCR_DMA_RX_EN_OFFSET)
78#define SCR_DMA_RX_EN (1 << SCR_DMA_RX_EN_OFFSET)
79#define SCR_DMA_TX_EN_OFFSET 8
80#define SCR_DMA_TX_EN_MASK (1 << SCR_DMA_TX_EN_OFFSET)
81#define SCR_DMA_TX_EN (1 << SCR_DMA_TX_EN_OFFSET)
82#define SCR_VAL_OFFSET 5
83#define SCR_VAL_MASK (1 << SCR_VAL_OFFSET)
84#define SCR_VAL_CLEAR (1 << SCR_VAL_OFFSET)
85#define SCR_TXSEL_OFFSET 2
86#define SCR_TXSEL_MASK (0x7 << SCR_TXSEL_OFFSET)
87#define SCR_TXSEL_OFF (0 << SCR_TXSEL_OFFSET)
88#define SCR_TXSEL_RX (1 << SCR_TXSEL_OFFSET)
89#define SCR_TXSEL_NORMAL (0x5 << SCR_TXSEL_OFFSET)
90#define SCR_USRC_SEL_OFFSET 0x0
91#define SCR_USRC_SEL_MASK (0x3 << SCR_USRC_SEL_OFFSET)
92#define SCR_USRC_SEL_NONE (0x0 << SCR_USRC_SEL_OFFSET)
93#define SCR_USRC_SEL_RECV (0x1 << SCR_USRC_SEL_OFFSET)
94#define SCR_USRC_SEL_CHIP (0x3 << SCR_USRC_SEL_OFFSET)
95
96/* SPDIF CDText control */
97#define SRCD_CD_USER_OFFSET 1
98#define SRCD_CD_USER (1 << SRCD_CD_USER_OFFSET)
99
100/* SPDIF Phase Configuration register */
101#define SRPC_DPLL_LOCKED (1 << 6)
102#define SRPC_CLKSRC_SEL_OFFSET 7
103#define SRPC_CLKSRC_SEL_MASK (0xf << SRPC_CLKSRC_SEL_OFFSET)
104#define SRPC_CLKSRC_SEL_SET(x) ((x << SRPC_CLKSRC_SEL_OFFSET) & SRPC_CLKSRC_SEL_MASK)
105#define SRPC_CLKSRC_SEL_LOCKED_OFFSET1 5
106#define SRPC_CLKSRC_SEL_LOCKED_OFFSET2 2
107#define SRPC_GAINSEL_OFFSET 3
108#define SRPC_GAINSEL_MASK (0x7 << SRPC_GAINSEL_OFFSET)
109#define SRPC_GAINSEL_SET(x) ((x << SRPC_GAINSEL_OFFSET) & SRPC_GAINSEL_MASK)
110
111#define SRPC_CLKSRC_MAX 16
112
113enum spdif_gainsel {
114 GAINSEL_MULTI_24 = 0,
115 GAINSEL_MULTI_16,
116 GAINSEL_MULTI_12,
117 GAINSEL_MULTI_8,
118 GAINSEL_MULTI_6,
119 GAINSEL_MULTI_4,
120 GAINSEL_MULTI_3,
121};
122#define GAINSEL_MULTI_MAX (GAINSEL_MULTI_3 + 1)
123#define SPDIF_DEFAULT_GAINSEL GAINSEL_MULTI_8
124
125/* SPDIF interrupt mask define */
126#define INT_DPLL_LOCKED (1 << 20)
127#define INT_TXFIFO_UNOV (1 << 19)
128#define INT_TXFIFO_RESYNC (1 << 18)
129#define INT_CNEW (1 << 17)
130#define INT_VAL_NOGOOD (1 << 16)
131#define INT_SYM_ERR (1 << 15)
132#define INT_BIT_ERR (1 << 14)
133#define INT_URX_FUL (1 << 10)
134#define INT_URX_OV (1 << 9)
135#define INT_QRX_FUL (1 << 8)
136#define INT_QRX_OV (1 << 7)
137#define INT_UQ_SYNC (1 << 6)
138#define INT_UQ_ERR (1 << 5)
139#define INT_RXFIFO_UNOV (1 << 4)
140#define INT_RXFIFO_RESYNC (1 << 3)
141#define INT_LOSS_LOCK (1 << 2)
142#define INT_TX_EM (1 << 1)
143#define INT_RXFIFO_FUL (1 << 0)
144
145/* SPDIF Clock register */
146#define STC_SYSCLK_DIV_OFFSET 11
147#define STC_SYSCLK_DIV_MASK (0x1ff << STC_TXCLK_SRC_OFFSET)
148#define STC_SYSCLK_DIV(x) ((((x) - 1) << STC_TXCLK_DIV_OFFSET) & STC_SYSCLK_DIV_MASK)
149#define STC_TXCLK_SRC_OFFSET 8
150#define STC_TXCLK_SRC_MASK (0x7 << STC_TXCLK_SRC_OFFSET)
151#define STC_TXCLK_SRC_SET(x) ((x << STC_TXCLK_SRC_OFFSET) & STC_TXCLK_SRC_MASK)
152#define STC_TXCLK_ALL_EN_OFFSET 7
153#define STC_TXCLK_ALL_EN_MASK (1 << STC_TXCLK_ALL_EN_OFFSET)
154#define STC_TXCLK_ALL_EN (1 << STC_TXCLK_ALL_EN_OFFSET)
155#define STC_TXCLK_DIV_OFFSET 0
156#define STC_TXCLK_DIV_MASK (0x7ff << STC_TXCLK_DIV_OFFSET)
157#define STC_TXCLK_DIV(x) ((((x) - 1) << STC_TXCLK_DIV_OFFSET) & STC_TXCLK_DIV_MASK)
158#define STC_TXCLK_SRC_MAX 8
159
160/* SPDIF tx rate */
161enum spdif_txrate {
162 SPDIF_TXRATE_32000 = 0,
163 SPDIF_TXRATE_44100,
164 SPDIF_TXRATE_48000,
165};
166#define SPDIF_TXRATE_MAX (SPDIF_TXRATE_48000 + 1)
167
168
169#define SPDIF_CSTATUS_BYTE 6
170#define SPDIF_UBITS_SIZE 96
171#define SPDIF_QSUB_SIZE (SPDIF_UBITS_SIZE / 8)
172
173
174#define FSL_SPDIF_RATES_PLAYBACK (SNDRV_PCM_RATE_32000 | \
175 SNDRV_PCM_RATE_44100 | \
176 SNDRV_PCM_RATE_48000)
177
178#define FSL_SPDIF_RATES_CAPTURE (SNDRV_PCM_RATE_16000 | \
179 SNDRV_PCM_RATE_32000 | \
180 SNDRV_PCM_RATE_44100 | \
181 SNDRV_PCM_RATE_48000 | \
182 SNDRV_PCM_RATE_64000 | \
183 SNDRV_PCM_RATE_96000)
184
185#define FSL_SPDIF_FORMATS_PLAYBACK (SNDRV_PCM_FMTBIT_S16_LE | \
186 SNDRV_PCM_FMTBIT_S20_3LE | \
187 SNDRV_PCM_FMTBIT_S24_LE)
188
189#define FSL_SPDIF_FORMATS_CAPTURE (SNDRV_PCM_FMTBIT_S24_LE)
190
191#endif /* _FSL_SPDIF_DAI_H */
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 2f2d837df07f..5cf626c4dc96 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -8,6 +8,26 @@
8 * This file is licensed under the terms of the GNU General Public License 8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any 9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied. 10 * kind, whether express or implied.
11 *
12 *
13 * Some notes why imx-pcm-fiq is used instead of DMA on some boards:
14 *
15 * The i.MX SSI core has some nasty limitations in AC97 mode. While most
16 * sane processor vendors have a FIFO per AC97 slot, the i.MX has only
17 * one FIFO which combines all valid receive slots. We cannot even select
18 * which slots we want to receive. The WM9712 with which this driver
19 * was developed with always sends GPIO status data in slot 12 which
20 * we receive in our (PCM-) data stream. The only chance we have is to
21 * manually skip this data in the FIQ handler. With sampling rates different
22 * from 48000Hz not every frame has valid receive data, so the ratio
23 * between pcm data and GPIO status data changes. Our FIQ handler is not
24 * able to handle this, hence this driver only works with 48000Hz sampling
25 * rate.
26 * Reading and writing AC97 registers is another challenge. The core
27 * provides us status bits when the read register is updated with *another*
28 * value. When we read the same register two times (and the register still
29 * contains the same value) these status bits are not set. We work
30 * around this by not polling these bits but only wait a fixed delay.
11 */ 31 */
12 32
13#include <linux/init.h> 33#include <linux/init.h>
@@ -36,7 +56,7 @@
36#define read_ssi(addr) in_be32(addr) 56#define read_ssi(addr) in_be32(addr)
37#define write_ssi(val, addr) out_be32(addr, val) 57#define write_ssi(val, addr) out_be32(addr, val)
38#define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) 58#define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
39#elif defined ARM 59#else
40#define read_ssi(addr) readl(addr) 60#define read_ssi(addr) readl(addr)
41#define write_ssi(val, addr) writel(val, addr) 61#define write_ssi(val, addr) writel(val, addr)
42/* 62/*
@@ -121,11 +141,14 @@ struct fsl_ssi_private {
121 141
122 bool new_binding; 142 bool new_binding;
123 bool ssi_on_imx; 143 bool ssi_on_imx;
144 bool imx_ac97;
145 bool use_dma;
124 struct clk *clk; 146 struct clk *clk;
125 struct snd_dmaengine_dai_dma_data dma_params_tx; 147 struct snd_dmaengine_dai_dma_data dma_params_tx;
126 struct snd_dmaengine_dai_dma_data dma_params_rx; 148 struct snd_dmaengine_dai_dma_data dma_params_rx;
127 struct imx_dma_data filter_data_tx; 149 struct imx_dma_data filter_data_tx;
128 struct imx_dma_data filter_data_rx; 150 struct imx_dma_data filter_data_rx;
151 struct imx_pcm_fiq_params fiq_params;
129 152
130 struct { 153 struct {
131 unsigned int rfrc; 154 unsigned int rfrc;
@@ -298,6 +321,102 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
298 return ret; 321 return ret;
299} 322}
300 323
324static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
325{
326 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
327 u8 i2s_mode;
328 u8 wm;
329 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
330
331 if (ssi_private->imx_ac97)
332 i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
333 else
334 i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
335
336 /*
337 * Section 16.5 of the MPC8610 reference manual says that the SSI needs
338 * to be disabled before updating the registers we set here.
339 */
340 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
341
342 /*
343 * Program the SSI into I2S Slave Non-Network Synchronous mode. Also
344 * enable the transmit and receive FIFO.
345 *
346 * FIXME: Little-endian samples require a different shift dir
347 */
348 write_ssi_mask(&ssi->scr,
349 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
350 CCSR_SSI_SCR_TFR_CLK_DIS |
351 i2s_mode |
352 (synchronous ? CCSR_SSI_SCR_SYN : 0));
353
354 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
355 CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
356 CCSR_SSI_STCR_TSCKP, &ssi->stcr);
357
358 write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
359 CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
360 CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
361 /*
362 * The DC and PM bits are only used if the SSI is the clock master.
363 */
364
365 /*
366 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
367 * use FIFO 1. We program the transmit water to signal a DMA transfer
368 * if there are only two (or fewer) elements left in the FIFO. Two
369 * elements equals one frame (left channel, right channel). This value,
370 * however, depends on the depth of the transmit buffer.
371 *
372 * We set the watermark on the same level as the DMA burstsize. For
373 * fiq it is probably better to use the biggest possible watermark
374 * size.
375 */
376 if (ssi_private->use_dma)
377 wm = ssi_private->fifo_depth - 2;
378 else
379 wm = ssi_private->fifo_depth;
380
381 write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
382 CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm),
383 &ssi->sfcsr);
384
385 /*
386 * For ac97 interrupts are enabled with the startup of the substream
387 * because it is also running without an active substream. Normally SSI
388 * is only enabled when there is a substream.
389 */
390 if (ssi_private->imx_ac97) {
391 /*
392 * Setup the clock control register
393 */
394 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
395 &ssi->stccr);
396 write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
397 &ssi->srccr);
398
399 /*
400 * Enable AC97 mode and startup the SSI
401 */
402 write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
403 &ssi->sacnt);
404 write_ssi(0xff, &ssi->saccdis);
405 write_ssi(0x300, &ssi->saccen);
406
407 /*
408 * Enable SSI, Transmit and Receive
409 */
410 write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
411 CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
412
413 write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
414 }
415
416 return 0;
417}
418
419
301/** 420/**
302 * fsl_ssi_startup: create a new substream 421 * fsl_ssi_startup: create a new substream
303 * 422 *
@@ -319,70 +438,14 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
319 * and initialize the SSI registers. 438 * and initialize the SSI registers.
320 */ 439 */
321 if (!ssi_private->first_stream) { 440 if (!ssi_private->first_stream) {
322 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
323
324 ssi_private->first_stream = substream; 441 ssi_private->first_stream = substream;
325 442
326 /* 443 /*
327 * Section 16.5 of the MPC8610 reference manual says that the 444 * fsl_ssi_setup was already called by ac97_init earlier if
328 * SSI needs to be disabled before updating the registers we set 445 * the driver is in ac97 mode.
329 * here.
330 */
331 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
332
333 /*
334 * Program the SSI into I2S Slave Non-Network Synchronous mode.
335 * Also enable the transmit and receive FIFO.
336 *
337 * FIXME: Little-endian samples require a different shift dir
338 */
339 write_ssi_mask(&ssi->scr,
340 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
341 CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE
342 | (synchronous ? CCSR_SSI_SCR_SYN : 0));
343
344 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
345 CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
346 CCSR_SSI_STCR_TSCKP, &ssi->stcr);
347
348 write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
349 CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
350 CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
351
352 /*
353 * The DC and PM bits are only used if the SSI is the clock
354 * master.
355 */
356
357 /* Enable the interrupts and DMA requests */
358 write_ssi(SIER_FLAGS, &ssi->sier);
359
360 /*
361 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
362 * don't use FIFO 1. We program the transmit water to signal a
363 * DMA transfer if there are only two (or fewer) elements left
364 * in the FIFO. Two elements equals one frame (left channel,
365 * right channel). This value, however, depends on the depth of
366 * the transmit buffer.
367 *
368 * We program the receive FIFO to notify us if at least two
369 * elements (one frame) have been written to the FIFO. We could
370 * make this value larger (and maybe we should), but this way
371 * data will be written to memory as soon as it's available.
372 */
373 write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
374 CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2),
375 &ssi->sfcsr);
376
377 /*
378 * We keep the SSI disabled because if we enable it, then the
379 * DMA controller will start. It's not supposed to start until
380 * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The
381 * DMA controller will transfer one "BWC" of data (i.e. the
382 * amount of data that the MR.BWC bits are set to). The reason
383 * this is bad is because at this point, the PCM driver has not
384 * finished initializing the DMA controller.
385 */ 446 */
447 if (!ssi_private->imx_ac97)
448 fsl_ssi_setup(ssi_private);
386 } else { 449 } else {
387 if (synchronous) { 450 if (synchronous) {
388 struct snd_pcm_runtime *first_runtime = 451 struct snd_pcm_runtime *first_runtime =
@@ -492,6 +555,27 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
492 struct snd_soc_pcm_runtime *rtd = substream->private_data; 555 struct snd_soc_pcm_runtime *rtd = substream->private_data;
493 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); 556 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
494 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 557 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
558 unsigned int sier_bits;
559
560 /*
561 * Enable only the interrupts and DMA requests
562 * that are needed for the channel. As the fiq
563 * is polling for this bits, we have to ensure
564 * that this are aligned with the preallocated
565 * buffers
566 */
567
568 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
569 if (ssi_private->use_dma)
570 sier_bits = SIER_FLAGS;
571 else
572 sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN;
573 } else {
574 if (ssi_private->use_dma)
575 sier_bits = SIER_FLAGS;
576 else
577 sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN;
578 }
495 579
496 switch (cmd) { 580 switch (cmd) {
497 case SNDRV_PCM_TRIGGER_START: 581 case SNDRV_PCM_TRIGGER_START:
@@ -510,12 +594,18 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
510 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); 594 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0);
511 else 595 else
512 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); 596 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
597
598 if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) &
599 (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0)
600 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
513 break; 601 break;
514 602
515 default: 603 default:
516 return -EINVAL; 604 return -EINVAL;
517 } 605 }
518 606
607 write_ssi(sier_bits, &ssi->sier);
608
519 return 0; 609 return 0;
520} 610}
521 611
@@ -534,22 +624,13 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
534 ssi_private->first_stream = ssi_private->second_stream; 624 ssi_private->first_stream = ssi_private->second_stream;
535 625
536 ssi_private->second_stream = NULL; 626 ssi_private->second_stream = NULL;
537
538 /*
539 * If this is the last active substream, disable the SSI.
540 */
541 if (!ssi_private->first_stream) {
542 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
543
544 write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
545 }
546} 627}
547 628
548static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) 629static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
549{ 630{
550 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); 631 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
551 632
552 if (ssi_private->ssi_on_imx) { 633 if (ssi_private->ssi_on_imx && ssi_private->use_dma) {
553 dai->playback_dma_data = &ssi_private->dma_params_tx; 634 dai->playback_dma_data = &ssi_private->dma_params_tx;
554 dai->capture_dma_data = &ssi_private->dma_params_rx; 635 dai->capture_dma_data = &ssi_private->dma_params_rx;
555 } 636 }
@@ -587,6 +668,133 @@ static const struct snd_soc_component_driver fsl_ssi_component = {
587 .name = "fsl-ssi", 668 .name = "fsl-ssi",
588}; 669};
589 670
671/**
672 * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit.
673 *
674 * This function is called by ALSA to start, stop, pause, and resume the
675 * transfer of data.
676 */
677static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
678 struct snd_soc_dai *dai)
679{
680 struct snd_soc_pcm_runtime *rtd = substream->private_data;
681 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(
682 rtd->cpu_dai);
683 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
684
685 switch (cmd) {
686 case SNDRV_PCM_TRIGGER_START:
687 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
688 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
689 write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE |
690 CCSR_SSI_SIER_TFE0_EN);
691 else
692 write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE |
693 CCSR_SSI_SIER_RFF0_EN);
694 break;
695
696 case SNDRV_PCM_TRIGGER_STOP:
697 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
698 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
699 write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE |
700 CCSR_SSI_SIER_TFE0_EN, 0);
701 else
702 write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE |
703 CCSR_SSI_SIER_RFF0_EN, 0);
704 break;
705
706 default:
707 return -EINVAL;
708 }
709
710 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
711 write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor);
712 else
713 write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor);
714
715 return 0;
716}
717
718static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = {
719 .startup = fsl_ssi_startup,
720 .shutdown = fsl_ssi_shutdown,
721 .trigger = fsl_ssi_ac97_trigger,
722};
723
724static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
725 .ac97_control = 1,
726 .playback = {
727 .stream_name = "AC97 Playback",
728 .channels_min = 2,
729 .channels_max = 2,
730 .rates = SNDRV_PCM_RATE_8000_48000,
731 .formats = SNDRV_PCM_FMTBIT_S16_LE,
732 },
733 .capture = {
734 .stream_name = "AC97 Capture",
735 .channels_min = 2,
736 .channels_max = 2,
737 .rates = SNDRV_PCM_RATE_48000,
738 .formats = SNDRV_PCM_FMTBIT_S16_LE,
739 },
740 .ops = &fsl_ssi_ac97_dai_ops,
741};
742
743
744static struct fsl_ssi_private *fsl_ac97_data;
745
746static void fsl_ssi_ac97_init(void)
747{
748 fsl_ssi_setup(fsl_ac97_data);
749}
750
751void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
752 unsigned short val)
753{
754 struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
755 unsigned int lreg;
756 unsigned int lval;
757
758 if (reg > 0x7f)
759 return;
760
761
762 lreg = reg << 12;
763 write_ssi(lreg, &ssi->sacadd);
764
765 lval = val << 4;
766 write_ssi(lval , &ssi->sacdat);
767
768 write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
769 CCSR_SSI_SACNT_WR);
770 udelay(100);
771}
772
773unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
774 unsigned short reg)
775{
776 struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
777
778 unsigned short val = -1;
779 unsigned int lreg;
780
781 lreg = (reg & 0x7f) << 12;
782 write_ssi(lreg, &ssi->sacadd);
783 write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
784 CCSR_SSI_SACNT_RD);
785
786 udelay(100);
787
788 val = (read_ssi(&ssi->sacdat) >> 4) & 0xffff;
789
790 return val;
791}
792
793static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
794 .read = fsl_ssi_ac97_read,
795 .write = fsl_ssi_ac97_write,
796};
797
590/* Show the statistics of a flag only if its interrupt is enabled. The 798/* Show the statistics of a flag only if its interrupt is enabled. The
591 * compiler will optimze this code to a no-op if the interrupt is not 799 * compiler will optimze this code to a no-op if the interrupt is not
592 * enabled. 800 * enabled.
@@ -663,6 +871,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
663 struct resource res; 871 struct resource res;
664 char name[64]; 872 char name[64];
665 bool shared; 873 bool shared;
874 bool ac97 = false;
666 875
667 /* SSIs that are not connected on the board should have a 876 /* SSIs that are not connected on the board should have a
668 * status = "disabled" 877 * status = "disabled"
@@ -673,14 +882,20 @@ static int fsl_ssi_probe(struct platform_device *pdev)
673 882
674 /* We only support the SSI in "I2S Slave" mode */ 883 /* We only support the SSI in "I2S Slave" mode */
675 sprop = of_get_property(np, "fsl,mode", NULL); 884 sprop = of_get_property(np, "fsl,mode", NULL);
676 if (!sprop || strcmp(sprop, "i2s-slave")) { 885 if (!sprop) {
886 dev_err(&pdev->dev, "fsl,mode property is necessary\n");
887 return -EINVAL;
888 }
889 if (!strcmp(sprop, "ac97-slave")) {
890 ac97 = true;
891 } else if (strcmp(sprop, "i2s-slave")) {
677 dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); 892 dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop);
678 return -ENODEV; 893 return -ENODEV;
679 } 894 }
680 895
681 /* The DAI name is the last part of the full name of the node. */ 896 /* The DAI name is the last part of the full name of the node. */
682 p = strrchr(np->full_name, '/') + 1; 897 p = strrchr(np->full_name, '/') + 1;
683 ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), 898 ssi_private = devm_kzalloc(&pdev->dev, sizeof(*ssi_private) + strlen(p),
684 GFP_KERNEL); 899 GFP_KERNEL);
685 if (!ssi_private) { 900 if (!ssi_private) {
686 dev_err(&pdev->dev, "could not allocate DAI object\n"); 901 dev_err(&pdev->dev, "could not allocate DAI object\n");
@@ -689,38 +904,41 @@ static int fsl_ssi_probe(struct platform_device *pdev)
689 904
690 strcpy(ssi_private->name, p); 905 strcpy(ssi_private->name, p);
691 906
692 /* Initialize this copy of the CPU DAI driver structure */ 907 ssi_private->use_dma = !of_property_read_bool(np,
693 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, 908 "fsl,fiq-stream-filter");
694 sizeof(fsl_ssi_dai_template)); 909
910 if (ac97) {
911 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai,
912 sizeof(fsl_ssi_ac97_dai));
913
914 fsl_ac97_data = ssi_private;
915 ssi_private->imx_ac97 = true;
916
917 snd_soc_set_ac97_ops_of_reset(&fsl_ssi_ac97_ops, pdev);
918 } else {
919 /* Initialize this copy of the CPU DAI driver structure */
920 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
921 sizeof(fsl_ssi_dai_template));
922 }
695 ssi_private->cpu_dai_drv.name = ssi_private->name; 923 ssi_private->cpu_dai_drv.name = ssi_private->name;
696 924
697 /* Get the addresses and IRQ */ 925 /* Get the addresses and IRQ */
698 ret = of_address_to_resource(np, 0, &res); 926 ret = of_address_to_resource(np, 0, &res);
699 if (ret) { 927 if (ret) {
700 dev_err(&pdev->dev, "could not determine device resources\n"); 928 dev_err(&pdev->dev, "could not determine device resources\n");
701 goto error_kmalloc; 929 return ret;
702 } 930 }
703 ssi_private->ssi = of_iomap(np, 0); 931 ssi_private->ssi = of_iomap(np, 0);
704 if (!ssi_private->ssi) { 932 if (!ssi_private->ssi) {
705 dev_err(&pdev->dev, "could not map device resources\n"); 933 dev_err(&pdev->dev, "could not map device resources\n");
706 ret = -ENOMEM; 934 return -ENOMEM;
707 goto error_kmalloc;
708 } 935 }
709 ssi_private->ssi_phys = res.start; 936 ssi_private->ssi_phys = res.start;
710 937
711 ssi_private->irq = irq_of_parse_and_map(np, 0); 938 ssi_private->irq = irq_of_parse_and_map(np, 0);
712 if (ssi_private->irq == NO_IRQ) { 939 if (ssi_private->irq == NO_IRQ) {
713 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); 940 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
714 ret = -ENXIO; 941 return -ENXIO;
715 goto error_iomap;
716 }
717
718 /* The 'name' should not have any slashes in it. */
719 ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name,
720 ssi_private);
721 if (ret < 0) {
722 dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq);
723 goto error_irqmap;
724 } 942 }
725 943
726 /* Are the RX and the TX clocks locked? */ 944 /* Are the RX and the TX clocks locked? */
@@ -739,13 +957,18 @@ static int fsl_ssi_probe(struct platform_device *pdev)
739 u32 dma_events[2]; 957 u32 dma_events[2];
740 ssi_private->ssi_on_imx = true; 958 ssi_private->ssi_on_imx = true;
741 959
742 ssi_private->clk = clk_get(&pdev->dev, NULL); 960 ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
743 if (IS_ERR(ssi_private->clk)) { 961 if (IS_ERR(ssi_private->clk)) {
744 ret = PTR_ERR(ssi_private->clk); 962 ret = PTR_ERR(ssi_private->clk);
745 dev_err(&pdev->dev, "could not get clock: %d\n", ret); 963 dev_err(&pdev->dev, "could not get clock: %d\n", ret);
746 goto error_irq; 964 goto error_irqmap;
965 }
966 ret = clk_prepare_enable(ssi_private->clk);
967 if (ret) {
968 dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n",
969 ret);
970 goto error_irqmap;
747 } 971 }
748 clk_prepare_enable(ssi_private->clk);
749 972
750 /* 973 /*
751 * We have burstsize be "fifo_depth - 2" to match the SSI 974 * We have burstsize be "fifo_depth - 2" to match the SSI
@@ -763,24 +986,38 @@ static int fsl_ssi_probe(struct platform_device *pdev)
763 &ssi_private->filter_data_tx; 986 &ssi_private->filter_data_tx;
764 ssi_private->dma_params_rx.filter_data = 987 ssi_private->dma_params_rx.filter_data =
765 &ssi_private->filter_data_rx; 988 &ssi_private->filter_data_rx;
766 /* 989 if (!of_property_read_bool(pdev->dev.of_node, "dmas") &&
767 * TODO: This is a temporary solution and should be changed 990 ssi_private->use_dma) {
768 * to use generic DMA binding later when the helplers get in. 991 /*
769 */ 992 * FIXME: This is a temporary solution until all
770 ret = of_property_read_u32_array(pdev->dev.of_node, 993 * necessary dma drivers support the generic dma
994 * bindings.
995 */
996 ret = of_property_read_u32_array(pdev->dev.of_node,
771 "fsl,ssi-dma-events", dma_events, 2); 997 "fsl,ssi-dma-events", dma_events, 2);
772 if (ret) { 998 if (ret && ssi_private->use_dma) {
773 dev_err(&pdev->dev, "could not get dma events\n"); 999 dev_err(&pdev->dev, "could not get dma events but fsl-ssi is configured to use DMA\n");
774 goto error_clk; 1000 goto error_clk;
1001 }
775 } 1002 }
776 1003
777 shared = of_device_is_compatible(of_get_parent(np), 1004 shared = of_device_is_compatible(of_get_parent(np),
778 "fsl,spba-bus"); 1005 "fsl,spba-bus");
779 1006
780 imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx, 1007 imx_pcm_dma_params_init_data(&ssi_private->filter_data_tx,
781 dma_events[0], shared); 1008 dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
782 imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, 1009 imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
783 dma_events[1], shared); 1010 dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
1011 } else if (ssi_private->use_dma) {
1012 /* The 'name' should not have any slashes in it. */
1013 ret = devm_request_irq(&pdev->dev, ssi_private->irq,
1014 fsl_ssi_isr, 0, ssi_private->name,
1015 ssi_private);
1016 if (ret < 0) {
1017 dev_err(&pdev->dev, "could not claim irq %u\n",
1018 ssi_private->irq);
1019 goto error_irqmap;
1020 }
784 } 1021 }
785 1022
786 /* Initialize the the device_attribute structure */ 1023 /* Initialize the the device_attribute structure */
@@ -794,7 +1031,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
794 if (ret) { 1031 if (ret) {
795 dev_err(&pdev->dev, "could not create sysfs %s file\n", 1032 dev_err(&pdev->dev, "could not create sysfs %s file\n",
796 ssi_private->dev_attr.attr.name); 1033 ssi_private->dev_attr.attr.name);
797 goto error_irq; 1034 goto error_clk;
798 } 1035 }
799 1036
800 /* Register with ASoC */ 1037 /* Register with ASoC */
@@ -808,9 +1045,30 @@ static int fsl_ssi_probe(struct platform_device *pdev)
808 } 1045 }
809 1046
810 if (ssi_private->ssi_on_imx) { 1047 if (ssi_private->ssi_on_imx) {
811 ret = imx_pcm_dma_init(pdev); 1048 if (!ssi_private->use_dma) {
812 if (ret) 1049
813 goto error_dev; 1050 /*
1051 * Some boards use an incompatible codec. To get it
1052 * working, we are using imx-fiq-pcm-audio, that
1053 * can handle those codecs. DMA is not possible in this
1054 * situation.
1055 */
1056
1057 ssi_private->fiq_params.irq = ssi_private->irq;
1058 ssi_private->fiq_params.base = ssi_private->ssi;
1059 ssi_private->fiq_params.dma_params_rx =
1060 &ssi_private->dma_params_rx;
1061 ssi_private->fiq_params.dma_params_tx =
1062 &ssi_private->dma_params_tx;
1063
1064 ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params);
1065 if (ret)
1066 goto error_dev;
1067 } else {
1068 ret = imx_pcm_dma_init(pdev);
1069 if (ret)
1070 goto error_dev;
1071 }
814 } 1072 }
815 1073
816 /* 1074 /*
@@ -845,6 +1103,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
845 } 1103 }
846 1104
847done: 1105done:
1106 if (ssi_private->imx_ac97)
1107 fsl_ssi_ac97_init();
1108
848 return 0; 1109 return 0;
849 1110
850error_dai: 1111error_dai:
@@ -857,23 +1118,12 @@ error_dev:
857 device_remove_file(&pdev->dev, dev_attr); 1118 device_remove_file(&pdev->dev, dev_attr);
858 1119
859error_clk: 1120error_clk:
860 if (ssi_private->ssi_on_imx) { 1121 if (ssi_private->ssi_on_imx)
861 clk_disable_unprepare(ssi_private->clk); 1122 clk_disable_unprepare(ssi_private->clk);
862 clk_put(ssi_private->clk);
863 }
864
865error_irq:
866 free_irq(ssi_private->irq, ssi_private);
867 1123
868error_irqmap: 1124error_irqmap:
869 irq_dispose_mapping(ssi_private->irq); 1125 irq_dispose_mapping(ssi_private->irq);
870 1126
871error_iomap:
872 iounmap(ssi_private->ssi);
873
874error_kmalloc:
875 kfree(ssi_private);
876
877 return ret; 1127 return ret;
878} 1128}
879 1129
@@ -883,20 +1133,15 @@ static int fsl_ssi_remove(struct platform_device *pdev)
883 1133
884 if (!ssi_private->new_binding) 1134 if (!ssi_private->new_binding)
885 platform_device_unregister(ssi_private->pdev); 1135 platform_device_unregister(ssi_private->pdev);
886 if (ssi_private->ssi_on_imx) { 1136 if (ssi_private->ssi_on_imx)
887 imx_pcm_dma_exit(pdev); 1137 imx_pcm_dma_exit(pdev);
888 clk_disable_unprepare(ssi_private->clk);
889 clk_put(ssi_private->clk);
890 }
891 snd_soc_unregister_component(&pdev->dev); 1138 snd_soc_unregister_component(&pdev->dev);
1139 dev_set_drvdata(&pdev->dev, NULL);
892 device_remove_file(&pdev->dev, &ssi_private->dev_attr); 1140 device_remove_file(&pdev->dev, &ssi_private->dev_attr);
893 1141 if (ssi_private->ssi_on_imx)
894 free_irq(ssi_private->irq, ssi_private); 1142 clk_disable_unprepare(ssi_private->clk);
895 irq_dispose_mapping(ssi_private->irq); 1143 irq_dispose_mapping(ssi_private->irq);
896 1144
897 kfree(ssi_private);
898 dev_set_drvdata(&pdev->dev, NULL);
899
900 return 0; 1145 return 0;
901} 1146}
902 1147
@@ -919,6 +1164,7 @@ static struct platform_driver fsl_ssi_driver = {
919 1164
920module_platform_driver(fsl_ssi_driver); 1165module_platform_driver(fsl_ssi_driver);
921 1166
1167MODULE_ALIAS("platform:fsl-ssi-dai");
922MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 1168MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
923MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); 1169MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
924MODULE_LICENSE("GPL v2"); 1170MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index e260f1f899db..ab17381cc981 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -73,8 +73,11 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
73 if (!buf) 73 if (!buf)
74 return -ENOMEM; 74 return -ENOMEM;
75 75
76 if (audmux_clk) 76 if (audmux_clk) {
77 clk_prepare_enable(audmux_clk); 77 ret = clk_prepare_enable(audmux_clk);
78 if (ret)
79 return ret;
80 }
78 81
79 ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port)); 82 ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port));
80 pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port)); 83 pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port));
@@ -224,14 +227,19 @@ EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port);
224int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, 227int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
225 unsigned int pdcr) 228 unsigned int pdcr)
226{ 229{
230 int ret;
231
227 if (audmux_type != IMX31_AUDMUX) 232 if (audmux_type != IMX31_AUDMUX)
228 return -EINVAL; 233 return -EINVAL;
229 234
230 if (!audmux_base) 235 if (!audmux_base)
231 return -ENOSYS; 236 return -ENOSYS;
232 237
233 if (audmux_clk) 238 if (audmux_clk) {
234 clk_prepare_enable(audmux_clk); 239 ret = clk_prepare_enable(audmux_clk);
240 if (ret)
241 return ret;
242 }
235 243
236 writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port)); 244 writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port));
237 writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port)); 245 writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port));
@@ -243,6 +251,66 @@ int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
243} 251}
244EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); 252EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
245 253
254static int imx_audmux_parse_dt_defaults(struct platform_device *pdev,
255 struct device_node *of_node)
256{
257 struct device_node *child;
258
259 for_each_available_child_of_node(of_node, child) {
260 unsigned int port;
261 unsigned int ptcr = 0;
262 unsigned int pdcr = 0;
263 unsigned int pcr = 0;
264 unsigned int val;
265 int ret;
266 int i = 0;
267
268 ret = of_property_read_u32(child, "fsl,audmux-port", &port);
269 if (ret) {
270 dev_warn(&pdev->dev, "Failed to get fsl,audmux-port of child node \"%s\"\n",
271 child->full_name);
272 continue;
273 }
274 if (!of_property_read_bool(child, "fsl,port-config")) {
275 dev_warn(&pdev->dev, "child node \"%s\" does not have property fsl,port-config\n",
276 child->full_name);
277 continue;
278 }
279
280 for (i = 0; (ret = of_property_read_u32_index(child,
281 "fsl,port-config", i, &val)) == 0;
282 ++i) {
283 if (audmux_type == IMX31_AUDMUX) {
284 if (i % 2)
285 pdcr |= val;
286 else
287 ptcr |= val;
288 } else {
289 pcr |= val;
290 }
291 }
292
293 if (ret != -EOVERFLOW) {
294 dev_err(&pdev->dev, "Failed to read u32 at index %d of child %s\n",
295 i, child->full_name);
296 continue;
297 }
298
299 if (audmux_type == IMX31_AUDMUX) {
300 if (i % 2) {
301 dev_err(&pdev->dev, "One pdcr value is missing in child node %s\n",
302 child->full_name);
303 continue;
304 }
305 imx_audmux_v2_configure_port(port, ptcr, pdcr);
306 } else {
307 imx_audmux_v1_configure_port(port, pcr);
308 }
309 }
310
311 return 0;
312}
313
246static int imx_audmux_probe(struct platform_device *pdev) 314static int imx_audmux_probe(struct platform_device *pdev)
247{ 315{
248 struct resource *res; 316 struct resource *res;
@@ -267,6 +335,8 @@ static int imx_audmux_probe(struct platform_device *pdev)
267 if (audmux_type == IMX31_AUDMUX) 335 if (audmux_type == IMX31_AUDMUX)
268 audmux_debugfs_init(); 336 audmux_debugfs_init();
269 337
338 imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node);
339
270 return 0; 340 return 0;
271} 341}
272 342
diff --git a/sound/soc/fsl/imx-audmux.h b/sound/soc/fsl/imx-audmux.h
index b8ff44b9dafa..38a4209af7c6 100644
--- a/sound/soc/fsl/imx-audmux.h
+++ b/sound/soc/fsl/imx-audmux.h
@@ -1,57 +1,7 @@
1#ifndef __IMX_AUDMUX_H 1#ifndef __IMX_AUDMUX_H
2#define __IMX_AUDMUX_H 2#define __IMX_AUDMUX_H
3 3
4#define MX27_AUDMUX_HPCR1_SSI0 0 4#include <dt-bindings/sound/fsl-imx-audmux.h>
5#define MX27_AUDMUX_HPCR2_SSI1 1
6#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2
7#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3
8#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4
9#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5
10
11#define MX31_AUDMUX_PORT1_SSI0 0
12#define MX31_AUDMUX_PORT2_SSI1 1
13#define MX31_AUDMUX_PORT3_SSI_PINS_3 2
14#define MX31_AUDMUX_PORT4_SSI_PINS_4 3
15#define MX31_AUDMUX_PORT5_SSI_PINS_5 4
16#define MX31_AUDMUX_PORT6_SSI_PINS_6 5
17#define MX31_AUDMUX_PORT7_SSI_PINS_7 6
18
19#define MX51_AUDMUX_PORT1_SSI0 0
20#define MX51_AUDMUX_PORT2_SSI1 1
21#define MX51_AUDMUX_PORT3 2
22#define MX51_AUDMUX_PORT4 3
23#define MX51_AUDMUX_PORT5 4
24#define MX51_AUDMUX_PORT6 5
25#define MX51_AUDMUX_PORT7 6
26
27/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
28#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff)
29#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8)
30#define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10)
31#define IMX_AUDMUX_V1_PCR_SYN (1 << 12)
32#define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13)
33#define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20)
34#define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24)
35#define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25)
36#define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26)
37#define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30)
38#define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31)
39
40/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
41#define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31)
42#define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27)
43#define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26)
44#define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22)
45#define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21)
46#define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17)
47#define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16)
48#define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12)
49#define IMX_AUDMUX_V2_PTCR_SYN (1 << 11)
50
51#define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13)
52#define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12)
53#define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8)
54#define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff)
55 5
56int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr); 6int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr);
57 7
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
index 9df173c091a6..a3d60d4bea4c 100644
--- a/sound/soc/fsl/imx-mc13783.c
+++ b/sound/soc/fsl/imx-mc13783.c
@@ -90,6 +90,7 @@ static const struct snd_soc_dapm_route imx_mc13783_routes[] = {
90 90
91static struct snd_soc_card imx_mc13783 = { 91static struct snd_soc_card imx_mc13783 = {
92 .name = "imx_mc13783", 92 .name = "imx_mc13783",
93 .owner = THIS_MODULE,
93 .dai_link = imx_mc13783_dai_mc13783, 94 .dai_link = imx_mc13783_dai_mc13783,
94 .num_links = ARRAY_SIZE(imx_mc13783_dai_mc13783), 95 .num_links = ARRAY_SIZE(imx_mc13783_dai_mc13783),
95 .dapm_widgets = imx_mc13783_widget, 96 .dapm_widgets = imx_mc13783_widget,
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index fde4d2ea68c8..4dc1296688e9 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -14,6 +14,7 @@
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
16#include <linux/types.h> 16#include <linux/types.h>
17#include <linux/module.h>
17 18
18#include <sound/core.h> 19#include <sound/core.h>
19#include <sound/pcm.h> 20#include <sound/pcm.h>
@@ -64,7 +65,6 @@ int imx_pcm_dma_init(struct platform_device *pdev)
64{ 65{
65 return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config, 66 return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config,
66 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | 67 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
67 SND_DMAENGINE_PCM_FLAG_NO_DT |
68 SND_DMAENGINE_PCM_FLAG_COMPAT); 68 SND_DMAENGINE_PCM_FLAG_COMPAT);
69} 69}
70EXPORT_SYMBOL_GPL(imx_pcm_dma_init); 70EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
@@ -74,3 +74,5 @@ void imx_pcm_dma_exit(struct platform_device *pdev)
74 snd_dmaengine_pcm_unregister(&pdev->dev); 74 snd_dmaengine_pcm_unregister(&pdev->dev);
75} 75}
76EXPORT_SYMBOL_GPL(imx_pcm_dma_exit); 76EXPORT_SYMBOL_GPL(imx_pcm_dma_exit);
77
78MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 310d90290320..34043c55f2a6 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -22,6 +22,7 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23 23
24#include <sound/core.h> 24#include <sound/core.h>
25#include <sound/dmaengine_pcm.h>
25#include <sound/initval.h> 26#include <sound/initval.h>
26#include <sound/pcm.h> 27#include <sound/pcm.h>
27#include <sound/pcm_params.h> 28#include <sound/pcm_params.h>
@@ -32,6 +33,7 @@
32#include <linux/platform_data/asoc-imx-ssi.h> 33#include <linux/platform_data/asoc-imx-ssi.h>
33 34
34#include "imx-ssi.h" 35#include "imx-ssi.h"
36#include "imx-pcm.h"
35 37
36struct imx_pcm_runtime_data { 38struct imx_pcm_runtime_data {
37 unsigned int period; 39 unsigned int period;
@@ -366,9 +368,9 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = {
366 .pcm_free = imx_pcm_fiq_free, 368 .pcm_free = imx_pcm_fiq_free,
367}; 369};
368 370
369int imx_pcm_fiq_init(struct platform_device *pdev) 371int imx_pcm_fiq_init(struct platform_device *pdev,
372 struct imx_pcm_fiq_params *params)
370{ 373{
371 struct imx_ssi *ssi = platform_get_drvdata(pdev);
372 int ret; 374 int ret;
373 375
374 ret = claim_fiq(&fh); 376 ret = claim_fiq(&fh);
@@ -377,15 +379,15 @@ int imx_pcm_fiq_init(struct platform_device *pdev)
377 return ret; 379 return ret;
378 } 380 }
379 381
380 mxc_set_irq_fiq(ssi->irq, 1); 382 mxc_set_irq_fiq(params->irq, 1);
381 ssi_irq = ssi->irq; 383 ssi_irq = params->irq;
382 384
383 imx_pcm_fiq = ssi->irq; 385 imx_pcm_fiq = params->irq;
384 386
385 imx_ssi_fiq_base = (unsigned long)ssi->base; 387 imx_ssi_fiq_base = (unsigned long)params->base;
386 388
387 ssi->dma_params_tx.maxburst = 4; 389 params->dma_params_tx->maxburst = 4;
388 ssi->dma_params_rx.maxburst = 6; 390 params->dma_params_rx->maxburst = 6;
389 391
390 ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); 392 ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq);
391 if (ret) 393 if (ret)
@@ -406,3 +408,5 @@ void imx_pcm_fiq_exit(struct platform_device *pdev)
406 snd_soc_unregister_platform(&pdev->dev); 408 snd_soc_unregister_platform(&pdev->dev);
407} 409}
408EXPORT_SYMBOL_GPL(imx_pcm_fiq_exit); 410EXPORT_SYMBOL_GPL(imx_pcm_fiq_exit);
411
412MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
index 67f656c7c320..5d5b73303e11 100644
--- a/sound/soc/fsl/imx-pcm.h
+++ b/sound/soc/fsl/imx-pcm.h
@@ -22,17 +22,23 @@
22 22
23static inline void 23static inline void
24imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data, 24imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data,
25 int dma, bool shared) 25 int dma, enum sdma_peripheral_type peripheral_type)
26{ 26{
27 dma_data->dma_request = dma; 27 dma_data->dma_request = dma;
28 dma_data->priority = DMA_PRIO_HIGH; 28 dma_data->priority = DMA_PRIO_HIGH;
29 if (shared) 29 dma_data->peripheral_type = peripheral_type;
30 dma_data->peripheral_type = IMX_DMATYPE_SSI_SP;
31 else
32 dma_data->peripheral_type = IMX_DMATYPE_SSI;
33} 30}
34 31
35#ifdef CONFIG_SND_SOC_IMX_PCM_DMA 32struct imx_pcm_fiq_params {
33 int irq;
34 void __iomem *base;
35
36 /* Pointer to original ssi driver to setup tx rx sizes */
37 struct snd_dmaengine_dai_dma_data *dma_params_rx;
38 struct snd_dmaengine_dai_dma_data *dma_params_tx;
39};
40
41#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)
36int imx_pcm_dma_init(struct platform_device *pdev); 42int imx_pcm_dma_init(struct platform_device *pdev);
37void imx_pcm_dma_exit(struct platform_device *pdev); 43void imx_pcm_dma_exit(struct platform_device *pdev);
38#else 44#else
@@ -46,11 +52,13 @@ static inline void imx_pcm_dma_exit(struct platform_device *pdev)
46} 52}
47#endif 53#endif
48 54
49#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ 55#if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ)
50int imx_pcm_fiq_init(struct platform_device *pdev); 56int imx_pcm_fiq_init(struct platform_device *pdev,
57 struct imx_pcm_fiq_params *params);
51void imx_pcm_fiq_exit(struct platform_device *pdev); 58void imx_pcm_fiq_exit(struct platform_device *pdev);
52#else 59#else
53static inline int imx_pcm_fiq_init(struct platform_device *pdev) 60static inline int imx_pcm_fiq_init(struct platform_device *pdev,
61 struct imx_pcm_fiq_params *params)
54{ 62{
55 return -ENODEV; 63 return -ENODEV;
56} 64}
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 3f726e4f88db..389cbfa6dca7 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -129,8 +129,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
129 } 129 }
130 130
131 data->codec_clk = devm_clk_get(&codec_dev->dev, NULL); 131 data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
132 if (IS_ERR(data->codec_clk)) 132 if (IS_ERR(data->codec_clk)) {
133 ret = PTR_ERR(data->codec_clk);
133 goto fail; 134 goto fail;
135 }
134 136
135 data->clk_frequency = clk_get_rate(data->codec_clk); 137 data->clk_frequency = clk_get_rate(data->codec_clk);
136 138
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index 51be3772cba9..f58bcd85c07f 100644
--- a/sound/soc/fsl/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -571,13 +571,13 @@ static int imx_ssi_probe(struct platform_device *pdev)
571 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); 571 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
572 if (res) { 572 if (res) {
573 imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start, 573 imx_pcm_dma_params_init_data(&ssi->filter_data_tx, res->start,
574 false); 574 IMX_DMATYPE_SSI);
575 } 575 }
576 576
577 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); 577 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0");
578 if (res) { 578 if (res) {
579 imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start, 579 imx_pcm_dma_params_init_data(&ssi->filter_data_rx, res->start,
580 false); 580 IMX_DMATYPE_SSI);
581 } 581 }
582 582
583 platform_set_drvdata(pdev, ssi); 583 platform_set_drvdata(pdev, ssi);
@@ -595,7 +595,12 @@ static int imx_ssi_probe(struct platform_device *pdev)
595 goto failed_register; 595 goto failed_register;
596 } 596 }
597 597
598 ret = imx_pcm_fiq_init(pdev); 598 ssi->fiq_params.irq = ssi->irq;
599 ssi->fiq_params.base = ssi->base;
600 ssi->fiq_params.dma_params_rx = &ssi->dma_params_rx;
601 ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx;
602
603 ret = imx_pcm_fiq_init(pdev, &ssi->fiq_params);
599 if (ret) 604 if (ret)
600 goto failed_pcm_fiq; 605 goto failed_pcm_fiq;
601 606
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h
index d5003cefca8d..fb1616ba8c59 100644
--- a/sound/soc/fsl/imx-ssi.h
+++ b/sound/soc/fsl/imx-ssi.h
@@ -209,6 +209,7 @@ struct imx_ssi {
209 struct snd_dmaengine_dai_dma_data dma_params_tx; 209 struct snd_dmaengine_dai_dma_data dma_params_tx;
210 struct imx_dma_data filter_data_tx; 210 struct imx_dma_data filter_data_tx;
211 struct imx_dma_data filter_data_rx; 211 struct imx_dma_data filter_data_rx;
212 struct imx_pcm_fiq_params fiq_params;
212 213
213 int enabled; 214 int enabled;
214}; 215};
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index 52a36a90f4f4..1d70e278e915 100644
--- a/sound/soc/fsl/imx-wm8962.c
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -217,7 +217,8 @@ static int imx_wm8962_probe(struct platform_device *pdev)
217 codec_dev = of_find_i2c_device_by_node(codec_np); 217 codec_dev = of_find_i2c_device_by_node(codec_np);
218 if (!codec_dev || !codec_dev->driver) { 218 if (!codec_dev || !codec_dev->driver) {
219 dev_err(&pdev->dev, "failed to find codec platform device\n"); 219 dev_err(&pdev->dev, "failed to find codec platform device\n");
220 return -EINVAL; 220 ret = -EINVAL;
221 goto fail;
221 } 222 }
222 223
223 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 224 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
index c62d715235e2..9e1970c44e86 100644
--- a/sound/soc/kirkwood/Kconfig
+++ b/sound/soc/kirkwood/Kconfig
@@ -1,19 +1,15 @@
1config SND_KIRKWOOD_SOC 1config SND_KIRKWOOD_SOC
2 tristate "SoC Audio for the Marvell Kirkwood chip" 2 tristate "SoC Audio for the Marvell Kirkwood chip"
3 depends on ARCH_KIRKWOOD 3 depends on ARCH_KIRKWOOD || COMPILE_TEST
4 help 4 help
5 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
6 the Kirkwood I2S interface. You will also need to select the 6 the Kirkwood I2S interface. You will also need to select the
7 audio interfaces to support below. 7 audio interfaces to support below.
8 8
9config SND_KIRKWOOD_SOC_I2S
10 tristate
11
12config SND_KIRKWOOD_SOC_OPENRD 9config SND_KIRKWOOD_SOC_OPENRD
13 tristate "SoC Audio support for Kirkwood Openrd Client" 10 tristate "SoC Audio support for Kirkwood Openrd Client"
14 depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE) 11 depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST)
15 depends on I2C 12 depends on I2C
16 select SND_KIRKWOOD_SOC_I2S
17 select SND_SOC_CS42L51 13 select SND_SOC_CS42L51
18 help 14 help
19 Say Y if you want to add support for SoC audio on 15 Say Y if you want to add support for SoC audio on
@@ -21,8 +17,7 @@ config SND_KIRKWOOD_SOC_OPENRD
21 17
22config SND_KIRKWOOD_SOC_T5325 18config SND_KIRKWOOD_SOC_T5325
23 tristate "SoC Audio support for HP t5325" 19 tristate "SoC Audio support for HP t5325"
24 depends on SND_KIRKWOOD_SOC && MACH_T5325 && I2C 20 depends on SND_KIRKWOOD_SOC && (MACH_T5325 || COMPILE_TEST) && I2C
25 select SND_KIRKWOOD_SOC_I2S
26 select SND_SOC_ALC5623 21 select SND_SOC_ALC5623
27 help 22 help
28 Say Y if you want to add support for SoC audio on 23 Say Y if you want to add support for SoC audio on
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile
index 3e62ae9e7bbe..9e781385cb88 100644
--- a/sound/soc/kirkwood/Makefile
+++ b/sound/soc/kirkwood/Makefile
@@ -1,8 +1,6 @@
1snd-soc-kirkwood-objs := kirkwood-dma.o 1snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o
2snd-soc-kirkwood-i2s-objs := kirkwood-i2s.o
3 2
4obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o 3obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o
5obj-$(CONFIG_SND_KIRKWOOD_SOC_I2S) += snd-soc-kirkwood-i2s.o
6 4
7snd-soc-openrd-objs := kirkwood-openrd.o 5snd-soc-openrd-objs := kirkwood-openrd.o
8snd-soc-t5325-objs := kirkwood-t5325.o 6snd-soc-t5325-objs := kirkwood-t5325.o
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index a9f14530c3db..b238434f92b0 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -33,11 +33,11 @@
33 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \ 33 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
34 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE) 34 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
35 35
36struct kirkwood_dma_priv { 36static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
37 struct snd_pcm_substream *play_stream; 37{
38 struct snd_pcm_substream *rec_stream; 38 struct snd_soc_pcm_runtime *soc_runtime = subs->private_data;
39 struct kirkwood_dma_data *data; 39 return snd_soc_dai_get_drvdata(soc_runtime->cpu_dai);
40}; 40}
41 41
42static struct snd_pcm_hardware kirkwood_dma_snd_hw = { 42static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
43 .info = (SNDRV_PCM_INFO_INTERLEAVED | 43 .info = (SNDRV_PCM_INFO_INTERLEAVED |
@@ -51,7 +51,7 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
51 .rate_max = 384000, 51 .rate_max = 384000,
52 .channels_min = 1, 52 .channels_min = 1,
53 .channels_max = 8, 53 .channels_max = 8,
54 .buffer_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS, 54 .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES,
55 .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, 55 .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES,
56 .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, 56 .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES,
57 .periods_min = KIRKWOOD_SND_MIN_PERIODS, 57 .periods_min = KIRKWOOD_SND_MIN_PERIODS,
@@ -63,8 +63,7 @@ static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
63 63
64static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id) 64static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
65{ 65{
66 struct kirkwood_dma_priv *prdata = dev_id; 66 struct kirkwood_dma_data *priv = dev_id;
67 struct kirkwood_dma_data *priv = prdata->data;
68 unsigned long mask, status, cause; 67 unsigned long mask, status, cause;
69 68
70 mask = readl(priv->io + KIRKWOOD_INT_MASK); 69 mask = readl(priv->io + KIRKWOOD_INT_MASK);
@@ -89,10 +88,10 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
89 writel(status, priv->io + KIRKWOOD_INT_CAUSE); 88 writel(status, priv->io + KIRKWOOD_INT_CAUSE);
90 89
91 if (status & KIRKWOOD_INT_CAUSE_PLAY_BYTES) 90 if (status & KIRKWOOD_INT_CAUSE_PLAY_BYTES)
92 snd_pcm_period_elapsed(prdata->play_stream); 91 snd_pcm_period_elapsed(priv->substream_play);
93 92
94 if (status & KIRKWOOD_INT_CAUSE_REC_BYTES) 93 if (status & KIRKWOOD_INT_CAUSE_REC_BYTES)
95 snd_pcm_period_elapsed(prdata->rec_stream); 94 snd_pcm_period_elapsed(priv->substream_rec);
96 95
97 return IRQ_HANDLED; 96 return IRQ_HANDLED;
98} 97}
@@ -126,15 +125,10 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
126{ 125{
127 int err; 126 int err;
128 struct snd_pcm_runtime *runtime = substream->runtime; 127 struct snd_pcm_runtime *runtime = substream->runtime;
129 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 128 struct kirkwood_dma_data *priv = kirkwood_priv(substream);
130 struct snd_soc_platform *platform = soc_runtime->platform;
131 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
132 struct kirkwood_dma_data *priv;
133 struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
134 const struct mbus_dram_target_info *dram; 129 const struct mbus_dram_target_info *dram;
135 unsigned long addr; 130 unsigned long addr;
136 131
137 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
138 snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw); 132 snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw);
139 133
140 /* Ensure that all constraints linked to dma burst are fulfilled */ 134 /* Ensure that all constraints linked to dma burst are fulfilled */
@@ -157,21 +151,11 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
157 if (err < 0) 151 if (err < 0)
158 return err; 152 return err;
159 153
160 if (prdata == NULL) { 154 if (!priv->substream_play && !priv->substream_rec) {
161 prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL);
162 if (prdata == NULL)
163 return -ENOMEM;
164
165 prdata->data = priv;
166
167 err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED, 155 err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED,
168 "kirkwood-i2s", prdata); 156 "kirkwood-i2s", priv);
169 if (err) { 157 if (err)
170 kfree(prdata);
171 return -EBUSY; 158 return -EBUSY;
172 }
173
174 snd_soc_platform_set_drvdata(platform, prdata);
175 159
176 /* 160 /*
177 * Enable Error interrupts. We're only ack'ing them but 161 * Enable Error interrupts. We're only ack'ing them but
@@ -183,11 +167,11 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
183 dram = mv_mbus_dram_info(); 167 dram = mv_mbus_dram_info();
184 addr = substream->dma_buffer.addr; 168 addr = substream->dma_buffer.addr;
185 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 169 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
186 prdata->play_stream = substream; 170 priv->substream_play = substream;
187 kirkwood_dma_conf_mbus_windows(priv->io, 171 kirkwood_dma_conf_mbus_windows(priv->io,
188 KIRKWOOD_PLAYBACK_WIN, addr, dram); 172 KIRKWOOD_PLAYBACK_WIN, addr, dram);
189 } else { 173 } else {
190 prdata->rec_stream = substream; 174 priv->substream_rec = substream;
191 kirkwood_dma_conf_mbus_windows(priv->io, 175 kirkwood_dma_conf_mbus_windows(priv->io,
192 KIRKWOOD_RECORD_WIN, addr, dram); 176 KIRKWOOD_RECORD_WIN, addr, dram);
193 } 177 }
@@ -197,27 +181,19 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
197 181
198static int kirkwood_dma_close(struct snd_pcm_substream *substream) 182static int kirkwood_dma_close(struct snd_pcm_substream *substream)
199{ 183{
200 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 184 struct kirkwood_dma_data *priv = kirkwood_priv(substream);
201 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
202 struct snd_soc_platform *platform = soc_runtime->platform;
203 struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
204 struct kirkwood_dma_data *priv;
205
206 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
207 185
208 if (!prdata || !priv) 186 if (!priv)
209 return 0; 187 return 0;
210 188
211 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 189 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
212 prdata->play_stream = NULL; 190 priv->substream_play = NULL;
213 else 191 else
214 prdata->rec_stream = NULL; 192 priv->substream_rec = NULL;
215 193
216 if (!prdata->play_stream && !prdata->rec_stream) { 194 if (!priv->substream_play && !priv->substream_rec) {
217 writel(0, priv->io + KIRKWOOD_ERR_MASK); 195 writel(0, priv->io + KIRKWOOD_ERR_MASK);
218 free_irq(priv->irq, prdata); 196 free_irq(priv->irq, priv);
219 kfree(prdata);
220 snd_soc_platform_set_drvdata(platform, NULL);
221 } 197 }
222 198
223 return 0; 199 return 0;
@@ -243,13 +219,9 @@ static int kirkwood_dma_hw_free(struct snd_pcm_substream *substream)
243static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) 219static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
244{ 220{
245 struct snd_pcm_runtime *runtime = substream->runtime; 221 struct snd_pcm_runtime *runtime = substream->runtime;
246 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 222 struct kirkwood_dma_data *priv = kirkwood_priv(substream);
247 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
248 struct kirkwood_dma_data *priv;
249 unsigned long size, count; 223 unsigned long size, count;
250 224
251 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
252
253 /* compute buffer size in term of "words" as requested in specs */ 225 /* compute buffer size in term of "words" as requested in specs */
254 size = frames_to_bytes(runtime, runtime->buffer_size); 226 size = frames_to_bytes(runtime, runtime->buffer_size);
255 size = (size>>2)-1; 227 size = (size>>2)-1;
@@ -272,13 +244,9 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
272static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream 244static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream
273 *substream) 245 *substream)
274{ 246{
275 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 247 struct kirkwood_dma_data *priv = kirkwood_priv(substream);
276 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
277 struct kirkwood_dma_data *priv;
278 snd_pcm_uframes_t count; 248 snd_pcm_uframes_t count;
279 249
280 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
281
282 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 250 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
283 count = bytes_to_frames(substream->runtime, 251 count = bytes_to_frames(substream->runtime,
284 readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT)); 252 readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT));
@@ -366,36 +334,8 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm)
366 } 334 }
367} 335}
368 336
369static struct snd_soc_platform_driver kirkwood_soc_platform = { 337struct snd_soc_platform_driver kirkwood_soc_platform = {
370 .ops = &kirkwood_dma_ops, 338 .ops = &kirkwood_dma_ops,
371 .pcm_new = kirkwood_dma_new, 339 .pcm_new = kirkwood_dma_new,
372 .pcm_free = kirkwood_dma_free_dma_buffers, 340 .pcm_free = kirkwood_dma_free_dma_buffers,
373}; 341};
374
375static int kirkwood_soc_platform_probe(struct platform_device *pdev)
376{
377 return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
378}
379
380static int kirkwood_soc_platform_remove(struct platform_device *pdev)
381{
382 snd_soc_unregister_platform(&pdev->dev);
383 return 0;
384}
385
386static struct platform_driver kirkwood_pcm_driver = {
387 .driver = {
388 .name = "kirkwood-pcm-audio",
389 .owner = THIS_MODULE,
390 },
391
392 .probe = kirkwood_soc_platform_probe,
393 .remove = kirkwood_soc_platform_remove,
394};
395
396module_platform_driver(kirkwood_pcm_driver);
397
398MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
399MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module");
400MODULE_LICENSE("GPL");
401MODULE_ALIAS("platform:kirkwood-pcm-audio");
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 4c9dad3263c5..e5f3f7a9ea26 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -24,11 +24,8 @@
24#include <linux/platform_data/asoc-kirkwood.h> 24#include <linux/platform_data/asoc-kirkwood.h>
25#include "kirkwood.h" 25#include "kirkwood.h"
26 26
27#define DRV_NAME "kirkwood-i2s" 27#define DRV_NAME "mvebu-audio"
28 28
29#define KIRKWOOD_I2S_RATES \
30 (SNDRV_PCM_RATE_44100 | \
31 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
32#define KIRKWOOD_I2S_FORMATS \ 29#define KIRKWOOD_I2S_FORMATS \
33 (SNDRV_PCM_FMTBIT_S16_LE | \ 30 (SNDRV_PCM_FMTBIT_S16_LE | \
34 SNDRV_PCM_FMTBIT_S24_LE | \ 31 SNDRV_PCM_FMTBIT_S24_LE | \
@@ -105,14 +102,16 @@ static void kirkwood_set_rate(struct snd_soc_dai *dai,
105 uint32_t clks_ctrl; 102 uint32_t clks_ctrl;
106 103
107 if (rate == 44100 || rate == 48000 || rate == 96000) { 104 if (rate == 44100 || rate == 48000 || rate == 96000) {
108 /* use internal dco for supported rates */ 105 /* use internal dco for the supported rates
106 * defined in kirkwood_i2s_dai */
109 dev_dbg(dai->dev, "%s: dco set rate = %lu\n", 107 dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
110 __func__, rate); 108 __func__, rate);
111 kirkwood_set_dco(priv->io, rate); 109 kirkwood_set_dco(priv->io, rate);
112 110
113 clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO; 111 clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
114 } else if (!IS_ERR(priv->extclk)) { 112 } else {
115 /* use optional external clk for other rates */ 113 /* use the external clock for the other rates
114 * defined in kirkwood_i2s_dai_extclk */
116 dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n", 115 dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
117 __func__, rate, 256 * rate); 116 __func__, rate, 256 * rate);
118 clk_set_rate(priv->extclk, 256 * rate); 117 clk_set_rate(priv->extclk, 256 * rate);
@@ -199,8 +198,7 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
199 ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF; 198 ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
200 199
201 priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK | 200 priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
202 KIRKWOOD_PLAYCTL_I2S_EN | 201 KIRKWOOD_PLAYCTL_ENABLE_MASK |
203 KIRKWOOD_PLAYCTL_SPDIF_EN |
204 KIRKWOOD_PLAYCTL_SIZE_MASK); 202 KIRKWOOD_PLAYCTL_SIZE_MASK);
205 priv->ctl_play |= ctl_play; 203 priv->ctl_play |= ctl_play;
206 } else { 204 } else {
@@ -244,8 +242,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
244 case SNDRV_PCM_TRIGGER_START: 242 case SNDRV_PCM_TRIGGER_START:
245 /* configure */ 243 /* configure */
246 ctl = priv->ctl_play; 244 ctl = priv->ctl_play;
247 value = ctl & ~(KIRKWOOD_PLAYCTL_I2S_EN | 245 value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
248 KIRKWOOD_PLAYCTL_SPDIF_EN);
249 writel(value, priv->io + KIRKWOOD_PLAYCTL); 246 writel(value, priv->io + KIRKWOOD_PLAYCTL);
250 247
251 /* enable interrupts */ 248 /* enable interrupts */
@@ -267,7 +264,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
267 writel(value, priv->io + KIRKWOOD_INT_MASK); 264 writel(value, priv->io + KIRKWOOD_INT_MASK);
268 265
269 /* disable all playbacks */ 266 /* disable all playbacks */
270 ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN); 267 ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
271 writel(ctl, priv->io + KIRKWOOD_PLAYCTL); 268 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
272 break; 269 break;
273 270
@@ -387,7 +384,7 @@ static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
387 384
388 /* disable playback/record */ 385 /* disable playback/record */
389 value = readl(priv->io + KIRKWOOD_PLAYCTL); 386 value = readl(priv->io + KIRKWOOD_PLAYCTL);
390 value &= ~(KIRKWOOD_PLAYCTL_I2S_EN|KIRKWOOD_PLAYCTL_SPDIF_EN); 387 value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
391 writel(value, priv->io + KIRKWOOD_PLAYCTL); 388 writel(value, priv->io + KIRKWOOD_PLAYCTL);
392 389
393 value = readl(priv->io + KIRKWOOD_RECCTL); 390 value = readl(priv->io + KIRKWOOD_RECCTL);
@@ -398,11 +395,6 @@ static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
398 395
399} 396}
400 397
401static int kirkwood_i2s_remove(struct snd_soc_dai *dai)
402{
403 return 0;
404}
405
406static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { 398static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
407 .startup = kirkwood_i2s_startup, 399 .startup = kirkwood_i2s_startup,
408 .trigger = kirkwood_i2s_trigger, 400 .trigger = kirkwood_i2s_trigger,
@@ -413,17 +405,18 @@ static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
413 405
414static struct snd_soc_dai_driver kirkwood_i2s_dai = { 406static struct snd_soc_dai_driver kirkwood_i2s_dai = {
415 .probe = kirkwood_i2s_probe, 407 .probe = kirkwood_i2s_probe,
416 .remove = kirkwood_i2s_remove,
417 .playback = { 408 .playback = {
418 .channels_min = 1, 409 .channels_min = 1,
419 .channels_max = 2, 410 .channels_max = 2,
420 .rates = KIRKWOOD_I2S_RATES, 411 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
412 SNDRV_PCM_RATE_96000,
421 .formats = KIRKWOOD_I2S_FORMATS, 413 .formats = KIRKWOOD_I2S_FORMATS,
422 }, 414 },
423 .capture = { 415 .capture = {
424 .channels_min = 1, 416 .channels_min = 1,
425 .channels_max = 2, 417 .channels_max = 2,
426 .rates = KIRKWOOD_I2S_RATES, 418 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
419 SNDRV_PCM_RATE_96000,
427 .formats = KIRKWOOD_I2S_FORMATS, 420 .formats = KIRKWOOD_I2S_FORMATS,
428 }, 421 },
429 .ops = &kirkwood_i2s_dai_ops, 422 .ops = &kirkwood_i2s_dai_ops,
@@ -431,7 +424,6 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai = {
431 424
432static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = { 425static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
433 .probe = kirkwood_i2s_probe, 426 .probe = kirkwood_i2s_probe,
434 .remove = kirkwood_i2s_remove,
435 .playback = { 427 .playback = {
436 .channels_min = 1, 428 .channels_min = 1,
437 .channels_max = 2, 429 .channels_max = 2,
@@ -498,10 +490,10 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
498 if (err < 0) 490 if (err < 0)
499 return err; 491 return err;
500 492
501 priv->extclk = clk_get(&pdev->dev, "extclk"); 493 priv->extclk = devm_clk_get(&pdev->dev, "extclk");
502 if (!IS_ERR(priv->extclk)) { 494 if (!IS_ERR(priv->extclk)) {
503 if (priv->extclk == priv->clk) { 495 if (priv->extclk == priv->clk) {
504 clk_put(priv->extclk); 496 devm_clk_put(&pdev->dev, priv->extclk);
505 priv->extclk = ERR_PTR(-EINVAL); 497 priv->extclk = ERR_PTR(-EINVAL);
506 } else { 498 } else {
507 dev_info(&pdev->dev, "found external clock\n"); 499 dev_info(&pdev->dev, "found external clock\n");
@@ -525,14 +517,22 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
525 517
526 err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component, 518 err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
527 soc_dai, 1); 519 soc_dai, 1);
528 if (!err) 520 if (err) {
529 return 0; 521 dev_err(&pdev->dev, "snd_soc_register_component failed\n");
530 dev_err(&pdev->dev, "snd_soc_register_component failed\n"); 522 goto err_component;
523 }
531 524
532 if (!IS_ERR(priv->extclk)) { 525 err = snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
533 clk_disable_unprepare(priv->extclk); 526 if (err) {
534 clk_put(priv->extclk); 527 dev_err(&pdev->dev, "snd_soc_register_platform failed\n");
528 goto err_platform;
535 } 529 }
530 return 0;
531 err_platform:
532 snd_soc_unregister_component(&pdev->dev);
533 err_component:
534 if (!IS_ERR(priv->extclk))
535 clk_disable_unprepare(priv->extclk);
536 clk_disable_unprepare(priv->clk); 536 clk_disable_unprepare(priv->clk);
537 537
538 return err; 538 return err;
@@ -542,12 +542,11 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
542{ 542{
543 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); 543 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
544 544
545 snd_soc_unregister_platform(&pdev->dev);
545 snd_soc_unregister_component(&pdev->dev); 546 snd_soc_unregister_component(&pdev->dev);
546 547
547 if (!IS_ERR(priv->extclk)) { 548 if (!IS_ERR(priv->extclk))
548 clk_disable_unprepare(priv->extclk); 549 clk_disable_unprepare(priv->extclk);
549 clk_put(priv->extclk);
550 }
551 clk_disable_unprepare(priv->clk); 550 clk_disable_unprepare(priv->clk);
552 551
553 return 0; 552 return 0;
@@ -568,4 +567,4 @@ module_platform_driver(kirkwood_i2s_driver);
568MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>"); 567MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
569MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); 568MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
570MODULE_LICENSE("GPL"); 569MODULE_LICENSE("GPL");
571MODULE_ALIAS("platform:kirkwood-i2s"); 570MODULE_ALIAS("platform:mvebu-audio");
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index b979c7154715..025be0e97164 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -16,9 +16,7 @@
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <sound/soc.h> 18#include <sound/soc.h>
19#include <mach/kirkwood.h>
20#include <linux/platform_data/asoc-kirkwood.h> 19#include <linux/platform_data/asoc-kirkwood.h>
21#include <asm/mach-types.h>
22#include "../codecs/cs42l51.h" 20#include "../codecs/cs42l51.h"
23 21
24static int openrd_client_hw_params(struct snd_pcm_substream *substream, 22static int openrd_client_hw_params(struct snd_pcm_substream *substream,
@@ -54,8 +52,8 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
54{ 52{
55 .name = "CS42L51", 53 .name = "CS42L51",
56 .stream_name = "CS42L51 HiFi", 54 .stream_name = "CS42L51 HiFi",
57 .cpu_dai_name = "kirkwood-i2s", 55 .cpu_dai_name = "mvebu-audio",
58 .platform_name = "kirkwood-pcm-audio", 56 .platform_name = "mvebu-audio",
59 .codec_dai_name = "cs42l51-hifi", 57 .codec_dai_name = "cs42l51-hifi",
60 .codec_name = "cs42l51-codec.0-004a", 58 .codec_name = "cs42l51-codec.0-004a",
61 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, 59 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index 1d0ed6f8add7..27545b0c4856 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -15,9 +15,7 @@
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <sound/soc.h> 17#include <sound/soc.h>
18#include <mach/kirkwood.h>
19#include <linux/platform_data/asoc-kirkwood.h> 18#include <linux/platform_data/asoc-kirkwood.h>
20#include <asm/mach-types.h>
21#include "../codecs/alc5623.h" 19#include "../codecs/alc5623.h"
22 20
23static int t5325_hw_params(struct snd_pcm_substream *substream, 21static int t5325_hw_params(struct snd_pcm_substream *substream,
@@ -70,8 +68,8 @@ static struct snd_soc_dai_link t5325_dai[] = {
70{ 68{
71 .name = "ALC5621", 69 .name = "ALC5621",
72 .stream_name = "ALC5621 HiFi", 70 .stream_name = "ALC5621 HiFi",
73 .cpu_dai_name = "kirkwood-i2s", 71 .cpu_dai_name = "mvebu-audio",
74 .platform_name = "kirkwood-pcm-audio", 72 .platform_name = "mvebu-audio",
75 .codec_dai_name = "alc5621-hifi", 73 .codec_dai_name = "alc5621-hifi",
76 .codec_name = "alc562x-codec.0-001a", 74 .codec_name = "alc562x-codec.0-001a",
77 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, 75 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h
index 4d92637ddb3f..f8e1ccc1c58c 100644
--- a/sound/soc/kirkwood/kirkwood.h
+++ b/sound/soc/kirkwood/kirkwood.h
@@ -54,7 +54,7 @@
54#define KIRKWOOD_PLAYCTL_MONO_OFF (0<<5) 54#define KIRKWOOD_PLAYCTL_MONO_OFF (0<<5)
55#define KIRKWOOD_PLAYCTL_I2S_MUTE (1<<7) 55#define KIRKWOOD_PLAYCTL_I2S_MUTE (1<<7)
56#define KIRKWOOD_PLAYCTL_SPDIF_EN (1<<4) 56#define KIRKWOOD_PLAYCTL_SPDIF_EN (1<<4)
57#define KIRKWOOD_PLAYCTL_I2S_EN (1<<3) 57#define KIRKWOOD_PLAYCTL_I2S_EN (1<<3)
58#define KIRKWOOD_PLAYCTL_SIZE_MASK (7<<0) 58#define KIRKWOOD_PLAYCTL_SIZE_MASK (7<<0)
59#define KIRKWOOD_PLAYCTL_SIZE_16 (7<<0) 59#define KIRKWOOD_PLAYCTL_SIZE_16 (7<<0)
60#define KIRKWOOD_PLAYCTL_SIZE_16_C (3<<0) 60#define KIRKWOOD_PLAYCTL_SIZE_16_C (3<<0)
@@ -62,6 +62,9 @@
62#define KIRKWOOD_PLAYCTL_SIZE_24 (1<<0) 62#define KIRKWOOD_PLAYCTL_SIZE_24 (1<<0)
63#define KIRKWOOD_PLAYCTL_SIZE_32 (0<<0) 63#define KIRKWOOD_PLAYCTL_SIZE_32 (0<<0)
64 64
65#define KIRKWOOD_PLAYCTL_ENABLE_MASK (KIRKWOOD_PLAYCTL_SPDIF_EN | \
66 KIRKWOOD_PLAYCTL_I2S_EN)
67
65#define KIRKWOOD_PLAY_BUF_ADDR 0x1104 68#define KIRKWOOD_PLAY_BUF_ADDR 0x1104
66#define KIRKWOOD_PLAY_BUF_SIZE 0x1108 69#define KIRKWOOD_PLAY_BUF_SIZE 0x1108
67#define KIRKWOOD_PLAY_BYTE_COUNT 0x110C 70#define KIRKWOOD_PLAY_BYTE_COUNT 0x110C
@@ -122,6 +125,8 @@
122#define KIRKWOOD_SND_MAX_PERIODS 16 125#define KIRKWOOD_SND_MAX_PERIODS 16
123#define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x4000 126#define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x4000
124#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000 127#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000
128#define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \
129 * KIRKWOOD_SND_MAX_PERIODS)
125 130
126struct kirkwood_dma_data { 131struct kirkwood_dma_data {
127 void __iomem *io; 132 void __iomem *io;
@@ -129,8 +134,12 @@ struct kirkwood_dma_data {
129 struct clk *extclk; 134 struct clk *extclk;
130 uint32_t ctl_play; 135 uint32_t ctl_play;
131 uint32_t ctl_rec; 136 uint32_t ctl_rec;
137 struct snd_pcm_substream *substream_play;
138 struct snd_pcm_substream *substream_rec;
132 int irq; 139 int irq;
133 int burst; 140 int burst;
134}; 141};
135 142
143extern struct snd_soc_platform_driver kirkwood_soc_platform;
144
136#endif 145#endif
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
index 78d321cbe8b4..219235c02212 100644
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -1,6 +1,7 @@
1menuconfig SND_MXS_SOC 1menuconfig SND_MXS_SOC
2 tristate "SoC Audio for Freescale MXS CPUs" 2 tristate "SoC Audio for Freescale MXS CPUs"
3 depends on ARCH_MXS 3 depends on ARCH_MXS || COMPILE_TEST
4 depends on COMMON_CLK
4 select SND_SOC_GENERIC_DMAENGINE_PCM 5 select SND_SOC_GENERIC_DMAENGINE_PCM
5 help 6 help
6 Say Y or M if you want to add support for codecs attached to 7 Say Y or M if you want to add support for codecs attached to
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 54511c5e6a7c..b56b8a0e8deb 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -31,7 +31,6 @@
31#include <sound/pcm.h> 31#include <sound/pcm.h>
32#include <sound/pcm_params.h> 32#include <sound/pcm_params.h>
33#include <sound/soc.h> 33#include <sound/soc.h>
34#include <asm/mach-types.h>
35 34
36#include "mxs-saif.h" 35#include "mxs-saif.h"
37 36
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 1b134d72f120..ce084eb10c49 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -25,7 +25,6 @@
25#include <sound/soc.h> 25#include <sound/soc.h>
26#include <sound/jack.h> 26#include <sound/jack.h>
27#include <sound/soc-dapm.h> 27#include <sound/soc-dapm.h>
28#include <asm/mach-types.h>
29 28
30#include "../codecs/sgtl5000.h" 29#include "../codecs/sgtl5000.h"
31#include "mxs-saif.h" 30#include "mxs-saif.h"
@@ -51,18 +50,27 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream,
51 } 50 }
52 51
53 /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */ 52 /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */
54 if (mclk < 8000000 || mclk > 27000000) 53 if (mclk < 8000000 || mclk > 27000000) {
54 dev_err(codec_dai->dev, "Invalid mclk frequency: %u.%03uMHz\n",
55 mclk / 1000000, mclk / 1000 % 1000);
55 return -EINVAL; 56 return -EINVAL;
57 }
56 58
57 /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */ 59 /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */
58 ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0); 60 ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0);
59 if (ret) 61 if (ret) {
62 dev_err(codec_dai->dev, "Failed to set sysclk to %u.%03uMHz\n",
63 mclk / 1000000, mclk / 1000 % 1000);
60 return ret; 64 return ret;
65 }
61 66
62 /* The SAIF MCLK should be the same as SGTL5000_SYSCLK */ 67 /* The SAIF MCLK should be the same as SGTL5000_SYSCLK */
63 ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0); 68 ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0);
64 if (ret) 69 if (ret) {
70 dev_err(cpu_dai->dev, "Failed to set sysclk to %u.%03uMHz\n",
71 mclk / 1000000, mclk / 1000 % 1000);
65 return ret; 72 return ret;
73 }
66 74
67 /* set codec to slave mode */ 75 /* set codec to slave mode */
68 dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 76 dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
@@ -70,13 +78,19 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream,
70 78
71 /* set codec DAI configuration */ 79 /* set codec DAI configuration */
72 ret = snd_soc_dai_set_fmt(codec_dai, dai_format); 80 ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
73 if (ret) 81 if (ret) {
82 dev_err(codec_dai->dev, "Failed to set dai format to %08x\n",
83 dai_format);
74 return ret; 84 return ret;
85 }
75 86
76 /* set cpu DAI configuration */ 87 /* set cpu DAI configuration */
77 ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); 88 ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
78 if (ret) 89 if (ret) {
90 dev_err(cpu_dai->dev, "Failed to set dai format to %08x\n",
91 dai_format);
79 return ret; 92 return ret;
93 }
80 94
81 return 0; 95 return 0;
82} 96}
@@ -154,8 +168,10 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev)
154 * should be >= 8MHz and <= 27M. 168 * should be >= 8MHz and <= 27M.
155 */ 169 */
156 ret = mxs_saif_get_mclk(0, 44100 * 256, 44100); 170 ret = mxs_saif_get_mclk(0, 44100 * 256, 44100);
157 if (ret) 171 if (ret) {
172 dev_err(&pdev->dev, "failed to get mclk\n");
158 return ret; 173 return ret;
174 }
159 175
160 card->dev = &pdev->dev; 176 card->dev = &pdev->dev;
161 platform_set_drvdata(pdev, card); 177 platform_set_drvdata(pdev, card);
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index f4c2417a8730..8987bf987e58 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -333,9 +333,6 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev)
333 spin_lock_init(&nuc900_audio->lock); 333 spin_lock_init(&nuc900_audio->lock);
334 334
335 nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 335 nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
336 if (!nuc900_audio->res)
337 return ret;
338
339 nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev, 336 nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev,
340 nuc900_audio->res); 337 nuc900_audio->res);
341 if (IS_ERR(nuc900_audio->mmio)) 338 if (IS_ERR(nuc900_audio->mmio))
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 9f5d55e6b17a..daa78a0095fa 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -1,7 +1,7 @@
1config SND_OMAP_SOC 1config SND_OMAP_SOC
2 tristate "SoC Audio for the Texas Instruments OMAP chips" 2 tristate "SoC Audio for the Texas Instruments OMAP chips"
3 depends on ARCH_OMAP && DMA_OMAP 3 depends on (ARCH_OMAP && DMA_OMAP) || (ARCH_ARM && COMPILE_TEST)
4 select SND_SOC_DMAENGINE_PCM 4 select SND_DMAENGINE_PCM
5 5
6config SND_OMAP_SOC_DMIC 6config SND_OMAP_SOC_DMIC
7 tristate 7 tristate
@@ -26,7 +26,7 @@ config SND_OMAP_SOC_N810
26 26
27config SND_OMAP_SOC_RX51 27config SND_OMAP_SOC_RX51
28 tristate "SoC Audio support for Nokia RX-51" 28 tristate "SoC Audio support for Nokia RX-51"
29 depends on SND_OMAP_SOC && MACH_NOKIA_RX51 29 depends on SND_OMAP_SOC && ARCH_ARM && (MACH_NOKIA_RX51 || COMPILE_TEST)
30 select SND_OMAP_SOC_MCBSP 30 select SND_OMAP_SOC_MCBSP
31 select SND_SOC_TLV320AIC3X 31 select SND_SOC_TLV320AIC3X
32 select SND_SOC_TPA6130A2 32 select SND_SOC_TPA6130A2
@@ -87,7 +87,7 @@ config SND_OMAP_SOC_OMAP_TWL4030
87 87
88config SND_OMAP_SOC_OMAP_ABE_TWL6040 88config SND_OMAP_SOC_OMAP_ABE_TWL6040
89 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" 89 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
90 depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 90 depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || COMPILE_TEST)
91 select SND_OMAP_SOC_DMIC 91 select SND_OMAP_SOC_DMIC
92 select SND_OMAP_SOC_MCPDM 92 select SND_OMAP_SOC_MCPDM
93 select SND_SOC_TWL6040 93 select SND_SOC_TWL6040
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index 70cd5c7b2e14..ebb13906b3a0 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -23,7 +23,6 @@
23#include <linux/clk.h> 23#include <linux/clk.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/mfd/twl6040.h> 25#include <linux/mfd/twl6040.h>
26#include <linux/platform_data/omap-abe-twl6040.h>
27#include <linux/module.h> 26#include <linux/module.h>
28#include <linux/of.h> 27#include <linux/of.h>
29 28
@@ -166,19 +165,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
166 {"AFMR", NULL, "Line In"}, 165 {"AFMR", NULL, "Line In"},
167}; 166};
168 167
169static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm,
170 int connected, char *pin)
171{
172 if (!connected)
173 snd_soc_dapm_disable_pin(dapm, pin);
174}
175
176static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) 168static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
177{ 169{
178 struct snd_soc_codec *codec = rtd->codec; 170 struct snd_soc_codec *codec = rtd->codec;
179 struct snd_soc_card *card = codec->card; 171 struct snd_soc_card *card = codec->card;
180 struct snd_soc_dapm_context *dapm = &codec->dapm;
181 struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
182 struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); 172 struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
183 int hs_trim; 173 int hs_trim;
184 int ret = 0; 174 int ret = 0;
@@ -203,24 +193,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
203 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); 193 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
204 } 194 }
205 195
206 /*
207 * NULL pdata means we booted with DT. In this case the routing is
208 * provided and the card is fully routed, no need to mark pins.
209 */
210 if (!pdata)
211 return ret;
212
213 /* Disable not connected paths if not used */
214 twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
215 twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
216 twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
217 twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
218 twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator");
219 twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
220 twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
221 twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
222 twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
223
224 return ret; 196 return ret;
225} 197}
226 198
@@ -274,13 +246,18 @@ static struct snd_soc_card omap_abe_card = {
274 246
275static int omap_abe_probe(struct platform_device *pdev) 247static int omap_abe_probe(struct platform_device *pdev)
276{ 248{
277 struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
278 struct device_node *node = pdev->dev.of_node; 249 struct device_node *node = pdev->dev.of_node;
279 struct snd_soc_card *card = &omap_abe_card; 250 struct snd_soc_card *card = &omap_abe_card;
251 struct device_node *dai_node;
280 struct abe_twl6040 *priv; 252 struct abe_twl6040 *priv;
281 int num_links = 0; 253 int num_links = 0;
282 int ret = 0; 254 int ret = 0;
283 255
256 if (!node) {
257 dev_err(&pdev->dev, "of node is missing.\n");
258 return -ENODEV;
259 }
260
284 card->dev = &pdev->dev; 261 card->dev = &pdev->dev;
285 262
286 priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); 263 priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL);
@@ -289,78 +266,50 @@ static int omap_abe_probe(struct platform_device *pdev)
289 266
290 priv->dmic_codec_dev = ERR_PTR(-EINVAL); 267 priv->dmic_codec_dev = ERR_PTR(-EINVAL);
291 268
292 if (node) { 269 if (snd_soc_of_parse_card_name(card, "ti,model")) {
293 struct device_node *dai_node; 270 dev_err(&pdev->dev, "Card name is not provided\n");
294 271 return -ENODEV;
295 if (snd_soc_of_parse_card_name(card, "ti,model")) { 272 }
296 dev_err(&pdev->dev, "Card name is not provided\n");
297 return -ENODEV;
298 }
299 273
300 ret = snd_soc_of_parse_audio_routing(card, 274 ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing");
301 "ti,audio-routing"); 275 if (ret) {
302 if (ret) { 276 dev_err(&pdev->dev, "Error while parsing DAPM routing\n");
303 dev_err(&pdev->dev, 277 return ret;
304 "Error while parsing DAPM routing\n"); 278 }
305 return ret;
306 }
307 279
308 dai_node = of_parse_phandle(node, "ti,mcpdm", 0); 280 dai_node = of_parse_phandle(node, "ti,mcpdm", 0);
309 if (!dai_node) { 281 if (!dai_node) {
310 dev_err(&pdev->dev, "McPDM node is not provided\n"); 282 dev_err(&pdev->dev, "McPDM node is not provided\n");
311 return -EINVAL; 283 return -EINVAL;
312 } 284 }
313 abe_twl6040_dai_links[0].cpu_dai_name = NULL; 285 abe_twl6040_dai_links[0].cpu_dai_name = NULL;
314 abe_twl6040_dai_links[0].cpu_of_node = dai_node; 286 abe_twl6040_dai_links[0].cpu_of_node = dai_node;
315 287
316 dai_node = of_parse_phandle(node, "ti,dmic", 0); 288 dai_node = of_parse_phandle(node, "ti,dmic", 0);
317 if (dai_node) { 289 if (dai_node) {
318 num_links = 2; 290 num_links = 2;
319 abe_twl6040_dai_links[1].cpu_dai_name = NULL; 291 abe_twl6040_dai_links[1].cpu_dai_name = NULL;
320 abe_twl6040_dai_links[1].cpu_of_node = dai_node; 292 abe_twl6040_dai_links[1].cpu_of_node = dai_node;
321 293
322 priv->dmic_codec_dev = platform_device_register_simple( 294 priv->dmic_codec_dev = platform_device_register_simple(
323 "dmic-codec", -1, NULL, 0); 295 "dmic-codec", -1, NULL, 0);
324 if (IS_ERR(priv->dmic_codec_dev)) { 296 if (IS_ERR(priv->dmic_codec_dev)) {
325 dev_err(&pdev->dev, 297 dev_err(&pdev->dev, "Can't instantiate dmic-codec\n");
326 "Can't instantiate dmic-codec\n"); 298 return PTR_ERR(priv->dmic_codec_dev);
327 return PTR_ERR(priv->dmic_codec_dev);
328 }
329 } else {
330 num_links = 1;
331 }
332
333 priv->jack_detection = of_property_read_bool(node,
334 "ti,jack-detection");
335 of_property_read_u32(node, "ti,mclk-freq",
336 &priv->mclk_freq);
337 if (!priv->mclk_freq) {
338 dev_err(&pdev->dev, "MCLK frequency not provided\n");
339 ret = -EINVAL;
340 goto err_unregister;
341 } 299 }
342
343 omap_abe_card.fully_routed = 1;
344 } else if (pdata) {
345 if (pdata->card_name) {
346 card->name = pdata->card_name;
347 } else {
348 dev_err(&pdev->dev, "Card name is not provided\n");
349 return -ENODEV;
350 }
351
352 if (pdata->has_dmic)
353 num_links = 2;
354 else
355 num_links = 1;
356
357 priv->jack_detection = pdata->jack_detection;
358 priv->mclk_freq = pdata->mclk_freq;
359 } else { 300 } else {
360 dev_err(&pdev->dev, "Missing pdata\n"); 301 num_links = 1;
361 return -ENODEV; 302 }
303
304 priv->jack_detection = of_property_read_bool(node, "ti,jack-detection");
305 of_property_read_u32(node, "ti,mclk-freq", &priv->mclk_freq);
306 if (!priv->mclk_freq) {
307 dev_err(&pdev->dev, "MCLK frequency not provided\n");
308 ret = -EINVAL;
309 goto err_unregister;
362 } 310 }
363 311
312 card->fully_routed = 1;
364 313
365 if (!priv->mclk_freq) { 314 if (!priv->mclk_freq) {
366 dev_err(&pdev->dev, "MCLK frequency missing\n"); 315 dev_err(&pdev->dev, "MCLK frequency missing\n");
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 4db1f8e6e172..12e566be3793 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -480,15 +480,12 @@ static int asoc_dmic_probe(struct platform_device *pdev)
480 dmic->dma_data.filter_data = "up_link"; 480 dmic->dma_data.filter_data = "up_link";
481 481
482 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); 482 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
483 if (!res) { 483 dmic->io_base = devm_ioremap_resource(&pdev->dev, res);
484 dev_err(dmic->dev, "invalid memory resource\n"); 484 if (IS_ERR(dmic->io_base)) {
485 ret = -ENODEV; 485 ret = PTR_ERR(dmic->io_base);
486 goto err_put_clk; 486 goto err_put_clk;
487 } 487 }
488 488
489 dmic->io_base = devm_ioremap_resource(&pdev->dev, res);
490 if (IS_ERR(dmic->io_base))
491 return PTR_ERR(dmic->io_base);
492 489
493 ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component, 490 ret = snd_soc_register_component(&pdev->dev, &omap_dmic_component,
494 &omap_dmic_dai, 1); 491 &omap_dmic_dai, 1);
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 7483efb6dc67..6c19bba23570 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -433,6 +433,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
433 /* Sample rate generator drives the FS */ 433 /* Sample rate generator drives the FS */
434 regs->srgr2 |= FSGM; 434 regs->srgr2 |= FSGM;
435 break; 435 break;
436 case SND_SOC_DAIFMT_CBM_CFS:
437 /* McBSP slave. FS clock as output */
438 regs->srgr2 |= FSGM;
439 regs->pcr0 |= FSXM;
440 break;
436 case SND_SOC_DAIFMT_CBM_CFM: 441 case SND_SOC_DAIFMT_CBM_CFM:
437 /* McBSP slave */ 442 /* McBSP slave */
438 break; 443 break;
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index a49dc52f8abc..90d2a7cd2563 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -480,9 +480,6 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
480 mcpdm->dma_data[1].filter_data = "up_link"; 480 mcpdm->dma_data[1].filter_data = "up_link";
481 481
482 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); 482 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
483 if (res == NULL)
484 return -ENOMEM;
485
486 mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res); 483 mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res);
487 if (IS_ERR(mcpdm->io_base)) 484 if (IS_ERR(mcpdm->io_base))
488 return PTR_ERR(mcpdm->io_base); 485 return PTR_ERR(mcpdm->io_base);
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index b35809467547..4db74a083db1 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -11,7 +11,7 @@ config SND_PXA2XX_SOC
11config SND_MMP_SOC 11config SND_MMP_SOC
12 bool "Soc Audio for Marvell MMP chips" 12 bool "Soc Audio for Marvell MMP chips"
13 depends on ARCH_MMP 13 depends on ARCH_MMP
14 select SND_SOC_DMAENGINE_PCM 14 select SND_DMAENGINE_PCM
15 select SND_ARM 15 select SND_ARM
16 help 16 help
17 Say Y if you want to add support for codecs attached to 17 Say Y if you want to add support for codecs attached to
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
index 4ad76099dd43..5b7d969f89a9 100644
--- a/sound/soc/pxa/brownstone.c
+++ b/sound/soc/pxa/brownstone.c
@@ -129,6 +129,7 @@ static struct snd_soc_dai_link brownstone_wm8994_dai[] = {
129/* audio machine driver */ 129/* audio machine driver */
130static struct snd_soc_card brownstone = { 130static struct snd_soc_card brownstone = {
131 .name = "brownstone", 131 .name = "brownstone",
132 .owner = THIS_MODULE,
132 .dai_link = brownstone_wm8994_dai, 133 .dai_link = brownstone_wm8994_dai,
133 .num_links = ARRAY_SIZE(brownstone_wm8994_dai), 134 .num_links = ARRAY_SIZE(brownstone_wm8994_dai),
134 135
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 97b711e12821..bbea7780eac6 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -56,8 +56,6 @@
56#include "pxa2xx-ac97.h" 56#include "pxa2xx-ac97.h"
57#include "../codecs/wm9713.h" 57#include "../codecs/wm9713.h"
58 58
59#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
60
61#define AC97_GPIO_PULL 0x58 59#define AC97_GPIO_PULL 0x58
62 60
63/* Use GPIO8 for rear speaker amplifier */ 61/* Use GPIO8 for rear speaker amplifier */
@@ -133,10 +131,11 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)
133 unsigned short reg; 131 unsigned short reg;
134 132
135 /* Add mioa701 specific widgets */ 133 /* Add mioa701 specific widgets */
136 snd_soc_dapm_new_controls(dapm, ARRAY_AND_SIZE(mioa701_dapm_widgets)); 134 snd_soc_dapm_new_controls(dapm, mioa701_dapm_widgets,
135 ARRAY_SIZE(mioa701_dapm_widgets));
137 136
138 /* Set up mioa701 specific audio path audio_mapnects */ 137 /* Set up mioa701 specific audio path audio_mapnects */
139 snd_soc_dapm_add_routes(dapm, ARRAY_AND_SIZE(audio_map)); 138 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
140 139
141 /* Prepare GPIO8 for rear speaker amplifier */ 140 /* Prepare GPIO8 for rear speaker amplifier */
142 reg = codec->driver->read(codec, AC97_GPIO_CFG); 141 reg = codec->driver->read(codec, AC97_GPIO_CFG);
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 5d57e071cdf5..8235e231d89c 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -17,6 +17,7 @@
17#include <linux/dmaengine.h> 17#include <linux/dmaengine.h>
18#include <linux/platform_data/dma-mmp_tdma.h> 18#include <linux/platform_data/dma-mmp_tdma.h>
19#include <linux/platform_data/mmp_audio.h> 19#include <linux/platform_data/mmp_audio.h>
20
20#include <sound/pxa2xx-lib.h> 21#include <sound/pxa2xx-lib.h>
21#include <sound/core.h> 22#include <sound/core.h>
22#include <sound/pcm.h> 23#include <sound/pcm.h>
@@ -67,7 +68,7 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream,
67{ 68{
68 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); 69 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
69 struct snd_soc_pcm_runtime *rtd = substream->private_data; 70 struct snd_soc_pcm_runtime *rtd = substream->private_data;
70 struct pxa2xx_pcm_dma_params *dma_params; 71 struct snd_dmaengine_dai_dma_data *dma_params;
71 struct dma_slave_config slave_config; 72 struct dma_slave_config slave_config;
72 int ret; 73 int ret;
73 74
@@ -80,10 +81,10 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream,
80 return ret; 81 return ret;
81 82
82 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 83 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
83 slave_config.dst_addr = dma_params->dev_addr; 84 slave_config.dst_addr = dma_params->addr;
84 slave_config.dst_maxburst = 4; 85 slave_config.dst_maxburst = 4;
85 } else { 86 } else {
86 slave_config.src_addr = dma_params->dev_addr; 87 slave_config.src_addr = dma_params->addr;
87 slave_config.src_maxburst = 4; 88 slave_config.src_maxburst = 4;
88 } 89 }
89 90
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 62142ce367c7..41752a5fe3b0 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -27,12 +27,15 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/pxa2xx_ssp.h> 28#include <linux/pxa2xx_ssp.h>
29#include <linux/io.h> 29#include <linux/io.h>
30#include <linux/dmaengine.h>
31
30#include <sound/core.h> 32#include <sound/core.h>
31#include <sound/pcm.h> 33#include <sound/pcm.h>
32#include <sound/initval.h> 34#include <sound/initval.h>
33#include <sound/pcm_params.h> 35#include <sound/pcm_params.h>
34#include <sound/soc.h> 36#include <sound/soc.h>
35#include <sound/pxa2xx-lib.h> 37#include <sound/pxa2xx-lib.h>
38#include <sound/dmaengine_pcm.h>
36#include "mmp-sspa.h" 39#include "mmp-sspa.h"
37 40
38/* 41/*
@@ -40,7 +43,7 @@
40 */ 43 */
41struct sspa_priv { 44struct sspa_priv {
42 struct ssp_device *sspa; 45 struct ssp_device *sspa;
43 struct pxa2xx_pcm_dma_params *dma_params; 46 struct snd_dmaengine_dai_dma_data *dma_params;
44 struct clk *audio_clk; 47 struct clk *audio_clk;
45 struct clk *sysclk; 48 struct clk *sysclk;
46 int dai_fmt; 49 int dai_fmt;
@@ -266,7 +269,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,
266 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 269 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
267 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); 270 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
268 struct ssp_device *sspa = sspa_priv->sspa; 271 struct ssp_device *sspa = sspa_priv->sspa;
269 struct pxa2xx_pcm_dma_params *dma_params; 272 struct snd_dmaengine_dai_dma_data *dma_params;
270 u32 sspa_ctrl; 273 u32 sspa_ctrl;
271 274
272 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 275 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -309,7 +312,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,
309 } 312 }
310 313
311 dma_params = &sspa_priv->dma_params[substream->stream]; 314 dma_params = &sspa_priv->dma_params[substream->stream];
312 dma_params->dev_addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 315 dma_params->addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
313 (sspa->phys_base + SSPA_TXD) : 316 (sspa->phys_base + SSPA_TXD) :
314 (sspa->phys_base + SSPA_RXD); 317 (sspa->phys_base + SSPA_RXD);
315 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params); 318 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params);
@@ -425,14 +428,12 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev)
425 return -ENOMEM; 428 return -ENOMEM;
426 429
427 priv->dma_params = devm_kzalloc(&pdev->dev, 430 priv->dma_params = devm_kzalloc(&pdev->dev,
428 2 * sizeof(struct pxa2xx_pcm_dma_params), GFP_KERNEL); 431 2 * sizeof(struct snd_dmaengine_dai_dma_data),
432 GFP_KERNEL);
429 if (priv->dma_params == NULL) 433 if (priv->dma_params == NULL)
430 return -ENOMEM; 434 return -ENOMEM;
431 435
432 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 436 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
433 if (res == NULL)
434 return -ENOMEM;
435
436 priv->sspa->mmio_base = devm_ioremap_resource(&pdev->dev, res); 437 priv->sspa->mmio_base = devm_ioremap_resource(&pdev->dev, res);
437 if (IS_ERR(priv->sspa->mmio_base)) 438 if (IS_ERR(priv->sspa->mmio_base))
438 return PTR_ERR(priv->sspa->mmio_base); 439 return PTR_ERR(priv->sspa->mmio_base);
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 6f4dd7543e82..a3119a00d8fa 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -21,6 +21,8 @@
21#include <linux/clk.h> 21#include <linux/clk.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/pxa2xx_ssp.h> 23#include <linux/pxa2xx_ssp.h>
24#include <linux/of.h>
25#include <linux/dmaengine.h>
24 26
25#include <asm/irq.h> 27#include <asm/irq.h>
26 28
@@ -30,9 +32,9 @@
30#include <sound/pcm_params.h> 32#include <sound/pcm_params.h>
31#include <sound/soc.h> 33#include <sound/soc.h>
32#include <sound/pxa2xx-lib.h> 34#include <sound/pxa2xx-lib.h>
35#include <sound/dmaengine_pcm.h>
33 36
34#include <mach/hardware.h> 37#include <mach/hardware.h>
35#include <mach/dma.h>
36 38
37#include "../../arm/pxa2xx-pcm.h" 39#include "../../arm/pxa2xx-pcm.h"
38#include "pxa-ssp.h" 40#include "pxa-ssp.h"
@@ -79,27 +81,13 @@ static void pxa_ssp_disable(struct ssp_device *ssp)
79 __raw_writel(sscr0, ssp->mmio_base + SSCR0); 81 __raw_writel(sscr0, ssp->mmio_base + SSCR0);
80} 82}
81 83
82struct pxa2xx_pcm_dma_data {
83 struct pxa2xx_pcm_dma_params params;
84 char name[20];
85};
86
87static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4, 84static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4,
88 int out, struct pxa2xx_pcm_dma_params *dma_data) 85 int out, struct snd_dmaengine_dai_dma_data *dma)
89{ 86{
90 struct pxa2xx_pcm_dma_data *dma; 87 dma->addr_width = width4 ? DMA_SLAVE_BUSWIDTH_4_BYTES :
91 88 DMA_SLAVE_BUSWIDTH_2_BYTES;
92 dma = container_of(dma_data, struct pxa2xx_pcm_dma_data, params); 89 dma->maxburst = 16;
93 90 dma->addr = ssp->phys_base + SSDR;
94 snprintf(dma->name, 20, "SSP%d PCM %s %s", ssp->port_id,
95 width4 ? "32-bit" : "16-bit", out ? "out" : "in");
96
97 dma->params.name = dma->name;
98 dma->params.drcmr = &DRCMR(out ? ssp->drcmr_tx : ssp->drcmr_rx);
99 dma->params.dcmd = (out ? (DCMD_INCSRCADDR | DCMD_FLOWTRG) :
100 (DCMD_INCTRGADDR | DCMD_FLOWSRC)) |
101 (width4 ? DCMD_WIDTH4 : DCMD_WIDTH2) | DCMD_BURST16;
102 dma->params.dev_addr = ssp->phys_base + SSDR;
103} 91}
104 92
105static int pxa_ssp_startup(struct snd_pcm_substream *substream, 93static int pxa_ssp_startup(struct snd_pcm_substream *substream,
@@ -107,7 +95,7 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
107{ 95{
108 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); 96 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
109 struct ssp_device *ssp = priv->ssp; 97 struct ssp_device *ssp = priv->ssp;
110 struct pxa2xx_pcm_dma_data *dma; 98 struct snd_dmaengine_dai_dma_data *dma;
111 int ret = 0; 99 int ret = 0;
112 100
113 if (!cpu_dai->active) { 101 if (!cpu_dai->active) {
@@ -115,10 +103,14 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
115 pxa_ssp_disable(ssp); 103 pxa_ssp_disable(ssp);
116 } 104 }
117 105
118 dma = kzalloc(sizeof(struct pxa2xx_pcm_dma_data), GFP_KERNEL); 106 dma = kzalloc(sizeof(struct snd_dmaengine_dai_dma_data), GFP_KERNEL);
119 if (!dma) 107 if (!dma)
120 return -ENOMEM; 108 return -ENOMEM;
121 snd_soc_dai_set_dma_data(cpu_dai, substream, &dma->params); 109
110 dma->filter_data = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
111 &ssp->drcmr_tx : &ssp->drcmr_rx;
112
113 snd_soc_dai_set_dma_data(cpu_dai, substream, dma);
122 114
123 return ret; 115 return ret;
124} 116}
@@ -559,7 +551,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
559 u32 sspsp; 551 u32 sspsp;
560 int width = snd_pcm_format_physical_width(params_format(params)); 552 int width = snd_pcm_format_physical_width(params_format(params));
561 int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; 553 int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf;
562 struct pxa2xx_pcm_dma_params *dma_data; 554 struct snd_dmaengine_dai_dma_data *dma_data;
563 555
564 dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); 556 dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
565 557
@@ -719,6 +711,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
719 711
720static int pxa_ssp_probe(struct snd_soc_dai *dai) 712static int pxa_ssp_probe(struct snd_soc_dai *dai)
721{ 713{
714 struct device *dev = dai->dev;
722 struct ssp_priv *priv; 715 struct ssp_priv *priv;
723 int ret; 716 int ret;
724 717
@@ -726,10 +719,26 @@ static int pxa_ssp_probe(struct snd_soc_dai *dai)
726 if (!priv) 719 if (!priv)
727 return -ENOMEM; 720 return -ENOMEM;
728 721
729 priv->ssp = pxa_ssp_request(dai->id + 1, "SoC audio"); 722 if (dev->of_node) {
730 if (priv->ssp == NULL) { 723 struct device_node *ssp_handle;
731 ret = -ENODEV; 724
732 goto err_priv; 725 ssp_handle = of_parse_phandle(dev->of_node, "port", 0);
726 if (!ssp_handle) {
727 dev_err(dev, "unable to get 'port' phandle\n");
728 return -ENODEV;
729 }
730
731 priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio");
732 if (priv->ssp == NULL) {
733 ret = -ENODEV;
734 goto err_priv;
735 }
736 } else {
737 priv->ssp = pxa_ssp_request(dai->id + 1, "SoC audio");
738 if (priv->ssp == NULL) {
739 ret = -ENODEV;
740 goto err_priv;
741 }
733 } 742 }
734 743
735 priv->dai_fmt = (unsigned int) -1; 744 priv->dai_fmt = (unsigned int) -1;
@@ -798,6 +807,12 @@ static const struct snd_soc_component_driver pxa_ssp_component = {
798 .name = "pxa-ssp", 807 .name = "pxa-ssp",
799}; 808};
800 809
810#ifdef CONFIG_OF
811static const struct of_device_id pxa_ssp_of_ids[] = {
812 { .compatible = "mrvl,pxa-ssp-dai" },
813};
814#endif
815
801static int asoc_ssp_probe(struct platform_device *pdev) 816static int asoc_ssp_probe(struct platform_device *pdev)
802{ 817{
803 return snd_soc_register_component(&pdev->dev, &pxa_ssp_component, 818 return snd_soc_register_component(&pdev->dev, &pxa_ssp_component,
@@ -812,8 +827,9 @@ static int asoc_ssp_remove(struct platform_device *pdev)
812 827
813static struct platform_driver asoc_ssp_driver = { 828static struct platform_driver asoc_ssp_driver = {
814 .driver = { 829 .driver = {
815 .name = "pxa-ssp-dai", 830 .name = "pxa-ssp-dai",
816 .owner = THIS_MODULE, 831 .owner = THIS_MODULE,
832 .of_match_table = of_match_ptr(pxa_ssp_of_ids),
817 }, 833 },
818 834
819 .probe = asoc_ssp_probe, 835 .probe = asoc_ssp_probe,
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 1475515712e6..f1059d999de6 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -14,15 +14,16 @@
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/dmaengine.h>
17 18
18#include <sound/core.h> 19#include <sound/core.h>
19#include <sound/ac97_codec.h> 20#include <sound/ac97_codec.h>
20#include <sound/soc.h> 21#include <sound/soc.h>
21#include <sound/pxa2xx-lib.h> 22#include <sound/pxa2xx-lib.h>
23#include <sound/dmaengine_pcm.h>
22 24
23#include <mach/hardware.h> 25#include <mach/hardware.h>
24#include <mach/regs-ac97.h> 26#include <mach/regs-ac97.h>
25#include <mach/dma.h>
26#include <mach/audio.h> 27#include <mach/audio.h>
27 28
28#include "pxa2xx-ac97.h" 29#include "pxa2xx-ac97.h"
@@ -48,44 +49,44 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
48 .reset = pxa2xx_ac97_cold_reset, 49 .reset = pxa2xx_ac97_cold_reset,
49}; 50};
50 51
51static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { 52static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 12;
52 .name = "AC97 PCM Stereo out", 53static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = {
53 .dev_addr = __PREG(PCDR), 54 .addr = __PREG(PCDR),
54 .drcmr = &DRCMR(12), 55 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
55 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 56 .maxburst = 32,
56 DCMD_BURST32 | DCMD_WIDTH4, 57 .filter_data = &pxa2xx_ac97_pcm_stereo_in_req,
57}; 58};
58 59
59static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = { 60static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 11;
60 .name = "AC97 PCM Stereo in", 61static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = {
61 .dev_addr = __PREG(PCDR), 62 .addr = __PREG(PCDR),
62 .drcmr = &DRCMR(11), 63 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
63 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 64 .maxburst = 32,
64 DCMD_BURST32 | DCMD_WIDTH4, 65 .filter_data = &pxa2xx_ac97_pcm_stereo_out_req,
65}; 66};
66 67
67static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = { 68static unsigned long pxa2xx_ac97_pcm_aux_mono_out_req = 10;
68 .name = "AC97 Aux PCM (Slot 5) Mono out", 69static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_out = {
69 .dev_addr = __PREG(MODR), 70 .addr = __PREG(MODR),
70 .drcmr = &DRCMR(10), 71 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES,
71 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 72 .maxburst = 16,
72 DCMD_BURST16 | DCMD_WIDTH2, 73 .filter_data = &pxa2xx_ac97_pcm_aux_mono_out_req,
73}; 74};
74 75
75static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = { 76static unsigned long pxa2xx_ac97_pcm_aux_mono_in_req = 9;
76 .name = "AC97 Aux PCM (Slot 5) Mono in", 77static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_in = {
77 .dev_addr = __PREG(MODR), 78 .addr = __PREG(MODR),
78 .drcmr = &DRCMR(9), 79 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES,
79 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 80 .maxburst = 16,
80 DCMD_BURST16 | DCMD_WIDTH2, 81 .filter_data = &pxa2xx_ac97_pcm_aux_mono_in_req,
81}; 82};
82 83
83static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = { 84static unsigned long pxa2xx_ac97_pcm_aux_mic_mono_req = 8;
84 .name = "AC97 Mic PCM (Slot 6) Mono in", 85static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = {
85 .dev_addr = __PREG(MCDR), 86 .addr = __PREG(MCDR),
86 .drcmr = &DRCMR(8), 87 .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES,
87 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 88 .maxburst = 16,
88 DCMD_BURST16 | DCMD_WIDTH2, 89 .filter_data = &pxa2xx_ac97_pcm_aux_mic_mono_req,
89}; 90};
90 91
91#ifdef CONFIG_PM 92#ifdef CONFIG_PM
@@ -119,7 +120,7 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
119 struct snd_pcm_hw_params *params, 120 struct snd_pcm_hw_params *params,
120 struct snd_soc_dai *cpu_dai) 121 struct snd_soc_dai *cpu_dai)
121{ 122{
122 struct pxa2xx_pcm_dma_params *dma_data; 123 struct snd_dmaengine_dai_dma_data *dma_data;
123 124
124 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 125 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
125 dma_data = &pxa2xx_ac97_pcm_stereo_out; 126 dma_data = &pxa2xx_ac97_pcm_stereo_out;
@@ -135,7 +136,7 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
135 struct snd_pcm_hw_params *params, 136 struct snd_pcm_hw_params *params,
136 struct snd_soc_dai *cpu_dai) 137 struct snd_soc_dai *cpu_dai)
137{ 138{
138 struct pxa2xx_pcm_dma_params *dma_data; 139 struct snd_dmaengine_dai_dma_data *dma_data;
139 140
140 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 141 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
141 dma_data = &pxa2xx_ac97_pcm_aux_mono_out; 142 dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index f7ca71664112..d5340a088858 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -23,9 +23,9 @@
23#include <sound/initval.h> 23#include <sound/initval.h>
24#include <sound/soc.h> 24#include <sound/soc.h>
25#include <sound/pxa2xx-lib.h> 25#include <sound/pxa2xx-lib.h>
26#include <sound/dmaengine_pcm.h>
26 27
27#include <mach/hardware.h> 28#include <mach/hardware.h>
28#include <mach/dma.h>
29#include <mach/audio.h> 29#include <mach/audio.h>
30 30
31#include "pxa2xx-i2s.h" 31#include "pxa2xx-i2s.h"
@@ -82,20 +82,20 @@ static struct pxa_i2s_port pxa_i2s;
82static struct clk *clk_i2s; 82static struct clk *clk_i2s;
83static int clk_ena = 0; 83static int clk_ena = 0;
84 84
85static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { 85static unsigned long pxa2xx_i2s_pcm_stereo_out_req = 3;
86 .name = "I2S PCM Stereo out", 86static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_out = {
87 .dev_addr = __PREG(SADR), 87 .addr = __PREG(SADR),
88 .drcmr = &DRCMR(3), 88 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
89 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 89 .maxburst = 32,
90 DCMD_BURST32 | DCMD_WIDTH4, 90 .filter_data = &pxa2xx_i2s_pcm_stereo_out_req,
91}; 91};
92 92
93static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { 93static unsigned long pxa2xx_i2s_pcm_stereo_in_req = 2;
94 .name = "I2S PCM Stereo in", 94static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_in = {
95 .dev_addr = __PREG(SADR), 95 .addr = __PREG(SADR),
96 .drcmr = &DRCMR(2), 96 .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
97 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 97 .maxburst = 32,
98 DCMD_BURST32 | DCMD_WIDTH4, 98 .filter_data = &pxa2xx_i2s_pcm_stereo_in_req,
99}; 99};
100 100
101static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, 101static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
@@ -163,7 +163,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
163 struct snd_pcm_hw_params *params, 163 struct snd_pcm_hw_params *params,
164 struct snd_soc_dai *dai) 164 struct snd_soc_dai *dai)
165{ 165{
166 struct pxa2xx_pcm_dma_params *dma_data; 166 struct snd_dmaengine_dai_dma_data *dma_data;
167 167
168 BUG_ON(IS_ERR(clk_i2s)); 168 BUG_ON(IS_ERR(clk_i2s));
169 clk_prepare_enable(clk_i2s); 169 clk_prepare_enable(clk_i2s);
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index ecff116cb7b0..806da27b8b67 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -12,10 +12,13 @@
12 12
13#include <linux/dma-mapping.h> 13#include <linux/dma-mapping.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/dmaengine.h>
16#include <linux/of.h>
15 17
16#include <sound/core.h> 18#include <sound/core.h>
17#include <sound/soc.h> 19#include <sound/soc.h>
18#include <sound/pxa2xx-lib.h> 20#include <sound/pxa2xx-lib.h>
21#include <sound/dmaengine_pcm.h>
19 22
20#include "../../arm/pxa2xx-pcm.h" 23#include "../../arm/pxa2xx-pcm.h"
21 24
@@ -25,7 +28,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
25 struct snd_pcm_runtime *runtime = substream->runtime; 28 struct snd_pcm_runtime *runtime = substream->runtime;
26 struct pxa2xx_runtime_data *prtd = runtime->private_data; 29 struct pxa2xx_runtime_data *prtd = runtime->private_data;
27 struct snd_soc_pcm_runtime *rtd = substream->private_data; 30 struct snd_soc_pcm_runtime *rtd = substream->private_data;
28 struct pxa2xx_pcm_dma_params *dma; 31 struct snd_dmaengine_dai_dma_data *dma;
29 int ret; 32 int ret;
30 33
31 dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 34 dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
@@ -39,7 +42,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
39 * with different params */ 42 * with different params */
40 if (prtd->params == NULL) { 43 if (prtd->params == NULL) {
41 prtd->params = dma; 44 prtd->params = dma;
42 ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW, 45 ret = pxa_request_dma("name", DMA_PRIO_LOW,
43 pxa2xx_pcm_dma_irq, substream); 46 pxa2xx_pcm_dma_irq, substream);
44 if (ret < 0) 47 if (ret < 0)
45 return ret; 48 return ret;
@@ -47,7 +50,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
47 } else if (prtd->params != dma) { 50 } else if (prtd->params != dma) {
48 pxa_free_dma(prtd->dma_ch); 51 pxa_free_dma(prtd->dma_ch);
49 prtd->params = dma; 52 prtd->params = dma;
50 ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW, 53 ret = pxa_request_dma("name", DMA_PRIO_LOW,
51 pxa2xx_pcm_dma_irq, substream); 54 pxa2xx_pcm_dma_irq, substream);
52 if (ret < 0) 55 if (ret < 0)
53 return ret; 56 return ret;
@@ -131,10 +134,18 @@ static int pxa2xx_soc_platform_remove(struct platform_device *pdev)
131 return 0; 134 return 0;
132} 135}
133 136
137#ifdef CONFIG_OF
138static const struct of_device_id snd_soc_pxa_audio_match[] = {
139 { .compatible = "mrvl,pxa-pcm-audio" },
140 { }
141};
142#endif
143
134static struct platform_driver pxa_pcm_driver = { 144static struct platform_driver pxa_pcm_driver = {
135 .driver = { 145 .driver = {
136 .name = "pxa-pcm-audio", 146 .name = "pxa-pcm-audio",
137 .owner = THIS_MODULE, 147 .owner = THIS_MODULE,
148 .of_match_table = of_match_ptr(snd_soc_pxa_audio_match),
138 }, 149 },
139 150
140 .probe = pxa2xx_soc_platform_probe, 151 .probe = pxa2xx_soc_platform_probe,
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c
index f4ea4f6663a2..13c9ee0cb83b 100644
--- a/sound/soc/pxa/ttc-dkb.c
+++ b/sound/soc/pxa/ttc-dkb.c
@@ -122,6 +122,7 @@ static struct snd_soc_dai_link ttc_pm860x_hifi_dai[] = {
122/* ttc/td audio machine driver */ 122/* ttc/td audio machine driver */
123static struct snd_soc_card ttc_dkb_card = { 123static struct snd_soc_card ttc_dkb_card = {
124 .name = "ttc-dkb-hifi", 124 .name = "ttc-dkb-hifi",
125 .owner = THIS_MODULE,
125 .dai_link = ttc_pm860x_hifi_dai, 126 .dai_link = ttc_pm860x_hifi_dai,
126 .num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai), 127 .num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai),
127 128
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
index 58cfb1eb7dd3..945e8abdc10f 100644
--- a/sound/soc/s6000/s6105-ipcam.c
+++ b/sound/soc/s6000/s6105-ipcam.c
@@ -192,7 +192,7 @@ static struct snd_soc_card snd_soc_card_s6105 = {
192 .num_links = 1, 192 .num_links = 1,
193}; 193};
194 194
195static struct s6000_snd_platform_data __initdata s6105_snd_data = { 195static struct s6000_snd_platform_data s6105_snd_data __initdata = {
196 .wide = 0, 196 .wide = 0,
197 .channel_in = 0, 197 .channel_in = 0,
198 .channel_out = 1, 198 .channel_out = 1,
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 2dd623fa3882..2acf987844e8 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -404,18 +404,13 @@ static int s3c_ac97_probe(struct platform_device *pdev)
404 return -ENXIO; 404 return -ENXIO;
405 } 405 }
406 406
407 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
408 if (!mem_res) {
409 dev_err(&pdev->dev, "Unable to get register resource\n");
410 return -ENXIO;
411 }
412
413 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 407 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
414 if (!irq_res) { 408 if (!irq_res) {
415 dev_err(&pdev->dev, "AC97 IRQ not provided!\n"); 409 dev_err(&pdev->dev, "AC97 IRQ not provided!\n");
416 return -ENXIO; 410 return -ENXIO;
417 } 411 }
418 412
413 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
419 s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); 414 s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res);
420 if (IS_ERR(s3c_ac97.regs)) 415 if (IS_ERR(s3c_ac97.regs))
421 return PTR_ERR(s3c_ac97.regs); 416 return PTR_ERR(s3c_ac97.regs);
@@ -462,7 +457,7 @@ static int s3c_ac97_probe(struct platform_device *pdev)
462 if (ret) 457 if (ret)
463 goto err5; 458 goto err5;
464 459
465 ret = asoc_dma_platform_register(&pdev->dev); 460 ret = samsung_asoc_dma_platform_register(&pdev->dev);
466 if (ret) { 461 if (ret) {
467 dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); 462 dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
468 goto err6; 463 goto err6;
@@ -485,7 +480,7 @@ static int s3c_ac97_remove(struct platform_device *pdev)
485{ 480{
486 struct resource *irq_res; 481 struct resource *irq_res;
487 482
488 asoc_dma_platform_unregister(&pdev->dev); 483 samsung_asoc_dma_platform_unregister(&pdev->dev);
489 snd_soc_unregister_component(&pdev->dev); 484 snd_soc_unregister_component(&pdev->dev);
490 485
491 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 486 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 21b79262010e..a0c67f60f594 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -176,6 +176,10 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
176 prtd->params->ch = prtd->params->ops->request( 176 prtd->params->ch = prtd->params->ops->request(
177 prtd->params->channel, &req, rtd->cpu_dai->dev, 177 prtd->params->channel, &req, rtd->cpu_dai->dev,
178 prtd->params->ch_name); 178 prtd->params->ch_name);
179 if (!prtd->params->ch) {
180 pr_err("Failed to allocate DMA channel\n");
181 return -ENXIO;
182 }
179 prtd->params->ops->config(prtd->params->ch, &config); 183 prtd->params->ops->config(prtd->params->ch, &config);
180 } 184 }
181 185
@@ -433,17 +437,17 @@ static struct snd_soc_platform_driver samsung_asoc_platform = {
433 .pcm_free = dma_free_dma_buffers, 437 .pcm_free = dma_free_dma_buffers,
434}; 438};
435 439
436int asoc_dma_platform_register(struct device *dev) 440int samsung_asoc_dma_platform_register(struct device *dev)
437{ 441{
438 return snd_soc_register_platform(dev, &samsung_asoc_platform); 442 return snd_soc_register_platform(dev, &samsung_asoc_platform);
439} 443}
440EXPORT_SYMBOL_GPL(asoc_dma_platform_register); 444EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register);
441 445
442void asoc_dma_platform_unregister(struct device *dev) 446void samsung_asoc_dma_platform_unregister(struct device *dev)
443{ 447{
444 snd_soc_unregister_platform(dev); 448 snd_soc_unregister_platform(dev);
445} 449}
446EXPORT_SYMBOL_GPL(asoc_dma_platform_unregister); 450EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister);
447 451
448MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 452MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
449MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); 453MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 189a7a6d5020..0e86315a3eaf 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -22,7 +22,7 @@ struct s3c_dma_params {
22 char *ch_name; 22 char *ch_name;
23}; 23};
24 24
25int asoc_dma_platform_register(struct device *dev); 25int samsung_asoc_dma_platform_register(struct device *dev);
26void asoc_dma_platform_unregister(struct device *dev); 26void samsung_asoc_dma_platform_unregister(struct device *dev);
27 27
28#endif 28#endif
diff --git a/sound/soc/samsung/i2s-regs.h b/sound/soc/samsung/i2s-regs.h
index c0e6d9a19efc..821a50231002 100644
--- a/sound/soc/samsung/i2s-regs.h
+++ b/sound/soc/samsung/i2s-regs.h
@@ -31,6 +31,10 @@
31#define I2SLVL1ADDR 0x34 31#define I2SLVL1ADDR 0x34
32#define I2SLVL2ADDR 0x38 32#define I2SLVL2ADDR 0x38
33#define I2SLVL3ADDR 0x3c 33#define I2SLVL3ADDR 0x3c
34#define I2SSTR1 0x40
35#define I2SVER 0x44
36#define I2SFIC2 0x48
37#define I2STDM 0x4c
34 38
35#define CON_RSTCLR (1 << 31) 39#define CON_RSTCLR (1 << 31)
36#define CON_FRXOFSTATUS (1 << 26) 40#define CON_FRXOFSTATUS (1 << 26)
@@ -95,24 +99,39 @@
95#define MOD_RXONLY (1 << 8) 99#define MOD_RXONLY (1 << 8)
96#define MOD_TXRX (2 << 8) 100#define MOD_TXRX (2 << 8)
97#define MOD_MASK (3 << 8) 101#define MOD_MASK (3 << 8)
98#define MOD_LR_LLOW (0 << 7) 102#define MOD_LRP_SHIFT 7
99#define MOD_LR_RLOW (1 << 7) 103#define MOD_LR_LLOW 0
100#define MOD_SDF_IIS (0 << 5) 104#define MOD_LR_RLOW 1
101#define MOD_SDF_MSB (1 << 5) 105#define MOD_SDF_SHIFT 5
102#define MOD_SDF_LSB (2 << 5) 106#define MOD_SDF_IIS 0
103#define MOD_SDF_MASK (3 << 5) 107#define MOD_SDF_MSB 1
104#define MOD_RCLK_256FS (0 << 3) 108#define MOD_SDF_LSB 2
105#define MOD_RCLK_512FS (1 << 3) 109#define MOD_SDF_MASK 3
106#define MOD_RCLK_384FS (2 << 3) 110#define MOD_RCLK_SHIFT 3
107#define MOD_RCLK_768FS (3 << 3) 111#define MOD_RCLK_256FS 0
108#define MOD_RCLK_MASK (3 << 3) 112#define MOD_RCLK_512FS 1
109#define MOD_BCLK_32FS (0 << 1) 113#define MOD_RCLK_384FS 2
110#define MOD_BCLK_48FS (1 << 1) 114#define MOD_RCLK_768FS 3
111#define MOD_BCLK_16FS (2 << 1) 115#define MOD_RCLK_MASK 3
112#define MOD_BCLK_24FS (3 << 1) 116#define MOD_BCLK_SHIFT 1
113#define MOD_BCLK_MASK (3 << 1) 117#define MOD_BCLK_32FS 0
118#define MOD_BCLK_48FS 1
119#define MOD_BCLK_16FS 2
120#define MOD_BCLK_24FS 3
121#define MOD_BCLK_MASK 3
114#define MOD_8BIT (1 << 0) 122#define MOD_8BIT (1 << 0)
115 123
124#define EXYNOS5420_MOD_LRP_SHIFT 15
125#define EXYNOS5420_MOD_SDF_SHIFT 6
126#define EXYNOS5420_MOD_RCLK_SHIFT 4
127#define EXYNOS5420_MOD_BCLK_SHIFT 0
128#define EXYNOS5420_MOD_BCLK_64FS 4
129#define EXYNOS5420_MOD_BCLK_96FS 5
130#define EXYNOS5420_MOD_BCLK_128FS 6
131#define EXYNOS5420_MOD_BCLK_192FS 7
132#define EXYNOS5420_MOD_BCLK_256FS 8
133#define EXYNOS5420_MOD_BCLK_MASK 0xf
134
116#define MOD_CDCLKCON (1 << 12) 135#define MOD_CDCLKCON (1 << 12)
117 136
118#define PSR_PSREN (1 << 15) 137#define PSR_PSREN (1 << 15)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 959c702235c8..b302f3b7a587 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -40,6 +40,7 @@ enum samsung_dai_type {
40 40
41struct samsung_i2s_dai_data { 41struct samsung_i2s_dai_data {
42 int dai_type; 42 int dai_type;
43 u32 quirks;
43}; 44};
44 45
45struct i2s_dai { 46struct i2s_dai {
@@ -198,7 +199,13 @@ static inline bool is_manager(struct i2s_dai *i2s)
198/* Read RCLK of I2S (in multiples of LRCLK) */ 199/* Read RCLK of I2S (in multiples of LRCLK) */
199static inline unsigned get_rfs(struct i2s_dai *i2s) 200static inline unsigned get_rfs(struct i2s_dai *i2s)
200{ 201{
201 u32 rfs = (readl(i2s->addr + I2SMOD) >> 3) & 0x3; 202 u32 rfs;
203
204 if (i2s->quirks & QUIRK_SUPPORTS_TDM)
205 rfs = readl(i2s->addr + I2SMOD) >> EXYNOS5420_MOD_RCLK_SHIFT;
206 else
207 rfs = (readl(i2s->addr + I2SMOD) >> MOD_RCLK_SHIFT);
208 rfs &= MOD_RCLK_MASK;
202 209
203 switch (rfs) { 210 switch (rfs) {
204 case 3: return 768; 211 case 3: return 768;
@@ -212,21 +219,26 @@ static inline unsigned get_rfs(struct i2s_dai *i2s)
212static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) 219static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
213{ 220{
214 u32 mod = readl(i2s->addr + I2SMOD); 221 u32 mod = readl(i2s->addr + I2SMOD);
222 int rfs_shift;
215 223
216 mod &= ~MOD_RCLK_MASK; 224 if (i2s->quirks & QUIRK_SUPPORTS_TDM)
225 rfs_shift = EXYNOS5420_MOD_RCLK_SHIFT;
226 else
227 rfs_shift = MOD_RCLK_SHIFT;
228 mod &= ~(MOD_RCLK_MASK << rfs_shift);
217 229
218 switch (rfs) { 230 switch (rfs) {
219 case 768: 231 case 768:
220 mod |= MOD_RCLK_768FS; 232 mod |= (MOD_RCLK_768FS << rfs_shift);
221 break; 233 break;
222 case 512: 234 case 512:
223 mod |= MOD_RCLK_512FS; 235 mod |= (MOD_RCLK_512FS << rfs_shift);
224 break; 236 break;
225 case 384: 237 case 384:
226 mod |= MOD_RCLK_384FS; 238 mod |= (MOD_RCLK_384FS << rfs_shift);
227 break; 239 break;
228 default: 240 default:
229 mod |= MOD_RCLK_256FS; 241 mod |= (MOD_RCLK_256FS << rfs_shift);
230 break; 242 break;
231 } 243 }
232 244
@@ -236,9 +248,22 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
236/* Read Bit-Clock of I2S (in multiples of LRCLK) */ 248/* Read Bit-Clock of I2S (in multiples of LRCLK) */
237static inline unsigned get_bfs(struct i2s_dai *i2s) 249static inline unsigned get_bfs(struct i2s_dai *i2s)
238{ 250{
239 u32 bfs = (readl(i2s->addr + I2SMOD) >> 1) & 0x3; 251 u32 bfs;
252
253 if (i2s->quirks & QUIRK_SUPPORTS_TDM) {
254 bfs = readl(i2s->addr + I2SMOD) >> EXYNOS5420_MOD_BCLK_SHIFT;
255 bfs &= EXYNOS5420_MOD_BCLK_MASK;
256 } else {
257 bfs = readl(i2s->addr + I2SMOD) >> MOD_BCLK_SHIFT;
258 bfs &= MOD_BCLK_MASK;
259 }
240 260
241 switch (bfs) { 261 switch (bfs) {
262 case 8: return 256;
263 case 7: return 192;
264 case 6: return 128;
265 case 5: return 96;
266 case 4: return 64;
242 case 3: return 24; 267 case 3: return 24;
243 case 2: return 16; 268 case 2: return 16;
244 case 1: return 48; 269 case 1: return 48;
@@ -250,21 +275,50 @@ static inline unsigned get_bfs(struct i2s_dai *i2s)
250static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) 275static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs)
251{ 276{
252 u32 mod = readl(i2s->addr + I2SMOD); 277 u32 mod = readl(i2s->addr + I2SMOD);
278 int bfs_shift;
279 int tdm = i2s->quirks & QUIRK_SUPPORTS_TDM;
253 280
254 mod &= ~MOD_BCLK_MASK; 281 if (i2s->quirks & QUIRK_SUPPORTS_TDM) {
282 bfs_shift = EXYNOS5420_MOD_BCLK_SHIFT;
283 mod &= ~(EXYNOS5420_MOD_BCLK_MASK << bfs_shift);
284 } else {
285 bfs_shift = MOD_BCLK_SHIFT;
286 mod &= ~(MOD_BCLK_MASK << bfs_shift);
287 }
288
289 /* Non-TDM I2S controllers do not support BCLK > 48 * FS */
290 if (!tdm && bfs > 48) {
291 dev_err(&i2s->pdev->dev, "Unsupported BCLK divider\n");
292 return;
293 }
255 294
256 switch (bfs) { 295 switch (bfs) {
257 case 48: 296 case 48:
258 mod |= MOD_BCLK_48FS; 297 mod |= (MOD_BCLK_48FS << bfs_shift);
259 break; 298 break;
260 case 32: 299 case 32:
261 mod |= MOD_BCLK_32FS; 300 mod |= (MOD_BCLK_32FS << bfs_shift);
262 break; 301 break;
263 case 24: 302 case 24:
264 mod |= MOD_BCLK_24FS; 303 mod |= (MOD_BCLK_24FS << bfs_shift);
265 break; 304 break;
266 case 16: 305 case 16:
267 mod |= MOD_BCLK_16FS; 306 mod |= (MOD_BCLK_16FS << bfs_shift);
307 break;
308 case 64:
309 mod |= (EXYNOS5420_MOD_BCLK_64FS << bfs_shift);
310 break;
311 case 96:
312 mod |= (EXYNOS5420_MOD_BCLK_96FS << bfs_shift);
313 break;
314 case 128:
315 mod |= (EXYNOS5420_MOD_BCLK_128FS << bfs_shift);
316 break;
317 case 192:
318 mod |= (EXYNOS5420_MOD_BCLK_192FS << bfs_shift);
319 break;
320 case 256:
321 mod |= (EXYNOS5420_MOD_BCLK_256FS << bfs_shift);
268 break; 322 break;
269 default: 323 default:
270 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); 324 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n");
@@ -491,20 +545,32 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
491{ 545{
492 struct i2s_dai *i2s = to_info(dai); 546 struct i2s_dai *i2s = to_info(dai);
493 u32 mod = readl(i2s->addr + I2SMOD); 547 u32 mod = readl(i2s->addr + I2SMOD);
548 int lrp_shift, sdf_shift, sdf_mask, lrp_rlow;
494 u32 tmp = 0; 549 u32 tmp = 0;
495 550
551 if (i2s->quirks & QUIRK_SUPPORTS_TDM) {
552 lrp_shift = EXYNOS5420_MOD_LRP_SHIFT;
553 sdf_shift = EXYNOS5420_MOD_SDF_SHIFT;
554 } else {
555 lrp_shift = MOD_LRP_SHIFT;
556 sdf_shift = MOD_SDF_SHIFT;
557 }
558
559 sdf_mask = MOD_SDF_MASK << sdf_shift;
560 lrp_rlow = MOD_LR_RLOW << lrp_shift;
561
496 /* Format is priority */ 562 /* Format is priority */
497 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 563 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
498 case SND_SOC_DAIFMT_RIGHT_J: 564 case SND_SOC_DAIFMT_RIGHT_J:
499 tmp |= MOD_LR_RLOW; 565 tmp |= lrp_rlow;
500 tmp |= MOD_SDF_MSB; 566 tmp |= (MOD_SDF_MSB << sdf_shift);
501 break; 567 break;
502 case SND_SOC_DAIFMT_LEFT_J: 568 case SND_SOC_DAIFMT_LEFT_J:
503 tmp |= MOD_LR_RLOW; 569 tmp |= lrp_rlow;
504 tmp |= MOD_SDF_LSB; 570 tmp |= (MOD_SDF_LSB << sdf_shift);
505 break; 571 break;
506 case SND_SOC_DAIFMT_I2S: 572 case SND_SOC_DAIFMT_I2S:
507 tmp |= MOD_SDF_IIS; 573 tmp |= (MOD_SDF_IIS << sdf_shift);
508 break; 574 break;
509 default: 575 default:
510 dev_err(&i2s->pdev->dev, "Format not supported\n"); 576 dev_err(&i2s->pdev->dev, "Format not supported\n");
@@ -519,10 +585,10 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
519 case SND_SOC_DAIFMT_NB_NF: 585 case SND_SOC_DAIFMT_NB_NF:
520 break; 586 break;
521 case SND_SOC_DAIFMT_NB_IF: 587 case SND_SOC_DAIFMT_NB_IF:
522 if (tmp & MOD_LR_RLOW) 588 if (tmp & lrp_rlow)
523 tmp &= ~MOD_LR_RLOW; 589 tmp &= ~lrp_rlow;
524 else 590 else
525 tmp |= MOD_LR_RLOW; 591 tmp |= lrp_rlow;
526 break; 592 break;
527 default: 593 default:
528 dev_err(&i2s->pdev->dev, "Polarity not supported\n"); 594 dev_err(&i2s->pdev->dev, "Polarity not supported\n");
@@ -544,15 +610,18 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
544 return -EINVAL; 610 return -EINVAL;
545 } 611 }
546 612
613 /*
614 * Don't change the I2S mode if any controller is active on this
615 * channel.
616 */
547 if (any_active(i2s) && 617 if (any_active(i2s) &&
548 ((mod & (MOD_SDF_MASK | MOD_LR_RLOW 618 ((mod & (sdf_mask | lrp_rlow | MOD_SLAVE)) != tmp)) {
549 | MOD_SLAVE)) != tmp)) {
550 dev_err(&i2s->pdev->dev, 619 dev_err(&i2s->pdev->dev,
551 "%s:%d Other DAI busy\n", __func__, __LINE__); 620 "%s:%d Other DAI busy\n", __func__, __LINE__);
552 return -EAGAIN; 621 return -EAGAIN;
553 } 622 }
554 623
555 mod &= ~(MOD_SDF_MASK | MOD_LR_RLOW | MOD_SLAVE); 624 mod &= ~(sdf_mask | lrp_rlow | MOD_SLAVE);
556 mod |= tmp; 625 mod |= tmp;
557 writel(mod, i2s->addr + I2SMOD); 626 writel(mod, i2s->addr + I2SMOD);
558 627
@@ -1007,6 +1076,8 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
1007 if (IS_ERR(i2s->pdev)) 1076 if (IS_ERR(i2s->pdev))
1008 return NULL; 1077 return NULL;
1009 1078
1079 i2s->pdev->dev.parent = &pdev->dev;
1080
1010 platform_set_drvdata(i2s->pdev, i2s); 1081 platform_set_drvdata(i2s->pdev, i2s);
1011 ret = platform_device_add(i2s->pdev); 1082 ret = platform_device_add(i2s->pdev);
1012 if (ret < 0) 1083 if (ret < 0)
@@ -1018,18 +1089,18 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
1018 1089
1019static const struct of_device_id exynos_i2s_match[]; 1090static const struct of_device_id exynos_i2s_match[];
1020 1091
1021static inline int samsung_i2s_get_driver_data(struct platform_device *pdev) 1092static inline const struct samsung_i2s_dai_data *samsung_i2s_get_driver_data(
1093 struct platform_device *pdev)
1022{ 1094{
1023#ifdef CONFIG_OF 1095#ifdef CONFIG_OF
1024 struct samsung_i2s_dai_data *data;
1025 if (pdev->dev.of_node) { 1096 if (pdev->dev.of_node) {
1026 const struct of_device_id *match; 1097 const struct of_device_id *match;
1027 match = of_match_node(exynos_i2s_match, pdev->dev.of_node); 1098 match = of_match_node(exynos_i2s_match, pdev->dev.of_node);
1028 data = (struct samsung_i2s_dai_data *) match->data; 1099 return match->data;
1029 return data->dai_type;
1030 } else 1100 } else
1031#endif 1101#endif
1032 return platform_get_device_id(pdev)->driver_data; 1102 return (struct samsung_i2s_dai_data *)
1103 platform_get_device_id(pdev)->driver_data;
1033} 1104}
1034 1105
1035#ifdef CONFIG_PM_RUNTIME 1106#ifdef CONFIG_PM_RUNTIME
@@ -1060,13 +1131,13 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1060 struct resource *res; 1131 struct resource *res;
1061 u32 regs_base, quirks = 0, idma_addr = 0; 1132 u32 regs_base, quirks = 0, idma_addr = 0;
1062 struct device_node *np = pdev->dev.of_node; 1133 struct device_node *np = pdev->dev.of_node;
1063 enum samsung_dai_type samsung_dai_type; 1134 const struct samsung_i2s_dai_data *i2s_dai_data;
1064 int ret = 0; 1135 int ret = 0;
1065 1136
1066 /* Call during Seconday interface registration */ 1137 /* Call during Seconday interface registration */
1067 samsung_dai_type = samsung_i2s_get_driver_data(pdev); 1138 i2s_dai_data = samsung_i2s_get_driver_data(pdev);
1068 1139
1069 if (samsung_dai_type == TYPE_SEC) { 1140 if (i2s_dai_data->dai_type == TYPE_SEC) {
1070 sec_dai = dev_get_drvdata(&pdev->dev); 1141 sec_dai = dev_get_drvdata(&pdev->dev);
1071 if (!sec_dai) { 1142 if (!sec_dai) {
1072 dev_err(&pdev->dev, "Unable to get drvdata\n"); 1143 dev_err(&pdev->dev, "Unable to get drvdata\n");
@@ -1075,7 +1146,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1075 snd_soc_register_component(&sec_dai->pdev->dev, 1146 snd_soc_register_component(&sec_dai->pdev->dev,
1076 &samsung_i2s_component, 1147 &samsung_i2s_component,
1077 &sec_dai->i2s_dai_drv, 1); 1148 &sec_dai->i2s_dai_drv, 1);
1078 asoc_dma_platform_register(&pdev->dev); 1149 samsung_asoc_dma_platform_register(&pdev->dev);
1079 return 0; 1150 return 0;
1080 } 1151 }
1081 1152
@@ -1115,15 +1186,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1115 idma_addr = i2s_cfg->idma_addr; 1186 idma_addr = i2s_cfg->idma_addr;
1116 } 1187 }
1117 } else { 1188 } else {
1118 if (of_find_property(np, "samsung,supports-6ch", NULL)) 1189 quirks = i2s_dai_data->quirks;
1119 quirks |= QUIRK_PRI_6CHAN;
1120
1121 if (of_find_property(np, "samsung,supports-secdai", NULL))
1122 quirks |= QUIRK_SEC_DAI;
1123
1124 if (of_find_property(np, "samsung,supports-rstclr", NULL))
1125 quirks |= QUIRK_NEED_RSTCLR;
1126
1127 if (of_property_read_u32(np, "samsung,idma-addr", 1190 if (of_property_read_u32(np, "samsung,idma-addr",
1128 &idma_addr)) { 1191 &idma_addr)) {
1129 if (quirks & QUIRK_SEC_DAI) { 1192 if (quirks & QUIRK_SEC_DAI) {
@@ -1200,7 +1263,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1200 1263
1201 pm_runtime_enable(&pdev->dev); 1264 pm_runtime_enable(&pdev->dev);
1202 1265
1203 asoc_dma_platform_register(&pdev->dev); 1266 samsung_asoc_dma_platform_register(&pdev->dev);
1204 1267
1205 return 0; 1268 return 0;
1206err: 1269err:
@@ -1230,33 +1293,59 @@ static int samsung_i2s_remove(struct platform_device *pdev)
1230 i2s->pri_dai = NULL; 1293 i2s->pri_dai = NULL;
1231 i2s->sec_dai = NULL; 1294 i2s->sec_dai = NULL;
1232 1295
1233 asoc_dma_platform_unregister(&pdev->dev); 1296 samsung_asoc_dma_platform_unregister(&pdev->dev);
1234 snd_soc_unregister_component(&pdev->dev); 1297 snd_soc_unregister_component(&pdev->dev);
1235 1298
1236 return 0; 1299 return 0;
1237} 1300}
1238 1301
1302static const struct samsung_i2s_dai_data i2sv3_dai_type = {
1303 .dai_type = TYPE_PRI,
1304 .quirks = QUIRK_NO_MUXPSR,
1305};
1306
1307static const struct samsung_i2s_dai_data i2sv5_dai_type = {
1308 .dai_type = TYPE_PRI,
1309 .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR,
1310};
1311
1312static const struct samsung_i2s_dai_data i2sv6_dai_type = {
1313 .dai_type = TYPE_PRI,
1314 .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
1315 QUIRK_SUPPORTS_TDM,
1316};
1317
1318static const struct samsung_i2s_dai_data samsung_dai_type_pri = {
1319 .dai_type = TYPE_PRI,
1320};
1321
1322static const struct samsung_i2s_dai_data samsung_dai_type_sec = {
1323 .dai_type = TYPE_SEC,
1324};
1325
1239static struct platform_device_id samsung_i2s_driver_ids[] = { 1326static struct platform_device_id samsung_i2s_driver_ids[] = {
1240 { 1327 {
1241 .name = "samsung-i2s", 1328 .name = "samsung-i2s",
1242 .driver_data = TYPE_PRI, 1329 .driver_data = (kernel_ulong_t)&samsung_dai_type_pri,
1243 }, { 1330 }, {
1244 .name = "samsung-i2s-sec", 1331 .name = "samsung-i2s-sec",
1245 .driver_data = TYPE_SEC, 1332 .driver_data = (kernel_ulong_t)&samsung_dai_type_sec,
1246 }, 1333 },
1247 {}, 1334 {},
1248}; 1335};
1249MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids); 1336MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids);
1250 1337
1251#ifdef CONFIG_OF 1338#ifdef CONFIG_OF
1252static struct samsung_i2s_dai_data samsung_i2s_dai_data_array[] = {
1253 [TYPE_PRI] = { TYPE_PRI },
1254 [TYPE_SEC] = { TYPE_SEC },
1255};
1256
1257static const struct of_device_id exynos_i2s_match[] = { 1339static const struct of_device_id exynos_i2s_match[] = {
1258 { .compatible = "samsung,i2s-v5", 1340 {
1259 .data = &samsung_i2s_dai_data_array[TYPE_PRI], 1341 .compatible = "samsung,s3c6410-i2s",
1342 .data = &i2sv3_dai_type,
1343 }, {
1344 .compatible = "samsung,s5pv210-i2s",
1345 .data = &i2sv5_dai_type,
1346 }, {
1347 .compatible = "samsung,exynos5420-i2s",
1348 .data = &i2sv6_dai_type,
1260 }, 1349 },
1261 {}, 1350 {},
1262}; 1351};
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 1566afe9ef52..e54256fc4b2c 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -594,7 +594,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
594 goto err5; 594 goto err5;
595 } 595 }
596 596
597 ret = asoc_dma_platform_register(&pdev->dev); 597 ret = samsung_asoc_dma_platform_register(&pdev->dev);
598 if (ret) { 598 if (ret) {
599 dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); 599 dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
600 goto err6; 600 goto err6;
@@ -623,7 +623,7 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev)
623 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; 623 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
624 struct resource *mem_res; 624 struct resource *mem_res;
625 625
626 asoc_dma_platform_unregister(&pdev->dev); 626 samsung_asoc_dma_platform_unregister(&pdev->dev);
627 snd_soc_unregister_component(&pdev->dev); 627 snd_soc_unregister_component(&pdev->dev);
628 628
629 pm_runtime_disable(&pdev->dev); 629 pm_runtime_disable(&pdev->dev);
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 47e23864ea72..ea885cb9f76c 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -176,7 +176,7 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
176 return ret; 176 return ret;
177 } 177 }
178 178
179 ret = asoc_dma_platform_register(&pdev->dev); 179 ret = samsung_asoc_dma_platform_register(&pdev->dev);
180 if (ret) { 180 if (ret) {
181 pr_err("failed to register the DMA: %d\n", ret); 181 pr_err("failed to register the DMA: %d\n", ret);
182 goto err; 182 goto err;
@@ -190,7 +190,7 @@ err:
190 190
191static int s3c2412_iis_dev_remove(struct platform_device *pdev) 191static int s3c2412_iis_dev_remove(struct platform_device *pdev)
192{ 192{
193 asoc_dma_platform_unregister(&pdev->dev); 193 samsung_asoc_dma_platform_unregister(&pdev->dev);
194 snd_soc_unregister_component(&pdev->dev); 194 snd_soc_unregister_component(&pdev->dev);
195 return 0; 195 return 0;
196} 196}
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 8b3414551a62..9c8ebd872fac 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -480,7 +480,7 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
480 return ret; 480 return ret;
481 } 481 }
482 482
483 ret = asoc_dma_platform_register(&pdev->dev); 483 ret = samsung_asoc_dma_platform_register(&pdev->dev);
484 if (ret) { 484 if (ret) {
485 pr_err("failed to register the dma: %d\n", ret); 485 pr_err("failed to register the dma: %d\n", ret);
486 goto err; 486 goto err;
@@ -494,7 +494,7 @@ err:
494 494
495static int s3c24xx_iis_dev_remove(struct platform_device *pdev) 495static int s3c24xx_iis_dev_remove(struct platform_device *pdev)
496{ 496{
497 asoc_dma_platform_unregister(&pdev->dev); 497 samsung_asoc_dma_platform_unregister(&pdev->dev);
498 snd_soc_unregister_component(&pdev->dev); 498 snd_soc_unregister_component(&pdev->dev);
499 return 0; 499 return 0;
500} 500}
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 581ea4a06fc6..5fd7a05a9b9e 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -11,6 +11,7 @@
11#include <sound/pcm_params.h> 11#include <sound/pcm_params.h>
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/of.h> 13#include <linux/of.h>
14#include <linux/of_device.h>
14 15
15 /* 16 /*
16 * Default CFG switch settings to use this driver: 17 * Default CFG switch settings to use this driver:
@@ -37,11 +38,19 @@
37/* SMDK has a 16.934MHZ crystal attached to WM8994 */ 38/* SMDK has a 16.934MHZ crystal attached to WM8994 */
38#define SMDK_WM8994_FREQ 16934000 39#define SMDK_WM8994_FREQ 16934000
39 40
41struct smdk_wm8994_data {
42 int mclk1_rate;
43};
44
45/* Default SMDKs */
46static struct smdk_wm8994_data smdk_board_data = {
47 .mclk1_rate = SMDK_WM8994_FREQ,
48};
49
40static int smdk_hw_params(struct snd_pcm_substream *substream, 50static int smdk_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params) 51 struct snd_pcm_hw_params *params)
42{ 52{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data; 53 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
45 struct snd_soc_dai *codec_dai = rtd->codec_dai; 54 struct snd_soc_dai *codec_dai = rtd->codec_dai;
46 unsigned int pll_out; 55 unsigned int pll_out;
47 int ret; 56 int ret;
@@ -54,18 +63,6 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
54 else 63 else
55 pll_out = params_rate(params) * 256; 64 pll_out = params_rate(params) * 256;
56 65
57 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
58 | SND_SOC_DAIFMT_NB_NF
59 | SND_SOC_DAIFMT_CBM_CFM);
60 if (ret < 0)
61 return ret;
62
63 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
64 | SND_SOC_DAIFMT_NB_NF
65 | SND_SOC_DAIFMT_CBM_CFM);
66 if (ret < 0)
67 return ret;
68
69 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, 66 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
70 SMDK_WM8994_FREQ, pll_out); 67 SMDK_WM8994_FREQ, pll_out);
71 if (ret < 0) 68 if (ret < 0)
@@ -131,6 +128,8 @@ static struct snd_soc_dai_link smdk_dai[] = {
131 .platform_name = "samsung-i2s.0", 128 .platform_name = "samsung-i2s.0",
132 .codec_name = "wm8994-codec", 129 .codec_name = "wm8994-codec",
133 .init = smdk_wm8994_init_paiftx, 130 .init = smdk_wm8994_init_paiftx,
131 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
132 SND_SOC_DAIFMT_CBM_CFM,
134 .ops = &smdk_ops, 133 .ops = &smdk_ops,
135 }, { /* Sec_Fifo Playback i/f */ 134 }, { /* Sec_Fifo Playback i/f */
136 .name = "Sec_FIFO TX", 135 .name = "Sec_FIFO TX",
@@ -139,6 +138,8 @@ static struct snd_soc_dai_link smdk_dai[] = {
139 .codec_dai_name = "wm8994-aif1", 138 .codec_dai_name = "wm8994-aif1",
140 .platform_name = "samsung-i2s-sec", 139 .platform_name = "samsung-i2s-sec",
141 .codec_name = "wm8994-codec", 140 .codec_name = "wm8994-codec",
141 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
142 SND_SOC_DAIFMT_CBM_CFM,
142 .ops = &smdk_ops, 143 .ops = &smdk_ops,
143 }, 144 },
144}; 145};
@@ -150,15 +151,28 @@ static struct snd_soc_card smdk = {
150 .num_links = ARRAY_SIZE(smdk_dai), 151 .num_links = ARRAY_SIZE(smdk_dai),
151}; 152};
152 153
154#ifdef CONFIG_OF
155static const struct of_device_id samsung_wm8994_of_match[] = {
156 { .compatible = "samsung,smdk-wm8994", .data = &smdk_board_data },
157 {},
158};
159MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match);
160#endif /* CONFIG_OF */
153 161
154static int smdk_audio_probe(struct platform_device *pdev) 162static int smdk_audio_probe(struct platform_device *pdev)
155{ 163{
156 int ret; 164 int ret;
157 struct device_node *np = pdev->dev.of_node; 165 struct device_node *np = pdev->dev.of_node;
158 struct snd_soc_card *card = &smdk; 166 struct snd_soc_card *card = &smdk;
167 struct smdk_wm8994_data *board;
168 const struct of_device_id *id;
159 169
160 card->dev = &pdev->dev; 170 card->dev = &pdev->dev;
161 171
172 board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL);
173 if (!board)
174 return -ENOMEM;
175
162 if (np) { 176 if (np) {
163 smdk_dai[0].cpu_dai_name = NULL; 177 smdk_dai[0].cpu_dai_name = NULL;
164 smdk_dai[0].cpu_of_node = of_parse_phandle(np, 178 smdk_dai[0].cpu_of_node = of_parse_phandle(np,
@@ -173,6 +187,12 @@ static int smdk_audio_probe(struct platform_device *pdev)
173 smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node; 187 smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node;
174 } 188 }
175 189
190 id = of_match_device(samsung_wm8994_of_match, &pdev->dev);
191 if (id)
192 *board = *((struct smdk_wm8994_data *)id->data);
193
194 platform_set_drvdata(pdev, board);
195
176 ret = snd_soc_register_card(card); 196 ret = snd_soc_register_card(card);
177 197
178 if (ret) 198 if (ret)
@@ -190,17 +210,9 @@ static int smdk_audio_remove(struct platform_device *pdev)
190 return 0; 210 return 0;
191} 211}
192 212
193#ifdef CONFIG_OF
194static const struct of_device_id samsung_wm8994_of_match[] = {
195 { .compatible = "samsung,smdk-wm8994", },
196 {},
197};
198MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match);
199#endif /* CONFIG_OF */
200
201static struct platform_driver smdk_audio_driver = { 213static struct platform_driver smdk_audio_driver = {
202 .driver = { 214 .driver = {
203 .name = "smdk-audio", 215 .name = "smdk-audio-wm8894",
204 .owner = THIS_MODULE, 216 .owner = THIS_MODULE,
205 .of_match_table = of_match_ptr(samsung_wm8994_of_match), 217 .of_match_table = of_match_ptr(samsung_wm8994_of_match),
206 }, 218 },
@@ -212,4 +224,4 @@ module_platform_driver(smdk_audio_driver);
212 224
213MODULE_DESCRIPTION("ALSA SoC SMDK WM8994"); 225MODULE_DESCRIPTION("ALSA SoC SMDK WM8994");
214MODULE_LICENSE("GPL"); 226MODULE_LICENSE("GPL");
215MODULE_ALIAS("platform:smdk-audio"); 227MODULE_ALIAS("platform:smdk-audio-wm8994");
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 2e5ebb2f1982..28487dcc4538 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -395,7 +395,7 @@ static int spdif_probe(struct platform_device *pdev)
395 395
396 spin_lock_init(&spdif->lock); 396 spin_lock_init(&spdif->lock);
397 397
398 spdif->pclk = clk_get(&pdev->dev, "spdif"); 398 spdif->pclk = devm_clk_get(&pdev->dev, "spdif");
399 if (IS_ERR(spdif->pclk)) { 399 if (IS_ERR(spdif->pclk)) {
400 dev_err(&pdev->dev, "failed to get peri-clock\n"); 400 dev_err(&pdev->dev, "failed to get peri-clock\n");
401 ret = -ENOENT; 401 ret = -ENOENT;
@@ -403,7 +403,7 @@ static int spdif_probe(struct platform_device *pdev)
403 } 403 }
404 clk_prepare_enable(spdif->pclk); 404 clk_prepare_enable(spdif->pclk);
405 405
406 spdif->sclk = clk_get(&pdev->dev, "sclk_spdif"); 406 spdif->sclk = devm_clk_get(&pdev->dev, "sclk_spdif");
407 if (IS_ERR(spdif->sclk)) { 407 if (IS_ERR(spdif->sclk)) {
408 dev_err(&pdev->dev, "failed to get internal source clock\n"); 408 dev_err(&pdev->dev, "failed to get internal source clock\n");
409 ret = -ENOENT; 409 ret = -ENOENT;
@@ -442,7 +442,7 @@ static int spdif_probe(struct platform_device *pdev)
442 442
443 spdif->dma_playback = &spdif_stereo_out; 443 spdif->dma_playback = &spdif_stereo_out;
444 444
445 ret = asoc_dma_platform_register(&pdev->dev); 445 ret = samsung_asoc_dma_platform_register(&pdev->dev);
446 if (ret) { 446 if (ret) {
447 dev_err(&pdev->dev, "failed to register DMA: %d\n", ret); 447 dev_err(&pdev->dev, "failed to register DMA: %d\n", ret);
448 goto err5; 448 goto err5;
@@ -457,10 +457,8 @@ err3:
457 release_mem_region(mem_res->start, resource_size(mem_res)); 457 release_mem_region(mem_res->start, resource_size(mem_res));
458err2: 458err2:
459 clk_disable_unprepare(spdif->sclk); 459 clk_disable_unprepare(spdif->sclk);
460 clk_put(spdif->sclk);
461err1: 460err1:
462 clk_disable_unprepare(spdif->pclk); 461 clk_disable_unprepare(spdif->pclk);
463 clk_put(spdif->pclk);
464err0: 462err0:
465 return ret; 463 return ret;
466} 464}
@@ -470,7 +468,7 @@ static int spdif_remove(struct platform_device *pdev)
470 struct samsung_spdif_info *spdif = &spdif_info; 468 struct samsung_spdif_info *spdif = &spdif_info;
471 struct resource *mem_res; 469 struct resource *mem_res;
472 470
473 asoc_dma_platform_unregister(&pdev->dev); 471 samsung_asoc_dma_platform_unregister(&pdev->dev);
474 snd_soc_unregister_component(&pdev->dev); 472 snd_soc_unregister_component(&pdev->dev);
475 473
476 iounmap(spdif->regs); 474 iounmap(spdif->regs);
@@ -480,9 +478,7 @@ static int spdif_remove(struct platform_device *pdev)
480 release_mem_region(mem_res->start, resource_size(mem_res)); 478 release_mem_region(mem_res->start, resource_size(mem_res));
481 479
482 clk_disable_unprepare(spdif->sclk); 480 clk_disable_unprepare(spdif->sclk);
483 clk_put(spdif->sclk);
484 clk_disable_unprepare(spdif->pclk); 481 clk_disable_unprepare(spdif->pclk);
485 clk_put(spdif->pclk);
486 482
487 return 0; 483 return 0;
488} 484}
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 6bcb1164d599..56d8ff6a402d 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -34,6 +34,13 @@ config SND_SOC_SH4_SIU
34 select SH_DMAE 34 select SH_DMAE
35 select FW_LOADER 35 select FW_LOADER
36 36
37config SND_SOC_RCAR
38 tristate "R-Car series SRU/SCU/SSIU/SSI support"
39 select SND_SIMPLE_CARD
40 select RCAR_CLK_ADG
41 help
42 This option enables R-Car SUR/SCU/SSIU/SSI sound support
43
37## 44##
38## Boards 45## Boards
39## 46##
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index 849b387d17d9..aaf3dcd1ee2a 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -12,6 +12,9 @@ obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o
12obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o 12obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o
13obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o 13obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
14 14
15## audio units for R-Car
16obj-$(CONFIG_SND_SOC_RCAR) += rcar/
17
15## boards 18## boards
16snd-soc-sh7760-ac97-objs := sh7760-ac97.o 19snd-soc-sh7760-ac97-objs := sh7760-ac97.o
17snd-soc-migor-objs := migor.o 20snd-soc-migor-objs := migor.o
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile
new file mode 100644
index 000000000000..0ff492df7929
--- /dev/null
+++ b/sound/soc/sh/rcar/Makefile
@@ -0,0 +1,2 @@
1snd-soc-rcar-objs := core.o gen.o scu.o adg.o ssi.o
2obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
new file mode 100644
index 000000000000..d80deb7ccf13
--- /dev/null
+++ b/sound/soc/sh/rcar/adg.c
@@ -0,0 +1,234 @@
1/*
2 * Helper routines for R-Car sound ADG.
3 *
4 * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/sh_clk.h>
11#include <mach/clock.h>
12#include "rsnd.h"
13
14#define CLKA 0
15#define CLKB 1
16#define CLKC 2
17#define CLKI 3
18#define CLKMAX 4
19
20struct rsnd_adg {
21 struct clk *clk[CLKMAX];
22
23 int rate_of_441khz_div_6;
24 int rate_of_48khz_div_6;
25};
26
27#define for_each_rsnd_clk(pos, adg, i) \
28 for (i = 0, (pos) = adg->clk[i]; \
29 i < CLKMAX; \
30 i++, (pos) = adg->clk[i])
31#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
32
33static enum rsnd_reg rsnd_adg_ssi_reg_get(int id)
34{
35 enum rsnd_reg reg;
36
37 /*
38 * SSI 8 is not connected to ADG.
39 * it works with SSI 7
40 */
41 if (id == 8)
42 return RSND_REG_MAX;
43
44 if (0 <= id && id <= 3)
45 reg = RSND_REG_AUDIO_CLK_SEL0;
46 else if (4 <= id && id <= 7)
47 reg = RSND_REG_AUDIO_CLK_SEL1;
48 else
49 reg = RSND_REG_AUDIO_CLK_SEL2;
50
51 return reg;
52}
53
54int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod)
55{
56 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
57 enum rsnd_reg reg;
58 int id;
59
60 /*
61 * "mod" = "ssi" here.
62 * we can get "ssi id" from mod
63 */
64 id = rsnd_mod_id(mod);
65 reg = rsnd_adg_ssi_reg_get(id);
66
67 rsnd_write(priv, mod, reg, 0);
68
69 return 0;
70}
71
72int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
73{
74 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
75 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
76 struct device *dev = rsnd_priv_to_dev(priv);
77 struct clk *clk;
78 enum rsnd_reg reg;
79 int id, shift, i;
80 u32 data;
81 int sel_table[] = {
82 [CLKA] = 0x1,
83 [CLKB] = 0x2,
84 [CLKC] = 0x3,
85 [CLKI] = 0x0,
86 };
87
88 dev_dbg(dev, "request clock = %d\n", rate);
89
90 /*
91 * find suitable clock from
92 * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
93 */
94 data = 0;
95 for_each_rsnd_clk(clk, adg, i) {
96 if (rate == clk_get_rate(clk)) {
97 data = sel_table[i];
98 goto found_clock;
99 }
100 }
101
102 /*
103 * find 1/6 clock from BRGA/BRGB
104 */
105 if (rate == adg->rate_of_441khz_div_6) {
106 data = 0x10;
107 goto found_clock;
108 }
109
110 if (rate == adg->rate_of_48khz_div_6) {
111 data = 0x20;
112 goto found_clock;
113 }
114
115 return -EIO;
116
117found_clock:
118
119 /*
120 * This "mod" = "ssi" here.
121 * we can get "ssi id" from mod
122 */
123 id = rsnd_mod_id(mod);
124 reg = rsnd_adg_ssi_reg_get(id);
125
126 dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate);
127
128 /*
129 * Enable SSIx clock
130 */
131 shift = (id % 4) * 8;
132
133 rsnd_bset(priv, mod, reg,
134 0xFF << shift,
135 data << shift);
136
137 return 0;
138}
139
140static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
141{
142 struct clk *clk;
143 unsigned long rate;
144 u32 ckr;
145 int i;
146 int brg_table[] = {
147 [CLKA] = 0x0,
148 [CLKB] = 0x1,
149 [CLKC] = 0x4,
150 [CLKI] = 0x2,
151 };
152
153 /*
154 * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
155 * have 44.1kHz or 48kHz base clocks for now.
156 *
157 * SSI itself can divide parent clock by 1/1 - 1/16
158 * So, BRGA outputs 44.1kHz base parent clock 1/32,
159 * and, BRGB outputs 48.0kHz base parent clock 1/32 here.
160 * see
161 * rsnd_adg_ssi_clk_try_start()
162 */
163 ckr = 0;
164 adg->rate_of_441khz_div_6 = 0;
165 adg->rate_of_48khz_div_6 = 0;
166 for_each_rsnd_clk(clk, adg, i) {
167 rate = clk_get_rate(clk);
168
169 if (0 == rate) /* not used */
170 continue;
171
172 /* RBGA */
173 if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) {
174 adg->rate_of_441khz_div_6 = rate / 6;
175 ckr |= brg_table[i] << 20;
176 }
177
178 /* RBGB */
179 if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) {
180 adg->rate_of_48khz_div_6 = rate / 6;
181 ckr |= brg_table[i] << 16;
182 }
183 }
184
185 rsnd_priv_bset(priv, SSICKR, 0x00FF0000, ckr);
186 rsnd_priv_write(priv, BRRA, 0x00000002); /* 1/6 */
187 rsnd_priv_write(priv, BRRB, 0x00000002); /* 1/6 */
188}
189
190int rsnd_adg_probe(struct platform_device *pdev,
191 struct rcar_snd_info *info,
192 struct rsnd_priv *priv)
193{
194 struct rsnd_adg *adg;
195 struct device *dev = rsnd_priv_to_dev(priv);
196 struct clk *clk;
197 int i;
198
199 adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
200 if (!adg) {
201 dev_err(dev, "ADG allocate failed\n");
202 return -ENOMEM;
203 }
204
205 adg->clk[CLKA] = clk_get(NULL, "audio_clk_a");
206 adg->clk[CLKB] = clk_get(NULL, "audio_clk_b");
207 adg->clk[CLKC] = clk_get(NULL, "audio_clk_c");
208 adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal");
209 for_each_rsnd_clk(clk, adg, i) {
210 if (IS_ERR(clk)) {
211 dev_err(dev, "Audio clock failed\n");
212 return -EIO;
213 }
214 }
215
216 rsnd_adg_ssi_clk_init(priv, adg);
217
218 priv->adg = adg;
219
220 dev_dbg(dev, "adg probed\n");
221
222 return 0;
223}
224
225void rsnd_adg_remove(struct platform_device *pdev,
226 struct rsnd_priv *priv)
227{
228 struct rsnd_adg *adg = priv->adg;
229 struct clk *clk;
230 int i;
231
232 for_each_rsnd_clk(clk, adg, i)
233 clk_put(clk);
234}
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
new file mode 100644
index 000000000000..a35706028514
--- /dev/null
+++ b/sound/soc/sh/rcar/core.c
@@ -0,0 +1,861 @@
1/*
2 * Renesas R-Car SRU/SCU/SSIU/SSI support
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * Based on fsi.c
8 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15/*
16 * Renesas R-Car sound device structure
17 *
18 * Gen1
19 *
20 * SRU : Sound Routing Unit
21 * - SRC : Sampling Rate Converter
22 * - CMD
23 * - CTU : Channel Count Conversion Unit
24 * - MIX : Mixer
25 * - DVC : Digital Volume and Mute Function
26 * - SSI : Serial Sound Interface
27 *
28 * Gen2
29 *
30 * SCU : Sampling Rate Converter Unit
31 * - SRC : Sampling Rate Converter
32 * - CMD
33 * - CTU : Channel Count Conversion Unit
34 * - MIX : Mixer
35 * - DVC : Digital Volume and Mute Function
36 * SSIU : Serial Sound Interface Unit
37 * - SSI : Serial Sound Interface
38 */
39
40/*
41 * driver data Image
42 *
43 * rsnd_priv
44 * |
45 * | ** this depends on Gen1/Gen2
46 * |
47 * +- gen
48 * |
49 * | ** these depend on data path
50 * | ** gen and platform data control it
51 * |
52 * +- rdai[0]
53 * | | sru ssiu ssi
54 * | +- playback -> [mod] -> [mod] -> [mod] -> ...
55 * | |
56 * | | sru ssiu ssi
57 * | +- capture -> [mod] -> [mod] -> [mod] -> ...
58 * |
59 * +- rdai[1]
60 * | | sru ssiu ssi
61 * | +- playback -> [mod] -> [mod] -> [mod] -> ...
62 * | |
63 * | | sru ssiu ssi
64 * | +- capture -> [mod] -> [mod] -> [mod] -> ...
65 * ...
66 * |
67 * | ** these control ssi
68 * |
69 * +- ssi
70 * | |
71 * | +- ssi[0]
72 * | +- ssi[1]
73 * | +- ssi[2]
74 * | ...
75 * |
76 * | ** these control scu
77 * |
78 * +- scu
79 * |
80 * +- scu[0]
81 * +- scu[1]
82 * +- scu[2]
83 * ...
84 *
85 *
86 * for_each_rsnd_dai(xx, priv, xx)
87 * rdai[0] => rdai[1] => rdai[2] => ...
88 *
89 * for_each_rsnd_mod(xx, rdai, xx)
90 * [mod] => [mod] => [mod] => ...
91 *
92 * rsnd_dai_call(xxx, fn )
93 * [mod]->fn() -> [mod]->fn() -> [mod]->fn()...
94 *
95 */
96#include <linux/pm_runtime.h>
97#include "rsnd.h"
98
99#define RSND_RATES SNDRV_PCM_RATE_8000_96000
100#define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
101
102/*
103 * rsnd_platform functions
104 */
105#define rsnd_platform_call(priv, dai, func, param...) \
106 (!(priv->info->func) ? -ENODEV : \
107 priv->info->func(param))
108
109
110/*
111 * basic function
112 */
113u32 rsnd_read(struct rsnd_priv *priv,
114 struct rsnd_mod *mod, enum rsnd_reg reg)
115{
116 void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
117
118 BUG_ON(!base);
119
120 return ioread32(base);
121}
122
123void rsnd_write(struct rsnd_priv *priv,
124 struct rsnd_mod *mod,
125 enum rsnd_reg reg, u32 data)
126{
127 void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
128 struct device *dev = rsnd_priv_to_dev(priv);
129
130 BUG_ON(!base);
131
132 dev_dbg(dev, "w %p : %08x\n", base, data);
133
134 iowrite32(data, base);
135}
136
137void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
138 enum rsnd_reg reg, u32 mask, u32 data)
139{
140 void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
141 struct device *dev = rsnd_priv_to_dev(priv);
142 u32 val;
143
144 BUG_ON(!base);
145
146 val = ioread32(base);
147 val &= ~mask;
148 val |= data & mask;
149 iowrite32(val, base);
150
151 dev_dbg(dev, "s %p : %08x\n", base, val);
152}
153
154/*
155 * rsnd_mod functions
156 */
157char *rsnd_mod_name(struct rsnd_mod *mod)
158{
159 if (!mod || !mod->ops)
160 return "unknown";
161
162 return mod->ops->name;
163}
164
165void rsnd_mod_init(struct rsnd_priv *priv,
166 struct rsnd_mod *mod,
167 struct rsnd_mod_ops *ops,
168 int id)
169{
170 mod->priv = priv;
171 mod->id = id;
172 mod->ops = ops;
173 INIT_LIST_HEAD(&mod->list);
174}
175
176/*
177 * rsnd_dma functions
178 */
179static void rsnd_dma_continue(struct rsnd_dma *dma)
180{
181 /* push next A or B plane */
182 dma->submit_loop = 1;
183 schedule_work(&dma->work);
184}
185
186void rsnd_dma_start(struct rsnd_dma *dma)
187{
188 /* push both A and B plane*/
189 dma->submit_loop = 2;
190 schedule_work(&dma->work);
191}
192
193void rsnd_dma_stop(struct rsnd_dma *dma)
194{
195 dma->submit_loop = 0;
196 cancel_work_sync(&dma->work);
197 dmaengine_terminate_all(dma->chan);
198}
199
200static void rsnd_dma_complete(void *data)
201{
202 struct rsnd_dma *dma = (struct rsnd_dma *)data;
203 struct rsnd_priv *priv = dma->priv;
204 unsigned long flags;
205
206 rsnd_lock(priv, flags);
207
208 dma->complete(dma);
209
210 if (dma->submit_loop)
211 rsnd_dma_continue(dma);
212
213 rsnd_unlock(priv, flags);
214}
215
216static void rsnd_dma_do_work(struct work_struct *work)
217{
218 struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work);
219 struct rsnd_priv *priv = dma->priv;
220 struct device *dev = rsnd_priv_to_dev(priv);
221 struct dma_async_tx_descriptor *desc;
222 dma_addr_t buf;
223 size_t len;
224 int i;
225
226 for (i = 0; i < dma->submit_loop; i++) {
227
228 if (dma->inquiry(dma, &buf, &len) < 0)
229 return;
230
231 desc = dmaengine_prep_slave_single(
232 dma->chan, buf, len, dma->dir,
233 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
234 if (!desc) {
235 dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
236 return;
237 }
238
239 desc->callback = rsnd_dma_complete;
240 desc->callback_param = dma;
241
242 if (dmaengine_submit(desc) < 0) {
243 dev_err(dev, "dmaengine_submit() fail\n");
244 return;
245 }
246
247 }
248
249 dma_async_issue_pending(dma->chan);
250}
251
252int rsnd_dma_available(struct rsnd_dma *dma)
253{
254 return !!dma->chan;
255}
256
257static bool rsnd_dma_filter(struct dma_chan *chan, void *param)
258{
259 chan->private = param;
260
261 return true;
262}
263
264int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
265 int is_play, int id,
266 int (*inquiry)(struct rsnd_dma *dma,
267 dma_addr_t *buf, int *len),
268 int (*complete)(struct rsnd_dma *dma))
269{
270 struct device *dev = rsnd_priv_to_dev(priv);
271 dma_cap_mask_t mask;
272
273 if (dma->chan) {
274 dev_err(dev, "it already has dma channel\n");
275 return -EIO;
276 }
277
278 dma_cap_zero(mask);
279 dma_cap_set(DMA_SLAVE, mask);
280
281 dma->slave.shdma_slave.slave_id = id;
282
283 dma->chan = dma_request_channel(mask, rsnd_dma_filter,
284 &dma->slave.shdma_slave);
285 if (!dma->chan) {
286 dev_err(dev, "can't get dma channel\n");
287 return -EIO;
288 }
289
290 dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
291 dma->priv = priv;
292 dma->inquiry = inquiry;
293 dma->complete = complete;
294 INIT_WORK(&dma->work, rsnd_dma_do_work);
295
296 return 0;
297}
298
299void rsnd_dma_quit(struct rsnd_priv *priv,
300 struct rsnd_dma *dma)
301{
302 if (dma->chan)
303 dma_release_channel(dma->chan);
304
305 dma->chan = NULL;
306}
307
308/*
309 * rsnd_dai functions
310 */
311#define rsnd_dai_call(rdai, io, fn) \
312({ \
313 struct rsnd_mod *mod, *n; \
314 int ret = 0; \
315 for_each_rsnd_mod(mod, n, io) { \
316 ret = rsnd_mod_call(mod, fn, rdai, io); \
317 if (ret < 0) \
318 break; \
319 } \
320 ret; \
321})
322
323int rsnd_dai_connect(struct rsnd_dai *rdai,
324 struct rsnd_mod *mod,
325 struct rsnd_dai_stream *io)
326{
327 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
328 struct device *dev = rsnd_priv_to_dev(priv);
329
330 if (!mod) {
331 dev_err(dev, "NULL mod\n");
332 return -EIO;
333 }
334
335 if (!list_empty(&mod->list)) {
336 dev_err(dev, "%s%d is not empty\n",
337 rsnd_mod_name(mod),
338 rsnd_mod_id(mod));
339 return -EIO;
340 }
341
342 list_add_tail(&mod->list, &io->head);
343
344 return 0;
345}
346
347int rsnd_dai_disconnect(struct rsnd_mod *mod)
348{
349 list_del_init(&mod->list);
350
351 return 0;
352}
353
354int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai)
355{
356 int id = rdai - priv->rdai;
357
358 if ((id < 0) || (id >= rsnd_dai_nr(priv)))
359 return -EINVAL;
360
361 return id;
362}
363
364struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id)
365{
366 return priv->rdai + id;
367}
368
369static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai)
370{
371 struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai);
372
373 return rsnd_dai_get(priv, dai->id);
374}
375
376int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io)
377{
378 return &rdai->playback == io;
379}
380
381/*
382 * rsnd_soc_dai functions
383 */
384int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional)
385{
386 struct snd_pcm_substream *substream = io->substream;
387 struct snd_pcm_runtime *runtime = substream->runtime;
388 int pos = io->byte_pos + additional;
389
390 pos %= (runtime->periods * io->byte_per_period);
391
392 return pos;
393}
394
395void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
396{
397 io->byte_pos += byte;
398
399 if (io->byte_pos >= io->next_period_byte) {
400 struct snd_pcm_substream *substream = io->substream;
401 struct snd_pcm_runtime *runtime = substream->runtime;
402
403 io->period_pos++;
404 io->next_period_byte += io->byte_per_period;
405
406 if (io->period_pos >= runtime->periods) {
407 io->byte_pos = 0;
408 io->period_pos = 0;
409 io->next_period_byte = io->byte_per_period;
410 }
411
412 snd_pcm_period_elapsed(substream);
413 }
414}
415
416static int rsnd_dai_stream_init(struct rsnd_dai_stream *io,
417 struct snd_pcm_substream *substream)
418{
419 struct snd_pcm_runtime *runtime = substream->runtime;
420
421 if (!list_empty(&io->head))
422 return -EIO;
423
424 INIT_LIST_HEAD(&io->head);
425 io->substream = substream;
426 io->byte_pos = 0;
427 io->period_pos = 0;
428 io->byte_per_period = runtime->period_size *
429 runtime->channels *
430 samples_to_bytes(runtime, 1);
431 io->next_period_byte = io->byte_per_period;
432
433 return 0;
434}
435
436static
437struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream)
438{
439 struct snd_soc_pcm_runtime *rtd = substream->private_data;
440
441 return rtd->cpu_dai;
442}
443
444static
445struct rsnd_dai_stream *rsnd_rdai_to_io(struct rsnd_dai *rdai,
446 struct snd_pcm_substream *substream)
447{
448 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
449 return &rdai->playback;
450 else
451 return &rdai->capture;
452}
453
454static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
455 struct snd_soc_dai *dai)
456{
457 struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai);
458 struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
459 struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
460 struct rsnd_mod *mod = rsnd_ssi_mod_get_frm_dai(priv,
461 rsnd_dai_id(priv, rdai),
462 rsnd_dai_is_play(rdai, io));
463 int ssi_id = rsnd_mod_id(mod);
464 int ret;
465 unsigned long flags;
466
467 rsnd_lock(priv, flags);
468
469 switch (cmd) {
470 case SNDRV_PCM_TRIGGER_START:
471 ret = rsnd_dai_stream_init(io, substream);
472 if (ret < 0)
473 goto dai_trigger_end;
474
475 ret = rsnd_platform_call(priv, dai, start, ssi_id);
476 if (ret < 0)
477 goto dai_trigger_end;
478
479 ret = rsnd_gen_path_init(priv, rdai, io);
480 if (ret < 0)
481 goto dai_trigger_end;
482
483 ret = rsnd_dai_call(rdai, io, init);
484 if (ret < 0)
485 goto dai_trigger_end;
486
487 ret = rsnd_dai_call(rdai, io, start);
488 if (ret < 0)
489 goto dai_trigger_end;
490 break;
491 case SNDRV_PCM_TRIGGER_STOP:
492 ret = rsnd_dai_call(rdai, io, stop);
493 if (ret < 0)
494 goto dai_trigger_end;
495
496 ret = rsnd_dai_call(rdai, io, quit);
497 if (ret < 0)
498 goto dai_trigger_end;
499
500 ret = rsnd_gen_path_exit(priv, rdai, io);
501 if (ret < 0)
502 goto dai_trigger_end;
503
504 ret = rsnd_platform_call(priv, dai, stop, ssi_id);
505 if (ret < 0)
506 goto dai_trigger_end;
507 break;
508 default:
509 ret = -EINVAL;
510 }
511
512dai_trigger_end:
513 rsnd_unlock(priv, flags);
514
515 return ret;
516}
517
518static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
519{
520 struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
521
522 /* set master/slave audio interface */
523 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
524 case SND_SOC_DAIFMT_CBM_CFM:
525 rdai->clk_master = 1;
526 break;
527 case SND_SOC_DAIFMT_CBS_CFS:
528 rdai->clk_master = 0;
529 break;
530 default:
531 return -EINVAL;
532 }
533
534 /* set clock inversion */
535 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
536 case SND_SOC_DAIFMT_NB_IF:
537 rdai->bit_clk_inv = 0;
538 rdai->frm_clk_inv = 1;
539 break;
540 case SND_SOC_DAIFMT_IB_NF:
541 rdai->bit_clk_inv = 1;
542 rdai->frm_clk_inv = 0;
543 break;
544 case SND_SOC_DAIFMT_IB_IF:
545 rdai->bit_clk_inv = 1;
546 rdai->frm_clk_inv = 1;
547 break;
548 case SND_SOC_DAIFMT_NB_NF:
549 default:
550 rdai->bit_clk_inv = 0;
551 rdai->frm_clk_inv = 0;
552 break;
553 }
554
555 /* set format */
556 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
557 case SND_SOC_DAIFMT_I2S:
558 rdai->sys_delay = 0;
559 rdai->data_alignment = 0;
560 break;
561 case SND_SOC_DAIFMT_LEFT_J:
562 rdai->sys_delay = 1;
563 rdai->data_alignment = 0;
564 break;
565 case SND_SOC_DAIFMT_RIGHT_J:
566 rdai->sys_delay = 1;
567 rdai->data_alignment = 1;
568 break;
569 }
570
571 return 0;
572}
573
574static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
575 .trigger = rsnd_soc_dai_trigger,
576 .set_fmt = rsnd_soc_dai_set_fmt,
577};
578
579static int rsnd_dai_probe(struct platform_device *pdev,
580 struct rcar_snd_info *info,
581 struct rsnd_priv *priv)
582{
583 struct snd_soc_dai_driver *drv;
584 struct rsnd_dai *rdai;
585 struct rsnd_mod *pmod, *cmod;
586 struct device *dev = rsnd_priv_to_dev(priv);
587 int dai_nr;
588 int i;
589
590 /* get max dai nr */
591 for (dai_nr = 0; dai_nr < 32; dai_nr++) {
592 pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1);
593 cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0);
594
595 if (!pmod && !cmod)
596 break;
597 }
598
599 if (!dai_nr) {
600 dev_err(dev, "no dai\n");
601 return -EIO;
602 }
603
604 drv = devm_kzalloc(dev, sizeof(*drv) * dai_nr, GFP_KERNEL);
605 rdai = devm_kzalloc(dev, sizeof(*rdai) * dai_nr, GFP_KERNEL);
606 if (!drv || !rdai) {
607 dev_err(dev, "dai allocate failed\n");
608 return -ENOMEM;
609 }
610
611 for (i = 0; i < dai_nr; i++) {
612
613 pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1);
614 cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0);
615
616 /*
617 * init rsnd_dai
618 */
619 INIT_LIST_HEAD(&rdai[i].playback.head);
620 INIT_LIST_HEAD(&rdai[i].capture.head);
621
622 snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i);
623
624 /*
625 * init snd_soc_dai_driver
626 */
627 drv[i].name = rdai[i].name;
628 drv[i].ops = &rsnd_soc_dai_ops;
629 if (pmod) {
630 drv[i].playback.rates = RSND_RATES;
631 drv[i].playback.formats = RSND_FMTS;
632 drv[i].playback.channels_min = 2;
633 drv[i].playback.channels_max = 2;
634 }
635 if (cmod) {
636 drv[i].capture.rates = RSND_RATES;
637 drv[i].capture.formats = RSND_FMTS;
638 drv[i].capture.channels_min = 2;
639 drv[i].capture.channels_max = 2;
640 }
641
642 dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name,
643 pmod ? "play" : " -- ",
644 cmod ? "capture" : " -- ");
645 }
646
647 priv->dai_nr = dai_nr;
648 priv->daidrv = drv;
649 priv->rdai = rdai;
650
651 return 0;
652}
653
654static void rsnd_dai_remove(struct platform_device *pdev,
655 struct rsnd_priv *priv)
656{
657}
658
659/*
660 * pcm ops
661 */
662static struct snd_pcm_hardware rsnd_pcm_hardware = {
663 .info = SNDRV_PCM_INFO_INTERLEAVED |
664 SNDRV_PCM_INFO_MMAP |
665 SNDRV_PCM_INFO_MMAP_VALID |
666 SNDRV_PCM_INFO_PAUSE,
667 .formats = RSND_FMTS,
668 .rates = RSND_RATES,
669 .rate_min = 8000,
670 .rate_max = 192000,
671 .channels_min = 2,
672 .channels_max = 2,
673 .buffer_bytes_max = 64 * 1024,
674 .period_bytes_min = 32,
675 .period_bytes_max = 8192,
676 .periods_min = 1,
677 .periods_max = 32,
678 .fifo_size = 256,
679};
680
681static int rsnd_pcm_open(struct snd_pcm_substream *substream)
682{
683 struct snd_pcm_runtime *runtime = substream->runtime;
684 int ret = 0;
685
686 snd_soc_set_runtime_hwparams(substream, &rsnd_pcm_hardware);
687
688 ret = snd_pcm_hw_constraint_integer(runtime,
689 SNDRV_PCM_HW_PARAM_PERIODS);
690
691 return ret;
692}
693
694static int rsnd_hw_params(struct snd_pcm_substream *substream,
695 struct snd_pcm_hw_params *hw_params)
696{
697 return snd_pcm_lib_malloc_pages(substream,
698 params_buffer_bytes(hw_params));
699}
700
701static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream)
702{
703 struct snd_pcm_runtime *runtime = substream->runtime;
704 struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
705 struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
706 struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
707
708 return bytes_to_frames(runtime, io->byte_pos);
709}
710
711static struct snd_pcm_ops rsnd_pcm_ops = {
712 .open = rsnd_pcm_open,
713 .ioctl = snd_pcm_lib_ioctl,
714 .hw_params = rsnd_hw_params,
715 .hw_free = snd_pcm_lib_free_pages,
716 .pointer = rsnd_pointer,
717};
718
719/*
720 * snd_soc_platform
721 */
722
723#define PREALLOC_BUFFER (32 * 1024)
724#define PREALLOC_BUFFER_MAX (32 * 1024)
725
726static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
727{
728 return snd_pcm_lib_preallocate_pages_for_all(
729 rtd->pcm,
730 SNDRV_DMA_TYPE_DEV,
731 rtd->card->snd_card->dev,
732 PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
733}
734
735static void rsnd_pcm_free(struct snd_pcm *pcm)
736{
737 snd_pcm_lib_preallocate_free_for_all(pcm);
738}
739
740static struct snd_soc_platform_driver rsnd_soc_platform = {
741 .ops = &rsnd_pcm_ops,
742 .pcm_new = rsnd_pcm_new,
743 .pcm_free = rsnd_pcm_free,
744};
745
746static const struct snd_soc_component_driver rsnd_soc_component = {
747 .name = "rsnd",
748};
749
750/*
751 * rsnd probe
752 */
753static int rsnd_probe(struct platform_device *pdev)
754{
755 struct rcar_snd_info *info;
756 struct rsnd_priv *priv;
757 struct device *dev = &pdev->dev;
758 int ret;
759
760 info = pdev->dev.platform_data;
761 if (!info) {
762 dev_err(dev, "driver needs R-Car sound information\n");
763 return -ENODEV;
764 }
765
766 /*
767 * init priv data
768 */
769 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
770 if (!priv) {
771 dev_err(dev, "priv allocate failed\n");
772 return -ENODEV;
773 }
774
775 priv->dev = dev;
776 priv->info = info;
777 spin_lock_init(&priv->lock);
778
779 /*
780 * init each module
781 */
782 ret = rsnd_gen_probe(pdev, info, priv);
783 if (ret < 0)
784 return ret;
785
786 ret = rsnd_scu_probe(pdev, info, priv);
787 if (ret < 0)
788 return ret;
789
790 ret = rsnd_adg_probe(pdev, info, priv);
791 if (ret < 0)
792 return ret;
793
794 ret = rsnd_ssi_probe(pdev, info, priv);
795 if (ret < 0)
796 return ret;
797
798 ret = rsnd_dai_probe(pdev, info, priv);
799 if (ret < 0)
800 return ret;
801
802 /*
803 * asoc register
804 */
805 ret = snd_soc_register_platform(dev, &rsnd_soc_platform);
806 if (ret < 0) {
807 dev_err(dev, "cannot snd soc register\n");
808 return ret;
809 }
810
811 ret = snd_soc_register_component(dev, &rsnd_soc_component,
812 priv->daidrv, rsnd_dai_nr(priv));
813 if (ret < 0) {
814 dev_err(dev, "cannot snd dai register\n");
815 goto exit_snd_soc;
816 }
817
818 dev_set_drvdata(dev, priv);
819
820 pm_runtime_enable(dev);
821
822 dev_info(dev, "probed\n");
823 return ret;
824
825exit_snd_soc:
826 snd_soc_unregister_platform(dev);
827
828 return ret;
829}
830
831static int rsnd_remove(struct platform_device *pdev)
832{
833 struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev);
834
835 pm_runtime_disable(&pdev->dev);
836
837 /*
838 * remove each module
839 */
840 rsnd_ssi_remove(pdev, priv);
841 rsnd_adg_remove(pdev, priv);
842 rsnd_scu_remove(pdev, priv);
843 rsnd_dai_remove(pdev, priv);
844 rsnd_gen_remove(pdev, priv);
845
846 return 0;
847}
848
849static struct platform_driver rsnd_driver = {
850 .driver = {
851 .name = "rcar_sound",
852 },
853 .probe = rsnd_probe,
854 .remove = rsnd_remove,
855};
856module_platform_driver(rsnd_driver);
857
858MODULE_LICENSE("GPL");
859MODULE_DESCRIPTION("Renesas R-Car audio driver");
860MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
861MODULE_ALIAS("platform:rcar-pcm-audio");
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
new file mode 100644
index 000000000000..babb203b43b7
--- /dev/null
+++ b/sound/soc/sh/rcar/gen.c
@@ -0,0 +1,280 @@
1/*
2 * Renesas R-Car Gen1 SRU/SSI support
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * 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#include "rsnd.h"
12
13struct rsnd_gen_ops {
14 int (*path_init)(struct rsnd_priv *priv,
15 struct rsnd_dai *rdai,
16 struct rsnd_dai_stream *io);
17 int (*path_exit)(struct rsnd_priv *priv,
18 struct rsnd_dai *rdai,
19 struct rsnd_dai_stream *io);
20};
21
22struct rsnd_gen_reg_map {
23 int index; /* -1 : not supported */
24 u32 offset_id; /* offset of ssi0, ssi1, ssi2... */
25 u32 offset_adr; /* offset of SSICR, SSISR, ... */
26};
27
28struct rsnd_gen {
29 void __iomem *base[RSND_BASE_MAX];
30
31 struct rsnd_gen_reg_map reg_map[RSND_REG_MAX];
32 struct rsnd_gen_ops *ops;
33};
34
35#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
36
37/*
38 * Gen2
39 * will be filled in the future
40 */
41
42/*
43 * Gen1
44 */
45static int rsnd_gen1_path_init(struct rsnd_priv *priv,
46 struct rsnd_dai *rdai,
47 struct rsnd_dai_stream *io)
48{
49 struct rsnd_mod *mod;
50 int ret;
51 int id;
52
53 /*
54 * Gen1 is created by SRU/SSI, and this SRU is base module of
55 * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU)
56 *
57 * Easy image is..
58 * Gen1 SRU = Gen2 SCU + SSIU + etc
59 *
60 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
61 * using fixed path.
62 *
63 * Then, SSI id = SCU id here
64 */
65
66 /* get SSI's ID */
67 mod = rsnd_ssi_mod_get_frm_dai(priv,
68 rsnd_dai_id(priv, rdai),
69 rsnd_dai_is_play(rdai, io));
70 id = rsnd_mod_id(mod);
71
72 /* SSI */
73 mod = rsnd_ssi_mod_get(priv, id);
74 ret = rsnd_dai_connect(rdai, mod, io);
75 if (ret < 0)
76 return ret;
77
78 /* SCU */
79 mod = rsnd_scu_mod_get(priv, id);
80 ret = rsnd_dai_connect(rdai, mod, io);
81
82 return ret;
83}
84
85static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
86 struct rsnd_dai *rdai,
87 struct rsnd_dai_stream *io)
88{
89 struct rsnd_mod *mod, *n;
90 int ret = 0;
91
92 /*
93 * remove all mod from rdai
94 */
95 for_each_rsnd_mod(mod, n, io)
96 ret |= rsnd_dai_disconnect(mod);
97
98 return ret;
99}
100
101static struct rsnd_gen_ops rsnd_gen1_ops = {
102 .path_init = rsnd_gen1_path_init,
103 .path_exit = rsnd_gen1_path_exit,
104};
105
106#define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \
107 do { \
108 (g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \
109 (g)->reg_map[RSND_REG_##i].offset_id = oi; \
110 (g)->reg_map[RSND_REG_##i].offset_adr = oa; \
111 } while (0)
112
113static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
114{
115 RSND_GEN1_REG_MAP(gen, SRU, SRC_ROUTE_SEL, 0x0, 0x00);
116 RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL0, 0x0, 0x08);
117 RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL1, 0x0, 0x0c);
118 RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL2, 0x0, 0x10);
119 RSND_GEN1_REG_MAP(gen, SRU, SRC_CTRL, 0x0, 0xc0);
120 RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE0, 0x0, 0xD0);
121 RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE1, 0x0, 0xD4);
122 RSND_GEN1_REG_MAP(gen, SRU, BUSIF_MODE, 0x4, 0x20);
123 RSND_GEN1_REG_MAP(gen, SRU, BUSIF_ADINR, 0x40, 0x214);
124
125 RSND_GEN1_REG_MAP(gen, ADG, BRRA, 0x0, 0x00);
126 RSND_GEN1_REG_MAP(gen, ADG, BRRB, 0x0, 0x04);
127 RSND_GEN1_REG_MAP(gen, ADG, SSICKR, 0x0, 0x08);
128 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL0, 0x0, 0x0c);
129 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL1, 0x0, 0x10);
130 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18);
131 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c);
132 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20);
133
134 RSND_GEN1_REG_MAP(gen, SSI, SSICR, 0x40, 0x00);
135 RSND_GEN1_REG_MAP(gen, SSI, SSISR, 0x40, 0x04);
136 RSND_GEN1_REG_MAP(gen, SSI, SSITDR, 0x40, 0x08);
137 RSND_GEN1_REG_MAP(gen, SSI, SSIRDR, 0x40, 0x0c);
138 RSND_GEN1_REG_MAP(gen, SSI, SSIWSR, 0x40, 0x20);
139}
140
141static int rsnd_gen1_probe(struct platform_device *pdev,
142 struct rcar_snd_info *info,
143 struct rsnd_priv *priv)
144{
145 struct device *dev = rsnd_priv_to_dev(priv);
146 struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
147 struct resource *sru_res;
148 struct resource *adg_res;
149 struct resource *ssi_res;
150
151 /*
152 * map address
153 */
154 sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU);
155 adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG);
156 ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI);
157
158 gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res);
159 gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res);
160 gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res);
161 if (IS_ERR(gen->base[RSND_GEN1_SRU]) ||
162 IS_ERR(gen->base[RSND_GEN1_ADG]) ||
163 IS_ERR(gen->base[RSND_GEN1_SSI]))
164 return -ENODEV;
165
166 gen->ops = &rsnd_gen1_ops;
167 rsnd_gen1_reg_map_init(gen);
168
169 dev_dbg(dev, "Gen1 device probed\n");
170 dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start,
171 gen->base[RSND_GEN1_SRU]);
172 dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start,
173 gen->base[RSND_GEN1_ADG]);
174 dev_dbg(dev, "SSI : %08x => %p\n", ssi_res->start,
175 gen->base[RSND_GEN1_SSI]);
176
177 return 0;
178
179}
180
181static void rsnd_gen1_remove(struct platform_device *pdev,
182 struct rsnd_priv *priv)
183{
184}
185
186/*
187 * Gen
188 */
189int rsnd_gen_path_init(struct rsnd_priv *priv,
190 struct rsnd_dai *rdai,
191 struct rsnd_dai_stream *io)
192{
193 struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
194
195 return gen->ops->path_init(priv, rdai, io);
196}
197
198int rsnd_gen_path_exit(struct rsnd_priv *priv,
199 struct rsnd_dai *rdai,
200 struct rsnd_dai_stream *io)
201{
202 struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
203
204 return gen->ops->path_exit(priv, rdai, io);
205}
206
207void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
208 struct rsnd_mod *mod,
209 enum rsnd_reg reg)
210{
211 struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
212 struct device *dev = rsnd_priv_to_dev(priv);
213 int index;
214 u32 offset_id, offset_adr;
215
216 if (reg >= RSND_REG_MAX) {
217 dev_err(dev, "rsnd_reg reg error\n");
218 return NULL;
219 }
220
221 index = gen->reg_map[reg].index;
222 offset_id = gen->reg_map[reg].offset_id;
223 offset_adr = gen->reg_map[reg].offset_adr;
224
225 if (index < 0) {
226 dev_err(dev, "unsupported reg access %d\n", reg);
227 return NULL;
228 }
229
230 if (offset_id && mod)
231 offset_id *= rsnd_mod_id(mod);
232
233 /*
234 * index/offset were set on gen1/gen2
235 */
236
237 return gen->base[index] + offset_id + offset_adr;
238}
239
240int rsnd_gen_probe(struct platform_device *pdev,
241 struct rcar_snd_info *info,
242 struct rsnd_priv *priv)
243{
244 struct device *dev = rsnd_priv_to_dev(priv);
245 struct rsnd_gen *gen;
246 int i;
247
248 gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
249 if (!gen) {
250 dev_err(dev, "GEN allocate failed\n");
251 return -ENOMEM;
252 }
253
254 priv->gen = gen;
255
256 /*
257 * see
258 * rsnd_reg_get()
259 * rsnd_gen_probe()
260 */
261 for (i = 0; i < RSND_REG_MAX; i++)
262 gen->reg_map[i].index = -1;
263
264 /*
265 * init each module
266 */
267 if (rsnd_is_gen1(priv))
268 return rsnd_gen1_probe(pdev, info, priv);
269
270 dev_err(dev, "unknown generation R-Car sound device\n");
271
272 return -ENODEV;
273}
274
275void rsnd_gen_remove(struct platform_device *pdev,
276 struct rsnd_priv *priv)
277{
278 if (rsnd_is_gen1(priv))
279 rsnd_gen1_remove(pdev, priv);
280}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
new file mode 100644
index 000000000000..9cc6986a8cfb
--- /dev/null
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -0,0 +1,302 @@
1/*
2 * Renesas R-Car
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * 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 RSND_H
12#define RSND_H
13
14#include <linux/clk.h>
15#include <linux/device.h>
16#include <linux/dma-mapping.h>
17#include <linux/io.h>
18#include <linux/list.h>
19#include <linux/module.h>
20#include <linux/sh_dma.h>
21#include <linux/workqueue.h>
22#include <sound/rcar_snd.h>
23#include <sound/soc.h>
24#include <sound/pcm_params.h>
25
26/*
27 * pseudo register
28 *
29 * The register address offsets SRU/SCU/SSIU on Gen1/Gen2 are very different.
30 * This driver uses pseudo register in order to hide it.
31 * see gen1/gen2 for detail
32 */
33enum rsnd_reg {
34 /* SRU/SCU */
35 RSND_REG_SRC_ROUTE_SEL,
36 RSND_REG_SRC_TMG_SEL0,
37 RSND_REG_SRC_TMG_SEL1,
38 RSND_REG_SRC_TMG_SEL2,
39 RSND_REG_SRC_CTRL,
40 RSND_REG_SSI_MODE0,
41 RSND_REG_SSI_MODE1,
42 RSND_REG_BUSIF_MODE,
43 RSND_REG_BUSIF_ADINR,
44
45 /* ADG */
46 RSND_REG_BRRA,
47 RSND_REG_BRRB,
48 RSND_REG_SSICKR,
49 RSND_REG_AUDIO_CLK_SEL0,
50 RSND_REG_AUDIO_CLK_SEL1,
51 RSND_REG_AUDIO_CLK_SEL2,
52 RSND_REG_AUDIO_CLK_SEL3,
53 RSND_REG_AUDIO_CLK_SEL4,
54 RSND_REG_AUDIO_CLK_SEL5,
55
56 /* SSI */
57 RSND_REG_SSICR,
58 RSND_REG_SSISR,
59 RSND_REG_SSITDR,
60 RSND_REG_SSIRDR,
61 RSND_REG_SSIWSR,
62
63 RSND_REG_MAX,
64};
65
66struct rsnd_priv;
67struct rsnd_mod;
68struct rsnd_dai;
69struct rsnd_dai_stream;
70
71/*
72 * R-Car basic functions
73 */
74#define rsnd_mod_read(m, r) \
75 rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r)
76#define rsnd_mod_write(m, r, d) \
77 rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d)
78#define rsnd_mod_bset(m, r, s, d) \
79 rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
80
81#define rsnd_priv_read(p, r) rsnd_read(p, NULL, RSND_REG_##r)
82#define rsnd_priv_write(p, r, d) rsnd_write(p, NULL, RSND_REG_##r, d)
83#define rsnd_priv_bset(p, r, s, d) rsnd_bset(p, NULL, RSND_REG_##r, s, d)
84
85u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
86void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
87 enum rsnd_reg reg, u32 data);
88void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
89 u32 mask, u32 data);
90
91/*
92 * R-Car DMA
93 */
94struct rsnd_dma {
95 struct rsnd_priv *priv;
96 struct sh_dmae_slave slave;
97 struct work_struct work;
98 struct dma_chan *chan;
99 enum dma_data_direction dir;
100 int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len);
101 int (*complete)(struct rsnd_dma *dma);
102
103 int submit_loop;
104};
105
106void rsnd_dma_start(struct rsnd_dma *dma);
107void rsnd_dma_stop(struct rsnd_dma *dma);
108int rsnd_dma_available(struct rsnd_dma *dma);
109int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
110 int is_play, int id,
111 int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len),
112 int (*complete)(struct rsnd_dma *dma));
113void rsnd_dma_quit(struct rsnd_priv *priv,
114 struct rsnd_dma *dma);
115
116
117/*
118 * R-Car sound mod
119 */
120
121struct rsnd_mod_ops {
122 char *name;
123 int (*init)(struct rsnd_mod *mod,
124 struct rsnd_dai *rdai,
125 struct rsnd_dai_stream *io);
126 int (*quit)(struct rsnd_mod *mod,
127 struct rsnd_dai *rdai,
128 struct rsnd_dai_stream *io);
129 int (*start)(struct rsnd_mod *mod,
130 struct rsnd_dai *rdai,
131 struct rsnd_dai_stream *io);
132 int (*stop)(struct rsnd_mod *mod,
133 struct rsnd_dai *rdai,
134 struct rsnd_dai_stream *io);
135};
136
137struct rsnd_mod {
138 int id;
139 struct rsnd_priv *priv;
140 struct rsnd_mod_ops *ops;
141 struct list_head list; /* connect to rsnd_dai playback/capture */
142 struct rsnd_dma dma;
143};
144
145#define rsnd_mod_to_priv(mod) ((mod)->priv)
146#define rsnd_mod_to_dma(mod) (&(mod)->dma)
147#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
148#define rsnd_mod_id(mod) ((mod)->id)
149#define for_each_rsnd_mod(pos, n, io) \
150 list_for_each_entry_safe(pos, n, &(io)->head, list)
151#define rsnd_mod_call(mod, func, rdai, io) \
152 (!(mod) ? -ENODEV : \
153 !((mod)->ops->func) ? 0 : \
154 (mod)->ops->func(mod, rdai, io))
155
156void rsnd_mod_init(struct rsnd_priv *priv,
157 struct rsnd_mod *mod,
158 struct rsnd_mod_ops *ops,
159 int id);
160char *rsnd_mod_name(struct rsnd_mod *mod);
161
162/*
163 * R-Car sound DAI
164 */
165#define RSND_DAI_NAME_SIZE 16
166struct rsnd_dai_stream {
167 struct list_head head; /* head of rsnd_mod list */
168 struct snd_pcm_substream *substream;
169 int byte_pos;
170 int period_pos;
171 int byte_per_period;
172 int next_period_byte;
173};
174
175struct rsnd_dai {
176 char name[RSND_DAI_NAME_SIZE];
177 struct rsnd_dai_platform_info *info; /* rcar_snd.h */
178 struct rsnd_dai_stream playback;
179 struct rsnd_dai_stream capture;
180
181 int clk_master:1;
182 int bit_clk_inv:1;
183 int frm_clk_inv:1;
184 int sys_delay:1;
185 int data_alignment:1;
186};
187
188#define rsnd_dai_nr(priv) ((priv)->dai_nr)
189#define for_each_rsnd_dai(rdai, priv, i) \
190 for (i = 0, (rdai) = rsnd_dai_get(priv, i); \
191 i < rsnd_dai_nr(priv); \
192 i++, (rdai) = rsnd_dai_get(priv, i))
193
194struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id);
195int rsnd_dai_disconnect(struct rsnd_mod *mod);
196int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod,
197 struct rsnd_dai_stream *io);
198int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io);
199int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai);
200#define rsnd_dai_get_platform_info(rdai) ((rdai)->info)
201#define rsnd_io_to_runtime(io) ((io)->substream->runtime)
202
203void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
204int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
205
206/*
207 * R-Car Gen1/Gen2
208 */
209int rsnd_gen_probe(struct platform_device *pdev,
210 struct rcar_snd_info *info,
211 struct rsnd_priv *priv);
212void rsnd_gen_remove(struct platform_device *pdev,
213 struct rsnd_priv *priv);
214int rsnd_gen_path_init(struct rsnd_priv *priv,
215 struct rsnd_dai *rdai,
216 struct rsnd_dai_stream *io);
217int rsnd_gen_path_exit(struct rsnd_priv *priv,
218 struct rsnd_dai *rdai,
219 struct rsnd_dai_stream *io);
220void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
221 struct rsnd_mod *mod,
222 enum rsnd_reg reg);
223#define rsnd_is_gen1(s) ((s)->info->flags & RSND_GEN1)
224#define rsnd_is_gen2(s) ((s)->info->flags & RSND_GEN2)
225
226/*
227 * R-Car ADG
228 */
229int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod);
230int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate);
231int rsnd_adg_probe(struct platform_device *pdev,
232 struct rcar_snd_info *info,
233 struct rsnd_priv *priv);
234void rsnd_adg_remove(struct platform_device *pdev,
235 struct rsnd_priv *priv);
236
237/*
238 * R-Car sound priv
239 */
240struct rsnd_priv {
241
242 struct device *dev;
243 struct rcar_snd_info *info;
244 spinlock_t lock;
245
246 /*
247 * below value will be filled on rsnd_gen_probe()
248 */
249 void *gen;
250
251 /*
252 * below value will be filled on rsnd_scu_probe()
253 */
254 void *scu;
255 int scu_nr;
256
257 /*
258 * below value will be filled on rsnd_adg_probe()
259 */
260 void *adg;
261
262 /*
263 * below value will be filled on rsnd_ssi_probe()
264 */
265 void *ssiu;
266
267 /*
268 * below value will be filled on rsnd_dai_probe()
269 */
270 struct snd_soc_dai_driver *daidrv;
271 struct rsnd_dai *rdai;
272 int dai_nr;
273};
274
275#define rsnd_priv_to_dev(priv) ((priv)->dev)
276#define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
277#define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)
278
279/*
280 * R-Car SCU
281 */
282int rsnd_scu_probe(struct platform_device *pdev,
283 struct rcar_snd_info *info,
284 struct rsnd_priv *priv);
285void rsnd_scu_remove(struct platform_device *pdev,
286 struct rsnd_priv *priv);
287struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
288#define rsnd_scu_nr(priv) ((priv)->scu_nr)
289
290/*
291 * R-Car SSI
292 */
293int rsnd_ssi_probe(struct platform_device *pdev,
294 struct rcar_snd_info *info,
295 struct rsnd_priv *priv);
296void rsnd_ssi_remove(struct platform_device *pdev,
297 struct rsnd_priv *priv);
298struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
299struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
300 int dai_id, int is_play);
301
302#endif
diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c
new file mode 100644
index 000000000000..184d9008cecd
--- /dev/null
+++ b/sound/soc/sh/rcar/scu.c
@@ -0,0 +1,236 @@
1/*
2 * Renesas R-Car SCU support
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * 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#include "rsnd.h"
12
13struct rsnd_scu {
14 struct rsnd_scu_platform_info *info; /* rcar_snd.h */
15 struct rsnd_mod mod;
16};
17
18#define rsnd_scu_mode_flags(p) ((p)->info->flags)
19
20/*
21 * ADINR
22 */
23#define OTBL_24 (0 << 16)
24#define OTBL_22 (2 << 16)
25#define OTBL_20 (4 << 16)
26#define OTBL_18 (6 << 16)
27#define OTBL_16 (8 << 16)
28
29
30#define rsnd_mod_to_scu(_mod) \
31 container_of((_mod), struct rsnd_scu, mod)
32
33#define for_each_rsnd_scu(pos, priv, i) \
34 for ((i) = 0; \
35 ((i) < rsnd_scu_nr(priv)) && \
36 ((pos) = (struct rsnd_scu *)(priv)->scu + i); \
37 i++)
38
39static int rsnd_scu_set_route(struct rsnd_priv *priv,
40 struct rsnd_mod *mod,
41 struct rsnd_dai *rdai,
42 struct rsnd_dai_stream *io)
43{
44 struct scu_route_config {
45 u32 mask;
46 int shift;
47 } routes[] = {
48 { 0xF, 0, }, /* 0 */
49 { 0xF, 4, }, /* 1 */
50 { 0xF, 8, }, /* 2 */
51 { 0x7, 12, }, /* 3 */
52 { 0x7, 16, }, /* 4 */
53 { 0x7, 20, }, /* 5 */
54 { 0x7, 24, }, /* 6 */
55 { 0x3, 28, }, /* 7 */
56 { 0x3, 30, }, /* 8 */
57 };
58
59 u32 mask;
60 u32 val;
61 int shift;
62 int id;
63
64 /*
65 * Gen1 only
66 */
67 if (!rsnd_is_gen1(priv))
68 return 0;
69
70 id = rsnd_mod_id(mod);
71 if (id < 0 || id > ARRAY_SIZE(routes))
72 return -EIO;
73
74 /*
75 * SRC_ROUTE_SELECT
76 */
77 val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2;
78 val = val << routes[id].shift;
79 mask = routes[id].mask << routes[id].shift;
80
81 rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val);
82
83 /*
84 * SRC_TIMING_SELECT
85 */
86 shift = (id % 4) * 8;
87 mask = 0x1F << shift;
88 if (8 == id) /* SRU8 is very special */
89 val = id << shift;
90 else
91 val = (id + 1) << shift;
92
93 switch (id / 4) {
94 case 0:
95 rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val);
96 break;
97 case 1:
98 rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val);
99 break;
100 case 2:
101 rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val);
102 break;
103 }
104
105 return 0;
106}
107
108static int rsnd_scu_set_mode(struct rsnd_priv *priv,
109 struct rsnd_mod *mod,
110 struct rsnd_dai *rdai,
111 struct rsnd_dai_stream *io)
112{
113 int id = rsnd_mod_id(mod);
114 u32 val;
115
116 if (rsnd_is_gen1(priv)) {
117 val = (1 << id);
118 rsnd_mod_bset(mod, SRC_CTRL, val, val);
119 }
120
121 return 0;
122}
123
124static int rsnd_scu_set_hpbif(struct rsnd_priv *priv,
125 struct rsnd_mod *mod,
126 struct rsnd_dai *rdai,
127 struct rsnd_dai_stream *io)
128{
129 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
130 u32 adinr = runtime->channels;
131
132 switch (runtime->sample_bits) {
133 case 16:
134 adinr |= OTBL_16;
135 break;
136 case 32:
137 adinr |= OTBL_24;
138 break;
139 default:
140 return -EIO;
141 }
142
143 rsnd_mod_write(mod, BUSIF_MODE, 1);
144 rsnd_mod_write(mod, BUSIF_ADINR, adinr);
145
146 return 0;
147}
148
149static int rsnd_scu_start(struct rsnd_mod *mod,
150 struct rsnd_dai *rdai,
151 struct rsnd_dai_stream *io)
152{
153 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
154 struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
155 struct device *dev = rsnd_priv_to_dev(priv);
156 u32 flags = rsnd_scu_mode_flags(scu);
157 int ret;
158
159 /*
160 * SCU will be used if it has RSND_SCU_USB_HPBIF flags
161 */
162 if (!(flags & RSND_SCU_USB_HPBIF)) {
163 /* it use PIO transter */
164 dev_dbg(dev, "%s%d is not used\n",
165 rsnd_mod_name(mod), rsnd_mod_id(mod));
166
167 return 0;
168 }
169
170 /* it use DMA transter */
171 ret = rsnd_scu_set_route(priv, mod, rdai, io);
172 if (ret < 0)
173 return ret;
174
175 ret = rsnd_scu_set_mode(priv, mod, rdai, io);
176 if (ret < 0)
177 return ret;
178
179 ret = rsnd_scu_set_hpbif(priv, mod, rdai, io);
180 if (ret < 0)
181 return ret;
182
183 dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
184
185 return 0;
186}
187
188static struct rsnd_mod_ops rsnd_scu_ops = {
189 .name = "scu",
190 .start = rsnd_scu_start,
191};
192
193struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id)
194{
195 BUG_ON(id < 0 || id >= rsnd_scu_nr(priv));
196
197 return &((struct rsnd_scu *)(priv->scu) + id)->mod;
198}
199
200int rsnd_scu_probe(struct platform_device *pdev,
201 struct rcar_snd_info *info,
202 struct rsnd_priv *priv)
203{
204 struct device *dev = rsnd_priv_to_dev(priv);
205 struct rsnd_scu *scu;
206 int i, nr;
207
208 /*
209 * init SCU
210 */
211 nr = info->scu_info_nr;
212 scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL);
213 if (!scu) {
214 dev_err(dev, "SCU allocate failed\n");
215 return -ENOMEM;
216 }
217
218 priv->scu_nr = nr;
219 priv->scu = scu;
220
221 for_each_rsnd_scu(scu, priv, i) {
222 rsnd_mod_init(priv, &scu->mod,
223 &rsnd_scu_ops, i);
224 scu->info = &info->scu_info[i];
225
226 dev_dbg(dev, "SCU%d probed\n", i);
227 }
228 dev_dbg(dev, "scu probed\n");
229
230 return 0;
231}
232
233void rsnd_scu_remove(struct platform_device *pdev,
234 struct rsnd_priv *priv)
235{
236}
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
new file mode 100644
index 000000000000..fae26d3f79d2
--- /dev/null
+++ b/sound/soc/sh/rcar/ssi.c
@@ -0,0 +1,728 @@
1/*
2 * Renesas R-Car SSIU/SSI support
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * Based on fsi.c
8 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/delay.h>
15#include "rsnd.h"
16#define RSND_SSI_NAME_SIZE 16
17
18/*
19 * SSICR
20 */
21#define FORCE (1 << 31) /* Fixed */
22#define DMEN (1 << 28) /* DMA Enable */
23#define UIEN (1 << 27) /* Underflow Interrupt Enable */
24#define OIEN (1 << 26) /* Overflow Interrupt Enable */
25#define IIEN (1 << 25) /* Idle Mode Interrupt Enable */
26#define DIEN (1 << 24) /* Data Interrupt Enable */
27
28#define DWL_8 (0 << 19) /* Data Word Length */
29#define DWL_16 (1 << 19) /* Data Word Length */
30#define DWL_18 (2 << 19) /* Data Word Length */
31#define DWL_20 (3 << 19) /* Data Word Length */
32#define DWL_22 (4 << 19) /* Data Word Length */
33#define DWL_24 (5 << 19) /* Data Word Length */
34#define DWL_32 (6 << 19) /* Data Word Length */
35
36#define SWL_32 (3 << 16) /* R/W System Word Length */
37#define SCKD (1 << 15) /* Serial Bit Clock Direction */
38#define SWSD (1 << 14) /* Serial WS Direction */
39#define SCKP (1 << 13) /* Serial Bit Clock Polarity */
40#define SWSP (1 << 12) /* Serial WS Polarity */
41#define SDTA (1 << 10) /* Serial Data Alignment */
42#define DEL (1 << 8) /* Serial Data Delay */
43#define CKDV(v) (v << 4) /* Serial Clock Division Ratio */
44#define TRMD (1 << 1) /* Transmit/Receive Mode Select */
45#define EN (1 << 0) /* SSI Module Enable */
46
47/*
48 * SSISR
49 */
50#define UIRQ (1 << 27) /* Underflow Error Interrupt Status */
51#define OIRQ (1 << 26) /* Overflow Error Interrupt Status */
52#define IIRQ (1 << 25) /* Idle Mode Interrupt Status */
53#define DIRQ (1 << 24) /* Data Interrupt Status Flag */
54
55/*
56 * SSIWSR
57 */
58#define CONT (1 << 8) /* WS Continue Function */
59
60struct rsnd_ssi {
61 struct clk *clk;
62 struct rsnd_ssi_platform_info *info; /* rcar_snd.h */
63 struct rsnd_ssi *parent;
64 struct rsnd_mod mod;
65
66 struct rsnd_dai *rdai;
67 struct rsnd_dai_stream *io;
68 u32 cr_own;
69 u32 cr_clk;
70 u32 cr_etc;
71 int err;
72 int dma_offset;
73 unsigned int usrcnt;
74 unsigned int rate;
75};
76
77struct rsnd_ssiu {
78 u32 ssi_mode0;
79 u32 ssi_mode1;
80
81 int ssi_nr;
82 struct rsnd_ssi *ssi;
83};
84
85#define for_each_rsnd_ssi(pos, priv, i) \
86 for (i = 0; \
87 (i < rsnd_ssi_nr(priv)) && \
88 ((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \
89 i++)
90
91#define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr)
92#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
93#define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma))
94#define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0)
95#define rsnd_ssi_dma_available(ssi) \
96 rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod))
97#define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent)
98#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master)
99#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
100#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
101#define rsnd_ssi_to_ssiu(ssi)\
102 (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1)
103
104static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
105 struct rsnd_ssiu *ssiu)
106{
107 struct device *dev = rsnd_priv_to_dev(priv);
108 struct rsnd_ssi *ssi;
109 u32 flags;
110 u32 val;
111 int i;
112
113 /*
114 * SSI_MODE0
115 */
116 ssiu->ssi_mode0 = 0;
117 for_each_rsnd_ssi(ssi, priv, i) {
118 flags = rsnd_ssi_mode_flags(ssi);
119
120 /* see also BUSIF_MODE */
121 if (!(flags & RSND_SSI_DEPENDENT)) {
122 ssiu->ssi_mode0 |= (1 << i);
123 dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", i);
124 } else {
125 dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", i);
126 }
127 }
128
129 /*
130 * SSI_MODE1
131 */
132#define ssi_parent_set(p, sync, adg, ext) \
133 do { \
134 ssi->parent = ssiu->ssi + p; \
135 if (flags & RSND_SSI_CLK_FROM_ADG) \
136 val = adg; \
137 else \
138 val = ext; \
139 if (flags & RSND_SSI_SYNC) \
140 val |= sync; \
141 } while (0)
142
143 ssiu->ssi_mode1 = 0;
144 for_each_rsnd_ssi(ssi, priv, i) {
145 flags = rsnd_ssi_mode_flags(ssi);
146
147 if (!(flags & RSND_SSI_CLK_PIN_SHARE))
148 continue;
149
150 val = 0;
151 switch (i) {
152 case 1:
153 ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0));
154 break;
155 case 2:
156 ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2));
157 break;
158 case 4:
159 ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16));
160 break;
161 case 8:
162 ssi_parent_set(7, 0, 0, 0);
163 break;
164 }
165
166 ssiu->ssi_mode1 |= val;
167 }
168}
169
170static void rsnd_ssi_mode_set(struct rsnd_ssi *ssi)
171{
172 struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi);
173
174 rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0);
175 rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1);
176}
177
178static void rsnd_ssi_status_check(struct rsnd_mod *mod,
179 u32 bit)
180{
181 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
182 struct device *dev = rsnd_priv_to_dev(priv);
183 u32 status;
184 int i;
185
186 for (i = 0; i < 1024; i++) {
187 status = rsnd_mod_read(mod, SSISR);
188 if (status & bit)
189 return;
190
191 udelay(50);
192 }
193
194 dev_warn(dev, "status check failed\n");
195}
196
197static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
198 unsigned int rate)
199{
200 struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
201 struct device *dev = rsnd_priv_to_dev(priv);
202 int i, j, ret;
203 int adg_clk_div_table[] = {
204 1, 6, /* see adg.c */
205 };
206 int ssi_clk_mul_table[] = {
207 1, 2, 4, 8, 16, 6, 12,
208 };
209 unsigned int main_rate;
210
211 /*
212 * Find best clock, and try to start ADG
213 */
214 for (i = 0; i < ARRAY_SIZE(adg_clk_div_table); i++) {
215 for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
216
217 /*
218 * this driver is assuming that
219 * system word is 64fs (= 2 x 32bit)
220 * see rsnd_ssi_start()
221 */
222 main_rate = rate / adg_clk_div_table[i]
223 * 32 * 2 * ssi_clk_mul_table[j];
224
225 ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate);
226 if (0 == ret) {
227 ssi->rate = rate;
228 ssi->cr_clk = FORCE | SWL_32 |
229 SCKD | SWSD | CKDV(j);
230
231 dev_dbg(dev, "ssi%d outputs %u Hz\n",
232 rsnd_mod_id(&ssi->mod), rate);
233
234 return 0;
235 }
236 }
237 }
238
239 dev_err(dev, "unsupported clock rate\n");
240 return -EIO;
241}
242
243static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi)
244{
245 ssi->rate = 0;
246 ssi->cr_clk = 0;
247 rsnd_adg_ssi_clk_stop(&ssi->mod);
248}
249
250static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
251 struct rsnd_dai *rdai,
252 struct rsnd_dai_stream *io)
253{
254 struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
255 struct device *dev = rsnd_priv_to_dev(priv);
256 u32 cr;
257
258 if (0 == ssi->usrcnt) {
259 clk_enable(ssi->clk);
260
261 if (rsnd_rdai_is_clk_master(rdai)) {
262 struct snd_pcm_runtime *runtime;
263
264 runtime = rsnd_io_to_runtime(io);
265
266 if (rsnd_ssi_clk_from_parent(ssi))
267 rsnd_ssi_hw_start(ssi->parent, rdai, io);
268 else
269 rsnd_ssi_master_clk_start(ssi, runtime->rate);
270 }
271 }
272
273 cr = ssi->cr_own |
274 ssi->cr_clk |
275 ssi->cr_etc |
276 EN;
277
278 rsnd_mod_write(&ssi->mod, SSICR, cr);
279
280 ssi->usrcnt++;
281
282 dev_dbg(dev, "ssi%d hw started\n", rsnd_mod_id(&ssi->mod));
283}
284
285static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
286 struct rsnd_dai *rdai)
287{
288 struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
289 struct device *dev = rsnd_priv_to_dev(priv);
290 u32 cr;
291
292 if (0 == ssi->usrcnt) /* stop might be called without start */
293 return;
294
295 ssi->usrcnt--;
296
297 if (0 == ssi->usrcnt) {
298 /*
299 * disable all IRQ,
300 * and, wait all data was sent
301 */
302 cr = ssi->cr_own |
303 ssi->cr_clk;
304
305 rsnd_mod_write(&ssi->mod, SSICR, cr | EN);
306 rsnd_ssi_status_check(&ssi->mod, DIRQ);
307
308 /*
309 * disable SSI,
310 * and, wait idle state
311 */
312 rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */
313 rsnd_ssi_status_check(&ssi->mod, IIRQ);
314
315 if (rsnd_rdai_is_clk_master(rdai)) {
316 if (rsnd_ssi_clk_from_parent(ssi))
317 rsnd_ssi_hw_stop(ssi->parent, rdai);
318 else
319 rsnd_ssi_master_clk_stop(ssi);
320 }
321
322 clk_disable(ssi->clk);
323 }
324
325 dev_dbg(dev, "ssi%d hw stopped\n", rsnd_mod_id(&ssi->mod));
326}
327
328/*
329 * SSI mod common functions
330 */
331static int rsnd_ssi_init(struct rsnd_mod *mod,
332 struct rsnd_dai *rdai,
333 struct rsnd_dai_stream *io)
334{
335 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
336 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
337 struct device *dev = rsnd_priv_to_dev(priv);
338 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
339 u32 cr;
340
341 cr = FORCE;
342
343 /*
344 * always use 32bit system word for easy clock calculation.
345 * see also rsnd_ssi_master_clk_enable()
346 */
347 cr |= SWL_32;
348
349 /*
350 * init clock settings for SSICR
351 */
352 switch (runtime->sample_bits) {
353 case 16:
354 cr |= DWL_16;
355 break;
356 case 32:
357 cr |= DWL_24;
358 break;
359 default:
360 return -EIO;
361 }
362
363 if (rdai->bit_clk_inv)
364 cr |= SCKP;
365 if (rdai->frm_clk_inv)
366 cr |= SWSP;
367 if (rdai->data_alignment)
368 cr |= SDTA;
369 if (rdai->sys_delay)
370 cr |= DEL;
371 if (rsnd_dai_is_play(rdai, io))
372 cr |= TRMD;
373
374 /*
375 * set ssi parameter
376 */
377 ssi->rdai = rdai;
378 ssi->io = io;
379 ssi->cr_own = cr;
380 ssi->err = -1; /* ignore 1st error */
381
382 rsnd_ssi_mode_set(ssi);
383
384 dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
385
386 return 0;
387}
388
389static int rsnd_ssi_quit(struct rsnd_mod *mod,
390 struct rsnd_dai *rdai,
391 struct rsnd_dai_stream *io)
392{
393 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
394 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
395 struct device *dev = rsnd_priv_to_dev(priv);
396
397 dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
398
399 if (ssi->err > 0)
400 dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err);
401
402 ssi->rdai = NULL;
403 ssi->io = NULL;
404 ssi->cr_own = 0;
405 ssi->err = 0;
406
407 return 0;
408}
409
410static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
411{
412 /* under/over flow error */
413 if (status & (UIRQ | OIRQ)) {
414 ssi->err++;
415
416 /* clear error status */
417 rsnd_mod_write(&ssi->mod, SSISR, 0);
418 }
419}
420
421/*
422 * SSI PIO
423 */
424static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data)
425{
426 struct rsnd_ssi *ssi = data;
427 struct rsnd_dai_stream *io = ssi->io;
428 u32 status = rsnd_mod_read(&ssi->mod, SSISR);
429 irqreturn_t ret = IRQ_NONE;
430
431 if (io && (status & DIRQ)) {
432 struct rsnd_dai *rdai = ssi->rdai;
433 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
434 u32 *buf = (u32 *)(runtime->dma_area +
435 rsnd_dai_pointer_offset(io, 0));
436
437 rsnd_ssi_record_error(ssi, status);
438
439 /*
440 * 8/16/32 data can be assesse to TDR/RDR register
441 * directly as 32bit data
442 * see rsnd_ssi_init()
443 */
444 if (rsnd_dai_is_play(rdai, io))
445 rsnd_mod_write(&ssi->mod, SSITDR, *buf);
446 else
447 *buf = rsnd_mod_read(&ssi->mod, SSIRDR);
448
449 rsnd_dai_pointer_update(io, sizeof(*buf));
450
451 ret = IRQ_HANDLED;
452 }
453
454 return ret;
455}
456
457static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
458 struct rsnd_dai *rdai,
459 struct rsnd_dai_stream *io)
460{
461 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
462 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
463 struct device *dev = rsnd_priv_to_dev(priv);
464
465 /* enable PIO IRQ */
466 ssi->cr_etc = UIEN | OIEN | DIEN;
467
468 rsnd_ssi_hw_start(ssi, rdai, io);
469
470 dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
471
472 return 0;
473}
474
475static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
476 struct rsnd_dai *rdai,
477 struct rsnd_dai_stream *io)
478{
479 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
480 struct device *dev = rsnd_priv_to_dev(priv);
481 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
482
483 dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
484
485 ssi->cr_etc = 0;
486
487 rsnd_ssi_hw_stop(ssi, rdai);
488
489 return 0;
490}
491
492static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
493 .name = "ssi (pio)",
494 .init = rsnd_ssi_init,
495 .quit = rsnd_ssi_quit,
496 .start = rsnd_ssi_pio_start,
497 .stop = rsnd_ssi_pio_stop,
498};
499
500static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len)
501{
502 struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma);
503 struct rsnd_dai_stream *io = ssi->io;
504 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
505
506 *len = io->byte_per_period;
507 *buf = runtime->dma_addr +
508 rsnd_dai_pointer_offset(io, ssi->dma_offset + *len);
509 ssi->dma_offset = *len; /* it cares A/B plane */
510
511 return 0;
512}
513
514static int rsnd_ssi_dma_complete(struct rsnd_dma *dma)
515{
516 struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma);
517 struct rsnd_dai_stream *io = ssi->io;
518 u32 status = rsnd_mod_read(&ssi->mod, SSISR);
519
520 rsnd_ssi_record_error(ssi, status);
521
522 rsnd_dai_pointer_update(ssi->io, io->byte_per_period);
523
524 return 0;
525}
526
527static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
528 struct rsnd_dai *rdai,
529 struct rsnd_dai_stream *io)
530{
531 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
532 struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod);
533
534 /* enable DMA transfer */
535 ssi->cr_etc = DMEN;
536 ssi->dma_offset = 0;
537
538 rsnd_dma_start(dma);
539
540 rsnd_ssi_hw_start(ssi, ssi->rdai, io);
541
542 /* enable WS continue */
543 if (rsnd_rdai_is_clk_master(rdai))
544 rsnd_mod_write(&ssi->mod, SSIWSR, CONT);
545
546 return 0;
547}
548
549static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
550 struct rsnd_dai *rdai,
551 struct rsnd_dai_stream *io)
552{
553 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
554 struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod);
555
556 ssi->cr_etc = 0;
557
558 rsnd_ssi_hw_stop(ssi, rdai);
559
560 rsnd_dma_stop(dma);
561
562 return 0;
563}
564
565static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
566 .name = "ssi (dma)",
567 .init = rsnd_ssi_init,
568 .quit = rsnd_ssi_quit,
569 .start = rsnd_ssi_dma_start,
570 .stop = rsnd_ssi_dma_stop,
571};
572
573/*
574 * Non SSI
575 */
576static int rsnd_ssi_non(struct rsnd_mod *mod,
577 struct rsnd_dai *rdai,
578 struct rsnd_dai_stream *io)
579{
580 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
581 struct device *dev = rsnd_priv_to_dev(priv);
582
583 dev_dbg(dev, "%s\n", __func__);
584
585 return 0;
586}
587
588static struct rsnd_mod_ops rsnd_ssi_non_ops = {
589 .name = "ssi (non)",
590 .init = rsnd_ssi_non,
591 .quit = rsnd_ssi_non,
592 .start = rsnd_ssi_non,
593 .stop = rsnd_ssi_non,
594};
595
596/*
597 * ssi mod function
598 */
599struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
600 int dai_id, int is_play)
601{
602 struct rsnd_ssi *ssi;
603 int i, has_play;
604
605 is_play = !!is_play;
606
607 for_each_rsnd_ssi(ssi, priv, i) {
608 if (rsnd_ssi_dai_id(ssi) != dai_id)
609 continue;
610
611 has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY);
612
613 if (is_play == has_play)
614 return &ssi->mod;
615 }
616
617 return NULL;
618}
619
620struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
621{
622 BUG_ON(id < 0 || id >= rsnd_ssi_nr(priv));
623
624 return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod;
625}
626
627int rsnd_ssi_probe(struct platform_device *pdev,
628 struct rcar_snd_info *info,
629 struct rsnd_priv *priv)
630{
631 struct rsnd_ssi_platform_info *pinfo;
632 struct device *dev = rsnd_priv_to_dev(priv);
633 struct rsnd_mod_ops *ops;
634 struct clk *clk;
635 struct rsnd_ssiu *ssiu;
636 struct rsnd_ssi *ssi;
637 char name[RSND_SSI_NAME_SIZE];
638 int i, nr, ret;
639
640 /*
641 * init SSI
642 */
643 nr = info->ssi_info_nr;
644 ssiu = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr),
645 GFP_KERNEL);
646 if (!ssiu) {
647 dev_err(dev, "SSI allocate failed\n");
648 return -ENOMEM;
649 }
650
651 priv->ssiu = ssiu;
652 ssiu->ssi = (struct rsnd_ssi *)(ssiu + 1);
653 ssiu->ssi_nr = nr;
654
655 for_each_rsnd_ssi(ssi, priv, i) {
656 pinfo = &info->ssi_info[i];
657
658 snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i);
659
660 clk = clk_get(dev, name);
661 if (IS_ERR(clk))
662 return PTR_ERR(clk);
663
664 ssi->info = pinfo;
665 ssi->clk = clk;
666
667 ops = &rsnd_ssi_non_ops;
668
669 /*
670 * SSI DMA case
671 */
672 if (pinfo->dma_id > 0) {
673 ret = rsnd_dma_init(
674 priv, rsnd_mod_to_dma(&ssi->mod),
675 (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY),
676 pinfo->dma_id,
677 rsnd_ssi_dma_inquiry,
678 rsnd_ssi_dma_complete);
679 if (ret < 0)
680 dev_info(dev, "SSI DMA failed. try PIO transter\n");
681 else
682 ops = &rsnd_ssi_dma_ops;
683
684 dev_dbg(dev, "SSI%d use DMA transfer\n", i);
685 }
686
687 /*
688 * SSI PIO case
689 */
690 if (!rsnd_ssi_dma_available(ssi) &&
691 rsnd_ssi_pio_available(ssi)) {
692 ret = devm_request_irq(dev, pinfo->pio_irq,
693 &rsnd_ssi_pio_interrupt,
694 IRQF_SHARED,
695 dev_name(dev), ssi);
696 if (ret) {
697 dev_err(dev, "SSI request interrupt failed\n");
698 return ret;
699 }
700
701 ops = &rsnd_ssi_pio_ops;
702
703 dev_dbg(dev, "SSI%d use PIO transfer\n", i);
704 }
705
706 rsnd_mod_init(priv, &ssi->mod, ops, i);
707 }
708
709 rsnd_ssi_mode_init(priv, ssiu);
710
711 dev_dbg(dev, "ssi probed\n");
712
713 return 0;
714}
715
716void rsnd_ssi_remove(struct platform_device *pdev,
717 struct rsnd_priv *priv)
718{
719 struct rsnd_ssi *ssi;
720 int i;
721
722 for_each_rsnd_ssi(ssi, priv, i) {
723 clk_put(ssi->clk);
724 if (rsnd_ssi_dma_available(ssi))
725 rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod));
726 }
727
728}
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 06a8000aa07b..53c9ecdd119f 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -149,8 +149,9 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
149 SND_SOC_DAPM_STREAM_STOP); 149 SND_SOC_DAPM_STREAM_STOP);
150 } else { 150 } else {
151 rtd->pop_wait = 1; 151 rtd->pop_wait = 1;
152 schedule_delayed_work(&rtd->delayed_work, 152 queue_delayed_work(system_power_efficient_wq,
153 msecs_to_jiffies(rtd->pmdown_time)); 153 &rtd->delayed_work,
154 msecs_to_jiffies(rtd->pmdown_time));
154 } 155 }
155 } else { 156 } else {
156 /* capture streams can be powered down now */ 157 /* capture streams can be powered down now */
@@ -334,7 +335,7 @@ static int soc_compr_copy(struct snd_compr_stream *cstream,
334 return ret; 335 return ret;
335} 336}
336 337
337static int sst_compr_set_metadata(struct snd_compr_stream *cstream, 338static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
338 struct snd_compr_metadata *metadata) 339 struct snd_compr_metadata *metadata)
339{ 340{
340 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 341 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
@@ -347,7 +348,7 @@ static int sst_compr_set_metadata(struct snd_compr_stream *cstream,
347 return ret; 348 return ret;
348} 349}
349 350
350static int sst_compr_get_metadata(struct snd_compr_stream *cstream, 351static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
351 struct snd_compr_metadata *metadata) 352 struct snd_compr_metadata *metadata)
352{ 353{
353 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 354 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
@@ -364,8 +365,8 @@ static struct snd_compr_ops soc_compr_ops = {
364 .open = soc_compr_open, 365 .open = soc_compr_open,
365 .free = soc_compr_free, 366 .free = soc_compr_free,
366 .set_params = soc_compr_set_params, 367 .set_params = soc_compr_set_params,
367 .set_metadata = sst_compr_set_metadata, 368 .set_metadata = soc_compr_set_metadata,
368 .get_metadata = sst_compr_get_metadata, 369 .get_metadata = soc_compr_get_metadata,
369 .get_params = soc_compr_get_params, 370 .get_params = soc_compr_get_params,
370 .trigger = soc_compr_trigger, 371 .trigger = soc_compr_trigger,
371 .pointer = soc_compr_pointer, 372 .pointer = soc_compr_pointer,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index d82ee386eab5..528f8708221d 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -30,9 +30,12 @@
30#include <linux/bitops.h> 30#include <linux/bitops.h>
31#include <linux/debugfs.h> 31#include <linux/debugfs.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pinctrl/consumer.h>
33#include <linux/ctype.h> 34#include <linux/ctype.h>
34#include <linux/slab.h> 35#include <linux/slab.h>
35#include <linux/of.h> 36#include <linux/of.h>
37#include <linux/gpio.h>
38#include <linux/of_gpio.h>
36#include <sound/ac97_codec.h> 39#include <sound/ac97_codec.h>
37#include <sound/core.h> 40#include <sound/core.h>
38#include <sound/jack.h> 41#include <sound/jack.h>
@@ -47,8 +50,6 @@
47 50
48#define NAME_SIZE 32 51#define NAME_SIZE 32
49 52
50static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
51
52#ifdef CONFIG_DEBUG_FS 53#ifdef CONFIG_DEBUG_FS
53struct dentry *snd_soc_debugfs_root; 54struct dentry *snd_soc_debugfs_root;
54EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); 55EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
@@ -69,6 +70,16 @@ static int pmdown_time = 5000;
69module_param(pmdown_time, int, 0); 70module_param(pmdown_time, int, 0);
70MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); 71MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
71 72
73struct snd_ac97_reset_cfg {
74 struct pinctrl *pctl;
75 struct pinctrl_state *pstate_reset;
76 struct pinctrl_state *pstate_warm_reset;
77 struct pinctrl_state *pstate_run;
78 int gpio_sdata;
79 int gpio_sync;
80 int gpio_reset;
81};
82
72/* returns the minimum number of bytes needed to represent 83/* returns the minimum number of bytes needed to represent
73 * a particular given value */ 84 * a particular given value */
74static int min_bytes_needed(unsigned long val) 85static int min_bytes_needed(unsigned long val)
@@ -530,6 +541,15 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
530} 541}
531#endif 542#endif
532 543
544static void codec2codec_close_delayed_work(struct work_struct *work)
545{
546 /* Currently nothing to do for c2c links
547 * Since c2c links are internal nodes in the DAPM graph and
548 * don't interface with the outside world or application layer
549 * we don't have to do any special handling on close.
550 */
551}
552
533#ifdef CONFIG_PM_SLEEP 553#ifdef CONFIG_PM_SLEEP
534/* powers down audio subsystem for suspend */ 554/* powers down audio subsystem for suspend */
535int snd_soc_suspend(struct device *dev) 555int snd_soc_suspend(struct device *dev)
@@ -1428,6 +1448,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
1428 return ret; 1448 return ret;
1429 } 1449 }
1430 } else { 1450 } else {
1451 INIT_DELAYED_WORK(&rtd->delayed_work,
1452 codec2codec_close_delayed_work);
1453
1431 /* link the DAI widgets */ 1454 /* link the DAI widgets */
1432 play_w = codec_dai->playback_widget; 1455 play_w = codec_dai->playback_widget;
1433 capture_w = cpu_dai->capture_widget; 1456 capture_w = cpu_dai->capture_widget;
@@ -2080,6 +2103,117 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
2080} 2103}
2081EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); 2104EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
2082 2105
2106static struct snd_ac97_reset_cfg snd_ac97_rst_cfg;
2107
2108static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97)
2109{
2110 struct pinctrl *pctl = snd_ac97_rst_cfg.pctl;
2111
2112 pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset);
2113
2114 gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1);
2115
2116 udelay(10);
2117
2118 gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0);
2119
2120 pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run);
2121 msleep(2);
2122}
2123
2124static void snd_soc_ac97_reset(struct snd_ac97 *ac97)
2125{
2126 struct pinctrl *pctl = snd_ac97_rst_cfg.pctl;
2127
2128 pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset);
2129
2130 gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0);
2131 gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0);
2132 gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0);
2133
2134 udelay(10);
2135
2136 gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1);
2137
2138 pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run);
2139 msleep(2);
2140}
2141
2142static int snd_soc_ac97_parse_pinctl(struct device *dev,
2143 struct snd_ac97_reset_cfg *cfg)
2144{
2145 struct pinctrl *p;
2146 struct pinctrl_state *state;
2147 int gpio;
2148 int ret;
2149
2150 p = devm_pinctrl_get(dev);
2151 if (IS_ERR(p)) {
2152 dev_err(dev, "Failed to get pinctrl\n");
2153 return PTR_RET(p);
2154 }
2155 cfg->pctl = p;
2156
2157 state = pinctrl_lookup_state(p, "ac97-reset");
2158 if (IS_ERR(state)) {
2159 dev_err(dev, "Can't find pinctrl state ac97-reset\n");
2160 return PTR_RET(state);
2161 }
2162 cfg->pstate_reset = state;
2163
2164 state = pinctrl_lookup_state(p, "ac97-warm-reset");
2165 if (IS_ERR(state)) {
2166 dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n");
2167 return PTR_RET(state);
2168 }
2169 cfg->pstate_warm_reset = state;
2170
2171 state = pinctrl_lookup_state(p, "ac97-running");
2172 if (IS_ERR(state)) {
2173 dev_err(dev, "Can't find pinctrl state ac97-running\n");
2174 return PTR_RET(state);
2175 }
2176 cfg->pstate_run = state;
2177
2178 gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0);
2179 if (gpio < 0) {
2180 dev_err(dev, "Can't find ac97-sync gpio\n");
2181 return gpio;
2182 }
2183 ret = devm_gpio_request(dev, gpio, "AC97 link sync");
2184 if (ret) {
2185 dev_err(dev, "Failed requesting ac97-sync gpio\n");
2186 return ret;
2187 }
2188 cfg->gpio_sync = gpio;
2189
2190 gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1);
2191 if (gpio < 0) {
2192 dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio);
2193 return gpio;
2194 }
2195 ret = devm_gpio_request(dev, gpio, "AC97 link sdata");
2196 if (ret) {
2197 dev_err(dev, "Failed requesting ac97-sdata gpio\n");
2198 return ret;
2199 }
2200 cfg->gpio_sdata = gpio;
2201
2202 gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2);
2203 if (gpio < 0) {
2204 dev_err(dev, "Can't find ac97-reset gpio\n");
2205 return gpio;
2206 }
2207 ret = devm_gpio_request(dev, gpio, "AC97 link reset");
2208 if (ret) {
2209 dev_err(dev, "Failed requesting ac97-reset gpio\n");
2210 return ret;
2211 }
2212 cfg->gpio_reset = gpio;
2213
2214 return 0;
2215}
2216
2083struct snd_ac97_bus_ops *soc_ac97_ops; 2217struct snd_ac97_bus_ops *soc_ac97_ops;
2084EXPORT_SYMBOL_GPL(soc_ac97_ops); 2218EXPORT_SYMBOL_GPL(soc_ac97_ops);
2085 2219
@@ -2098,6 +2232,35 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops)
2098EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); 2232EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops);
2099 2233
2100/** 2234/**
2235 * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions
2236 *
2237 * This function sets the reset and warm_reset properties of ops and parses
2238 * the device node of pdev to get pinctrl states and gpio numbers to use.
2239 */
2240int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
2241 struct platform_device *pdev)
2242{
2243 struct device *dev = &pdev->dev;
2244 struct snd_ac97_reset_cfg cfg;
2245 int ret;
2246
2247 ret = snd_soc_ac97_parse_pinctl(dev, &cfg);
2248 if (ret)
2249 return ret;
2250
2251 ret = snd_soc_set_ac97_ops(ops);
2252 if (ret)
2253 return ret;
2254
2255 ops->warm_reset = snd_soc_ac97_warm_reset;
2256 ops->reset = snd_soc_ac97_reset;
2257
2258 snd_ac97_rst_cfg = cfg;
2259 return 0;
2260}
2261EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset);
2262
2263/**
2101 * snd_soc_free_ac97_codec - free AC97 codec device 2264 * snd_soc_free_ac97_codec - free AC97 codec device
2102 * @codec: audio codec 2265 * @codec: audio codec
2103 * 2266 *
@@ -2299,6 +2462,22 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
2299 return 0; 2462 return 0;
2300} 2463}
2301 2464
2465struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
2466 const char *name)
2467{
2468 struct snd_card *card = soc_card->snd_card;
2469 struct snd_kcontrol *kctl;
2470
2471 if (unlikely(!name))
2472 return NULL;
2473
2474 list_for_each_entry(kctl, &card->controls, list)
2475 if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name)))
2476 return kctl;
2477 return NULL;
2478}
2479EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
2480
2302/** 2481/**
2303 * snd_soc_add_codec_controls - add an array of controls to a codec. 2482 * snd_soc_add_codec_controls - add an array of controls to a codec.
2304 * Convenience function to add a list of controls. Many codecs were 2483 * Convenience function to add a list of controls. Many codecs were
@@ -2541,59 +2720,6 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
2541EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); 2720EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
2542 2721
2543/** 2722/**
2544 * snd_soc_info_enum_ext - external enumerated single mixer info callback
2545 * @kcontrol: mixer control
2546 * @uinfo: control element information
2547 *
2548 * Callback to provide information about an external enumerated
2549 * single mixer.
2550 *
2551 * Returns 0 for success.
2552 */
2553int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
2554 struct snd_ctl_elem_info *uinfo)
2555{
2556 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2557
2558 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2559 uinfo->count = 1;
2560 uinfo->value.enumerated.items = e->max;
2561
2562 if (uinfo->value.enumerated.item > e->max - 1)
2563 uinfo->value.enumerated.item = e->max - 1;
2564 strcpy(uinfo->value.enumerated.name,
2565 e->texts[uinfo->value.enumerated.item]);
2566 return 0;
2567}
2568EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
2569
2570/**
2571 * snd_soc_info_volsw_ext - external single mixer info callback
2572 * @kcontrol: mixer control
2573 * @uinfo: control element information
2574 *
2575 * Callback to provide information about a single external mixer control.
2576 *
2577 * Returns 0 for success.
2578 */
2579int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
2580 struct snd_ctl_elem_info *uinfo)
2581{
2582 int max = kcontrol->private_value;
2583
2584 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
2585 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2586 else
2587 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2588
2589 uinfo->count = 1;
2590 uinfo->value.integer.min = 0;
2591 uinfo->value.integer.max = max;
2592 return 0;
2593}
2594EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
2595
2596/**
2597 * snd_soc_info_volsw - single mixer info callback 2723 * snd_soc_info_volsw - single mixer info callback
2598 * @kcontrol: mixer control 2724 * @kcontrol: mixer control
2599 * @uinfo: control element information 2725 * @uinfo: control element information
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 4375c9f2b791..d84bd0f167b6 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -47,6 +47,15 @@
47 47
48#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++; 48#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
49 49
50static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
51 struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
52 const char *control,
53 int (*connected)(struct snd_soc_dapm_widget *source,
54 struct snd_soc_dapm_widget *sink));
55static struct snd_soc_dapm_widget *
56snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
57 const struct snd_soc_dapm_widget *widget);
58
50/* dapm power sequences - make this per codec in the future */ 59/* dapm power sequences - make this per codec in the future */
51static int dapm_up_seq[] = { 60static int dapm_up_seq[] = {
52 [snd_soc_dapm_pre] = 0, 61 [snd_soc_dapm_pre] = 0,
@@ -73,16 +82,18 @@ static int dapm_up_seq[] = {
73 [snd_soc_dapm_hp] = 10, 82 [snd_soc_dapm_hp] = 10,
74 [snd_soc_dapm_spk] = 10, 83 [snd_soc_dapm_spk] = 10,
75 [snd_soc_dapm_line] = 10, 84 [snd_soc_dapm_line] = 10,
76 [snd_soc_dapm_post] = 11, 85 [snd_soc_dapm_kcontrol] = 11,
86 [snd_soc_dapm_post] = 12,
77}; 87};
78 88
79static int dapm_down_seq[] = { 89static int dapm_down_seq[] = {
80 [snd_soc_dapm_pre] = 0, 90 [snd_soc_dapm_pre] = 0,
81 [snd_soc_dapm_adc] = 1, 91 [snd_soc_dapm_kcontrol] = 1,
82 [snd_soc_dapm_hp] = 2, 92 [snd_soc_dapm_adc] = 2,
83 [snd_soc_dapm_spk] = 2, 93 [snd_soc_dapm_hp] = 3,
84 [snd_soc_dapm_line] = 2, 94 [snd_soc_dapm_spk] = 3,
85 [snd_soc_dapm_out_drv] = 2, 95 [snd_soc_dapm_line] = 3,
96 [snd_soc_dapm_out_drv] = 3,
86 [snd_soc_dapm_pga] = 4, 97 [snd_soc_dapm_pga] = 4,
87 [snd_soc_dapm_switch] = 5, 98 [snd_soc_dapm_switch] = 5,
88 [snd_soc_dapm_mixer_named_ctl] = 5, 99 [snd_soc_dapm_mixer_named_ctl] = 5,
@@ -174,36 +185,176 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
174 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); 185 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
175} 186}
176 187
177/* get snd_card from DAPM context */ 188struct dapm_kcontrol_data {
178static inline struct snd_card *dapm_get_snd_card( 189 unsigned int value;
179 struct snd_soc_dapm_context *dapm) 190 struct snd_soc_dapm_widget *widget;
191 struct list_head paths;
192 struct snd_soc_dapm_widget_list *wlist;
193};
194
195static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
196 struct snd_kcontrol *kcontrol)
180{ 197{
181 if (dapm->codec) 198 struct dapm_kcontrol_data *data;
182 return dapm->codec->card->snd_card; 199 struct soc_mixer_control *mc;
183 else if (dapm->platform)
184 return dapm->platform->card->snd_card;
185 else
186 BUG();
187 200
188 /* unreachable */ 201 data = kzalloc(sizeof(*data), GFP_KERNEL);
189 return NULL; 202 if (!data) {
203 dev_err(widget->dapm->dev,
204 "ASoC: can't allocate kcontrol data for %s\n",
205 widget->name);
206 return -ENOMEM;
207 }
208
209 INIT_LIST_HEAD(&data->paths);
210
211 switch (widget->id) {
212 case snd_soc_dapm_switch:
213 case snd_soc_dapm_mixer:
214 case snd_soc_dapm_mixer_named_ctl:
215 mc = (struct soc_mixer_control *)kcontrol->private_value;
216
217 if (mc->autodisable) {
218 struct snd_soc_dapm_widget template;
219
220 memset(&template, 0, sizeof(template));
221 template.reg = mc->reg;
222 template.mask = (1 << fls(mc->max)) - 1;
223 template.shift = mc->shift;
224 if (mc->invert)
225 template.off_val = mc->max;
226 else
227 template.off_val = 0;
228 template.on_val = template.off_val;
229 template.id = snd_soc_dapm_kcontrol;
230 template.name = kcontrol->id.name;
231
232 data->widget = snd_soc_dapm_new_control(widget->dapm,
233 &template);
234 if (!data->widget) {
235 kfree(data);
236 return -ENOMEM;
237 }
238 }
239 break;
240 default:
241 break;
242 }
243
244 kcontrol->private_data = data;
245
246 return 0;
190} 247}
191 248
192/* get soc_card from DAPM context */ 249static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
193static inline struct snd_soc_card *dapm_get_soc_card(
194 struct snd_soc_dapm_context *dapm)
195{ 250{
196 if (dapm->codec) 251 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
197 return dapm->codec->card; 252 kfree(data->widget);
198 else if (dapm->platform) 253 kfree(data->wlist);
199 return dapm->platform->card; 254 kfree(data);
255}
256
257static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist(
258 const struct snd_kcontrol *kcontrol)
259{
260 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
261
262 return data->wlist;
263}
264
265static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol,
266 struct snd_soc_dapm_widget *widget)
267{
268 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
269 struct snd_soc_dapm_widget_list *new_wlist;
270 unsigned int n;
271
272 if (data->wlist)
273 n = data->wlist->num_widgets + 1;
200 else 274 else
201 BUG(); 275 n = 1;
202 276
203 /* unreachable */ 277 new_wlist = krealloc(data->wlist,
204 return NULL; 278 sizeof(*new_wlist) + sizeof(widget) * n, GFP_KERNEL);
279 if (!new_wlist)
280 return -ENOMEM;
281
282 new_wlist->widgets[n - 1] = widget;
283 new_wlist->num_widgets = n;
284
285 data->wlist = new_wlist;
286
287 return 0;
288}
289
290static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol,
291 struct snd_soc_dapm_path *path)
292{
293 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
294
295 list_add_tail(&path->list_kcontrol, &data->paths);
296
297 if (data->widget) {
298 snd_soc_dapm_add_path(data->widget->dapm, data->widget,
299 path->source, NULL, NULL);
300 }
301}
302
303static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol)
304{
305 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
306
307 if (!data->widget)
308 return true;
309
310 return data->widget->power;
311}
312
313static struct list_head *dapm_kcontrol_get_path_list(
314 const struct snd_kcontrol *kcontrol)
315{
316 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
317
318 return &data->paths;
319}
320
321#define dapm_kcontrol_for_each_path(path, kcontrol) \
322 list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \
323 list_kcontrol)
324
325static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
326{
327 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
328
329 return data->value;
330}
331
332static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
333 unsigned int value)
334{
335 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
336
337 if (data->value == value)
338 return false;
339
340 if (data->widget)
341 data->widget->on_val = value;
342
343 data->value = value;
344
345 return true;
205} 346}
206 347
348/**
349 * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
350 * @kcontrol: The kcontrol
351 */
352struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol)
353{
354 return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec;
355}
356EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec);
357
207static void dapm_reset(struct snd_soc_card *card) 358static void dapm_reset(struct snd_soc_card *card)
208{ 359{
209 struct snd_soc_dapm_widget *w; 360 struct snd_soc_dapm_widget *w;
@@ -211,6 +362,7 @@ static void dapm_reset(struct snd_soc_card *card)
211 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); 362 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
212 363
213 list_for_each_entry(w, &card->widgets, list) { 364 list_for_each_entry(w, &card->widgets, list) {
365 w->new_power = w->power;
214 w->power_checked = false; 366 w->power_checked = false;
215 w->inputs = -1; 367 w->inputs = -1;
216 w->outputs = -1; 368 w->outputs = -1;
@@ -428,6 +580,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
428 case snd_soc_dapm_spk: 580 case snd_soc_dapm_spk:
429 case snd_soc_dapm_line: 581 case snd_soc_dapm_line:
430 case snd_soc_dapm_dai_link: 582 case snd_soc_dapm_dai_link:
583 case snd_soc_dapm_kcontrol:
431 p->connect = 1; 584 p->connect = 1;
432 break; 585 break;
433 /* does affect routing - dynamically connected */ 586 /* does affect routing - dynamically connected */
@@ -507,17 +660,12 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
507 return 0; 660 return 0;
508} 661}
509 662
510static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
511{
512 kfree(kctl->private_data);
513}
514
515/* 663/*
516 * Determine if a kcontrol is shared. If it is, look it up. If it isn't, 664 * Determine if a kcontrol is shared. If it is, look it up. If it isn't,
517 * create it. Either way, add the widget into the control's widget list 665 * create it. Either way, add the widget into the control's widget list
518 */ 666 */
519static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, 667static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
520 int kci, struct snd_soc_dapm_path *path) 668 int kci)
521{ 669{
522 struct snd_soc_dapm_context *dapm = w->dapm; 670 struct snd_soc_dapm_context *dapm = w->dapm;
523 struct snd_card *card = dapm->card->snd_card; 671 struct snd_card *card = dapm->card->snd_card;
@@ -525,9 +673,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
525 size_t prefix_len; 673 size_t prefix_len;
526 int shared; 674 int shared;
527 struct snd_kcontrol *kcontrol; 675 struct snd_kcontrol *kcontrol;
528 struct snd_soc_dapm_widget_list *wlist;
529 int wlistentries;
530 size_t wlistsize;
531 bool wname_in_long_name, kcname_in_long_name; 676 bool wname_in_long_name, kcname_in_long_name;
532 char *long_name; 677 char *long_name;
533 const char *name; 678 const char *name;
@@ -546,25 +691,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
546 shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci], 691 shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
547 &kcontrol); 692 &kcontrol);
548 693
549 if (kcontrol) {
550 wlist = kcontrol->private_data;
551 wlistentries = wlist->num_widgets + 1;
552 } else {
553 wlist = NULL;
554 wlistentries = 1;
555 }
556
557 wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
558 wlistentries * sizeof(struct snd_soc_dapm_widget *);
559 wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
560 if (wlist == NULL) {
561 dev_err(dapm->dev, "ASoC: can't allocate widget list for %s\n",
562 w->name);
563 return -ENOMEM;
564 }
565 wlist->num_widgets = wlistentries;
566 wlist->widgets[wlistentries - 1] = w;
567
568 if (!kcontrol) { 694 if (!kcontrol) {
569 if (shared) { 695 if (shared) {
570 wname_in_long_name = false; 696 wname_in_long_name = false;
@@ -587,7 +713,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
587 kcname_in_long_name = false; 713 kcname_in_long_name = false;
588 break; 714 break;
589 default: 715 default:
590 kfree(wlist);
591 return -EINVAL; 716 return -EINVAL;
592 } 717 }
593 } 718 }
@@ -602,10 +727,8 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
602 long_name = kasprintf(GFP_KERNEL, "%s %s", 727 long_name = kasprintf(GFP_KERNEL, "%s %s",
603 w->name + prefix_len, 728 w->name + prefix_len,
604 w->kcontrol_news[kci].name); 729 w->kcontrol_news[kci].name);
605 if (long_name == NULL) { 730 if (long_name == NULL)
606 kfree(wlist);
607 return -ENOMEM; 731 return -ENOMEM;
608 }
609 732
610 name = long_name; 733 name = long_name;
611 } else if (wname_in_long_name) { 734 } else if (wname_in_long_name) {
@@ -616,23 +739,33 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
616 name = w->kcontrol_news[kci].name; 739 name = w->kcontrol_news[kci].name;
617 } 740 }
618 741
619 kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, 742 kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name,
620 prefix); 743 prefix);
621 kcontrol->private_free = dapm_kcontrol_free;
622 kfree(long_name); 744 kfree(long_name);
745 if (!kcontrol)
746 return -ENOMEM;
747 kcontrol->private_free = dapm_kcontrol_free;
748
749 ret = dapm_kcontrol_data_alloc(w, kcontrol);
750 if (ret) {
751 snd_ctl_free_one(kcontrol);
752 return ret;
753 }
754
623 ret = snd_ctl_add(card, kcontrol); 755 ret = snd_ctl_add(card, kcontrol);
624 if (ret < 0) { 756 if (ret < 0) {
625 dev_err(dapm->dev, 757 dev_err(dapm->dev,
626 "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", 758 "ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
627 w->name, name, ret); 759 w->name, name, ret);
628 kfree(wlist);
629 return ret; 760 return ret;
630 } 761 }
631 } 762 }
632 763
633 kcontrol->private_data = wlist; 764 ret = dapm_kcontrol_add_widget(kcontrol, w);
765 if (ret)
766 return ret;
767
634 w->kcontrols[kci] = kcontrol; 768 w->kcontrols[kci] = kcontrol;
635 path->kcontrol = kcontrol;
636 769
637 return 0; 770 return 0;
638} 771}
@@ -652,13 +785,15 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
652 continue; 785 continue;
653 786
654 if (w->kcontrols[i]) { 787 if (w->kcontrols[i]) {
655 path->kcontrol = w->kcontrols[i]; 788 dapm_kcontrol_add_path(w->kcontrols[i], path);
656 continue; 789 continue;
657 } 790 }
658 791
659 ret = dapm_create_or_share_mixmux_kcontrol(w, i, path); 792 ret = dapm_create_or_share_mixmux_kcontrol(w, i);
660 if (ret < 0) 793 if (ret < 0)
661 return ret; 794 return ret;
795
796 dapm_kcontrol_add_path(w->kcontrols[i], path);
662 } 797 }
663 } 798 }
664 799
@@ -684,15 +819,12 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
684 return -EINVAL; 819 return -EINVAL;
685 } 820 }
686 821
687 path = list_first_entry(&w->sources, struct snd_soc_dapm_path, 822 ret = dapm_create_or_share_mixmux_kcontrol(w, 0);
688 list_sink);
689
690 ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path);
691 if (ret < 0) 823 if (ret < 0)
692 return ret; 824 return ret;
693 825
694 list_for_each_entry(path, &w->sources, list_sink) 826 list_for_each_entry(path, &w->sources, list_sink)
695 path->kcontrol = w->kcontrols[0]; 827 dapm_kcontrol_add_path(w->kcontrols[0], path);
696 828
697 return 0; 829 return 0;
698} 830}
@@ -813,6 +945,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
813 case snd_soc_dapm_supply: 945 case snd_soc_dapm_supply:
814 case snd_soc_dapm_regulator_supply: 946 case snd_soc_dapm_regulator_supply:
815 case snd_soc_dapm_clock_supply: 947 case snd_soc_dapm_clock_supply:
948 case snd_soc_dapm_kcontrol:
816 return 0; 949 return 0;
817 default: 950 default:
818 break; 951 break;
@@ -908,6 +1041,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
908 case snd_soc_dapm_supply: 1041 case snd_soc_dapm_supply:
909 case snd_soc_dapm_regulator_supply: 1042 case snd_soc_dapm_regulator_supply:
910 case snd_soc_dapm_clock_supply: 1043 case snd_soc_dapm_clock_supply:
1044 case snd_soc_dapm_kcontrol:
911 return 0; 1045 return 0;
912 default: 1046 default:
913 break; 1047 break;
@@ -1062,7 +1196,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
1062 int ret; 1196 int ret;
1063 1197
1064 if (SND_SOC_DAPM_EVENT_ON(event)) { 1198 if (SND_SOC_DAPM_EVENT_ON(event)) {
1065 if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { 1199 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1066 ret = regulator_allow_bypass(w->regulator, false); 1200 ret = regulator_allow_bypass(w->regulator, false);
1067 if (ret != 0) 1201 if (ret != 0)
1068 dev_warn(w->dapm->dev, 1202 dev_warn(w->dapm->dev,
@@ -1072,7 +1206,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
1072 1206
1073 return regulator_enable(w->regulator); 1207 return regulator_enable(w->regulator);
1074 } else { 1208 } else {
1075 if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { 1209 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1076 ret = regulator_allow_bypass(w->regulator, true); 1210 ret = regulator_allow_bypass(w->regulator, true);
1077 if (ret != 0) 1211 if (ret != 0)
1078 dev_warn(w->dapm->dev, 1212 dev_warn(w->dapm->dev,
@@ -1244,10 +1378,9 @@ static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
1244 list_add_tail(&new_widget->power_list, list); 1378 list_add_tail(&new_widget->power_list, list);
1245} 1379}
1246 1380
1247static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, 1381static void dapm_seq_check_event(struct snd_soc_card *card,
1248 struct snd_soc_dapm_widget *w, int event) 1382 struct snd_soc_dapm_widget *w, int event)
1249{ 1383{
1250 struct snd_soc_card *card = dapm->card;
1251 const char *ev_name; 1384 const char *ev_name;
1252 int power, ret; 1385 int power, ret;
1253 1386
@@ -1281,55 +1414,50 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
1281 return; 1414 return;
1282 } 1415 }
1283 1416
1284 if (w->power != power) 1417 if (w->new_power != power)
1285 return; 1418 return;
1286 1419
1287 if (w->event && (w->event_flags & event)) { 1420 if (w->event && (w->event_flags & event)) {
1288 pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n", 1421 pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
1289 w->name, ev_name); 1422 w->name, ev_name);
1290 trace_snd_soc_dapm_widget_event_start(w, event); 1423 trace_snd_soc_dapm_widget_event_start(w, event);
1291 ret = w->event(w, NULL, event); 1424 ret = w->event(w, NULL, event);
1292 trace_snd_soc_dapm_widget_event_done(w, event); 1425 trace_snd_soc_dapm_widget_event_done(w, event);
1293 if (ret < 0) 1426 if (ret < 0)
1294 dev_err(dapm->dev, "ASoC: %s: %s event failed: %d\n", 1427 dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",
1295 ev_name, w->name, ret); 1428 ev_name, w->name, ret);
1296 } 1429 }
1297} 1430}
1298 1431
1299/* Apply the coalesced changes from a DAPM sequence */ 1432/* Apply the coalesced changes from a DAPM sequence */
1300static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, 1433static void dapm_seq_run_coalesced(struct snd_soc_card *card,
1301 struct list_head *pending) 1434 struct list_head *pending)
1302{ 1435{
1303 struct snd_soc_card *card = dapm->card;
1304 struct snd_soc_dapm_widget *w; 1436 struct snd_soc_dapm_widget *w;
1305 int reg, power; 1437 int reg;
1306 unsigned int value = 0; 1438 unsigned int value = 0;
1307 unsigned int mask = 0; 1439 unsigned int mask = 0;
1308 unsigned int cur_mask;
1309 1440
1310 reg = list_first_entry(pending, struct snd_soc_dapm_widget, 1441 reg = list_first_entry(pending, struct snd_soc_dapm_widget,
1311 power_list)->reg; 1442 power_list)->reg;
1312 1443
1313 list_for_each_entry(w, pending, power_list) { 1444 list_for_each_entry(w, pending, power_list) {
1314 cur_mask = 1 << w->shift;
1315 BUG_ON(reg != w->reg); 1445 BUG_ON(reg != w->reg);
1446 w->power = w->new_power;
1316 1447
1317 if (w->invert) 1448 mask |= w->mask << w->shift;
1318 power = !w->power; 1449 if (w->power)
1450 value |= w->on_val << w->shift;
1319 else 1451 else
1320 power = w->power; 1452 value |= w->off_val << w->shift;
1321 1453
1322 mask |= cur_mask; 1454 pop_dbg(w->dapm->dev, card->pop_time,
1323 if (power)
1324 value |= cur_mask;
1325
1326 pop_dbg(dapm->dev, card->pop_time,
1327 "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", 1455 "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
1328 w->name, reg, value, mask); 1456 w->name, reg, value, mask);
1329 1457
1330 /* Check for events */ 1458 /* Check for events */
1331 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU); 1459 dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU);
1332 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD); 1460 dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD);
1333 } 1461 }
1334 1462
1335 if (reg >= 0) { 1463 if (reg >= 0) {
@@ -1339,7 +1467,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
1339 w = list_first_entry(pending, struct snd_soc_dapm_widget, 1467 w = list_first_entry(pending, struct snd_soc_dapm_widget,
1340 power_list); 1468 power_list);
1341 1469
1342 pop_dbg(dapm->dev, card->pop_time, 1470 pop_dbg(w->dapm->dev, card->pop_time,
1343 "pop test : Applying 0x%x/0x%x to %x in %dms\n", 1471 "pop test : Applying 0x%x/0x%x to %x in %dms\n",
1344 value, mask, reg, card->pop_time); 1472 value, mask, reg, card->pop_time);
1345 pop_wait(card->pop_time); 1473 pop_wait(card->pop_time);
@@ -1347,8 +1475,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
1347 } 1475 }
1348 1476
1349 list_for_each_entry(w, pending, power_list) { 1477 list_for_each_entry(w, pending, power_list) {
1350 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU); 1478 dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU);
1351 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD); 1479 dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD);
1352 } 1480 }
1353} 1481}
1354 1482
@@ -1360,8 +1488,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
1360 * Currently anything that requires more than a single write is not 1488 * Currently anything that requires more than a single write is not
1361 * handled. 1489 * handled.
1362 */ 1490 */
1363static void dapm_seq_run(struct snd_soc_dapm_context *dapm, 1491static void dapm_seq_run(struct snd_soc_card *card,
1364 struct list_head *list, int event, bool power_up) 1492 struct list_head *list, int event, bool power_up)
1365{ 1493{
1366 struct snd_soc_dapm_widget *w, *n; 1494 struct snd_soc_dapm_widget *w, *n;
1367 LIST_HEAD(pending); 1495 LIST_HEAD(pending);
@@ -1384,7 +1512,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
1384 if (sort[w->id] != cur_sort || w->reg != cur_reg || 1512 if (sort[w->id] != cur_sort || w->reg != cur_reg ||
1385 w->dapm != cur_dapm || w->subseq != cur_subseq) { 1513 w->dapm != cur_dapm || w->subseq != cur_subseq) {
1386 if (!list_empty(&pending)) 1514 if (!list_empty(&pending))
1387 dapm_seq_run_coalesced(cur_dapm, &pending); 1515 dapm_seq_run_coalesced(card, &pending);
1388 1516
1389 if (cur_dapm && cur_dapm->seq_notifier) { 1517 if (cur_dapm && cur_dapm->seq_notifier) {
1390 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) 1518 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
@@ -1444,7 +1572,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
1444 } 1572 }
1445 1573
1446 if (!list_empty(&pending)) 1574 if (!list_empty(&pending))
1447 dapm_seq_run_coalesced(cur_dapm, &pending); 1575 dapm_seq_run_coalesced(card, &pending);
1448 1576
1449 if (cur_dapm && cur_dapm->seq_notifier) { 1577 if (cur_dapm && cur_dapm->seq_notifier) {
1450 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) 1578 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
@@ -1454,37 +1582,48 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
1454 } 1582 }
1455} 1583}
1456 1584
1457static void dapm_widget_update(struct snd_soc_dapm_context *dapm) 1585static void dapm_widget_update(struct snd_soc_card *card)
1458{ 1586{
1459 struct snd_soc_dapm_update *update = dapm->update; 1587 struct snd_soc_dapm_update *update = card->update;
1460 struct snd_soc_dapm_widget *w; 1588 struct snd_soc_dapm_widget_list *wlist;
1589 struct snd_soc_dapm_widget *w = NULL;
1590 unsigned int wi;
1461 int ret; 1591 int ret;
1462 1592
1463 if (!update) 1593 if (!update || !dapm_kcontrol_is_powered(update->kcontrol))
1464 return; 1594 return;
1465 1595
1466 w = update->widget; 1596 wlist = dapm_kcontrol_get_wlist(update->kcontrol);
1467 1597
1468 if (w->event && 1598 for (wi = 0; wi < wlist->num_widgets; wi++) {
1469 (w->event_flags & SND_SOC_DAPM_PRE_REG)) { 1599 w = wlist->widgets[wi];
1470 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG); 1600
1471 if (ret != 0) 1601 if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
1472 dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n", 1602 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
1473 w->name, ret); 1603 if (ret != 0)
1604 dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
1605 w->name, ret);
1606 }
1474 } 1607 }
1475 1608
1609 if (!w)
1610 return;
1611
1476 ret = soc_widget_update_bits_locked(w, update->reg, update->mask, 1612 ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
1477 update->val); 1613 update->val);
1478 if (ret < 0) 1614 if (ret < 0)
1479 dev_err(dapm->dev, "ASoC: %s DAPM update failed: %d\n", 1615 dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
1480 w->name, ret); 1616 w->name, ret);
1481 1617
1482 if (w->event && 1618 for (wi = 0; wi < wlist->num_widgets; wi++) {
1483 (w->event_flags & SND_SOC_DAPM_POST_REG)) { 1619 w = wlist->widgets[wi];
1484 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG); 1620
1485 if (ret != 0) 1621 if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) {
1486 dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n", 1622 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
1487 w->name, ret); 1623 if (ret != 0)
1624 dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
1625 w->name, ret);
1626 }
1488 } 1627 }
1489} 1628}
1490 1629
@@ -1596,6 +1735,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1596 case snd_soc_dapm_supply: 1735 case snd_soc_dapm_supply:
1597 case snd_soc_dapm_regulator_supply: 1736 case snd_soc_dapm_regulator_supply:
1598 case snd_soc_dapm_clock_supply: 1737 case snd_soc_dapm_clock_supply:
1738 case snd_soc_dapm_kcontrol:
1599 /* Supplies can't affect their outputs, only their inputs */ 1739 /* Supplies can't affect their outputs, only their inputs */
1600 break; 1740 break;
1601 default: 1741 default:
@@ -1612,8 +1752,6 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1612 dapm_seq_insert(w, up_list, true); 1752 dapm_seq_insert(w, up_list, true);
1613 else 1753 else
1614 dapm_seq_insert(w, down_list, false); 1754 dapm_seq_insert(w, down_list, false);
1615
1616 w->power = power;
1617} 1755}
1618 1756
1619static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, 1757static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
@@ -1647,9 +1785,8 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
1647 * o Input pin to Output pin (bypass, sidetone) 1785 * o Input pin to Output pin (bypass, sidetone)
1648 * o DAC to ADC (loopback). 1786 * o DAC to ADC (loopback).
1649 */ 1787 */
1650static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) 1788static int dapm_power_widgets(struct snd_soc_card *card, int event)
1651{ 1789{
1652 struct snd_soc_card *card = dapm->card;
1653 struct snd_soc_dapm_widget *w; 1790 struct snd_soc_dapm_widget *w;
1654 struct snd_soc_dapm_context *d; 1791 struct snd_soc_dapm_context *d;
1655 LIST_HEAD(up_list); 1792 LIST_HEAD(up_list);
@@ -1689,7 +1826,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1689 break; 1826 break;
1690 } 1827 }
1691 1828
1692 if (w->power) { 1829 if (w->new_power) {
1693 d = w->dapm; 1830 d = w->dapm;
1694 1831
1695 /* Supplies and micbiases only bring the 1832 /* Supplies and micbiases only bring the
@@ -1731,29 +1868,29 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1731 trace_snd_soc_dapm_walk_done(card); 1868 trace_snd_soc_dapm_walk_done(card);
1732 1869
1733 /* Run all the bias changes in parallel */ 1870 /* Run all the bias changes in parallel */
1734 list_for_each_entry(d, &dapm->card->dapm_list, list) 1871 list_for_each_entry(d, &card->dapm_list, list)
1735 async_schedule_domain(dapm_pre_sequence_async, d, 1872 async_schedule_domain(dapm_pre_sequence_async, d,
1736 &async_domain); 1873 &async_domain);
1737 async_synchronize_full_domain(&async_domain); 1874 async_synchronize_full_domain(&async_domain);
1738 1875
1739 list_for_each_entry(w, &down_list, power_list) { 1876 list_for_each_entry(w, &down_list, power_list) {
1740 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMD); 1877 dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD);
1741 } 1878 }
1742 1879
1743 list_for_each_entry(w, &up_list, power_list) { 1880 list_for_each_entry(w, &up_list, power_list) {
1744 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMU); 1881 dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU);
1745 } 1882 }
1746 1883
1747 /* Power down widgets first; try to avoid amplifying pops. */ 1884 /* Power down widgets first; try to avoid amplifying pops. */
1748 dapm_seq_run(dapm, &down_list, event, false); 1885 dapm_seq_run(card, &down_list, event, false);
1749 1886
1750 dapm_widget_update(dapm); 1887 dapm_widget_update(card);
1751 1888
1752 /* Now power up. */ 1889 /* Now power up. */
1753 dapm_seq_run(dapm, &up_list, event, true); 1890 dapm_seq_run(card, &up_list, event, true);
1754 1891
1755 /* Run all the bias changes in parallel */ 1892 /* Run all the bias changes in parallel */
1756 list_for_each_entry(d, &dapm->card->dapm_list, list) 1893 list_for_each_entry(d, &card->dapm_list, list)
1757 async_schedule_domain(dapm_post_sequence_async, d, 1894 async_schedule_domain(dapm_post_sequence_async, d,
1758 &async_domain); 1895 &async_domain);
1759 async_synchronize_full_domain(&async_domain); 1896 async_synchronize_full_domain(&async_domain);
@@ -1764,7 +1901,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1764 d->stream_event(d, event); 1901 d->stream_event(d, event);
1765 } 1902 }
1766 1903
1767 pop_dbg(dapm->dev, card->pop_time, 1904 pop_dbg(card->dev, card->pop_time,
1768 "DAPM sequencing finished, waiting %dms\n", card->pop_time); 1905 "DAPM sequencing finished, waiting %dms\n", card->pop_time);
1769 pop_wait(card->pop_time); 1906 pop_wait(card->pop_time);
1770 1907
@@ -1799,8 +1936,8 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1799 1936
1800 if (w->reg >= 0) 1937 if (w->reg >= 0)
1801 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1938 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1802 " - R%d(0x%x) bit %d", 1939 " - R%d(0x%x) mask 0x%x",
1803 w->reg, w->reg, w->shift); 1940 w->reg, w->reg, w->mask << w->shift);
1804 1941
1805 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); 1942 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
1806 1943
@@ -1937,22 +2074,14 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
1937#endif 2074#endif
1938 2075
1939/* test and update the power status of a mux widget */ 2076/* test and update the power status of a mux widget */
1940static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 2077static int soc_dapm_mux_update_power(struct snd_soc_card *card,
1941 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) 2078 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
1942{ 2079{
1943 struct snd_soc_dapm_path *path; 2080 struct snd_soc_dapm_path *path;
1944 int found = 0; 2081 int found = 0;
1945 2082
1946 if (widget->id != snd_soc_dapm_mux &&
1947 widget->id != snd_soc_dapm_virt_mux &&
1948 widget->id != snd_soc_dapm_value_mux)
1949 return -ENODEV;
1950
1951 /* find dapm widget path assoc with kcontrol */ 2083 /* find dapm widget path assoc with kcontrol */
1952 list_for_each_entry(path, &widget->dapm->card->paths, list) { 2084 dapm_kcontrol_for_each_path(path, kcontrol) {
1953 if (path->kcontrol != kcontrol)
1954 continue;
1955
1956 if (!path->name || !e->texts[mux]) 2085 if (!path->name || !e->texts[mux])
1957 continue; 2086 continue;
1958 2087
@@ -1967,73 +2096,68 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1967 "mux disconnection"); 2096 "mux disconnection");
1968 path->connect = 0; /* old connection must be powered down */ 2097 path->connect = 0; /* old connection must be powered down */
1969 } 2098 }
2099 dapm_mark_dirty(path->sink, "mux change");
1970 } 2100 }
1971 2101
1972 if (found) { 2102 if (found)
1973 dapm_mark_dirty(widget, "mux change"); 2103 dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
1974 dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
1975 }
1976 2104
1977 return found; 2105 return found;
1978} 2106}
1979 2107
1980int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 2108int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
1981 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) 2109 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
2110 struct snd_soc_dapm_update *update)
1982{ 2111{
1983 struct snd_soc_card *card = widget->dapm->card; 2112 struct snd_soc_card *card = dapm->card;
1984 int ret; 2113 int ret;
1985 2114
1986 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2115 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1987 ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e); 2116 card->update = update;
2117 ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
2118 card->update = NULL;
1988 mutex_unlock(&card->dapm_mutex); 2119 mutex_unlock(&card->dapm_mutex);
1989 if (ret > 0) 2120 if (ret > 0)
1990 soc_dpcm_runtime_update(widget); 2121 soc_dpcm_runtime_update(card);
1991 return ret; 2122 return ret;
1992} 2123}
1993EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); 2124EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
1994 2125
1995/* test and update the power status of a mixer or switch widget */ 2126/* test and update the power status of a mixer or switch widget */
1996static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 2127static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
1997 struct snd_kcontrol *kcontrol, int connect) 2128 struct snd_kcontrol *kcontrol, int connect)
1998{ 2129{
1999 struct snd_soc_dapm_path *path; 2130 struct snd_soc_dapm_path *path;
2000 int found = 0; 2131 int found = 0;
2001 2132
2002 if (widget->id != snd_soc_dapm_mixer &&
2003 widget->id != snd_soc_dapm_mixer_named_ctl &&
2004 widget->id != snd_soc_dapm_switch)
2005 return -ENODEV;
2006
2007 /* find dapm widget path assoc with kcontrol */ 2133 /* find dapm widget path assoc with kcontrol */
2008 list_for_each_entry(path, &widget->dapm->card->paths, list) { 2134 dapm_kcontrol_for_each_path(path, kcontrol) {
2009 if (path->kcontrol != kcontrol)
2010 continue;
2011
2012 /* found, now check type */
2013 found = 1; 2135 found = 1;
2014 path->connect = connect; 2136 path->connect = connect;
2015 dapm_mark_dirty(path->source, "mixer connection"); 2137 dapm_mark_dirty(path->source, "mixer connection");
2138 dapm_mark_dirty(path->sink, "mixer update");
2016 } 2139 }
2017 2140
2018 if (found) { 2141 if (found)
2019 dapm_mark_dirty(widget, "mixer update"); 2142 dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
2020 dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
2021 }
2022 2143
2023 return found; 2144 return found;
2024} 2145}
2025 2146
2026int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 2147int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
2027 struct snd_kcontrol *kcontrol, int connect) 2148 struct snd_kcontrol *kcontrol, int connect,
2149 struct snd_soc_dapm_update *update)
2028{ 2150{
2029 struct snd_soc_card *card = widget->dapm->card; 2151 struct snd_soc_card *card = dapm->card;
2030 int ret; 2152 int ret;
2031 2153
2032 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2154 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2033 ret = soc_dapm_mixer_update_power(widget, kcontrol, connect); 2155 card->update = update;
2156 ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
2157 card->update = NULL;
2034 mutex_unlock(&card->dapm_mutex); 2158 mutex_unlock(&card->dapm_mutex);
2035 if (ret > 0) 2159 if (ret > 0)
2036 soc_dpcm_runtime_update(widget); 2160 soc_dpcm_runtime_update(card);
2037 return ret; 2161 return ret;
2038} 2162}
2039EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); 2163EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
@@ -2112,6 +2236,7 @@ static void dapm_free_path(struct snd_soc_dapm_path *path)
2112{ 2236{
2113 list_del(&path->list_sink); 2237 list_del(&path->list_sink);
2114 list_del(&path->list_source); 2238 list_del(&path->list_source);
2239 list_del(&path->list_kcontrol);
2115 list_del(&path->list); 2240 list_del(&path->list);
2116 kfree(path); 2241 kfree(path);
2117} 2242}
@@ -2206,70 +2331,20 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
2206 return 0; 2331 return 0;
2207 2332
2208 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2333 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2209 ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); 2334 ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
2210 mutex_unlock(&dapm->card->dapm_mutex); 2335 mutex_unlock(&dapm->card->dapm_mutex);
2211 return ret; 2336 return ret;
2212} 2337}
2213EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 2338EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
2214 2339
2215static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, 2340static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
2216 const struct snd_soc_dapm_route *route) 2341 struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
2342 const char *control,
2343 int (*connected)(struct snd_soc_dapm_widget *source,
2344 struct snd_soc_dapm_widget *sink))
2217{ 2345{
2218 struct snd_soc_dapm_path *path; 2346 struct snd_soc_dapm_path *path;
2219 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 2347 int ret;
2220 struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
2221 const char *sink;
2222 const char *control = route->control;
2223 const char *source;
2224 char prefixed_sink[80];
2225 char prefixed_source[80];
2226 int ret = 0;
2227
2228 if (dapm->codec && dapm->codec->name_prefix) {
2229 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2230 dapm->codec->name_prefix, route->sink);
2231 sink = prefixed_sink;
2232 snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2233 dapm->codec->name_prefix, route->source);
2234 source = prefixed_source;
2235 } else {
2236 sink = route->sink;
2237 source = route->source;
2238 }
2239
2240 /*
2241 * find src and dest widgets over all widgets but favor a widget from
2242 * current DAPM context
2243 */
2244 list_for_each_entry(w, &dapm->card->widgets, list) {
2245 if (!wsink && !(strcmp(w->name, sink))) {
2246 wtsink = w;
2247 if (w->dapm == dapm)
2248 wsink = w;
2249 continue;
2250 }
2251 if (!wsource && !(strcmp(w->name, source))) {
2252 wtsource = w;
2253 if (w->dapm == dapm)
2254 wsource = w;
2255 }
2256 }
2257 /* use widget from another DAPM context if not found from this */
2258 if (!wsink)
2259 wsink = wtsink;
2260 if (!wsource)
2261 wsource = wtsource;
2262
2263 if (wsource == NULL) {
2264 dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
2265 route->source);
2266 return -ENODEV;
2267 }
2268 if (wsink == NULL) {
2269 dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
2270 route->sink);
2271 return -ENODEV;
2272 }
2273 2348
2274 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); 2349 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
2275 if (!path) 2350 if (!path)
@@ -2277,8 +2352,9 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2277 2352
2278 path->source = wsource; 2353 path->source = wsource;
2279 path->sink = wsink; 2354 path->sink = wsink;
2280 path->connected = route->connected; 2355 path->connected = connected;
2281 INIT_LIST_HEAD(&path->list); 2356 INIT_LIST_HEAD(&path->list);
2357 INIT_LIST_HEAD(&path->list_kcontrol);
2282 INIT_LIST_HEAD(&path->list_source); 2358 INIT_LIST_HEAD(&path->list_source);
2283 INIT_LIST_HEAD(&path->list_sink); 2359 INIT_LIST_HEAD(&path->list_sink);
2284 2360
@@ -2328,6 +2404,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2328 case snd_soc_dapm_dai_in: 2404 case snd_soc_dapm_dai_in:
2329 case snd_soc_dapm_dai_out: 2405 case snd_soc_dapm_dai_out:
2330 case snd_soc_dapm_dai_link: 2406 case snd_soc_dapm_dai_link:
2407 case snd_soc_dapm_kcontrol:
2331 list_add(&path->list, &dapm->card->paths); 2408 list_add(&path->list, &dapm->card->paths);
2332 list_add(&path->list_sink, &wsink->sources); 2409 list_add(&path->list_sink, &wsink->sources);
2333 list_add(&path->list_source, &wsource->sinks); 2410 list_add(&path->list_source, &wsource->sinks);
@@ -2363,11 +2440,77 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2363 dapm_mark_dirty(wsink, "Route added"); 2440 dapm_mark_dirty(wsink, "Route added");
2364 2441
2365 return 0; 2442 return 0;
2443err:
2444 kfree(path);
2445 return ret;
2446}
2447
2448static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2449 const struct snd_soc_dapm_route *route)
2450{
2451 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
2452 struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
2453 const char *sink;
2454 const char *source;
2455 char prefixed_sink[80];
2456 char prefixed_source[80];
2457 int ret;
2458
2459 if (dapm->codec && dapm->codec->name_prefix) {
2460 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2461 dapm->codec->name_prefix, route->sink);
2462 sink = prefixed_sink;
2463 snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2464 dapm->codec->name_prefix, route->source);
2465 source = prefixed_source;
2466 } else {
2467 sink = route->sink;
2468 source = route->source;
2469 }
2470
2471 /*
2472 * find src and dest widgets over all widgets but favor a widget from
2473 * current DAPM context
2474 */
2475 list_for_each_entry(w, &dapm->card->widgets, list) {
2476 if (!wsink && !(strcmp(w->name, sink))) {
2477 wtsink = w;
2478 if (w->dapm == dapm)
2479 wsink = w;
2480 continue;
2481 }
2482 if (!wsource && !(strcmp(w->name, source))) {
2483 wtsource = w;
2484 if (w->dapm == dapm)
2485 wsource = w;
2486 }
2487 }
2488 /* use widget from another DAPM context if not found from this */
2489 if (!wsink)
2490 wsink = wtsink;
2491 if (!wsource)
2492 wsource = wtsource;
2493
2494 if (wsource == NULL) {
2495 dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
2496 route->source);
2497 return -ENODEV;
2498 }
2499 if (wsink == NULL) {
2500 dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
2501 route->sink);
2502 return -ENODEV;
2503 }
2366 2504
2505 ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,
2506 route->connected);
2507 if (ret)
2508 goto err;
2509
2510 return 0;
2367err: 2511err:
2368 dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n", 2512 dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
2369 source, control, sink); 2513 source, route->control, sink);
2370 kfree(path);
2371 return ret; 2514 return ret;
2372} 2515}
2373 2516
@@ -2571,12 +2714,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);
2571 */ 2714 */
2572int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) 2715int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2573{ 2716{
2717 struct snd_soc_card *card = dapm->card;
2574 struct snd_soc_dapm_widget *w; 2718 struct snd_soc_dapm_widget *w;
2575 unsigned int val; 2719 unsigned int val;
2576 2720
2577 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); 2721 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2578 2722
2579 list_for_each_entry(w, &dapm->card->widgets, list) 2723 list_for_each_entry(w, &card->widgets, list)
2580 { 2724 {
2581 if (w->new) 2725 if (w->new)
2582 continue; 2726 continue;
@@ -2586,7 +2730,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2586 sizeof(struct snd_kcontrol *), 2730 sizeof(struct snd_kcontrol *),
2587 GFP_KERNEL); 2731 GFP_KERNEL);
2588 if (!w->kcontrols) { 2732 if (!w->kcontrols) {
2589 mutex_unlock(&dapm->card->dapm_mutex); 2733 mutex_unlock(&card->dapm_mutex);
2590 return -ENOMEM; 2734 return -ENOMEM;
2591 } 2735 }
2592 } 2736 }
@@ -2612,12 +2756,9 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2612 2756
2613 /* Read the initial power state from the device */ 2757 /* Read the initial power state from the device */
2614 if (w->reg >= 0) { 2758 if (w->reg >= 0) {
2615 val = soc_widget_read(w, w->reg); 2759 val = soc_widget_read(w, w->reg) >> w->shift;
2616 val &= 1 << w->shift; 2760 val &= w->mask;
2617 if (w->invert) 2761 if (val == w->on_val)
2618 val = !val;
2619
2620 if (val)
2621 w->power = 1; 2762 w->power = 1;
2622 } 2763 }
2623 2764
@@ -2627,8 +2768,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2627 dapm_debugfs_add_widget(w); 2768 dapm_debugfs_add_widget(w);
2628 } 2769 }
2629 2770
2630 dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); 2771 dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
2631 mutex_unlock(&dapm->card->dapm_mutex); 2772 mutex_unlock(&card->dapm_mutex);
2632 return 0; 2773 return 0;
2633} 2774}
2634EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); 2775EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
@@ -2645,8 +2786,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
2645int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, 2786int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
2646 struct snd_ctl_elem_value *ucontrol) 2787 struct snd_ctl_elem_value *ucontrol)
2647{ 2788{
2648 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2789 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2649 struct snd_soc_dapm_widget *widget = wlist->widgets[0]; 2790 struct snd_soc_card *card = codec->card;
2650 struct soc_mixer_control *mc = 2791 struct soc_mixer_control *mc =
2651 (struct soc_mixer_control *)kcontrol->private_value; 2792 (struct soc_mixer_control *)kcontrol->private_value;
2652 unsigned int reg = mc->reg; 2793 unsigned int reg = mc->reg;
@@ -2654,17 +2795,24 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
2654 int max = mc->max; 2795 int max = mc->max;
2655 unsigned int mask = (1 << fls(max)) - 1; 2796 unsigned int mask = (1 << fls(max)) - 1;
2656 unsigned int invert = mc->invert; 2797 unsigned int invert = mc->invert;
2798 unsigned int val;
2657 2799
2658 if (snd_soc_volsw_is_stereo(mc)) 2800 if (snd_soc_volsw_is_stereo(mc))
2659 dev_warn(widget->dapm->dev, 2801 dev_warn(codec->dapm.dev,
2660 "ASoC: Control '%s' is stereo, which is not supported\n", 2802 "ASoC: Control '%s' is stereo, which is not supported\n",
2661 kcontrol->id.name); 2803 kcontrol->id.name);
2662 2804
2663 ucontrol->value.integer.value[0] = 2805 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2664 (snd_soc_read(widget->codec, reg) >> shift) & mask; 2806 if (dapm_kcontrol_is_powered(kcontrol))
2807 val = (snd_soc_read(codec, reg) >> shift) & mask;
2808 else
2809 val = dapm_kcontrol_get_value(kcontrol);
2810 mutex_unlock(&card->dapm_mutex);
2811
2665 if (invert) 2812 if (invert)
2666 ucontrol->value.integer.value[0] = 2813 ucontrol->value.integer.value[0] = max - val;
2667 max - ucontrol->value.integer.value[0]; 2814 else
2815 ucontrol->value.integer.value[0] = val;
2668 2816
2669 return 0; 2817 return 0;
2670} 2818}
@@ -2682,9 +2830,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
2682int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, 2830int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2683 struct snd_ctl_elem_value *ucontrol) 2831 struct snd_ctl_elem_value *ucontrol)
2684{ 2832{
2685 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2833 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2686 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2687 struct snd_soc_codec *codec = widget->codec;
2688 struct snd_soc_card *card = codec->card; 2834 struct snd_soc_card *card = codec->card;
2689 struct soc_mixer_control *mc = 2835 struct soc_mixer_control *mc =
2690 (struct soc_mixer_control *)kcontrol->private_value; 2836 (struct soc_mixer_control *)kcontrol->private_value;
@@ -2696,10 +2842,9 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2696 unsigned int val; 2842 unsigned int val;
2697 int connect, change; 2843 int connect, change;
2698 struct snd_soc_dapm_update update; 2844 struct snd_soc_dapm_update update;
2699 int wi;
2700 2845
2701 if (snd_soc_volsw_is_stereo(mc)) 2846 if (snd_soc_volsw_is_stereo(mc))
2702 dev_warn(widget->dapm->dev, 2847 dev_warn(codec->dapm.dev,
2703 "ASoC: Control '%s' is stereo, which is not supported\n", 2848 "ASoC: Control '%s' is stereo, which is not supported\n",
2704 kcontrol->id.name); 2849 kcontrol->id.name);
2705 2850
@@ -2708,29 +2853,26 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2708 2853
2709 if (invert) 2854 if (invert)
2710 val = max - val; 2855 val = max - val;
2711 mask = mask << shift;
2712 val = val << shift;
2713 2856
2714 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2857 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2715 2858
2716 change = snd_soc_test_bits(widget->codec, reg, mask, val); 2859 dapm_kcontrol_set_value(kcontrol, val);
2717 if (change) {
2718 for (wi = 0; wi < wlist->num_widgets; wi++) {
2719 widget = wlist->widgets[wi];
2720 2860
2721 widget->value = val; 2861 mask = mask << shift;
2862 val = val << shift;
2722 2863
2723 update.kcontrol = kcontrol; 2864 change = snd_soc_test_bits(codec, reg, mask, val);
2724 update.widget = widget; 2865 if (change) {
2725 update.reg = reg; 2866 update.kcontrol = kcontrol;
2726 update.mask = mask; 2867 update.reg = reg;
2727 update.val = val; 2868 update.mask = mask;
2728 widget->dapm->update = &update; 2869 update.val = val;
2729 2870
2730 soc_dapm_mixer_update_power(widget, kcontrol, connect); 2871 card->update = &update;
2731 2872
2732 widget->dapm->update = NULL; 2873 soc_dapm_mixer_update_power(card, kcontrol, connect);
2733 } 2874
2875 card->update = NULL;
2734 } 2876 }
2735 2877
2736 mutex_unlock(&card->dapm_mutex); 2878 mutex_unlock(&card->dapm_mutex);
@@ -2750,12 +2892,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
2750int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, 2892int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
2751 struct snd_ctl_elem_value *ucontrol) 2893 struct snd_ctl_elem_value *ucontrol)
2752{ 2894{
2753 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2895 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2754 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2755 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2896 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2756 unsigned int val; 2897 unsigned int val;
2757 2898
2758 val = snd_soc_read(widget->codec, e->reg); 2899 val = snd_soc_read(codec, e->reg);
2759 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; 2900 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask;
2760 if (e->shift_l != e->shift_r) 2901 if (e->shift_l != e->shift_r)
2761 ucontrol->value.enumerated.item[1] = 2902 ucontrol->value.enumerated.item[1] =
@@ -2777,15 +2918,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
2777int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, 2918int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2778 struct snd_ctl_elem_value *ucontrol) 2919 struct snd_ctl_elem_value *ucontrol)
2779{ 2920{
2780 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2921 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2781 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2782 struct snd_soc_codec *codec = widget->codec;
2783 struct snd_soc_card *card = codec->card; 2922 struct snd_soc_card *card = codec->card;
2784 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2923 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2785 unsigned int val, mux, change; 2924 unsigned int val, mux, change;
2786 unsigned int mask; 2925 unsigned int mask;
2787 struct snd_soc_dapm_update update; 2926 struct snd_soc_dapm_update update;
2788 int wi;
2789 2927
2790 if (ucontrol->value.enumerated.item[0] > e->max - 1) 2928 if (ucontrol->value.enumerated.item[0] > e->max - 1)
2791 return -EINVAL; 2929 return -EINVAL;
@@ -2801,24 +2939,17 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2801 2939
2802 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2940 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2803 2941
2804 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); 2942 change = snd_soc_test_bits(codec, e->reg, mask, val);
2805 if (change) { 2943 if (change) {
2806 for (wi = 0; wi < wlist->num_widgets; wi++) { 2944 update.kcontrol = kcontrol;
2807 widget = wlist->widgets[wi]; 2945 update.reg = e->reg;
2946 update.mask = mask;
2947 update.val = val;
2948 card->update = &update;
2808 2949
2809 widget->value = val; 2950 soc_dapm_mux_update_power(card, kcontrol, mux, e);
2810 2951
2811 update.kcontrol = kcontrol; 2952 card->update = NULL;
2812 update.widget = widget;
2813 update.reg = e->reg;
2814 update.mask = mask;
2815 update.val = val;
2816 widget->dapm->update = &update;
2817
2818 soc_dapm_mux_update_power(widget, kcontrol, mux, e);
2819
2820 widget->dapm->update = NULL;
2821 }
2822 } 2953 }
2823 2954
2824 mutex_unlock(&card->dapm_mutex); 2955 mutex_unlock(&card->dapm_mutex);
@@ -2836,11 +2967,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
2836int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, 2967int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
2837 struct snd_ctl_elem_value *ucontrol) 2968 struct snd_ctl_elem_value *ucontrol)
2838{ 2969{
2839 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2970 ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol);
2840 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2841
2842 ucontrol->value.enumerated.item[0] = widget->value;
2843
2844 return 0; 2971 return 0;
2845} 2972}
2846EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); 2973EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
@@ -2855,30 +2982,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
2855int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, 2982int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
2856 struct snd_ctl_elem_value *ucontrol) 2983 struct snd_ctl_elem_value *ucontrol)
2857{ 2984{
2858 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2985 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2859 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2860 struct snd_soc_codec *codec = widget->codec;
2861 struct snd_soc_card *card = codec->card; 2986 struct snd_soc_card *card = codec->card;
2987 unsigned int value;
2862 struct soc_enum *e = 2988 struct soc_enum *e =
2863 (struct soc_enum *)kcontrol->private_value; 2989 (struct soc_enum *)kcontrol->private_value;
2864 int change; 2990 int change;
2865 int wi;
2866 2991
2867 if (ucontrol->value.enumerated.item[0] >= e->max) 2992 if (ucontrol->value.enumerated.item[0] >= e->max)
2868 return -EINVAL; 2993 return -EINVAL;
2869 2994
2870 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2995 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2871 2996
2872 change = widget->value != ucontrol->value.enumerated.item[0]; 2997 value = ucontrol->value.enumerated.item[0];
2873 if (change) { 2998 change = dapm_kcontrol_set_value(kcontrol, value);
2874 for (wi = 0; wi < wlist->num_widgets; wi++) { 2999 if (change)
2875 widget = wlist->widgets[wi]; 3000 soc_dapm_mux_update_power(card, kcontrol, value, e);
2876
2877 widget->value = ucontrol->value.enumerated.item[0];
2878
2879 soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
2880 }
2881 }
2882 3001
2883 mutex_unlock(&card->dapm_mutex); 3002 mutex_unlock(&card->dapm_mutex);
2884 return change; 3003 return change;
@@ -2901,12 +3020,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
2901int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, 3020int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
2902 struct snd_ctl_elem_value *ucontrol) 3021 struct snd_ctl_elem_value *ucontrol)
2903{ 3022{
2904 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 3023 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2905 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2906 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 3024 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2907 unsigned int reg_val, val, mux; 3025 unsigned int reg_val, val, mux;
2908 3026
2909 reg_val = snd_soc_read(widget->codec, e->reg); 3027 reg_val = snd_soc_read(codec, e->reg);
2910 val = (reg_val >> e->shift_l) & e->mask; 3028 val = (reg_val >> e->shift_l) & e->mask;
2911 for (mux = 0; mux < e->max; mux++) { 3029 for (mux = 0; mux < e->max; mux++) {
2912 if (val == e->values[mux]) 3030 if (val == e->values[mux])
@@ -2942,15 +3060,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
2942int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, 3060int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2943 struct snd_ctl_elem_value *ucontrol) 3061 struct snd_ctl_elem_value *ucontrol)
2944{ 3062{
2945 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 3063 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2946 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2947 struct snd_soc_codec *codec = widget->codec;
2948 struct snd_soc_card *card = codec->card; 3064 struct snd_soc_card *card = codec->card;
2949 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 3065 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2950 unsigned int val, mux, change; 3066 unsigned int val, mux, change;
2951 unsigned int mask; 3067 unsigned int mask;
2952 struct snd_soc_dapm_update update; 3068 struct snd_soc_dapm_update update;
2953 int wi;
2954 3069
2955 if (ucontrol->value.enumerated.item[0] > e->max - 1) 3070 if (ucontrol->value.enumerated.item[0] > e->max - 1)
2956 return -EINVAL; 3071 return -EINVAL;
@@ -2966,24 +3081,17 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2966 3081
2967 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 3082 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2968 3083
2969 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); 3084 change = snd_soc_test_bits(codec, e->reg, mask, val);
2970 if (change) { 3085 if (change) {
2971 for (wi = 0; wi < wlist->num_widgets; wi++) { 3086 update.kcontrol = kcontrol;
2972 widget = wlist->widgets[wi]; 3087 update.reg = e->reg;
2973 3088 update.mask = mask;
2974 widget->value = val; 3089 update.val = val;
3090 card->update = &update;
2975 3091
2976 update.kcontrol = kcontrol; 3092 soc_dapm_mux_update_power(card, kcontrol, mux, e);
2977 update.widget = widget;
2978 update.reg = e->reg;
2979 update.mask = mask;
2980 update.val = val;
2981 widget->dapm->update = &update;
2982 3093
2983 soc_dapm_mux_update_power(widget, kcontrol, mux, e); 3094 card->update = NULL;
2984
2985 widget->dapm->update = NULL;
2986 }
2987 } 3095 }
2988 3096
2989 mutex_unlock(&card->dapm_mutex); 3097 mutex_unlock(&card->dapm_mutex);
@@ -3080,7 +3188,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3080 return NULL; 3188 return NULL;
3081 } 3189 }
3082 3190
3083 if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { 3191 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
3084 ret = regulator_allow_bypass(w->regulator, true); 3192 ret = regulator_allow_bypass(w->regulator, true);
3085 if (ret != 0) 3193 if (ret != 0)
3086 dev_warn(w->dapm->dev, 3194 dev_warn(w->dapm->dev,
@@ -3127,16 +3235,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3127 case snd_soc_dapm_value_mux: 3235 case snd_soc_dapm_value_mux:
3128 w->power_check = dapm_generic_check_power; 3236 w->power_check = dapm_generic_check_power;
3129 break; 3237 break;
3130 case snd_soc_dapm_adc:
3131 case snd_soc_dapm_aif_out:
3132 case snd_soc_dapm_dai_out: 3238 case snd_soc_dapm_dai_out:
3133 w->power_check = dapm_adc_check_power; 3239 w->power_check = dapm_adc_check_power;
3134 break; 3240 break;
3135 case snd_soc_dapm_dac:
3136 case snd_soc_dapm_aif_in:
3137 case snd_soc_dapm_dai_in: 3241 case snd_soc_dapm_dai_in:
3138 w->power_check = dapm_dac_check_power; 3242 w->power_check = dapm_dac_check_power;
3139 break; 3243 break;
3244 case snd_soc_dapm_adc:
3245 case snd_soc_dapm_aif_out:
3246 case snd_soc_dapm_dac:
3247 case snd_soc_dapm_aif_in:
3140 case snd_soc_dapm_pga: 3248 case snd_soc_dapm_pga:
3141 case snd_soc_dapm_out_drv: 3249 case snd_soc_dapm_out_drv:
3142 case snd_soc_dapm_input: 3250 case snd_soc_dapm_input:
@@ -3152,6 +3260,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3152 case snd_soc_dapm_supply: 3260 case snd_soc_dapm_supply:
3153 case snd_soc_dapm_regulator_supply: 3261 case snd_soc_dapm_regulator_supply:
3154 case snd_soc_dapm_clock_supply: 3262 case snd_soc_dapm_clock_supply:
3263 case snd_soc_dapm_kcontrol:
3155 w->power_check = dapm_supply_check_power; 3264 w->power_check = dapm_supply_check_power;
3156 break; 3265 break;
3157 default: 3266 default:
@@ -3416,9 +3525,6 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
3416{ 3525{
3417 struct snd_soc_dapm_widget *dai_w, *w; 3526 struct snd_soc_dapm_widget *dai_w, *w;
3418 struct snd_soc_dai *dai; 3527 struct snd_soc_dai *dai;
3419 struct snd_soc_dapm_route r;
3420
3421 memset(&r, 0, sizeof(r));
3422 3528
3423 /* For each DAI widget... */ 3529 /* For each DAI widget... */
3424 list_for_each_entry(dai_w, &card->widgets, list) { 3530 list_for_each_entry(dai_w, &card->widgets, list) {
@@ -3445,29 +3551,27 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
3445 break; 3551 break;
3446 } 3552 }
3447 3553
3448 if (!w->sname) 3554 if (!w->sname || !strstr(w->sname, dai_w->name))
3449 continue; 3555 continue;
3450 3556
3451 if (dai->driver->playback.stream_name && 3557 if (dai->driver->playback.stream_name &&
3452 strstr(w->sname, 3558 strstr(w->sname,
3453 dai->driver->playback.stream_name)) { 3559 dai->driver->playback.stream_name)) {
3454 r.source = dai->playback_widget->name;
3455 r.sink = w->name;
3456 dev_dbg(dai->dev, "%s -> %s\n", 3560 dev_dbg(dai->dev, "%s -> %s\n",
3457 r.source, r.sink); 3561 dai->playback_widget->name, w->name);
3458 3562
3459 snd_soc_dapm_add_route(w->dapm, &r); 3563 snd_soc_dapm_add_path(w->dapm,
3564 dai->playback_widget, w, NULL, NULL);
3460 } 3565 }
3461 3566
3462 if (dai->driver->capture.stream_name && 3567 if (dai->driver->capture.stream_name &&
3463 strstr(w->sname, 3568 strstr(w->sname,
3464 dai->driver->capture.stream_name)) { 3569 dai->driver->capture.stream_name)) {
3465 r.source = w->name;
3466 r.sink = dai->capture_widget->name;
3467 dev_dbg(dai->dev, "%s -> %s\n", 3570 dev_dbg(dai->dev, "%s -> %s\n",
3468 r.source, r.sink); 3571 w->name, dai->capture_widget->name);
3469 3572
3470 snd_soc_dapm_add_route(w->dapm, &r); 3573 snd_soc_dapm_add_path(w->dapm, w,
3574 dai->capture_widget, NULL, NULL);
3471 } 3575 }
3472 } 3576 }
3473 } 3577 }
@@ -3529,7 +3633,7 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
3529 } 3633 }
3530 } 3634 }
3531 3635
3532 dapm_power_widgets(&rtd->card->dapm, event); 3636 dapm_power_widgets(rtd->card, event);
3533} 3637}
3534 3638
3535/** 3639/**
@@ -3798,7 +3902,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
3798 if (dapm->bias_level == SND_SOC_BIAS_ON) 3902 if (dapm->bias_level == SND_SOC_BIAS_ON)
3799 snd_soc_dapm_set_bias_level(dapm, 3903 snd_soc_dapm_set_bias_level(dapm,
3800 SND_SOC_BIAS_PREPARE); 3904 SND_SOC_BIAS_PREPARE);
3801 dapm_seq_run(dapm, &down_list, 0, false); 3905 dapm_seq_run(card, &down_list, 0, false);
3802 if (dapm->bias_level == SND_SOC_BIAS_PREPARE) 3906 if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
3803 snd_soc_dapm_set_bias_level(dapm, 3907 snd_soc_dapm_set_bias_level(dapm,
3804 SND_SOC_BIAS_STANDBY); 3908 SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 0bb5cccd7766..7aa26b5178aa 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -263,7 +263,7 @@ static irqreturn_t gpio_handler(int irq, void *data)
263 if (device_may_wakeup(dev)) 263 if (device_may_wakeup(dev))
264 pm_wakeup_event(dev, gpio->debounce_time + 50); 264 pm_wakeup_event(dev, gpio->debounce_time + 50);
265 265
266 schedule_delayed_work(&gpio->work, 266 queue_delayed_work(system_power_efficient_wq, &gpio->work,
267 msecs_to_jiffies(gpio->debounce_time)); 267 msecs_to_jiffies(gpio->debounce_time));
268 268
269 return IRQ_HANDLED; 269 return IRQ_HANDLED;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index b6c640332a17..fb70fbe26862 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -411,8 +411,9 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
411 } else { 411 } else {
412 /* start delayed pop wq here for playback streams */ 412 /* start delayed pop wq here for playback streams */
413 rtd->pop_wait = 1; 413 rtd->pop_wait = 1;
414 schedule_delayed_work(&rtd->delayed_work, 414 queue_delayed_work(system_power_efficient_wq,
415 msecs_to_jiffies(rtd->pmdown_time)); 415 &rtd->delayed_work,
416 msecs_to_jiffies(rtd->pmdown_time));
416 } 417 }
417 } else { 418 } else {
418 /* capture streams can be powered down now */ 419 /* capture streams can be powered down now */
@@ -1832,18 +1833,10 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
1832/* Called by DAPM mixer/mux changes to update audio routing between PCMs and 1833/* Called by DAPM mixer/mux changes to update audio routing between PCMs and
1833 * any DAI links. 1834 * any DAI links.
1834 */ 1835 */
1835int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget) 1836int soc_dpcm_runtime_update(struct snd_soc_card *card)
1836{ 1837{
1837 struct snd_soc_card *card;
1838 int i, old, new, paths; 1838 int i, old, new, paths;
1839 1839
1840 if (widget->codec)
1841 card = widget->codec->card;
1842 else if (widget->platform)
1843 card = widget->platform->card;
1844 else
1845 return -EINVAL;
1846
1847 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 1840 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
1848 for (i = 0; i < card->num_rtd; i++) { 1841 for (i = 0; i < card->num_rtd; i++) {
1849 struct snd_soc_dapm_widget_list *list; 1842 struct snd_soc_dapm_widget_list *list;
diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig
index 3567d73b218e..0a53053495f3 100644
--- a/sound/soc/spear/Kconfig
+++ b/sound/soc/spear/Kconfig
@@ -1,6 +1,6 @@
1config SND_SPEAR_SOC 1config SND_SPEAR_SOC
2 tristate 2 tristate
3 select SND_SOC_DMAENGINE_PCM 3 select SND_DMAENGINE_PCM
4 4
5config SND_SPEAR_SPDIF_OUT 5config SND_SPEAR_SPDIF_OUT
6 tristate 6 tristate
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 995b120c2cd0..8fc653ca3ab4 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -1,8 +1,8 @@
1config SND_SOC_TEGRA 1config SND_SOC_TEGRA
2 tristate "SoC Audio for the Tegra System-on-Chip" 2 tristate "SoC Audio for the Tegra System-on-Chip"
3 depends on ARCH_TEGRA && TEGRA20_APB_DMA 3 depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
4 select REGMAP_MMIO 4 select REGMAP_MMIO
5 select SND_SOC_GENERIC_DMAENGINE_PCM if TEGRA20_APB_DMA 5 select SND_SOC_GENERIC_DMAENGINE_PCM
6 help 6 help
7 Say Y or M here if you want support for SoC audio on Tegra. 7 Say Y or M here if you want support for SoC audio on Tegra.
8 8
@@ -61,7 +61,7 @@ config SND_SOC_TEGRA30_I2S
61 61
62config SND_SOC_TEGRA_RT5640 62config SND_SOC_TEGRA_RT5640
63 tristate "SoC Audio support for Tegra boards using an RT5640 codec" 63 tristate "SoC Audio support for Tegra boards using an RT5640 codec"
64 depends on SND_SOC_TEGRA && I2C 64 depends on SND_SOC_TEGRA && I2C && GPIOLIB
65 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC 65 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
66 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC 66 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
67 select SND_SOC_RT5640 67 select SND_SOC_RT5640
@@ -71,7 +71,7 @@ config SND_SOC_TEGRA_RT5640
71 71
72config SND_SOC_TEGRA_WM8753 72config SND_SOC_TEGRA_WM8753
73 tristate "SoC Audio support for Tegra boards using a WM8753 codec" 73 tristate "SoC Audio support for Tegra boards using a WM8753 codec"
74 depends on SND_SOC_TEGRA && I2C 74 depends on SND_SOC_TEGRA && I2C && GPIOLIB
75 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC 75 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
76 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC 76 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
77 select SND_SOC_WM8753 77 select SND_SOC_WM8753
@@ -81,7 +81,7 @@ config SND_SOC_TEGRA_WM8753
81 81
82config SND_SOC_TEGRA_WM8903 82config SND_SOC_TEGRA_WM8903
83 tristate "SoC Audio support for Tegra boards using a WM8903 codec" 83 tristate "SoC Audio support for Tegra boards using a WM8903 codec"
84 depends on SND_SOC_TEGRA && I2C 84 depends on SND_SOC_TEGRA && I2C && GPIOLIB
85 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC 85 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
86 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC 86 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
87 select SND_SOC_WM8903 87 select SND_SOC_WM8903
@@ -92,7 +92,7 @@ config SND_SOC_TEGRA_WM8903
92 92
93config SND_SOC_TEGRA_WM9712 93config SND_SOC_TEGRA_WM9712
94 tristate "SoC Audio support for Tegra boards using a WM9712 codec" 94 tristate "SoC Audio support for Tegra boards using a WM9712 codec"
95 depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC 95 depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC && GPIOLIB
96 select SND_SOC_TEGRA20_AC97 96 select SND_SOC_TEGRA20_AC97
97 select SND_SOC_WM9712 97 select SND_SOC_WM9712
98 help 98 help
@@ -110,7 +110,7 @@ config SND_SOC_TEGRA_TRIMSLICE
110 110
111config SND_SOC_TEGRA_ALC5632 111config SND_SOC_TEGRA_ALC5632
112 tristate "SoC Audio support for Tegra boards using an ALC5632 codec" 112 tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
113 depends on SND_SOC_TEGRA && I2C 113 depends on SND_SOC_TEGRA && I2C && GPIOLIB
114 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC 114 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
115 select SND_SOC_ALC5632 115 select SND_SOC_ALC5632
116 help 116 help
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
index 6c486625321b..ae27bcd586d2 100644
--- a/sound/soc/tegra/tegra20_ac97.c
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -334,12 +334,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
334 } 334 }
335 335
336 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 336 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
337 if (!mem) {
338 dev_err(&pdev->dev, "No memory resource\n");
339 ret = -ENODEV;
340 goto err_clk_put;
341 }
342
343 regs = devm_ioremap_resource(&pdev->dev, mem); 337 regs = devm_ioremap_resource(&pdev->dev, mem);
344 if (IS_ERR(regs)) { 338 if (IS_ERR(regs)) {
345 ret = PTR_ERR(regs); 339 ret = PTR_ERR(regs);
@@ -432,8 +426,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
432 426
433 return 0; 427 return 0;
434 428
435err_unregister_pcm:
436 tegra_pcm_platform_unregister(&pdev->dev);
437err_unregister_component: 429err_unregister_component:
438 snd_soc_unregister_component(&pdev->dev); 430 snd_soc_unregister_component(&pdev->dev);
439err_asoc_utils_fini: 431err_asoc_utils_fini:
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 48d05d9e1002..c61ea3a1030f 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -13,8 +13,6 @@
13 * published by the Free Software Foundation. 13 * published by the Free Software Foundation.
14 */ 14 */
15 15
16#include <asm/mach-types.h>
17
18#include <linux/module.h> 16#include <linux/module.h>
19#include <linux/platform_device.h> 17#include <linux/platform_device.h>
20#include <linux/slab.h> 18#include <linux/slab.h>
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index 08794f915a94..4511c5a875ec 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -99,6 +99,7 @@ static struct snd_soc_jack_gpio tegra_rt5640_hp_jack_gpio = {
99static const struct snd_soc_dapm_widget tegra_rt5640_dapm_widgets[] = { 99static const struct snd_soc_dapm_widget tegra_rt5640_dapm_widgets[] = {
100 SND_SOC_DAPM_HP("Headphones", NULL), 100 SND_SOC_DAPM_HP("Headphones", NULL),
101 SND_SOC_DAPM_SPK("Speakers", NULL), 101 SND_SOC_DAPM_SPK("Speakers", NULL),
102 SND_SOC_DAPM_MIC("Mic Jack", NULL),
102}; 103};
103 104
104static const struct snd_kcontrol_new tegra_rt5640_controls[] = { 105static const struct snd_kcontrol_new tegra_rt5640_controls[] = {
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index f87fc53e9b8c..8e774d1a243c 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -28,8 +28,6 @@
28 * 28 *
29 */ 29 */
30 30
31#include <asm/mach-types.h>
32
33#include <linux/module.h> 31#include <linux/module.h>
34#include <linux/platform_device.h> 32#include <linux/platform_device.h>
35#include <linux/slab.h> 33#include <linux/slab.h>
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 05c68aab5cf0..734bfcd21148 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -24,8 +24,6 @@
24 * 24 *
25 */ 25 */
26 26
27#include <asm/mach-types.h>
28
29#include <linux/module.h> 27#include <linux/module.h>
30#include <linux/of.h> 28#include <linux/of.h>
31#include <linux/platform_device.h> 29#include <linux/platform_device.h>
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index 4bcce8a3cded..e0305a148568 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -184,9 +184,6 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
184 if (irq < 0) 184 if (irq < 0)
185 return irq; 185 return irq;
186 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 186 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
187 if (!r)
188 return -EBUSY;
189
190 drvdata->base = devm_ioremap_resource(&pdev->dev, r); 187 drvdata->base = devm_ioremap_resource(&pdev->dev, r);
191 if (IS_ERR(drvdata->base)) 188 if (IS_ERR(drvdata->base))
192 return PTR_ERR(drvdata->base); 189 return PTR_ERR(drvdata->base);
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c
index 8f5cd00a6e46..178d1bad6259 100644
--- a/sound/soc/ux500/mop500.c
+++ b/sound/soc/ux500/mop500.c
@@ -52,6 +52,7 @@ static struct snd_soc_dai_link mop500_dai_links[] = {
52 52
53static struct snd_soc_card mop500_card = { 53static struct snd_soc_card mop500_card = {
54 .name = "MOP500-card", 54 .name = "MOP500-card",
55 .owner = THIS_MODULE,
55 .probe = NULL, 56 .probe = NULL,
56 .dai_link = mop500_dai_links, 57 .dai_link = mop500_dai_links,
57 .num_links = ARRAY_SIZE(mop500_dai_links), 58 .num_links = ARRAY_SIZE(mop500_dai_links),