]> git.karo-electronics.de Git - mv-sheeva.git/blob - sound/soc/samsung/neo1973_gta02_wm8753.c
Merge git://git.infradead.org/users/dwmw2/mtd-2.6.38
[mv-sheeva.git] / sound / soc / samsung / neo1973_gta02_wm8753.c
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
26 #include <asm/mach-types.h>
27
28 #include <plat/regs-iis.h>
29
30 #include <mach/regs-clock.h>
31 #include <asm/io.h>
32 #include <mach/gta02.h>
33 #include "../codecs/wm8753.h"
34 #include "dma.h"
35 #include "s3c24xx-i2s.h"
36
37 static struct snd_soc_card neo1973_gta02;
38
39 static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
40         struct snd_pcm_hw_params *params)
41 {
42         struct snd_soc_pcm_runtime *rtd = substream->private_data;
43         struct snd_soc_dai *codec_dai = rtd->codec_dai;
44         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
45         unsigned int pll_out = 0, bclk = 0;
46         int ret = 0;
47         unsigned long iis_clkrate;
48
49         iis_clkrate = s3c24xx_i2s_get_clockrate();
50
51         switch (params_rate(params)) {
52         case 8000:
53         case 16000:
54                 pll_out = 12288000;
55                 break;
56         case 48000:
57                 bclk = WM8753_BCLK_DIV_4;
58                 pll_out = 12288000;
59                 break;
60         case 96000:
61                 bclk = WM8753_BCLK_DIV_2;
62                 pll_out = 12288000;
63                 break;
64         case 11025:
65                 bclk = WM8753_BCLK_DIV_16;
66                 pll_out = 11289600;
67                 break;
68         case 22050:
69                 bclk = WM8753_BCLK_DIV_8;
70                 pll_out = 11289600;
71                 break;
72         case 44100:
73                 bclk = WM8753_BCLK_DIV_4;
74                 pll_out = 11289600;
75                 break;
76         case 88200:
77                 bclk = WM8753_BCLK_DIV_2;
78                 pll_out = 11289600;
79                 break;
80         }
81
82         /* set codec DAI configuration */
83         ret = snd_soc_dai_set_fmt(codec_dai,
84                 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
85                 SND_SOC_DAIFMT_CBM_CFM);
86         if (ret < 0)
87                 return ret;
88
89         /* set cpu DAI configuration */
90         ret = snd_soc_dai_set_fmt(cpu_dai,
91                 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
92                 SND_SOC_DAIFMT_CBM_CFM);
93         if (ret < 0)
94                 return ret;
95
96         /* set the codec system clock for DAC and ADC */
97         ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
98                 SND_SOC_CLOCK_IN);
99         if (ret < 0)
100                 return ret;
101
102         /* set MCLK division for sample rate */
103         ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
104                 S3C2410_IISMOD_32FS);
105         if (ret < 0)
106                 return ret;
107
108         /* set codec BCLK division for sample rate */
109         ret = snd_soc_dai_set_clkdiv(codec_dai,
110                                         WM8753_BCLKDIV, bclk);
111         if (ret < 0)
112                 return ret;
113
114         /* set prescaler division for sample rate */
115         ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
116                 S3C24XX_PRESCALE(4, 4));
117         if (ret < 0)
118                 return ret;
119
120         /* codec PLL input is PCLK/4 */
121         ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
122                 iis_clkrate / 4, pll_out);
123         if (ret < 0)
124                 return ret;
125
126         return 0;
127 }
128
129 static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
130 {
131         struct snd_soc_pcm_runtime *rtd = substream->private_data;
132         struct snd_soc_dai *codec_dai = rtd->codec_dai;
133
134         /* disable the PLL */
135         return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
136 }
137
138 /*
139  * Neo1973 WM8753 HiFi DAI opserations.
140  */
141 static struct snd_soc_ops neo1973_gta02_hifi_ops = {
142         .hw_params = neo1973_gta02_hifi_hw_params,
143         .hw_free = neo1973_gta02_hifi_hw_free,
144 };
145
146 static int neo1973_gta02_voice_hw_params(
147         struct snd_pcm_substream *substream,
148         struct snd_pcm_hw_params *params)
149 {
150         struct snd_soc_pcm_runtime *rtd = substream->private_data;
151         struct snd_soc_dai *codec_dai = rtd->codec_dai;
152         unsigned int pcmdiv = 0;
153         int ret = 0;
154         unsigned long iis_clkrate;
155
156         iis_clkrate = s3c24xx_i2s_get_clockrate();
157
158         if (params_rate(params) != 8000)
159                 return -EINVAL;
160         if (params_channels(params) != 1)
161                 return -EINVAL;
162
163         pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
164
165         /* todo: gg check mode (DSP_B) against CSR datasheet */
166         /* set codec DAI configuration */
167         ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
168                 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
169         if (ret < 0)
170                 return ret;
171
172         /* set the codec system clock for DAC and ADC */
173         ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK,
174                 12288000, SND_SOC_CLOCK_IN);
175         if (ret < 0)
176                 return ret;
177
178         /* set codec PCM division for sample rate */
179         ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV,
180                                         pcmdiv);
181         if (ret < 0)
182                 return ret;
183
184         /* configure and enable PLL for 12.288MHz output */
185         ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
186                 iis_clkrate / 4, 12288000);
187         if (ret < 0)
188                 return ret;
189
190         return 0;
191 }
192
193 static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
194 {
195         struct snd_soc_pcm_runtime *rtd = substream->private_data;
196         struct snd_soc_dai *codec_dai = rtd->codec_dai;
197
198         /* disable the PLL */
199         return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
200 }
201
202 static struct snd_soc_ops neo1973_gta02_voice_ops = {
203         .hw_params = neo1973_gta02_voice_hw_params,
204         .hw_free = neo1973_gta02_voice_hw_free,
205 };
206
207 #define LM4853_AMP 1
208 #define LM4853_SPK 2
209
210 static u8 lm4853_state;
211
212 /* This has no effect, it exists only to maintain compatibility with
213  * existing ALSA state files.
214  */
215 static int lm4853_set_state(struct snd_kcontrol *kcontrol,
216         struct snd_ctl_elem_value *ucontrol)
217 {
218         int val = ucontrol->value.integer.value[0];
219
220         if (val)
221                 lm4853_state |= LM4853_AMP;
222         else
223                 lm4853_state &= ~LM4853_AMP;
224
225         return 0;
226 }
227
228 static int lm4853_get_state(struct snd_kcontrol *kcontrol,
229         struct snd_ctl_elem_value *ucontrol)
230 {
231         ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
232
233         return 0;
234 }
235
236 static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
237         struct snd_ctl_elem_value *ucontrol)
238 {
239         int val = ucontrol->value.integer.value[0];
240
241         if (val) {
242                 lm4853_state |= LM4853_SPK;
243                 gpio_set_value(GTA02_GPIO_HP_IN, 0);
244         } else {
245                 lm4853_state &= ~LM4853_SPK;
246                 gpio_set_value(GTA02_GPIO_HP_IN, 1);
247         }
248
249         return 0;
250 }
251
252 static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
253         struct snd_ctl_elem_value *ucontrol)
254 {
255         ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
256
257         return 0;
258 }
259
260 static int lm4853_event(struct snd_soc_dapm_widget *w,
261                         struct snd_kcontrol *k,
262                         int event)
263 {
264         gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));
265
266         return 0;
267 }
268
269 static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
270         SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
271         SND_SOC_DAPM_LINE("GSM Line Out", NULL),
272         SND_SOC_DAPM_LINE("GSM Line In", NULL),
273         SND_SOC_DAPM_MIC("Headset Mic", NULL),
274         SND_SOC_DAPM_MIC("Handset Mic", NULL),
275         SND_SOC_DAPM_SPK("Handset Spk", NULL),
276 };
277
278
279 /* example machine audio_mapnections */
280 static const struct snd_soc_dapm_route audio_map[] = {
281
282         /* Connections to the lm4853 amp */
283         {"Stereo Out", NULL, "LOUT1"},
284         {"Stereo Out", NULL, "ROUT1"},
285
286         /* Connections to the GSM Module */
287         {"GSM Line Out", NULL, "MONO1"},
288         {"GSM Line Out", NULL, "MONO2"},
289         {"RXP", NULL, "GSM Line In"},
290         {"RXN", NULL, "GSM Line In"},
291
292         /* Connections to Headset */
293         {"MIC1", NULL, "Mic Bias"},
294         {"Mic Bias", NULL, "Headset Mic"},
295
296         /* Call Mic */
297         {"MIC2", NULL, "Mic Bias"},
298         {"MIC2N", NULL, "Mic Bias"},
299         {"Mic Bias", NULL, "Handset Mic"},
300
301         /* Call Speaker */
302         {"Handset Spk", NULL, "LOUT2"},
303         {"Handset Spk", NULL, "ROUT2"},
304
305         /* Connect the ALC pins */
306         {"ACIN", NULL, "ACOP"},
307 };
308
309 static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
310         SOC_DAPM_PIN_SWITCH("Stereo Out"),
311         SOC_DAPM_PIN_SWITCH("GSM Line Out"),
312         SOC_DAPM_PIN_SWITCH("GSM Line In"),
313         SOC_DAPM_PIN_SWITCH("Headset Mic"),
314         SOC_DAPM_PIN_SWITCH("Handset Mic"),
315         SOC_DAPM_PIN_SWITCH("Handset Spk"),
316
317         /* This has no effect, it exists only to maintain compatibility with
318          * existing ALSA state files.
319          */
320         SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0,
321                 lm4853_get_state,
322                 lm4853_set_state),
323         SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0,
324                 lm4853_get_spk,
325                 lm4853_set_spk),
326 };
327
328 /*
329  * This is an example machine initialisation for a wm8753 connected to a
330  * neo1973 GTA02.
331  */
332 static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd)
333 {
334         struct snd_soc_codec *codec = rtd->codec;
335         struct snd_soc_dapm_context *dapm = &codec->dapm;
336         int err;
337
338         /* set up NC codec pins */
339         snd_soc_dapm_nc_pin(dapm, "OUT3");
340         snd_soc_dapm_nc_pin(dapm, "OUT4");
341         snd_soc_dapm_nc_pin(dapm, "LINE1");
342         snd_soc_dapm_nc_pin(dapm, "LINE2");
343
344         /* Add neo1973 gta02 specific widgets */
345         snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets,
346                                   ARRAY_SIZE(wm8753_dapm_widgets));
347
348         /* add neo1973 gta02 specific controls */
349         err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls,
350                 ARRAY_SIZE(wm8753_neo1973_gta02_controls));
351
352         if (err < 0)
353                 return err;
354
355         /* set up neo1973 gta02 specific audio path audio_map */
356         snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
357
358         /* set endpoints to default off mode */
359         snd_soc_dapm_disable_pin(dapm, "Stereo Out");
360         snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
361         snd_soc_dapm_disable_pin(dapm, "GSM Line In");
362         snd_soc_dapm_disable_pin(dapm, "Headset Mic");
363         snd_soc_dapm_disable_pin(dapm, "Handset Mic");
364         snd_soc_dapm_disable_pin(dapm, "Handset Spk");
365
366         /* allow audio paths from the GSM modem to run during suspend */
367         snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
368         snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out");
369         snd_soc_dapm_ignore_suspend(dapm, "GSM Line In");
370         snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
371         snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
372         snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
373
374         snd_soc_dapm_sync(dapm);
375
376         return 0;
377 }
378
379 /*
380  * BT Codec DAI
381  */
382 static struct snd_soc_dai_driver bt_dai = {
383         .name = "bluetooth-dai",
384         .playback = {
385                 .channels_min = 1,
386                 .channels_max = 1,
387                 .rates = SNDRV_PCM_RATE_8000,
388                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
389         .capture = {
390                 .channels_min = 1,
391                 .channels_max = 1,
392                 .rates = SNDRV_PCM_RATE_8000,
393                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
394 };
395
396 static struct snd_soc_dai_link neo1973_gta02_dai[] = {
397 { /* Hifi Playback - for similatious use with voice below */
398         .name = "WM8753",
399         .stream_name = "WM8753 HiFi",
400         .cpu_dai_name = "s3c24xx-iis",
401         .codec_dai_name = "wm8753-hifi",
402         .init = neo1973_gta02_wm8753_init,
403         .platform_name = "samsung-audio",
404         .codec_name = "wm8753-codec.0-001a",
405         .ops = &neo1973_gta02_hifi_ops,
406 },
407 { /* Voice via BT */
408         .name = "Bluetooth",
409         .stream_name = "Voice",
410         .cpu_dai_name = "bluetooth-dai",
411         .codec_dai_name = "wm8753-voice",
412         .ops = &neo1973_gta02_voice_ops,
413         .codec_name = "wm8753-codec.0-001a",
414         .platform_name = "samsung-audio",
415 },
416 };
417
418 static struct snd_soc_card neo1973_gta02 = {
419         .name = "neo1973-gta02",
420         .dai_link = neo1973_gta02_dai,
421         .num_links = ARRAY_SIZE(neo1973_gta02_dai),
422 };
423
424 static struct platform_device *neo1973_gta02_snd_device;
425
426 static int __init neo1973_gta02_init(void)
427 {
428         int ret;
429
430         if (!machine_is_neo1973_gta02()) {
431                 printk(KERN_INFO
432                        "Only GTA02 is supported by this ASoC driver\n");
433                 return -ENODEV;
434         }
435
436         neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
437         if (!neo1973_gta02_snd_device)
438                 return -ENOMEM;
439
440         /* register bluetooth DAI here */
441         ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, &bt_dai);
442         if (ret)
443                 goto err_put_device;
444
445         platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02);
446         ret = platform_device_add(neo1973_gta02_snd_device);
447
448         if (ret)
449                 goto err_unregister_dai;
450
451         /* Initialise GPIOs used by amp */
452         ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN");
453         if (ret) {
454                 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN);
455                 goto err_del_device;
456         }
457
458         ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1);
459         if (ret) {
460                 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN);
461                 goto err_free_gpio_hp_in;
462         }
463
464         ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT");
465         if (ret) {
466                 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT);
467                 goto err_free_gpio_hp_in;
468         }
469
470         ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1);
471         if (ret) {
472                 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT);
473                 goto err_free_gpio_amp_shut;
474         }
475
476         return 0;
477
478 err_free_gpio_amp_shut:
479         gpio_free(GTA02_GPIO_AMP_SHUT);
480 err_free_gpio_hp_in:
481         gpio_free(GTA02_GPIO_HP_IN);
482 err_del_device:
483         platform_device_del(neo1973_gta02_snd_device);
484 err_unregister_dai:
485         snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev);
486 err_put_device:
487         platform_device_put(neo1973_gta02_snd_device);
488         return ret;
489 }
490 module_init(neo1973_gta02_init);
491
492 static void __exit neo1973_gta02_exit(void)
493 {
494         snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev);
495         platform_device_unregister(neo1973_gta02_snd_device);
496         gpio_free(GTA02_GPIO_HP_IN);
497         gpio_free(GTA02_GPIO_AMP_SHUT);
498 }
499 module_exit(neo1973_gta02_exit);
500
501 /* Module information */
502 MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org");
503 MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02");
504 MODULE_LICENSE("GPL");