[ALSA] ASoC S3C24xx machine drivers - Openmoko Neo1973
[cascardo/linux.git] / sound / soc / s3c24xx / neo1973_wm8753.c
1 /*
2  * neo1973_wm8753.c  --  SoC audio for Neo1973
3  *
4  * Copyright 2007 Wolfson Microelectronics PLC.
5  * Author: Graeme Gregory
6  *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
7  *
8  *  This program is free software; you can redistribute  it and/or modify it
9  *  under  the terms of  the GNU General  Public License as published by the
10  *  Free Software Foundation;  either version 2 of the  License, or (at your
11  *  option) any later version.
12  *
13  *  Revision history
14  *    20th Jan 2007   Initial version.
15  *    05th Feb 2007   Rename all to Neo1973
16  *
17  */
18
19 #include <linux/module.h>
20 #include <linux/moduleparam.h>
21 #include <linux/timer.h>
22 #include <linux/interrupt.h>
23 #include <linux/platform_device.h>
24 #include <linux/i2c.h>
25 #include <sound/driver.h>
26 #include <sound/core.h>
27 #include <sound/pcm.h>
28 #include <sound/soc.h>
29 #include <sound/soc-dapm.h>
30
31 #include <asm/mach-types.h>
32 #include <asm/hardware/scoop.h>
33 #include <asm/arch/regs-iis.h>
34 #include <asm/arch/regs-clock.h>
35 #include <asm/arch/regs-gpio.h>
36 #include <asm/hardware.h>
37 #include <asm/arch/audio.h>
38 #include <asm/io.h>
39 #include <asm/arch/spi-gpio.h>
40 #include "../codecs/wm8753.h"
41 #include "lm4857.h"
42 #include "s3c24xx-pcm.h"
43 #include "s3c24xx-i2s.h"
44
45 /* define the scenarios */
46 #define NEO_AUDIO_OFF                   0
47 #define NEO_GSM_CALL_AUDIO_HANDSET      1
48 #define NEO_GSM_CALL_AUDIO_HEADSET      2
49 #define NEO_GSM_CALL_AUDIO_BLUETOOTH    3
50 #define NEO_STEREO_TO_SPEAKERS          4
51 #define NEO_STEREO_TO_HEADPHONES        5
52 #define NEO_CAPTURE_HANDSET             6
53 #define NEO_CAPTURE_HEADSET             7
54 #define NEO_CAPTURE_BLUETOOTH           8
55
56 static struct snd_soc_machine neo1973;
57 static struct i2c_client *i2c;
58
59 static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
60         struct snd_pcm_hw_params *params)
61 {
62         struct snd_soc_pcm_runtime *rtd = substream->private_data;
63         struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
64         struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
65         unsigned int pll_out = 0, bclk = 0;
66         int ret = 0;
67         unsigned long iis_clkrate;
68
69         iis_clkrate = s3c24xx_i2s_get_clockrate();
70
71         switch (params_rate(params)) {
72         case 8000:
73         case 16000:
74                 pll_out = 12288000;
75                 break;
76         case 48000:
77                 bclk = WM8753_BCLK_DIV_4;
78                 pll_out = 12288000;
79                 break;
80         case 96000:
81                 bclk = WM8753_BCLK_DIV_2;
82                 pll_out = 12288000;
83                 break;
84         case 11025:
85                 bclk = WM8753_BCLK_DIV_16;
86                 pll_out = 11289600;
87                 break;
88         case 22050:
89                 bclk = WM8753_BCLK_DIV_8;
90                 pll_out = 11289600;
91                 break;
92         case 44100:
93                 bclk = WM8753_BCLK_DIV_4;
94                 pll_out = 11289600;
95                 break;
96         case 88200:
97                 bclk = WM8753_BCLK_DIV_2;
98                 pll_out = 11289600;
99                 break;
100         }
101
102         /* set codec DAI configuration */
103         ret = codec_dai->dai_ops.set_fmt(codec_dai,
104                 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
105                 SND_SOC_DAIFMT_CBM_CFM);
106         if (ret < 0)
107                 return ret;
108
109         /* set cpu DAI configuration */
110         ret = cpu_dai->dai_ops.set_fmt(cpu_dai,
111                 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
112                 SND_SOC_DAIFMT_CBM_CFM);
113         if (ret < 0)
114                 return ret;
115
116         /* set the codec system clock for DAC and ADC */
117         ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_MCLK, pll_out,
118                 SND_SOC_CLOCK_IN);
119         if (ret < 0)
120                 return ret;
121
122         /* set MCLK division for sample rate */
123         ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
124                 S3C2410_IISMOD_32FS );
125         if (ret < 0)
126                 return ret;
127
128         /* set codec BCLK division for sample rate */
129         ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
130         if (ret < 0)
131                 return ret;
132
133         /* set prescaler division for sample rate */
134         ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
135                 S3C24XX_PRESCALE(4,4));
136         if (ret < 0)
137                 return ret;
138
139         /* codec PLL input is PCLK/4 */
140         ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1,
141                 iis_clkrate / 4, pll_out);
142         if (ret < 0)
143                 return ret;
144
145         return 0;
146 }
147
148 static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
149 {
150         struct snd_soc_pcm_runtime *rtd = substream->private_data;
151         struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
152
153         /* disable the PLL */
154         return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, 0, 0);
155 }
156
157 /*
158  * Neo1973 WM8753 HiFi DAI opserations.
159  */
160 static struct snd_soc_ops neo1973_hifi_ops = {
161         .hw_params = neo1973_hifi_hw_params,
162         .hw_free = neo1973_hifi_hw_free,
163 };
164
165 static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
166         struct snd_pcm_hw_params *params)
167 {
168         struct snd_soc_pcm_runtime *rtd = substream->private_data;
169         struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
170         unsigned int pcmdiv = 0;
171         int ret = 0;
172         unsigned long iis_clkrate;
173
174         iis_clkrate = s3c24xx_i2s_get_clockrate();
175
176         if (params_rate(params) != 8000)
177                 return -EINVAL;
178         if (params_channels(params) != 1)
179                 return -EINVAL;
180
181         pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
182
183         /* todo: gg check mode (DSP_B) against CSR datasheet */
184         /* set codec DAI configuration */
185         ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
186                 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
187         if (ret < 0)
188                 return ret;
189
190         /* set the codec system clock for DAC and ADC */
191         ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
192                 SND_SOC_CLOCK_IN);
193         if (ret < 0)
194                 return ret;
195
196         /* set codec PCM division for sample rate */
197         ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
198         if (ret < 0)
199                 return ret;
200
201         /* configue and enable PLL for 12.288MHz output */
202         ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2,
203                 iis_clkrate / 4, 12288000);
204         if (ret < 0)
205                 return ret;
206
207         return 0;
208 }
209
210 static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
211 {
212         struct snd_soc_pcm_runtime *rtd = substream->private_data;
213         struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
214
215         /* disable the PLL */
216         return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, 0, 0);
217 }
218
219 static struct snd_soc_ops neo1973_voice_ops = {
220         .hw_params = neo1973_voice_hw_params,
221         .hw_free = neo1973_voice_hw_free,
222 };
223
224 static int neo1973_scenario = 0;
225
226 static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
227         struct snd_ctl_elem_value *ucontrol)
228 {
229         ucontrol->value.integer.value[0] = neo1973_scenario;
230         return 0;
231 }
232
233 static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
234 {
235         switch(neo1973_scenario) {
236         case NEO_AUDIO_OFF:
237                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
238                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
239                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
240                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
241                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
242                 break;
243         case NEO_GSM_CALL_AUDIO_HANDSET:
244                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
245                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
246                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
247                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
248                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     1);
249                 break;
250         case NEO_GSM_CALL_AUDIO_HEADSET:
251                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
252                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
253                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
254                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  1);
255                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
256                 break;
257         case NEO_GSM_CALL_AUDIO_BLUETOOTH:
258                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
259                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
260                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
261                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
262                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
263                 break;
264         case NEO_STEREO_TO_SPEAKERS:
265                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
266                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
267                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
268                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
269                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
270                 break;
271         case NEO_STEREO_TO_HEADPHONES:
272                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
273                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
274                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
275                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
276                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
277                 break;
278         case NEO_CAPTURE_HANDSET:
279                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
280                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
281                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
282                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
283                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     1);
284                 break;
285         case NEO_CAPTURE_HEADSET:
286                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
287                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
288                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
289                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  1);
290                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
291                 break;
292         case NEO_CAPTURE_BLUETOOTH:
293                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
294                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
295                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
296                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
297                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
298                 break;
299         default:
300                 snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
301                 snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
302                 snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
303                 snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
304                 snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
305         }
306
307         snd_soc_dapm_sync_endpoints(codec);
308
309         return 0;
310 }
311
312 static int neo1973_set_scenario(struct snd_kcontrol *kcontrol,
313         struct snd_ctl_elem_value *ucontrol)
314 {
315         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
316
317         if (neo1973_scenario == ucontrol->value.integer.value[0])
318                 return 0;
319
320         neo1973_scenario = ucontrol->value.integer.value[0];
321         set_scenario_endpoints(codec, neo1973_scenario);
322         return 1;
323 }
324
325 static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};
326
327 static void lm4857_write_regs(void)
328 {
329         if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
330                 printk(KERN_ERR "lm4857: i2c write failed\n");
331 }
332
333 static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
334         struct snd_ctl_elem_value *ucontrol)
335 {
336         int reg=kcontrol->private_value & 0xFF;
337         int shift = (kcontrol->private_value >> 8) & 0x0F;
338         int mask = (kcontrol->private_value >> 16) & 0xFF;
339
340         ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
341         return 0;
342 }
343
344 static int lm4857_set_reg(struct snd_kcontrol *kcontrol,
345         struct snd_ctl_elem_value *ucontrol)
346 {
347         int reg = kcontrol->private_value & 0xFF;
348         int shift = (kcontrol->private_value >> 8) & 0x0F;
349         int mask = (kcontrol->private_value >> 16) & 0xFF;
350
351         if (((lm4857_regs[reg] >> shift ) & mask) ==
352                 ucontrol->value.integer.value[0])
353                 return 0;
354
355         lm4857_regs[reg] &= ~ (mask << shift);
356         lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
357         lm4857_write_regs();
358         return 1;
359 }
360
361 static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
362         struct snd_ctl_elem_value *ucontrol)
363 {
364         u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
365
366         if (value)
367                 value -= 5;
368
369         ucontrol->value.integer.value[0] = value;
370         return 0;
371 }
372
373 static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
374         struct snd_ctl_elem_value *ucontrol)
375 {
376         u8 value = ucontrol->value.integer.value[0];
377
378         if (value)
379                 value += 5;
380
381         if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value)
382                 return 0;
383
384         lm4857_regs[LM4857_CTRL] &= 0xF0;
385         lm4857_regs[LM4857_CTRL] |= value;
386         lm4857_write_regs();
387         return 1;
388 }
389
390 static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
391         SND_SOC_DAPM_LINE("Audio Out", NULL),
392         SND_SOC_DAPM_LINE("GSM Line Out", NULL),
393         SND_SOC_DAPM_LINE("GSM Line In", NULL),
394         SND_SOC_DAPM_MIC("Headset Mic", NULL),
395         SND_SOC_DAPM_MIC("Call Mic", NULL),
396 };
397
398
399 /* example machine audio_mapnections */
400 static const char* audio_map[][3] = {
401
402         /* Connections to the lm4857 amp */
403         {"Audio Out", NULL, "LOUT1"},
404         {"Audio Out", NULL, "ROUT1"},
405
406         /* Connections to the GSM Module */
407         {"GSM Line Out", NULL, "MONO1"},
408         {"GSM Line Out", NULL, "MONO2"},
409         {"RXP", NULL, "GSM Line In"},
410         {"RXN", NULL, "GSM Line In"},
411
412         /* Connections to Headset */
413         {"MIC1", NULL, "Mic Bias"},
414         {"Mic Bias", NULL, "Headset Mic"},
415
416         /* Call Mic */
417         {"MIC2", NULL, "Mic Bias"},
418         {"MIC2N", NULL, "Mic Bias"},
419         {"Mic Bias", NULL, "Call Mic"},
420
421         /* Connect the ALC pins */
422         {"ACIN", NULL, "ACOP"},
423
424         {NULL, NULL, NULL},
425 };
426
427 static const char *lm4857_mode[] = {
428         "Off",
429         "Call Speaker",
430         "Stereo Speakers",
431         "Stereo Speakers + Headphones",
432         "Headphones"
433 };
434
435 static const struct soc_enum lm4857_mode_enum[] = {
436         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode),
437 };
438
439 static const char *neo_scenarios[] = {
440         "Off",
441         "GSM Handset",
442         "GSM Headset",
443         "GSM Bluetooth",
444         "Speakers",
445         "Headphones",
446         "Capture Handset",
447         "Capture Headset",
448         "Capture Bluetooth"
449 };
450
451 static const struct soc_enum neo_scenario_enum[] = {
452         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios),neo_scenarios),
453 };
454
455 static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
456         SOC_SINGLE_EXT("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
457                 lm4857_get_reg, lm4857_set_reg),
458         SOC_SINGLE_EXT("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
459                 lm4857_get_reg, lm4857_set_reg),
460         SOC_SINGLE_EXT("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
461                 lm4857_get_reg, lm4857_set_reg),
462         SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
463                 lm4857_get_mode, lm4857_set_mode),
464         SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0],
465                 neo1973_get_scenario, neo1973_set_scenario),
466         SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0,
467                 lm4857_get_reg, lm4857_set_reg),
468         SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0,
469                 lm4857_get_reg, lm4857_set_reg),
470         SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0,
471                 lm4857_get_reg, lm4857_set_reg),
472         SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0,
473                 lm4857_get_reg, lm4857_set_reg),
474 };
475
476 /*
477  * This is an example machine initialisation for a wm8753 connected to a
478  * neo1973 II. It is missing logic to detect hp/mic insertions and logic
479  * to re-route the audio in such an event.
480  */
481 static int neo1973_wm8753_init(struct snd_soc_codec *codec)
482 {
483         int i, err;
484
485         /* set up NC codec pins */
486         snd_soc_dapm_set_endpoint(codec, "LOUT2", 0);
487         snd_soc_dapm_set_endpoint(codec, "ROUT2", 0);
488         snd_soc_dapm_set_endpoint(codec, "OUT3",  0);
489         snd_soc_dapm_set_endpoint(codec, "OUT4",  0);
490         snd_soc_dapm_set_endpoint(codec, "LINE1", 0);
491         snd_soc_dapm_set_endpoint(codec, "LINE2", 0);
492
493
494         /* set endpoints to default mode */
495         set_scenario_endpoints(codec, NEO_AUDIO_OFF);
496
497         /* Add neo1973 specific widgets */
498         for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++)
499                 snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]);
500
501         /* add neo1973 specific controls */
502         for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
503                 err = snd_ctl_add(codec->card,
504                                 snd_soc_cnew(&wm8753_neo1973_controls[i],
505                                 codec, NULL));
506                 if (err < 0)
507                         return err;
508         }
509
510         /* set up neo1973 specific audio path audio_mapnects */
511         for (i = 0; audio_map[i][0] != NULL; i++) {
512                 snd_soc_dapm_connect_input(codec, audio_map[i][0],
513                         audio_map[i][1], audio_map[i][2]);
514         }
515
516         snd_soc_dapm_sync_endpoints(codec);
517         return 0;
518 }
519
520 /*
521  * BT Codec DAI
522  */
523 static struct snd_soc_cpu_dai bt_dai =
524 {       .name = "Bluetooth",
525         .id = 0,
526         .type = SND_SOC_DAI_PCM,
527         .playback = {
528                 .channels_min = 1,
529                 .channels_max = 1,
530                 .rates = SNDRV_PCM_RATE_8000,
531                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
532         .capture = {
533                 .channels_min = 1,
534                 .channels_max = 1,
535                 .rates = SNDRV_PCM_RATE_8000,
536                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
537 };
538
539 static struct snd_soc_dai_link neo1973_dai[] = {
540 { /* Hifi Playback - for similatious use with voice below */
541         .name = "WM8753",
542         .stream_name = "WM8753 HiFi",
543         .cpu_dai = &s3c24xx_i2s_dai,
544         .codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
545         .init = neo1973_wm8753_init,
546         .ops = &neo1973_hifi_ops,
547 },
548 { /* Voice via BT */
549         .name = "Bluetooth",
550         .stream_name = "Voice",
551         .cpu_dai = &bt_dai,
552         .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
553         .ops = &neo1973_voice_ops,
554 },
555 };
556
557 static struct snd_soc_machine neo1973 = {
558         .name = "neo1973",
559         .dai_link = neo1973_dai,
560         .num_links = ARRAY_SIZE(neo1973_dai),
561 };
562
563 static struct wm8753_setup_data neo1973_wm8753_setup = {
564         .i2c_address = 0x1a,
565 };
566
567 static struct snd_soc_device neo1973_snd_devdata = {
568         .machine = &neo1973,
569         .platform = &s3c24xx_soc_platform,
570         .codec_dev = &soc_codec_dev_wm8753,
571         .codec_data = &neo1973_wm8753_setup,
572 };
573
574 static struct i2c_client client_template;
575
576 static unsigned short normal_i2c[] = { 0x7C, I2C_CLIENT_END };
577
578 /* Magic definition of all other variables and things */
579 I2C_CLIENT_INSMOD;
580
581 static int lm4857_amp_probe(struct i2c_adapter *adap, int addr, int kind)
582 {
583         int ret;
584
585         client_template.adapter = adap;
586         client_template.addr = addr;
587
588         i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
589         if (i2c == NULL)
590                 return -ENOMEM;
591
592         ret = i2c_attach_client(i2c);
593         if (ret < 0) {
594                 printk(KERN_ERR "LM4857 failed to attach at addr %x\n", addr);
595                 goto exit_err;
596         }
597
598         lm4857_write_regs();
599         return ret;
600
601 exit_err:
602         kfree(i2c);
603         return ret;
604 }
605
606 static int lm4857_i2c_detach(struct i2c_client *client)
607 {
608         i2c_detach_client(client);
609         kfree(client);
610         return 0;
611 }
612
613 static int lm4857_i2c_attach(struct i2c_adapter *adap)
614 {
615         return i2c_probe(adap, &addr_data, lm4857_amp_probe);
616 }
617
618 /* corgi i2c codec control layer */
619 static struct i2c_driver lm4857_i2c_driver = {
620         .driver = {
621                 .name = "LM4857 I2C Amp",
622                 .owner = THIS_MODULE,
623         },
624         .id =             I2C_DRIVERID_LM4857,
625         .attach_adapter = lm4857_i2c_attach,
626         .detach_client =  lm4857_i2c_detach,
627         .command =        NULL,
628 };
629
630 static struct i2c_client client_template = {
631         .name =   "LM4857",
632         .driver = &lm4857_i2c_driver,
633 };
634
635 static struct platform_device *neo1973_snd_device;
636
637 static int __init neo1973_init(void)
638 {
639         int ret;
640
641         neo1973_snd_device = platform_device_alloc("soc-audio", -1);
642         if (!neo1973_snd_device)
643                 return -ENOMEM;
644
645         platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata);
646         neo1973_snd_devdata.dev = &neo1973_snd_device->dev;
647         ret = platform_device_add(neo1973_snd_device);
648
649         if (ret)
650                 platform_device_put(neo1973_snd_device);
651
652         ret = i2c_add_driver(&lm4857_i2c_driver);
653         if (ret != 0)
654                 printk(KERN_ERR "can't add i2c driver");
655
656         return ret;
657 }
658
659 static void __exit neo1973_exit(void)
660 {
661         platform_device_unregister(neo1973_snd_device);
662 }
663
664 module_init(neo1973_init);
665 module_exit(neo1973_exit);
666
667 /* Module information */
668 MODULE_AUTHOR("Graeme Gregory, graeme.gregory@wolfsonmicro.com, www.wolfsonmicro.com");
669 MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973");
670 MODULE_LICENSE("GPL");