Merge remote-tracking branch 'origin/upstream/linux-linaro-lsk-v3.10-android' into...
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / rk610_codec.c
1 /*
2  * rk610.c -- RK610 ALSA SoC audio driver
3  *
4  * Copyright (C) 2009 rockchip lhh
5  *
6  *
7  * Based on RK610.c
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/init.h>
17 #include <linux/delay.h>
18 #include <linux/pm.h>
19 #include <linux/i2c.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 #include <sound/soc.h>
26 #include <sound/soc-dapm.h>
27 #include <sound/initval.h>
28 #include <mach/gpio.h>
29 #include <mach/iomux.h>
30 #include <linux/workqueue.h>
31 #include "rk610_codec.h"
32 #include <mach/board.h>
33
34 #define RK610_PROC
35 #ifdef RK610_PROC
36 #include <linux/proc_fs.h>
37 #include <linux/seq_file.h>
38 #include <linux/vmalloc.h>
39 #endif
40 #define HP_OUT 0
41 #define HP_IN  1
42
43 //if you find resume rk610 cannot work,you can try RESUME_PROBLEM 1.
44 //if rk610 Normal working on RESUME_PROBLEM 1, you must detect Machine other driver queue.
45 //you can look soc-core.c the resume source.s
46 #define RESUME_PROBLEM 0
47
48 //1:set pll from rk610
49 #define RK610_CTL_PLL 0
50
51 /*
52  * Debug
53  */
54 #if 0
55 #define DBG(x...)       printk(KERN_INFO x)
56 #else
57 #define DBG(x...)
58 #endif
59
60 //rk610 output volume,DAC Digital Gain
61 //0x0000 ~ 0xF42                                        
62 #define Volume_Output 0xF42
63 //0x0 ~ 0x3f(bit0-bit5)  max=0x0(+6DB) min=0x3f(-60DB)  //Analog Gain
64 #define Volume_Codec_PA 0x0
65
66 //rk610 input volume,rk610 can not adjust the recording volume 
67 #define Volume_Input 0x07
68
69
70
71 #define OUT_CAPLESS  (1)   //ÊÇ·ñΪÎÞµçÈÝÊä³ö£¬1:ÎÞµçÈÝÊä³ö£¬0:ÓеçÈÝÊä³ö
72
73 static u8 gR0AReg = 0;  //ÓÃÓڼǼR0A¼Ä´æÆ÷µÄÖµ£¬ÓÃÓڸıä²ÉÑùÂÊǰͨ¹ýR0AÍ£Ö¹clk
74 static u8 gR0BReg = 0;  //ÓÃÓڼǼR0B¼Ä´æÆ÷µÄÖµ£¬ÓÃÓڸıä²ÉÑùÂÊǰͨ¹ýR0BÍ£Ö¹interplateºÍdecimation
75
76
77 /*
78  * rk610 register cache
79  * We can't read the RK610 register space when we
80  * are using 2 wire for device control, so we cache them instead.
81  */
82 static const u16 rk610_codec_reg[] = {
83         0x0005, 0x0004, 0x00fd, 0x00f3,  /*  0 */
84         0x0003, 0x0000, 0x0000, 0x0000,  /*  4 */
85         0x0000, 0x0005, 0x0000, 0x0000,  /*  8 */
86         0x0097, 0x0097, 0x0097, 0x0097,  /* 12 */
87         0x0097, 0x0097, 0x00cc, 0x0000,  /* 16 */
88         0x0000, 0x00f1, 0x0090, 0x00ff,  /* 20 */
89         0x00ff, 0x00ff, 0x009c, 0x0000,  /* 24 */
90         0x0000, 0x00ff, 0x00ff, 0x00ff,  /* 28 */
91 };
92
93 static struct snd_soc_codec *rk610_codec_codec=NULL;
94 /* codec private data */
95 struct rk610_codec_priv {
96         enum snd_soc_control_type control_type;
97         unsigned int sysclk;
98         struct snd_soc_codec codec;
99         struct snd_pcm_hw_constraint_list *sysclk_constraints;
100         u16 reg_cache[RK610_CODEC_NUM_REG];
101
102         struct delayed_work rk610_delayed_work;
103         unsigned int spk_ctrl_io;
104         unsigned int pa_enable_time;
105         bool hdmi_ndet;
106 #if RESUME_PROBLEM
107         int rk610_workstatus;
108 #endif
109         struct rk610_codec_platform_data *pdata;
110         int call_enable;        
111         int headset_status;     
112 };
113
114 static void spk_ctrl_fun(int status)
115 {
116         struct rk610_codec_priv *rk610_codec = NULL;
117         if(rk610_codec_codec == NULL)
118                 return;
119         rk610_codec = snd_soc_codec_get_drvdata(rk610_codec_codec);
120         if(rk610_codec == NULL)
121                 return;
122 #ifdef CONFIG_MODEM_SOUND
123         if(rk610_codec->call_enable){
124                 DBG("%s:: is calling cannot set spk\n",__FUNCTION__);
125                 return;
126         }       
127 #endif          
128         if(rk610_codec->spk_ctrl_io)
129         {
130                 DBG("%s:: spk status = %d\n",__FUNCTION__,status);
131                 gpio_set_value(rk610_codec->spk_ctrl_io, status);
132         }
133 }
134
135 void codec_set_spk(bool on)
136 {
137         struct rk610_codec_priv *rk610_codec;
138         if(!rk610_codec_codec)
139                 return;
140                 
141         rk610_codec=snd_soc_codec_get_drvdata(rk610_codec_codec);
142         if(!rk610_codec)
143                 return;
144         
145         rk610_codec->hdmi_ndet = on;
146         if(on)
147                 gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_HIGH);
148         else
149                 gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_LOW);                     
150 }
151 EXPORT_SYMBOL(codec_set_spk);
152
153 /*
154  * read rk610 register cache
155  */
156 static inline unsigned int rk610_codec_read_reg_cache(struct snd_soc_codec *codec,
157         unsigned int reg)
158 {
159         u16 *cache = codec->reg_cache;
160         if (reg > RK610_CACHE_REGNUM)
161                 return -1;
162         return cache[reg];
163 }
164
165 static unsigned int rk610_codec_read(struct snd_soc_codec *codec, unsigned int r)
166 {
167         struct i2c_msg xfer[1];
168         u8 reg = r;
169         int ret;
170         struct i2c_client *client = codec->control_data;
171
172         /* Read register */
173         xfer[0].addr = (client->addr& 0x60)|(reg);
174         xfer[0].flags = I2C_M_RD;
175         xfer[0].len = 1;
176         xfer[0].buf = &reg;
177         xfer[0].scl_rate = 100000;
178         ret = i2c_transfer(client->adapter, xfer, 1);
179         if (ret != 1) {
180                 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
181                 return 0;
182         }
183
184         return reg;
185 }
186
187 /*
188  * write rk610 register cache
189  */
190 static inline void rk610_codec_write_reg_cache(struct snd_soc_codec *codec,
191         unsigned int reg, unsigned int value)
192 {
193         u16 *cache = codec->reg_cache;
194         if (reg > RK610_CACHE_REGNUM)
195                 return;
196         cache[reg] = value;
197 }
198
199 static int rk610_codec_write(struct snd_soc_codec *codec, unsigned int reg,
200         unsigned int value)
201 {
202         struct rk610_codec_priv *rk610_codec = snd_soc_codec_get_drvdata(rk610_codec_codec);
203         u8 data[2];
204         struct i2c_client *i2c;
205 #ifdef CONFIG_MODEM_SOUND       
206         if(rk610_codec->call_enable)
207                 return 0;
208 #endif  
209         DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n",__FUNCTION__,__LINE__, reg, value);
210         data[0] = value & 0x00ff;
211         rk610_codec_write_reg_cache (codec, reg, value);
212         i2c = (struct i2c_client *)codec->control_data;
213         i2c->addr = (i2c->addr & 0x60)|reg;
214
215         if (codec->hw_write(codec->control_data, data, 1) == 1){
216 //              DBG("================%s %d Run OK================\n",__FUNCTION__,__LINE__);
217                 return 0;
218         }else{
219                 DBG("================%s %d Run EIO================\n",__FUNCTION__,__LINE__);
220                 return -EIO;
221         }
222 }
223
224 #ifdef CONFIG_MODEM_SOUND
225 static int rk610_codec_write_incall(struct snd_soc_codec *codec, unsigned int reg,
226         unsigned int value)
227 {
228         u8 data[2];
229         struct i2c_client *i2c;
230         DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n",__FUNCTION__,__LINE__, reg, value);
231         data[0] = value & 0x00ff;
232         rk610_codec_write_reg_cache (codec, reg, value);
233         i2c = (struct i2c_client *)codec->control_data;
234         i2c->addr = (i2c->addr & 0x60)|reg;
235
236         if (codec->hw_write(codec->control_data, data, 1) == 1)
237                 return 0;
238         else
239                 return -EIO;
240 }
241
242 void call_set_spk(int on)
243 {
244         struct rk610_codec_priv *rk610_codec;
245         if(!rk610_codec_codec)
246                 return;
247         rk610_codec = snd_soc_codec_get_drvdata(rk610_codec_codec);
248         if(!rk610_codec)
249                 return;
250                 
251         switch(on)
252         {
253         case 0:
254                 //modem exit call,codec disable loopback
255                 printk("%s modem exit call \n", __FUNCTION__);          
256                 rk610_codec_write_incall(rk610_codec_codec,ACCELCODEC_R0E, 0x80);
257                 rk610_codec->call_enable = 0;   
258                 break;
259         case 1:
260                 //modem calling,codec enable loopback,spk hp different volume
261                 printk("%s spk incalling\n", __FUNCTION__);
262                 rk610_codec->call_enable = 1;   
263                 rk610_codec_write_incall(rk610_codec_codec,ACCELCODEC_R0E, 0x00);
264                 return;
265         case 2:
266                 printk("%s hp incalling\n", __FUNCTION__);
267                 rk610_codec->call_enable = 1;
268                 rk610_codec_write_incall(rk610_codec_codec,ACCELCODEC_R0E, 0x00);       
269                 break;
270         case 3:
271                 printk("%s bt incalling\n", __FUNCTION__);    
272                 rk610_codec->call_enable = 1;   
273                 rk610_codec_write_incall(rk610_codec_codec,ACCELCODEC_R0E, 0x00);
274                 break;
275         }
276
277         return;
278 }
279 #endif
280 #ifdef CONFIG_RK_HEADSET_DET
281 //for headset
282 void rk2928_codec_set_spk(bool on)
283 {
284         struct rk610_codec_priv *rk610_codec;
285         if(!rk610_codec_codec)
286                 return;
287         rk610_codec=snd_soc_codec_get_drvdata(rk610_codec_codec);
288         if(!rk610_codec)
289                 return;
290                 
291         if(on)
292                 rk610_codec->headset_status = HP_IN;
293         else
294                 rk610_codec->headset_status = HP_OUT;
295                 
296         if(rk610_codec->call_enable)
297                 return;
298                 
299         printk("%s: headset %s %s PA bias_level=%d\n",__FUNCTION__,on?"in":"out",on?"disable":"enable",codec->dapm.bias_level);
300         if(on) {
301                 if(rk610_codec->spk_ctrl_io)
302                         gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_LOW);
303         }
304         else {
305                 if(codec->dapm.bias_level == SND_SOC_BIAS_STANDBY 
306                 || codec->dapm.bias_level == SND_SOC_BIAS_OFF){
307                         return;
308                 }
309                 if(rk610_codec->spk_ctrl_io)
310                         gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_HIGH);
311         }
312 }
313 #endif
314
315 void rk610_codec_reg_read(void)
316 {
317     struct snd_soc_codec *codec = rk610_codec_codec;
318     int i;
319     unsigned int data;
320
321     for (i=0; i<=0x1f; i++){
322         data = rk610_codec_read(codec, i);
323         printk("reg[0x%x]=0x%x\n",i,data);
324     }
325 }
326
327 struct _coeff_div {
328         u32 mclk;
329         u32 rate;
330         u16 fs;
331         u8 sr:5;
332         u8 usb:1;
333         u8 bclk;
334 };
335
336 /* codec hifi mclk clock divider coefficients */
337 static const struct _coeff_div coeff_div[] = {
338         /* 8k */
339         {12288000, 8000, 1536, 0x6, 0x0,ASC_BCLKDIV_16},
340         {11289600, 8000, 1408, 0x16, 0x0,ASC_BCLKDIV_16},
341         {18432000, 8000, 2304, 0x7, 0x0,ASC_BCLKDIV_16},
342         {16934400, 8000, 2112, 0x17, 0x0,ASC_BCLKDIV_16},
343         {8192000, 8000, 1024, 0x0, 0x0,ASC_BCLKDIV_16},
344         {12000000, 8000, 1500, 0x6, 0x1,ASC_BCLKDIV_16},
345
346         /* 11.025k */
347         {11289600, 11025, 1024, 0x18, 0x0,ASC_BCLKDIV_16},
348         {16934400, 11025, 1536, 0x19, 0x0,ASC_BCLKDIV_16},
349         {12000000, 11025, 1088, 0x19, 0x1,ASC_BCLKDIV_16},
350
351     /* 12k */
352         {12288000, 12000, 1024, 0x8, 0x0,ASC_BCLKDIV_16},
353         {18432000, 12000, 1536, 0x9, 0x0,ASC_BCLKDIV_16},
354         {12000000, 12000, 1000, 0x8, 0x1,ASC_BCLKDIV_16},
355
356         /* 16k */
357         {12288000, 16000, 768, 0xa, 0x0,ASC_BCLKDIV_8},
358         {18432000, 16000, 1152, 0xb, 0x0,ASC_BCLKDIV_8},
359         {12000000, 16000, 750, 0xa, 0x1,ASC_BCLKDIV_8},
360
361         /* 22.05k */
362         {11289600, 22050, 512, 0x1a, 0x0,ASC_BCLKDIV_8},
363         {16934400, 22050, 768, 0x1b, 0x0,ASC_BCLKDIV_8},
364         {12000000, 22050, 544, 0x1b, 0x1,ASC_BCLKDIV_8},
365
366     /* 24k */
367         {12288000, 24000, 512, 0x1c, 0x0,ASC_BCLKDIV_8},
368         {18432000, 24000, 768, 0x1d, 0x0,ASC_BCLKDIV_8},
369         {12000000, 24000, 500, 0x1c, 0x1,ASC_BCLKDIV_8},
370
371         /* 32k */
372         {12288000, 32000, 384, 0xc, 0x0,ASC_BCLKDIV_8},
373         {18432000, 32000, 576, 0xd, 0x0,ASC_BCLKDIV_8},
374         {12000000, 32000, 375, 0xa, 0x1,ASC_BCLKDIV_8},
375
376         /* 44.1k */
377         {11289600, 44100, 256, 0x10, 0x0,ASC_BCLKDIV_4},
378         {16934400, 44100, 384, 0x11, 0x0,ASC_BCLKDIV_8},
379         {12000000, 44100, 272, 0x11, 0x1,ASC_BCLKDIV_8},
380
381         /* 48k */
382         {12288000, 48000, 256, 0x0, 0x0,ASC_BCLKDIV_4},
383         {18432000, 48000, 384, 0x1, 0x0,ASC_BCLKDIV_4},
384         {12000000, 48000, 250, 0x0, 0x1,ASC_BCLKDIV_4},
385
386         /* 88.2k */
387         {11289600, 88200, 128, 0x1e, 0x0,ASC_BCLKDIV_4},
388         {16934400, 88200, 192, 0x1f, 0x0,ASC_BCLKDIV_4},
389         {12000000, 88200, 136, 0x1f, 0x1,ASC_BCLKDIV_4},
390
391         /* 96k */
392         {12288000, 96000, 128, 0xe, 0x0,ASC_BCLKDIV_4},
393         {18432000, 96000, 192, 0xf, 0x0,ASC_BCLKDIV_4},
394         {12000000, 96000, 125, 0xe, 0x1,ASC_BCLKDIV_4},
395 };
396
397 static inline int get_coeff(int mclk, int rate)
398 {
399         int i;
400
401         for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
402                 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
403                         return i;
404         }
405
406         return -EINVAL;
407 }
408
409 /* The set of rates we can generate from the above for each SYSCLK */
410
411 static unsigned int rates_12288[] = {
412         8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
413 };
414
415 static struct snd_pcm_hw_constraint_list constraints_12288 = {
416         .count  = ARRAY_SIZE(rates_12288),
417         .list   = rates_12288,
418 };
419
420 static unsigned int rates_112896[] = {
421         8000, 11025, 22050, 44100,
422 };
423
424 static struct snd_pcm_hw_constraint_list constraints_112896 = {
425         .count  = ARRAY_SIZE(rates_112896),
426         .list   = rates_112896,
427 };
428
429 static unsigned int rates_12[] = {
430         8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
431         48000, 88235, 96000,
432 };
433
434 static struct snd_pcm_hw_constraint_list constraints_12 = {
435         .count  = ARRAY_SIZE(rates_12),
436         .list   = rates_12,
437 };
438
439 static int rk610_codec_set_bias_level(struct snd_soc_codec *codec,
440                                  enum snd_soc_bias_level level)
441 {
442         struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
443         DBG("Enter::%s----%d now_level =%d  old_level = %d\n",__FUNCTION__,__LINE__,level,codec->dapm.bias_level);
444         switch (level) {
445         case SND_SOC_BIAS_ON:
446                 break;
447         case SND_SOC_BIAS_PREPARE:
448                 /* VREF, VMID=2x50k, digital enabled */
449         //      rk610_codec_write(codec, ACCELCODEC_R1D, pwr_reg | 0x0080);
450                 break;
451
452         case SND_SOC_BIAS_STANDBY:
453 #if RESUME_PROBLEM      
454                 if(rk610_codec->rk610_workstatus == SND_SOC_DAPM_STREAM_RESUME)
455                 {
456                         DBG("rk610 is resume,have not into standby\n");
457                         rk610_codec->rk610_workstatus = SND_SOC_DAPM_STREAM_NOP;
458                         break;
459                 }
460 #endif
461                 printk("rk610 standby\n");
462                 spk_ctrl_fun(GPIO_LOW);
463                 rk610_codec_write(codec,ACCELCODEC_R0A, ASC_CLK_DISABLE);
464                 rk610_codec_write(codec, ACCELCODEC_R1D, 0xFE);
465                 rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF);
466                 rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF);
467                 break;
468
469         case SND_SOC_BIAS_OFF:
470                 printk("rk610 power off\n");
471                 spk_ctrl_fun(GPIO_LOW);
472                 rk610_codec_write(codec,ACCELCODEC_R0A, ASC_CLK_DISABLE);               
473                 rk610_codec_write(codec, ACCELCODEC_R1D, 0xFF);
474                 rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF);
475                 rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF);
476                 break;
477         }
478
479         codec->dapm.bias_level = level;
480
481         return 0;
482 }
483
484 /*
485  * Note that this should be called from init rather than from hw_params.
486  */
487 static int rk610_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
488                 int clk_id, unsigned int freq, int dir)
489 {
490         struct snd_soc_codec *codec = codec_dai->codec;
491
492         struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
493
494         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
495
496 #if RK610_CTL_PLL
497         if(rk610_codec_pll_set(freq))
498                 return -EINVAL;
499 #endif
500         switch (freq) {
501         case 11289600:
502         case 18432000:
503         case 22579200:
504         case 36864000:
505                 rk610_codec->sysclk_constraints = &constraints_112896;
506                 rk610_codec->sysclk = freq;
507                 break;
508
509         case 12288000:
510         case 16934400:
511         case 24576000:
512         case 33868800:
513                 rk610_codec->sysclk_constraints = &constraints_12288;
514                 rk610_codec->sysclk = freq;
515                 break;
516
517         case 12000000:
518         case 24000000:
519                 rk610_codec->sysclk_constraints = &constraints_12;
520                 rk610_codec->sysclk = freq;
521                 break;
522         default:
523                 return -EINVAL;
524         }
525         return 0;
526 }
527
528 static int rk610_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
529                 unsigned int fmt)
530 {
531         struct snd_soc_codec *codec = codec_dai->codec;
532         struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
533         u16 iface = 0;
534
535 //modify 2013-06-27
536         if(rk610_codec->pa_enable_time<300)
537                 spk_ctrl_fun(GPIO_LOW);
538         else
539                 spk_ctrl_fun(GPIO_HIGH);
540         rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a);  //setup Vmid and Vref, other module power down
541         rk610_codec_write(codec,ACCELCODEC_R1E, 0x40);  ///|ASC_PDASDML_ENABLE);
542
543         /* set master/slave audio interface */
544         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
545         case SND_SOC_DAIFMT_CBM_CFM:
546                 iface = 0x0040;
547                 break;
548         case SND_SOC_DAIFMT_CBS_CFS:
549                 iface = 0x0000;
550                 break;
551         default:
552                 return -EINVAL;
553         }
554
555         /* interface format */
556         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
557         case SND_SOC_DAIFMT_I2S:
558                 iface |= 0x0002;
559                 break;
560         case SND_SOC_DAIFMT_RIGHT_J:
561                 break;
562         case SND_SOC_DAIFMT_LEFT_J:
563                 iface |= 0x0001;
564                 break;
565         case SND_SOC_DAIFMT_DSP_A:
566                 iface |= 0x0003;
567                 break;
568         case SND_SOC_DAIFMT_DSP_B:
569                 iface |= 0x0013;
570                 break;
571         default:
572                 return -EINVAL;
573         }
574
575         /* clock inversion */
576         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
577         case SND_SOC_DAIFMT_NB_NF:
578                 break;
579         case SND_SOC_DAIFMT_IB_IF:
580                 iface |= 0x0090;
581                 break;
582         case SND_SOC_DAIFMT_IB_NF:
583                 iface |= 0x0080;
584                 break;
585         case SND_SOC_DAIFMT_NB_IF:
586                 iface |= 0x0010;
587                 break;
588         default:
589                 return -EINVAL;
590         }
591
592         DBG("Enter::%s----%d  iface=%x\n",__FUNCTION__,__LINE__,iface);
593         rk610_codec_write(codec, ACCELCODEC_R09, iface);
594         return 0;
595 }
596
597 static int rk610_codec_pcm_hw_params(struct snd_pcm_substream *substream,
598                                 struct snd_pcm_hw_params *params,
599                                 struct snd_soc_dai *dai)
600 {
601         struct snd_soc_pcm_runtime *rtd = substream->private_data;
602         struct snd_soc_codec *codec = rtd->codec;
603         struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
604
605         u16 iface = rk610_codec_read_reg_cache(codec, ACCELCODEC_R09) & 0x1f3;
606         u16 srate = rk610_codec_read_reg_cache(codec, ACCELCODEC_R00) & 0x180;
607         int coeff;
608
609         coeff = get_coeff(rk610_codec->sysclk, params_rate(params));
610         DBG("Enter::%s----%d  rk610_codec->sysclk=%d coeff = %d\n",__FUNCTION__,__LINE__,rk610_codec->sysclk, coeff);
611         /* bit size */
612         switch (params_format(params)) {
613         case SNDRV_PCM_FORMAT_S16_LE:
614                 break;
615         case SNDRV_PCM_FORMAT_S20_3LE:
616                 iface |= 0x0004;
617                 break;
618         case SNDRV_PCM_FORMAT_S24_LE:
619                 iface |= 0x0008;
620                 break;
621         case SNDRV_PCM_FORMAT_S32_LE:
622                 iface |= 0x000c;
623                 break;
624         }
625         DBG("Enter::%s----%d  iface=%x srate =%x rate=%d\n",__FUNCTION__,__LINE__,iface,srate,params_rate(params));
626
627 //      rk610_codec_write(codec,ACCELCODEC_R0C, 0x17);
628         rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);   //soft mute
629         //±ØÐëÏȽ«clkºÍEN_INT¶¼disableµô£¬·ñÔòÇл»bclk·ÖƵֵ¿ÉÄܵ¼ÖÂcodecÄÚ²¿Ê±Ðò»ìÂÒµô£¬
630         //±íÏÖ³öÀ´µÄÏÖÏóÊÇ£¬ÒÔºóµÄÒôÀÖ¶¼±ä³ÉÁËÔëÒô£¬¶øÇÒ¾ÍËã°ÑÊäÈëcodecµÄI2S_DATAOUT¶Ï¿ªÒ²Ò»Ñù³öÔëÒô
631         rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE);  //0x00
632
633         /* set iface & srate */
634         #ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
635         iface |= ASC_INVERT_BCLK;//·­×ªBCLK  master״̬ËͳöµÄÉÙÁË°ë¸öʱÖÓ£¬µ¼ÖÂδµ½×î´óÒôÁ¿µÄʱºòÆÆÒô¡¢
636         #endif
637         rk610_codec_write(codec, ACCELCODEC_R09, iface);
638         if (coeff >= 0){
639         //    rk610_codec_write(codec, ACCELCODEC_R00, srate|coeff_div[coeff].bclk);
640                 rk610_codec_write(codec, ACCELCODEC_R0A, (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb|ASC_CLKNODIV|ASC_CLK_ENABLE);
641         }
642         rk610_codec_write(codec,ACCELCODEC_R0B, gR0BReg);
643
644         return 0;
645 }
646
647 static int rk610_codec_mute(struct snd_soc_dai *dai, int mute)
648 {
649     struct snd_soc_codec *codec = dai->codec;
650         struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
651     DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute);
652
653     if (mute)
654         {
655                 rk610_codec_write(codec,ACCELCODEC_R17, 0xFF);  //AOL
656                 rk610_codec_write(codec,ACCELCODEC_R18, 0xFF);  //AOR
657         rk610_codec_write(codec,ACCELCODEC_R19, 0xFF);  //AOM
658         rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);  //soft mute
659         //add for standby
660         //      if(!dai->capture_active)
661         //      {
662         //              rk610_codec_write(codec, ACCELCODEC_R1D, 0xFE);
663         //              rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF);
664         //              rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF);
665         //      }
666     }
667         else
668         {
669         //      rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a);  //setup Vmid and Vref, other module power down
670         //      rk610_codec_write(codec,ACCELCODEC_R1E, 0x40);  ///|ASC_PDASDML_ENABLE);
671                 rk610_codec_write(codec,ACCELCODEC_R17, Volume_Codec_PA|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN);  //AOL Volume_Codec_PA|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN);  //AOL
672                 rk610_codec_write(codec,ACCELCODEC_R18, Volume_Codec_PA|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //Volume_Codec_PA|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN);  //AOR
673         rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_ACTIVE_L|ASC_INT_ACTIVE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);
674                 rk610_codec_write(codec,ACCELCODEC_R19, 0x7F);  //AOM
675
676                 if(rk610_codec->pa_enable_time == 0)
677                         msleep(300);
678                 #if OUT_CAPLESS
679         rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE);
680         #else
681         rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE);
682                 #endif
683         //      schedule_delayed_work(&rk610_codec->rk610_delayed_work, 0);
684         //      rk610_codec_reg_read();
685                 if(rk610_codec->hdmi_ndet)
686                         if(rk610_codec->pa_enable_time == 0 )
687                                 spk_ctrl_fun(GPIO_HIGH);
688                         else if(rk610_codec->pa_enable_time > 0 && rk610_codec->pa_enable_time < 300){
689                                 spk_ctrl_fun(GPIO_HIGH);
690                                 msleep(rk610_codec->pa_enable_time)     ;
691                         }
692                         else if(rk610_codec->pa_enable_time >=300 && rk610_codec->pa_enable_time < 1000)
693                                 msleep(rk610_codec->pa_enable_time);
694     }
695
696     return 0;
697 }
698
699 static void rk610_delayedwork_fun(struct work_struct *work)
700 {
701     struct snd_soc_codec *codec = rk610_codec_codec;
702         struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); 
703         struct rk610_codec_platform_data *pdata= rk610_codec->pdata;    
704         DBG("--------%s----------\n",__FUNCTION__);
705         if(!pdata->boot_depop){
706                 #if OUT_CAPLESS
707                 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE);
708                 #else
709                 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE);
710                 #endif
711         }
712         spk_ctrl_fun(GPIO_HIGH);
713 }
714
715 static struct snd_soc_dai_ops rk610_codec_ops = {
716         .hw_params = rk610_codec_pcm_hw_params,
717         .set_fmt = rk610_codec_set_dai_fmt,
718         .set_sysclk = rk610_codec_set_dai_sysclk,
719         .digital_mute = rk610_codec_mute,
720 };
721
722 #define RK610_CODEC_RATES SNDRV_PCM_RATE_8000_96000
723 #define RK610_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
724                                                         SNDRV_PCM_FMTBIT_S24_LE)
725
726 static struct snd_soc_dai_driver rk610_codec_dai = {
727         .name = "rk610_codec",
728         .playback = {
729                 .stream_name = "Playback",
730                 .channels_min = 1,
731                 .channels_max = 2,
732                 .rates = RK610_CODEC_RATES,
733                 .formats = RK610_CODEC_FORMATS,
734         },
735         .capture = {
736                 .stream_name = "Capture",
737                 .channels_min = 1,
738                 .channels_max = 2,
739                 .rates = RK610_CODEC_RATES,
740                 .formats = RK610_CODEC_FORMATS,
741          },
742         .ops = &rk610_codec_ops,
743         .symmetric_rates = 1,
744 };
745
746 static int rk610_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
747 {
748         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
749         rk610_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
750 //      rk610_codec_reg_read();
751         return 0;
752 }
753
754 static int rk610_codec_resume(struct snd_soc_codec *codec)
755 {
756         struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
757
758         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
759         /* Sync reg_cache with the hardware */
760         
761 //      rk610_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
762 #if RESUME_PROBLEM
763         rk610_codec->rk610_workstatus = SND_SOC_DAPM_STREAM_RESUME;
764 #endif
765         return 0;
766 }
767
768 #define USE_MIC_IN
769 #define USE_LPF
770 void rk610_codec_reg_set(void)
771 {
772     struct snd_soc_codec *codec = rk610_codec_codec;
773         struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec); 
774         struct rk610_codec_platform_data *pdata= rk610_codec->pdata;
775     unsigned int digital_gain;
776         unsigned int mic_vol = Volume_Input;
777         rk610_codec_write(codec,ACCELCODEC_R1D, 0x30);
778         rk610_codec_write(codec,ACCELCODEC_R1E, 0x40);
779
780 #ifdef USE_LPF
781         // Route R-LPF->R-Mixer, L-LPF->L-Mixer
782         rk610_codec_write(codec,ACCELCODEC_R15, 0xC1);
783 #else
784         // Route RDAC->R-Mixer, LDAC->L->Mixer
785         rk610_codec_write(codec,ACCELCODEC_R15, 0x0C);
786 #endif
787         // With Cap Output, VMID ramp up slow
788         rk610_codec_write(codec,ACCELCODEC_R1A, 0x14);
789     mdelay(10);
790
791         rk610_codec_write(codec,ACCELCODEC_R0C, 0x10|ASC_INPUT_VOL_0DB);   //LIL
792     rk610_codec_write(codec,ACCELCODEC_R0D, 0x10|ASC_INPUT_VOL_0DB);   //LIR
793
794 #ifdef USE_MIC_IN
795         if(mic_vol > 0x07)
796         {
797                 rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT|ASC_MIC_BOOST_20DB);   //Select MIC input
798                 mic_vol -= 0x07;
799         }       
800         else
801                 rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT);   //Select MIC input
802     rk610_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE);  //0x00);  //use default value
803 #else
804     rk610_codec_write(codec,ACCELCODEC_R12, 0x4c);   //Select Line input
805 #endif
806
807     rk610_codec_write(codec,ACCELCODEC_R0E, 0x10|mic_vol);   //MIC
808         
809         // Diable route PGA->R/L Mixer, PGA gain 0db.
810     rk610_codec_write(codec,ACCELCODEC_R13, 0x05 | 0 << 3);
811     rk610_codec_write(codec,ACCELCODEC_R14, 0x05 | 0 << 3);
812
813     //2soft mute
814     rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);   //soft mute
815
816     //2set default SR and clk
817     rk610_codec_write(codec,ACCELCODEC_R0A, ASC_NORMAL_MODE|(0x10 << 1)|ASC_CLKNODIV|ASC_CLK_DISABLE);
818     gR0AReg = ASC_NORMAL_MODE|(0x10 << 1)|ASC_CLKNODIV|ASC_CLK_DISABLE;
819     //2Config audio  interface
820     rk610_codec_write(codec,ACCELCODEC_R09, ASC_I2S_MODE|ASC_16BIT_MODE|ASC_NORMAL_LRCLK|ASC_LRSWAP_DISABLE|ASC_NORMAL_BCLK);
821     rk610_codec_write(codec,ACCELCODEC_R00, ASC_HPF_ENABLE|ASC_DSM_MODE_ENABLE|ASC_SCRAMBLE_ENABLE|ASC_DITHER_ENABLE|ASC_BCLKDIV_4);
822     //2volume,input,output
823     digital_gain = Volume_Output;
824         
825         if(rk610_codec_read(codec,ACCELCODEC_R05)!=0x0f) {
826                 rk610_codec_write(codec,ACCELCODEC_R05, (digital_gain >> 8) & 0xFF);
827                 rk610_codec_write(codec,ACCELCODEC_R06, digital_gain & 0xFF);
828         }
829         if(rk610_codec_read(codec,ACCELCODEC_R07)!=0x0f){
830                 rk610_codec_write(codec,ACCELCODEC_R07, (digital_gain >> 8) & 0xFF);
831                 rk610_codec_write(codec,ACCELCODEC_R08, digital_gain & 0xFF);
832         }
833     rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_ENABLE|ASC_INT_ENABLE);
834     gR0BReg = ASC_DEC_ENABLE|ASC_INT_ENABLE;  //ASC_DEC_DISABLE|ASC_INT_ENABLE;
835
836         if(pdata->boot_depop){
837                 #if OUT_CAPLESS
838                 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE);
839                 #else
840                 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE);
841                 #endif
842         }       
843 }
844
845 #ifdef RK610_PROC       
846 static int RK610_PROC_init(void);
847 #endif
848
849 static int rk610_codec_probe(struct snd_soc_codec *codec)
850 {
851         struct rk610_codec_priv *rk610_codec = snd_soc_codec_get_drvdata(codec);
852         int ret;
853
854 #ifdef RK610_PROC       
855         RK610_PROC_init();
856 #endif  
857         rk610_codec_codec = codec;
858         DBG("[%s] start\n", __FUNCTION__);
859         ret = snd_soc_codec_set_cache_io(codec, 8, 16, rk610_codec->control_type);
860         if (ret != 0) {
861                 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
862                 return ret;
863         }
864         //For RK610, i2c write&read method is special, do not use system default method.
865         codec->write = rk610_codec_write;
866         codec->read = rk610_codec_read;
867         codec->hw_write = (hw_write_t)i2c_master_send;
868
869         if (rk610_codec_codec == NULL) {
870                 dev_err(codec->dev, "Codec device not registered\n");
871                 return -ENODEV;
872         }
873
874         INIT_DELAYED_WORK(&rk610_codec->rk610_delayed_work, rk610_delayedwork_fun);
875         
876         if(rk610_codec->spk_ctrl_io)
877         {
878                 ret = gpio_request(rk610_codec->spk_ctrl_io, "rk610 spk_ctrl");
879             if (ret){
880                 printk("rk610_control request gpio fail!\n");
881                         return ret;
882             }
883             gpio_direction_output(rk610_codec->spk_ctrl_io, GPIO_LOW);
884             gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_LOW); 
885         }
886         
887         rk610_codec->hdmi_ndet = true;
888         rk610_codec->call_enable = 0;
889         rk610_codec->headset_status = HP_OUT;
890 #if RESUME_PROBLEM      
891         rk610_codec->rk610_workstatus = SND_SOC_DAPM_STREAM_NOP;
892 #endif
893         
894     rk610_control_init_codec();
895     rk610_codec_reg_set();
896 //      rk610_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
897         schedule_delayed_work(&rk610_codec->rk610_delayed_work, msecs_to_jiffies(1000));
898
899         codec->dapm.bias_level = SND_SOC_BIAS_PREPARE;
900         return ret;
901 }
902
903 /* power down chip */
904 static int rk610_codec_remove(struct snd_soc_codec *codec)
905 {
906         rk610_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
907         return 0;
908 }
909
910 static struct snd_soc_codec_driver soc_codec_dev_rk610_codec = {
911         .probe =        rk610_codec_probe,
912         .remove =       rk610_codec_remove,
913         .suspend =      rk610_codec_suspend,
914         .resume =       rk610_codec_resume,
915         .set_bias_level = rk610_codec_set_bias_level,
916 //      .volatile_register = wm8900_volatile_register,
917         .reg_cache_size = ARRAY_SIZE(rk610_codec_reg),
918         .reg_word_size = sizeof(u16),
919         .reg_cache_default = rk610_codec_reg,
920 //      .dapm_widgets = rk610_codec_dapm_widgets,
921 //      .num_dapm_widgets = ARRAY_SIZE(rk610_codec_dapm_widgets),
922 //      .dapm_routes = audio_map,
923 //      .num_dapm_routes = ARRAY_SIZE(audio_map),
924 };
925
926 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
927 static int rk610_codec_i2c_probe(struct i2c_client *i2c,
928                             const struct i2c_device_id *id)
929 {
930         struct rk610_codec_priv *rk610_codec;
931         struct rk610_codec_platform_data *pdata = i2c->dev.platform_data;
932         int ret;
933         DBG("%s start\n", __FUNCTION__);
934         rk610_codec = kzalloc(sizeof(struct rk610_codec_priv), GFP_KERNEL);
935         if (rk610_codec == NULL)
936                 return -ENOMEM;
937 //qjb 2013-01-14
938         rk610_codec->pdata = pdata;
939         rk610_codec->spk_ctrl_io = pdata->spk_ctl_io;
940 //qjb 2013-06-27        
941         rk610_codec->pa_enable_time = pdata->pa_enable_time;
942         if(rk610_codec->pa_enable_time > 1000)
943                 rk610_codec->pa_enable_time = 1000;
944         if(pdata->io_init){
945                 ret =  pdata->io_init();
946                 if (ret < 0) {
947                         dev_err(&i2c->dev, "Failed to register codec pdata io_init error: %d\n", ret);
948                         kfree(rk610_codec);
949                         return ret;
950                 }
951         }
952         
953         i2c_set_clientdata(i2c, rk610_codec);
954         rk610_codec->control_type = SND_SOC_I2C;
955
956         ret =  snd_soc_register_codec(&i2c->dev,
957                         &soc_codec_dev_rk610_codec, &rk610_codec_dai, 1);
958         if (ret < 0) {
959                 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
960                 kfree(rk610_codec);
961         }
962         return ret;
963 }
964
965 static int rk610_codec_i2c_remove(struct i2c_client *client)
966 {
967         snd_soc_unregister_codec(&client->dev);
968         kfree(i2c_get_clientdata(client));
969         return 0;
970 }
971
972 static const struct i2c_device_id rk610_codec_i2c_id[] = {
973         { "rk610_i2c_codec", 0 },
974         { }
975 };
976 MODULE_DEVICE_TABLE(i2c, rk610_codec_i2c_id);
977
978 /* corgi i2c codec control layer */
979 static struct i2c_driver rk610_codec_i2c_driver = {
980         .driver = {
981                 .name = "RK610_CODEC",
982                 .owner = THIS_MODULE,
983         },
984         .probe = rk610_codec_i2c_probe,
985         .remove = rk610_codec_i2c_remove,
986         .id_table = rk610_codec_i2c_id,
987 };
988 #endif
989
990 static int __init rk610_codec_modinit(void)
991 {
992         int ret;
993         DBG("[%s] start\n", __FUNCTION__);
994         ret = i2c_add_driver(&rk610_codec_i2c_driver);
995         if (ret != 0)
996                 pr_err("rk610 codec: Unable to register I2C driver: %d\n", ret);
997         return ret;
998 }
999 module_init(rk610_codec_modinit);
1000
1001 static void __exit rk610_codec_exit(void)
1002 {
1003         i2c_del_driver(&rk610_codec_i2c_driver);
1004 }
1005 module_exit(rk610_codec_exit);
1006
1007 MODULE_DESCRIPTION("ASoC RK610 CODEC driver");
1008 MODULE_AUTHOR("rk@rock-chips.com");
1009 MODULE_LICENSE("GPL");
1010
1011 //=====================================================================
1012 //Proc
1013 #ifdef RK610_PROC
1014 static ssize_t RK610_PROC_write(struct file *file, const char __user *buffer,
1015                            unsigned long len, void *data)
1016 {
1017         char *cookie_pot; 
1018         char *p;
1019         int reg;
1020         int value;
1021         struct rk610_codec_priv *rk610_codec = snd_soc_codec_get_drvdata(rk610_codec_codec);
1022
1023         cookie_pot = (char *)vmalloc( len );
1024         if (!cookie_pot) 
1025         {
1026                 return -ENOMEM;
1027         } 
1028         else 
1029         {
1030                 if (copy_from_user( cookie_pot, buffer, len )) 
1031                         return -EFAULT;
1032         }
1033
1034         switch(cookie_pot[0])
1035         {
1036         case 'p':
1037                 spk_ctrl_fun(GPIO_HIGH);
1038                 break;
1039         case 'o':
1040                 spk_ctrl_fun(GPIO_LOW);
1041                 break;  
1042         case 'r':
1043         case 'R':
1044                 printk("Read reg debug\n");             
1045                 if(cookie_pot[1] ==':')
1046                 {
1047                         strsep(&cookie_pot,":");
1048                         while((p=strsep(&cookie_pot,",")))
1049                         {
1050                                 reg = simple_strtol(p,NULL,16);
1051                                 value = rk610_codec_read(rk610_codec_codec,reg);
1052                                 printk("wm8994_read:0x%04x = 0x%04x\n",reg,value);
1053                         }
1054                         printk("\n");
1055                 }
1056                 else
1057                 {
1058                         printk("Error Read reg debug.\n");
1059                         printk("For example: echo 'r:22,23,24,25'>wm8994_ts\n");
1060                 }
1061                 break;
1062         case 'w':
1063         case 'W':
1064                 printk("Write reg debug\n");            
1065                 if(cookie_pot[1] ==':')
1066                 {
1067                         strsep(&cookie_pot,":");
1068                         while((p=strsep(&cookie_pot,"=")))
1069                         {
1070                                 reg = simple_strtol(p,NULL,16);
1071                                 p=strsep(&cookie_pot,",");
1072                                 value = simple_strtol(p,NULL,16);
1073                                 rk610_codec_write(rk610_codec_codec,reg,value);
1074                                 printk("wm8994_write:0x%04x = 0x%04x\n",reg,value);
1075                         }
1076                         printk("\n");
1077                 }
1078                 else
1079                 {
1080                         printk("Error Write reg debug.\n");
1081                         printk("For example: w:22=0,23=0,24=0,25=0\n");
1082                 }
1083                 break;  
1084         case 'D' :
1085                 printk("Dump reg\n");
1086                 rk610_codec_reg_read();
1087                 break;
1088         case 't' :
1089                 printk("old pa_enable_time = %d\n",rk610_codec->pa_enable_time);
1090                 if(cookie_pot[1] ==':')
1091                 {
1092                         strsep(&cookie_pot,":");
1093                         p=strsep(&cookie_pot," ");
1094                         rk610_codec->pa_enable_time = simple_strtol(p,NULL,10);
1095                         printk("new pa_enable_time = %d\n",rk610_codec->pa_enable_time);
1096                 }
1097                 break;          
1098         }
1099
1100         return len;
1101 }
1102
1103 static int RK610_PROC_init(void)
1104 {
1105         struct proc_dir_entry *RK610_PROC_entry;
1106         RK610_PROC_entry = create_proc_entry("driver/rk610_ts", 0777, NULL);
1107         if(RK610_PROC_entry != NULL)
1108         {
1109                 RK610_PROC_entry->write_proc = RK610_PROC_write;
1110                 return -1;
1111         }
1112         else
1113         {
1114                 printk("create proc error !\n");
1115         }
1116         return 0;
1117 }
1118
1119 #endif