aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-02-09 02:54:50 -0500
committerTakashi Iwai <tiwai@suse.de>2015-02-09 02:54:50 -0500
commitd1612c80edaab7ac9170cb2fc86b538ab2e5a741 (patch)
tree759755d5abef02f23a42f5056aaac84de694d5ad
parentd34890cf4113397625a6629d71749fa638a7a734 (diff)
parentf4c2e9bcb0be4ee1c8722853e4faaaf6a9423d72 (diff)
Merge tag 'asoc-v3.20-3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Final updates for v3.20 A few more updates for v3.20 that have accumilated over the second half of last week. One new (relatively simple) driver for the Maxim max98357a and some other driver specific fixes and enhancements. I did apply a few patches that haven't been in -next just now before sending this, all fixes except for one simple device ID addition patch.
-rw-r--r--Documentation/devicetree/bindings/sound/ingenic,jz4740-i2s.txt23
-rw-r--r--Documentation/devicetree/bindings/sound/max98357a.txt14
-rw-r--r--arch/arm/boot/dts/exynos4.dtsi13
-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--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/max98357a.c138
-rw-r--r--sound/soc/codecs/rt286.c31
-rw-r--r--sound/soc/codecs/rt286.h7
-rw-r--r--sound/soc/codecs/rt5645.c81
-rw-r--r--sound/soc/codecs/rt5645.h72
-rw-r--r--sound/soc/codecs/rt5670.c1
-rw-r--r--sound/soc/intel/Kconfig11
-rw-r--r--sound/soc/intel/Makefile2
-rw-r--r--sound/soc/intel/cht_bsw_rt5645.c326
-rw-r--r--sound/soc/intel/sst-haswell-ipc.c168
-rw-r--r--sound/soc/intel/sst-haswell-ipc.h31
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c70
-rw-r--r--sound/soc/intel/sst/sst.h3
-rw-r--r--sound/soc/intel/sst/sst_acpi.c6
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c21
-rw-r--r--sound/soc/samsung/Kconfig11
-rw-r--r--sound/soc/samsung/Makefile2
-rw-r--r--sound/soc/samsung/goni_wm8994.c289
-rw-r--r--sound/soc/soc-core.c2
27 files changed, 775 insertions, 596 deletions
diff --git a/Documentation/devicetree/bindings/sound/ingenic,jz4740-i2s.txt b/Documentation/devicetree/bindings/sound/ingenic,jz4740-i2s.txt
new file mode 100644
index 000000000000..b41433386e2f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ingenic,jz4740-i2s.txt
@@ -0,0 +1,23 @@
1Ingenic JZ4740 I2S controller
2
3Required properties:
4- compatible : "ingenic,jz4740-i2s"
5- reg : I2S registers location and length
6- clocks : AIC and I2S PLL clock specifiers.
7- clock-names: "aic" and "i2s"
8- dmas: DMA controller phandle and DMA request line for I2S Tx and Rx channels
9- dma-names: Must be "tx" and "rx"
10
11Example:
12
13i2s: i2s@10020000 {
14 compatible = "ingenic,jz4740-i2s";
15 reg = <0x10020000 0x94>;
16
17 clocks = <&cgu JZ4740_CLK_AIC>, <&cgu JZ4740_CLK_I2SPLL>;
18 clock-names = "aic", "i2s";
19
20 dmas = <&dma 2>, <&dma 3>;
21 dma-names = "tx", "rx";
22
23};
diff --git a/Documentation/devicetree/bindings/sound/max98357a.txt b/Documentation/devicetree/bindings/sound/max98357a.txt
new file mode 100644
index 000000000000..a7a149a236e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/max98357a.txt
@@ -0,0 +1,14 @@
1Maxim MAX98357A audio DAC
2
3This node models the Maxim MAX98357A DAC.
4
5Required properties:
6- compatible : "maxim,max98357a"
7- sdmode-gpios : GPIO specifier for the GPIO -> DAC SDMODE pin
8
9Example:
10
11max98357a {
12 compatible = "maxim,max98357a";
13 sdmode-gpios = <&qcom_pinmux 25 0>;
14};
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index b8168f1f8139..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
@@ -368,22 +371,28 @@
368 }; 371 };
369 372
370 i2s1: i2s@13960000 { 373 i2s1: i2s@13960000 {
371 compatible = "samsung,s5pv210-i2s"; 374 compatible = "samsung,s3c6410-i2s";
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
380 i2s2: i2s@13970000 { 386 i2s2: i2s@13970000 {
381 compatible = "samsung,s5pv210-i2s"; 387 compatible = "samsung,s3c6410-i2s";
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/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 3190eed43c38..064e6c18e109 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -69,6 +69,7 @@ config SND_SOC_ALL_CODECS
69 select SND_SOC_MAX98088 if I2C 69 select SND_SOC_MAX98088 if I2C
70 select SND_SOC_MAX98090 if I2C 70 select SND_SOC_MAX98090 if I2C
71 select SND_SOC_MAX98095 if I2C 71 select SND_SOC_MAX98095 if I2C
72 select SND_SOC_MAX98357A
72 select SND_SOC_MAX9850 if I2C 73 select SND_SOC_MAX9850 if I2C
73 select SND_SOC_MAX9768 if I2C 74 select SND_SOC_MAX9768 if I2C
74 select SND_SOC_MAX9877 if I2C 75 select SND_SOC_MAX9877 if I2C
@@ -456,6 +457,9 @@ config SND_SOC_MAX98090
456config SND_SOC_MAX98095 457config SND_SOC_MAX98095
457 tristate 458 tristate
458 459
460config SND_SOC_MAX98357A
461 tristate
462
459config SND_SOC_MAX9850 463config SND_SOC_MAX9850
460 tristate 464 tristate
461 465
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bbdfd1e1c182..69b8666d187a 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -64,6 +64,7 @@ snd-soc-max9768-objs := max9768.o
64snd-soc-max98088-objs := max98088.o 64snd-soc-max98088-objs := max98088.o
65snd-soc-max98090-objs := max98090.o 65snd-soc-max98090-objs := max98090.o
66snd-soc-max98095-objs := max98095.o 66snd-soc-max98095-objs := max98095.o
67snd-soc-max98357a-objs := max98357a.o
67snd-soc-max9850-objs := max9850.o 68snd-soc-max9850-objs := max9850.o
68snd-soc-mc13783-objs := mc13783.o 69snd-soc-mc13783-objs := mc13783.o
69snd-soc-ml26124-objs := ml26124.o 70snd-soc-ml26124-objs := ml26124.o
@@ -245,6 +246,7 @@ obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
245obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o 246obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
246obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o 247obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o
247obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o 248obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
249obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o
248obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o 250obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
249obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o 251obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
250obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o 252obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
new file mode 100644
index 000000000000..1806333ea29e
--- /dev/null
+++ b/sound/soc/codecs/max98357a.c
@@ -0,0 +1,138 @@
1/* Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * max98357a.c -- MAX98357A ALSA SoC Codec driver
13 */
14
15#include <linux/module.h>
16#include <linux/gpio.h>
17#include <sound/soc.h>
18
19#define DRV_NAME "max98357a"
20
21static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
22 int cmd, struct snd_soc_dai *dai)
23{
24 struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai);
25
26 switch (cmd) {
27 case SNDRV_PCM_TRIGGER_START:
28 case SNDRV_PCM_TRIGGER_RESUME:
29 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
30 gpiod_set_value(sdmode, 1);
31 break;
32 case SNDRV_PCM_TRIGGER_STOP:
33 case SNDRV_PCM_TRIGGER_SUSPEND:
34 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
35 gpiod_set_value(sdmode, 0);
36 break;
37 }
38
39 return 0;
40}
41
42static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = {
43 SND_SOC_DAPM_DAC("SDMode", NULL, SND_SOC_NOPM, 0, 0),
44 SND_SOC_DAPM_OUTPUT("Speaker"),
45};
46
47static const struct snd_soc_dapm_route max98357a_dapm_routes[] = {
48 {"Speaker", NULL, "SDMode"},
49};
50
51static int max98357a_codec_probe(struct snd_soc_codec *codec)
52{
53 struct gpio_desc *sdmode;
54
55 sdmode = devm_gpiod_get(codec->dev, "sdmode");
56 if (IS_ERR(sdmode)) {
57 dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n",
58 __func__, PTR_ERR(sdmode));
59 return PTR_ERR(sdmode);
60 }
61 gpiod_direction_output(sdmode, 0);
62 snd_soc_codec_set_drvdata(codec, sdmode);
63
64 return 0;
65}
66
67static struct snd_soc_codec_driver max98357a_codec_driver = {
68 .probe = max98357a_codec_probe,
69 .dapm_widgets = max98357a_dapm_widgets,
70 .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets),
71 .dapm_routes = max98357a_dapm_routes,
72 .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes),
73};
74
75static struct snd_soc_dai_ops max98357a_dai_ops = {
76 .trigger = max98357a_daiops_trigger,
77};
78
79static struct snd_soc_dai_driver max98357a_dai_driver = {
80 .name = DRV_NAME,
81 .playback = {
82 .stream_name = DRV_NAME "-playback",
83 .formats = SNDRV_PCM_FMTBIT_S16 |
84 SNDRV_PCM_FMTBIT_S24 |
85 SNDRV_PCM_FMTBIT_S32,
86 .rates = SNDRV_PCM_RATE_8000 |
87 SNDRV_PCM_RATE_16000 |
88 SNDRV_PCM_RATE_48000 |
89 SNDRV_PCM_RATE_96000,
90 .rate_min = 8000,
91 .rate_max = 96000,
92 .channels_min = 1,
93 .channels_max = 2,
94 },
95 .ops = &max98357a_dai_ops,
96};
97
98static int max98357a_platform_probe(struct platform_device *pdev)
99{
100 int ret;
101
102 ret = snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver,
103 &max98357a_dai_driver, 1);
104 if (ret)
105 dev_err(&pdev->dev, "%s() error registering codec driver: %d\n",
106 __func__, ret);
107
108 return ret;
109}
110
111static int max98357a_platform_remove(struct platform_device *pdev)
112{
113 snd_soc_unregister_codec(&pdev->dev);
114
115 return 0;
116}
117
118#ifdef CONFIG_OF
119static const struct of_device_id max98357a_device_id[] = {
120 { .compatible = "maxim," DRV_NAME, },
121 {}
122};
123MODULE_DEVICE_TABLE(of, max98357a_device_id);
124#endif
125
126static struct platform_driver max98357a_platform_driver = {
127 .driver = {
128 .name = DRV_NAME,
129 .of_match_table = of_match_ptr(max98357a_device_id),
130 },
131 .probe = max98357a_platform_probe,
132 .remove = max98357a_platform_remove,
133};
134module_platform_driver(max98357a_platform_driver);
135
136MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver");
137MODULE_LICENSE("GPL v2");
138MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 8104d2285602..f374840a5a7c 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -34,6 +34,7 @@
34#include "rt286.h" 34#include "rt286.h"
35 35
36#define RT286_VENDOR_ID 0x10ec0286 36#define RT286_VENDOR_ID 0x10ec0286
37#define RT288_VENDOR_ID 0x10ec0288
37 38
38struct rt286_priv { 39struct rt286_priv {
39 struct regmap *regmap; 40 struct regmap *regmap;
@@ -305,6 +306,8 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
305 *hp = false; 306 *hp = false;
306 *mic = false; 307 *mic = false;
307 308
309 if (!rt286->codec)
310 return -EINVAL;
308 if (rt286->pdata.cbj_en) { 311 if (rt286->pdata.cbj_en) {
309 regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); 312 regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf);
310 *hp = buf & 0x80000000; 313 *hp = buf & 0x80000000;
@@ -1169,6 +1172,7 @@ static const struct regmap_config rt286_regmap = {
1169 1172
1170static const struct i2c_device_id rt286_i2c_id[] = { 1173static const struct i2c_device_id rt286_i2c_id[] = {
1171 {"rt286", 0}, 1174 {"rt286", 0},
1175 {"rt288", 0},
1172 {} 1176 {}
1173}; 1177};
1174MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); 1178MODULE_DEVICE_TABLE(i2c, rt286_i2c_id);
@@ -1189,6 +1193,17 @@ static struct dmi_system_id force_combo_jack_table[] = {
1189 { } 1193 { }
1190}; 1194};
1191 1195
1196static struct dmi_system_id dmi_dell_dino[] = {
1197 {
1198 .ident = "Dell Dino",
1199 .matches = {
1200 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
1201 DMI_MATCH(DMI_BOARD_NAME, "0144P8")
1202 }
1203 },
1204 { }
1205};
1206
1192static int rt286_i2c_probe(struct i2c_client *i2c, 1207static int rt286_i2c_probe(struct i2c_client *i2c,
1193 const struct i2c_device_id *id) 1208 const struct i2c_device_id *id)
1194{ 1209{
@@ -1211,7 +1226,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
1211 1226
1212 regmap_read(rt286->regmap, 1227 regmap_read(rt286->regmap,
1213 RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); 1228 RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret);
1214 if (ret != RT286_VENDOR_ID) { 1229 if (ret != RT286_VENDOR_ID && ret != RT288_VENDOR_ID) {
1215 dev_err(&i2c->dev, 1230 dev_err(&i2c->dev,
1216 "Device with ID register %x is not rt286\n", ret); 1231 "Device with ID register %x is not rt286\n", ret);
1217 return -ENODEV; 1232 return -ENODEV;
@@ -1224,7 +1239,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
1224 if (pdata) 1239 if (pdata)
1225 rt286->pdata = *pdata; 1240 rt286->pdata = *pdata;
1226 1241
1227 if (dmi_check_system(force_combo_jack_table)) 1242 if (dmi_check_system(force_combo_jack_table) ||
1243 dmi_check_system(dmi_dell_dino))
1228 rt286->pdata.cbj_en = true; 1244 rt286->pdata.cbj_en = true;
1229 1245
1230 regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); 1246 regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3);
@@ -1263,6 +1279,17 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
1263 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); 1279 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737);
1264 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); 1280 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
1265 1281
1282 if (dmi_check_system(dmi_dell_dino)) {
1283 regmap_update_bits(rt286->regmap,
1284 RT286_SET_GPIO_MASK, 0x40, 0x40);
1285 regmap_update_bits(rt286->regmap,
1286 RT286_SET_GPIO_DIRECTION, 0x40, 0x40);
1287 regmap_update_bits(rt286->regmap,
1288 RT286_SET_GPIO_DATA, 0x40, 0x40);
1289 regmap_update_bits(rt286->regmap,
1290 RT286_GPIO_CTRL, 0xc, 0x8);
1291 }
1292
1266 if (rt286->i2c->irq) { 1293 if (rt286->i2c->irq) {
1267 ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, 1294 ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq,
1268 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); 1295 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286);
diff --git a/sound/soc/codecs/rt286.h b/sound/soc/codecs/rt286.h
index b539b7320a79..7130edb152ef 100644
--- a/sound/soc/codecs/rt286.h
+++ b/sound/soc/codecs/rt286.h
@@ -117,6 +117,12 @@
117 VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0) 117 VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0)
118#define RT286_PROC_COEF\ 118#define RT286_PROC_COEF\
119 VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0) 119 VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0)
120#define RT286_SET_GPIO_MASK\
121 VERB_CMD(AC_VERB_SET_GPIO_MASK, RT286_AUDIO_FUNCTION_GROUP, 0)
122#define RT286_SET_GPIO_DIRECTION\
123 VERB_CMD(AC_VERB_SET_GPIO_DIRECTION, RT286_AUDIO_FUNCTION_GROUP, 0)
124#define RT286_SET_GPIO_DATA\
125 VERB_CMD(AC_VERB_SET_GPIO_DATA, RT286_AUDIO_FUNCTION_GROUP, 0)
120 126
121/* Index registers */ 127/* Index registers */
122#define RT286_A_BIAS_CTRL1 0x01 128#define RT286_A_BIAS_CTRL1 0x01
@@ -131,6 +137,7 @@
131#define RT286_POWER_CTRL3 0x0f 137#define RT286_POWER_CTRL3 0x0f
132#define RT286_MIC1_DET_CTRL 0x19 138#define RT286_MIC1_DET_CTRL 0x19
133#define RT286_MISC_CTRL1 0x20 139#define RT286_MISC_CTRL1 0x20
140#define RT286_GPIO_CTRL 0x29
134#define RT286_IRQ_CTRL 0x33 141#define RT286_IRQ_CTRL 0x33
135#define RT286_PLL_CTRL1 0x49 142#define RT286_PLL_CTRL1 0x49
136#define RT286_CBJ_CTRL1 0x4f 143#define RT286_CBJ_CTRL1 0x4f
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 3e16a889a806..c9a4c5be083b 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -615,6 +615,87 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source,
615 615
616} 616}
617 617
618/**
619 * rt5645_sel_asrc_clk_src - select ASRC clock source for a set of filters
620 * @codec: SoC audio codec device.
621 * @filter_mask: mask of filters.
622 * @clk_src: clock source
623 *
624 * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5645 can
625 * only support standard 32fs or 64fs i2s format, ASRC should be enabled to
626 * support special i2s clock format such as Intel's 100fs(100 * sampling rate).
627 * ASRC function will track i2s clock and generate a corresponding system clock
628 * for codec. This function provides an API to select the clock source for a
629 * set of filters specified by the mask. And the codec driver will turn on ASRC
630 * for these filters if ASRC is selected as their clock source.
631 */
632int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec,
633 unsigned int filter_mask, unsigned int clk_src)
634{
635 unsigned int asrc2_mask = 0;
636 unsigned int asrc2_value = 0;
637 unsigned int asrc3_mask = 0;
638 unsigned int asrc3_value = 0;
639
640 switch (clk_src) {
641 case RT5645_CLK_SEL_SYS:
642 case RT5645_CLK_SEL_I2S1_ASRC:
643 case RT5645_CLK_SEL_I2S2_ASRC:
644 case RT5645_CLK_SEL_SYS2:
645 break;
646
647 default:
648 return -EINVAL;
649 }
650
651 if (filter_mask & RT5645_DA_STEREO_FILTER) {
652 asrc2_mask |= RT5645_DA_STO_CLK_SEL_MASK;
653 asrc2_value = (asrc2_value & ~RT5645_DA_STO_CLK_SEL_MASK)
654 | (clk_src << RT5645_DA_STO_CLK_SEL_SFT);
655 }
656
657 if (filter_mask & RT5645_DA_MONO_L_FILTER) {
658 asrc2_mask |= RT5645_DA_MONOL_CLK_SEL_MASK;
659 asrc2_value = (asrc2_value & ~RT5645_DA_MONOL_CLK_SEL_MASK)
660 | (clk_src << RT5645_DA_MONOL_CLK_SEL_SFT);
661 }
662
663 if (filter_mask & RT5645_DA_MONO_R_FILTER) {
664 asrc2_mask |= RT5645_DA_MONOR_CLK_SEL_MASK;
665 asrc2_value = (asrc2_value & ~RT5645_DA_MONOR_CLK_SEL_MASK)
666 | (clk_src << RT5645_DA_MONOR_CLK_SEL_SFT);
667 }
668
669 if (filter_mask & RT5645_AD_STEREO_FILTER) {
670 asrc2_mask |= RT5645_AD_STO1_CLK_SEL_MASK;
671 asrc2_value = (asrc2_value & ~RT5645_AD_STO1_CLK_SEL_MASK)
672 | (clk_src << RT5645_AD_STO1_CLK_SEL_SFT);
673 }
674
675 if (filter_mask & RT5645_AD_MONO_L_FILTER) {
676 asrc3_mask |= RT5645_AD_MONOL_CLK_SEL_MASK;
677 asrc3_value = (asrc3_value & ~RT5645_AD_MONOL_CLK_SEL_MASK)
678 | (clk_src << RT5645_AD_MONOL_CLK_SEL_SFT);
679 }
680
681 if (filter_mask & RT5645_AD_MONO_R_FILTER) {
682 asrc3_mask |= RT5645_AD_MONOR_CLK_SEL_MASK;
683 asrc3_value = (asrc3_value & ~RT5645_AD_MONOR_CLK_SEL_MASK)
684 | (clk_src << RT5645_AD_MONOR_CLK_SEL_SFT);
685 }
686
687 if (asrc2_mask)
688 snd_soc_update_bits(codec, RT5645_ASRC_2,
689 asrc2_mask, asrc2_value);
690
691 if (asrc3_mask)
692 snd_soc_update_bits(codec, RT5645_ASRC_3,
693 asrc3_mask, asrc3_value);
694
695 return 0;
696}
697EXPORT_SYMBOL_GPL(rt5645_sel_asrc_clk_src);
698
618/* Digital Mixer */ 699/* Digital Mixer */
619static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { 700static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = {
620 SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, 701 SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER,
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
index 74542310d3f0..dbfd98c22f4d 100644
--- a/sound/soc/codecs/rt5645.h
+++ b/sound/soc/codecs/rt5645.h
@@ -1120,50 +1120,27 @@
1120#define RT5645_DMIC_2_M_NOR (0x0 << 8) 1120#define RT5645_DMIC_2_M_NOR (0x0 << 8)
1121#define RT5645_DMIC_2_M_ASYN (0x1 << 8) 1121#define RT5645_DMIC_2_M_ASYN (0x1 << 8)
1122 1122
1123/* ASRC clock source selection (0x84, 0x85) */
1124#define RT5645_CLK_SEL_SYS (0x0)
1125#define RT5645_CLK_SEL_I2S1_ASRC (0x1)
1126#define RT5645_CLK_SEL_I2S2_ASRC (0x2)
1127#define RT5645_CLK_SEL_SYS2 (0x5)
1128
1123/* ASRC Control 2 (0x84) */ 1129/* ASRC Control 2 (0x84) */
1124#define RT5645_MDA_L_M_MASK (0x1 << 15) 1130#define RT5645_DA_STO_CLK_SEL_MASK (0xf << 12)
1125#define RT5645_MDA_L_M_SFT 15 1131#define RT5645_DA_STO_CLK_SEL_SFT 12
1126#define RT5645_MDA_L_M_NOR (0x0 << 15) 1132#define RT5645_DA_MONOL_CLK_SEL_MASK (0xf << 8)
1127#define RT5645_MDA_L_M_ASYN (0x1 << 15) 1133#define RT5645_DA_MONOL_CLK_SEL_SFT 8
1128#define RT5645_MDA_R_M_MASK (0x1 << 14) 1134#define RT5645_DA_MONOR_CLK_SEL_MASK (0xf << 4)
1129#define RT5645_MDA_R_M_SFT 14 1135#define RT5645_DA_MONOR_CLK_SEL_SFT 4
1130#define RT5645_MDA_R_M_NOR (0x0 << 14) 1136#define RT5645_AD_STO1_CLK_SEL_MASK (0xf << 0)
1131#define RT5645_MDA_R_M_ASYN (0x1 << 14) 1137#define RT5645_AD_STO1_CLK_SEL_SFT 0
1132#define RT5645_MAD_L_M_MASK (0x1 << 13)
1133#define RT5645_MAD_L_M_SFT 13
1134#define RT5645_MAD_L_M_NOR (0x0 << 13)
1135#define RT5645_MAD_L_M_ASYN (0x1 << 13)
1136#define RT5645_MAD_R_M_MASK (0x1 << 12)
1137#define RT5645_MAD_R_M_SFT 12
1138#define RT5645_MAD_R_M_NOR (0x0 << 12)
1139#define RT5645_MAD_R_M_ASYN (0x1 << 12)
1140#define RT5645_ADC_M_MASK (0x1 << 11)
1141#define RT5645_ADC_M_SFT 11
1142#define RT5645_ADC_M_NOR (0x0 << 11)
1143#define RT5645_ADC_M_ASYN (0x1 << 11)
1144#define RT5645_STO_DAC_M_MASK (0x1 << 5)
1145#define RT5645_STO_DAC_M_SFT 5
1146#define RT5645_STO_DAC_M_NOR (0x0 << 5)
1147#define RT5645_STO_DAC_M_ASYN (0x1 << 5)
1148#define RT5645_I2S1_R_D_MASK (0x1 << 4)
1149#define RT5645_I2S1_R_D_SFT 4
1150#define RT5645_I2S1_R_D_DIS (0x0 << 4)
1151#define RT5645_I2S1_R_D_EN (0x1 << 4)
1152#define RT5645_I2S2_R_D_MASK (0x1 << 3)
1153#define RT5645_I2S2_R_D_SFT 3
1154#define RT5645_I2S2_R_D_DIS (0x0 << 3)
1155#define RT5645_I2S2_R_D_EN (0x1 << 3)
1156#define RT5645_PRE_SCLK_MASK (0x3)
1157#define RT5645_PRE_SCLK_SFT 0
1158#define RT5645_PRE_SCLK_512 (0x0)
1159#define RT5645_PRE_SCLK_1024 (0x1)
1160#define RT5645_PRE_SCLK_2048 (0x2)
1161 1138
1162/* ASRC Control 3 (0x85) */ 1139/* ASRC Control 3 (0x85) */
1163#define RT5645_I2S1_RATE_MASK (0xf << 12) 1140#define RT5645_AD_MONOL_CLK_SEL_MASK (0xf << 4)
1164#define RT5645_I2S1_RATE_SFT 12 1141#define RT5645_AD_MONOL_CLK_SEL_SFT 4
1165#define RT5645_I2S2_RATE_MASK (0xf << 8) 1142#define RT5645_AD_MONOR_CLK_SEL_MASK (0xf << 0)
1166#define RT5645_I2S2_RATE_SFT 8 1143#define RT5645_AD_MONOR_CLK_SEL_SFT 0
1167 1144
1168/* ASRC Control 4 (0x89) */ 1145/* ASRC Control 4 (0x89) */
1169#define RT5645_I2S1_PD_MASK (0x7 << 12) 1146#define RT5645_I2S1_PD_MASK (0x7 << 12)
@@ -2189,6 +2166,19 @@ enum {
2189 CODEC_TYPE_RT5650, 2166 CODEC_TYPE_RT5650,
2190}; 2167};
2191 2168
2169/* filter mask */
2170enum {
2171 RT5645_DA_STEREO_FILTER = 0x1,
2172 RT5645_DA_MONO_L_FILTER = (0x1 << 1),
2173 RT5645_DA_MONO_R_FILTER = (0x1 << 2),
2174 RT5645_AD_STEREO_FILTER = (0x1 << 3),
2175 RT5645_AD_MONO_L_FILTER = (0x1 << 4),
2176 RT5645_AD_MONO_R_FILTER = (0x1 << 5),
2177};
2178
2179int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec,
2180 unsigned int filter_mask, unsigned int clk_src);
2181
2192struct rt5645_priv { 2182struct rt5645_priv {
2193 struct snd_soc_codec *codec; 2183 struct snd_soc_codec *codec;
2194 struct rt5645_platform_data pdata; 2184 struct rt5645_platform_data pdata;
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/intel/Kconfig b/sound/soc/intel/Kconfig
index c0813f546d1f..ee03dbdda235 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -110,3 +110,14 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
110 platforms with RT5672 audio codec. 110 platforms with RT5672 audio codec.
111 Say Y if you have such a device 111 Say Y if you have such a device
112 If unsure select "N". 112 If unsure select "N".
113
114config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
115 tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645 codec"
116 depends on X86_INTEL_LPSS
117 select SND_SOC_RT5645
118 select SND_SST_MFLD_PLATFORM
119 select SND_SST_IPC_ACPI
120 help
121 This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
122 platforms with RT5645 audio codec.
123 If unsure select "N".
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile
index e928ec385300..a8e53c45c6b6 100644
--- a/sound/soc/intel/Makefile
+++ b/sound/soc/intel/Makefile
@@ -28,6 +28,7 @@ snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
28snd-soc-sst-broadwell-objs := broadwell.o 28snd-soc-sst-broadwell-objs := broadwell.o
29snd-soc-sst-bytcr-dpcm-rt5640-objs := bytcr_dpcm_rt5640.o 29snd-soc-sst-bytcr-dpcm-rt5640-objs := bytcr_dpcm_rt5640.o
30snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o 30snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
31snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
31 32
32obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o 33obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
33obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o 34obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
@@ -35,6 +36,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
35obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o 36obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
36obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-dpcm-rt5640.o 37obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-dpcm-rt5640.o
37obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o 38obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
39obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
38 40
39# DSP driver 41# DSP driver
40obj-$(CONFIG_SND_SST_IPC) += sst/ 42obj-$(CONFIG_SND_SST_IPC) += sst/
diff --git a/sound/soc/intel/cht_bsw_rt5645.c b/sound/soc/intel/cht_bsw_rt5645.c
new file mode 100644
index 000000000000..bd29617a9ab9
--- /dev/null
+++ b/sound/soc/intel/cht_bsw_rt5645.c
@@ -0,0 +1,326 @@
1/*
2 * cht-bsw-rt5645.c - ASoc Machine driver for Intel Cherryview-based platforms
3 * Cherrytrail and Braswell, with RT5645 codec.
4 *
5 * Copyright (C) 2015 Intel Corp
6 * Author: Fang, Yang A <yang.a.fang@intel.com>
7 * N,Harshapriya <harshapriya.n@intel.com>
8 * This file is modified from cht_bsw_rt5672.c
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 */
22
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/soc.h>
29#include <sound/jack.h>
30#include "../codecs/rt5645.h"
31#include "sst-atom-controls.h"
32
33#define CHT_PLAT_CLK_3_HZ 19200000
34#define CHT_CODEC_DAI "rt5645-aif1"
35
36struct cht_mc_private {
37 struct snd_soc_jack hp_jack;
38 struct snd_soc_jack mic_jack;
39};
40
41static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
42{
43 int i;
44
45 for (i = 0; i < card->num_rtd; i++) {
46 struct snd_soc_pcm_runtime *rtd;
47
48 rtd = card->rtd + i;
49 if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI,
50 strlen(CHT_CODEC_DAI)))
51 return rtd->codec_dai;
52 }
53 return NULL;
54}
55
56static int platform_clock_control(struct snd_soc_dapm_widget *w,
57 struct snd_kcontrol *k, int event)
58{
59 struct snd_soc_dapm_context *dapm = w->dapm;
60 struct snd_soc_card *card = dapm->card;
61 struct snd_soc_dai *codec_dai;
62 int ret;
63
64 codec_dai = cht_get_codec_dai(card);
65 if (!codec_dai) {
66 dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
67 return -EIO;
68 }
69
70 if (!SND_SOC_DAPM_EVENT_OFF(event))
71 return 0;
72
73 /* Set codec sysclk source to its internal clock because codec PLL will
74 * be off when idle and MCLK will also be off by ACPI when codec is
75 * runtime suspended. Codec needs clock for jack detection and button
76 * press.
77 */
78 ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK,
79 0, SND_SOC_CLOCK_IN);
80 if (ret < 0) {
81 dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
82 return ret;
83 }
84
85 return 0;
86}
87
88static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
89 SND_SOC_DAPM_HP("Headphone", NULL),
90 SND_SOC_DAPM_MIC("Headset Mic", NULL),
91 SND_SOC_DAPM_MIC("Int Mic", NULL),
92 SND_SOC_DAPM_SPK("Ext Spk", NULL),
93 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
94 platform_clock_control, SND_SOC_DAPM_POST_PMD),
95};
96
97static const struct snd_soc_dapm_route cht_audio_map[] = {
98 {"IN1P", NULL, "Headset Mic"},
99 {"IN1N", NULL, "Headset Mic"},
100 {"DMIC L1", NULL, "Int Mic"},
101 {"DMIC R1", NULL, "Int Mic"},
102 {"Headphone", NULL, "HPOL"},
103 {"Headphone", NULL, "HPOR"},
104 {"Ext Spk", NULL, "SPOL"},
105 {"Ext Spk", NULL, "SPOR"},
106 {"AIF1 Playback", NULL, "ssp2 Tx"},
107 {"ssp2 Tx", NULL, "codec_out0"},
108 {"ssp2 Tx", NULL, "codec_out1"},
109 {"codec_in0", NULL, "ssp2 Rx" },
110 {"codec_in1", NULL, "ssp2 Rx" },
111 {"ssp2 Rx", NULL, "AIF1 Capture"},
112 {"Headphone", NULL, "Platform Clock"},
113 {"Headset Mic", NULL, "Platform Clock"},
114 {"Int Mic", NULL, "Platform Clock"},
115 {"Ext Spk", NULL, "Platform Clock"},
116};
117
118static const struct snd_kcontrol_new cht_mc_controls[] = {
119 SOC_DAPM_PIN_SWITCH("Headphone"),
120 SOC_DAPM_PIN_SWITCH("Headset Mic"),
121 SOC_DAPM_PIN_SWITCH("Int Mic"),
122 SOC_DAPM_PIN_SWITCH("Ext Spk"),
123};
124
125static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
126 struct snd_pcm_hw_params *params)
127{
128 struct snd_soc_pcm_runtime *rtd = substream->private_data;
129 struct snd_soc_dai *codec_dai = rtd->codec_dai;
130 int ret;
131
132 /* set codec PLL source to the 19.2MHz platform clock (MCLK) */
133 ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK,
134 CHT_PLAT_CLK_3_HZ, params_rate(params) * 512);
135 if (ret < 0) {
136 dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
137 return ret;
138 }
139
140 ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_PLL1,
141 params_rate(params) * 512, SND_SOC_CLOCK_IN);
142 if (ret < 0) {
143 dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
144 return ret;
145 }
146
147 return 0;
148}
149
150static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
151{
152 int ret;
153 struct snd_soc_codec *codec = runtime->codec;
154 struct snd_soc_dai *codec_dai = runtime->codec_dai;
155 struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
156
157 /* Select clk_i2s1_asrc as ASRC clock source */
158 rt5645_sel_asrc_clk_src(codec,
159 RT5645_DA_STEREO_FILTER |
160 RT5645_DA_MONO_L_FILTER |
161 RT5645_DA_MONO_R_FILTER |
162 RT5645_AD_STEREO_FILTER,
163 RT5645_CLK_SEL_I2S1_ASRC);
164
165 /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */
166 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24);
167 if (ret < 0) {
168 dev_err(runtime->dev, "can't set codec TDM slot %d\n", ret);
169 return ret;
170 }
171
172 ret = snd_soc_jack_new(codec, "Headphone Jack",
173 SND_JACK_HEADPHONE,
174 &ctx->hp_jack);
175 if (ret) {
176 dev_err(runtime->dev, "HP jack creation failed %d\n", ret);
177 return ret;
178 }
179
180 ret = snd_soc_jack_new(codec, "Mic Jack",
181 SND_JACK_MICROPHONE,
182 &ctx->mic_jack);
183 if (ret) {
184 dev_err(runtime->dev, "Mic jack creation failed %d\n", ret);
185 return ret;
186 }
187
188 rt5645_set_jack_detect(codec, &ctx->hp_jack, &ctx->mic_jack);
189
190 return ret;
191}
192
193static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
194 struct snd_pcm_hw_params *params)
195{
196 struct snd_interval *rate = hw_param_interval(params,
197 SNDRV_PCM_HW_PARAM_RATE);
198 struct snd_interval *channels = hw_param_interval(params,
199 SNDRV_PCM_HW_PARAM_CHANNELS);
200
201 /* The DSP will covert the FE rate to 48k, stereo, 24bits */
202 rate->min = rate->max = 48000;
203 channels->min = channels->max = 2;
204
205 /* set SSP2 to 24-bit */
206 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
207 SNDRV_PCM_HW_PARAM_FIRST_MASK],
208 SNDRV_PCM_FORMAT_S24_LE);
209 return 0;
210}
211
212static unsigned int rates_48000[] = {
213 48000,
214};
215
216static struct snd_pcm_hw_constraint_list constraints_48000 = {
217 .count = ARRAY_SIZE(rates_48000),
218 .list = rates_48000,
219};
220
221static int cht_aif1_startup(struct snd_pcm_substream *substream)
222{
223 return snd_pcm_hw_constraint_list(substream->runtime, 0,
224 SNDRV_PCM_HW_PARAM_RATE,
225 &constraints_48000);
226}
227
228static struct snd_soc_ops cht_aif1_ops = {
229 .startup = cht_aif1_startup,
230};
231
232static struct snd_soc_ops cht_be_ssp2_ops = {
233 .hw_params = cht_aif1_hw_params,
234};
235
236static struct snd_soc_dai_link cht_dailink[] = {
237 [MERR_DPCM_AUDIO] = {
238 .name = "Audio Port",
239 .stream_name = "Audio",
240 .cpu_dai_name = "media-cpu-dai",
241 .codec_dai_name = "snd-soc-dummy-dai",
242 .codec_name = "snd-soc-dummy",
243 .platform_name = "sst-mfld-platform",
244 .ignore_suspend = 1,
245 .dynamic = 1,
246 .dpcm_playback = 1,
247 .dpcm_capture = 1,
248 .ops = &cht_aif1_ops,
249 },
250 [MERR_DPCM_COMPR] = {
251 .name = "Compressed Port",
252 .stream_name = "Compress",
253 .cpu_dai_name = "compress-cpu-dai",
254 .codec_dai_name = "snd-soc-dummy-dai",
255 .codec_name = "snd-soc-dummy",
256 .platform_name = "sst-mfld-platform",
257 },
258 /* CODEC<->CODEC link */
259 /* back ends */
260 {
261 .name = "SSP2-Codec",
262 .be_id = 1,
263 .cpu_dai_name = "ssp2-port",
264 .platform_name = "sst-mfld-platform",
265 .no_pcm = 1,
266 .codec_dai_name = "rt5645-aif1",
267 .codec_name = "i2c-10EC5645:00",
268 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF
269 | SND_SOC_DAIFMT_CBS_CFS,
270 .init = cht_codec_init,
271 .be_hw_params_fixup = cht_codec_fixup,
272 .ignore_suspend = 1,
273 .dpcm_playback = 1,
274 .dpcm_capture = 1,
275 .ops = &cht_be_ssp2_ops,
276 },
277};
278
279/* SoC card */
280static struct snd_soc_card snd_soc_card_cht = {
281 .name = "chtrt5645",
282 .dai_link = cht_dailink,
283 .num_links = ARRAY_SIZE(cht_dailink),
284 .dapm_widgets = cht_dapm_widgets,
285 .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets),
286 .dapm_routes = cht_audio_map,
287 .num_dapm_routes = ARRAY_SIZE(cht_audio_map),
288 .controls = cht_mc_controls,
289 .num_controls = ARRAY_SIZE(cht_mc_controls),
290};
291
292static int snd_cht_mc_probe(struct platform_device *pdev)
293{
294 int ret_val = 0;
295 struct cht_mc_private *drv;
296
297 drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
298 if (!drv)
299 return -ENOMEM;
300
301 snd_soc_card_cht.dev = &pdev->dev;
302 snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
303 ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
304 if (ret_val) {
305 dev_err(&pdev->dev,
306 "snd_soc_register_card failed %d\n", ret_val);
307 return ret_val;
308 }
309 platform_set_drvdata(pdev, &snd_soc_card_cht);
310 return ret_val;
311}
312
313static struct platform_driver snd_cht_mc_driver = {
314 .driver = {
315 .name = "cht-bsw-rt5645",
316 .pm = &snd_soc_pm_ops,
317 },
318 .probe = snd_cht_mc_probe,
319};
320
321module_platform_driver(snd_cht_mc_driver)
322
323MODULE_DESCRIPTION("ASoC Intel(R) Braswell Machine driver");
324MODULE_AUTHOR("Fang, Yang A,N,Harshapriya");
325MODULE_LICENSE("GPL v2");
326MODULE_ALIAS("platform:cht-bsw-rt5645");
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c
index a282179a3064..0ab1309ef274 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/sst-haswell-ipc.c
@@ -338,12 +338,6 @@ static inline u32 msg_get_stage_type(u32 msg)
338 return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; 338 return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT;
339} 339}
340 340
341static inline u32 msg_set_stage_type(u32 msg, u32 type)
342{
343 return (msg & ~IPC_STG_TYPE_MASK) +
344 (type << IPC_STG_TYPE_SHIFT);
345}
346
347static inline u32 msg_get_stream_id(u32 msg) 341static inline u32 msg_get_stream_id(u32 msg)
348{ 342{
349 return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT; 343 return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT;
@@ -970,45 +964,6 @@ int sst_hsw_fw_get_version(struct sst_hsw *hsw,
970} 964}
971 965
972/* Mixer Controls */ 966/* Mixer Controls */
973int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
974 u32 stage_id, u32 channel)
975{
976 int ret;
977
978 ret = sst_hsw_stream_get_volume(hsw, stream, stage_id, channel,
979 &stream->mute_volume[channel]);
980 if (ret < 0)
981 return ret;
982
983 ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, 0);
984 if (ret < 0) {
985 dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n",
986 stream->reply.stream_hw_id, channel);
987 return ret;
988 }
989
990 stream->mute[channel] = 1;
991 return 0;
992}
993
994int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
995 u32 stage_id, u32 channel)
996
997{
998 int ret;
999
1000 stream->mute[channel] = 0;
1001 ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel,
1002 stream->mute_volume[channel]);
1003 if (ret < 0) {
1004 dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n",
1005 stream->reply.stream_hw_id, channel);
1006 return ret;
1007 }
1008
1009 return 0;
1010}
1011
1012int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, 967int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
1013 u32 stage_id, u32 channel, u32 *volume) 968 u32 stage_id, u32 channel, u32 *volume)
1014{ 969{
@@ -1022,17 +977,6 @@ int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream
1022 return 0; 977 return 0;
1023} 978}
1024 979
1025int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw,
1026 struct sst_hsw_stream *stream, u64 curve_duration,
1027 enum sst_hsw_volume_curve curve)
1028{
1029 /* curve duration in steps of 100ns */
1030 stream->vol_req.curve_duration = curve_duration;
1031 stream->vol_req.curve_type = curve;
1032
1033 return 0;
1034}
1035
1036/* stream volume */ 980/* stream volume */
1037int sst_hsw_stream_set_volume(struct sst_hsw *hsw, 981int sst_hsw_stream_set_volume(struct sst_hsw *hsw,
1038 struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) 982 struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume)
@@ -1084,42 +1028,6 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw,
1084 return 0; 1028 return 0;
1085} 1029}
1086 1030
1087int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel)
1088{
1089 int ret;
1090
1091 ret = sst_hsw_mixer_get_volume(hsw, stage_id, channel,
1092 &hsw->mute_volume[channel]);
1093 if (ret < 0)
1094 return ret;
1095
1096 ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, 0);
1097 if (ret < 0) {
1098 dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n",
1099 channel);
1100 return ret;
1101 }
1102
1103 hsw->mute[channel] = 1;
1104 return 0;
1105}
1106
1107int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel)
1108{
1109 int ret;
1110
1111 ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel,
1112 hsw->mixer_info.volume_register_address[channel]);
1113 if (ret < 0) {
1114 dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n",
1115 channel);
1116 return ret;
1117 }
1118
1119 hsw->mute[channel] = 0;
1120 return 0;
1121}
1122
1123int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, 1031int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
1124 u32 *volume) 1032 u32 *volume)
1125{ 1033{
@@ -1133,16 +1041,6 @@ int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
1133 return 0; 1041 return 0;
1134} 1042}
1135 1043
1136int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw,
1137 u64 curve_duration, enum sst_hsw_volume_curve curve)
1138{
1139 /* curve duration in steps of 100ns */
1140 hsw->curve_duration = curve_duration;
1141 hsw->curve_type = curve;
1142
1143 return 0;
1144}
1145
1146/* global mixer volume */ 1044/* global mixer volume */
1147int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, 1045int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
1148 u32 volume) 1046 u32 volume)
@@ -1451,48 +1349,6 @@ int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
1451 1349
1452/* Stream Information - these calls could be inline but we want the IPC 1350/* Stream Information - these calls could be inline but we want the IPC
1453 ABI to be opaque to client PCM drivers to cope with any future ABI changes */ 1351 ABI to be opaque to client PCM drivers to cope with any future ABI changes */
1454int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw,
1455 struct sst_hsw_stream *stream)
1456{
1457 return stream->reply.stream_hw_id;
1458}
1459
1460int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw,
1461 struct sst_hsw_stream *stream)
1462{
1463 return stream->reply.mixer_hw_id;
1464}
1465
1466u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw,
1467 struct sst_hsw_stream *stream)
1468{
1469 return stream->reply.read_position_register_address;
1470}
1471
1472u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw,
1473 struct sst_hsw_stream *stream)
1474{
1475 return stream->reply.presentation_position_register_address;
1476}
1477
1478u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw,
1479 struct sst_hsw_stream *stream, u32 channel)
1480{
1481 if (channel >= 2)
1482 return 0;
1483
1484 return stream->reply.peak_meter_register_address[channel];
1485}
1486
1487u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw,
1488 struct sst_hsw_stream *stream, u32 channel)
1489{
1490 if (channel >= 2)
1491 return 0;
1492
1493 return stream->reply.volume_register_address[channel];
1494}
1495
1496int sst_hsw_mixer_get_info(struct sst_hsw *hsw) 1352int sst_hsw_mixer_get_info(struct sst_hsw *hsw)
1497{ 1353{
1498 struct sst_hsw_ipc_stream_info_reply *reply; 1354 struct sst_hsw_ipc_stream_info_reply *reply;
@@ -1630,30 +1486,6 @@ u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw,
1630 return ppos; 1486 return ppos;
1631} 1487}
1632 1488
1633int sst_hsw_stream_set_write_position(struct sst_hsw *hsw,
1634 struct sst_hsw_stream *stream, u32 stage_id, u32 position)
1635{
1636 u32 header;
1637 int ret;
1638
1639 trace_stream_write_position(stream->reply.stream_hw_id, position);
1640
1641 header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) |
1642 IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE);
1643 header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT);
1644 header |= (IPC_STG_SET_WRITE_POSITION << IPC_STG_TYPE_SHIFT);
1645 header |= (stage_id << IPC_STG_ID_SHIFT);
1646 stream->wpos.position = position;
1647
1648 ret = ipc_tx_message_nowait(hsw, header, &stream->wpos,
1649 sizeof(stream->wpos));
1650 if (ret < 0)
1651 dev_err(hsw->dev, "error: stream %d set position %d failed\n",
1652 stream->reply.stream_hw_id, position);
1653
1654 return ret;
1655}
1656
1657/* physical BE config */ 1489/* physical BE config */
1658int sst_hsw_device_set_config(struct sst_hsw *hsw, 1490int sst_hsw_device_set_config(struct sst_hsw *hsw,
1659 enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, 1491 enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk,
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h
index 138e894ab413..c1ad901342f2 100644
--- a/sound/soc/intel/sst-haswell-ipc.h
+++ b/sound/soc/intel/sst-haswell-ipc.h
@@ -376,32 +376,17 @@ int sst_hsw_fw_get_version(struct sst_hsw *hsw,
376u32 create_channel_map(enum sst_hsw_channel_config config); 376u32 create_channel_map(enum sst_hsw_channel_config config);
377 377
378/* Stream Mixer Controls - */ 378/* Stream Mixer Controls - */
379int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
380 u32 stage_id, u32 channel);
381int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
382 u32 stage_id, u32 channel);
383
384int sst_hsw_stream_set_volume(struct sst_hsw *hsw, 379int sst_hsw_stream_set_volume(struct sst_hsw *hsw,
385 struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume); 380 struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume);
386int sst_hsw_stream_get_volume(struct sst_hsw *hsw, 381int sst_hsw_stream_get_volume(struct sst_hsw *hsw,
387 struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume); 382 struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume);
388 383
389int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw,
390 struct sst_hsw_stream *stream, u64 curve_duration,
391 enum sst_hsw_volume_curve curve);
392
393/* Global Mixer Controls - */ 384/* Global Mixer Controls - */
394int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel);
395int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel);
396
397int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, 385int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
398 u32 volume); 386 u32 volume);
399int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, 387int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
400 u32 *volume); 388 u32 *volume);
401 389
402int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw,
403 u64 curve_duration, enum sst_hsw_volume_curve curve);
404
405/* Stream API */ 390/* Stream API */
406struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, 391struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id,
407 u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), 392 u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data),
@@ -440,18 +425,6 @@ int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw,
440 struct sst_hsw_stream *stream, u32 offset, u32 size); 425 struct sst_hsw_stream *stream, u32 offset, u32 size);
441int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, 426int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw,
442 struct sst_hsw_stream *stream, u32 offset, u32 size); 427 struct sst_hsw_stream *stream, u32 offset, u32 size);
443int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw,
444 struct sst_hsw_stream *stream);
445int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw,
446 struct sst_hsw_stream *stream);
447u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw,
448 struct sst_hsw_stream *stream);
449u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw,
450 struct sst_hsw_stream *stream);
451u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw,
452 struct sst_hsw_stream *stream, u32 channel);
453u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw,
454 struct sst_hsw_stream *stream, u32 channel);
455int sst_hsw_mixer_get_info(struct sst_hsw *hsw); 428int sst_hsw_mixer_get_info(struct sst_hsw *hsw);
456 429
457/* Stream ALSA trigger operations */ 430/* Stream ALSA trigger operations */
@@ -466,8 +439,6 @@ int sst_hsw_stream_get_read_pos(struct sst_hsw *hsw,
466 struct sst_hsw_stream *stream, u32 *position); 439 struct sst_hsw_stream *stream, u32 *position);
467int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, 440int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw,
468 struct sst_hsw_stream *stream, u32 *position); 441 struct sst_hsw_stream *stream, u32 *position);
469int sst_hsw_stream_set_write_position(struct sst_hsw *hsw,
470 struct sst_hsw_stream *stream, u32 stage_id, u32 position);
471u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw, 442u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw,
472 struct sst_hsw_stream *stream); 443 struct sst_hsw_stream *stream);
473u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, 444u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw,
@@ -481,8 +452,6 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw,
481/* DX Config */ 452/* DX Config */
482int sst_hsw_dx_set_state(struct sst_hsw *hsw, 453int sst_hsw_dx_set_state(struct sst_hsw *hsw,
483 enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx); 454 enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx);
484int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item,
485 u32 *offset, u32 *size, u32 *source);
486 455
487/* init */ 456/* init */
488int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata); 457int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata);
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c
index ad7f4a51e138..78fa01be57f2 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -119,8 +119,9 @@ struct hsw_pcm_data {
119}; 119};
120 120
121enum hsw_pm_state { 121enum hsw_pm_state {
122 HSW_PM_STATE_D3 = 0, 122 HSW_PM_STATE_D0 = 0,
123 HSW_PM_STATE_D0 = 1, 123 HSW_PM_STATE_RTD3 = 1,
124 HSW_PM_STATE_D3 = 2,
124}; 125};
125 126
126/* private data for the driver */ 127/* private data for the driver */
@@ -1035,12 +1036,12 @@ static int hsw_pcm_runtime_suspend(struct device *dev)
1035 struct hsw_priv_data *pdata = dev_get_drvdata(dev); 1036 struct hsw_priv_data *pdata = dev_get_drvdata(dev);
1036 struct sst_hsw *hsw = pdata->hsw; 1037 struct sst_hsw *hsw = pdata->hsw;
1037 1038
1038 if (pdata->pm_state == HSW_PM_STATE_D3) 1039 if (pdata->pm_state >= HSW_PM_STATE_RTD3)
1039 return 0; 1040 return 0;
1040 1041
1041 sst_hsw_dsp_runtime_suspend(hsw); 1042 sst_hsw_dsp_runtime_suspend(hsw);
1042 sst_hsw_dsp_runtime_sleep(hsw); 1043 sst_hsw_dsp_runtime_sleep(hsw);
1043 pdata->pm_state = HSW_PM_STATE_D3; 1044 pdata->pm_state = HSW_PM_STATE_RTD3;
1044 1045
1045 return 0; 1046 return 0;
1046} 1047}
@@ -1051,7 +1052,7 @@ static int hsw_pcm_runtime_resume(struct device *dev)
1051 struct sst_hsw *hsw = pdata->hsw; 1052 struct sst_hsw *hsw = pdata->hsw;
1052 int ret; 1053 int ret;
1053 1054
1054 if (pdata->pm_state == HSW_PM_STATE_D0) 1055 if (pdata->pm_state != HSW_PM_STATE_RTD3)
1055 return 0; 1056 return 0;
1056 1057
1057 ret = sst_hsw_dsp_load(hsw); 1058 ret = sst_hsw_dsp_load(hsw);
@@ -1091,7 +1092,7 @@ static void hsw_pcm_complete(struct device *dev)
1091 struct hsw_pcm_data *pcm_data; 1092 struct hsw_pcm_data *pcm_data;
1092 int i, err; 1093 int i, err;
1093 1094
1094 if (pdata->pm_state == HSW_PM_STATE_D0) 1095 if (pdata->pm_state != HSW_PM_STATE_D3)
1095 return; 1096 return;
1096 1097
1097 err = sst_hsw_dsp_load(hsw); 1098 err = sst_hsw_dsp_load(hsw);
@@ -1139,41 +1140,42 @@ static int hsw_pcm_prepare(struct device *dev)
1139 1140
1140 if (pdata->pm_state == HSW_PM_STATE_D3) 1141 if (pdata->pm_state == HSW_PM_STATE_D3)
1141 return 0; 1142 return 0;
1142 /* suspend all active streams */ 1143 else if (pdata->pm_state == HSW_PM_STATE_D0) {
1143 for (i = 0; i < ARRAY_SIZE(mod_map); i++) { 1144 /* suspend all active streams */
1144 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; 1145 for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
1146 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
1147
1148 if (!pcm_data->substream)
1149 continue;
1150 dev_dbg(dev, "suspending pcm %d\n", i);
1151 snd_pcm_suspend_all(pcm_data->hsw_pcm);
1152
1153 /* We need to wait until the DSP FW stops the streams */
1154 msleep(2);
1155 }
1145 1156
1146 if (!pcm_data->substream) 1157 /* preserve persistent memory */
1147 continue; 1158 for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
1148 dev_dbg(dev, "suspending pcm %d\n", i); 1159 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
1149 snd_pcm_suspend_all(pcm_data->hsw_pcm); 1160
1161 if (!pcm_data->substream)
1162 continue;
1150 1163
1151 /* We need to wait until the DSP FW stops the streams */ 1164 dev_dbg(dev, "saving context pcm %d\n", i);
1152 msleep(2); 1165 err = sst_module_runtime_save(pcm_data->runtime,
1166 &pcm_data->context);
1167 if (err < 0)
1168 dev_err(dev, "failed to save context for PCM %d\n", i);
1169 }
1170 /* enter D3 state and stall */
1171 sst_hsw_dsp_runtime_suspend(hsw);
1172 /* put the DSP to sleep */
1173 sst_hsw_dsp_runtime_sleep(hsw);
1153 } 1174 }
1154 1175
1155 snd_soc_suspend(pdata->soc_card->dev); 1176 snd_soc_suspend(pdata->soc_card->dev);
1156 snd_soc_poweroff(pdata->soc_card->dev); 1177 snd_soc_poweroff(pdata->soc_card->dev);
1157 1178
1158 /* enter D3 state and stall */
1159 sst_hsw_dsp_runtime_suspend(hsw);
1160
1161 /* preserve persistent memory */
1162 for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
1163 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
1164
1165 if (!pcm_data->substream)
1166 continue;
1167
1168 dev_dbg(dev, "saving context pcm %d\n", i);
1169 err = sst_module_runtime_save(pcm_data->runtime,
1170 &pcm_data->context);
1171 if (err < 0)
1172 dev_err(dev, "failed to save context for PCM %d\n", i);
1173 }
1174
1175 /* put the DSP to sleep */
1176 sst_hsw_dsp_runtime_sleep(hsw);
1177 pdata->pm_state = HSW_PM_STATE_D3; 1179 pdata->pm_state = HSW_PM_STATE_D3;
1178 1180
1179 return 0; 1181 return 0;
diff --git a/sound/soc/intel/sst/sst.h b/sound/soc/intel/sst/sst.h
index 7f4bbfcbc6f5..562bc483d6b7 100644
--- a/sound/soc/intel/sst/sst.h
+++ b/sound/soc/intel/sst/sst.h
@@ -58,6 +58,7 @@ enum sst_algo_ops {
58#define SST_BLOCK_TIMEOUT 1000 58#define SST_BLOCK_TIMEOUT 1000
59 59
60#define FW_SIGNATURE_SIZE 4 60#define FW_SIGNATURE_SIZE 4
61#define FW_NAME_SIZE 32
61 62
62/* stream states */ 63/* stream states */
63enum sst_stream_states { 64enum sst_stream_states {
@@ -426,7 +427,7 @@ struct intel_sst_drv {
426 * Holder for firmware name. Due to async call it needs to be 427 * Holder for firmware name. Due to async call it needs to be
427 * persistent till worker thread gets called 428 * persistent till worker thread gets called
428 */ 429 */
429 char firmware_name[20]; 430 char firmware_name[FW_NAME_SIZE];
430}; 431};
431 432
432/* misc definitions */ 433/* misc definitions */
diff --git a/sound/soc/intel/sst/sst_acpi.c b/sound/soc/intel/sst/sst_acpi.c
index 43bc1c4b9207..b782dfdcdbba 100644
--- a/sound/soc/intel/sst/sst_acpi.c
+++ b/sound/soc/intel/sst/sst_acpi.c
@@ -47,7 +47,7 @@ struct sst_machines {
47 char board[32]; 47 char board[32];
48 char machine[32]; 48 char machine[32];
49 void (*machine_quirk)(void); 49 void (*machine_quirk)(void);
50 char firmware[32]; 50 char firmware[FW_NAME_SIZE];
51 struct sst_platform_info *pdata; 51 struct sst_platform_info *pdata;
52 52
53}; 53};
@@ -350,9 +350,9 @@ static struct sst_machines sst_acpi_bytcr[] = {
350 350
351/* Cherryview-based platforms: CherryTrail and Braswell */ 351/* Cherryview-based platforms: CherryTrail and Braswell */
352static struct sst_machines sst_acpi_chv[] = { 352static struct sst_machines sst_acpi_chv[] = {
353 {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "fw_sst_22a8.bin", 353 {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin",
354 &chv_platform_data }, 354 &chv_platform_data },
355 {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "fw_sst_22a8.bin", 355 {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
356 &chv_platform_data }, 356 &chv_platform_data },
357 {}, 357 {},
358}; 358};
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index d3d45c6f064f..07f77815a586 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -14,6 +14,8 @@
14 14
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/of.h>
18#include <linux/of_device.h>
17#include <linux/kernel.h> 19#include <linux/kernel.h>
18#include <linux/module.h> 20#include <linux/module.h>
19#include <linux/platform_device.h> 21#include <linux/platform_device.h>
@@ -83,6 +85,8 @@
83#define JZ_AIC_I2S_STATUS_BUSY BIT(2) 85#define JZ_AIC_I2S_STATUS_BUSY BIT(2)
84 86
85#define JZ_AIC_CLK_DIV_MASK 0xf 87#define JZ_AIC_CLK_DIV_MASK 0xf
88#define I2SDIV_DV_SHIFT 8
89#define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT)
86 90
87struct jz4740_i2s { 91struct jz4740_i2s {
88 struct resource *mem; 92 struct resource *mem;
@@ -237,10 +241,14 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
237{ 241{
238 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 242 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
239 unsigned int sample_size; 243 unsigned int sample_size;
240 uint32_t ctrl; 244 uint32_t ctrl, div_reg;
245 int div;
241 246
242 ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); 247 ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
243 248
249 div_reg = jz4740_i2s_read(i2s, JZ_REG_AIC_CLK_DIV);
250 div = clk_get_rate(i2s->clk_i2s) / (64 * params_rate(params));
251
244 switch (params_format(params)) { 252 switch (params_format(params)) {
245 case SNDRV_PCM_FORMAT_S8: 253 case SNDRV_PCM_FORMAT_S8:
246 sample_size = 0; 254 sample_size = 0;
@@ -264,7 +272,10 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
264 ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; 272 ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET;
265 } 273 }
266 274
275 div_reg &= ~I2SDIV_DV_MASK;
276 div_reg |= (div - 1) << I2SDIV_DV_SHIFT;
267 jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); 277 jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
278 jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div_reg);
268 279
269 return 0; 280 return 0;
270} 281}
@@ -415,6 +426,13 @@ static const struct snd_soc_component_driver jz4740_i2s_component = {
415 .name = "jz4740-i2s", 426 .name = "jz4740-i2s",
416}; 427};
417 428
429#ifdef CONFIG_OF
430static const struct of_device_id jz4740_of_matches[] = {
431 { .compatible = "ingenic,jz4740-i2s" },
432 { /* sentinel */ }
433};
434#endif
435
418static int jz4740_i2s_dev_probe(struct platform_device *pdev) 436static int jz4740_i2s_dev_probe(struct platform_device *pdev)
419{ 437{
420 struct jz4740_i2s *i2s; 438 struct jz4740_i2s *i2s;
@@ -455,6 +473,7 @@ static struct platform_driver jz4740_i2s_driver = {
455 .probe = jz4740_i2s_dev_probe, 473 .probe = jz4740_i2s_dev_probe,
456 .driver = { 474 .driver = {
457 .name = "jz4740-i2s", 475 .name = "jz4740-i2s",
476 .of_match_table = of_match_ptr(jz4740_of_matches)
458 }, 477 },
459}; 478};
460 479
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index e817a2f43ea8..3cebf6ca03df 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -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
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/soc-core.c b/sound/soc/soc-core.c
index d94434d6138e..30579ca5bacb 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2419,8 +2419,8 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
2419 card->instantiated = false; 2419 card->instantiated = false;
2420 snd_soc_dapm_shutdown(card); 2420 snd_soc_dapm_shutdown(card);
2421 soc_cleanup_card_resources(card); 2421 soc_cleanup_card_resources(card);
2422 dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
2422 } 2423 }
2423 dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
2424 2424
2425 return 0; 2425 return 0;
2426} 2426}