aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/s3c24xx/Kconfig9
-rw-r--r--sound/soc/s3c24xx/Makefile2
-rw-r--r--sound/soc/s3c24xx/aquila_wm8994.c295
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c2
4 files changed, 307 insertions, 1 deletions
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 213963ac3c2..c09b4021afe 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -131,3 +131,12 @@ config SND_S3C64XX_SOC_SMARTQ
131 depends on SND_S3C24XX_SOC && MACH_SMARTQ 131 depends on SND_S3C24XX_SOC && MACH_SMARTQ
132 select SND_S3C64XX_SOC_I2S 132 select SND_S3C64XX_SOC_I2S
133 select SND_SOC_WM8750 133 select SND_SOC_WM8750
134
135config SND_S5PC110_SOC_AQUILA_WM8994
136 tristate "SoC I2S Audio support for AQUILA - WM8994"
137 depends on SND_S3C24XX_SOC && MACH_AQUILA
138 select SND_S3C64XX_SOC_I2S_V4
139 select SND_SOC_WM8994
140 help
141 Say Y if you want to add support for SoC audio on aquila
142 with the WM8994.
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 50172c385d9..02dd12c714f 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -30,6 +30,7 @@ snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o
30snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o 30snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o
31snd-soc-smdk-wm9713-objs := smdk_wm9713.o 31snd-soc-smdk-wm9713-objs := smdk_wm9713.o
32snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o 32snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
33snd-soc-aquila-wm8994-objs := aquila_wm8994.o
33 34
34obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o 35obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
35obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 36obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -43,3 +44,4 @@ obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv32
43obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o 44obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o
44obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o 45obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o
45obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o 46obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o
47obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o
diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c
new file mode 100644
index 00000000000..235d1973f7d
--- /dev/null
+++ b/sound/soc/s3c24xx/aquila_wm8994.c
@@ -0,0 +1,295 @@
1/*
2 * aquila_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 <linux/moduleparam.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/jack.h>
21#include <asm/mach-types.h>
22#include <mach/gpio.h>
23#include <mach/regs-clock.h>
24
25#include <linux/mfd/wm8994/core.h>
26#include <linux/mfd/wm8994/registers.h>
27#include "../codecs/wm8994.h"
28#include "s3c-dma.h"
29#include "s3c64xx-i2s.h"
30
31static struct snd_soc_card aquila;
32static struct platform_device *aquila_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 aquila_dapm_widgets[] = {
61 SND_SOC_DAPM_SPK("Ext Spk", NULL),
62 SND_SOC_DAPM_SPK("Ext Rcv", NULL),
63 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
64 SND_SOC_DAPM_MIC("Headset Mic", NULL),
65 SND_SOC_DAPM_MIC("Main Mic", NULL),
66 SND_SOC_DAPM_MIC("2nd Mic", NULL),
67 SND_SOC_DAPM_LINE("Radio In", NULL),
68};
69
70static const struct snd_soc_dapm_route aquila_dapm_routes[] = {
71 {"Ext Spk", NULL, "SPKOUTLP"},
72 {"Ext Spk", NULL, "SPKOUTLN"},
73
74 {"Ext Rcv", NULL, "HPOUT2N"},
75 {"Ext Rcv", NULL, "HPOUT2P"},
76
77 {"Headset Stereophone", NULL, "HPOUT1L"},
78 {"Headset Stereophone", NULL, "HPOUT1R"},
79
80 {"IN1RN", NULL, "Headset Mic"},
81 {"IN1RP", NULL, "Headset Mic"},
82
83 {"IN1RN", NULL, "2nd Mic"},
84 {"IN1RP", NULL, "2nd Mic"},
85
86 {"IN1LN", NULL, "Main Mic"},
87 {"IN1LP", NULL, "Main Mic"},
88
89 {"IN2LN", NULL, "Radio In"},
90 {"IN2RN", NULL, "Radio In"},
91};
92
93static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd)
94{
95 struct snd_soc_codec *codec = rtd->codec;
96 int ret;
97
98 /* add aquila specific widgets */
99 snd_soc_dapm_new_controls(codec, aquila_dapm_widgets,
100 ARRAY_SIZE(aquila_dapm_widgets));
101
102 /* set up aquila specific audio routes */
103 snd_soc_dapm_add_routes(codec, aquila_dapm_routes,
104 ARRAY_SIZE(aquila_dapm_routes));
105
106 /* set endpoints to not connected */
107 snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN");
108 snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP");
109 snd_soc_dapm_nc_pin(codec, "LINEOUT1N");
110 snd_soc_dapm_nc_pin(codec, "LINEOUT1P");
111 snd_soc_dapm_nc_pin(codec, "LINEOUT2N");
112 snd_soc_dapm_nc_pin(codec, "LINEOUT2P");
113 snd_soc_dapm_nc_pin(codec, "SPKOUTRN");
114 snd_soc_dapm_nc_pin(codec, "SPKOUTRP");
115
116 snd_soc_dapm_sync(codec);
117
118 /* Headset jack detection */
119 ret = snd_soc_jack_new(&aquila, "Headset Jack",
120 SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
121 &jack);
122 if (ret)
123 return ret;
124
125 ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
126 if (ret)
127 return ret;
128
129 ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
130 if (ret)
131 return ret;
132
133 return 0;
134}
135
136static int aquila_hifi_hw_params(struct snd_pcm_substream *substream,
137 struct snd_pcm_hw_params *params)
138{
139 struct snd_soc_pcm_runtime *rtd = substream->private_data;
140 struct snd_soc_dai *codec_dai = rtd->codec_dai;
141 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
142 unsigned int pll_out = 24000000;
143 int ret = 0;
144
145 /* set the cpu DAI configuration */
146 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
148 if (ret < 0)
149 return ret;
150
151 /* set the cpu system clock */
152 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
153 0, SND_SOC_CLOCK_IN);
154 if (ret < 0)
155 return ret;
156
157 /* set codec DAI configuration */
158 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
159 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
160 if (ret < 0)
161 return ret;
162
163 /* set the codec FLL */
164 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
165 params_rate(params) * 256);
166 if (ret < 0)
167 return ret;
168
169 /* set the codec system clock */
170 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
171 params_rate(params) * 256, SND_SOC_CLOCK_IN);
172 if (ret < 0)
173 return ret;
174
175 return 0;
176}
177
178static struct snd_soc_ops aquila_hifi_ops = {
179 .hw_params = aquila_hifi_hw_params,
180};
181
182static int aquila_voice_hw_params(struct snd_pcm_substream *substream,
183 struct snd_pcm_hw_params *params)
184{
185 struct snd_soc_pcm_runtime *rtd = substream->private_data;
186 struct snd_soc_dai *codec_dai = rtd->codec_dai;
187 unsigned int pll_out = 24000000;
188 int ret = 0;
189
190 if (params_rate(params) != 8000)
191 return -EINVAL;
192
193 /* set codec DAI configuration */
194 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
195 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
196 if (ret < 0)
197 return ret;
198
199 /* set the codec FLL */
200 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
201 params_rate(params) * 256);
202 if (ret < 0)
203 return ret;
204
205 /* set the codec system clock */
206 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
207 params_rate(params) * 256, SND_SOC_CLOCK_IN);
208 if (ret < 0)
209 return ret;
210
211 return 0;
212}
213
214static struct snd_soc_dai_driver voice_dai = {
215 .name = "aquila-voice-dai",
216 .playback = {
217 .channels_min = 1,
218 .channels_max = 2,
219 .rates = SNDRV_PCM_RATE_8000,
220 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
221 .capture = {
222 .channels_min = 1,
223 .channels_max = 2,
224 .rates = SNDRV_PCM_RATE_8000,
225 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
226};
227
228static struct snd_soc_ops aquila_voice_ops = {
229 .hw_params = aquila_voice_hw_params,
230};
231
232static struct snd_soc_dai_link aquila_dai[] = {
233{
234 .name = "WM8994",
235 .stream_name = "WM8994 HiFi",
236 .cpu_dai_name = "s3c64xx-i2s-v4",
237 .codec_dai_name = "wm8994-hifi",
238 .platform_name = "s3c24xx-pcm-audio",
239 .codec_name = "wm8994-codec.0-0x1a",
240 .init = aquila_wm8994_init,
241 .ops = &aquila_hifi_ops,
242}, {
243 .name = "WM8994 Voice",
244 .stream_name = "Voice",
245 .cpu_dai_name = "aquila-voice-dai",
246 .codec_dai_name = "wm8994-voice",
247 .platform_name = "s3c24xx-pcm-audio",
248 .codec_name = "wm8994-codec.0-0x1a",
249 .ops = &aquila_voice_ops,
250},
251};
252
253static struct snd_soc_card aquila = {
254 .name = "aquila",
255 .dai_link = aquila_dai,
256 .num_links = ARRAY_SIZE(aquila_dai),
257};
258
259static int __init aquila_init(void)
260{
261 int ret;
262
263 if (!machine_is_aquila())
264 return -ENODEV;
265
266 aquila_snd_device = platform_device_alloc("soc-audio", -1);
267 if (!aquila_snd_device)
268 return -ENOMEM;
269
270 /* register voice DAI here */
271 ret = snd_soc_register_dai(&aquila_snd_device->dev, &voice_dai);
272 if (ret)
273 return ret;
274
275 platform_set_drvdata(aquila_snd_device, &aquila);
276 ret = platform_device_add(aquila_snd_device);
277
278 if (ret)
279 platform_device_put(aquila_snd_device);
280
281 return ret;
282}
283
284static void __exit aquila_exit(void)
285{
286 platform_device_unregister(aquila_snd_device);
287}
288
289module_init(aquila_init);
290module_exit(aquila_exit);
291
292/* Module information */
293MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)");
294MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
295MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index f4fbc0e6173..b3866d5b19e 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -750,7 +750,7 @@ int s3c_i2sv2_register_dai(struct device *dev, int id,
750 drv->suspend = s3c2412_i2s_suspend; 750 drv->suspend = s3c2412_i2s_suspend;
751 drv->resume = s3c2412_i2s_resume; 751 drv->resume = s3c2412_i2s_resume;
752 752
753 return snd_soc_register_dai(dev, id, drv); 753 return snd_soc_register_dai(dev, drv);
754} 754}
755EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); 755EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
756 756