diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-07-30 08:21:38 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-07-30 08:21:38 -0400 |
commit | a1daf67d721adfecc298132550bc2967c67f764f (patch) | |
tree | f62c35d07804ad01ae5546072cb5f1b485ae97ac /sound/soc | |
parent | 3a39f832a5699d50a6785de97c551033cc09d0ec (diff) | |
parent | 82c4362ee3d8a0b8797ba77222b25c7671696e2b (diff) |
Merge branch 'gta02-audio' into for-2.6.32
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/s3c24xx/Kconfig | 9 | ||||
-rw-r--r-- | sound/soc/s3c24xx/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/s3c24xx/neo1973_gta02_wm8753.c | 498 |
3 files changed, 509 insertions, 0 deletions
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index df494d1e346f..d1ed0f537c3a 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig | |||
@@ -38,6 +38,15 @@ config SND_S3C24XX_SOC_NEO1973_WM8753 | |||
38 | Say Y if you want to add support for SoC audio on smdk2440 | 38 | Say Y if you want to add support for SoC audio on smdk2440 |
39 | with the WM8753. | 39 | with the WM8753. |
40 | 40 | ||
41 | config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753 | ||
42 | tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)" | ||
43 | depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02 | ||
44 | select SND_S3C24XX_SOC_I2S | ||
45 | select SND_SOC_WM8753 | ||
46 | help | ||
47 | This driver provides audio support for the Openmoko Neo FreeRunner | ||
48 | smartphone. | ||
49 | |||
41 | config SND_S3C24XX_SOC_JIVE_WM8750 | 50 | config SND_S3C24XX_SOC_JIVE_WM8750 |
42 | tristate "SoC I2S Audio support for Jive" | 51 | tristate "SoC I2S Audio support for Jive" |
43 | depends on SND_S3C24XX_SOC && MACH_JIVE | 52 | depends on SND_S3C24XX_SOC && MACH_JIVE |
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 07a93a2ebe5f..eb219b016499 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile | |||
@@ -16,12 +16,14 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o | |||
16 | # S3C24XX Machine Support | 16 | # S3C24XX Machine Support |
17 | snd-soc-jive-wm8750-objs := jive_wm8750.o | 17 | snd-soc-jive-wm8750-objs := jive_wm8750.o |
18 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o | 18 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o |
19 | snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o | ||
19 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o | 20 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o |
20 | snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o | 21 | snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o |
21 | snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o | 22 | snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o |
22 | 23 | ||
23 | obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o | 24 | obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o |
24 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 25 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
26 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o | ||
25 | obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o | 27 | obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o |
26 | obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o | 28 | obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o |
27 | obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o | 29 | obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o |
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c new file mode 100644 index 000000000000..0c52e36ddd87 --- /dev/null +++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c | |||
@@ -0,0 +1,498 @@ | |||
1 | /* | ||
2 | * neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02) | ||
3 | * | ||
4 | * Copyright 2007 Openmoko Inc | ||
5 | * Author: Graeme Gregory <graeme@openmoko.org> | ||
6 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
7 | * Author: Graeme Gregory <linux@wolfsonmicro.com> | ||
8 | * Copyright 2009 Wolfson Microelectronics | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/moduleparam.h> | ||
18 | #include <linux/timer.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | |||
27 | #include <asm/mach-types.h> | ||
28 | |||
29 | #include <plat/regs-iis.h> | ||
30 | |||
31 | #include <mach/regs-clock.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <mach/gta02.h> | ||
34 | #include "../codecs/wm8753.h" | ||
35 | #include "s3c24xx-pcm.h" | ||
36 | #include "s3c24xx-i2s.h" | ||
37 | |||
38 | static struct snd_soc_card neo1973_gta02; | ||
39 | |||
40 | static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, | ||
41 | struct snd_pcm_hw_params *params) | ||
42 | { | ||
43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
44 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
45 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
46 | unsigned int pll_out = 0, bclk = 0; | ||
47 | int ret = 0; | ||
48 | unsigned long iis_clkrate; | ||
49 | |||
50 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | ||
51 | |||
52 | switch (params_rate(params)) { | ||
53 | case 8000: | ||
54 | case 16000: | ||
55 | pll_out = 12288000; | ||
56 | break; | ||
57 | case 48000: | ||
58 | bclk = WM8753_BCLK_DIV_4; | ||
59 | pll_out = 12288000; | ||
60 | break; | ||
61 | case 96000: | ||
62 | bclk = WM8753_BCLK_DIV_2; | ||
63 | pll_out = 12288000; | ||
64 | break; | ||
65 | case 11025: | ||
66 | bclk = WM8753_BCLK_DIV_16; | ||
67 | pll_out = 11289600; | ||
68 | break; | ||
69 | case 22050: | ||
70 | bclk = WM8753_BCLK_DIV_8; | ||
71 | pll_out = 11289600; | ||
72 | break; | ||
73 | case 44100: | ||
74 | bclk = WM8753_BCLK_DIV_4; | ||
75 | pll_out = 11289600; | ||
76 | break; | ||
77 | case 88200: | ||
78 | bclk = WM8753_BCLK_DIV_2; | ||
79 | pll_out = 11289600; | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | /* set codec DAI configuration */ | ||
84 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
85 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
86 | SND_SOC_DAIFMT_CBM_CFM); | ||
87 | if (ret < 0) | ||
88 | return ret; | ||
89 | |||
90 | /* set cpu DAI configuration */ | ||
91 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
92 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
93 | SND_SOC_DAIFMT_CBM_CFM); | ||
94 | if (ret < 0) | ||
95 | return ret; | ||
96 | |||
97 | /* set the codec system clock for DAC and ADC */ | ||
98 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, | ||
99 | SND_SOC_CLOCK_IN); | ||
100 | if (ret < 0) | ||
101 | return ret; | ||
102 | |||
103 | /* set MCLK division for sample rate */ | ||
104 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, | ||
105 | S3C2410_IISMOD_32FS); | ||
106 | if (ret < 0) | ||
107 | return ret; | ||
108 | |||
109 | /* set codec BCLK division for sample rate */ | ||
110 | ret = snd_soc_dai_set_clkdiv(codec_dai, | ||
111 | WM8753_BCLKDIV, bclk); | ||
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | /* set prescaler division for sample rate */ | ||
116 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, | ||
117 | S3C24XX_PRESCALE(4, 4)); | ||
118 | if (ret < 0) | ||
119 | return ret; | ||
120 | |||
121 | /* codec PLL input is PCLK/4 */ | ||
122 | ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, | ||
123 | iis_clkrate / 4, pll_out); | ||
124 | if (ret < 0) | ||
125 | return ret; | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) | ||
131 | { | ||
132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
133 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
134 | |||
135 | /* disable the PLL */ | ||
136 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Neo1973 WM8753 HiFi DAI opserations. | ||
141 | */ | ||
142 | static struct snd_soc_ops neo1973_gta02_hifi_ops = { | ||
143 | .hw_params = neo1973_gta02_hifi_hw_params, | ||
144 | .hw_free = neo1973_gta02_hifi_hw_free, | ||
145 | }; | ||
146 | |||
147 | static int neo1973_gta02_voice_hw_params( | ||
148 | struct snd_pcm_substream *substream, | ||
149 | struct snd_pcm_hw_params *params) | ||
150 | { | ||
151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
152 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
153 | unsigned int pcmdiv = 0; | ||
154 | int ret = 0; | ||
155 | unsigned long iis_clkrate; | ||
156 | |||
157 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | ||
158 | |||
159 | if (params_rate(params) != 8000) | ||
160 | return -EINVAL; | ||
161 | if (params_channels(params) != 1) | ||
162 | return -EINVAL; | ||
163 | |||
164 | pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ | ||
165 | |||
166 | /* todo: gg check mode (DSP_B) against CSR datasheet */ | ||
167 | /* set codec DAI configuration */ | ||
168 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | | ||
169 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
170 | if (ret < 0) | ||
171 | return ret; | ||
172 | |||
173 | /* set the codec system clock for DAC and ADC */ | ||
174 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, | ||
175 | 12288000, SND_SOC_CLOCK_IN); | ||
176 | if (ret < 0) | ||
177 | return ret; | ||
178 | |||
179 | /* set codec PCM division for sample rate */ | ||
180 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, | ||
181 | pcmdiv); | ||
182 | if (ret < 0) | ||
183 | return ret; | ||
184 | |||
185 | /* configue and enable PLL for 12.288MHz output */ | ||
186 | ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, | ||
187 | iis_clkrate / 4, 12288000); | ||
188 | if (ret < 0) | ||
189 | return ret; | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) | ||
195 | { | ||
196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
197 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
198 | |||
199 | /* disable the PLL */ | ||
200 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); | ||
201 | } | ||
202 | |||
203 | static struct snd_soc_ops neo1973_gta02_voice_ops = { | ||
204 | .hw_params = neo1973_gta02_voice_hw_params, | ||
205 | .hw_free = neo1973_gta02_voice_hw_free, | ||
206 | }; | ||
207 | |||
208 | #define LM4853_AMP 1 | ||
209 | #define LM4853_SPK 2 | ||
210 | |||
211 | static u8 lm4853_state; | ||
212 | |||
213 | /* This has no effect, it exists only to maintain compatibility with | ||
214 | * existing ALSA state files. | ||
215 | */ | ||
216 | static int lm4853_set_state(struct snd_kcontrol *kcontrol, | ||
217 | struct snd_ctl_elem_value *ucontrol) | ||
218 | { | ||
219 | int val = ucontrol->value.integer.value[0]; | ||
220 | |||
221 | if (val) | ||
222 | lm4853_state |= LM4853_AMP; | ||
223 | else | ||
224 | lm4853_state &= ~LM4853_AMP; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int lm4853_get_state(struct snd_kcontrol *kcontrol, | ||
230 | struct snd_ctl_elem_value *ucontrol) | ||
231 | { | ||
232 | ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP; | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int lm4853_set_spk(struct snd_kcontrol *kcontrol, | ||
238 | struct snd_ctl_elem_value *ucontrol) | ||
239 | { | ||
240 | int val = ucontrol->value.integer.value[0]; | ||
241 | |||
242 | if (val) { | ||
243 | lm4853_state |= LM4853_SPK; | ||
244 | gpio_set_value(GTA02_GPIO_HP_IN, 0); | ||
245 | } else { | ||
246 | lm4853_state &= ~LM4853_SPK; | ||
247 | gpio_set_value(GTA02_GPIO_HP_IN, 1); | ||
248 | } | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int lm4853_get_spk(struct snd_kcontrol *kcontrol, | ||
254 | struct snd_ctl_elem_value *ucontrol) | ||
255 | { | ||
256 | ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1; | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int lm4853_event(struct snd_soc_dapm_widget *w, | ||
262 | struct snd_kcontrol *k, | ||
263 | int event) | ||
264 | { | ||
265 | gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { | ||
271 | SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), | ||
272 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | ||
273 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | ||
274 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
275 | SND_SOC_DAPM_MIC("Handset Mic", NULL), | ||
276 | SND_SOC_DAPM_SPK("Handset Spk", NULL), | ||
277 | }; | ||
278 | |||
279 | |||
280 | /* example machine audio_mapnections */ | ||
281 | static const struct snd_soc_dapm_route audio_map[] = { | ||
282 | |||
283 | /* Connections to the lm4853 amp */ | ||
284 | {"Stereo Out", NULL, "LOUT1"}, | ||
285 | {"Stereo Out", NULL, "ROUT1"}, | ||
286 | |||
287 | /* Connections to the GSM Module */ | ||
288 | {"GSM Line Out", NULL, "MONO1"}, | ||
289 | {"GSM Line Out", NULL, "MONO2"}, | ||
290 | {"RXP", NULL, "GSM Line In"}, | ||
291 | {"RXN", NULL, "GSM Line In"}, | ||
292 | |||
293 | /* Connections to Headset */ | ||
294 | {"MIC1", NULL, "Mic Bias"}, | ||
295 | {"Mic Bias", NULL, "Headset Mic"}, | ||
296 | |||
297 | /* Call Mic */ | ||
298 | {"MIC2", NULL, "Mic Bias"}, | ||
299 | {"MIC2N", NULL, "Mic Bias"}, | ||
300 | {"Mic Bias", NULL, "Handset Mic"}, | ||
301 | |||
302 | /* Call Speaker */ | ||
303 | {"Handset Spk", NULL, "LOUT2"}, | ||
304 | {"Handset Spk", NULL, "ROUT2"}, | ||
305 | |||
306 | /* Connect the ALC pins */ | ||
307 | {"ACIN", NULL, "ACOP"}, | ||
308 | }; | ||
309 | |||
310 | static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = { | ||
311 | SOC_DAPM_PIN_SWITCH("Stereo Out"), | ||
312 | SOC_DAPM_PIN_SWITCH("GSM Line Out"), | ||
313 | SOC_DAPM_PIN_SWITCH("GSM Line In"), | ||
314 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
315 | SOC_DAPM_PIN_SWITCH("Handset Mic"), | ||
316 | SOC_DAPM_PIN_SWITCH("Handset Spk"), | ||
317 | |||
318 | /* This has no effect, it exists only to maintain compatibility with | ||
319 | * existing ALSA state files. | ||
320 | */ | ||
321 | SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0, | ||
322 | lm4853_get_state, | ||
323 | lm4853_set_state), | ||
324 | SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0, | ||
325 | lm4853_get_spk, | ||
326 | lm4853_set_spk), | ||
327 | }; | ||
328 | |||
329 | /* | ||
330 | * This is an example machine initialisation for a wm8753 connected to a | ||
331 | * neo1973 GTA02. | ||
332 | */ | ||
333 | static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) | ||
334 | { | ||
335 | int err; | ||
336 | |||
337 | /* set up NC codec pins */ | ||
338 | snd_soc_dapm_nc_pin(codec, "OUT3"); | ||
339 | snd_soc_dapm_nc_pin(codec, "OUT4"); | ||
340 | snd_soc_dapm_nc_pin(codec, "LINE1"); | ||
341 | snd_soc_dapm_nc_pin(codec, "LINE2"); | ||
342 | |||
343 | /* Add neo1973 gta02 specific widgets */ | ||
344 | snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets, | ||
345 | ARRAY_SIZE(wm8753_dapm_widgets)); | ||
346 | |||
347 | /* add neo1973 gta02 specific controls */ | ||
348 | err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls, | ||
349 | ARRAY_SIZE(wm8753_neo1973_gta02_controls)); | ||
350 | |||
351 | if (err < 0) | ||
352 | return err; | ||
353 | |||
354 | /* set up neo1973 gta02 specific audio path audio_map */ | ||
355 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
356 | |||
357 | /* set endpoints to default off mode */ | ||
358 | snd_soc_dapm_disable_pin(codec, "Stereo Out"); | ||
359 | snd_soc_dapm_disable_pin(codec, "GSM Line Out"); | ||
360 | snd_soc_dapm_disable_pin(codec, "GSM Line In"); | ||
361 | snd_soc_dapm_disable_pin(codec, "Headset Mic"); | ||
362 | snd_soc_dapm_disable_pin(codec, "Handset Mic"); | ||
363 | snd_soc_dapm_disable_pin(codec, "Handset Spk"); | ||
364 | |||
365 | snd_soc_dapm_sync(codec); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * BT Codec DAI | ||
372 | */ | ||
373 | static struct snd_soc_dai bt_dai = { | ||
374 | .name = "Bluetooth", | ||
375 | .id = 0, | ||
376 | .playback = { | ||
377 | .channels_min = 1, | ||
378 | .channels_max = 1, | ||
379 | .rates = SNDRV_PCM_RATE_8000, | ||
380 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
381 | .capture = { | ||
382 | .channels_min = 1, | ||
383 | .channels_max = 1, | ||
384 | .rates = SNDRV_PCM_RATE_8000, | ||
385 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
386 | }; | ||
387 | |||
388 | static struct snd_soc_dai_link neo1973_gta02_dai[] = { | ||
389 | { /* Hifi Playback - for similatious use with voice below */ | ||
390 | .name = "WM8753", | ||
391 | .stream_name = "WM8753 HiFi", | ||
392 | .cpu_dai = &s3c24xx_i2s_dai, | ||
393 | .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], | ||
394 | .init = neo1973_gta02_wm8753_init, | ||
395 | .ops = &neo1973_gta02_hifi_ops, | ||
396 | }, | ||
397 | { /* Voice via BT */ | ||
398 | .name = "Bluetooth", | ||
399 | .stream_name = "Voice", | ||
400 | .cpu_dai = &bt_dai, | ||
401 | .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], | ||
402 | .ops = &neo1973_gta02_voice_ops, | ||
403 | }, | ||
404 | }; | ||
405 | |||
406 | static struct snd_soc_card neo1973_gta02 = { | ||
407 | .name = "neo1973-gta02", | ||
408 | .platform = &s3c24xx_soc_platform, | ||
409 | .dai_link = neo1973_gta02_dai, | ||
410 | .num_links = ARRAY_SIZE(neo1973_gta02_dai), | ||
411 | }; | ||
412 | |||
413 | static struct snd_soc_device neo1973_gta02_snd_devdata = { | ||
414 | .card = &neo1973_gta02, | ||
415 | .codec_dev = &soc_codec_dev_wm8753, | ||
416 | }; | ||
417 | |||
418 | static struct platform_device *neo1973_gta02_snd_device; | ||
419 | |||
420 | static int __init neo1973_gta02_init(void) | ||
421 | { | ||
422 | int ret; | ||
423 | |||
424 | if (!machine_is_neo1973_gta02()) { | ||
425 | printk(KERN_INFO | ||
426 | "Only GTA02 is supported by this ASoC driver\n"); | ||
427 | return -ENODEV; | ||
428 | } | ||
429 | |||
430 | /* register bluetooth DAI here */ | ||
431 | ret = snd_soc_register_dai(&bt_dai); | ||
432 | if (ret) | ||
433 | return ret; | ||
434 | |||
435 | neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); | ||
436 | if (!neo1973_gta02_snd_device) | ||
437 | return -ENOMEM; | ||
438 | |||
439 | platform_set_drvdata(neo1973_gta02_snd_device, | ||
440 | &neo1973_gta02_snd_devdata); | ||
441 | neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; | ||
442 | ret = platform_device_add(neo1973_gta02_snd_device); | ||
443 | |||
444 | if (ret) { | ||
445 | platform_device_put(neo1973_gta02_snd_device); | ||
446 | return ret; | ||
447 | } | ||
448 | |||
449 | /* Initialise GPIOs used by amp */ | ||
450 | ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN"); | ||
451 | if (ret) { | ||
452 | pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN); | ||
453 | goto err_unregister_device; | ||
454 | } | ||
455 | |||
456 | ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); | ||
457 | if (ret) { | ||
458 | pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); | ||
459 | goto err_free_gpio_hp_in; | ||
460 | } | ||
461 | |||
462 | ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT"); | ||
463 | if (ret) { | ||
464 | pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT); | ||
465 | goto err_free_gpio_hp_in; | ||
466 | } | ||
467 | |||
468 | ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1); | ||
469 | if (ret) { | ||
470 | pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT); | ||
471 | goto err_free_gpio_amp_shut; | ||
472 | } | ||
473 | |||
474 | return 0; | ||
475 | |||
476 | err_free_gpio_amp_shut: | ||
477 | gpio_free(GTA02_GPIO_AMP_SHUT); | ||
478 | err_free_gpio_hp_in: | ||
479 | gpio_free(GTA02_GPIO_HP_IN); | ||
480 | err_unregister_device: | ||
481 | platform_device_unregister(neo1973_gta02_snd_device); | ||
482 | return ret; | ||
483 | } | ||
484 | module_init(neo1973_gta02_init); | ||
485 | |||
486 | static void __exit neo1973_gta02_exit(void) | ||
487 | { | ||
488 | snd_soc_unregister_dai(&bt_dai); | ||
489 | platform_device_unregister(neo1973_gta02_snd_device); | ||
490 | gpio_free(GTA02_GPIO_HP_IN); | ||
491 | gpio_free(GTA02_GPIO_AMP_SHUT); | ||
492 | } | ||
493 | module_exit(neo1973_gta02_exit); | ||
494 | |||
495 | /* Module information */ | ||
496 | MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org"); | ||
497 | MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02"); | ||
498 | MODULE_LICENSE("GPL"); | ||