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