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