ASoC: TWL4030: Change the capture volume control to TLV
[pandora-kernel.git] / sound / soc / codecs / twl4030.c
1 /*
2  * ALSA SoC TWL4030 codec driver
3  *
4  * Author:      Steve Sakoman, <steve@sakoman.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/platform_device.h>
29 #include <linux/i2c/twl4030.h>
30 #include <sound/core.h>
31 #include <sound/pcm.h>
32 #include <sound/pcm_params.h>
33 #include <sound/soc.h>
34 #include <sound/soc-dapm.h>
35 #include <sound/initval.h>
36 #include <sound/tlv.h>
37
38 #include "twl4030.h"
39
40 /*
41  * twl4030 register cache & default register settings
42  */
43 static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
44         0x00, /* this register not used         */
45         0x93, /* REG_CODEC_MODE         (0x1)   */
46         0xc3, /* REG_OPTION             (0x2)   */
47         0x00, /* REG_UNKNOWN            (0x3)   */
48         0x00, /* REG_MICBIAS_CTL        (0x4)   */
49         0x24, /* REG_ANAMICL            (0x5)   */
50         0x04, /* REG_ANAMICR            (0x6)   */
51         0x0a, /* REG_AVADC_CTL          (0x7)   */
52         0x00, /* REG_ADCMICSEL          (0x8)   */
53         0x00, /* REG_DIGMIXING          (0x9)   */
54         0x0c, /* REG_ATXL1PGA           (0xA)   */
55         0x0c, /* REG_ATXR1PGA           (0xB)   */
56         0x00, /* REG_AVTXL2PGA          (0xC)   */
57         0x00, /* REG_AVTXR2PGA          (0xD)   */
58         0x01, /* REG_AUDIO_IF           (0xE)   */
59         0x00, /* REG_VOICE_IF           (0xF)   */
60         0x00, /* REG_ARXR1PGA           (0x10)  */
61         0x00, /* REG_ARXL1PGA           (0x11)  */
62         0x6c, /* REG_ARXR2PGA           (0x12)  */
63         0x6c, /* REG_ARXL2PGA           (0x13)  */
64         0x00, /* REG_VRXPGA             (0x14)  */
65         0x00, /* REG_VSTPGA             (0x15)  */
66         0x00, /* REG_VRX2ARXPGA         (0x16)  */
67         0x0c, /* REG_AVDAC_CTL          (0x17)  */
68         0x00, /* REG_ARX2VTXPGA         (0x18)  */
69         0x00, /* REG_ARXL1_APGA_CTL     (0x19)  */
70         0x00, /* REG_ARXR1_APGA_CTL     (0x1A)  */
71         0x4b, /* REG_ARXL2_APGA_CTL     (0x1B)  */
72         0x4b, /* REG_ARXR2_APGA_CTL     (0x1C)  */
73         0x00, /* REG_ATX2ARXPGA         (0x1D)  */
74         0x00, /* REG_BT_IF              (0x1E)  */
75         0x00, /* REG_BTPGA              (0x1F)  */
76         0x00, /* REG_BTSTPGA            (0x20)  */
77         0x00, /* REG_EAR_CTL            (0x21)  */
78         0x24, /* REG_HS_SEL             (0x22)  */
79         0x0a, /* REG_HS_GAIN_SET        (0x23)  */
80         0x00, /* REG_HS_POPN_SET        (0x24)  */
81         0x00, /* REG_PREDL_CTL          (0x25)  */
82         0x00, /* REG_PREDR_CTL          (0x26)  */
83         0x00, /* REG_PRECKL_CTL         (0x27)  */
84         0x00, /* REG_PRECKR_CTL         (0x28)  */
85         0x00, /* REG_HFL_CTL            (0x29)  */
86         0x00, /* REG_HFR_CTL            (0x2A)  */
87         0x00, /* REG_ALC_CTL            (0x2B)  */
88         0x00, /* REG_ALC_SET1           (0x2C)  */
89         0x00, /* REG_ALC_SET2           (0x2D)  */
90         0x00, /* REG_BOOST_CTL          (0x2E)  */
91         0x00, /* REG_SOFTVOL_CTL        (0x2F)  */
92         0x00, /* REG_DTMF_FREQSEL       (0x30)  */
93         0x00, /* REG_DTMF_TONEXT1H      (0x31)  */
94         0x00, /* REG_DTMF_TONEXT1L      (0x32)  */
95         0x00, /* REG_DTMF_TONEXT2H      (0x33)  */
96         0x00, /* REG_DTMF_TONEXT2L      (0x34)  */
97         0x00, /* REG_DTMF_TONOFF        (0x35)  */
98         0x00, /* REG_DTMF_WANONOFF      (0x36)  */
99         0x00, /* REG_I2S_RX_SCRAMBLE_H  (0x37)  */
100         0x00, /* REG_I2S_RX_SCRAMBLE_M  (0x38)  */
101         0x00, /* REG_I2S_RX_SCRAMBLE_L  (0x39)  */
102         0x16, /* REG_APLL_CTL           (0x3A)  */
103         0x00, /* REG_DTMF_CTL           (0x3B)  */
104         0x00, /* REG_DTMF_PGA_CTL2      (0x3C)  */
105         0x00, /* REG_DTMF_PGA_CTL1      (0x3D)  */
106         0x00, /* REG_MISC_SET_1         (0x3E)  */
107         0x00, /* REG_PCMBTMUX           (0x3F)  */
108         0x00, /* not used               (0x40)  */
109         0x00, /* not used               (0x41)  */
110         0x00, /* not used               (0x42)  */
111         0x00, /* REG_RX_PATH_SEL        (0x43)  */
112         0x00, /* REG_VDL_APGA_CTL       (0x44)  */
113         0x00, /* REG_VIBRA_CTL          (0x45)  */
114         0x00, /* REG_VIBRA_SET          (0x46)  */
115         0x00, /* REG_VIBRA_PWM_SET      (0x47)  */
116         0x00, /* REG_ANAMIC_GAIN        (0x48)  */
117         0x00, /* REG_MISC_SET_2         (0x49)  */
118 };
119
120 /*
121  * read twl4030 register cache
122  */
123 static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec,
124         unsigned int reg)
125 {
126         u8 *cache = codec->reg_cache;
127
128         return cache[reg];
129 }
130
131 /*
132  * write twl4030 register cache
133  */
134 static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
135                                                 u8 reg, u8 value)
136 {
137         u8 *cache = codec->reg_cache;
138
139         if (reg >= TWL4030_CACHEREGNUM)
140                 return;
141         cache[reg] = value;
142 }
143
144 /*
145  * write to the twl4030 register space
146  */
147 static int twl4030_write(struct snd_soc_codec *codec,
148                         unsigned int reg, unsigned int value)
149 {
150         twl4030_write_reg_cache(codec, reg, value);
151         return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
152 }
153
154 static void twl4030_clear_codecpdz(struct snd_soc_codec *codec)
155 {
156         u8 mode;
157
158         mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
159         twl4030_write(codec, TWL4030_REG_CODEC_MODE,
160                 mode & ~TWL4030_CODECPDZ);
161
162         /* REVISIT: this delay is present in TI sample drivers */
163         /* but there seems to be no TRM requirement for it     */
164         udelay(10);
165 }
166
167 static void twl4030_set_codecpdz(struct snd_soc_codec *codec)
168 {
169         u8 mode;
170
171         mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
172         twl4030_write(codec, TWL4030_REG_CODEC_MODE,
173                 mode | TWL4030_CODECPDZ);
174
175         /* REVISIT: this delay is present in TI sample drivers */
176         /* but there seems to be no TRM requirement for it     */
177         udelay(10);
178 }
179
180 static void twl4030_init_chip(struct snd_soc_codec *codec)
181 {
182         int i;
183
184         /* clear CODECPDZ prior to setting register defaults */
185         twl4030_clear_codecpdz(codec);
186
187         /* set all audio section registers to reasonable defaults */
188         for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
189                 twl4030_write(codec, i, twl4030_reg[i]);
190
191 }
192
193 /*
194  * Some of the gain controls in TWL (mostly those which are associated with
195  * the outputs) are implemented in an interesting way:
196  * 0x0 : Power down (mute)
197  * 0x1 : 6dB
198  * 0x2 : 0 dB
199  * 0x3 : -6 dB
200  * Inverting not going to help with these.
201  * Custom volsw and volsw_2r get/put functions to handle these gain bits.
202  */
203 #define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
204                                xinvert, tlv_array) \
205 {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
206         .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
207                  SNDRV_CTL_ELEM_ACCESS_READWRITE,\
208         .tlv.p = (tlv_array), \
209         .info = snd_soc_info_volsw, \
210         .get = snd_soc_get_volsw_twl4030, \
211         .put = snd_soc_put_volsw_twl4030, \
212         .private_value = (unsigned long)&(struct soc_mixer_control) \
213                 {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
214                  .max = xmax, .invert = xinvert} }
215 #define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
216                                  xinvert, tlv_array) \
217 {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
218         .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
219                  SNDRV_CTL_ELEM_ACCESS_READWRITE,\
220         .tlv.p = (tlv_array), \
221         .info = snd_soc_info_volsw_2r, \
222         .get = snd_soc_get_volsw_r2_twl4030,\
223         .put = snd_soc_put_volsw_r2_twl4030, \
224         .private_value = (unsigned long)&(struct soc_mixer_control) \
225                 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
226                 .max = xmax, .invert = xinvert} }
227 #define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
228         SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
229                                xinvert, tlv_array)
230
231 static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
232         struct snd_ctl_elem_value *ucontrol)
233 {
234         struct soc_mixer_control *mc =
235                 (struct soc_mixer_control *)kcontrol->private_value;
236         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
237         unsigned int reg = mc->reg;
238         unsigned int shift = mc->shift;
239         unsigned int rshift = mc->rshift;
240         int max = mc->max;
241         int mask = (1 << fls(max)) - 1;
242
243         ucontrol->value.integer.value[0] =
244                 (snd_soc_read(codec, reg) >> shift) & mask;
245         if (ucontrol->value.integer.value[0])
246                 ucontrol->value.integer.value[0] =
247                         max + 1 - ucontrol->value.integer.value[0];
248
249         if (shift != rshift) {
250                 ucontrol->value.integer.value[1] =
251                         (snd_soc_read(codec, reg) >> rshift) & mask;
252                 if (ucontrol->value.integer.value[1])
253                         ucontrol->value.integer.value[1] =
254                                 max + 1 - ucontrol->value.integer.value[1];
255         }
256
257         return 0;
258 }
259
260 static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
261         struct snd_ctl_elem_value *ucontrol)
262 {
263         struct soc_mixer_control *mc =
264                 (struct soc_mixer_control *)kcontrol->private_value;
265         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
266         unsigned int reg = mc->reg;
267         unsigned int shift = mc->shift;
268         unsigned int rshift = mc->rshift;
269         int max = mc->max;
270         int mask = (1 << fls(max)) - 1;
271         unsigned short val, val2, val_mask;
272
273         val = (ucontrol->value.integer.value[0] & mask);
274
275         val_mask = mask << shift;
276         if (val)
277                 val = max + 1 - val;
278         val = val << shift;
279         if (shift != rshift) {
280                 val2 = (ucontrol->value.integer.value[1] & mask);
281                 val_mask |= mask << rshift;
282                 if (val2)
283                         val2 = max + 1 - val2;
284                 val |= val2 << rshift;
285         }
286         return snd_soc_update_bits(codec, reg, val_mask, val);
287 }
288
289 static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
290         struct snd_ctl_elem_value *ucontrol)
291 {
292         struct soc_mixer_control *mc =
293                 (struct soc_mixer_control *)kcontrol->private_value;
294         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
295         unsigned int reg = mc->reg;
296         unsigned int reg2 = mc->rreg;
297         unsigned int shift = mc->shift;
298         int max = mc->max;
299         int mask = (1<<fls(max))-1;
300
301         ucontrol->value.integer.value[0] =
302                 (snd_soc_read(codec, reg) >> shift) & mask;
303         ucontrol->value.integer.value[1] =
304                 (snd_soc_read(codec, reg2) >> shift) & mask;
305
306         if (ucontrol->value.integer.value[0])
307                 ucontrol->value.integer.value[0] =
308                         max + 1 - ucontrol->value.integer.value[0];
309         if (ucontrol->value.integer.value[1])
310                 ucontrol->value.integer.value[1] =
311                         max + 1 - ucontrol->value.integer.value[1];
312
313         return 0;
314 }
315
316 static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
317         struct snd_ctl_elem_value *ucontrol)
318 {
319         struct soc_mixer_control *mc =
320                 (struct soc_mixer_control *)kcontrol->private_value;
321         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
322         unsigned int reg = mc->reg;
323         unsigned int reg2 = mc->rreg;
324         unsigned int shift = mc->shift;
325         int max = mc->max;
326         int mask = (1 << fls(max)) - 1;
327         int err;
328         unsigned short val, val2, val_mask;
329
330         val_mask = mask << shift;
331         val = (ucontrol->value.integer.value[0] & mask);
332         val2 = (ucontrol->value.integer.value[1] & mask);
333
334         if (val)
335                 val = max + 1 - val;
336         if (val2)
337                 val2 = max + 1 - val2;
338
339         val = val << shift;
340         val2 = val2 << shift;
341
342         err = snd_soc_update_bits(codec, reg, val_mask, val);
343         if (err < 0)
344                 return err;
345
346         err = snd_soc_update_bits(codec, reg2, val_mask, val2);
347         return err;
348 }
349
350 /*
351  * FGAIN volume control:
352  * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
353  */
354 static DECLARE_TLV_DB_SCALE(master_tlv, -6300, 100, 1);
355
356 /*
357  * CGAIN volume control:
358  * 0 dB to 12 dB in 6 dB steps
359  * value 2 and 3 means 12 dB
360  */
361 static DECLARE_TLV_DB_SCALE(master_coarse_tlv, 0, 600, 0);
362
363 /*
364  * Capture gain after the ADCs
365  * from 0 dB to 31 dB in 1 dB steps
366  */
367 static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
368
369 static const struct snd_kcontrol_new twl4030_snd_controls[] = {
370         SOC_DOUBLE_R_TLV("Master Playback Volume",
371                  TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
372                 0, 0x3f, 0, master_tlv),
373         SOC_DOUBLE_R_TLV("Master PCM Playback Volume",
374                  TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
375                 6, 0x2, 0, master_coarse_tlv),
376
377         /* Common capture gain controls */
378         SOC_DOUBLE_R_TLV("Capture Volume",
379                 TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA,
380                 0, 0x1f, 0, digital_capture_tlv),
381 };
382
383 /* add non dapm controls */
384 static int twl4030_add_controls(struct snd_soc_codec *codec)
385 {
386         int err, i;
387
388         for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) {
389                 err = snd_ctl_add(codec->card,
390                                   snd_soc_cnew(&twl4030_snd_controls[i],
391                                                 codec, NULL));
392                 if (err < 0)
393                         return err;
394         }
395
396         return 0;
397 }
398
399 static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
400         SND_SOC_DAPM_INPUT("INL"),
401         SND_SOC_DAPM_INPUT("INR"),
402
403         SND_SOC_DAPM_OUTPUT("OUTL"),
404         SND_SOC_DAPM_OUTPUT("OUTR"),
405
406         SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0),
407         SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0),
408
409         SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0),
410         SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0),
411 };
412
413 static const struct snd_soc_dapm_route intercon[] = {
414         /* outputs */
415         {"OUTL", NULL, "DACL"},
416         {"OUTR", NULL, "DACR"},
417
418         /* inputs */
419         {"ADCL", NULL, "INL"},
420         {"ADCR", NULL, "INR"},
421 };
422
423 static int twl4030_add_widgets(struct snd_soc_codec *codec)
424 {
425         snd_soc_dapm_new_controls(codec, twl4030_dapm_widgets,
426                                  ARRAY_SIZE(twl4030_dapm_widgets));
427
428         snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
429
430         snd_soc_dapm_new_widgets(codec);
431         return 0;
432 }
433
434 static void twl4030_power_up(struct snd_soc_codec *codec)
435 {
436         u8 anamicl, regmisc1, byte, popn, hsgain;
437         int i = 0;
438
439         /* set CODECPDZ to turn on codec */
440         twl4030_set_codecpdz(codec);
441
442         /* initiate offset cancellation */
443         anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
444         twl4030_write(codec, TWL4030_REG_ANAMICL,
445                 anamicl | TWL4030_CNCL_OFFSET_START);
446
447         /* wait for offset cancellation to complete */
448         do {
449                 /* this takes a little while, so don't slam i2c */
450                 udelay(2000);
451                 twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
452                                     TWL4030_REG_ANAMICL);
453         } while ((i++ < 100) &&
454                  ((byte & TWL4030_CNCL_OFFSET_START) ==
455                   TWL4030_CNCL_OFFSET_START));
456
457         /* anti-pop when changing analog gain */
458         regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
459         twl4030_write(codec, TWL4030_REG_MISC_SET_1,
460                 regmisc1 | TWL4030_SMOOTH_ANAVOL_EN);
461
462         /* toggle CODECPDZ as per TRM */
463         twl4030_clear_codecpdz(codec);
464         twl4030_set_codecpdz(codec);
465
466         /* program anti-pop with bias ramp delay */
467         popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
468         popn &= TWL4030_RAMP_DELAY;
469         popn |= TWL4030_RAMP_DELAY_645MS;
470         twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
471         popn |= TWL4030_VMID_EN;
472         twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
473
474         /* enable output stage and gain setting */
475         hsgain = TWL4030_HSR_GAIN_0DB | TWL4030_HSL_GAIN_0DB;
476         twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hsgain);
477
478         /* enable anti-pop ramp */
479         popn |= TWL4030_RAMP_EN;
480         twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
481 }
482
483 static void twl4030_power_down(struct snd_soc_codec *codec)
484 {
485         u8 popn, hsgain;
486
487         /* disable anti-pop ramp */
488         popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
489         popn &= ~TWL4030_RAMP_EN;
490         twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
491
492         /* disable output stage and gain setting */
493         hsgain = TWL4030_HSR_GAIN_PWR_DOWN | TWL4030_HSL_GAIN_PWR_DOWN;
494         twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hsgain);
495
496         /* disable bias out */
497         popn &= ~TWL4030_VMID_EN;
498         twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
499
500         /* power down */
501         twl4030_clear_codecpdz(codec);
502 }
503
504 static int twl4030_set_bias_level(struct snd_soc_codec *codec,
505                                   enum snd_soc_bias_level level)
506 {
507         switch (level) {
508         case SND_SOC_BIAS_ON:
509                 twl4030_power_up(codec);
510                 break;
511         case SND_SOC_BIAS_PREPARE:
512                 /* TODO: develop a twl4030_prepare function */
513                 break;
514         case SND_SOC_BIAS_STANDBY:
515                 /* TODO: develop a twl4030_standby function */
516                 twl4030_power_down(codec);
517                 break;
518         case SND_SOC_BIAS_OFF:
519                 twl4030_power_down(codec);
520                 break;
521         }
522         codec->bias_level = level;
523
524         return 0;
525 }
526
527 static int twl4030_hw_params(struct snd_pcm_substream *substream,
528                            struct snd_pcm_hw_params *params,
529                            struct snd_soc_dai *dai)
530 {
531         struct snd_soc_pcm_runtime *rtd = substream->private_data;
532         struct snd_soc_device *socdev = rtd->socdev;
533         struct snd_soc_codec *codec = socdev->codec;
534         u8 mode, old_mode, format, old_format;
535
536
537         /* bit rate */
538         old_mode = twl4030_read_reg_cache(codec,
539                         TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
540         mode = old_mode & ~TWL4030_APLL_RATE;
541
542         switch (params_rate(params)) {
543         case 8000:
544                 mode |= TWL4030_APLL_RATE_8000;
545                 break;
546         case 11025:
547                 mode |= TWL4030_APLL_RATE_11025;
548                 break;
549         case 12000:
550                 mode |= TWL4030_APLL_RATE_12000;
551                 break;
552         case 16000:
553                 mode |= TWL4030_APLL_RATE_16000;
554                 break;
555         case 22050:
556                 mode |= TWL4030_APLL_RATE_22050;
557                 break;
558         case 24000:
559                 mode |= TWL4030_APLL_RATE_24000;
560                 break;
561         case 32000:
562                 mode |= TWL4030_APLL_RATE_32000;
563                 break;
564         case 44100:
565                 mode |= TWL4030_APLL_RATE_44100;
566                 break;
567         case 48000:
568                 mode |= TWL4030_APLL_RATE_48000;
569                 break;
570         default:
571                 printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
572                         params_rate(params));
573                 return -EINVAL;
574         }
575
576         if (mode != old_mode) {
577                 /* change rate and set CODECPDZ */
578                 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
579                 twl4030_set_codecpdz(codec);
580         }
581
582         /* sample size */
583         old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
584         format = old_format;
585         format &= ~TWL4030_DATA_WIDTH;
586         switch (params_format(params)) {
587         case SNDRV_PCM_FORMAT_S16_LE:
588                 format |= TWL4030_DATA_WIDTH_16S_16W;
589                 break;
590         case SNDRV_PCM_FORMAT_S24_LE:
591                 format |= TWL4030_DATA_WIDTH_32S_24W;
592                 break;
593         default:
594                 printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
595                         params_format(params));
596                 return -EINVAL;
597         }
598
599         if (format != old_format) {
600
601                 /* clear CODECPDZ before changing format (codec requirement) */
602                 twl4030_clear_codecpdz(codec);
603
604                 /* change format */
605                 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
606
607                 /* set CODECPDZ afterwards */
608                 twl4030_set_codecpdz(codec);
609         }
610         return 0;
611 }
612
613 static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
614                 int clk_id, unsigned int freq, int dir)
615 {
616         struct snd_soc_codec *codec = codec_dai->codec;
617         u8 infreq;
618
619         switch (freq) {
620         case 19200000:
621                 infreq = TWL4030_APLL_INFREQ_19200KHZ;
622                 break;
623         case 26000000:
624                 infreq = TWL4030_APLL_INFREQ_26000KHZ;
625                 break;
626         case 38400000:
627                 infreq = TWL4030_APLL_INFREQ_38400KHZ;
628                 break;
629         default:
630                 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n",
631                         freq);
632                 return -EINVAL;
633         }
634
635         infreq |= TWL4030_APLL_EN;
636         twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
637
638         return 0;
639 }
640
641 static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
642                              unsigned int fmt)
643 {
644         struct snd_soc_codec *codec = codec_dai->codec;
645         u8 old_format, format;
646
647         /* get format */
648         old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
649         format = old_format;
650
651         /* set master/slave audio interface */
652         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
653         case SND_SOC_DAIFMT_CBM_CFM:
654                 format &= ~(TWL4030_AIF_SLAVE_EN);
655                 format &= ~(TWL4030_CLK256FS_EN);
656                 break;
657         case SND_SOC_DAIFMT_CBS_CFS:
658                 format |= TWL4030_AIF_SLAVE_EN;
659                 format |= TWL4030_CLK256FS_EN;
660                 break;
661         default:
662                 return -EINVAL;
663         }
664
665         /* interface format */
666         format &= ~TWL4030_AIF_FORMAT;
667         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
668         case SND_SOC_DAIFMT_I2S:
669                 format |= TWL4030_AIF_FORMAT_CODEC;
670                 break;
671         default:
672                 return -EINVAL;
673         }
674
675         if (format != old_format) {
676
677                 /* clear CODECPDZ before changing format (codec requirement) */
678                 twl4030_clear_codecpdz(codec);
679
680                 /* change format */
681                 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
682
683                 /* set CODECPDZ afterwards */
684                 twl4030_set_codecpdz(codec);
685         }
686
687         return 0;
688 }
689
690 #define TWL4030_RATES    (SNDRV_PCM_RATE_8000_48000)
691 #define TWL4030_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
692
693 struct snd_soc_dai twl4030_dai = {
694         .name = "twl4030",
695         .playback = {
696                 .stream_name = "Playback",
697                 .channels_min = 2,
698                 .channels_max = 2,
699                 .rates = TWL4030_RATES,
700                 .formats = TWL4030_FORMATS,},
701         .capture = {
702                 .stream_name = "Capture",
703                 .channels_min = 2,
704                 .channels_max = 2,
705                 .rates = TWL4030_RATES,
706                 .formats = TWL4030_FORMATS,},
707         .ops = {
708                 .hw_params = twl4030_hw_params,
709                 .set_sysclk = twl4030_set_dai_sysclk,
710                 .set_fmt = twl4030_set_dai_fmt,
711         }
712 };
713 EXPORT_SYMBOL_GPL(twl4030_dai);
714
715 static int twl4030_suspend(struct platform_device *pdev, pm_message_t state)
716 {
717         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
718         struct snd_soc_codec *codec = socdev->codec;
719
720         twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
721
722         return 0;
723 }
724
725 static int twl4030_resume(struct platform_device *pdev)
726 {
727         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
728         struct snd_soc_codec *codec = socdev->codec;
729
730         twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
731         twl4030_set_bias_level(codec, codec->suspend_bias_level);
732         return 0;
733 }
734
735 /*
736  * initialize the driver
737  * register the mixer and dsp interfaces with the kernel
738  */
739
740 static int twl4030_init(struct snd_soc_device *socdev)
741 {
742         struct snd_soc_codec *codec = socdev->codec;
743         int ret = 0;
744
745         printk(KERN_INFO "TWL4030 Audio Codec init \n");
746
747         codec->name = "twl4030";
748         codec->owner = THIS_MODULE;
749         codec->read = twl4030_read_reg_cache;
750         codec->write = twl4030_write;
751         codec->set_bias_level = twl4030_set_bias_level;
752         codec->dai = &twl4030_dai;
753         codec->num_dai = 1;
754         codec->reg_cache_size = sizeof(twl4030_reg);
755         codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
756                                         GFP_KERNEL);
757         if (codec->reg_cache == NULL)
758                 return -ENOMEM;
759
760         /* register pcms */
761         ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
762         if (ret < 0) {
763                 printk(KERN_ERR "twl4030: failed to create pcms\n");
764                 goto pcm_err;
765         }
766
767         twl4030_init_chip(codec);
768
769         /* power on device */
770         twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
771
772         twl4030_add_controls(codec);
773         twl4030_add_widgets(codec);
774
775         ret = snd_soc_init_card(socdev);
776         if (ret < 0) {
777                 printk(KERN_ERR "twl4030: failed to register card\n");
778                 goto card_err;
779         }
780
781         return ret;
782
783 card_err:
784         snd_soc_free_pcms(socdev);
785         snd_soc_dapm_free(socdev);
786 pcm_err:
787         kfree(codec->reg_cache);
788         return ret;
789 }
790
791 static struct snd_soc_device *twl4030_socdev;
792
793 static int twl4030_probe(struct platform_device *pdev)
794 {
795         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
796         struct snd_soc_codec *codec;
797
798         codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
799         if (codec == NULL)
800                 return -ENOMEM;
801
802         socdev->codec = codec;
803         mutex_init(&codec->mutex);
804         INIT_LIST_HEAD(&codec->dapm_widgets);
805         INIT_LIST_HEAD(&codec->dapm_paths);
806
807         twl4030_socdev = socdev;
808         twl4030_init(socdev);
809
810         return 0;
811 }
812
813 static int twl4030_remove(struct platform_device *pdev)
814 {
815         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
816         struct snd_soc_codec *codec = socdev->codec;
817
818         printk(KERN_INFO "TWL4030 Audio Codec remove\n");
819         kfree(codec);
820
821         return 0;
822 }
823
824 struct snd_soc_codec_device soc_codec_dev_twl4030 = {
825         .probe = twl4030_probe,
826         .remove = twl4030_remove,
827         .suspend = twl4030_suspend,
828         .resume = twl4030_resume,
829 };
830 EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
831
832 MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
833 MODULE_AUTHOR("Steve Sakoman");
834 MODULE_LICENSE("GPL");