newton:cs42l52 only support 44.1k sample rate
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / cs42l52.c
1 /*
2  * cs42l52.c -- CS42L52 ALSA SoC audio driver
3  *
4  * Copyright 2007 CirrusLogic, Inc. 
5  *
6  * Author: Bo Liu <Bo.Liu@cirrus.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  * Revision history
12  * Nov 2007  Initial version.
13  * Oct 2008  Updated to 2.6.26
14  */
15
16
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/version.h>
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/delay.h>
23 #include <linux/pm.h>
24 #include <linux/i2c.h>
25 #include <linux/platform_device.h>
26 #include <linux/spi/spi.h>
27 #include <sound/core.h>
28 #include <sound/pcm.h>
29 #include <sound/pcm_params.h>
30 #include <sound/soc.h>
31 #include <sound/soc-dapm.h>
32 #include <sound/initval.h>
33 #include <sound/tlv.h>
34
35 #include <linux/types.h>
36 #include <linux/device.h>
37
38 #include <asm/io.h>
39 #include "cs42l52.h"
40 #include <mach/board.h>
41
42 //#include "cs42L52_control.h"
43
44
45 #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
46         #define AUTO_DETECT_DISABLE
47 #else
48         //#define AUTO_DETECT_DISABLE
49         #undef AUTO_DETECT_DISABLE
50 #endif
51
52 //#define DEBUG
53 #ifdef DEBUG
54 #define SOCDBG(fmt, arg...)     printk(KERN_ERR "%s: %s() " fmt, SOC_CS42L52_NAME, __FUNCTION__, ##arg)
55 #else
56 #define SOCDBG(fmt, arg...)     do { } while (0)
57 #endif
58 #define SOCINF(fmt, args...)    printk(KERN_INFO "%s: " fmt, SOC_CS42L52_NAME,  ##args)
59 #define SOCERR(fmt, args...)    printk(KERN_ERR "%s: " fmt, SOC_CS42L52_NAME,  ##args)
60
61
62
63 static void soc_cs42l52_work(struct work_struct *work);
64
65 static struct snd_soc_codec *cs42l52_codec;
66
67 //added for suspend
68 #ifdef CONFIG_HAS_EARLYSUSPEND
69 #include <linux/earlysuspend.h>
70 static struct early_suspend cs42l52_early_suspend;
71 #endif
72
73 /**
74  * snd_soc_get_volsw - single mixer get callback
75  * @kcontrol: mixer control
76  * @uinfo: control element information
77  *
78  * Callback to get the value of a single mixer control.
79  *
80  * Returns 0 for success.
81  */
82 int snd_soc_cs42l5x_get_volsw(struct snd_kcontrol *kcontrol,
83     struct snd_ctl_elem_value *ucontrol)
84 {
85     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
86     int reg = kcontrol->private_value & 0xff;
87     int shift = (kcontrol->private_value >> 8) & 0x0f;
88     int rshift = (kcontrol->private_value >> 12) & 0x0f;
89     int max = (kcontrol->private_value >> 16) & 0xff;
90     int mask = (1 << fls(max)) - 1;
91     int min = (kcontrol->private_value >> 24) & 0xff;
92
93     ucontrol->value.integer.value[0] =
94         ((snd_soc_read(codec, reg) >> shift) - min) & mask;
95     if (shift != rshift)
96         ucontrol->value.integer.value[1] =
97             ((snd_soc_read(codec, reg) >> rshift) - min) & mask;
98
99     return 0;
100 }
101
102 /**
103  * snd_soc_put_volsw - single mixer put callback
104  * @kcontrol: mixer control
105  * @uinfo: control element information
106  *
107  * Callback to set the value of a single mixer control.
108  *
109  * Returns 0 for success.
110  */
111 int snd_soc_cs42l5x_put_volsw(struct snd_kcontrol *kcontrol,
112     struct snd_ctl_elem_value *ucontrol)
113 {
114 SOCDBG("i am here\n");
115     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
116     int reg = kcontrol->private_value & 0xff;
117     int shift = (kcontrol->private_value >> 8) & 0x0f;
118     int rshift = (kcontrol->private_value >> 12) & 0x0f;
119     int max = (kcontrol->private_value >> 16) & 0xff;
120     int mask = (1 << fls(max)) - 1;
121     int min = (kcontrol->private_value >> 24) & 0xff;
122     unsigned short val, val2, val_mask;
123
124     val = ((ucontrol->value.integer.value[0] + min) & mask);
125
126     val_mask = mask << shift;
127     val = val << shift;
128     if (shift != rshift) {
129         val2 = ((ucontrol->value.integer.value[1] + min) & mask);
130         val_mask |= mask << rshift;
131         val |= val2 << rshift;
132     }
133     return snd_soc_update_bits(codec, reg, val_mask, val);
134 }
135
136 /**
137  * snd_soc_info_volsw_2r - double mixer info callback
138  * @kcontrol: mixer control
139  * @uinfo: control element information
140  *
141  * Callback to provide information about a double mixer control that
142  * spans 2 codec registers.
143  *
144  * Returns 0 for success.
145  */
146 int snd_soc_cs42l5x_info_volsw_2r(struct snd_kcontrol *kcontrol,
147     struct snd_ctl_elem_info *uinfo)
148 {
149     int max = (kcontrol->private_value >> 8) & 0xff;
150
151     if (max == 1)
152         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
153     else
154         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
155
156     uinfo->count = 2;
157     uinfo->value.integer.min = 0;
158     uinfo->value.integer.max = max;
159     return 0;
160 }
161
162 /**
163  * snd_soc_get_volsw_2r - double mixer get callback
164  * @kcontrol: mixer control
165  * @uinfo: control element information
166  *
167  * Callback to get the value of a double mixer control that spans 2 registers.
168  *
169  * Returns 0 for success.
170  */
171 int snd_soc_cs42l5x_get_volsw_2r(struct snd_kcontrol *kcontrol,
172     struct snd_ctl_elem_value *ucontrol)
173 {
174     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
175     int reg = kcontrol->private_value & 0xff;
176     int reg2 = (kcontrol->private_value >> 24) & 0xff;
177     int max = (kcontrol->private_value >> 8) & 0xff;
178     int min = (kcontrol->private_value >> 16) & 0xff;
179     int mask = (1<<fls(max))-1;
180     int val, val2;
181
182     val = snd_soc_read(codec, reg);
183     val2 = snd_soc_read(codec, reg2);
184     ucontrol->value.integer.value[0] = (val - min) & mask;
185     ucontrol->value.integer.value[1] = (val2 - min) & mask;
186 /*    
187     SOCDBG("reg[%02x:%02x] = %02x:%02x ucontrol[%02x:%02x], min = %02x, max = %02x, mask %02x\n",
188             reg, reg2, val,val2, 
189             ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], 
190             min, max, mask);
191 */
192     return 0;
193 }
194
195 /**
196  * snd_soc_put_volsw_2r - double mixer set callback
197  * @kcontrol: mixer control
198  * @uinfo: control element information
199  *
200  * Callback to set the value of a double mixer control that spans 2 registers.
201  *
202  * Returns 0 for success.
203  */
204 int snd_soc_cs42l5x_put_volsw_2r(struct snd_kcontrol *kcontrol,
205     struct snd_ctl_elem_value *ucontrol)
206 {
207     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
208     int reg = kcontrol->private_value & 0xff;
209     int reg2 = (kcontrol->private_value >> 24) & 0xff;
210     int max = (kcontrol->private_value >> 8) & 0xff;
211     int min = (kcontrol->private_value >> 16) & 0xff;
212     int mask = (1 << fls(max)) - 1;
213     int err;
214     unsigned short val, val2;
215
216     val = (ucontrol->value.integer.value[0] + min) & mask;
217     val2 = (ucontrol->value.integer.value[1] + min) & mask;
218
219     if ((err = snd_soc_update_bits(codec, reg, mask, val)) < 0)
220         return err;
221
222     err = snd_soc_update_bits(codec, reg2, mask, val2);
223 /*
224     SOCDBG("reg[%02x:%02x] = %02x:%02x, ucontrol[%02x:%02x], min = %02x, max = %02x, mask = %02x\n",
225             reg, reg2, val, val2, 
226             ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], 
227             min, max, mask);
228 */
229     return err;
230 }
231
232 #define SOC_SINGLE_CS42L52(xname, reg, shift, max, min) \
233 {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
234         .info = snd_soc_info_volsw, .get = snd_soc_cs42l5x_get_volsw,\
235         .put = snd_soc_cs42l5x_put_volsw, \
236         .private_value =  SOC_SINGLE_VALUE(reg, shift, max, min) }
237
238 #define SOC_DOUBLE_CS42L52(xname, reg, shift_left, shift_right, max, min) \
239 {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
240         .info = snd_soc_info_volsw, .get = snd_soc_cs42l5x_get_volsw, \
241         .put = snd_soc_cs42l5x_put_volsw, \
242         .private_value = (reg) | ((shift_left) << 8) | \
243                 ((shift_right) << 12) | ((max) << 16) | ((min) << 24) }
244
245 /* No shifts required */
246 #define SOC_DOUBLE_R_CS42L52(xname, reg_left, reg_right, max, min) \
247 {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
248         .info = snd_soc_cs42l5x_info_volsw_2r, \
249         .get = snd_soc_cs42l5x_get_volsw_2r, .put = snd_soc_cs42l5x_put_volsw_2r, \
250         .private_value = (reg_left) | ((max) << 8) | ((min) << 16) | \
251                 ((reg_right) << 24) }
252
253
254 /*
255  * CS42L52 register default value
256  */
257 static const u8 soc_cs42l52_reg_default[] = {
258         0x00, 0xE0, 0x01, 0x07, 0x05, /*4*/
259         0xa0, 0x00, 0x00, 0x81, /*8*/
260         0x81, 0xa5, 0x00, 0x00, /*12*/
261         0x60, 0x02, 0x00, 0x00, /*16*/
262         0x00, 0x00, 0x00, 0x00, /*20*/
263         0x00, 0x00, 0x00, 0x80, /*24*/
264         0x80, 0x00, 0x00, 0x00, /*28*/
265         0x00, 0x00, 0x88, 0x00, /*32*/
266         0x00, 0x00, 0x00, 0x00, /*36*/
267         0x00, 0x00, 0x00, 0x7f, /*40*/
268         0xc0, 0x00, 0x3f, 0x00, /*44*/
269         0x00, 0x00, 0x00, 0x00, /*48*/
270         0x00, 0x3b, 0x00, 0x5f, /*52*/
271 };
272
273 static inline int soc_cs42l52_read_reg_cache(struct snd_soc_codec *codec,
274                 u_int reg)
275 {
276         u8 *cache = codec->reg_cache;
277
278         return reg > SOC_CS42L52_REG_NUM ? -EINVAL : cache[reg];
279 }
280
281 static inline void soc_cs42l52_write_reg_cache(struct snd_soc_codec *codec,
282                 u_int reg, u_int val)
283 {
284         u8 *cache = codec->reg_cache;
285         
286         if(reg > SOC_CS42L52_REG_NUM)
287                 return;
288         cache[reg] = val & 0xff;
289 }
290
291 static int soc_cs42l52_write(struct snd_soc_codec *codec,
292                 unsigned reg, u_int val)
293 {
294 #if 1
295         u8 datas[2];
296         int i,num, ret = 0;
297         struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)codec->private_data;
298
299         datas[0] = reg & 0xff;
300         datas[1] = val & 0xff;
301         codec->num_dai = 1;
302         if(info->flags & SOC_CS42L52_ALL_IN_ONE)
303         {
304                 for(i = 0; i < codec->num_dai; i++)
305                 {
306                         if(codec->hw_write(codec->control_data, datas, 2) != 2)
307                         {
308                                 ret = -EIO;
309                                 break;
310                         }
311                 }
312         }
313         else
314         {
315                 if(info->flags & SOC_CS42L52_CHIP_SWICTH)
316                 {
317                         num = info->flags & SOC_CS42L52_CHIP_MASK;
318                 }
319                 
320                 if(codec->hw_write(codec->control_data, datas, 2) != 2)
321                         ret = -EIO;
322         }
323
324         if(ret >= 0)
325                 soc_cs42l52_write_reg_cache(codec, reg, val);
326
327         return ret;
328 #else
329         return codec->write(codec, reg, val);
330 #endif
331 }
332
333 static unsigned int soc_cs42l52_read(struct snd_soc_codec *codec,
334                 u_int reg)
335 {
336 #if 1
337         u8 data;
338         if(i2c_master_reg8_recv(codec->control_data,reg,&data,1,50*1000)>0) {
339                 return data;
340         }
341         else {
342                 printk("cs42l52  read error\n");
343                 return -1;
344         }
345 #else
346         return codec->read(codec, reg);
347 #endif  
348 }
349
350 struct soc_cs42l52_clk_para {
351         u32 mclk;
352         u32 rate;
353         u8 speed;
354         u8 group;
355         u8 videoclk;
356         u8 ratio;
357         u8 mclkdiv2;
358 };
359
360 static const struct soc_cs42l52_clk_para clk_map_table[] = {
361         /*8k*/
362         {12288000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
363         {18432000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
364         {12000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
365         {24000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
366         {27000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0}, /*4*/
367
368         /*11.025k*/
369         {11289600, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
370         {16934400, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
371         
372         /*16k*/
373         {12288000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
374         {18432000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
375         {12000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},/*9*/
376         {24000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
377         {27000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1},
378
379         /*22.05k*/
380         {11289600, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
381         {16934400, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
382         
383         /* 32k */
384         {12288000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*14*/
385         {18432000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
386         {12000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
387         {24000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
388         {27000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0},
389
390         /* 44.1k */
391         {11289600, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*19*/
392         {16934400, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
393         {12000000, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_136, 0},
394
395         /* 48k */
396         {12288000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
397         {18432000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
398         {12000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
399         {24000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},/*25*/
400         {27000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1},
401
402         /* 88.2k */
403         {11289600, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
404         {16934400, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
405
406         /* 96k */
407         {12288000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
408         {18432000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*30*/
409         {12000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
410         {24000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
411 };
412
413 static int soc_cs42l52_get_clk(int mclk, int rate)
414 {
415         int i , ret = 0;
416         u_int mclk1, mclk2 = 0;
417
418         for(i = 0; i < ARRAY_SIZE(clk_map_table); i++){
419                 if(clk_map_table[i].rate == rate){
420                         mclk1 = clk_map_table[i].mclk;
421                         if(abs(mclk - mclk1) < abs(mclk - mclk2)){
422                                 mclk2 = mclk1;
423                                 ret = i;
424                         }
425                 }
426         }
427
428         return ret < ARRAY_SIZE(clk_map_table) ? ret : -EINVAL;
429 }
430
431 static const char *cs42l52_mic_bias[] = {"0.5VA", "0.6VA", "0.7VA", "0.8VA", "0.83VA", "0.91VA"};
432 static const char *cs42l52_hpf_freeze[] = {"Continuous DC Subtraction", "Frozen DC Subtraction"};
433 static const char *cs42l52_hpf_corner_freq[] = {"Normal", "119Hz", "236Hz", "464Hz"};
434 static const char *cs42l52_adc_sum[] = {"Normal", "Sum half", "Sub half", "Inverted"};
435 static const char *cs42l52_sig_polarity[] = {"Normal", "Inverted"};
436 static const char *cs42l52_spk_mono_channel[] = {"ChannelA", "ChannelB"};
437 static const char *cs42l52_beep_type[] = {"Off", "Single", "Multiple", "Continuous"};
438 static const char *cs42l52_treble_freq[] = {"5kHz", "7kHz", "10kHz", "15kHz"};
439 static const char *cs42l52_bass_freq[] = {"50Hz", "100Hz", "200Hz", "250Hz"};
440 static const char *cs42l52_target_sel[] = {"Apply Specific", "Apply All"};
441 static const char *cs42l52_noise_gate_delay[] = {"50ms", "100ms", "150ms", "200ms"};
442 static const char *cs42l52_adc_mux[] = {"AIN1", "AIN2", "AIN3", "AIN4", "PGA"};
443 static const char *cs42l52_mic_mux[] = {"MIC1", "MIC2"};
444 static const char *cs42l52_stereo_mux[] = {"Mono", "Stereo"};
445 static const char *cs42l52_off[] = {"On", "Off"};
446 static const char *cs42l52_hpmux[] = {"Off", "On"};
447
448 static const struct soc_enum soc_cs42l52_enum[] = {
449 SOC_ENUM_DOUBLE(CODEC_CS42L52_ANALOG_HPF_CTL, 4, 6, 2, cs42l52_hpf_freeze), /*0*/
450 SOC_ENUM_SINGLE(CODEC_CS42L52_ADC_HPF_FREQ, 0, 4, cs42l52_hpf_corner_freq),
451 SOC_ENUM_SINGLE(CODEC_CS42L52_ADC_MISC_CTL, 4, 4, cs42l52_adc_sum),
452 SOC_ENUM_DOUBLE(CODEC_CS42L52_ADC_MISC_CTL, 2, 3, 2, cs42l52_sig_polarity),
453 SOC_ENUM_DOUBLE(CODEC_CS42L52_PB_CTL1, 2, 3, 2, cs42l52_sig_polarity),
454 SOC_ENUM_SINGLE(CODEC_CS42L52_PB_CTL2, 2, 2, cs42l52_spk_mono_channel), /*5*/
455 SOC_ENUM_SINGLE(CODEC_CS42L52_BEEP_TONE_CTL, 6, 4, cs42l52_beep_type),
456 SOC_ENUM_SINGLE(CODEC_CS42L52_BEEP_TONE_CTL, 3, 4, cs42l52_treble_freq),
457 SOC_ENUM_SINGLE(CODEC_CS42L52_BEEP_TONE_CTL, 1, 4, cs42l52_bass_freq),
458 SOC_ENUM_SINGLE(CODEC_CS42L52_LIMITER_CTL2, 6, 2, cs42l52_target_sel),
459 SOC_ENUM_SINGLE(CODEC_CS42L52_NOISE_GATE_CTL, 7, 2, cs42l52_target_sel), /*10*/
460 SOC_ENUM_SINGLE(CODEC_CS42L52_NOISE_GATE_CTL, 0, 4, cs42l52_noise_gate_delay),
461 SOC_ENUM_SINGLE(CODEC_CS42L52_ADC_PGA_A, 5, 5, cs42l52_adc_mux),
462 SOC_ENUM_SINGLE(CODEC_CS42L52_ADC_PGA_B, 5, 5, cs42l52_adc_mux),
463 SOC_ENUM_SINGLE(CODEC_CS42L52_MICA_CTL, 6, 2, cs42l52_mic_mux),
464 SOC_ENUM_SINGLE(CODEC_CS42L52_MICB_CTL, 6, 2, cs42l52_mic_mux), /*15*/
465 SOC_ENUM_SINGLE(CODEC_CS42L52_MICA_CTL, 5, 2, cs42l52_stereo_mux),
466 SOC_ENUM_SINGLE(CODEC_CS42L52_MICB_CTL, 5, 2, cs42l52_stereo_mux),
467 SOC_ENUM_SINGLE(CODEC_CS42L52_IFACE_CTL2, 0, 6, cs42l52_mic_bias), /*18*/
468 SOC_ENUM_SINGLE(CODEC_CS42L52_PWCTL2, 0, 2, cs42l52_off),
469 SOC_ENUM_SINGLE(CODEC_CS42L52_MISC_CTL, 6, 2, cs42l52_hpmux),
470 SOC_ENUM_SINGLE(CODEC_CS42L52_MISC_CTL, 7, 2, cs42l52_hpmux),
471 };
472
473 static const struct snd_kcontrol_new soc_cs42l52_controls[] = {
474
475 SOC_ENUM("Mic VA Capture Switch", soc_cs42l52_enum[18]), /*0*/
476 SOC_DOUBLE("HPF Capture Switch", CODEC_CS42L52_ANALOG_HPF_CTL, 5, 7, 1, 0),
477 SOC_ENUM("HPF Freeze Capture Switch", soc_cs42l52_enum[0]),
478
479 SOC_DOUBLE("Analog SR Capture Switch", CODEC_CS42L52_ANALOG_HPF_CTL, 1, 3, 1, 1),
480 SOC_DOUBLE("Analog ZC Capture Switch", CODEC_CS42L52_ANALOG_HPF_CTL, 0, 2, 1, 1),
481 SOC_ENUM("HPF corner freq Capture Switch", soc_cs42l52_enum[1]), /*5*/
482
483 SOC_SINGLE("Ganged Ctl Capture Switch", CODEC_CS42L52_ADC_MISC_CTL, 7, 1, 1), /* should be enabled init */
484 SOC_ENUM("Mix/Swap Capture Switch",soc_cs42l52_enum[2]),
485 SOC_ENUM("Signal Polarity Capture Switch", soc_cs42l52_enum[3]),
486
487 SOC_SINGLE("HP Analog Gain Playback Volume", CODEC_CS42L52_PB_CTL1, 5, 7, 0),
488 SOC_SINGLE("Playback B=A Volume Playback Switch", CODEC_CS42L52_PB_CTL1, 4, 1, 0), /*10*/ /*should be enabled init*/ 
489 SOC_ENUM("PCM Signal Polarity Playback Switch",soc_cs42l52_enum[4]),
490
491 SOC_SINGLE("Digital De-Emphasis Playback Switch", CODEC_CS42L52_MISC_CTL, 2, 1, 0),
492 SOC_SINGLE("Digital SR Playback Switch", CODEC_CS42L52_MISC_CTL, 1, 1, 0),
493 SOC_SINGLE("Digital ZC Playback Switch", CODEC_CS42L52_MISC_CTL, 0, 1, 0),
494
495 SOC_SINGLE("Spk Volume Equal Playback Switch", CODEC_CS42L52_PB_CTL2, 3, 1, 0) , /*15*/ /*should be enabled init*/
496 SOC_SINGLE("Spk Mute 50/50 Playback Switch", CODEC_CS42L52_PB_CTL2, 0, 1, 0),
497 SOC_ENUM("Spk Swap Channel Playback Switch", soc_cs42l52_enum[5]),
498 SOC_SINGLE("Spk Full-Bridge Playback Switch", CODEC_CS42L52_PB_CTL2, 1, 1, 0),
499 SOC_DOUBLE_R("Mic Gain Capture Volume", CODEC_CS42L52_MICA_CTL, CODEC_CS42L52_MICB_CTL, 0, 31, 0),
500
501 SOC_DOUBLE_R("ALC SR Capture Switch", CODEC_CS42L52_PGAA_CTL, CODEC_CS42L52_PGAB_CTL, 7, 1, 1), /*20*/
502 SOC_DOUBLE_R("ALC ZC Capture Switch", CODEC_CS42L52_PGAA_CTL, CODEC_CS42L52_PGAB_CTL, 6, 1, 1),
503 SOC_DOUBLE_R_CS42L52("PGA Capture Volume", CODEC_CS42L52_PGAA_CTL, CODEC_CS42L52_PGAB_CTL, 0x30, 0x18),
504
505 SOC_DOUBLE_R_CS42L52("Passthru Playback Volume", CODEC_CS42L52_PASSTHRUA_VOL, CODEC_CS42L52_PASSTHRUB_VOL, 0x90, 0x88),
506 SOC_DOUBLE("Passthru Playback Switch", CODEC_CS42L52_MISC_CTL, 4, 5, 1, 1),
507 SOC_DOUBLE_R_CS42L52("ADC Capture Volume", CODEC_CS42L52_ADCA_VOL, CODEC_CS42L52_ADCB_VOL, 0x80, 0xA0),
508 SOC_DOUBLE("ADC Capture Switch", CODEC_CS42L52_ADC_MISC_CTL, 0, 1, 1, 1),
509 SOC_DOUBLE_R_CS42L52("ADC Mixer Capture Volume", CODEC_CS42L52_ADCA_MIXER_VOL, CODEC_CS42L52_ADCB_MIXER_VOL, 0x7f, 0x19),
510 SOC_DOUBLE_R("ADC Mixer Capture Switch", CODEC_CS42L52_ADCA_MIXER_VOL, CODEC_CS42L52_ADCB_MIXER_VOL, 7, 1, 1),
511 SOC_DOUBLE_R_CS42L52("PCM Mixer Playback Volume", CODEC_CS42L52_PCMA_MIXER_VOL, CODEC_CS42L52_PCMB_MIXER_VOL, 0x7f, 0x19),
512 SOC_DOUBLE_R("PCM Mixer Playback Switch", CODEC_CS42L52_PCMA_MIXER_VOL, CODEC_CS42L52_PCMB_MIXER_VOL, 7, 1, 1),
513
514 SOC_SINGLE("Beep Freq", CODEC_CS42L52_BEEP_FREQ, 4, 15, 0),
515 SOC_SINGLE("Beep OnTime", CODEC_CS42L52_BEEP_FREQ, 0, 15, 0), /*30*/
516 SOC_SINGLE_CS42L52("Beep Volume", CODEC_CS42L52_BEEP_VOL, 0, 0x1f, 0x07),
517 SOC_SINGLE("Beep OffTime", CODEC_CS42L52_BEEP_VOL, 5, 7, 0),
518 SOC_ENUM("Beep Type", soc_cs42l52_enum[6]),
519 SOC_SINGLE("Beep Mix Switch", CODEC_CS42L52_BEEP_TONE_CTL, 5, 1, 1),
520
521 SOC_ENUM("Treble Corner Freq Playback Switch", soc_cs42l52_enum[7]), /*35*/
522 SOC_ENUM("Bass Corner Freq Playback Switch",soc_cs42l52_enum[8]),
523 SOC_SINGLE("Tone Control Playback Switch", CODEC_CS42L52_BEEP_TONE_CTL, 0, 1, 0),
524 SOC_SINGLE("Treble Gain Playback Volume", CODEC_CS42L52_TONE_CTL, 4, 15, 1),
525 SOC_SINGLE("Bass Gain Playback Volume", CODEC_CS42L52_TONE_CTL, 0, 15, 1),
526
527 SOC_DOUBLE_R_CS42L52("Master Playback Volume", CODEC_CS42L52_MASTERA_VOL, CODEC_CS42L52_MASTERB_VOL,0x18, 0x18), /* koffu 40*/
528 SOC_DOUBLE_R_CS42L52("HP Digital Playback Volume", CODEC_CS42L52_HPA_VOL, CODEC_CS42L52_HPB_VOL, 0xff, 0x1),
529 SOC_DOUBLE("HP Digital Playback Switch", CODEC_CS42L52_PB_CTL2, 6, 7, 1, 1),
530 SOC_DOUBLE_R_CS42L52("Speaker Playback Volume", CODEC_CS42L52_SPKA_VOL, CODEC_CS42L52_SPKB_VOL, 0xff, 0x1),
531 SOC_DOUBLE("Speaker Playback Switch", CODEC_CS42L52_PB_CTL2, 4, 5, 1, 1),
532
533 SOC_SINGLE("Limiter Max Threshold Playback Volume", CODEC_CS42L52_LIMITER_CTL1, 5, 7, 0),
534 SOC_SINGLE("Limiter Cushion Threshold Playback Volume", CODEC_CS42L52_LIMITER_CTL1, 2, 7, 0),
535 SOC_SINGLE("Limiter SR Playback Switch", CODEC_CS42L52_LIMITER_CTL1, 1, 1, 0), /*45*/
536 SOC_SINGLE("Limiter ZC Playback Switch", CODEC_CS42L52_LIMITER_CTL1, 0, 1, 0),
537 SOC_SINGLE("Limiter Playback Switch", CODEC_CS42L52_LIMITER_CTL2, 7, 1, 0),
538 SOC_ENUM("Limiter Attnenuate Playback Switch", soc_cs42l52_enum[9]),
539 SOC_SINGLE("Limiter Release Rate Playback Volume", CODEC_CS42L52_LIMITER_CTL2, 0, 63, 0),
540 SOC_SINGLE("Limiter Attack Rate Playback Volume", CODEC_CS42L52_LIMITER_AT_RATE, 0, 63, 0), /*50*/
541
542 SOC_DOUBLE("ALC Capture Switch",CODEC_CS42L52_ALC_CTL, 6, 7, 1, 0),
543 SOC_SINGLE("ALC Attack Rate Capture Volume", CODEC_CS42L52_ALC_CTL, 0, 63, 0),
544 SOC_SINGLE("ALC Release Rate Capture Volume", CODEC_CS42L52_ALC_RATE, 0, 63, 0),
545 SOC_SINGLE("ALC Max Threshold Capture Volume", CODEC_CS42L52_ALC_THRESHOLD, 5, 7, 0),
546 SOC_SINGLE("ALC Min Threshold Capture Volume", CODEC_CS42L52_ALC_THRESHOLD, 2, 7, 0), /*55*/
547
548 SOC_ENUM("Noise Gate Type Capture Switch", soc_cs42l52_enum[10]),
549 SOC_SINGLE("Noise Gate Capture Switch", CODEC_CS42L52_NOISE_GATE_CTL, 6, 1, 0),
550 SOC_SINGLE("Noise Gate Boost Capture Switch", CODEC_CS42L52_NOISE_GATE_CTL, 5, 1, 1),
551 SOC_SINGLE("Noise Gate Threshold Capture Volume", CODEC_CS42L52_NOISE_GATE_CTL, 2, 7, 0),
552 SOC_ENUM("Noise Gate Delay Time Capture Switch", soc_cs42l52_enum[11]), /*60*/
553
554 SOC_SINGLE("Batt Compensation Switch", CODEC_CS42L52_BATT_COMPEN, 7, 1, 0),
555 SOC_SINGLE("Batt VP Monitor Switch", CODEC_CS42L52_BATT_COMPEN, 6, 1, 0),
556 SOC_SINGLE("Batt VP ref", CODEC_CS42L52_BATT_COMPEN, 0, 0x0f, 0),
557 SOC_SINGLE("Playback Charge Pump Freq", CODEC_CS42L52_CHARGE_PUMP, 4, 15, 0), /*64*/
558
559 };
560
561 static int soc_cs42l52_add_controls(struct snd_soc_codec *codec)
562 {
563         int i,ret = 0;
564
565         for(i = 0; i < ARRAY_SIZE(soc_cs42l52_controls); i++)
566         {
567                 ret = snd_ctl_add(codec->card,
568                 snd_soc_cnew(&soc_cs42l52_controls[i], codec, NULL));
569
570                 if(ret < 0)
571                 {
572                         SOCDBG("add cs42l52 controls failed\n");
573                         break;
574                 }
575         }
576         return ret;
577 }
578
579 static const struct snd_kcontrol_new cs42l52_adca_mux =
580 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[12]);
581
582 static const struct snd_kcontrol_new cs42l52_adcb_mux =
583 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[13]);
584
585 static const struct snd_kcontrol_new cs42l52_mica_mux =
586 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[14]);
587
588 static const struct snd_kcontrol_new cs42l52_micb_mux =
589 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[15]);
590
591 static const struct snd_kcontrol_new cs42l52_mica_stereo_mux =
592 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[16]);
593
594 static const struct snd_kcontrol_new cs42l52_micb_stereo_mux =
595 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[17]);
596
597 static const struct snd_kcontrol_new cs42l52_passa_switch =
598 SOC_DAPM_SINGLE("Switch", CODEC_CS42L52_MISC_CTL, 6, 1, 0);
599
600 static const struct snd_kcontrol_new cs42l52_passb_switch =
601 SOC_DAPM_SINGLE("Switch", CODEC_CS42L52_MISC_CTL, 7, 1, 0);
602
603 static const struct snd_kcontrol_new cs42l52_micbias_switch =
604 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[19]);
605
606 static const struct snd_kcontrol_new cs42l52_hpa_mux =
607 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[20]);
608
609 static const struct snd_kcontrol_new cs42l52_hpb_mux =
610 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[21]);
611
612 static const struct snd_soc_dapm_widget soc_cs42l52_dapm_widgets[] = {
613
614         /* Input path */
615         SND_SOC_DAPM_ADC("ADC Left", "Capture", CODEC_CS42L52_PWCTL1, 1, 1),
616         //SND_SOC_DAPM_ADC("ADC Right", "Capture", CODEC_CS42L52_PWCTL1, 2, 1),
617
618         
619         SND_SOC_DAPM_MUX("MICA Mux Capture Switch", SND_SOC_NOPM, 0, 0, &cs42l52_mica_mux),
620         SND_SOC_DAPM_MUX("MICB Mux Capture Switch", SND_SOC_NOPM, 0, 0, &cs42l52_micb_mux),
621         SND_SOC_DAPM_MUX("MICA Stereo Mux Capture Switch", SND_SOC_NOPM, 1, 0, &cs42l52_mica_stereo_mux),
622         SND_SOC_DAPM_MUX("MICB Stereo Mux Capture Switch", SND_SOC_NOPM, 2, 0, &cs42l52_micb_stereo_mux),
623
624         SND_SOC_DAPM_MUX("ADC Mux Left Capture Switch", SND_SOC_NOPM, 1, 1, &cs42l52_adca_mux),
625         SND_SOC_DAPM_MUX("ADC Mux Right Capture Switch", SND_SOC_NOPM, 2, 1, &cs42l52_adcb_mux),
626
627
628         /* Sum switches */
629         SND_SOC_DAPM_PGA("AIN1A Switch", CODEC_CS42L52_ADC_PGA_A, 0, 0, NULL, 0),
630         SND_SOC_DAPM_PGA("AIN2A Switch", CODEC_CS42L52_ADC_PGA_A, 1, 0, NULL, 0),
631         SND_SOC_DAPM_PGA("AIN3A Switch", CODEC_CS42L52_ADC_PGA_A, 2, 0, NULL, 0),
632         SND_SOC_DAPM_PGA("AIN4A Switch", CODEC_CS42L52_ADC_PGA_A, 3, 0, NULL, 0),
633         SND_SOC_DAPM_PGA("MICA Switch" , CODEC_CS42L52_ADC_PGA_A, 4, 0, NULL, 0),
634
635         SND_SOC_DAPM_PGA("AIN1B Switch", CODEC_CS42L52_ADC_PGA_B, 0, 0, NULL, 0),
636         SND_SOC_DAPM_PGA("AIN2B Switch", CODEC_CS42L52_ADC_PGA_B, 1, 0, NULL, 0),
637         SND_SOC_DAPM_PGA("AIN3B Switch", CODEC_CS42L52_ADC_PGA_B, 2, 0, NULL, 0),
638         SND_SOC_DAPM_PGA("AIN4B Switch", CODEC_CS42L52_ADC_PGA_B, 3, 0, NULL, 0),
639         SND_SOC_DAPM_PGA("MICB Switch" , CODEC_CS42L52_ADC_PGA_B, 4, 0, NULL, 0),
640
641         /* MIC PGA Power */
642         SND_SOC_DAPM_PGA("PGA MICA", CODEC_CS42L52_PWCTL2, PWCTL2_PDN_MICA_SHIFT, 1, NULL, 0),
643         SND_SOC_DAPM_PGA("PGA MICB", CODEC_CS42L52_PWCTL2, PWCTL2_PDN_MICB_SHIFT, 1, NULL, 0),
644
645         /* MIC bias switch */
646         SND_SOC_DAPM_MUX("Mic Bias Capture Switch", SND_SOC_NOPM, 0, 0, &cs42l52_micbias_switch),
647         SND_SOC_DAPM_PGA("Mic-Bias", CODEC_CS42L52_PWCTL2, 0, 1, NULL, 0),
648
649         /* PGA Power */
650         SND_SOC_DAPM_PGA("PGA Left", CODEC_CS42L52_PWCTL1, PWCTL1_PDN_PGAA_SHIFT, 1, NULL, 0),
651         SND_SOC_DAPM_PGA("PGA Right", CODEC_CS42L52_PWCTL1, PWCTL1_PDN_PGAB_SHIFT, 1, NULL, 0),
652
653         /* Output path */
654         SND_SOC_DAPM_MUX("Passthrough Left Playback Switch", SND_SOC_NOPM, 0, 0, &cs42l52_hpa_mux),
655         SND_SOC_DAPM_MUX("Passthrough Right Playback Switch", SND_SOC_NOPM, 0, 0, &cs42l52_hpb_mux),
656
657         SND_SOC_DAPM_DAC("DAC Left", "Playback", SND_SOC_NOPM, 0, 0),
658         SND_SOC_DAPM_DAC("DAC Right", "Playback", SND_SOC_NOPM, 0, 0),
659
660         SND_SOC_DAPM_PGA("HP Amp Left", CODEC_CS42L52_PWCTL3, 4, 1, NULL, 0),
661         SND_SOC_DAPM_PGA("HP Amp Right", CODEC_CS42L52_PWCTL3, 6, 1, NULL, 0),
662
663         SND_SOC_DAPM_PGA("SPK Pwr Left", CODEC_CS42L52_PWCTL3, 0, 0, NULL, 0),
664         SND_SOC_DAPM_PGA("SPK Pwr Right", CODEC_CS42L52_PWCTL3, 2, 0, NULL, 0),
665
666         SND_SOC_DAPM_OUTPUT("HPA"),
667         SND_SOC_DAPM_OUTPUT("HPB"),
668         SND_SOC_DAPM_OUTPUT("SPKA"),
669         SND_SOC_DAPM_OUTPUT("SPKB"),
670         SND_SOC_DAPM_OUTPUT("MICBIAS"),
671
672         SND_SOC_DAPM_INPUT("INPUT1A"),
673         SND_SOC_DAPM_INPUT("INPUT2A"),
674         SND_SOC_DAPM_INPUT("INPUT3A"),
675         SND_SOC_DAPM_INPUT("INPUT4A"),
676         SND_SOC_DAPM_INPUT("INPUT1B"),
677         SND_SOC_DAPM_INPUT("INPUT2B"),
678         SND_SOC_DAPM_INPUT("INPUT3B"),
679         SND_SOC_DAPM_INPUT("INPUT4B"),
680         SND_SOC_DAPM_INPUT("MICA"),
681         SND_SOC_DAPM_INPUT("MICB"),
682 };
683
684 static const struct snd_soc_dapm_route soc_cs42l52_audio_map[] = {
685
686         /* adc select path */
687         {"ADC Mux Left Capture Switch", "AIN1", "INPUT1A"},
688         {"ADC Mux Right Capture Switch", "AIN1", "INPUT1B"},
689         {"ADC Mux Left Capture Switch", "AIN2", "INPUT2A"},
690         {"ADC Mux Right Capture Switch", "AIN2", "INPUT2B"},
691         {"ADC Mux Left Capture Switch", "AIN3", "INPUT3A"},
692         {"ADC Mux Right Capture Switch", "AIN3", "INPUT3B"},
693         {"ADC Mux Left Capture Switch", "AIN4", "INPUT4A"},
694         {"ADC Mux Right Capture Switch", "AIN4", "INPUT4B"},
695
696         /* left capture part */
697         {"AIN1A Switch", NULL, "INPUT1A"},
698         {"AIN2A Switch", NULL, "INPUT2A"},
699         {"AIN3A Switch", NULL, "INPUT3A"},
700         {"AIN4A Switch", NULL, "INPUT4A"},
701         {"MICA Switch",  NULL, "MICA"},
702         {"PGA MICA", NULL, "MICA Switch"},
703
704         {"PGA Left", NULL, "AIN1A Switch"},
705         {"PGA Left", NULL, "AIN2A Switch"},
706         {"PGA Left", NULL, "AIN3A Switch"},
707         {"PGA Left", NULL, "AIN4A Switch"},
708         {"PGA Left", NULL, "PGA MICA"},
709
710         /* right capture part */
711         {"AIN1B Switch", NULL, "INPUT1B"},
712         {"AIN2B Switch", NULL, "INPUT2B"},
713         {"AIN3B Switch", NULL, "INPUT3B"},
714         {"AIN4B Switch", NULL, "INPUT4B"},
715         {"MICB Switch",  NULL, "MICB"},
716         {"PGA MICB", NULL, "MICB Switch"},
717
718         {"PGA Right", NULL, "AIN1B Switch"},
719         {"PGA Right", NULL, "AIN2B Switch"},
720         {"PGA Right", NULL, "AIN3B Switch"},
721         {"PGA Right", NULL, "AIN4B Switch"},
722         {"PGA Right", NULL, "PGA MICB"},
723
724         {"ADC Mux Left Capture Switch", "PGA", "PGA Left"},
725         {"ADC Mux Right Capture Switch", "PGA", "PGA Right"},
726         {"ADC Left", NULL, "ADC Mux Left Capture Switch"},
727         {"ADC Right", NULL, "ADC Mux Right Capture Switch"},
728
729         /* Mic Bias */
730         {"Mic Bias Capture Switch", "On", "PGA MICA"},
731         {"Mic Bias Capture Switch", "On", "PGA MICB"},
732         {"Mic-Bias", NULL, "Mic Bias Capture Switch"},
733         {"Mic-Bias", NULL, "Mic Bias Capture Switch"},
734         {"ADC Mux Left Capture Switch",  "PGA", "Mic-Bias"},
735         {"ADC Mux Right Capture Switch", "PGA", "Mic-Bias"},
736         {"Passthrough Left Playback Switch",  "On", "Mic-Bias"},
737         {"Passthrough Right Playback Switch", "On", "Mic-Bias"},
738
739         /* loopback path */
740         {"Passthrough Left Playback Switch",  "On",  "PGA Left"},
741         {"Passthrough Right Playback Switch", "On",  "PGA Right"},
742         {"Passthrough Left Playback Switch",  "Off", "DAC Left"},
743         {"Passthrough Right Playback Switch", "Off", "DAC Right"},
744
745         /* Output map */
746         /* Headphone */
747         {"HP Amp Left",  NULL, "Passthrough Left Playback Switch"},
748         {"HP Amp Right", NULL, "Passthrough Right Playback Switch"},
749         {"HPA", NULL, "HP Amp Left"},
750         {"HPB", NULL, "HP Amp Right"},
751
752         /* Speakers */
753         {"SPK Pwr Left",  NULL, "DAC Left"},
754         {"SPK Pwr Right", NULL, "DAC Right"},
755         {"SPKA", NULL, "SPK Pwr Left"},
756         {"SPKB", NULL, "SPK Pwr Right"},
757
758         /* terminator */
759         //{NULL, NULL, NULL},
760 };
761
762 static int soc_cs42l52_add_widgets(struct snd_soc_codec *soc_codec)
763 {
764         snd_soc_dapm_new_controls(soc_codec, soc_cs42l52_dapm_widgets,
765                                 ARRAY_SIZE(soc_cs42l52_dapm_widgets));
766
767         snd_soc_dapm_add_routes(soc_codec, soc_cs42l52_audio_map,
768                                 ARRAY_SIZE(soc_cs42l52_audio_map));     
769
770         snd_soc_dapm_new_widgets(soc_codec);
771         return 0;
772 }
773 #if 0
774 #define SOC_CS42L52_RATES ( SNDRV_PCM_RATE_8000  | SNDRV_PCM_RATE_11025 | \
775                             SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
776                             SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
777                             SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
778                             SNDRV_PCM_RATE_96000 )
779 #else
780 #define SOC_CS42L52_RATES  SNDRV_PCM_RATE_44100
781 #endif
782 #define SOC_CS42L52_FORMATS ( SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
783                               SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \
784                               SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
785                               SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE )
786
787
788 /*
789  *----------------------------------------------------------------------------
790  * Function : soc_cs42l52_set_bias_level
791  * Purpose  : This function is to get triggered when dapm events occurs.
792  *            
793  *----------------------------------------------------------------------------
794  */
795 int soc_cs42l52_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level)
796 {
797         u8 pwctl1 = soc_cs42l52_read(codec, CODEC_CS42L52_PWCTL1) & 0x9f;
798         u8 pwctl2 = soc_cs42l52_read(codec, CODEC_CS42L52_PWCTL2) & 0x07;
799
800         switch (level) {
801         case SND_SOC_BIAS_ON: /* full On */
802                 SOCDBG("full on\n");
803                 break;
804         case SND_SOC_BIAS_PREPARE: /* partial On */
805                 SOCDBG("partial on\n");
806                 pwctl1 &= ~(PWCTL1_PDN_CHRG | PWCTL1_PDN_CODEC);
807                 soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1);
808                 break;
809         case SND_SOC_BIAS_STANDBY: /* Off, with power */
810                 SOCDBG("off with power\n");
811                 pwctl1 &= ~(PWCTL1_PDN_CHRG | PWCTL1_PDN_CODEC);
812                 soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1);
813                 break;
814         case SND_SOC_BIAS_OFF: /* Off, without power */
815                 SOCDBG("off without power\n");
816               soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1 | 0x9f);
817                 soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL2, pwctl2 | 0x07);
818                 break;
819         }
820         codec->bias_level = level;
821
822         return 0;
823 }
824
825 /*
826  *----------------------------------------------------------------------------
827  * Function : cs42l52_power_init
828  * Purpose  : This function is toinit codec to a normal status
829  *   
830  *----------------------------------------------------------------------------
831  */
832 static void cs42l52_power_init (struct snd_soc_codec *soc_codec)
833 {
834         int i,ret;
835
836         SOCDBG("\n");
837         for(i = 0; i < soc_codec->num_dai; i++)
838         {
839                 SOCINF("Cirrus CS42L52 codec , revision %d\n", ret & CHIP_REV_MASK);
840
841                 /*set hp default volume*/
842                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPA_VOL, DEFAULT_HP_VOL);
843                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPB_VOL, DEFAULT_HP_VOL);
844
845                 /*set spk default volume*/
846                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_SPKA_VOL, DEFAULT_SPK_VOL);
847                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_SPKB_VOL, DEFAULT_SPK_VOL);
848
849                 /*set output default powerstate*/
850                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL3, 5);
851
852 #ifdef AUTO_DETECT_DISABLE
853                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, 
854                                 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_CLK_CTL) 
855                                  & ~CLK_CTL_AUTODECT_ENABLE));
856 #else
857                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL,
858                                 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_CLK_CTL)
859                                  |CLK_CTL_AUTODECT_ENABLE));
860 #endif
861
862                 /*default output stream configure*/
863                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1,
864                                 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_PB_CTL1)
865                                 | (PB_CTL1_HP_GAIN_06047 << PB_CTL1_HP_GAIN_SHIFT)));
866
867                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MISC_CTL,
868                                 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MISC_CTL))
869                                 | (MISC_CTL_DEEMPH | MISC_CTL_DIGZC | MISC_CTL_DIGSFT));
870
871                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICA_CTL,
872                                 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MICA_CTL)
873                                 | 0<<6));/*pre-amplifer 16db*/
874                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICB_CTL,
875                                 (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MICB_CTL)
876                                 | 0<<6));/*pre-amplifer 16db*/
877
878                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL2, 0x00);
879                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_A, 0x90); 
880                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_B, 0x90); 
881
882                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICA_CTL, 0x2c);
883                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICB_CTL, 0x2c);
884
885                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_PGAA_CTL, 0x00);  //0dB PGA
886                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_PGAB_CTL, 0x00);  //0dB PGA
887
888                  soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_HPF_FREQ, 0x0F);  //enable 464Hz HPF
889                          
890                 //soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERA_VOL, 0x12);
891                 //soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERB_VOL, 0x12);
892
893                 //soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPA_VOL, 0xc0);
894                 //soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPB_VOL, 0xc0);
895
896                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_BEEP_TONE_CTL, 0X07);
897                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_TONE_CTL, 0X8f);
898
899                 /*      
900                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERA_VOL, 0x00);
901                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERB_VOL, 0x00);
902
903                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_BEEP_TONE_CTL, 0X00);
904                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_TONE_CTL, 0X00);
905                 */
906         }
907
908         return;
909 }
910
911 /*
912  *----------------------------------------------------------------------------
913  * Function : soc_cs42l52_work
914  * Purpose  : This function is to power on bias.
915  *            
916  *----------------------------------------------------------------------------
917  */
918 static void soc_cs42l52_work(struct work_struct *work)
919 {
920         struct snd_soc_codec *codec =
921                 container_of(work, struct snd_soc_codec, delayed_work.work);
922
923         soc_cs42l52_set_bias_level(codec, codec->bias_level);
924
925         return;
926 }
927
928 /*
929  *----------------------------------------------------------------------------
930  * Function : soc_cs42l52_trigger
931  * Purpose  : This function is to respond to trigger.
932  *            
933  *----------------------------------------------------------------------------
934  */
935 static int soc_cs42l52_trigger(struct snd_pcm_substream *substream,
936                           int status,
937                           struct snd_soc_dai *dai)
938 {       
939         struct snd_soc_pcm_runtime *rtd = substream->private_data;
940         struct snd_soc_dai_link *machine = rtd->dai;
941         struct snd_soc_dai *codec_dai = machine->codec_dai;
942
943         SOCDBG ("substream->stream:%s status:%d\n",
944                    substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE", status);
945
946         if(status == 1 || status == 0){
947                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
948                         codec_dai->playback.active = status;
949                 }else{
950                         codec_dai->capture.active = status;
951                 }
952         }
953
954         return 0;
955 }
956
957 /*
958  *----------------------------------------------------------------------------
959  * Function : soc_cs42l52_hw_params
960  * Purpose  : This function is to set the hardware parameters for CS42L52.
961  *            The functions set the sample rate and audio serial data word 
962  *            length.
963  *            
964  *----------------------------------------------------------------------------
965  */
966 static int soc_cs42l52_hw_params(struct snd_pcm_substream *substream,
967                         struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
968 {
969         struct snd_soc_pcm_runtime *rtd = substream->private_data;
970         struct snd_soc_device *soc_dev = rtd->socdev;
971         struct snd_soc_codec *soc_codec = soc_dev->card->codec;
972         struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
973
974         u32 clk = 0;
975         int ret = 0;
976         int index = soc_cs42l52_get_clk(info->sysclk, params_rate(params));
977
978         SOCDBG("----------sysclk=%d,rate=%d\n",info->sysclk, params_rate(params));
979
980         if(index >= 0)
981         {
982                 info->sysclk = clk_map_table[index].mclk;
983                 clk |= (clk_map_table[index].speed << CLK_CTL_SPEED_SHIFT) | 
984                       (clk_map_table[index].group << CLK_CTL_32K_SR_SHIFT) | 
985                       (clk_map_table[index].videoclk << CLK_CTL_27M_MCLK_SHIFT) | 
986                       (clk_map_table[index].ratio << CLK_CTL_RATIO_SHIFT) | 
987                       clk_map_table[index].mclkdiv2;
988
989 #ifdef AUTO_DETECT_DISABLE
990                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, clk);
991 #else
992                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, 0xa0);
993 #endif
994         }
995         else{
996                 SOCDBG("can't find out right mclk\n");
997                 ret = -EINVAL;
998         }
999
1000         return ret;
1001 }
1002
1003 /*
1004  *----------------------------------------------------------------------------
1005  * Function : soc_cs42l52_set_sysclk
1006  * Purpose  : This function is to set the DAI system clock
1007  *            
1008  *----------------------------------------------------------------------------
1009  */
1010 static int soc_cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
1011                         int clk_id, u_int freq, int dir)
1012 {
1013         int ret = 0;
1014         struct snd_soc_codec *soc_codec = codec_dai->codec;
1015         struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
1016
1017         SOCDBG("sysclk=%dHz,freq=%d\n", info->sysclk,freq);
1018
1019         if((freq >= SOC_CS42L52_MIN_CLK) && (freq <= SOC_CS42L52_MAX_CLK)){
1020                 info->sysclk = freq;
1021                 SOCDBG("info->sysclk set to %d Hz\n", info->sysclk);
1022         }
1023         else{
1024                 printk("invalid paramter\n");
1025                 ret = -EINVAL;
1026         }
1027         return ret;
1028 }
1029
1030 /*
1031  *----------------------------------------------------------------------------
1032  * Function : soc_cs42l52_set_fmt
1033  * Purpose  : This function is to set the DAI format
1034  *            
1035  *----------------------------------------------------------------------------
1036  */
1037 static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
1038                         u_int fmt)
1039 {
1040         struct snd_soc_codec *soc_codec = codec_dai->codec;
1041         struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
1042         int ret = 0;
1043         u8 iface = 0;
1044
1045         /* set master/slave audio interface */
1046         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1047         case SND_SOC_DAIFMT_CBM_CFM:
1048                 SOCDBG("codec dai fmt master\n");
1049                 iface = IFACE_CTL1_MASTER;
1050                 break;
1051         case SND_SOC_DAIFMT_CBS_CFS:
1052                 SOCDBG("codec dai fmt slave\n");
1053                 break;
1054         default:
1055                 SOCDBG("invaild formate\n");
1056                 ret = -EINVAL;
1057                 goto done;
1058         }
1059
1060          /* interface format */
1061         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1062         case SND_SOC_DAIFMT_I2S:
1063                 SOCDBG("codec dai fmt i2s\n");
1064                 iface |= (IFACE_CTL1_ADC_FMT_I2S | IFACE_CTL1_DAC_FMT_I2S);
1065                 break;
1066         case SND_SOC_DAIFMT_RIGHT_J:
1067                 SOCDBG("codec dai fmt right justified\n");
1068                 iface |= IFACE_CTL1_DAC_FMT_RIGHT_J;
1069                 SOCINF("warning only playback stream support this format\n");
1070                 break;
1071         case SND_SOC_DAIFMT_LEFT_J:
1072                 SOCDBG("codec dai fmt left justified\n");
1073                 iface |= (IFACE_CTL1_ADC_FMT_LEFT_J | IFACE_CTL1_DAC_FMT_LEFT_J);
1074                 break;
1075         case SND_SOC_DAIFMT_DSP_A:
1076                 iface |= IFACE_CTL1_DSP_MODE_EN;
1077                 break;
1078         case SND_SOC_DAIFMT_DSP_B:
1079                 SOCINF("unsupported format\n");
1080                 ret = -EINVAL;
1081                 goto done;
1082         default:
1083                 SOCINF("invaild format\n");
1084                 ret = -EINVAL;
1085                 goto done;
1086         }
1087
1088         /* clock inversion */
1089         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1090         case SND_SOC_DAIFMT_NB_NF:
1091                 SOCDBG("codec dai fmt normal sclk\n");
1092                 break;
1093         case SND_SOC_DAIFMT_IB_IF:
1094                 SOCDBG("codec dai fmt inversed sclk\n");
1095                 iface |= IFACE_CTL1_INV_SCLK;
1096                 break;
1097         case SND_SOC_DAIFMT_IB_NF:
1098                 iface |= IFACE_CTL1_INV_SCLK;
1099                 break;
1100         case SND_SOC_DAIFMT_NB_IF:
1101                 break;
1102         default:
1103                 SOCDBG("unsupported format\n");
1104                 ret = -EINVAL;
1105         }
1106
1107         info->format = iface;
1108 done:
1109         soc_cs42l52_write(soc_codec, CODEC_CS42L52_IFACE_CTL1, info->format);
1110
1111         return ret;
1112 }
1113
1114 /*
1115  *----------------------------------------------------------------------------
1116  * Function : soc_cs42l52_digital_mute
1117  * Purpose  : This function is to mute DAC or not
1118  *            
1119  *----------------------------------------------------------------------------
1120  */
1121 static int soc_cs42l52_digital_mute(struct snd_soc_dai *dai, int mute)
1122 {
1123         struct snd_soc_codec *soc_codec = dai->codec;
1124         u8 mute_val = soc_cs42l52_read(soc_codec, CODEC_CS42L52_PB_CTL1) & PB_CTL1_MUTE_MASK;
1125
1126         SOCDBG("%d\n",mute);
1127
1128         if(mute) {
1129                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1, mute_val \
1130                         | PB_CTL1_MSTB_MUTE | PB_CTL1_MSTA_MUTE);
1131         }
1132         else {
1133                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1, mute_val );
1134         }
1135
1136         return 0;
1137 }
1138
1139 static struct snd_soc_dai_ops cs42l52_ops = {
1140                         .hw_params              = soc_cs42l52_hw_params,
1141                         .set_sysclk             = soc_cs42l52_set_sysclk,
1142                         .set_fmt                = soc_cs42l52_set_fmt,
1143                         .trigger                = soc_cs42l52_trigger,
1144                         .digital_mute   = soc_cs42l52_digital_mute,
1145 };
1146 /*
1147  *----------------------------------------------------------------------------
1148  * @struct  soc_cs42l52_dai |
1149  *          It is SoC Codec DAI structure which has DAI capabilities viz., 
1150  *          playback and capture, DAI runtime information viz. state of DAI 
1151  *                      and pop wait state, and DAI private data. 
1152  *          The AIC3111 rates ranges from 8k to 192k
1153  *          The PCM bit format supported are 16, 20, 24 and 32 bits
1154  *----------------------------------------------------------------------------
1155  */
1156 struct  snd_soc_dai soc_cs42l52_dai = {
1157             .name = SOC_CS42L52_NAME,
1158             .playback = {
1159                     .stream_name = "Playback",
1160                     .channels_min = 1,
1161                     .channels_max = SOC_CS42L52_DEFAULT_MAX_CHANS,
1162                     .rates = SOC_CS42L52_RATES,
1163                     .formats = SOC_CS42L52_FORMATS,
1164             },
1165             .capture = {
1166                     .stream_name = "Capture",
1167                     .channels_min = 1,
1168                     .channels_max = SOC_CS42L52_DEFAULT_MAX_CHANS,
1169                     .rates = SOC_CS42L52_RATES,
1170                     .formats = SOC_CS42L52_FORMATS,
1171             },
1172                         .ops = &cs42l52_ops,
1173 };
1174 EXPORT_SYMBOL_GPL(soc_cs42l52_dai);
1175
1176
1177 #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
1178 static int cs42l52_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
1179 {       
1180         struct snd_soc_codec *soc_codec;
1181         struct soc_codec_cs42l52 * info;
1182         struct cs42l52_platform_data *pdata = i2c->dev.platform_data;
1183         int ret = 0;
1184
1185         soc_codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1186         if (soc_codec == NULL)
1187                 return -ENOMEM;
1188
1189         soc_codec->name = SOC_CS42L52_NAME;
1190         soc_codec->owner = THIS_MODULE;
1191         soc_codec->write = soc_cs42l52_write;
1192         soc_codec->read = soc_cs42l52_read;
1193         soc_codec->hw_write = (hw_write_t)i2c_master_send;
1194         mutex_init(&soc_codec->mutex);
1195         INIT_LIST_HEAD(&soc_codec->dapm_widgets);
1196         INIT_LIST_HEAD(&soc_codec->dapm_paths);
1197         
1198         soc_codec->set_bias_level = soc_cs42l52_set_bias_level;
1199         soc_codec->dai = &soc_cs42l52_dai;
1200         soc_codec->dai->playback.channels_max = 2;
1201         soc_codec->dai->capture.channels_max = 2;
1202         soc_codec->num_dai = 1;
1203         soc_codec->control_data = i2c;
1204         soc_codec->dev = &i2c->dev;     
1205         soc_codec->pcm_devs = 0;
1206         soc_codec->pop_time = 2;
1207         soc_codec->dai[0].codec = soc_codec;
1208
1209         soc_codec->reg_cache_size = sizeof(soc_cs42l52_reg_default);
1210
1211         soc_codec->reg_cache = kmemdup(soc_cs42l52_reg_default, sizeof(soc_cs42l52_reg_default), GFP_KERNEL);
1212
1213         info = (struct soc_codec_cs42l52 *)kmalloc(sizeof(struct soc_codec_cs42l52),GFP_KERNEL);
1214         if (info == NULL) {
1215                 kfree(soc_codec);
1216                 return -ENOMEM;
1217         }
1218
1219         info->sysclk = SOC_CS42L52_DEFAULT_CLK;
1220         info->format = SOC_CS42L52_DEFAULT_FORMAT;
1221
1222         soc_codec->private_data =(void*)info;   
1223         if(!soc_codec->reg_cache) {
1224                 SOCERR("%s: err out of memory\n", __FUNCTION__);
1225                 ret = -ENOMEM;
1226                 goto err;
1227         }
1228
1229         if (pdata->init_platform_hw)                              
1230                 pdata->init_platform_hw();
1231
1232         /*initialize codec*/
1233         cs42l52_power_init(soc_codec);
1234
1235     INIT_DELAYED_WORK(&soc_codec->delayed_work, soc_cs42l52_work);
1236
1237         soc_cs42l52_dai.dev = &i2c->dev;
1238         cs42l52_codec = soc_codec;
1239
1240         ret = snd_soc_register_codec(soc_codec);
1241         if (ret != 0) {
1242                 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1243                 goto err;
1244         }
1245
1246         ret = snd_soc_register_dai(&soc_cs42l52_dai);
1247         if (ret != 0) {
1248                 dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
1249                 goto err_codec;
1250         }
1251
1252         return ret;
1253
1254 err_codec:
1255         snd_soc_unregister_codec(soc_codec);
1256 err:
1257         kfree(cs42l52_codec);
1258         cs42l52_codec = NULL;
1259         return ret;
1260 }
1261
1262 static int cs42l52_i2c_remove(struct i2c_client *client)
1263 {
1264         snd_soc_unregister_dai(&soc_cs42l52_dai);
1265         snd_soc_unregister_codec(cs42l52_codec);
1266
1267         soc_cs42l52_set_bias_level(cs42l52_codec, SND_SOC_BIAS_OFF);
1268
1269         soc_cs42l52_dai.dev = NULL;
1270         if(cs42l52_codec->reg_cache)            
1271                 kfree(cs42l52_codec->reg_cache);
1272         if(cs42l52_codec->private_data)         
1273                 kfree(cs42l52_codec->private_data);
1274         kfree(cs42l52_codec);
1275         cs42l52_codec = NULL;
1276
1277         return 0;
1278 }
1279
1280
1281 static int cs42l52_i2c_shutdown(struct i2c_client *client)
1282 {
1283         SOCDBG("i am here\n");        
1284         snd_soc_unregister_dai(&soc_cs42l52_dai);
1285         snd_soc_unregister_codec(cs42l52_codec);
1286
1287         soc_cs42l52_set_bias_level(cs42l52_codec, SND_SOC_BIAS_OFF);
1288
1289         soc_cs42l52_dai.dev = NULL;
1290         if(cs42l52_codec->reg_cache)            
1291                 kfree(cs42l52_codec->reg_cache);
1292         if(cs42l52_codec->private_data)         
1293                 kfree(cs42l52_codec->private_data);
1294         kfree(cs42l52_codec);
1295         cs42l52_codec = NULL;
1296
1297         return 0;
1298 }
1299
1300 static const struct i2c_device_id cs42l52_i2c_id[] = {
1301         { "cs42l52", 0 },
1302 };
1303 MODULE_DEVICE_TABLE(i2c, cs42l52_i2c_id);
1304
1305 static struct i2c_driver cs42l52_i2c_drv = {
1306         .driver = {
1307                 .name = "CS42L52",
1308                 .owner = THIS_MODULE,
1309         },
1310         .probe =    cs42l52_i2c_probe,
1311         .remove =   cs42l52_i2c_remove,
1312         .shutdown =  cs42l52_i2c_shutdown,
1313         .id_table = cs42l52_i2c_id,
1314 };
1315
1316 #endif
1317
1318
1319 #ifdef CONFIG_HAS_EARLYSUSPEND
1320 static int soc_cs42l52_suspend(struct early_suspend *h)
1321 {
1322         
1323         soc_cs42l52_write(cs42l52_codec, CODEC_CS42L52_PWCTL1, PWCTL1_PDN_CODEC);
1324         soc_cs42l52_set_bias_level(cs42l52_codec, SND_SOC_BIAS_OFF);
1325         return 0;
1326 }
1327
1328 static int soc_cs42l52_resume(struct early_suspend *h)
1329 {
1330         struct snd_soc_codec *soc_codec = cs42l52_codec;
1331         struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*) soc_codec->private_data;
1332         int i, reg;
1333         u8 data[2];
1334         u8 *reg_cache = (u8*) soc_codec->reg_cache;
1335         soc_codec->num_dai = 1;
1336         /* Sync reg_cache with the hardware */
1337         for(i = 0; i < soc_codec->num_dai; i++) {
1338
1339             for(reg = 0; reg < ARRAY_SIZE(soc_cs42l52_reg_default); reg++) {
1340                 data[0] = reg;
1341                 data[1] = reg_cache[reg];
1342                 if(soc_codec->hw_write(soc_codec->control_data, data, 2) != 2)
1343                     break;
1344             }
1345         }
1346
1347         soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_STANDBY);
1348
1349         /*charge cs42l52 codec*/
1350         if(soc_codec->suspend_bias_level == SND_SOC_BIAS_ON)
1351         {
1352                 soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_PREPARE);
1353                 soc_codec->bias_level = SND_SOC_BIAS_ON;
1354                 schedule_delayed_work(&soc_codec->delayed_work, msecs_to_jiffies(1000));
1355         }
1356         return 0;
1357
1358 }
1359 #else
1360 static int soc_cs42l52_suspend(struct platform_device *pdev, pm_message_t state)
1361 {
1362         struct snd_soc_device *soc_dev = (struct snd_soc_device*)platform_get_drvdata(pdev);
1363         struct snd_soc_codec *soc_codec = soc_dev->card->codec;
1364         
1365         soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL1, PWCTL1_PDN_CODEC);
1366         soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_OFF);
1367         return 0;
1368 }
1369
1370 static int soc_cs42l52_resume(struct platform_device *pdev)
1371 {
1372         struct snd_soc_device *soc_dev = (struct snd_soc_device*) platform_get_drvdata(pdev);
1373         struct snd_soc_codec *soc_codec = soc_dev->card->codec;
1374         struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*) soc_codec->private_data;
1375         int i, reg;
1376         u8 data[2];
1377         u8 *reg_cache = (u8*) soc_codec->reg_cache;
1378         soc_codec->num_dai = 1;
1379         /* Sync reg_cache with the hardware */
1380         for(i = 0; i < soc_codec->num_dai; i++) {
1381
1382             for(reg = 0; reg < ARRAY_SIZE(soc_cs42l52_reg_default); reg++) {
1383                 data[0] = reg;
1384                 data[1] = reg_cache[reg];
1385                 if(soc_codec->hw_write(soc_codec->control_data, data, 2) != 2)
1386                     break;
1387             }
1388         }
1389
1390         soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_STANDBY);
1391
1392         /*charge cs42l52 codec*/
1393         if(soc_codec->suspend_bias_level == SND_SOC_BIAS_ON)
1394         {
1395                 soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_PREPARE);
1396                 soc_codec->bias_level = SND_SOC_BIAS_ON;
1397                 schedule_delayed_work(&soc_codec->delayed_work, msecs_to_jiffies(1000));
1398         }
1399         return 0;
1400
1401 }
1402 #endif
1403 static int soc_cs42l52_probe(struct platform_device *pdev)
1404 {
1405         struct snd_soc_device *soc_dev = platform_get_drvdata(pdev);
1406         struct snd_soc_codec *soc_codec;
1407         int ret = 0;
1408
1409         if (cs42l52_codec == NULL) {
1410                 dev_err(&pdev->dev, "Codec device not registered\n");
1411                 return -ENODEV;
1412         }
1413
1414         soc_dev->card->codec = cs42l52_codec;
1415         soc_codec = cs42l52_codec;
1416
1417         ret = snd_soc_new_pcms(soc_dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1418         if(ret)
1419         {
1420                 SOCERR("%s: add new pcms failed\n",__FUNCTION__);
1421                 goto pcm_err;
1422         }
1423
1424         soc_cs42l52_add_controls(soc_codec);
1425         soc_cs42l52_add_widgets(soc_codec);
1426
1427         ret = snd_soc_init_card(soc_dev);
1428
1429         INIT_DELAYED_WORK(&soc_codec->delayed_work, soc_cs42l52_work);
1430
1431         if(ret)
1432         {
1433                 SOCERR("add snd card failed\n");
1434                 goto card_err;
1435         }
1436
1437 #ifdef CONFIG_HAS_EARLYSUSPEND   
1438         cs42l52_early_suspend.suspend =soc_cs42l52_suspend;  
1439         cs42l52_early_suspend.resume =soc_cs42l52_resume;//   cs42l52_early_suspend.level = 0x2;    
1440         register_early_suspend(&cs42l52_early_suspend);
1441 #endif
1442         return ret;
1443
1444 card_err:
1445         snd_soc_free_pcms(soc_dev);
1446         snd_soc_dapm_free(soc_dev);
1447 pcm_err:
1448         return ret;
1449
1450 }
1451
1452 static int soc_cs42l52_remove(struct platform_device *pdev)
1453 {
1454         struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1455
1456         snd_soc_free_pcms(socdev);
1457         snd_soc_dapm_free(socdev);
1458 #ifdef CONFIG_HAS_EARLYSUSPEND          
1459         unregister_early_suspend(&cs42l52_early_suspend);
1460 #endif 
1461         return 0;
1462 }
1463
1464 struct snd_soc_codec_device soc_codec_dev_cs42l52 = {
1465         .probe = soc_cs42l52_probe,
1466         .remove = soc_cs42l52_remove,
1467 #ifndef         CONFIG_HAS_EARLYSUSPEND
1468         .suspend = soc_cs42l52_suspend,
1469         .resume = soc_cs42l52_resume,
1470 #endif  
1471 };
1472
1473 EXPORT_SYMBOL_GPL(soc_codec_dev_cs42l52);
1474
1475 static int __init cs42l52_modinit(void)
1476 {
1477         return i2c_add_driver(&cs42l52_i2c_drv);
1478 }
1479 module_init(cs42l52_modinit);
1480
1481 static void __exit cs42l52_exit(void)
1482 {
1483         i2c_del_driver(&cs42l52_i2c_drv);
1484 }
1485 module_exit(cs42l52_exit);
1486
1487
1488
1489 MODULE_DESCRIPTION("ALSA SoC CS42L52 Codec");
1490 MODULE_AUTHOR("Bo Liu, Bo.Liu@cirrus.com, www.cirrus.com");
1491 MODULE_LICENSE("GPL");
1492
1493
1494
1495
1496 #ifdef CONFIG_PROC_FS
1497 #include <linux/proc_fs.h>
1498 #include <linux/seq_file.h>
1499 static int proc_cs42l52_show (struct seq_file *s, void *v)
1500 {
1501         struct snd_soc_codec *codec = cs42l52_codec;
1502         int reg;
1503
1504         seq_printf (s, "    cs42l52 registers:\n");
1505         for (reg = 0; reg < 53; reg++) {
1506                 if (reg%10 == 0) 
1507                         seq_printf (s, "\n            ");
1508                 seq_printf (s, "0x%02x ", soc_cs42l52_read(codec, reg));
1509         }
1510         seq_printf (s, "\n\n");
1511
1512 #if 0//for check cache
1513         u8 *cache = codec->reg_cache;
1514         seq_printf (s, "            cache:\n");
1515         for (reg = 0; reg < 53; reg++) {
1516                 if (reg%10 == 0) 
1517                         seq_printf (s, "\n            ");
1518                 seq_printf (s, "0x%02x ", cache[reg]);
1519         }
1520         seq_printf (s, "\n\n");
1521 #endif
1522
1523         return 0;
1524 }
1525
1526 static int proc_cs42l52_open (struct inode *inode, struct file *file)
1527 {
1528         return single_open (file, proc_cs42l52_show, NULL);
1529 }
1530
1531 static const struct file_operations proc_cs42l52_fops = {
1532         .open           = proc_cs42l52_open,
1533         .read           = seq_read,
1534         .llseek         = seq_lseek,
1535         .release        = single_release,
1536 };
1537
1538 static int __init codec_proc_init (void)
1539 {
1540         proc_create ("cs42l52", 0, NULL, &proc_cs42l52_fops);
1541         return 0;
1542 }
1543 late_initcall (codec_proc_init);
1544 #endif /* CONFIG_PROC_FS */