2 * rk610.c -- RK610 ALSA SoC audio driver
4 * Copyright (C) 2009 rockchip lhh
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.
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/init.h>
17 #include <linux/delay.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>
36 #include <linux/proc_fs.h>
37 #include <linux/seq_file.h>
38 #include <linux/vmalloc.h>
41 //if you find resume rk610 cannot work,you can try RESUME_PROBLEM 1.
42 //if rk610 Normal working on RESUME_PROBLEM 1, you must detect Machine other driver queue.
43 //you can look soc-core.c the resume source.s
44 #define RESUME_PROBLEM 0
46 //old control method,please filling rk610_codec_platform_data into Board-xx-xx.c
49 #if defined(CONFIG_MACH_RK3168_DS1006H)|| defined(CONFIG_MACH_RK3168_LR097)
50 #define RK610_SPK_CTRL_PIN RK30_PIN2_PD7
51 #elif defined(CONFIG_ARCH_RK3066B)
52 #define RK610_SPK_CTRL_PIN RK30_PIN2_PA0
53 #elif defined(CONFIG_ARCH_RK30)
54 #define RK610_SPK_CTRL_PIN RK30_PIN4_PC6
56 #define RK610_SPK_CTRL_PIN RK29_PIN6_PB6
60 //1:set pll from rk610
61 #define RK610_CTL_PLL 0
67 #define DBG(x...) printk(KERN_INFO x)
72 //it can change rk610 output volume
74 #define Volume_Output 0xF42
75 //it can change rk610 input volume
77 #define Volume_Input 0x07
79 #define OUT_CAPLESS (1) //ÊÇ·ñΪÎÞµçÈÝÊä³ö£¬1:ÎÞµçÈÝÊä³ö£¬0:ÓеçÈÝÊä³ö
81 static u32 gVolReg = 0x00; ///0x0f; //ÓÃÓڼǼÒôÁ¿¼Ä´æÆ÷
82 //static u32 gCodecVol = 0x0f;
83 static u8 gR0AReg = 0; //ÓÃÓڼǼR0A¼Ä´æÆ÷µÄÖµ£¬ÓÃÓڸıä²ÉÑùÂÊǰͨ¹ýR0AÍ£Ö¹clk
84 static u8 gR0BReg = 0; //ÓÃÓڼǼR0B¼Ä´æÆ÷µÄÖµ£¬ÓÃÓڸıä²ÉÑùÂÊǰͨ¹ýR0BÍ£Ö¹interplateºÍdecimation
85 //static u8 gR1314Reg = 0; //ÓÃÓڼǼR13,R14¼Ä´æÆ÷µÄÖµ£¬ÓÃÓÚFMÒôÁ¿Îª0ʱ
88 * rk610 register cache
89 * We can't read the RK610 register space when we
90 * are using 2 wire for device control, so we cache them instead.
92 static const u16 rk610_codec_reg[] = {
93 0x0005, 0x0004, 0x00fd, 0x00f3, /* 0 */
94 0x0003, 0x0000, 0x0000, 0x0000, /* 4 */
95 0x0000, 0x0005, 0x0000, 0x0000, /* 8 */
96 0x0097, 0x0097, 0x0097, 0x0097, /* 12 */
97 0x0097, 0x0097, 0x00cc, 0x0000, /* 16 */
98 0x0000, 0x00f1, 0x0090, 0x00ff, /* 20 */
99 0x00ff, 0x00ff, 0x009c, 0x0000, /* 24 */
100 0x0000, 0x00ff, 0x00ff, 0x00ff, /* 28 */
103 static struct snd_soc_codec *rk610_codec_codec=NULL;
104 /* codec private data */
105 struct rk610_codec_priv {
106 enum snd_soc_control_type control_type;
108 struct snd_soc_codec codec;
109 struct snd_pcm_hw_constraint_list *sysclk_constraints;
110 u16 reg_cache[RK610_CODEC_NUM_REG];
112 struct delayed_work rk610_delayed_work;
113 unsigned int spk_ctrl_io;
116 int rk610_workstatus;
118 struct rk610_codec_platform_data *pdata;
121 void codec_set_spk(bool on)
123 struct rk610_codec_priv *rk610_codec;
124 if(!rk610_codec_codec)
127 rk610_codec=snd_soc_codec_get_drvdata(rk610_codec_codec);
131 rk610_codec->hdmi_ndet = on;
133 gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_HIGH);
135 gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_LOW);
137 EXPORT_SYMBOL(codec_set_spk);
140 * read rk610 register cache
142 static inline unsigned int rk610_codec_read_reg_cache(struct snd_soc_codec *codec,
145 u16 *cache = codec->reg_cache;
146 if (reg > RK610_CACHE_REGNUM)
151 static unsigned int rk610_codec_read(struct snd_soc_codec *codec, unsigned int r)
153 struct i2c_msg xfer[1];
156 struct i2c_client *client = codec->control_data;
159 xfer[0].addr = (client->addr& 0x60)|(reg);
160 xfer[0].flags = I2C_M_RD;
163 xfer[0].scl_rate = 100000;
164 ret = i2c_transfer(client->adapter, xfer, 1);
166 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
174 * write rk610 register cache
176 static inline void rk610_codec_write_reg_cache(struct snd_soc_codec *codec,
177 unsigned int reg, unsigned int value)
179 u16 *cache = codec->reg_cache;
180 if (reg > RK610_CACHE_REGNUM)
185 static int rk610_codec_write(struct snd_soc_codec *codec, unsigned int reg,
189 struct i2c_client *i2c;
190 DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n",__FUNCTION__,__LINE__, reg, value);
191 data[0] = value & 0x00ff;
192 rk610_codec_write_reg_cache (codec, reg, value);
193 i2c = (struct i2c_client *)codec->control_data;
194 i2c->addr = (i2c->addr & 0x60)|reg;
196 if (codec->hw_write(codec->control_data, data, 1) == 1){
197 // DBG("================%s %d Run OK================\n",__FUNCTION__,__LINE__);
200 DBG("================%s %d Run EIO================\n",__FUNCTION__,__LINE__);
205 void rk610_codec_reg_read(void)
207 struct snd_soc_codec *codec = rk610_codec_codec;
211 for (i=0; i<=0x1f; i++){
212 data = rk610_codec_read(codec, i);
213 printk("reg[0x%x]=0x%x\n",i,data);
217 static void spk_ctrl_fun(int status)
219 struct rk610_codec_priv *rk610_codec = NULL;
220 if(rk610_codec_codec == NULL)
222 rk610_codec = snd_soc_codec_get_drvdata(rk610_codec_codec);
223 if(rk610_codec == NULL)
226 if(rk610_codec->spk_ctrl_io)
228 DBG("--------%s----------status = %d\n",__FUNCTION__,status);
229 gpio_set_value(rk610_codec->spk_ctrl_io, status);
242 /* codec hifi mclk clock divider coefficients */
243 static const struct _coeff_div coeff_div[] = {
245 {12288000, 8000, 1536, 0x6, 0x0,ASC_BCLKDIV_16},
246 {11289600, 8000, 1408, 0x16, 0x0,ASC_BCLKDIV_16},
247 {18432000, 8000, 2304, 0x7, 0x0,ASC_BCLKDIV_16},
248 {16934400, 8000, 2112, 0x17, 0x0,ASC_BCLKDIV_16},
249 {8192000, 8000, 1024, 0x0, 0x0,ASC_BCLKDIV_16},
250 {12000000, 8000, 1500, 0x6, 0x1,ASC_BCLKDIV_16},
253 {11289600, 11025, 1024, 0x18, 0x0,ASC_BCLKDIV_16},
254 {16934400, 11025, 1536, 0x19, 0x0,ASC_BCLKDIV_16},
255 {12000000, 11025, 1088, 0x19, 0x1,ASC_BCLKDIV_16},
258 {12288000, 12000, 1024, 0x8, 0x0,ASC_BCLKDIV_16},
259 {18432000, 12000, 1536, 0x9, 0x0,ASC_BCLKDIV_16},
260 {12000000, 12000, 1000, 0x8, 0x1,ASC_BCLKDIV_16},
263 {12288000, 16000, 768, 0xa, 0x0,ASC_BCLKDIV_8},
264 {18432000, 16000, 1152, 0xb, 0x0,ASC_BCLKDIV_8},
265 {12000000, 16000, 750, 0xa, 0x1,ASC_BCLKDIV_8},
268 {11289600, 22050, 512, 0x1a, 0x0,ASC_BCLKDIV_8},
269 {16934400, 22050, 768, 0x1b, 0x0,ASC_BCLKDIV_8},
270 {12000000, 22050, 544, 0x1b, 0x1,ASC_BCLKDIV_8},
273 {12288000, 24000, 512, 0x1c, 0x0,ASC_BCLKDIV_8},
274 {18432000, 24000, 768, 0x1d, 0x0,ASC_BCLKDIV_8},
275 {12000000, 24000, 500, 0x1c, 0x1,ASC_BCLKDIV_8},
278 {12288000, 32000, 384, 0xc, 0x0,ASC_BCLKDIV_8},
279 {18432000, 32000, 576, 0xd, 0x0,ASC_BCLKDIV_8},
280 {12000000, 32000, 375, 0xa, 0x1,ASC_BCLKDIV_8},
283 {11289600, 44100, 256, 0x10, 0x0,ASC_BCLKDIV_4},
284 {16934400, 44100, 384, 0x11, 0x0,ASC_BCLKDIV_8},
285 {12000000, 44100, 272, 0x11, 0x1,ASC_BCLKDIV_8},
288 {12288000, 48000, 256, 0x0, 0x0,ASC_BCLKDIV_4},
289 {18432000, 48000, 384, 0x1, 0x0,ASC_BCLKDIV_4},
290 {12000000, 48000, 250, 0x0, 0x1,ASC_BCLKDIV_4},
293 {11289600, 88200, 128, 0x1e, 0x0,ASC_BCLKDIV_4},
294 {16934400, 88200, 192, 0x1f, 0x0,ASC_BCLKDIV_4},
295 {12000000, 88200, 136, 0x1f, 0x1,ASC_BCLKDIV_4},
298 {12288000, 96000, 128, 0xe, 0x0,ASC_BCLKDIV_4},
299 {18432000, 96000, 192, 0xf, 0x0,ASC_BCLKDIV_4},
300 {12000000, 96000, 125, 0xe, 0x1,ASC_BCLKDIV_4},
303 static inline int get_coeff(int mclk, int rate)
307 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
308 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
315 /* The set of rates we can generate from the above for each SYSCLK */
317 static unsigned int rates_12288[] = {
318 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
321 static struct snd_pcm_hw_constraint_list constraints_12288 = {
322 .count = ARRAY_SIZE(rates_12288),
326 static unsigned int rates_112896[] = {
327 8000, 11025, 22050, 44100,
330 static struct snd_pcm_hw_constraint_list constraints_112896 = {
331 .count = ARRAY_SIZE(rates_112896),
332 .list = rates_112896,
335 static unsigned int rates_12[] = {
336 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
340 static struct snd_pcm_hw_constraint_list constraints_12 = {
341 .count = ARRAY_SIZE(rates_12),
345 static int rk610_codec_set_bias_level(struct snd_soc_codec *codec,
346 enum snd_soc_bias_level level)
348 struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
349 DBG("Enter::%s----%d now_level =%d old_level = %d\n",__FUNCTION__,__LINE__,level,codec->dapm.bias_level);
351 case SND_SOC_BIAS_ON:
353 case SND_SOC_BIAS_PREPARE:
354 /* VREF, VMID=2x50k, digital enabled */
355 // rk610_codec_write(codec, ACCELCODEC_R1D, pwr_reg | 0x0080);
358 case SND_SOC_BIAS_STANDBY:
360 if(rk610_codec->rk610_workstatus == SND_SOC_DAPM_STREAM_RESUME)
362 DBG("rk610 is resume,have not into standby\n");
363 rk610_codec->rk610_workstatus = SND_SOC_DAPM_STREAM_NOP;
367 printk("rk610 standby\n");
368 spk_ctrl_fun(GPIO_LOW);
369 rk610_codec_write(codec,ACCELCODEC_R0A, ASC_CLK_DISABLE);
370 rk610_codec_write(codec, ACCELCODEC_R1D, 0xFE);
371 rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF);
372 rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF);
375 case SND_SOC_BIAS_OFF:
376 printk("rk610 power off\n");
377 spk_ctrl_fun(GPIO_LOW);
378 rk610_codec_write(codec, ACCELCODEC_R1D, 0xFF);
379 rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF);
380 rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF);
384 codec->dapm.bias_level = level;
390 * Note that this should be called from init rather than from hw_params.
392 static int rk610_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
393 int clk_id, unsigned int freq, int dir)
395 struct snd_soc_codec *codec = codec_dai->codec;
397 struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
399 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
402 if(rk610_codec_pll_set(freq))
410 rk610_codec->sysclk_constraints = &constraints_112896;
411 rk610_codec->sysclk = freq;
418 rk610_codec->sysclk_constraints = &constraints_12288;
419 rk610_codec->sysclk = freq;
424 rk610_codec->sysclk_constraints = &constraints_12;
425 rk610_codec->sysclk = freq;
433 static int rk610_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
436 struct snd_soc_codec *codec = codec_dai->codec;
437 struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
440 spk_ctrl_fun(GPIO_LOW);
441 rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a); //setup Vmid and Vref, other module power down
442 rk610_codec_write(codec,ACCELCODEC_R1E, 0x40); ///|ASC_PDASDML_ENABLE);
444 /* set master/slave audio interface */
445 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
446 case SND_SOC_DAIFMT_CBM_CFM:
449 case SND_SOC_DAIFMT_CBS_CFS:
456 /* interface format */
457 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
458 case SND_SOC_DAIFMT_I2S:
461 case SND_SOC_DAIFMT_RIGHT_J:
463 case SND_SOC_DAIFMT_LEFT_J:
466 case SND_SOC_DAIFMT_DSP_A:
469 case SND_SOC_DAIFMT_DSP_B:
476 /* clock inversion */
477 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
478 case SND_SOC_DAIFMT_NB_NF:
480 case SND_SOC_DAIFMT_IB_IF:
483 case SND_SOC_DAIFMT_IB_NF:
486 case SND_SOC_DAIFMT_NB_IF:
493 DBG("Enter::%s----%d iface=%x\n",__FUNCTION__,__LINE__,iface);
494 rk610_codec_write(codec, ACCELCODEC_R09, iface);
498 static int rk610_codec_pcm_hw_params(struct snd_pcm_substream *substream,
499 struct snd_pcm_hw_params *params,
500 struct snd_soc_dai *dai)
502 struct snd_soc_pcm_runtime *rtd = substream->private_data;
503 struct snd_soc_codec *codec = rtd->codec;
504 struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
506 u16 iface = rk610_codec_read_reg_cache(codec, ACCELCODEC_R09) & 0x1f3;
507 u16 srate = rk610_codec_read_reg_cache(codec, ACCELCODEC_R00) & 0x180;
510 coeff = get_coeff(rk610_codec->sysclk, params_rate(params));
511 DBG("Enter::%s----%d rk610_codec->sysclk=%d coeff = %d\n",__FUNCTION__,__LINE__,rk610_codec->sysclk, coeff);
513 switch (params_format(params)) {
514 case SNDRV_PCM_FORMAT_S16_LE:
516 case SNDRV_PCM_FORMAT_S20_3LE:
519 case SNDRV_PCM_FORMAT_S24_LE:
522 case SNDRV_PCM_FORMAT_S32_LE:
526 DBG("Enter::%s----%d iface=%x srate =%x rate=%d\n",__FUNCTION__,__LINE__,iface,srate,params_rate(params));
528 // rk610_codec_write(codec,ACCELCODEC_R0C, 0x17);
529 rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute
530 //±ØÐëÏȽ«clkºÍEN_INT¶¼disableµô£¬·ñÔòÇл»bclk·ÖƵֵ¿ÉÄܵ¼ÖÂcodecÄÚ²¿Ê±Ðò»ìÂÒµô£¬
531 //±íÏÖ³öÀ´µÄÏÖÏóÊÇ£¬ÒÔºóµÄÒôÀÖ¶¼±ä³ÉÁËÔëÒô£¬¶øÇÒ¾ÍËã°ÑÊäÈëcodecµÄI2S_DATAOUT¶Ï¿ªÒ²Ò»Ñù³öÔëÒô
532 rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE); //0x00
534 /* set iface & srate */
535 #ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
536 iface |= ASC_INVERT_BCLK;//·×ªBCLK master״̬ËͳöµÄÉÙÁË°ë¸öʱÖÓ£¬µ¼ÖÂδµ½×î´óÒôÁ¿µÄʱºòÆÆÒô¡¢
538 rk610_codec_write(codec, ACCELCODEC_R09, iface);
540 // rk610_codec_write(codec, ACCELCODEC_R00, srate|coeff_div[coeff].bclk);
541 rk610_codec_write(codec, ACCELCODEC_R0A, (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb|ASC_CLKNODIV|ASC_CLK_ENABLE);
543 rk610_codec_write(codec,ACCELCODEC_R0B, gR0BReg);
548 static int rk610_codec_mute(struct snd_soc_dai *dai, int mute)
550 struct snd_soc_codec *codec = dai->codec;
551 struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
552 DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute);
556 rk610_codec_write(codec,ACCELCODEC_R17, 0xFF); //AOL
557 rk610_codec_write(codec,ACCELCODEC_R18, 0xFF); //AOR
558 rk610_codec_write(codec,ACCELCODEC_R19, 0xFF); //AOM
559 rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute
561 // if(!dai->capture_active)
563 // rk610_codec_write(codec, ACCELCODEC_R1D, 0xFE);
564 // rk610_codec_write(codec, ACCELCODEC_R1E, 0xFF);
565 // rk610_codec_write(codec, ACCELCODEC_R1F, 0xFF);
570 // rk610_codec_write(codec,ACCELCODEC_R1D, 0x2a); //setup Vmid and Vref, other module power down
571 // rk610_codec_write(codec,ACCELCODEC_R1E, 0x40); ///|ASC_PDASDML_ENABLE);
572 rk610_codec_write(codec,ACCELCODEC_R17, gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOL
573 rk610_codec_write(codec,ACCELCODEC_R18, gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //AOR
574 rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_ACTIVE_L|ASC_INT_ACTIVE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);
575 rk610_codec_write(codec,ACCELCODEC_R19, 0x7F); //AOM
578 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE);
580 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE);
582 // schedule_delayed_work(&rk610_codec->rk610_delayed_work, 0);
583 // rk610_codec_reg_read();
584 if(rk610_codec->hdmi_ndet)
585 spk_ctrl_fun(GPIO_HIGH);
591 static void rk610_delayedwork_fun(struct work_struct *work)
593 struct snd_soc_codec *codec = rk610_codec_codec;
594 struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
595 struct rk610_codec_platform_data *pdata= rk610_codec->pdata;
596 DBG("--------%s----------\n",__FUNCTION__);
597 if(!pdata->boot_depop){
599 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE);
601 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE);
604 spk_ctrl_fun(GPIO_HIGH);
607 static struct snd_soc_dai_ops rk610_codec_ops = {
608 .hw_params = rk610_codec_pcm_hw_params,
609 .set_fmt = rk610_codec_set_dai_fmt,
610 .set_sysclk = rk610_codec_set_dai_sysclk,
611 .digital_mute = rk610_codec_mute,
614 #define RK610_CODEC_RATES SNDRV_PCM_RATE_8000_96000
615 #define RK610_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
616 SNDRV_PCM_FMTBIT_S24_LE)
618 static struct snd_soc_dai_driver rk610_codec_dai = {
619 .name = "rk610_codec",
621 .stream_name = "Playback",
624 .rates = RK610_CODEC_RATES,
625 .formats = RK610_CODEC_FORMATS,
628 .stream_name = "Capture",
631 .rates = RK610_CODEC_RATES,
632 .formats = RK610_CODEC_FORMATS,
634 .ops = &rk610_codec_ops,
635 .symmetric_rates = 1,
638 static int rk610_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
640 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
641 rk610_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
642 // rk610_codec_reg_read();
646 static int rk610_codec_resume(struct snd_soc_codec *codec)
648 struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
650 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
651 /* Sync reg_cache with the hardware */
653 // rk610_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
655 rk610_codec->rk610_workstatus = SND_SOC_DAPM_STREAM_RESUME;
662 void rk610_codec_reg_set(void)
664 struct snd_soc_codec *codec = rk610_codec_codec;
665 struct rk610_codec_priv *rk610_codec =snd_soc_codec_get_drvdata(codec);
666 struct rk610_codec_platform_data *pdata= rk610_codec->pdata;
667 unsigned int digital_gain;
668 unsigned int mic_vol = Volume_Input;
669 rk610_codec_write(codec,ACCELCODEC_R1D, 0x30);
670 rk610_codec_write(codec,ACCELCODEC_R1E, 0x40);
673 // Route R-LPF->R-Mixer, L-LPF->L-Mixer
674 rk610_codec_write(codec,ACCELCODEC_R15, 0xC1);
676 // Route RDAC->R-Mixer, LDAC->L->Mixer
677 rk610_codec_write(codec,ACCELCODEC_R15, 0x0C);
679 // With Cap Output, VMID ramp up slow
680 rk610_codec_write(codec,ACCELCODEC_R1A, 0x14);
683 rk610_codec_write(codec,ACCELCODEC_R0C, 0x10|ASC_INPUT_VOL_0DB); //LIL
684 rk610_codec_write(codec,ACCELCODEC_R0D, 0x10|ASC_INPUT_VOL_0DB); //LIR
689 rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT|ASC_MIC_BOOST_20DB); //Select MIC input
693 rk610_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT); //Select MIC input
694 rk610_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE); //0x00); //use default value
696 rk610_codec_write(codec,ACCELCODEC_R12, 0x4c); //Select Line input
699 rk610_codec_write(codec,ACCELCODEC_R0E, 0x10|mic_vol); //MIC
701 // Diable route PGA->R/L Mixer, PGA gain 0db.
702 rk610_codec_write(codec,ACCELCODEC_R13, 0x05 | 0 << 3);
703 rk610_codec_write(codec,ACCELCODEC_R14, 0x05 | 0 << 3);
706 rk610_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF); //soft mute
708 //2set default SR and clk
709 rk610_codec_write(codec,ACCELCODEC_R0A, ASC_NORMAL_MODE|(0x10 << 1)|ASC_CLKNODIV|ASC_CLK_DISABLE);
710 gR0AReg = ASC_NORMAL_MODE|(0x10 << 1)|ASC_CLKNODIV|ASC_CLK_DISABLE;
711 //2Config audio interface
712 rk610_codec_write(codec,ACCELCODEC_R09, ASC_I2S_MODE|ASC_16BIT_MODE|ASC_NORMAL_LRCLK|ASC_LRSWAP_DISABLE|ASC_MASTER_MODE|ASC_NORMAL_BCLK);
713 rk610_codec_write(codec,ACCELCODEC_R00, ASC_HPF_ENABLE|ASC_DSM_MODE_ENABLE|ASC_SCRAMBLE_ENABLE|ASC_DITHER_ENABLE|ASC_BCLKDIV_4);
714 //2volume,input,output
715 digital_gain = Volume_Output;
717 if(rk610_codec_read(codec,ACCELCODEC_R05)!=0x0f) {
718 rk610_codec_write(codec,ACCELCODEC_R05, (digital_gain >> 8) & 0xFF);
719 rk610_codec_write(codec,ACCELCODEC_R06, digital_gain & 0xFF);
721 if(rk610_codec_read(codec,ACCELCODEC_R07)!=0x0f){
722 rk610_codec_write(codec,ACCELCODEC_R07, (digital_gain >> 8) & 0xFF);
723 rk610_codec_write(codec,ACCELCODEC_R08, digital_gain & 0xFF);
725 rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_ENABLE|ASC_INT_ENABLE);
726 gR0BReg = ASC_DEC_ENABLE|ASC_INT_ENABLE; //ASC_DEC_DISABLE|ASC_INT_ENABLE;
728 if(pdata->boot_depop){
730 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE);
732 rk610_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE);
738 static int RK610_PROC_init(void);
741 static int rk610_codec_probe(struct snd_soc_codec *codec)
743 struct rk610_codec_priv *rk610_codec = snd_soc_codec_get_drvdata(codec);
749 rk610_codec_codec = codec;
750 DBG("[%s] start\n", __FUNCTION__);
751 ret = snd_soc_codec_set_cache_io(codec, 8, 16, rk610_codec->control_type);
753 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
756 //For RK610, i2c write&read method is special, do not use system default method.
757 codec->write = rk610_codec_write;
758 codec->read = rk610_codec_read;
759 codec->hw_write = (hw_write_t)i2c_master_send;
761 if (rk610_codec_codec == NULL) {
762 dev_err(codec->dev, "Codec device not registered\n");
766 INIT_DELAYED_WORK(&rk610_codec->rk610_delayed_work, rk610_delayedwork_fun);
768 //old control method,please filling rk610_codec_platform_data into Board-xx-xx.c
771 #ifdef RK610_SPK_CTRL_PIN
772 rk610_codec->spk_ctrl_io = RK610_SPK_CTRL_PIN;
773 ret = gpio_request(rk610_codec->spk_ctrl_io, "rk610 spk_ctrl");
775 printk("rk610_control request gpio fail!\n");
778 gpio_direction_output(rk610_codec->spk_ctrl_io, GPIO_LOW);
779 gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_LOW);
781 rk610_codec->spk_ctrl_io = 0;
784 if(rk610_codec->spk_ctrl_io)
786 ret = gpio_request(rk610_codec->spk_ctrl_io, "rk610 spk_ctrl");
788 printk("rk610_control request gpio fail!\n");
791 gpio_direction_output(rk610_codec->spk_ctrl_io, GPIO_LOW);
792 gpio_set_value(rk610_codec->spk_ctrl_io, GPIO_LOW);
795 rk610_codec->hdmi_ndet = true;
797 rk610_codec->rk610_workstatus = SND_SOC_DAPM_STREAM_NOP;
800 rk610_control_init_codec();
801 rk610_codec_reg_set();
802 // rk610_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
803 schedule_delayed_work(&rk610_codec->rk610_delayed_work, msecs_to_jiffies(1000));
805 codec->dapm.bias_level = SND_SOC_BIAS_PREPARE;
809 /* power down chip */
810 static int rk610_codec_remove(struct snd_soc_codec *codec)
812 rk610_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
816 static struct snd_soc_codec_driver soc_codec_dev_rk610_codec = {
817 .probe = rk610_codec_probe,
818 .remove = rk610_codec_remove,
819 .suspend = rk610_codec_suspend,
820 .resume = rk610_codec_resume,
821 .set_bias_level = rk610_codec_set_bias_level,
822 // .volatile_register = wm8900_volatile_register,
823 .reg_cache_size = ARRAY_SIZE(rk610_codec_reg),
824 .reg_word_size = sizeof(u16),
825 .reg_cache_default = rk610_codec_reg,
826 // .dapm_widgets = rk610_codec_dapm_widgets,
827 // .num_dapm_widgets = ARRAY_SIZE(rk610_codec_dapm_widgets),
828 // .dapm_routes = audio_map,
829 // .num_dapm_routes = ARRAY_SIZE(audio_map),
832 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
833 static int rk610_codec_i2c_probe(struct i2c_client *i2c,
834 const struct i2c_device_id *id)
836 struct rk610_codec_priv *rk610_codec;
837 struct rk610_codec_platform_data *pdata = i2c->dev.platform_data;
839 DBG("%s start\n", __FUNCTION__);
840 rk610_codec = kzalloc(sizeof(struct rk610_codec_priv), GFP_KERNEL);
841 if (rk610_codec == NULL)
844 rk610_codec->pdata = pdata;
845 rk610_codec->spk_ctrl_io = pdata->spk_ctl_io;
847 ret = pdata->io_init();
849 dev_err(&i2c->dev, "Failed to register codec pdata io_init error: %d\n", ret);
855 i2c_set_clientdata(i2c, rk610_codec);
856 rk610_codec->control_type = SND_SOC_I2C;
858 ret = snd_soc_register_codec(&i2c->dev,
859 &soc_codec_dev_rk610_codec, &rk610_codec_dai, 1);
861 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
867 static int rk610_codec_i2c_remove(struct i2c_client *client)
869 snd_soc_unregister_codec(&client->dev);
870 kfree(i2c_get_clientdata(client));
874 static const struct i2c_device_id rk610_codec_i2c_id[] = {
875 { "rk610_i2c_codec", 0 },
878 MODULE_DEVICE_TABLE(i2c, rk610_codec_i2c_id);
880 /* corgi i2c codec control layer */
881 static struct i2c_driver rk610_codec_i2c_driver = {
883 .name = "RK610_CODEC",
884 .owner = THIS_MODULE,
886 .probe = rk610_codec_i2c_probe,
887 .remove = rk610_codec_i2c_remove,
888 .id_table = rk610_codec_i2c_id,
892 static int __init rk610_codec_modinit(void)
895 DBG("[%s] start\n", __FUNCTION__);
896 ret = i2c_add_driver(&rk610_codec_i2c_driver);
898 pr_err("rk610 codec: Unable to register I2C driver: %d\n", ret);
901 module_init(rk610_codec_modinit);
903 static void __exit rk610_codec_exit(void)
905 i2c_del_driver(&rk610_codec_i2c_driver);
907 module_exit(rk610_codec_exit);
909 MODULE_DESCRIPTION("ASoC RK610 CODEC driver");
910 MODULE_AUTHOR("rk@rock-chips.com");
911 MODULE_LICENSE("GPL");
913 //=====================================================================
916 static ssize_t RK610_PROC_write(struct file *file, const char __user *buffer,
917 unsigned long len, void *data)
924 cookie_pot = (char *)vmalloc( len );
931 if (copy_from_user( cookie_pot, buffer, len ))
935 switch(cookie_pot[0])
938 spk_ctrl_fun(GPIO_HIGH);
941 spk_ctrl_fun(GPIO_LOW);
945 printk("Read reg debug\n");
946 if(cookie_pot[1] ==':')
948 strsep(&cookie_pot,":");
949 while((p=strsep(&cookie_pot,",")))
951 reg = simple_strtol(p,NULL,16);
952 value = rk610_codec_read(rk610_codec_codec,reg);
953 printk("wm8994_read:0x%04x = 0x%04x\n",reg,value);
959 printk("Error Read reg debug.\n");
960 printk("For example: echo 'r:22,23,24,25'>wm8994_ts\n");
965 printk("Write reg debug\n");
966 if(cookie_pot[1] ==':')
968 strsep(&cookie_pot,":");
969 while((p=strsep(&cookie_pot,"=")))
971 reg = simple_strtol(p,NULL,16);
972 p=strsep(&cookie_pot,",");
973 value = simple_strtol(p,NULL,16);
974 rk610_codec_write(rk610_codec_codec,reg,value);
975 printk("wm8994_write:0x%04x = 0x%04x\n",reg,value);
981 printk("Error Write reg debug.\n");
982 printk("For example: w:22=0,23=0,24=0,25=0\n");
986 printk("Dump reg\n");
987 rk610_codec_reg_read();
994 static int RK610_PROC_init(void)
996 struct proc_dir_entry *RK610_PROC_entry;
997 RK610_PROC_entry = create_proc_entry("driver/rk610_ts", 0777, NULL);
998 if(RK610_PROC_entry != NULL)
1000 RK610_PROC_entry->write_proc = RK610_PROC_write;
1005 printk("create proc error !\n");