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