ead6d4b43b25f3076eb3ee5008046278654bf78c
[safe/jmp/linux-2.6] / sound / soc / codecs / twl6040.c
1 /*
2  * ALSA SoC TWL6040 codec driver
3  *
4  * Author:       Misael Lopez Cruz <x0052729@ti.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  *
20  */
21
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
26 #include <linux/pm.h>
27 #include <linux/i2c.h>
28 #include <linux/gpio.h>
29 #include <linux/platform_device.h>
30 #include <linux/slab.h>
31 #include <linux/i2c/twl.h>
32
33 #include <sound/core.h>
34 #include <sound/pcm.h>
35 #include <sound/pcm_params.h>
36 #include <sound/soc.h>
37 #include <sound/soc-dapm.h>
38 #include <sound/initval.h>
39 #include <sound/tlv.h>
40
41 #include "twl6040.h"
42
43 #define TWL6040_RATES    (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
44 #define TWL6040_FORMATS  (SNDRV_PCM_FMTBIT_S32_LE)
45
46 /* codec private data */
47 struct twl6040_data {
48         struct snd_soc_codec codec;
49         int audpwron;
50         int naudint;
51         int codec_powered;
52         int pll;
53         int non_lp;
54         unsigned int sysclk;
55         struct snd_pcm_hw_constraint_list *sysclk_constraints;
56         struct completion ready;
57 };
58
59 /*
60  * twl6040 register cache & default register settings
61  */
62 static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
63         0x00, /* not used               0x00    */
64         0x4B, /* TWL6040_ASICID (ro)    0x01    */
65         0x00, /* TWL6040_ASICREV (ro)   0x02    */
66         0x00, /* TWL6040_INTID          0x03    */
67         0x00, /* TWL6040_INTMR          0x04    */
68         0x00, /* TWL6040_NCPCTRL        0x05    */
69         0x00, /* TWL6040_LDOCTL         0x06    */
70         0x60, /* TWL6040_HPPLLCTL       0x07    */
71         0x00, /* TWL6040_LPPLLCTL       0x08    */
72         0x4A, /* TWL6040_LPPLLDIV       0x09    */
73         0x00, /* TWL6040_AMICBCTL       0x0A    */
74         0x00, /* TWL6040_DMICBCTL       0x0B    */
75         0x18, /* TWL6040_MICLCTL        0x0C    - No input selected on Left Mic */
76         0x18, /* TWL6040_MICRCTL        0x0D    - No input selected on Right Mic */
77         0x00, /* TWL6040_MICGAIN        0x0E    */
78         0x1B, /* TWL6040_LINEGAIN       0x0F    */
79         0x00, /* TWL6040_HSLCTL         0x10    */
80         0x00, /* TWL6040_HSRCTL         0x11    */
81         0x00, /* TWL6040_HSGAIN         0x12    */
82         0x00, /* TWL6040_EARCTL         0x13    */
83         0x00, /* TWL6040_HFLCTL         0x14    */
84         0x00, /* TWL6040_HFLGAIN        0x15    */
85         0x00, /* TWL6040_HFRCTL         0x16    */
86         0x00, /* TWL6040_HFRGAIN        0x17    */
87         0x00, /* TWL6040_VIBCTLL        0x18    */
88         0x00, /* TWL6040_VIBDATL        0x19    */
89         0x00, /* TWL6040_VIBCTLR        0x1A    */
90         0x00, /* TWL6040_VIBDATR        0x1B    */
91         0x00, /* TWL6040_HKCTL1         0x1C    */
92         0x00, /* TWL6040_HKCTL2         0x1D    */
93         0x00, /* TWL6040_GPOCTL         0x1E    */
94         0x00, /* TWL6040_ALB            0x1F    */
95         0x00, /* TWL6040_DLB            0x20    */
96         0x00, /* not used               0x21    */
97         0x00, /* not used               0x22    */
98         0x00, /* not used               0x23    */
99         0x00, /* not used               0x24    */
100         0x00, /* not used               0x25    */
101         0x00, /* not used               0x26    */
102         0x00, /* not used               0x27    */
103         0x00, /* TWL6040_TRIM1          0x28    */
104         0x00, /* TWL6040_TRIM2          0x29    */
105         0x00, /* TWL6040_TRIM3          0x2A    */
106         0x00, /* TWL6040_HSOTRIM        0x2B    */
107         0x00, /* TWL6040_HFOTRIM        0x2C    */
108         0x09, /* TWL6040_ACCCTL         0x2D    */
109         0x00, /* TWL6040_STATUS (ro)    0x2E    */
110 };
111
112 /*
113  * twl6040 vio/gnd registers:
114  * registers under vio/gnd supply can be accessed
115  * before the power-up sequence, after NRESPWRON goes high
116  */
117 static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = {
118         TWL6040_REG_ASICID,
119         TWL6040_REG_ASICREV,
120         TWL6040_REG_INTID,
121         TWL6040_REG_INTMR,
122         TWL6040_REG_NCPCTL,
123         TWL6040_REG_LDOCTL,
124         TWL6040_REG_AMICBCTL,
125         TWL6040_REG_DMICBCTL,
126         TWL6040_REG_HKCTL1,
127         TWL6040_REG_HKCTL2,
128         TWL6040_REG_GPOCTL,
129         TWL6040_REG_TRIM1,
130         TWL6040_REG_TRIM2,
131         TWL6040_REG_TRIM3,
132         TWL6040_REG_HSOTRIM,
133         TWL6040_REG_HFOTRIM,
134         TWL6040_REG_ACCCTL,
135         TWL6040_REG_STATUS,
136 };
137
138 /*
139  * twl6040 vdd/vss registers:
140  * registers under vdd/vss supplies can only be accessed
141  * after the power-up sequence
142  */
143 static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
144         TWL6040_REG_HPPLLCTL,
145         TWL6040_REG_LPPLLCTL,
146         TWL6040_REG_LPPLLDIV,
147         TWL6040_REG_MICLCTL,
148         TWL6040_REG_MICRCTL,
149         TWL6040_REG_MICGAIN,
150         TWL6040_REG_LINEGAIN,
151         TWL6040_REG_HSLCTL,
152         TWL6040_REG_HSRCTL,
153         TWL6040_REG_HSGAIN,
154         TWL6040_REG_EARCTL,
155         TWL6040_REG_HFLCTL,
156         TWL6040_REG_HFLGAIN,
157         TWL6040_REG_HFRCTL,
158         TWL6040_REG_HFRGAIN,
159         TWL6040_REG_VIBCTLL,
160         TWL6040_REG_VIBDATL,
161         TWL6040_REG_VIBCTLR,
162         TWL6040_REG_VIBDATR,
163         TWL6040_REG_ALB,
164         TWL6040_REG_DLB,
165 };
166
167 /*
168  * read twl6040 register cache
169  */
170 static inline unsigned int twl6040_read_reg_cache(struct snd_soc_codec *codec,
171                                                 unsigned int reg)
172 {
173         u8 *cache = codec->reg_cache;
174
175         if (reg >= TWL6040_CACHEREGNUM)
176                 return -EIO;
177
178         return cache[reg];
179 }
180
181 /*
182  * write twl6040 register cache
183  */
184 static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
185                                                 u8 reg, u8 value)
186 {
187         u8 *cache = codec->reg_cache;
188
189         if (reg >= TWL6040_CACHEREGNUM)
190                 return;
191         cache[reg] = value;
192 }
193
194 /*
195  * read from twl6040 hardware register
196  */
197 static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
198                         unsigned int reg)
199 {
200         u8 value;
201
202         if (reg >= TWL6040_CACHEREGNUM)
203                 return -EIO;
204
205         twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &value, reg);
206         twl6040_write_reg_cache(codec, reg, value);
207
208         return value;
209 }
210
211 /*
212  * write to the twl6040 register space
213  */
214 static int twl6040_write(struct snd_soc_codec *codec,
215                         unsigned int reg, unsigned int value)
216 {
217         if (reg >= TWL6040_CACHEREGNUM)
218                 return -EIO;
219
220         twl6040_write_reg_cache(codec, reg, value);
221         return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
222 }
223
224 static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
225 {
226         u8 *cache = codec->reg_cache;
227         int reg, i;
228
229         /* allow registers to be accessed by i2c */
230         twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]);
231
232         for (i = 0; i < TWL6040_VIOREGNUM; i++) {
233                 reg = twl6040_vio_reg[i];
234                 /* skip read-only registers (ASICID, ASICREV, STATUS) */
235                 switch (reg) {
236                 case TWL6040_REG_ASICID:
237                 case TWL6040_REG_ASICREV:
238                 case TWL6040_REG_STATUS:
239                         continue;
240                 default:
241                         break;
242                 }
243                 twl6040_write(codec, reg, cache[reg]);
244         }
245 }
246
247 static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
248 {
249         u8 *cache = codec->reg_cache;
250         int reg, i;
251
252         for (i = 0; i < TWL6040_VDDREGNUM; i++) {
253                 reg = twl6040_vdd_reg[i];
254                 twl6040_write(codec, reg, cache[reg]);
255         }
256 }
257
258 /* twl6040 codec manual power-up sequence */
259 static void twl6040_power_up(struct snd_soc_codec *codec)
260 {
261         u8 ncpctl, ldoctl, lppllctl, accctl;
262
263         ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
264         ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
265         lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
266         accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
267
268         /* enable reference system */
269         ldoctl |= TWL6040_REFENA;
270         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
271         msleep(10);
272         /* enable internal oscillator */
273         ldoctl |= TWL6040_OSCENA;
274         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
275         udelay(10);
276         /* enable high-side ldo */
277         ldoctl |= TWL6040_HSLDOENA;
278         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
279         udelay(244);
280         /* enable negative charge pump */
281         ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
282         twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
283         udelay(488);
284         /* enable low-side ldo */
285         ldoctl |= TWL6040_LSLDOENA;
286         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
287         udelay(244);
288         /* enable low-power pll */
289         lppllctl |= TWL6040_LPLLENA;
290         twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
291         /* reset state machine */
292         accctl |= TWL6040_RESETSPLIT;
293         twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
294         mdelay(5);
295         accctl &= ~TWL6040_RESETSPLIT;
296         twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
297         /* disable internal oscillator */
298         ldoctl &= ~TWL6040_OSCENA;
299         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
300 }
301
302 /* twl6040 codec manual power-down sequence */
303 static void twl6040_power_down(struct snd_soc_codec *codec)
304 {
305         u8 ncpctl, ldoctl, lppllctl, accctl;
306
307         ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
308         ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
309         lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
310         accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
311
312         /* enable internal oscillator */
313         ldoctl |= TWL6040_OSCENA;
314         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
315         udelay(10);
316         /* disable low-power pll */
317         lppllctl &= ~TWL6040_LPLLENA;
318         twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
319         /* disable low-side ldo */
320         ldoctl &= ~TWL6040_LSLDOENA;
321         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
322         udelay(244);
323         /* disable negative charge pump */
324         ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
325         twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
326         udelay(488);
327         /* disable high-side ldo */
328         ldoctl &= ~TWL6040_HSLDOENA;
329         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
330         udelay(244);
331         /* disable internal oscillator */
332         ldoctl &= ~TWL6040_OSCENA;
333         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
334         /* disable reference system */
335         ldoctl &= ~TWL6040_REFENA;
336         twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
337         msleep(10);
338 }
339
340 /* set headset dac and driver power mode */
341 static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
342 {
343         int hslctl, hsrctl;
344         int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;
345
346         hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
347         hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
348
349         if (high_perf) {
350                 hslctl &= ~mask;
351                 hsrctl &= ~mask;
352         } else {
353                 hslctl |= mask;
354                 hsrctl |= mask;
355         }
356
357         twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
358         twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
359
360         return 0;
361 }
362
363 static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
364                         struct snd_kcontrol *kcontrol, int event)
365 {
366         struct snd_soc_codec *codec = w->codec;
367         struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
368
369         if (SND_SOC_DAPM_EVENT_ON(event))
370                 priv->non_lp++;
371         else
372                 priv->non_lp--;
373
374         return 0;
375 }
376
377 /* audio interrupt handler */
378 static irqreturn_t twl6040_naudint_handler(int irq, void *data)
379 {
380         struct snd_soc_codec *codec = data;
381         struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
382         u8 intid;
383
384         twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
385
386         switch (intid) {
387         case TWL6040_THINT:
388                 dev_alert(codec->dev, "die temp over-limit detection\n");
389                 break;
390         case TWL6040_PLUGINT:
391         case TWL6040_UNPLUGINT:
392         case TWL6040_HOOKINT:
393                 break;
394         case TWL6040_HFINT:
395                 dev_alert(codec->dev, "hf drivers over current detection\n");
396                 break;
397         case TWL6040_VIBINT:
398                 dev_alert(codec->dev, "vib drivers over current detection\n");
399                 break;
400         case TWL6040_READYINT:
401                 complete(&priv->ready);
402                 break;
403         default:
404                 dev_err(codec->dev, "unknown audio interrupt %d\n", intid);
405                 break;
406         }
407
408         return IRQ_HANDLED;
409 }
410
411 /*
412  * MICATT volume control:
413  * from -6 to 0 dB in 6 dB steps
414  */
415 static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
416
417 /*
418  * MICGAIN volume control:
419  * from 6 to 30 dB in 6 dB steps
420  */
421 static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0);
422
423 /*
424  * HSGAIN volume control:
425  * from -30 to 0 dB in 2 dB steps
426  */
427 static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0);
428
429 /*
430  * HFGAIN volume control:
431  * from -52 to 6 dB in 2 dB steps
432  */
433 static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0);
434
435 /* Left analog microphone selection */
436 static const char *twl6040_amicl_texts[] =
437         {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
438
439 /* Right analog microphone selection */
440 static const char *twl6040_amicr_texts[] =
441         {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
442
443 static const struct soc_enum twl6040_enum[] = {
444         SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 3, twl6040_amicl_texts),
445         SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 3, twl6040_amicr_texts),
446 };
447
448 static const struct snd_kcontrol_new amicl_control =
449         SOC_DAPM_ENUM("Route", twl6040_enum[0]);
450
451 static const struct snd_kcontrol_new amicr_control =
452         SOC_DAPM_ENUM("Route", twl6040_enum[1]);
453
454 /* Headset DAC playback switches */
455 static const struct snd_kcontrol_new hsdacl_switch_controls =
456         SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 5, 1, 0);
457
458 static const struct snd_kcontrol_new hsdacr_switch_controls =
459         SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 5, 1, 0);
460
461 /* Handsfree DAC playback switches */
462 static const struct snd_kcontrol_new hfdacl_switch_controls =
463         SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 2, 1, 0);
464
465 static const struct snd_kcontrol_new hfdacr_switch_controls =
466         SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 2, 1, 0);
467
468 /* Headset driver switches */
469 static const struct snd_kcontrol_new hsl_driver_switch_controls =
470         SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 2, 1, 0);
471
472 static const struct snd_kcontrol_new hsr_driver_switch_controls =
473         SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 2, 1, 0);
474
475 /* Handsfree driver switches */
476 static const struct snd_kcontrol_new hfl_driver_switch_controls =
477         SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 4, 1, 0);
478
479 static const struct snd_kcontrol_new hfr_driver_switch_controls =
480         SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 4, 1, 0);
481
482 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
483         /* Capture gains */
484         SOC_DOUBLE_TLV("Capture Preamplifier Volume",
485                 TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv),
486         SOC_DOUBLE_TLV("Capture Volume",
487                 TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv),
488
489         /* Playback gains */
490         SOC_DOUBLE_TLV("Headset Playback Volume",
491                 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
492         SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
493                 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
494
495 };
496
497 static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
498         /* Inputs */
499         SND_SOC_DAPM_INPUT("MAINMIC"),
500         SND_SOC_DAPM_INPUT("HSMIC"),
501         SND_SOC_DAPM_INPUT("SUBMIC"),
502         SND_SOC_DAPM_INPUT("AFML"),
503         SND_SOC_DAPM_INPUT("AFMR"),
504
505         /* Outputs */
506         SND_SOC_DAPM_OUTPUT("HSOL"),
507         SND_SOC_DAPM_OUTPUT("HSOR"),
508         SND_SOC_DAPM_OUTPUT("HFL"),
509         SND_SOC_DAPM_OUTPUT("HFR"),
510
511         /* Analog input muxes for the capture amplifiers */
512         SND_SOC_DAPM_MUX("Analog Left Capture Route",
513                         SND_SOC_NOPM, 0, 0, &amicl_control),
514         SND_SOC_DAPM_MUX("Analog Right Capture Route",
515                         SND_SOC_NOPM, 0, 0, &amicr_control),
516
517         /* Analog capture PGAs */
518         SND_SOC_DAPM_PGA("MicAmpL",
519                         TWL6040_REG_MICLCTL, 0, 0, NULL, 0),
520         SND_SOC_DAPM_PGA("MicAmpR",
521                         TWL6040_REG_MICRCTL, 0, 0, NULL, 0),
522
523         /* ADCs */
524         SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture",
525                         TWL6040_REG_MICLCTL, 2, 0),
526         SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture",
527                         TWL6040_REG_MICRCTL, 2, 0),
528
529         /* Microphone bias */
530         SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
531                         TWL6040_REG_AMICBCTL, 0, 0),
532         SND_SOC_DAPM_MICBIAS("Main Mic Bias",
533                         TWL6040_REG_AMICBCTL, 4, 0),
534         SND_SOC_DAPM_MICBIAS("Digital Mic1 Bias",
535                         TWL6040_REG_DMICBCTL, 0, 0),
536         SND_SOC_DAPM_MICBIAS("Digital Mic2 Bias",
537                         TWL6040_REG_DMICBCTL, 4, 0),
538
539         /* DACs */
540         SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback",
541                         TWL6040_REG_HSLCTL, 0, 0),
542         SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback",
543                         TWL6040_REG_HSRCTL, 0, 0),
544         SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
545                         TWL6040_REG_HFLCTL, 0, 0,
546                         twl6040_power_mode_event,
547                         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
548         SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
549                         TWL6040_REG_HFRCTL, 0, 0,
550                         twl6040_power_mode_event,
551                         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
552
553         /* Analog playback switches */
554         SND_SOC_DAPM_SWITCH("HSDAC Left Playback",
555                         SND_SOC_NOPM, 0, 0, &hsdacl_switch_controls),
556         SND_SOC_DAPM_SWITCH("HSDAC Right Playback",
557                         SND_SOC_NOPM, 0, 0, &hsdacr_switch_controls),
558         SND_SOC_DAPM_SWITCH("HFDAC Left Playback",
559                         SND_SOC_NOPM, 0, 0, &hfdacl_switch_controls),
560         SND_SOC_DAPM_SWITCH("HFDAC Right Playback",
561                         SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls),
562
563         SND_SOC_DAPM_SWITCH("Headset Left Driver",
564                         SND_SOC_NOPM, 0, 0, &hsl_driver_switch_controls),
565         SND_SOC_DAPM_SWITCH("Headset Right Driver",
566                         SND_SOC_NOPM, 0, 0, &hsr_driver_switch_controls),
567         SND_SOC_DAPM_SWITCH_E("Handsfree Left Driver",
568                         SND_SOC_NOPM, 0, 0, &hfl_driver_switch_controls,
569                         twl6040_power_mode_event,
570                         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
571         SND_SOC_DAPM_SWITCH_E("Handsfree Right Driver",
572                         SND_SOC_NOPM, 0, 0, &hfr_driver_switch_controls,
573                         twl6040_power_mode_event,
574                         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
575
576         /* Analog playback PGAs */
577         SND_SOC_DAPM_PGA("HFDAC Left PGA",
578                         TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
579         SND_SOC_DAPM_PGA("HFDAC Right PGA",
580                         TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
581
582 };
583
584 static const struct snd_soc_dapm_route intercon[] = {
585         /* Capture path */
586         {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
587         {"Analog Left Capture Route", "Main Mic", "MAINMIC"},
588         {"Analog Left Capture Route", "Aux/FM Left", "AFML"},
589
590         {"Analog Right Capture Route", "Headset Mic", "HSMIC"},
591         {"Analog Right Capture Route", "Sub Mic", "SUBMIC"},
592         {"Analog Right Capture Route", "Aux/FM Right", "AFMR"},
593
594         {"MicAmpL", NULL, "Analog Left Capture Route"},
595         {"MicAmpR", NULL, "Analog Right Capture Route"},
596
597         {"ADC Left", NULL, "MicAmpL"},
598         {"ADC Right", NULL, "MicAmpR"},
599
600         /* Headset playback path */
601         {"HSDAC Left Playback", "Switch", "HSDAC Left"},
602         {"HSDAC Right Playback", "Switch", "HSDAC Right"},
603
604         {"Headset Left Driver", "Switch", "HSDAC Left Playback"},
605         {"Headset Right Driver", "Switch", "HSDAC Right Playback"},
606
607         {"HSOL", NULL, "Headset Left Driver"},
608         {"HSOR", NULL, "Headset Right Driver"},
609
610         /* Handsfree playback path */
611         {"HFDAC Left Playback", "Switch", "HFDAC Left"},
612         {"HFDAC Right Playback", "Switch", "HFDAC Right"},
613
614         {"HFDAC Left PGA", NULL, "HFDAC Left Playback"},
615         {"HFDAC Right PGA", NULL, "HFDAC Right Playback"},
616
617         {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
618         {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
619
620         {"HFL", NULL, "Handsfree Left Driver"},
621         {"HFR", NULL, "Handsfree Right Driver"},
622 };
623
624 static int twl6040_add_widgets(struct snd_soc_codec *codec)
625 {
626         snd_soc_dapm_new_controls(codec, twl6040_dapm_widgets,
627                                  ARRAY_SIZE(twl6040_dapm_widgets));
628
629         snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
630
631         snd_soc_dapm_new_widgets(codec);
632
633         return 0;
634 }
635
636 static int twl6040_power_up_completion(struct snd_soc_codec *codec,
637                                         int naudint)
638 {
639         struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
640         int time_left;
641         u8 intid;
642
643         time_left = wait_for_completion_timeout(&priv->ready,
644                                 msecs_to_jiffies(48));
645
646         if (!time_left) {
647                 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid,
648                                                         TWL6040_REG_INTID);
649                 if (!(intid & TWL6040_READYINT)) {
650                         dev_err(codec->dev, "timeout waiting for READYINT\n");
651                         return -ETIMEDOUT;
652                 }
653         }
654
655         priv->codec_powered = 1;
656
657         return 0;
658 }
659
660 static int twl6040_set_bias_level(struct snd_soc_codec *codec,
661                                 enum snd_soc_bias_level level)
662 {
663         struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
664         int audpwron = priv->audpwron;
665         int naudint = priv->naudint;
666         int ret;
667
668         switch (level) {
669         case SND_SOC_BIAS_ON:
670                 break;
671         case SND_SOC_BIAS_PREPARE:
672                 break;
673         case SND_SOC_BIAS_STANDBY:
674                 if (priv->codec_powered)
675                         break;
676
677                 if (gpio_is_valid(audpwron)) {
678                         /* use AUDPWRON line */
679                         gpio_set_value(audpwron, 1);
680
681                         /* wait for power-up completion */
682                         ret = twl6040_power_up_completion(codec, naudint);
683                         if (ret)
684                                 return ret;
685
686                         /* sync registers updated during power-up sequence */
687                         twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
688                         twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
689                         twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
690                 } else {
691                         /* use manual power-up sequence */
692                         twl6040_power_up(codec);
693                         priv->codec_powered = 1;
694                 }
695
696                 /* initialize vdd/vss registers with reg_cache */
697                 twl6040_init_vdd_regs(codec);
698                 break;
699         case SND_SOC_BIAS_OFF:
700                 if (!priv->codec_powered)
701                         break;
702
703                 if (gpio_is_valid(audpwron)) {
704                         /* use AUDPWRON line */
705                         gpio_set_value(audpwron, 0);
706
707                         /* power-down sequence latency */
708                         udelay(500);
709
710                         /* sync registers updated during power-down sequence */
711                         twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
712                         twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
713                         twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
714                                                 0x00);
715                 } else {
716                         /* use manual power-down sequence */
717                         twl6040_power_down(codec);
718                 }
719
720                 priv->codec_powered = 0;
721                 break;
722         }
723
724         codec->bias_level = level;
725
726         return 0;
727 }
728
729 /* set of rates for each pll: low-power and high-performance */
730
731 static unsigned int lp_rates[] = {
732         88200,
733         96000,
734 };
735
736 static struct snd_pcm_hw_constraint_list lp_constraints = {
737         .count  = ARRAY_SIZE(lp_rates),
738         .list   = lp_rates,
739 };
740
741 static unsigned int hp_rates[] = {
742         96000,
743 };
744
745 static struct snd_pcm_hw_constraint_list hp_constraints = {
746         .count  = ARRAY_SIZE(hp_rates),
747         .list   = hp_rates,
748 };
749
750 static int twl6040_startup(struct snd_pcm_substream *substream,
751                         struct snd_soc_dai *dai)
752 {
753         struct snd_soc_pcm_runtime *rtd = substream->private_data;
754         struct snd_soc_device *socdev = rtd->socdev;
755         struct snd_soc_codec *codec = socdev->card->codec;
756         struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
757
758         if (!priv->sysclk) {
759                 dev_err(codec->dev,
760                         "no mclk configured, call set_sysclk() on init\n");
761                 return -EINVAL;
762         }
763
764         /*
765          * capture is not supported at 17.64 MHz,
766          * it's reserved for headset low-power playback scenario
767          */
768         if ((priv->sysclk == 17640000) && substream->stream) {
769                 dev_err(codec->dev,
770                         "capture mode is not supported at %dHz\n",
771                         priv->sysclk);
772                 return -EINVAL;
773         }
774
775         snd_pcm_hw_constraint_list(substream->runtime, 0,
776                                 SNDRV_PCM_HW_PARAM_RATE,
777                                 priv->sysclk_constraints);
778
779         return 0;
780 }
781
782 static int twl6040_hw_params(struct snd_pcm_substream *substream,
783                         struct snd_pcm_hw_params *params,
784                         struct snd_soc_dai *dai)
785 {
786         struct snd_soc_pcm_runtime *rtd = substream->private_data;
787         struct snd_soc_device *socdev = rtd->socdev;
788         struct snd_soc_codec *codec = socdev->card->codec;
789         struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
790         u8 lppllctl;
791         int rate;
792
793         /* nothing to do for high-perf pll, it supports only 48 kHz */
794         if (priv->pll == TWL6040_HPPLL_ID)
795                 return 0;
796
797         lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
798
799         rate = params_rate(params);
800         switch (rate) {
801         case 88200:
802                 lppllctl |= TWL6040_LPLLFIN;
803                 priv->sysclk = 17640000;
804                 break;
805         case 96000:
806                 lppllctl &= ~TWL6040_LPLLFIN;
807                 priv->sysclk = 19200000;
808                 break;
809         default:
810                 dev_err(codec->dev, "unsupported rate %d\n", rate);
811                 return -EINVAL;
812         }
813
814         twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
815
816         return 0;
817 }
818
819 static int twl6040_trigger(struct snd_pcm_substream *substream,
820                         int cmd, struct snd_soc_dai *dai)
821 {
822         struct snd_soc_pcm_runtime *rtd = substream->private_data;
823         struct snd_soc_device *socdev = rtd->socdev;
824         struct snd_soc_codec *codec = socdev->card->codec;
825         struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
826
827         switch (cmd) {
828         case SNDRV_PCM_TRIGGER_START:
829         case SNDRV_PCM_TRIGGER_RESUME:
830                 /*
831                  * low-power playback mode is restricted
832                  * for headset path only
833                  */
834                 if ((priv->sysclk == 17640000) && priv->non_lp) {
835                         dev_err(codec->dev,
836                                 "some enabled paths aren't supported at %dHz\n",
837                                 priv->sysclk);
838                         return -EPERM;
839                 }
840                 break;
841         default:
842                 break;
843         }
844
845         return 0;
846 }
847
848 static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
849                 int clk_id, unsigned int freq, int dir)
850 {
851         struct snd_soc_codec *codec = codec_dai->codec;
852         struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
853         u8 hppllctl, lppllctl;
854
855         hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL);
856         lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
857
858         switch (clk_id) {
859         case TWL6040_SYSCLK_SEL_LPPLL:
860                 switch (freq) {
861                 case 32768:
862                         /* headset dac and driver must be in low-power mode */
863                         headset_power_mode(codec, 0);
864
865                         /* clk32k input requires low-power pll */
866                         lppllctl |= TWL6040_LPLLENA;
867                         twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
868                         mdelay(5);
869                         lppllctl &= ~TWL6040_HPLLSEL;
870                         twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
871                         hppllctl &= ~TWL6040_HPLLENA;
872                         twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
873                         break;
874                 default:
875                         dev_err(codec->dev, "unknown mclk freq %d\n", freq);
876                         return -EINVAL;
877                 }
878
879                 /* lppll divider */
880                 switch (priv->sysclk) {
881                 case 17640000:
882                         lppllctl |= TWL6040_LPLLFIN;
883                         break;
884                 case 19200000:
885                         lppllctl &= ~TWL6040_LPLLFIN;
886                         break;
887                 default:
888                         /* sysclk not yet configured */
889                         lppllctl &= ~TWL6040_LPLLFIN;
890                         priv->sysclk = 19200000;
891                         break;
892                 }
893
894                 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
895
896                 priv->pll = TWL6040_LPPLL_ID;
897                 priv->sysclk_constraints = &lp_constraints;
898                 break;
899         case TWL6040_SYSCLK_SEL_HPPLL:
900                 hppllctl &= ~TWL6040_MCLK_MSK;
901
902                 switch (freq) {
903                 case 12000000:
904                         /* mclk input, pll enabled */
905                         hppllctl |= TWL6040_MCLK_12000KHZ |
906                                     TWL6040_HPLLSQRBP |
907                                     TWL6040_HPLLENA;
908                         break;
909                 case 19200000:
910                         /* mclk input, pll disabled */
911                         hppllctl |= TWL6040_MCLK_19200KHZ |
912                                     TWL6040_HPLLSQRBP |
913                                     TWL6040_HPLLBP;
914                         break;
915                 case 26000000:
916                         /* mclk input, pll enabled */
917                         hppllctl |= TWL6040_MCLK_26000KHZ |
918                                     TWL6040_HPLLSQRBP |
919                                     TWL6040_HPLLENA;
920                         break;
921                 case 38400000:
922                         /* clk slicer, pll disabled */
923                         hppllctl |= TWL6040_MCLK_38400KHZ |
924                                     TWL6040_HPLLSQRENA |
925                                     TWL6040_HPLLBP;
926                         break;
927                 default:
928                         dev_err(codec->dev, "unknown mclk freq %d\n", freq);
929                         return -EINVAL;
930                 }
931
932                 /* headset dac and driver must be in high-performance mode */
933                 headset_power_mode(codec, 1);
934
935                 twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
936                 udelay(500);
937                 lppllctl |= TWL6040_HPLLSEL;
938                 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
939                 lppllctl &= ~TWL6040_LPLLENA;
940                 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
941
942                 /* high-performance pll can provide only 19.2 MHz */
943                 priv->pll = TWL6040_HPPLL_ID;
944                 priv->sysclk = 19200000;
945                 priv->sysclk_constraints = &hp_constraints;
946                 break;
947         default:
948                 dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
949                 return -EINVAL;
950         }
951
952         return 0;
953 }
954
955 static struct snd_soc_dai_ops twl6040_dai_ops = {
956         .startup        = twl6040_startup,
957         .hw_params      = twl6040_hw_params,
958         .trigger        = twl6040_trigger,
959         .set_sysclk     = twl6040_set_dai_sysclk,
960 };
961
962 struct snd_soc_dai twl6040_dai = {
963         .name = "twl6040",
964         .playback = {
965                 .stream_name = "Playback",
966                 .channels_min = 1,
967                 .channels_max = 4,
968                 .rates = TWL6040_RATES,
969                 .formats = TWL6040_FORMATS,
970         },
971         .capture = {
972                 .stream_name = "Capture",
973                 .channels_min = 1,
974                 .channels_max = 2,
975                 .rates = TWL6040_RATES,
976                 .formats = TWL6040_FORMATS,
977         },
978         .ops = &twl6040_dai_ops,
979 };
980 EXPORT_SYMBOL_GPL(twl6040_dai);
981
982 #ifdef CONFIG_PM
983 static int twl6040_suspend(struct platform_device *pdev, pm_message_t state)
984 {
985         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
986         struct snd_soc_codec *codec = socdev->card->codec;
987
988         twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
989
990         return 0;
991 }
992
993 static int twl6040_resume(struct platform_device *pdev)
994 {
995         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
996         struct snd_soc_codec *codec = socdev->card->codec;
997
998         twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
999         twl6040_set_bias_level(codec, codec->suspend_bias_level);
1000
1001         return 0;
1002 }
1003 #else
1004 #define twl6040_suspend NULL
1005 #define twl6040_resume NULL
1006 #endif
1007
1008 static struct snd_soc_codec *twl6040_codec;
1009
1010 static int twl6040_probe(struct platform_device *pdev)
1011 {
1012         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1013         struct snd_soc_codec *codec;
1014         int ret = 0;
1015
1016         BUG_ON(!twl6040_codec);
1017
1018         codec = twl6040_codec;
1019         socdev->card->codec = codec;
1020
1021         /* register pcms */
1022         ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1023         if (ret < 0) {
1024                 dev_err(&pdev->dev, "failed to create pcms\n");
1025                 return ret;
1026         }
1027
1028         snd_soc_add_controls(codec, twl6040_snd_controls,
1029                                 ARRAY_SIZE(twl6040_snd_controls));
1030         twl6040_add_widgets(codec);
1031
1032         if (ret < 0) {
1033                 dev_err(&pdev->dev, "failed to register card\n");
1034                 goto card_err;
1035         }
1036
1037         return ret;
1038
1039 card_err:
1040         snd_soc_free_pcms(socdev);
1041         snd_soc_dapm_free(socdev);
1042         return ret;
1043 }
1044
1045 static int twl6040_remove(struct platform_device *pdev)
1046 {
1047         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1048         struct snd_soc_codec *codec = socdev->card->codec;
1049
1050         twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1051         snd_soc_free_pcms(socdev);
1052         snd_soc_dapm_free(socdev);
1053         kfree(codec);
1054
1055         return 0;
1056 }
1057
1058 struct snd_soc_codec_device soc_codec_dev_twl6040 = {
1059         .probe = twl6040_probe,
1060         .remove = twl6040_remove,
1061         .suspend = twl6040_suspend,
1062         .resume = twl6040_resume,
1063 };
1064 EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040);
1065
1066 static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1067 {
1068         struct twl4030_codec_data *twl_codec = pdev->dev.platform_data;
1069         struct snd_soc_codec *codec;
1070         struct twl6040_data *priv;
1071         int audpwron, naudint;
1072         int ret = 0;
1073
1074         priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
1075         if (priv == NULL)
1076                 return -ENOMEM;
1077
1078         if (twl_codec) {
1079                 audpwron = twl_codec->audpwron_gpio;
1080                 naudint = twl_codec->naudint_irq;
1081         } else {
1082                 audpwron = -EINVAL;
1083                 naudint = 0;
1084         }
1085
1086         priv->audpwron = audpwron;
1087         priv->naudint = naudint;
1088
1089         codec = &priv->codec;
1090         codec->dev = &pdev->dev;
1091         twl6040_dai.dev = &pdev->dev;
1092
1093         codec->name = "twl6040";
1094         codec->owner = THIS_MODULE;
1095         codec->read = twl6040_read_reg_cache;
1096         codec->write = twl6040_write;
1097         codec->set_bias_level = twl6040_set_bias_level;
1098         snd_soc_codec_set_drvdata(codec, priv);
1099         codec->dai = &twl6040_dai;
1100         codec->num_dai = 1;
1101         codec->reg_cache_size = ARRAY_SIZE(twl6040_reg);
1102         codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg),
1103                                         GFP_KERNEL);
1104         if (codec->reg_cache == NULL) {
1105                 ret = -ENOMEM;
1106                 goto cache_err;
1107         }
1108
1109         mutex_init(&codec->mutex);
1110         INIT_LIST_HEAD(&codec->dapm_widgets);
1111         INIT_LIST_HEAD(&codec->dapm_paths);
1112         init_completion(&priv->ready);
1113
1114         if (gpio_is_valid(audpwron)) {
1115                 ret = gpio_request(audpwron, "audpwron");
1116                 if (ret)
1117                         goto gpio1_err;
1118
1119                 ret = gpio_direction_output(audpwron, 0);
1120                 if (ret)
1121                         goto gpio2_err;
1122
1123                 priv->codec_powered = 0;
1124         }
1125
1126         if (naudint) {
1127                 /* audio interrupt */
1128                 ret = request_threaded_irq(naudint, NULL,
1129                                 twl6040_naudint_handler,
1130                                 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
1131                                 "twl6040_codec", codec);
1132                 if (ret)
1133                         goto gpio2_err;
1134         } else {
1135                 if (gpio_is_valid(audpwron)) {
1136                         /* enable only codec ready interrupt */
1137                         twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1138                                         ~TWL6040_READYMSK & TWL6040_ALLINT_MSK);
1139                 } else {
1140                         /* no interrupts at all */
1141                         twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1142                                                 TWL6040_ALLINT_MSK);
1143                 }
1144         }
1145
1146         /* init vio registers */
1147         twl6040_init_vio_regs(codec);
1148
1149         /* power on device */
1150         ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1151         if (ret)
1152                 goto irq_err;
1153
1154         ret = snd_soc_register_codec(codec);
1155         if (ret)
1156                 goto reg_err;
1157
1158         twl6040_codec = codec;
1159
1160         ret = snd_soc_register_dai(&twl6040_dai);
1161         if (ret)
1162                 goto dai_err;
1163
1164         return 0;
1165
1166 dai_err:
1167         snd_soc_unregister_codec(codec);
1168         twl6040_codec = NULL;
1169 reg_err:
1170         twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1171 irq_err:
1172         if (naudint)
1173                 free_irq(naudint, codec);
1174 gpio2_err:
1175         if (gpio_is_valid(audpwron))
1176                 gpio_free(audpwron);
1177 gpio1_err:
1178         kfree(codec->reg_cache);
1179 cache_err:
1180         kfree(priv);
1181         return ret;
1182 }
1183
1184 static int __devexit twl6040_codec_remove(struct platform_device *pdev)
1185 {
1186         struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec);
1187         int audpwron = priv->audpwron;
1188         int naudint = priv->naudint;
1189
1190         if (gpio_is_valid(audpwron))
1191                 gpio_free(audpwron);
1192
1193         if (naudint)
1194                 free_irq(naudint, twl6040_codec);
1195
1196         snd_soc_unregister_dai(&twl6040_dai);
1197         snd_soc_unregister_codec(twl6040_codec);
1198
1199         kfree(twl6040_codec);
1200         twl6040_codec = NULL;
1201
1202         return 0;
1203 }
1204
1205 static struct platform_driver twl6040_codec_driver = {
1206         .driver = {
1207                 .name = "twl6040_codec",
1208                 .owner = THIS_MODULE,
1209         },
1210         .probe = twl6040_codec_probe,
1211         .remove = __devexit_p(twl6040_codec_remove),
1212 };
1213
1214 static int __init twl6040_codec_init(void)
1215 {
1216         return platform_driver_register(&twl6040_codec_driver);
1217 }
1218 module_init(twl6040_codec_init);
1219
1220 static void __exit twl6040_codec_exit(void)
1221 {
1222         platform_driver_unregister(&twl6040_codec_driver);
1223 }
1224 module_exit(twl6040_codec_exit);
1225
1226 MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
1227 MODULE_AUTHOR("Misael Lopez Cruz");
1228 MODULE_LICENSE("GPL");