aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/samsung-i2s.txt22
-rw-r--r--arch/arm/boot/dts/exynos4.dtsi9
-rw-r--r--arch/arm/boot/dts/exynos4412-odroid-common.dtsi27
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidu3.dts8
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidx2.dts8
-rw-r--r--include/dt-bindings/sound/samsung-i2s.h8
-rw-r--r--sound/soc/codecs/Kconfig2
-rw-r--r--sound/soc/codecs/rt5670.c1
-rw-r--r--sound/soc/codecs/rt5677.c3
-rw-r--r--sound/soc/omap/rx51.c8
-rw-r--r--sound/soc/samsung/Kconfig15
-rw-r--r--sound/soc/samsung/Makefile2
-rw-r--r--sound/soc/samsung/goni_wm8994.c289
-rw-r--r--sound/soc/samsung/i2s.c362
-rw-r--r--sound/soc/samsung/jive_wm8750.c18
-rw-r--r--sound/soc/samsung/odroidx2_max98090.c6
-rw-r--r--sound/soc/samsung/smdk_wm8580.c5
-rw-r--r--sound/soc/sh/dma-sh7760.c6
-rw-r--r--sound/soc/sh/fsi.c6
-rw-r--r--sound/soc/sh/siu_pcm.c1
20 files changed, 306 insertions, 500 deletions
diff --git a/Documentation/devicetree/bindings/sound/samsung-i2s.txt b/Documentation/devicetree/bindings/sound/samsung-i2s.txt
index d188296bb6ec..09e0e18591ae 100644
--- a/Documentation/devicetree/bindings/sound/samsung-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/samsung-i2s.txt
@@ -33,6 +33,25 @@ Required SoC Specific Properties:
33 "iis" is the i2s bus clock and i2s_opclk0, i2s_opclk1 are sources of the root 33 "iis" is the i2s bus clock and i2s_opclk0, i2s_opclk1 are sources of the root
34 clk. i2s0 has internal mux to select the source of root clk and i2s1 and i2s2 34 clk. i2s0 has internal mux to select the source of root clk and i2s1 and i2s2
35 doesn't have any such mux. 35 doesn't have any such mux.
36- #clock-cells: should be 1, this property must be present if the I2S device
37 is a clock provider in terms of the common clock bindings, described in
38 ../clock/clock-bindings.txt.
39- clock-output-names: from the common clock bindings, names of the CDCLK
40 I2S output clocks, suggested values are "i2s_cdclk0", "i2s_cdclk1",
41 "i2s_cdclk3" for the I2S0, I2S1, I2S2 devices recpectively.
42
43There are following clocks available at the I2S device nodes:
44 CLK_I2S_CDCLK - the CDCLK (CODECLKO) gate clock,
45 CLK_I2S_RCLK_PSR - the RCLK prescaler divider clock (corresponding to the
46 IISPSR register),
47 CLK_I2S_RCLK_SRC - the RCLKSRC mux clock (corresponding to RCLKSRC bit in
48 IISMOD register).
49
50Refer to the SoC datasheet for availability of the above clocks.
51The CLK_I2S_RCLK_PSR and CLK_I2S_RCLK_SRC clocks are usually only available
52in the IIS Multi Audio Interface (I2S0).
53Note: Old DTs may not have the #clock-cells, clock-output-names properties
54and then not use the I2S node as a clock supplier.
36 55
37Optional SoC Specific Properties: 56Optional SoC Specific Properties:
38 57
@@ -41,6 +60,7 @@ Optional SoC Specific Properties:
41- pinctrl-0: Should specify pin control groups used for this controller. 60- pinctrl-0: Should specify pin control groups used for this controller.
42- pinctrl-names: Should contain only one value - "default". 61- pinctrl-names: Should contain only one value - "default".
43 62
63
44Example: 64Example:
45 65
46i2s0: i2s@03830000 { 66i2s0: i2s@03830000 {
@@ -54,6 +74,8 @@ i2s0: i2s@03830000 {
54 <&clock_audss EXYNOS_I2S_BUS>, 74 <&clock_audss EXYNOS_I2S_BUS>,
55 <&clock_audss EXYNOS_SCLK_I2S>; 75 <&clock_audss EXYNOS_SCLK_I2S>;
56 clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; 76 clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
77 #clock-cells;
78 clock-output-names = "i2s_cdclk0";
57 samsung,idma-addr = <0x03000000>; 79 samsung,idma-addr = <0x03000000>;
58 pinctrl-names = "default"; 80 pinctrl-names = "default";
59 pinctrl-0 = <&i2s0_bus>; 81 pinctrl-0 = <&i2s0_bus>;
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 24ff27049ce0..cb6001085f1a 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -61,9 +61,12 @@
61 reg = <0x03830000 0x100>; 61 reg = <0x03830000 0x100>;
62 clocks = <&clock_audss EXYNOS_I2S_BUS>; 62 clocks = <&clock_audss EXYNOS_I2S_BUS>;
63 clock-names = "iis"; 63 clock-names = "iis";
64 #clock-cells = <1>;
65 clock-output-names = "i2s_cdclk0";
64 dmas = <&pdma0 12>, <&pdma0 11>, <&pdma0 10>; 66 dmas = <&pdma0 12>, <&pdma0 11>, <&pdma0 10>;
65 dma-names = "tx", "rx", "tx-sec"; 67 dma-names = "tx", "rx", "tx-sec";
66 samsung,idma-addr = <0x03000000>; 68 samsung,idma-addr = <0x03000000>;
69 #sound-dai-cells = <1>;
67 status = "disabled"; 70 status = "disabled";
68 }; 71 };
69 72
@@ -372,8 +375,11 @@
372 reg = <0x13960000 0x100>; 375 reg = <0x13960000 0x100>;
373 clocks = <&clock CLK_I2S1>; 376 clocks = <&clock CLK_I2S1>;
374 clock-names = "iis"; 377 clock-names = "iis";
378 #clock-cells = <1>;
379 clock-output-names = "i2s_cdclk1";
375 dmas = <&pdma1 12>, <&pdma1 11>; 380 dmas = <&pdma1 12>, <&pdma1 11>;
376 dma-names = "tx", "rx"; 381 dma-names = "tx", "rx";
382 #sound-dai-cells = <1>;
377 status = "disabled"; 383 status = "disabled";
378 }; 384 };
379 385
@@ -382,8 +388,11 @@
382 reg = <0x13970000 0x100>; 388 reg = <0x13970000 0x100>;
383 clocks = <&clock CLK_I2S2>; 389 clocks = <&clock CLK_I2S2>;
384 clock-names = "iis"; 390 clock-names = "iis";
391 #clock-cells = <1>;
392 clock-output-names = "i2s_cdclk2";
385 dmas = <&pdma0 14>, <&pdma0 13>; 393 dmas = <&pdma0 14>, <&pdma0 13>;
386 dma-names = "tx", "rx"; 394 dma-names = "tx", "rx";
395 #sound-dai-cells = <1>;
387 status = "disabled"; 396 status = "disabled";
388 }; 397 };
389 398
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index 3fbf588682b9..abd63366298a 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -7,6 +7,7 @@
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8*/ 8*/
9 9
10#include <dt-bindings/sound/samsung-i2s.h>
10#include <dt-bindings/input/input.h> 11#include <dt-bindings/input/input.h>
11#include "exynos4412.dtsi" 12#include "exynos4412.dtsi"
12 13
@@ -37,14 +38,13 @@
37 pinctrl-names = "default"; 38 pinctrl-names = "default";
38 status = "okay"; 39 status = "okay";
39 clocks = <&clock_audss EXYNOS_I2S_BUS>, 40 clocks = <&clock_audss EXYNOS_I2S_BUS>,
40 <&clock_audss EXYNOS_DOUT_AUD_BUS>; 41 <&clock_audss EXYNOS_DOUT_AUD_BUS>,
41 clock-names = "iis", "i2s_opclk0"; 42 <&clock_audss EXYNOS_SCLK_I2S>;
43 clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
42 }; 44 };
43 45
44 sound: sound { 46 sound: sound {
45 compatible = "samsung,odroidx2-audio"; 47 compatible = "simple-audio-card";
46 samsung,i2s-controller = <&i2s0>;
47 samsung,audio-codec = <&max98090>;
48 assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>, 48 assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>,
49 <&clock_audss EXYNOS_MOUT_I2S>, 49 <&clock_audss EXYNOS_MOUT_I2S>,
50 <&clock_audss EXYNOS_DOUT_SRP>, 50 <&clock_audss EXYNOS_DOUT_SRP>,
@@ -55,6 +55,20 @@
55 <0>, 55 <0>,
56 <192000000>, 56 <192000000>,
57 <19200000>; 57 <19200000>;
58
59 simple-audio-card,format = "i2s";
60 simple-audio-card,bitclock-master = <&link0_codec>;
61 simple-audio-card,frame-master = <&link0_codec>;
62
63 simple-audio-card,cpu {
64 sound-dai = <&i2s0 0>;
65 system-clock-frequency = <19200000>;
66 };
67
68 link0_codec: simple-audio-card,codec {
69 sound-dai = <&max98090>;
70 clocks = <&i2s0 CLK_I2S_CDCLK>;
71 };
58 }; 72 };
59 73
60 mmc@12550000 { 74 mmc@12550000 {
@@ -373,6 +387,9 @@
373 reg = <0x10>; 387 reg = <0x10>;
374 interrupt-parent = <&gpx0>; 388 interrupt-parent = <&gpx0>;
375 interrupts = <0 0>; 389 interrupts = <0 0>;
390 clocks = <&i2s0 CLK_I2S_CDCLK>;
391 clock-names = "mclk";
392 #sound-dai-cells = <0>;
376 }; 393 };
377 }; 394 };
378 395
diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts
index c8a64be55d07..44684e57ead1 100644
--- a/arch/arm/boot/dts/exynos4412-odroidu3.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts
@@ -49,9 +49,11 @@
49}; 49};
50 50
51&sound { 51&sound {
52 compatible = "samsung,odroidu3-audio"; 52 simple-audio-card,name = "Odroid-U3";
53 samsung,model = "Odroid-U3"; 53 simple-audio-card,widgets =
54 samsung,audio-routing = 54 "Headphone", "Headphone Jack",
55 "Speakers", "Speakers";
56 simple-audio-card,routing =
55 "Headphone Jack", "HPL", 57 "Headphone Jack", "HPL",
56 "Headphone Jack", "HPR", 58 "Headphone Jack", "HPR",
57 "Headphone Jack", "MICBIAS", 59 "Headphone Jack", "MICBIAS",
diff --git a/arch/arm/boot/dts/exynos4412-odroidx2.dts b/arch/arm/boot/dts/exynos4412-odroidx2.dts
index 96b43f4497cc..6e33678562ae 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx2.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx2.dts
@@ -23,8 +23,12 @@
23}; 23};
24 24
25&sound { 25&sound {
26 samsung,model = "Odroid-X2"; 26 simple-audio-card,name = "Odroid-X2";
27 samsung,audio-routing = 27 simple-audio-card,widgets =
28 "Headphone", "Headphone Jack",
29 "Microphone", "Mic Jack",
30 "Microphone", "DMIC";
31 simple-audio-card,routing =
28 "Headphone Jack", "HPL", 32 "Headphone Jack", "HPL",
29 "Headphone Jack", "HPR", 33 "Headphone Jack", "HPR",
30 "IN1", "Mic Jack", 34 "IN1", "Mic Jack",
diff --git a/include/dt-bindings/sound/samsung-i2s.h b/include/dt-bindings/sound/samsung-i2s.h
new file mode 100644
index 000000000000..0c69818d530c
--- /dev/null
+++ b/include/dt-bindings/sound/samsung-i2s.h
@@ -0,0 +1,8 @@
1#ifndef _DT_BINDINGS_SAMSUNG_I2S_H
2#define _DT_BINDINGS_SAMSUNG_I2S_H
3
4#define CLK_I2S_CDCLK 0
5#define CLK_I2S_RCLK_SRC 1
6#define CLK_I2S_RCLK_PSR 2
7
8#endif /* _DT_BINDINGS_SAMSUNG_I2S_H */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 6ecac1e4428e..1471fad19cfa 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -529,7 +529,7 @@ config SND_SOC_RT5677
529 529
530config SND_SOC_RT5677_SPI 530config SND_SOC_RT5677_SPI
531 tristate 531 tristate
532 default SND_SOC_RT5677 532 default SND_SOC_RT5677 && SPI
533 533
534#Freescale sgtl5000 codec 534#Freescale sgtl5000 codec
535config SND_SOC_SGTL5000 535config SND_SOC_SGTL5000
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index 7b3d6b5992f1..e1a4a45c57e2 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -2616,6 +2616,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5670 = {
2616static const struct regmap_config rt5670_regmap = { 2616static const struct regmap_config rt5670_regmap = {
2617 .reg_bits = 8, 2617 .reg_bits = 8,
2618 .val_bits = 16, 2618 .val_bits = 16,
2619 .use_single_rw = true,
2619 .max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) * 2620 .max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) *
2620 RT5670_PR_SPACING), 2621 RT5670_PR_SPACING),
2621 .volatile_reg = rt5670_volatile_register, 2622 .volatile_reg = rt5670_volatile_register,
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index 26fc538f03b1..5d0bb8748dd1 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -702,6 +702,9 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
702 static bool activity; 702 static bool activity;
703 int ret; 703 int ret;
704 704
705 if (!IS_ENABLED(CONFIG_SND_SOC_RT5677_SPI))
706 return -ENXIO;
707
705 if (on && !activity) { 708 if (on && !activity) {
706 activity = true; 709 activity = true;
707 710
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 04896d6252a2..7f299357c2d2 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -250,14 +250,14 @@ static const struct snd_soc_dapm_route audio_map[] = {
250 {"FM Transmitter", NULL, "LLOUT"}, 250 {"FM Transmitter", NULL, "LLOUT"},
251 {"FM Transmitter", NULL, "RLOUT"}, 251 {"FM Transmitter", NULL, "RLOUT"},
252 252
253 {"DMic Rate 64", NULL, "Mic Bias"}, 253 {"DMic Rate 64", NULL, "DMic"},
254 {"Mic Bias", NULL, "DMic"}, 254 {"DMic", NULL, "Mic Bias"},
255 255
256 {"b LINE2R", NULL, "MONO_LOUT"}, 256 {"b LINE2R", NULL, "MONO_LOUT"},
257 {"Earphone", NULL, "b HPLOUT"}, 257 {"Earphone", NULL, "b HPLOUT"},
258 258
259 {"LINE1L", NULL, "b Mic Bias"}, 259 {"LINE1L", NULL, "HS Mic"},
260 {"b Mic Bias", NULL, "HS Mic"} 260 {"HS Mic", NULL, "b Mic Bias"},
261}; 261};
262 262
263static const char * const spk_function[] = {"Off", "On"}; 263static const char * const spk_function[] = {"Off", "On"};
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index fc67f97f19f6..3cebf6ca03df 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -54,7 +54,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750
54config SND_SOC_SAMSUNG_SMDK_WM8580 54config SND_SOC_SAMSUNG_SMDK_WM8580
55 tristate "SoC I2S Audio support for WM8580 on SMDK" 55 tristate "SoC I2S Audio support for WM8580 on SMDK"
56 depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) 56 depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
57 depends on REGMAP_I2C 57 depends on I2C
58 select SND_SOC_WM8580 58 select SND_SOC_WM8580
59 select SND_SAMSUNG_I2S 59 select SND_SAMSUNG_I2S
60 help 60 help
@@ -146,17 +146,6 @@ config SND_SOC_SMARTQ
146 select SND_SAMSUNG_I2S 146 select SND_SAMSUNG_I2S
147 select SND_SOC_WM8750 147 select SND_SOC_WM8750
148 148
149config SND_SOC_GONI_AQUILA_WM8994
150 tristate "SoC I2S Audio support for AQUILA/GONI - WM8994"
151 depends on SND_SOC_SAMSUNG && (MACH_GONI || MACH_AQUILA)
152 depends on I2C=y
153 select SND_SAMSUNG_I2S
154 select MFD_WM8994
155 select SND_SOC_WM8994
156 help
157 Say Y if you want to add support for SoC audio on goni or aquila
158 with the WM8994.
159
160config SND_SOC_SAMSUNG_SMDK_SPDIF 149config SND_SOC_SAMSUNG_SMDK_SPDIF
161 tristate "SoC S/PDIF Audio support for SMDK" 150 tristate "SoC S/PDIF Audio support for SMDK"
162 depends on SND_SOC_SAMSUNG 151 depends on SND_SOC_SAMSUNG
@@ -167,7 +156,7 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF
167config SND_SOC_SMDK_WM8580_PCM 156config SND_SOC_SMDK_WM8580_PCM
168 tristate "SoC PCM Audio support for WM8580 on SMDK" 157 tristate "SoC PCM Audio support for WM8580 on SMDK"
169 depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110) 158 depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110)
170 depends on REGMAP_I2C 159 depends on I2C
171 select SND_SOC_WM8580 160 select SND_SOC_WM8580
172 select SND_SAMSUNG_PCM 161 select SND_SAMSUNG_PCM
173 help 162 help
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 31e3dba7e3b5..052fe71be518 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -35,7 +35,6 @@ snd-soc-smdk-wm8994-objs := smdk_wm8994.o
35snd-soc-snow-objs := snow.o 35snd-soc-snow-objs := snow.o
36snd-soc-smdk-wm9713-objs := smdk_wm9713.o 36snd-soc-smdk-wm9713-objs := smdk_wm9713.o
37snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o 37snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
38snd-soc-goni-wm8994-objs := goni_wm8994.o
39snd-soc-smdk-spdif-objs := smdk_spdif.o 38snd-soc-smdk-spdif-objs := smdk_spdif.o
40snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o 39snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o
41snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o 40snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o
@@ -63,7 +62,6 @@ obj-$(CONFIG_SND_SOC_SNOW) += snd-soc-snow.o
63obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM9713) += snd-soc-smdk-wm9713.o 62obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM9713) += snd-soc-smdk-wm9713.o
64obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o 63obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o
65obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o 64obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o
66obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o
67obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o 65obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o
68obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o 66obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o
69obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o 67obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c
deleted file mode 100644
index fad56b9e7369..000000000000
--- a/sound/soc/samsung/goni_wm8994.c
+++ /dev/null
@@ -1,289 +0,0 @@
1/*
2 * goni_wm8994.c
3 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <sound/soc.h>
16#include <sound/jack.h>
17
18#include <asm/mach-types.h>
19#include <mach/gpio-samsung.h>
20
21#include "../codecs/wm8994.h"
22
23#define MACHINE_NAME 0
24#define CPU_VOICE_DAI 1
25
26static const char *aquila_str[] = {
27 [MACHINE_NAME] = "aquila",
28 [CPU_VOICE_DAI] = "aquila-voice-dai",
29};
30
31static struct snd_soc_card goni;
32static struct platform_device *goni_snd_device;
33
34/* 3.5 pie jack */
35static struct snd_soc_jack jack;
36
37/* 3.5 pie jack detection DAPM pins */
38static struct snd_soc_jack_pin jack_pins[] = {
39 {
40 .pin = "Headset Mic",
41 .mask = SND_JACK_MICROPHONE,
42 }, {
43 .pin = "Headset Stereophone",
44 .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL |
45 SND_JACK_AVOUT,
46 },
47};
48
49/* 3.5 pie jack detection gpios */
50static struct snd_soc_jack_gpio jack_gpios[] = {
51 {
52 .gpio = S5PV210_GPH0(6),
53 .name = "DET_3.5",
54 .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL |
55 SND_JACK_AVOUT,
56 .debounce_time = 200,
57 },
58};
59
60static const struct snd_soc_dapm_widget goni_dapm_widgets[] = {
61 SND_SOC_DAPM_SPK("Ext Left Spk", NULL),
62 SND_SOC_DAPM_SPK("Ext Right Spk", NULL),
63 SND_SOC_DAPM_SPK("Ext Rcv", NULL),
64 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
65 SND_SOC_DAPM_MIC("Headset Mic", NULL),
66 SND_SOC_DAPM_MIC("Main Mic", NULL),
67 SND_SOC_DAPM_MIC("2nd Mic", NULL),
68 SND_SOC_DAPM_LINE("Radio In", NULL),
69};
70
71static const struct snd_soc_dapm_route goni_dapm_routes[] = {
72 {"Ext Left Spk", NULL, "SPKOUTLP"},
73 {"Ext Left Spk", NULL, "SPKOUTLN"},
74
75 {"Ext Right Spk", NULL, "SPKOUTRP"},
76 {"Ext Right Spk", NULL, "SPKOUTRN"},
77
78 {"Ext Rcv", NULL, "HPOUT2N"},
79 {"Ext Rcv", NULL, "HPOUT2P"},
80
81 {"Headset Stereophone", NULL, "HPOUT1L"},
82 {"Headset Stereophone", NULL, "HPOUT1R"},
83
84 {"IN1RN", NULL, "Headset Mic"},
85 {"IN1RP", NULL, "Headset Mic"},
86
87 {"IN1RN", NULL, "2nd Mic"},
88 {"IN1RP", NULL, "2nd Mic"},
89
90 {"IN1LN", NULL, "Main Mic"},
91 {"IN1LP", NULL, "Main Mic"},
92
93 {"IN2LN", NULL, "Radio In"},
94 {"IN2RN", NULL, "Radio In"},
95};
96
97static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
98{
99 struct snd_soc_codec *codec = rtd->codec;
100 struct snd_soc_dapm_context *dapm = &codec->dapm;
101 int ret;
102
103 /* set endpoints to not connected */
104 snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
105 snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
106 snd_soc_dapm_nc_pin(dapm, "LINEOUT1N");
107 snd_soc_dapm_nc_pin(dapm, "LINEOUT1P");
108 snd_soc_dapm_nc_pin(dapm, "LINEOUT2N");
109 snd_soc_dapm_nc_pin(dapm, "LINEOUT2P");
110
111 if (machine_is_aquila()) {
112 snd_soc_dapm_nc_pin(dapm, "SPKOUTRN");
113 snd_soc_dapm_nc_pin(dapm, "SPKOUTRP");
114 }
115
116 /* Headset jack detection */
117 ret = snd_soc_jack_new(codec, "Headset Jack",
118 SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
119 &jack);
120 if (ret)
121 return ret;
122
123 ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
124 if (ret)
125 return ret;
126
127 ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
128 if (ret)
129 return ret;
130
131 return 0;
132}
133
134static int goni_hifi_hw_params(struct snd_pcm_substream *substream,
135 struct snd_pcm_hw_params *params)
136{
137 struct snd_soc_pcm_runtime *rtd = substream->private_data;
138 struct snd_soc_dai *codec_dai = rtd->codec_dai;
139 unsigned int pll_out = 24000000;
140 int ret = 0;
141
142 /* set the codec FLL */
143 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
144 params_rate(params) * 256);
145 if (ret < 0)
146 return ret;
147
148 /* set the codec system clock */
149 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
150 params_rate(params) * 256, SND_SOC_CLOCK_IN);
151 if (ret < 0)
152 return ret;
153
154 return 0;
155}
156
157static struct snd_soc_ops goni_hifi_ops = {
158 .hw_params = goni_hifi_hw_params,
159};
160
161static int goni_voice_hw_params(struct snd_pcm_substream *substream,
162 struct snd_pcm_hw_params *params)
163{
164 struct snd_soc_pcm_runtime *rtd = substream->private_data;
165 struct snd_soc_dai *codec_dai = rtd->codec_dai;
166 unsigned int pll_out = 24000000;
167 int ret = 0;
168
169 if (params_rate(params) != 8000)
170 return -EINVAL;
171
172 /* set the codec FLL */
173 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
174 params_rate(params) * 256);
175 if (ret < 0)
176 return ret;
177
178 /* set the codec system clock */
179 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
180 params_rate(params) * 256, SND_SOC_CLOCK_IN);
181 if (ret < 0)
182 return ret;
183
184 return 0;
185}
186
187static struct snd_soc_dai_driver voice_dai = {
188 .name = "goni-voice-dai",
189 .id = 0,
190 .playback = {
191 .channels_min = 1,
192 .channels_max = 2,
193 .rates = SNDRV_PCM_RATE_8000,
194 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
195 .capture = {
196 .channels_min = 1,
197 .channels_max = 2,
198 .rates = SNDRV_PCM_RATE_8000,
199 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
200};
201
202static const struct snd_soc_component_driver voice_component = {
203 .name = "goni-voice",
204};
205
206static struct snd_soc_ops goni_voice_ops = {
207 .hw_params = goni_voice_hw_params,
208};
209
210static struct snd_soc_dai_link goni_dai[] = {
211{
212 .name = "WM8994",
213 .stream_name = "WM8994 HiFi",
214 .cpu_dai_name = "samsung-i2s.0",
215 .codec_dai_name = "wm8994-aif1",
216 .platform_name = "samsung-i2s.0",
217 .codec_name = "wm8994-codec.0-001a",
218 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
219 SND_SOC_DAIFMT_CBM_CFM,
220 .init = goni_wm8994_init,
221 .ops = &goni_hifi_ops,
222}, {
223 .name = "WM8994 Voice",
224 .stream_name = "Voice",
225 .cpu_dai_name = "goni-voice-dai",
226 .codec_dai_name = "wm8994-aif2",
227 .codec_name = "wm8994-codec.0-001a",
228 .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_IB_IF |
229 SND_SOC_DAIFMT_CBM_CFM,
230 .ops = &goni_voice_ops,
231},
232};
233
234static struct snd_soc_card goni = {
235 .name = "goni",
236 .owner = THIS_MODULE,
237 .dai_link = goni_dai,
238 .num_links = ARRAY_SIZE(goni_dai),
239
240 .dapm_widgets = goni_dapm_widgets,
241 .num_dapm_widgets = ARRAY_SIZE(goni_dapm_widgets),
242 .dapm_routes = goni_dapm_routes,
243 .num_dapm_routes = ARRAY_SIZE(goni_dapm_routes),
244};
245
246static int __init goni_init(void)
247{
248 int ret;
249
250 if (machine_is_aquila()) {
251 voice_dai.name = aquila_str[CPU_VOICE_DAI];
252 goni_dai[1].cpu_dai_name = aquila_str[CPU_VOICE_DAI];
253 goni.name = aquila_str[MACHINE_NAME];
254 } else if (!machine_is_goni())
255 return -ENODEV;
256
257 goni_snd_device = platform_device_alloc("soc-audio", -1);
258 if (!goni_snd_device)
259 return -ENOMEM;
260
261 /* register voice DAI here */
262 ret = devm_snd_soc_register_component(&goni_snd_device->dev,
263 &voice_component, &voice_dai, 1);
264 if (ret) {
265 platform_device_put(goni_snd_device);
266 return ret;
267 }
268
269 platform_set_drvdata(goni_snd_device, &goni);
270 ret = platform_device_add(goni_snd_device);
271
272 if (ret)
273 platform_device_put(goni_snd_device);
274
275 return ret;
276}
277
278static void __exit goni_exit(void)
279{
280 platform_device_unregister(goni_snd_device);
281}
282
283module_init(goni_init);
284module_exit(goni_exit);
285
286/* Module information */
287MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)");
288MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
289MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index b5a80c528d86..b92ab40d2be6 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -10,9 +10,11 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <dt-bindings/sound/samsung-i2s.h>
13#include <linux/delay.h> 14#include <linux/delay.h>
14#include <linux/slab.h> 15#include <linux/slab.h>
15#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/clk-provider.h>
16#include <linux/io.h> 18#include <linux/io.h>
17#include <linux/module.h> 19#include <linux/module.h>
18#include <linux/of.h> 20#include <linux/of.h>
@@ -59,10 +61,8 @@ struct samsung_i2s_dai_data {
59struct i2s_dai { 61struct i2s_dai {
60 /* Platform device for this DAI */ 62 /* Platform device for this DAI */
61 struct platform_device *pdev; 63 struct platform_device *pdev;
62 /* IOREMAP'd SFRs */ 64 /* Memory mapped SFR region */
63 void __iomem *addr; 65 void __iomem *addr;
64 /* Physical base address of SFRs */
65 u32 base;
66 /* Rate of RCLK source clock */ 66 /* Rate of RCLK source clock */
67 unsigned long rclk_srcrate; 67 unsigned long rclk_srcrate;
68 /* Frame Clock */ 68 /* Frame Clock */
@@ -83,8 +83,6 @@ struct i2s_dai {
83#define DAI_OPENED (1 << 0) /* Dai is opened */ 83#define DAI_OPENED (1 << 0) /* Dai is opened */
84#define DAI_MANAGER (1 << 1) /* Dai is the manager */ 84#define DAI_MANAGER (1 << 1) /* Dai is the manager */
85 unsigned mode; 85 unsigned mode;
86 /* CDCLK pin direction: 0 - input, 1 - output */
87 unsigned int cdclk_out:1;
88 /* Driver for this DAI */ 86 /* Driver for this DAI */
89 struct snd_soc_dai_driver i2s_dai_drv; 87 struct snd_soc_dai_driver i2s_dai_drv;
90 /* DMA parameters */ 88 /* DMA parameters */
@@ -95,8 +93,15 @@ struct i2s_dai {
95 u32 suspend_i2smod; 93 u32 suspend_i2smod;
96 u32 suspend_i2scon; 94 u32 suspend_i2scon;
97 u32 suspend_i2spsr; 95 u32 suspend_i2spsr;
98 unsigned long gpios[7]; /* i2s gpio line numbers */
99 const struct samsung_i2s_variant_regs *variant_regs; 96 const struct samsung_i2s_variant_regs *variant_regs;
97
98 /* Spinlock protecting access to the device's registers */
99 spinlock_t spinlock;
100 spinlock_t *lock;
101
102 /* Below fields are only valid if this is the primary FIFO */
103 struct clk *clk_table[3];
104 struct clk_onecell_data clk_data;
100}; 105};
101 106
102/* Lock for cross i/f checks */ 107/* Lock for cross i/f checks */
@@ -133,10 +138,16 @@ static inline bool tx_active(struct i2s_dai *i2s)
133 return active ? true : false; 138 return active ? true : false;
134} 139}
135 140
141/* Return pointer to the other DAI */
142static inline struct i2s_dai *get_other_dai(struct i2s_dai *i2s)
143{
144 return i2s->pri_dai ? : i2s->sec_dai;
145}
146
136/* If the other interface of the controller is transmitting data */ 147/* If the other interface of the controller is transmitting data */
137static inline bool other_tx_active(struct i2s_dai *i2s) 148static inline bool other_tx_active(struct i2s_dai *i2s)
138{ 149{
139 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 150 struct i2s_dai *other = get_other_dai(i2s);
140 151
141 return tx_active(other); 152 return tx_active(other);
142} 153}
@@ -163,7 +174,7 @@ static inline bool rx_active(struct i2s_dai *i2s)
163/* If the other interface of the controller is receiving data */ 174/* If the other interface of the controller is receiving data */
164static inline bool other_rx_active(struct i2s_dai *i2s) 175static inline bool other_rx_active(struct i2s_dai *i2s)
165{ 176{
166 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 177 struct i2s_dai *other = get_other_dai(i2s);
167 178
168 return rx_active(other); 179 return rx_active(other);
169} 180}
@@ -464,18 +475,23 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
464 int clk_id, unsigned int rfs, int dir) 475 int clk_id, unsigned int rfs, int dir)
465{ 476{
466 struct i2s_dai *i2s = to_info(dai); 477 struct i2s_dai *i2s = to_info(dai);
467 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 478 struct i2s_dai *other = get_other_dai(i2s);
468 u32 mod = readl(i2s->addr + I2SMOD);
469 const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; 479 const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs;
470 unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off; 480 unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off;
471 unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; 481 unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;
482 u32 mod, mask, val = 0;
483
484 spin_lock(i2s->lock);
485 mod = readl(i2s->addr + I2SMOD);
486 spin_unlock(i2s->lock);
472 487
473 switch (clk_id) { 488 switch (clk_id) {
474 case SAMSUNG_I2S_OPCLK: 489 case SAMSUNG_I2S_OPCLK:
475 mod &= ~MOD_OPCLK_MASK; 490 mask = MOD_OPCLK_MASK;
476 mod |= dir; 491 val = dir;
477 break; 492 break;
478 case SAMSUNG_I2S_CDCLK: 493 case SAMSUNG_I2S_CDCLK:
494 mask = 1 << i2s_regs->cdclkcon_off;
479 /* Shouldn't matter in GATING(CLOCK_IN) mode */ 495 /* Shouldn't matter in GATING(CLOCK_IN) mode */
480 if (dir == SND_SOC_CLOCK_IN) 496 if (dir == SND_SOC_CLOCK_IN)
481 rfs = 0; 497 rfs = 0;
@@ -492,15 +508,15 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
492 } 508 }
493 509
494 if (dir == SND_SOC_CLOCK_IN) 510 if (dir == SND_SOC_CLOCK_IN)
495 mod |= 1 << i2s_regs->cdclkcon_off; 511 val = 1 << i2s_regs->cdclkcon_off;
496 else
497 mod &= ~(1 << i2s_regs->cdclkcon_off);
498 512
499 i2s->rfs = rfs; 513 i2s->rfs = rfs;
500 break; 514 break;
501 515
502 case SAMSUNG_I2S_RCLKSRC_0: /* clock corrsponding to IISMOD[10] := 0 */ 516 case SAMSUNG_I2S_RCLKSRC_0: /* clock corrsponding to IISMOD[10] := 0 */
503 case SAMSUNG_I2S_RCLKSRC_1: /* clock corrsponding to IISMOD[10] := 1 */ 517 case SAMSUNG_I2S_RCLKSRC_1: /* clock corrsponding to IISMOD[10] := 1 */
518 mask = 1 << i2s_regs->rclksrc_off;
519
504 if ((i2s->quirks & QUIRK_NO_MUXPSR) 520 if ((i2s->quirks & QUIRK_NO_MUXPSR)
505 || (clk_id == SAMSUNG_I2S_RCLKSRC_0)) 521 || (clk_id == SAMSUNG_I2S_RCLKSRC_0))
506 clk_id = 0; 522 clk_id = 0;
@@ -550,18 +566,19 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
550 return 0; 566 return 0;
551 } 567 }
552 568
553 if (clk_id == 0) 569 if (clk_id == 1)
554 mod &= ~(1 << i2s_regs->rclksrc_off); 570 val = 1 << i2s_regs->rclksrc_off;
555 else
556 mod |= 1 << i2s_regs->rclksrc_off;
557
558 break; 571 break;
559 default: 572 default:
560 dev_err(&i2s->pdev->dev, "We don't serve that!\n"); 573 dev_err(&i2s->pdev->dev, "We don't serve that!\n");
561 return -EINVAL; 574 return -EINVAL;
562 } 575 }
563 576
577 spin_lock(i2s->lock);
578 mod = readl(i2s->addr + I2SMOD);
579 mod = (mod & ~mask) | val;
564 writel(mod, i2s->addr + I2SMOD); 580 writel(mod, i2s->addr + I2SMOD);
581 spin_unlock(i2s->lock);
565 582
566 return 0; 583 return 0;
567} 584}
@@ -570,9 +587,8 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
570 unsigned int fmt) 587 unsigned int fmt)
571{ 588{
572 struct i2s_dai *i2s = to_info(dai); 589 struct i2s_dai *i2s = to_info(dai);
573 u32 mod = readl(i2s->addr + I2SMOD);
574 int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave; 590 int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave;
575 u32 tmp = 0; 591 u32 mod, tmp = 0;
576 592
577 lrp_shift = i2s->variant_regs->lrp_off; 593 lrp_shift = i2s->variant_regs->lrp_off;
578 sdf_shift = i2s->variant_regs->sdf_off; 594 sdf_shift = i2s->variant_regs->sdf_off;
@@ -632,12 +648,15 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
632 return -EINVAL; 648 return -EINVAL;
633 } 649 }
634 650
651 spin_lock(i2s->lock);
652 mod = readl(i2s->addr + I2SMOD);
635 /* 653 /*
636 * Don't change the I2S mode if any controller is active on this 654 * Don't change the I2S mode if any controller is active on this
637 * channel. 655 * channel.
638 */ 656 */
639 if (any_active(i2s) && 657 if (any_active(i2s) &&
640 ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) { 658 ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) {
659 spin_unlock(i2s->lock);
641 dev_err(&i2s->pdev->dev, 660 dev_err(&i2s->pdev->dev,
642 "%s:%d Other DAI busy\n", __func__, __LINE__); 661 "%s:%d Other DAI busy\n", __func__, __LINE__);
643 return -EAGAIN; 662 return -EAGAIN;
@@ -646,6 +665,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
646 mod &= ~(sdf_mask | lrp_rlow | mod_slave); 665 mod &= ~(sdf_mask | lrp_rlow | mod_slave);
647 mod |= tmp; 666 mod |= tmp;
648 writel(mod, i2s->addr + I2SMOD); 667 writel(mod, i2s->addr + I2SMOD);
668 spin_unlock(i2s->lock);
649 669
650 return 0; 670 return 0;
651} 671}
@@ -654,16 +674,16 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
654 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 674 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
655{ 675{
656 struct i2s_dai *i2s = to_info(dai); 676 struct i2s_dai *i2s = to_info(dai);
657 u32 mod = readl(i2s->addr + I2SMOD); 677 u32 mod, mask = 0, val = 0;
658 678
659 if (!is_secondary(i2s)) 679 if (!is_secondary(i2s))
660 mod &= ~(MOD_DC2_EN | MOD_DC1_EN); 680 mask |= (MOD_DC2_EN | MOD_DC1_EN);
661 681
662 switch (params_channels(params)) { 682 switch (params_channels(params)) {
663 case 6: 683 case 6:
664 mod |= MOD_DC2_EN; 684 val |= MOD_DC2_EN;
665 case 4: 685 case 4:
666 mod |= MOD_DC1_EN; 686 val |= MOD_DC1_EN;
667 break; 687 break;
668 case 2: 688 case 2:
669 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 689 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -685,44 +705,49 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
685 } 705 }
686 706
687 if (is_secondary(i2s)) 707 if (is_secondary(i2s))
688 mod &= ~MOD_BLCS_MASK; 708 mask |= MOD_BLCS_MASK;
689 else 709 else
690 mod &= ~MOD_BLCP_MASK; 710 mask |= MOD_BLCP_MASK;
691 711
692 if (is_manager(i2s)) 712 if (is_manager(i2s))
693 mod &= ~MOD_BLC_MASK; 713 mask |= MOD_BLC_MASK;
694 714
695 switch (params_width(params)) { 715 switch (params_width(params)) {
696 case 8: 716 case 8:
697 if (is_secondary(i2s)) 717 if (is_secondary(i2s))
698 mod |= MOD_BLCS_8BIT; 718 val |= MOD_BLCS_8BIT;
699 else 719 else
700 mod |= MOD_BLCP_8BIT; 720 val |= MOD_BLCP_8BIT;
701 if (is_manager(i2s)) 721 if (is_manager(i2s))
702 mod |= MOD_BLC_8BIT; 722 val |= MOD_BLC_8BIT;
703 break; 723 break;
704 case 16: 724 case 16:
705 if (is_secondary(i2s)) 725 if (is_secondary(i2s))
706 mod |= MOD_BLCS_16BIT; 726 val |= MOD_BLCS_16BIT;
707 else 727 else
708 mod |= MOD_BLCP_16BIT; 728 val |= MOD_BLCP_16BIT;
709 if (is_manager(i2s)) 729 if (is_manager(i2s))
710 mod |= MOD_BLC_16BIT; 730 val |= MOD_BLC_16BIT;
711 break; 731 break;
712 case 24: 732 case 24:
713 if (is_secondary(i2s)) 733 if (is_secondary(i2s))
714 mod |= MOD_BLCS_24BIT; 734 val |= MOD_BLCS_24BIT;
715 else 735 else
716 mod |= MOD_BLCP_24BIT; 736 val |= MOD_BLCP_24BIT;
717 if (is_manager(i2s)) 737 if (is_manager(i2s))
718 mod |= MOD_BLC_24BIT; 738 val |= MOD_BLC_24BIT;
719 break; 739 break;
720 default: 740 default:
721 dev_err(&i2s->pdev->dev, "Format(%d) not supported\n", 741 dev_err(&i2s->pdev->dev, "Format(%d) not supported\n",
722 params_format(params)); 742 params_format(params));
723 return -EINVAL; 743 return -EINVAL;
724 } 744 }
745
746 spin_lock(i2s->lock);
747 mod = readl(i2s->addr + I2SMOD);
748 mod = (mod & ~mask) | val;
725 writel(mod, i2s->addr + I2SMOD); 749 writel(mod, i2s->addr + I2SMOD);
750 spin_unlock(i2s->lock);
726 751
727 samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); 752 samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
728 753
@@ -736,7 +761,7 @@ static int i2s_startup(struct snd_pcm_substream *substream,
736 struct snd_soc_dai *dai) 761 struct snd_soc_dai *dai)
737{ 762{
738 struct i2s_dai *i2s = to_info(dai); 763 struct i2s_dai *i2s = to_info(dai);
739 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 764 struct i2s_dai *other = get_other_dai(i2s);
740 unsigned long flags; 765 unsigned long flags;
741 766
742 spin_lock_irqsave(&lock, flags); 767 spin_lock_irqsave(&lock, flags);
@@ -753,9 +778,6 @@ static int i2s_startup(struct snd_pcm_substream *substream,
753 778
754 spin_unlock_irqrestore(&lock, flags); 779 spin_unlock_irqrestore(&lock, flags);
755 780
756 if (!is_opened(other) && i2s->cdclk_out)
757 i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK,
758 0, SND_SOC_CLOCK_OUT);
759 return 0; 781 return 0;
760} 782}
761 783
@@ -763,38 +785,27 @@ static void i2s_shutdown(struct snd_pcm_substream *substream,
763 struct snd_soc_dai *dai) 785 struct snd_soc_dai *dai)
764{ 786{
765 struct i2s_dai *i2s = to_info(dai); 787 struct i2s_dai *i2s = to_info(dai);
766 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 788 struct i2s_dai *other = get_other_dai(i2s);
767 unsigned long flags; 789 unsigned long flags;
768 const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs;
769 790
770 spin_lock_irqsave(&lock, flags); 791 spin_lock_irqsave(&lock, flags);
771 792
772 i2s->mode &= ~DAI_OPENED; 793 i2s->mode &= ~DAI_OPENED;
773 i2s->mode &= ~DAI_MANAGER; 794 i2s->mode &= ~DAI_MANAGER;
774 795
775 if (is_opened(other)) { 796 if (is_opened(other))
776 other->mode |= DAI_MANAGER; 797 other->mode |= DAI_MANAGER;
777 } else { 798
778 u32 mod = readl(i2s->addr + I2SMOD);
779 i2s->cdclk_out = !(mod & (1 << i2s_regs->cdclkcon_off));
780 if (other)
781 other->cdclk_out = i2s->cdclk_out;
782 }
783 /* Reset any constraint on RFS and BFS */ 799 /* Reset any constraint on RFS and BFS */
784 i2s->rfs = 0; 800 i2s->rfs = 0;
785 i2s->bfs = 0; 801 i2s->bfs = 0;
786 802
787 spin_unlock_irqrestore(&lock, flags); 803 spin_unlock_irqrestore(&lock, flags);
788
789 /* Gate CDCLK by default */
790 if (!is_opened(other))
791 i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK,
792 0, SND_SOC_CLOCK_IN);
793} 804}
794 805
795static int config_setup(struct i2s_dai *i2s) 806static int config_setup(struct i2s_dai *i2s)
796{ 807{
797 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 808 struct i2s_dai *other = get_other_dai(i2s);
798 unsigned rfs, bfs, blc; 809 unsigned rfs, bfs, blc;
799 u32 psr; 810 u32 psr;
800 811
@@ -864,10 +875,10 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
864 case SNDRV_PCM_TRIGGER_START: 875 case SNDRV_PCM_TRIGGER_START:
865 case SNDRV_PCM_TRIGGER_RESUME: 876 case SNDRV_PCM_TRIGGER_RESUME:
866 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 877 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
867 local_irq_save(flags); 878 spin_lock_irqsave(i2s->lock, flags);
868 879
869 if (config_setup(i2s)) { 880 if (config_setup(i2s)) {
870 local_irq_restore(flags); 881 spin_unlock_irqrestore(i2s->lock, flags);
871 return -EINVAL; 882 return -EINVAL;
872 } 883 }
873 884
@@ -876,12 +887,12 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
876 else 887 else
877 i2s_txctrl(i2s, 1); 888 i2s_txctrl(i2s, 1);
878 889
879 local_irq_restore(flags); 890 spin_unlock_irqrestore(i2s->lock, flags);
880 break; 891 break;
881 case SNDRV_PCM_TRIGGER_STOP: 892 case SNDRV_PCM_TRIGGER_STOP:
882 case SNDRV_PCM_TRIGGER_SUSPEND: 893 case SNDRV_PCM_TRIGGER_SUSPEND:
883 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 894 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
884 local_irq_save(flags); 895 spin_lock_irqsave(i2s->lock, flags);
885 896
886 if (capture) { 897 if (capture) {
887 i2s_rxctrl(i2s, 0); 898 i2s_rxctrl(i2s, 0);
@@ -891,7 +902,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
891 i2s_fifo(i2s, FIC_TXFLUSH); 902 i2s_fifo(i2s, FIC_TXFLUSH);
892 } 903 }
893 904
894 local_irq_restore(flags); 905 spin_unlock_irqrestore(i2s->lock, flags);
895 break; 906 break;
896 } 907 }
897 908
@@ -902,7 +913,7 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai,
902 int div_id, int div) 913 int div_id, int div)
903{ 914{
904 struct i2s_dai *i2s = to_info(dai); 915 struct i2s_dai *i2s = to_info(dai);
905 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 916 struct i2s_dai *other = get_other_dai(i2s);
906 917
907 switch (div_id) { 918 switch (div_id) {
908 case SAMSUNG_I2S_DIV_BCLK: 919 case SAMSUNG_I2S_DIV_BCLK:
@@ -971,58 +982,36 @@ static int i2s_resume(struct snd_soc_dai *dai)
971static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) 982static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
972{ 983{
973 struct i2s_dai *i2s = to_info(dai); 984 struct i2s_dai *i2s = to_info(dai);
974 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 985 struct i2s_dai *other = get_other_dai(i2s);
975 int ret; 986 unsigned long flags;
976 987
977 if (other && other->clk) { /* If this is probe on secondary */ 988 if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */
978 samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback, 989 samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback,
979 NULL); 990 NULL);
980 goto probe_exit; 991 } else {
981 } 992 samsung_asoc_init_dma_data(dai, &i2s->dma_playback,
982 993 &i2s->dma_capture);
983 i2s->addr = ioremap(i2s->base, 0x100);
984 if (i2s->addr == NULL) {
985 dev_err(&i2s->pdev->dev, "cannot ioremap registers\n");
986 return -ENXIO;
987 }
988
989 i2s->clk = clk_get(&i2s->pdev->dev, "iis");
990 if (IS_ERR(i2s->clk)) {
991 dev_err(&i2s->pdev->dev, "failed to get i2s_clock\n");
992 iounmap(i2s->addr);
993 return PTR_ERR(i2s->clk);
994 }
995
996 ret = clk_prepare_enable(i2s->clk);
997 if (ret != 0) {
998 dev_err(&i2s->pdev->dev, "failed to enable clock: %d\n", ret);
999 return ret;
1000 }
1001
1002 samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
1003
1004 if (other) {
1005 other->addr = i2s->addr;
1006 other->clk = i2s->clk;
1007 }
1008 994
1009 if (i2s->quirks & QUIRK_NEED_RSTCLR) 995 if (i2s->quirks & QUIRK_NEED_RSTCLR)
1010 writel(CON_RSTCLR, i2s->addr + I2SCON); 996 writel(CON_RSTCLR, i2s->addr + I2SCON);
1011 997
1012 if (i2s->quirks & QUIRK_SUPPORTS_IDMA) 998 if (i2s->quirks & QUIRK_SUPPORTS_IDMA)
1013 idma_reg_addr_init(i2s->addr, 999 idma_reg_addr_init(i2s->addr,
1014 i2s->sec_dai->idma_playback.dma_addr); 1000 i2s->sec_dai->idma_playback.dma_addr);
1001 }
1015 1002
1016probe_exit:
1017 /* Reset any constraint on RFS and BFS */ 1003 /* Reset any constraint on RFS and BFS */
1018 i2s->rfs = 0; 1004 i2s->rfs = 0;
1019 i2s->bfs = 0; 1005 i2s->bfs = 0;
1020 i2s->rclk_srcrate = 0; 1006 i2s->rclk_srcrate = 0;
1007
1008 spin_lock_irqsave(i2s->lock, flags);
1021 i2s_txctrl(i2s, 0); 1009 i2s_txctrl(i2s, 0);
1022 i2s_rxctrl(i2s, 0); 1010 i2s_rxctrl(i2s, 0);
1023 i2s_fifo(i2s, FIC_TXFLUSH); 1011 i2s_fifo(i2s, FIC_TXFLUSH);
1024 i2s_fifo(other, FIC_TXFLUSH); 1012 i2s_fifo(other, FIC_TXFLUSH);
1025 i2s_fifo(i2s, FIC_RXFLUSH); 1013 i2s_fifo(i2s, FIC_RXFLUSH);
1014 spin_unlock_irqrestore(i2s->lock, flags);
1026 1015
1027 /* Gate CDCLK by default */ 1016 /* Gate CDCLK by default */
1028 if (!is_opened(other)) 1017 if (!is_opened(other))
@@ -1035,21 +1024,15 @@ probe_exit:
1035static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) 1024static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
1036{ 1025{
1037 struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); 1026 struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai);
1038 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai;
1039
1040 if (!other || !other->clk) {
1041 1027
1042 if (i2s->quirks & QUIRK_NEED_RSTCLR) 1028 if (!is_secondary(i2s)) {
1029 if (i2s->quirks & QUIRK_NEED_RSTCLR) {
1030 spin_lock(i2s->lock);
1043 writel(0, i2s->addr + I2SCON); 1031 writel(0, i2s->addr + I2SCON);
1044 1032 spin_unlock(i2s->lock);
1045 clk_disable_unprepare(i2s->clk); 1033 }
1046 clk_put(i2s->clk);
1047
1048 iounmap(i2s->addr);
1049 } 1034 }
1050 1035
1051 i2s->clk = NULL;
1052
1053 return 0; 1036 return 0;
1054} 1037}
1055 1038
@@ -1124,15 +1107,14 @@ static const struct of_device_id exynos_i2s_match[];
1124static inline const struct samsung_i2s_dai_data *samsung_i2s_get_driver_data( 1107static inline const struct samsung_i2s_dai_data *samsung_i2s_get_driver_data(
1125 struct platform_device *pdev) 1108 struct platform_device *pdev)
1126{ 1109{
1127#ifdef CONFIG_OF 1110 if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
1128 if (pdev->dev.of_node) {
1129 const struct of_device_id *match; 1111 const struct of_device_id *match;
1130 match = of_match_node(exynos_i2s_match, pdev->dev.of_node); 1112 match = of_match_node(exynos_i2s_match, pdev->dev.of_node);
1131 return match->data; 1113 return match ? match->data : NULL;
1132 } else 1114 } else {
1133#endif
1134 return (struct samsung_i2s_dai_data *) 1115 return (struct samsung_i2s_dai_data *)
1135 platform_get_device_id(pdev)->driver_data; 1116 platform_get_device_id(pdev)->driver_data;
1117 }
1136} 1118}
1137 1119
1138#ifdef CONFIG_PM 1120#ifdef CONFIG_PM
@@ -1155,6 +1137,87 @@ static int i2s_runtime_resume(struct device *dev)
1155} 1137}
1156#endif /* CONFIG_PM */ 1138#endif /* CONFIG_PM */
1157 1139
1140static void i2s_unregister_clocks(struct i2s_dai *i2s)
1141{
1142 int i;
1143
1144 for (i = 0; i < i2s->clk_data.clk_num; i++) {
1145 if (!IS_ERR(i2s->clk_table[i]))
1146 clk_unregister(i2s->clk_table[i]);
1147 }
1148}
1149
1150static void i2s_unregister_clock_provider(struct platform_device *pdev)
1151{
1152 struct i2s_dai *i2s = dev_get_drvdata(&pdev->dev);
1153
1154 of_clk_del_provider(pdev->dev.of_node);
1155 i2s_unregister_clocks(i2s);
1156}
1157
1158static int i2s_register_clock_provider(struct platform_device *pdev)
1159{
1160 struct device *dev = &pdev->dev;
1161 struct i2s_dai *i2s = dev_get_drvdata(dev);
1162 const char *clk_name[2] = { "i2s_opclk0", "i2s_opclk1" };
1163 const char *p_names[2] = { NULL };
1164 const struct samsung_i2s_variant_regs *reg_info = i2s->variant_regs;
1165 struct clk *rclksrc;
1166 int ret, i;
1167
1168 /* Register the clock provider only if it's expected in the DTB */
1169 if (!of_find_property(dev->of_node, "#clock-cells", NULL))
1170 return 0;
1171
1172 /* Get the RCLKSRC mux clock parent clock names */
1173 for (i = 0; i < ARRAY_SIZE(p_names); i++) {
1174 rclksrc = clk_get(dev, clk_name[i]);
1175 if (IS_ERR(rclksrc))
1176 continue;
1177 p_names[i] = __clk_get_name(rclksrc);
1178 clk_put(rclksrc);
1179 }
1180
1181 if (!(i2s->quirks & QUIRK_NO_MUXPSR)) {
1182 /* Activate the prescaler */
1183 u32 val = readl(i2s->addr + I2SPSR);
1184 writel(val | PSR_PSREN, i2s->addr + I2SPSR);
1185
1186 i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(NULL,
1187 "i2s_rclksrc", p_names, ARRAY_SIZE(p_names),
1188 CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
1189 i2s->addr + I2SMOD, reg_info->rclksrc_off,
1190 1, 0, i2s->lock);
1191
1192 i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(NULL,
1193 "i2s_presc", "i2s_rclksrc",
1194 CLK_SET_RATE_PARENT,
1195 i2s->addr + I2SPSR, 8, 6, 0, i2s->lock);
1196
1197 p_names[0] = "i2s_presc";
1198 i2s->clk_data.clk_num = 2;
1199 }
1200 of_property_read_string_index(dev->of_node,
1201 "clock-output-names", 0, &clk_name[0]);
1202
1203 i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(NULL, clk_name[0],
1204 p_names[0], CLK_SET_RATE_PARENT,
1205 i2s->addr + I2SMOD, reg_info->cdclkcon_off,
1206 CLK_GATE_SET_TO_DISABLE, i2s->lock);
1207
1208 i2s->clk_data.clk_num += 1;
1209 i2s->clk_data.clks = i2s->clk_table;
1210
1211 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
1212 &i2s->clk_data);
1213 if (ret < 0) {
1214 dev_err(dev, "failed to add clock provider: %d\n", ret);
1215 i2s_unregister_clocks(i2s);
1216 }
1217
1218 return ret;
1219}
1220
1158static int samsung_i2s_probe(struct platform_device *pdev) 1221static int samsung_i2s_probe(struct platform_device *pdev)
1159{ 1222{
1160 struct i2s_dai *pri_dai, *sec_dai = NULL; 1223 struct i2s_dai *pri_dai, *sec_dai = NULL;
@@ -1164,7 +1227,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1164 u32 regs_base, quirks = 0, idma_addr = 0; 1227 u32 regs_base, quirks = 0, idma_addr = 0;
1165 struct device_node *np = pdev->dev.of_node; 1228 struct device_node *np = pdev->dev.of_node;
1166 const struct samsung_i2s_dai_data *i2s_dai_data; 1229 const struct samsung_i2s_dai_data *i2s_dai_data;
1167 int ret = 0; 1230 int ret;
1168 1231
1169 /* Call during Seconday interface registration */ 1232 /* Call during Seconday interface registration */
1170 i2s_dai_data = samsung_i2s_get_driver_data(pdev); 1233 i2s_dai_data = samsung_i2s_get_driver_data(pdev);
@@ -1175,11 +1238,13 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1175 dev_err(&pdev->dev, "Unable to get drvdata\n"); 1238 dev_err(&pdev->dev, "Unable to get drvdata\n");
1176 return -EFAULT; 1239 return -EFAULT;
1177 } 1240 }
1178 devm_snd_soc_register_component(&sec_dai->pdev->dev, 1241 ret = devm_snd_soc_register_component(&sec_dai->pdev->dev,
1179 &samsung_i2s_component, 1242 &samsung_i2s_component,
1180 &sec_dai->i2s_dai_drv, 1); 1243 &sec_dai->i2s_dai_drv, 1);
1181 samsung_asoc_dma_platform_register(&pdev->dev); 1244 if (ret != 0)
1182 return 0; 1245 return ret;
1246
1247 return samsung_asoc_dma_platform_register(&pdev->dev);
1183 } 1248 }
1184 1249
1185 pri_dai = i2s_alloc_dai(pdev, false); 1250 pri_dai = i2s_alloc_dai(pdev, false);
@@ -1188,6 +1253,9 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1188 return -ENOMEM; 1253 return -ENOMEM;
1189 } 1254 }
1190 1255
1256 spin_lock_init(&pri_dai->spinlock);
1257 pri_dai->lock = &pri_dai->spinlock;
1258
1191 if (!np) { 1259 if (!np) {
1192 res = platform_get_resource(pdev, IORESOURCE_DMA, 0); 1260 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
1193 if (!res) { 1261 if (!res) {
@@ -1229,25 +1297,29 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1229 } 1297 }
1230 1298
1231 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1299 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1232 if (!res) { 1300 pri_dai->addr = devm_ioremap_resource(&pdev->dev, res);
1233 dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); 1301 if (IS_ERR(pri_dai->addr))
1234 return -ENXIO; 1302 return PTR_ERR(pri_dai->addr);
1235 }
1236 1303
1237 if (!request_mem_region(res->start, resource_size(res),
1238 "samsung-i2s")) {
1239 dev_err(&pdev->dev, "Unable to request SFR region\n");
1240 return -EBUSY;
1241 }
1242 regs_base = res->start; 1304 regs_base = res->start;
1243 1305
1306 pri_dai->clk = devm_clk_get(&pdev->dev, "iis");
1307 if (IS_ERR(pri_dai->clk)) {
1308 dev_err(&pdev->dev, "Failed to get iis clock\n");
1309 return PTR_ERR(pri_dai->clk);
1310 }
1311
1312 ret = clk_prepare_enable(pri_dai->clk);
1313 if (ret != 0) {
1314 dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
1315 return ret;
1316 }
1244 pri_dai->dma_playback.dma_addr = regs_base + I2STXD; 1317 pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
1245 pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; 1318 pri_dai->dma_capture.dma_addr = regs_base + I2SRXD;
1246 pri_dai->dma_playback.ch_name = "tx"; 1319 pri_dai->dma_playback.ch_name = "tx";
1247 pri_dai->dma_capture.ch_name = "rx"; 1320 pri_dai->dma_capture.ch_name = "rx";
1248 pri_dai->dma_playback.dma_size = 4; 1321 pri_dai->dma_playback.dma_size = 4;
1249 pri_dai->dma_capture.dma_size = 4; 1322 pri_dai->dma_capture.dma_size = 4;
1250 pri_dai->base = regs_base;
1251 pri_dai->quirks = quirks; 1323 pri_dai->quirks = quirks;
1252 pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs; 1324 pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs;
1253 1325
@@ -1258,10 +1330,10 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1258 sec_dai = i2s_alloc_dai(pdev, true); 1330 sec_dai = i2s_alloc_dai(pdev, true);
1259 if (!sec_dai) { 1331 if (!sec_dai) {
1260 dev_err(&pdev->dev, "Unable to alloc I2S_sec\n"); 1332 dev_err(&pdev->dev, "Unable to alloc I2S_sec\n");
1261 ret = -ENOMEM; 1333 return -ENOMEM;
1262 goto err;
1263 } 1334 }
1264 1335
1336 sec_dai->lock = &pri_dai->spinlock;
1265 sec_dai->variant_regs = pri_dai->variant_regs; 1337 sec_dai->variant_regs = pri_dai->variant_regs;
1266 sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; 1338 sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
1267 sec_dai->dma_playback.ch_name = "tx-sec"; 1339 sec_dai->dma_playback.ch_name = "tx-sec";
@@ -1273,7 +1345,8 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1273 } 1345 }
1274 1346
1275 sec_dai->dma_playback.dma_size = 4; 1347 sec_dai->dma_playback.dma_size = 4;
1276 sec_dai->base = regs_base; 1348 sec_dai->addr = pri_dai->addr;
1349 sec_dai->clk = pri_dai->clk;
1277 sec_dai->quirks = quirks; 1350 sec_dai->quirks = quirks;
1278 sec_dai->idma_playback.dma_addr = idma_addr; 1351 sec_dai->idma_playback.dma_addr = idma_addr;
1279 sec_dai->pri_dai = pri_dai; 1352 sec_dai->pri_dai = pri_dai;
@@ -1282,8 +1355,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1282 1355
1283 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { 1356 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
1284 dev_err(&pdev->dev, "Unable to configure gpio\n"); 1357 dev_err(&pdev->dev, "Unable to configure gpio\n");
1285 ret = -EINVAL; 1358 return -EINVAL;
1286 goto err;
1287 } 1359 }
1288 1360
1289 devm_snd_soc_register_component(&pri_dai->pdev->dev, 1361 devm_snd_soc_register_component(&pri_dai->pdev->dev,
@@ -1292,32 +1364,30 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1292 1364
1293 pm_runtime_enable(&pdev->dev); 1365 pm_runtime_enable(&pdev->dev);
1294 1366
1295 samsung_asoc_dma_platform_register(&pdev->dev); 1367 ret = samsung_asoc_dma_platform_register(&pdev->dev);
1296 1368 if (ret != 0)
1297 return 0; 1369 return ret;
1298err:
1299 if (res)
1300 release_mem_region(regs_base, resource_size(res));
1301 1370
1302 return ret; 1371 return i2s_register_clock_provider(pdev);
1303} 1372}
1304 1373
1305static int samsung_i2s_remove(struct platform_device *pdev) 1374static int samsung_i2s_remove(struct platform_device *pdev)
1306{ 1375{
1307 struct i2s_dai *i2s, *other; 1376 struct i2s_dai *i2s, *other;
1308 struct resource *res;
1309 1377
1310 i2s = dev_get_drvdata(&pdev->dev); 1378 i2s = dev_get_drvdata(&pdev->dev);
1311 other = i2s->pri_dai ? : i2s->sec_dai; 1379 other = get_other_dai(i2s);
1312 1380
1313 if (other) { 1381 if (other) {
1314 other->pri_dai = NULL; 1382 other->pri_dai = NULL;
1315 other->sec_dai = NULL; 1383 other->sec_dai = NULL;
1316 } else { 1384 } else {
1317 pm_runtime_disable(&pdev->dev); 1385 pm_runtime_disable(&pdev->dev);
1318 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1386 }
1319 if (res) 1387
1320 release_mem_region(res->start, resource_size(res)); 1388 if (!is_secondary(i2s)) {
1389 i2s_unregister_clock_provider(pdev);
1390 clk_disable_unprepare(i2s->clk);
1321 } 1391 }
1322 1392
1323 i2s->pri_dai = NULL; 1393 i2s->pri_dai = NULL;
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c
index 6c3b359bb4c1..7fcb51faa2a0 100644
--- a/sound/soc/samsung/jive_wm8750.c
+++ b/sound/soc/samsung/jive_wm8750.c
@@ -83,22 +83,6 @@ static struct snd_soc_ops jive_ops = {
83 .hw_params = jive_hw_params, 83 .hw_params = jive_hw_params,
84}; 84};
85 85
86static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
87{
88 struct snd_soc_codec *codec = rtd->codec;
89 struct snd_soc_dapm_context *dapm = &codec->dapm;
90
91 /* These endpoints are not being used. */
92 snd_soc_dapm_nc_pin(dapm, "LINPUT2");
93 snd_soc_dapm_nc_pin(dapm, "RINPUT2");
94 snd_soc_dapm_nc_pin(dapm, "LINPUT3");
95 snd_soc_dapm_nc_pin(dapm, "RINPUT3");
96 snd_soc_dapm_nc_pin(dapm, "OUT3");
97 snd_soc_dapm_nc_pin(dapm, "MONO");
98
99 return 0;
100}
101
102static struct snd_soc_dai_link jive_dai = { 86static struct snd_soc_dai_link jive_dai = {
103 .name = "wm8750", 87 .name = "wm8750",
104 .stream_name = "WM8750", 88 .stream_name = "WM8750",
@@ -106,7 +90,6 @@ static struct snd_soc_dai_link jive_dai = {
106 .codec_dai_name = "wm8750-hifi", 90 .codec_dai_name = "wm8750-hifi",
107 .platform_name = "s3c2412-i2s", 91 .platform_name = "s3c2412-i2s",
108 .codec_name = "wm8750.0-001a", 92 .codec_name = "wm8750.0-001a",
109 .init = jive_wm8750_init,
110 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 93 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
111 SND_SOC_DAIFMT_CBS_CFS, 94 SND_SOC_DAIFMT_CBS_CFS,
112 .ops = &jive_ops, 95 .ops = &jive_ops,
@@ -123,6 +106,7 @@ static struct snd_soc_card snd_soc_machine_jive = {
123 .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), 106 .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
124 .dapm_routes = audio_map, 107 .dapm_routes = audio_map,
125 .num_dapm_routes = ARRAY_SIZE(audio_map), 108 .num_dapm_routes = ARRAY_SIZE(audio_map),
109 .fully_routed = true,
126}; 110};
127 111
128static struct platform_device *jive_snd_device; 112static struct platform_device *jive_snd_device;
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c
index fa4f1d2f69bf..596f1180a369 100644
--- a/sound/soc/samsung/odroidx2_max98090.c
+++ b/sound/soc/samsung/odroidx2_max98090.c
@@ -21,6 +21,8 @@ struct odroidx2_drv_data {
21/* The I2S CDCLK output clock frequency for the MAX98090 codec */ 21/* The I2S CDCLK output clock frequency for the MAX98090 codec */
22#define MAX98090_MCLK 19200000 22#define MAX98090_MCLK 19200000
23 23
24static struct snd_soc_dai_link odroidx2_dai[];
25
24static int odroidx2_late_probe(struct snd_soc_card *card) 26static int odroidx2_late_probe(struct snd_soc_card *card)
25{ 27{
26 struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; 28 struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
@@ -29,7 +31,9 @@ static int odroidx2_late_probe(struct snd_soc_card *card)
29 31
30 ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK, 32 ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK,
31 SND_SOC_CLOCK_IN); 33 SND_SOC_CLOCK_IN);
32 if (ret < 0) 34
35 if (ret < 0 || of_find_property(odroidx2_dai[0].codec_of_node,
36 "clocks", NULL))
33 return ret; 37 return ret;
34 38
35 /* Set the cpu DAI configuration in order to use CDCLK */ 39 /* Set the cpu DAI configuration in order to use CDCLK */
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index 17a2f717ec02..548bfd993788 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -136,13 +136,10 @@ static const struct snd_soc_dapm_route smdk_wm8580_audio_map[] = {
136 136
137static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) 137static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
138{ 138{
139 struct snd_soc_codec *codec = rtd->codec;
140 struct snd_soc_dapm_context *dapm = &codec->dapm;
141
142 /* Enabling the microphone requires the fitting of a 0R 139 /* Enabling the microphone requires the fitting of a 0R
143 * resistor to connect the line from the microphone jack. 140 * resistor to connect the line from the microphone jack.
144 */ 141 */
145 snd_soc_dapm_disable_pin(dapm, "MicIn"); 142 snd_soc_dapm_disable_pin(&rtd->card->dapm, "MicIn");
146 143
147 return 0; 144 return 0;
148} 145}
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index a5b2c4ea90d9..fd11404a3bc7 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -305,11 +305,6 @@ static struct snd_pcm_ops camelot_pcm_ops = {
305 .pointer = camelot_pos, 305 .pointer = camelot_pos,
306}; 306};
307 307
308static void camelot_pcm_free(struct snd_pcm *pcm)
309{
310 snd_pcm_lib_preallocate_free_for_all(pcm);
311}
312
313static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd) 308static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
314{ 309{
315 struct snd_pcm *pcm = rtd->pcm; 310 struct snd_pcm *pcm = rtd->pcm;
@@ -328,7 +323,6 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
328static struct snd_soc_platform_driver sh7760_soc_platform = { 323static struct snd_soc_platform_driver sh7760_soc_platform = {
329 .ops = &camelot_pcm_ops, 324 .ops = &camelot_pcm_ops,
330 .pcm_new = camelot_pcm_new, 325 .pcm_new = camelot_pcm_new,
331 .pcm_free = camelot_pcm_free,
332}; 326};
333 327
334static int sh7760_soc_platform_probe(struct platform_device *pdev) 328static int sh7760_soc_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index d49f25f9efd3..b87b22e88e43 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -1762,11 +1762,6 @@ static struct snd_pcm_ops fsi_pcm_ops = {
1762#define PREALLOC_BUFFER (32 * 1024) 1762#define PREALLOC_BUFFER (32 * 1024)
1763#define PREALLOC_BUFFER_MAX (32 * 1024) 1763#define PREALLOC_BUFFER_MAX (32 * 1024)
1764 1764
1765static void fsi_pcm_free(struct snd_pcm *pcm)
1766{
1767 snd_pcm_lib_preallocate_free_for_all(pcm);
1768}
1769
1770static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) 1765static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd)
1771{ 1766{
1772 return snd_pcm_lib_preallocate_pages_for_all( 1767 return snd_pcm_lib_preallocate_pages_for_all(
@@ -1818,7 +1813,6 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
1818static struct snd_soc_platform_driver fsi_soc_platform = { 1813static struct snd_soc_platform_driver fsi_soc_platform = {
1819 .ops = &fsi_pcm_ops, 1814 .ops = &fsi_pcm_ops,
1820 .pcm_new = fsi_pcm_new, 1815 .pcm_new = fsi_pcm_new,
1821 .pcm_free = fsi_pcm_free,
1822}; 1816};
1823 1817
1824static const struct snd_soc_component_driver fsi_soc_component = { 1818static const struct snd_soc_component_driver fsi_soc_component = {
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index 32eb6da2d2bd..82902f56e82f 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -589,7 +589,6 @@ static void siu_pcm_free(struct snd_pcm *pcm)
589 tasklet_kill(&port_info->playback.tasklet); 589 tasklet_kill(&port_info->playback.tasklet);
590 590
591 siu_free_port(port_info); 591 siu_free_port(port_info);
592 snd_pcm_lib_preallocate_free_for_all(pcm);
593 592
594 dev_dbg(pcm->card->dev, "%s\n", __func__); 593 dev_dbg(pcm->card->dev, "%s\n", __func__);
595} 594}