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