add rt5625 driver
author陈金泉 <chenjq@rock-chips.com>
Wed, 18 May 2011 08:39:05 +0000 (16:39 +0800)
committer陈金泉 <chenjq@rock-chips.com>
Wed, 18 May 2011 08:39:05 +0000 (16:39 +0800)
arch/arm/mach-rk29/board-rk29phonepadsdk.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/rt5625.c [new file with mode: 0644]
sound/soc/codecs/rt5625.h [new file with mode: 0644]
sound/soc/rk29/Kconfig
sound/soc/rk29/Makefile
sound/soc/rk29/rk29_rt5625.c [new file with mode: 0644]

index 0be0d09cea0e1bb119dc41a794162f2a9381cbce..d5336961b7fb739e419fc15550a33a156e27b66f 100755 (executable)
@@ -567,6 +567,15 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = {
                 .flags                  = 0,
         },
 #endif
+
+#if defined (CONFIG_SND_SOC_RT5625)
+       {
+               .type                   = "rt5625",
+               .addr                   = 0x1e,         //need check A1 pin,A1 pin is low,addr=0x1e,A1 pin is high,addr=0x1f.
+               .flags                  = 0,
+       },
+#endif
+
 #if defined (CONFIG_SND_SOC_RK1000)
        {
                .type                   = "rk1000_i2c_codec",
index 4ba65a696c2df4204eb2e4aac7da6b087f34fe57..ec6669f9ed7258cfa34ac8d7f74f7aeb347b7f6a 100644 (file)
@@ -44,6 +44,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WM8900 if I2C
        select SND_SOC_alc5621 if I2C
        select SND_SOC_alc5631 if I2C
+       select SND_SOC_RT5625 if I2C
        select SND_SOC_WM8903 if I2C
        select SND_SOC_WM8940 if I2C
        select SND_SOC_WM8960 if I2C
@@ -188,6 +189,9 @@ config SND_SOC_alc5621
 
 config SND_SOC_alc5631
        tristate
+
+config SND_SOC_RT5625
+       tristate
        
 config SND_SOC_WM8903
        tristate
index 49b4439c6a359acef739828633fc86563a0a62ff..cef035f1cb3ebb4d0cd499430ce46a27328ff847 100644 (file)
@@ -32,6 +32,7 @@ snd-soc-wm8776-objs := wm8776.o
 snd-soc-wm8900-objs := wm8900.o
 snd-soc-alc5621-objs := alc5621.o
 snd-soc-alc5631-objs := rt5631.o
+snd-soc-rt5625-objs := rt5625.o
 snd-soc-wm8903-objs := wm8903.o
 snd-soc-wm8940-objs := wm8940.o
 snd-soc-wm8960-objs := wm8960.o
@@ -87,6 +88,7 @@ obj-$(CONFIG_SND_SOC_WM8776)  += snd-soc-wm8776.o
 obj-$(CONFIG_SND_SOC_WM8900)   += snd-soc-wm8900.o
 obj-$(CONFIG_SND_SOC_alc5621)  += snd-soc-alc5621.o
 obj-$(CONFIG_SND_SOC_alc5631)  += snd-soc-alc5631.o
+obj-$(CONFIG_SND_SOC_RT5625)   += snd-soc-rt5625.o
 obj-$(CONFIG_SND_SOC_WM8903)   += snd-soc-wm8903.o
 obj-$(CONFIG_SND_SOC_WM8971)   += snd-soc-wm8971.o
 obj-$(CONFIG_SND_SOC_WM8974)   += snd-soc-wm8974.o
diff --git a/sound/soc/codecs/rt5625.c b/sound/soc/codecs/rt5625.c
new file mode 100644 (file)
index 0000000..960f944
--- /dev/null
@@ -0,0 +1,2451 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/jiffies.h>
+#include <asm/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <asm/div64.h>
+
+#include "rt5625.h"
+
+#if REALTEK_HWDEP
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#endif
+
+#define AUDIO_NAME "rt5625"
+#define RT5625_VERSION "0.03 alsa 1.0.21"
+#define ALSA_SOC_VERSION "1.0.21"
+
+#define RT5625_EQ_FUNC_ENA  0
+
+static void hp_depop_mode2(struct snd_soc_codec *codec);
+static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute); 
+
+struct rt5625_priv {
+       unsigned int stereo_sysclk;
+       unsigned int voice_sysclk;
+};
+
+struct rt5625_init_reg {
+       u8 reg_index;
+       u16 reg_value;  
+};
+
+static struct rt5625_init_reg rt5625_init_list[] = {
+
+       {RT5625_HP_OUT_VOL                      , 0x8888},      //default is -12db
+       {RT5625_SPK_OUT_VOL             , 0x8080},      //default is 0db
+       {RT5625_DAC_AND_MIC_CTRL        , 0xee03},      //DAC to hpmixer
+       {RT5625_OUTPUT_MIXER_CTRL       , 0x0748},      //all output from hpmixer
+       {RT5625_MIC_CTRL                        , 0x0500},      //mic boost 20db
+       {RT5625_ADC_REC_MIXER           , 0x3f3f},      //record source from mic1
+       {RT5625_GEN_CTRL_REG1           , 0x0c0a},      //speaker vdd ratio is 1
+       {RT5625_ADC_REC_GAIN            , 0xd5d5},      //gain 15db of ADC by default
+
+};
+
+#define RT5625_INIT_REG_NUM ARRAY_SIZE(rt5625_init_list)
+
+#if (RT5625_EQ_FUNC_ENA==1)
+//*************************************************************************************************
+//eq table
+//*************************************************************************************************
+enum
+{
+       NORMAL=0,
+       CLUB,
+       DANCE,
+       LIVE,   
+       POP,
+       ROCK,
+       OPPO,
+       TREBLE,
+       BASS    
+};
+
+typedef struct  _HW_EQ_PRESET
+{
+       u16     HwEqType;
+       u16     EqValue[14];
+       u16  HwEQCtrl;
+
+}HW_EQ_PRESET;
+
+
+HW_EQ_PRESET HwEq_Preset[]={
+/*                     0x0             0x1             0x2       0x3   0x4             0x5             0x6             0x7     0x8             0x9             0xa     0xb             0xc             0x6e*/
+       {NORMAL,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0000},                   
+       {CLUB  ,{0x1C10,0x0000,0xC1CC,0x1E5D,0x0699,0xCD48,0x188D,0x0699,0xC3B6,0x1CD0,0x0699,0x0436,0x0000},0x800E},
+       {DANCE ,{0x1F2C,0x095B,0xC071,0x1F95,0x0616,0xC96E,0x1B11,0xFC91,0xDCF2,0x1194,0xFAF2,0x0436,0x0000},0x800F},
+       {LIVE  ,{0x1EB5,0xFCB6,0xC24A,0x1DF8,0x0E7C,0xC883,0x1C10,0x0699,0xDA41,0x1561,0x0295,0x0436,0x0000},0x800F},
+       {POP   ,{0x1EB5,0xFCB6,0xC1D4,0x1E5D,0x0E23,0xD92E,0x16E6,0xFCB6,0x0000,0x0969,0xF988,0x0436,0x0000},0x800F},
+       {ROCK  ,{0x1EB5,0xFCB6,0xC071,0x1F95,0x0424,0xC30A,0x1D27,0xF900,0x0C5D,0x0FC7,0x0E23,0x0436,0x0000},0x800F},
+       {OPPO  ,{0x0000,0x0000,0xCA4A,0x17F8,0x0FEC,0xCA4A,0x17F8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x800F},
+       {TREBLE,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x188D,0x1699},0x8010},
+       {BASS  ,{0x1A43,0x0C00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x8001},
+       
+};
+
+#endif
+//*************************************************************************************************
+//*************************************************************************************************
+
+/*
+ *     bit[0]  for linein playback switch
+ *     bit[1] phone
+ *     bit[2] mic1
+ *     bit[3] mic2
+ *     bit[4] vopcm
+ *     
+ */
+#define HPL_MIXER 0x80
+#define HPR_MIXER 0x82
+static unsigned int reg80 = 0, reg82 = 0;
+
+/*
+ *     bit[0][1][2] use for aec control
+ *  bit[3] for none  
+ *     bit[4] for SPKL pga
+ *     bit[5] for SPKR pga
+ *     bit[6] for hpl pga
+ *     bit[7] for hpr pga
+ *  bit[8] for dump dsp
+ *  bit[12~15] for eq function
+ */
+ #define VIRTUAL_REG_FOR_MISC_FUNC 0x84
+static unsigned int reg84 = 0;
+
+
+static const u16 rt5625_reg[] = {
+       0x59b4, 0x8080, 0x8080, 0x8080,         /*reg00-reg06*/
+       0xc800, 0xe808, 0x1010, 0x0808,         /*reg08-reg0e*/
+       0xe0ef, 0xcbcb, 0x7f7f, 0x0000,         /*reg10-reg16*/
+       0xe010, 0x0000, 0x8008, 0x2007,         /*reg18-reg1e*/
+       0x0000, 0x0000, 0x00c0, 0xef00,         /*reg20-reg26*/
+       0x0000, 0x0000, 0x0000, 0x0000,         /*reg28-reg2e*/
+       0x0000, 0x0000, 0x0000, 0x0000,         /*reg30-reg36*/
+       0x0000, 0x0000, 0x0000, 0x0000,         /*reg38-reg3e*/
+       0x0c0a, 0x0000, 0x0000, 0x0000,         /*reg40-reg46*/
+       0x0029, 0x0000, 0xbe3e, 0x3e3e,         /*reg48-reg4e*/
+       0x0000, 0x0000, 0x803a, 0x0000,         /*reg50-reg56*/
+       0x0000, 0x0009, 0x0000, 0x3000,         /*reg58-reg5e*/
+       0x3075, 0x1010, 0x3110, 0x0000,         /*reg60-reg66*/
+       0x0553, 0x0000, 0x0000, 0x0000,         /*reg68-reg6e*/
+       0x0000, 0x0000, 0x0000, 0x0000,         /*reg70-reg76*/
+       0x0000, 0x0000, 0x0000, 0x0000,     /*reg78-reg7e*/
+};
+
+
+Voice_DSP_Reg VODSP_AEC_Init_Value[]=
+{
+       {0x232C, 0x0025},
+       {0x230B, 0x0001},
+       {0x2308, 0x007F},
+       {0x23F8, 0x4003},
+       {0x2301, 0x0002},
+       {0x2328, 0x0001},
+       {0x2304, 0x00FA},
+       {0x2305, 0x0500},
+       {0x2306, 0x4000},
+       {0x230D, 0x0900},
+       {0x230E, 0x0280},
+       {0x2312, 0x00B1},
+       {0x2314, 0xC000},
+       {0x2316, 0x0041},
+       {0x2317, 0x2200},
+       {0x2318, 0x0C00},
+       {0x231D, 0x0050},
+       {0x231F, 0x4000},
+       {0x2330, 0x0008},
+       {0x2335, 0x000A},
+       {0x2336, 0x0004},
+       {0x2337, 0x5000},
+       {0x233A, 0x0300},
+       {0x233B, 0x0030},
+       {0x2341, 0x0008},
+       {0x2343, 0x0800},       
+       {0x2352, 0x7FFF},
+       {0x237F, 0x0400},
+       {0x23A7, 0x2800},
+       {0x22CE, 0x0400},
+       {0x22D3, 0x1500},
+       {0x22D4, 0x2800},
+       {0x22D5, 0x3000},
+       {0x2399, 0x2800},
+       {0x230C, 0x0000},       //to enable VODSP AEC function
+};
+
+
+#define SET_VODSP_REG_INIT_NUM ARRAY_SIZE(VODSP_AEC_Init_Value)
+static struct snd_soc_device *rt5625_socdev;
+
+static inline unsigned int rt5625_read_reg_cache(struct snd_soc_codec *codec, 
+       unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+
+       if (reg > 0x7e)
+               return 0;
+       return cache[reg / 2];
+}
+
+
+static unsigned int rt5625_read_hw_reg(struct snd_soc_codec *codec, unsigned int reg) 
+{
+       u8 data[2] = {0};
+       unsigned int value = 0x0;
+       
+       data[0] = reg;
+       
+       i2c_master_reg8_recv(codec->control_data,reg,data,2,100 * 1000);        
+                     
+    value = (data[0]<<8) | data[1];         
+    
+    printk("rt5625_read reg%x=%x\n",reg,value);
+       
+    return value;      
+}
+
+
+static unsigned int rt5625_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+       if ((reg == 0x80)
+               || (reg == 0x82)
+               || (reg == 0x84))
+               return (reg == 0x80) ? reg80 : ((reg == 0x82) ? reg82 : reg84);
+       
+               return rt5625_read_hw_reg(codec, reg);
+}
+
+
+static inline void rt5625_write_reg_cache(struct snd_soc_codec *codec,
+       unsigned int reg, unsigned int value)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg > 0x7E)
+               return;
+       cache[reg / 2] = value;
+}
+
+static int rt5625_write(struct snd_soc_codec *codec, unsigned int reg,
+       unsigned int value)
+{
+       u8 data[3];
+       unsigned int *regvalue = NULL;
+
+       data[0] = reg;
+       data[1] = (value & 0xff00) >> 8;
+       data[2] = value & 0x00ff;
+       
+       if ((reg == 0x80)
+               || (reg == 0x82)
+               || (reg == 0x84))
+       {               
+               regvalue = ((reg == 0x80) ? &reg80 : ((reg == 0x82) ? &reg82 : &reg84));
+               *regvalue = value;
+               printk(KERN_INFO "rt5625_write ok, reg = %x, value = %x\n", reg, value);
+               return 0;
+       }
+       rt5625_write_reg_cache(codec, reg, value);
+
+       if (codec->hw_write(codec->control_data, data, 3) == 3)
+       {
+               printk(KERN_INFO "rt5625_write ok, reg = %x, value = %x\n", reg, value);
+               return 0;
+       }
+       else 
+       {
+               printk(KERN_ERR "rt5625_write fail\n");
+               return -EIO;
+       }
+}
+
+int rt5625_write_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask)
+{
+       
+       unsigned char RetVal=0;
+       unsigned  int CodecData;
+
+//     printk(KERN_INFO "rt5625_write_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask);
+
+       if(!mask)
+               return 0; 
+
+       if(mask!=0xffff)
+        {
+               CodecData=rt5625_read(codec,reg);               
+               CodecData&=~mask;
+               CodecData|=(value&mask);
+               RetVal=rt5625_write(codec,reg,CodecData);
+        }              
+       else
+       {
+               RetVal=rt5625_write(codec,reg,value);
+       }
+
+       return RetVal;
+}
+
+
+void rt5625_write_index(struct snd_soc_codec *codec, unsigned int reg,
+       unsigned int value)
+{
+       
+       rt5625_write(codec,0x6a,reg);
+       rt5625_write(codec,0x6c,value); 
+}
+
+unsigned int rt5625_read_index(struct snd_soc_codec *codec, unsigned int reg)
+{
+       unsigned int value = 0x0;
+       rt5625_write(codec,0x6a,reg);
+       value=rt5625_read(codec,0x6c);  
+       
+       return value;
+}
+
+void rt5625_write_index_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask)
+{
+       
+//     unsigned char RetVal=0;
+       unsigned  int CodecData;
+
+//     printk(KERN_INFO "rt5625_write_index_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask);
+
+       if(!mask)
+               return; 
+
+       if(mask!=0xffff)
+        {
+               CodecData=rt5625_read_index(codec,reg);         
+               CodecData&=~mask;
+               CodecData|=(value&mask);
+               rt5625_write_index(codec,reg,CodecData);
+        }              
+       else
+       {
+               rt5625_write_index(codec,reg,value);
+       }
+}
+
+//#define rt5625_write_mask(c, reg, value, mask) snd_soc_update_bits(c, reg, mask, value)
+
+#define rt5625_reset(c) rt5625_write(c, RT5625_RESET, 0)
+
+/*read/write dsp reg*/
+static int rt5625_wait_vodsp_i2c_done(struct snd_soc_codec *codec)
+{
+       unsigned int checkcount = 0, vodsp_data;
+
+       vodsp_data = rt5625_read(codec, RT5625_VODSP_REG_CMD);
+       while(vodsp_data & VODSP_BUSY)
+       {
+               if(checkcount > 10)
+                       return -EBUSY;
+               vodsp_data = rt5625_read(codec, RT5625_VODSP_REG_CMD);
+               checkcount ++;          
+       }
+       return 0;
+}
+
+static int rt5625_write_vodsp_reg(struct snd_soc_codec *codec, unsigned int vodspreg, unsigned int value)
+{
+       int ret = 0;
+
+       if(ret != rt5625_wait_vodsp_i2c_done(codec))
+               return -EBUSY;
+
+       rt5625_write(codec, RT5625_VODSP_REG_ADDR, vodspreg);
+       rt5625_write(codec, RT5625_VODSP_REG_DATA, value);
+       rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_WRITE_ENABLE | VODSP_CMD_MW);
+       mdelay(10);
+       return ret;
+       
+}
+
+static unsigned int rt5625_read_vodsp_reg(struct snd_soc_codec *codec, unsigned int vodspreg)
+{
+       int ret = 0;
+       unsigned int nDataH, nDataL;
+       unsigned int value;
+
+       if(ret != rt5625_wait_vodsp_i2c_done(codec))
+               return -EBUSY;
+       
+       rt5625_write(codec, RT5625_VODSP_REG_ADDR, vodspreg);
+       rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_MR);
+
+       if (ret != rt5625_wait_vodsp_i2c_done(codec))
+               return -EBUSY;
+       rt5625_write(codec, RT5625_VODSP_REG_ADDR, 0x26);
+       rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_RR);
+
+       if(ret != rt5625_wait_vodsp_i2c_done(codec))
+               return -EBUSY;
+       nDataH = rt5625_read(codec, RT5625_VODSP_REG_DATA);
+       rt5625_write(codec, RT5625_VODSP_REG_ADDR, 0x25);
+       rt5625_write(codec, RT5625_VODSP_REG_CMD, VODSP_READ_ENABLE | VODSP_CMD_RR);
+
+       if(ret != rt5625_wait_vodsp_i2c_done(codec))
+               return -EBUSY;
+       nDataL = rt5625_read(codec, RT5625_VODSP_REG_DATA);
+       value = ((nDataH & 0xff) << 8) |(nDataL & 0xff);
+       printk(KERN_INFO "%s vodspreg=0x%x, value=0x%x\n", __func__, vodspreg, value);
+       return value;
+}
+
+static int rt5625_reg_init(struct snd_soc_codec *codec)
+{
+       int i;
+
+       for (i = 0; i < RT5625_INIT_REG_NUM; i++)
+               rt5625_write(codec, rt5625_init_list[i].reg_index, rt5625_init_list[i].reg_value);
+
+       return 0;
+}
+
+//*************************************************************************************************
+//*************************************************************************************************
+#if (RT5625_EQ_FUNC_ENA==1)    
+//eq function
+static void rt5625_update_eqmode(struct snd_soc_codec *codec, int mode)
+{
+       u16 HwEqIndex=0;
+
+       if(mode==NORMAL)
+       {
+               /*clear EQ parameter*/
+               for(HwEqIndex=0;HwEqIndex<=0x0C;HwEqIndex++)
+               {
+                       rt5625_write_index(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex]);
+               }
+               
+               rt5625_write_mask(codec, 0x6e,0x0,EN_HW_EQ_BLK | EN_HW_EQ_HPF | EN_HW_EQ_BP3 | EN_HW_EQ_BP2 | EN_HW_EQ_BP1 | EN_HW_EQ_LPF);             /*disable EQ block*/
+       }
+       else
+       {               
+               /*Fill EQ parameter*/
+               for(HwEqIndex=0;HwEqIndex<=0x0C;HwEqIndex++)
+               {
+                       rt5625_write_index(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex]); 
+               }               
+
+               //enable EQ block
+               rt5625_write_mask(codec, 0x6e,HwEq_Preset[mode].HwEQCtrl,EN_HW_EQ_BLK | EN_HW_EQ_HPF | EN_HW_EQ_BP3 | EN_HW_EQ_BP2 | EN_HW_EQ_BP1 | EN_HW_EQ_LPF);              
+               
+               //update EQ parameter
+               rt5625_write_mask(codec, 0x6e,0x0080,0x0080);
+       }
+}
+
+
+static int rt5625_eq_sel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       u16 Virtual_reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC);
+       int rt5625_mode=((Virtual_reg)&0xf000)>>12;
+       
+       if ( rt5625_mode == ucontrol->value.integer.value[0])
+               return 0;
+
+       rt5625_update_eqmode(codec, ucontrol->value.enumerated.item[0]);
+
+       Virtual_reg &= 0x0fff;
+       Virtual_reg |= (ucontrol->value.integer.value[0])<<12;
+       rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, Virtual_reg);            
+       
+       return 0;
+}
+#endif
+//*************************************************************************************************
+//*************************************************************************************************
+static const char *rt5625_aec_path_sel[] = {"aec func disable","aec func for pcm in/out",
+                                                                                       "aec func for iis in/out","aec func for analog in/out"};                /*0*/                   
+static const char *rt5625_spk_out_sel[] = {"Class AB", "Class D"};                                     /*1*/
+static const char *rt5625_spk_l_source_sel[] = {"LPRN", "LPRP", "LPLN", "MM"};         /*2*/   
+static const char *rt5625_spkmux_source_sel[] = {"VMID", "HP Mixer", 
+                                                       "SPK Mixer", "Mono Mixer"};                                                     /*3*/
+static const char *rt5625_hplmux_source_sel[] = {"VMID","HPL Mixer"};                          /*4*/
+static const char *rt5625_hprmux_source_sel[] = {"VMID","HPR Mixer"};                          /*5*/
+static const char *rt5625_auxmux_source_sel[] = {"VMID", "HP Mixer", 
+                                                       "SPK Mixer", "Mono Mixer"};                                                     /*6*/
+static const char *rt5625_spkamp_ratio_sel[] = {"2.25 Vdd", "2.00 Vdd",
+                                       "1.75 Vdd", "1.50 Vdd", "1.25 Vdd", "1.00 Vdd"};                                /*7*/
+static const char *rt5625_mic1_boost_sel[] = {"Bypass", "+20db", "+30db", "+40db"};    /*8*/
+static const char *rt5625_mic2_boost_sel[] = {"Bypass", "+20db", "+30db", "+40db"};    /*9*/
+static const char *rt5625_dmic_boost_sel[] = {"Bypass", "+6db", "+12db", "+18db", 
+                                       "+24db", "+30db", "+36db", "+42db"};                                            /*10*/
+static const char *rt5625_adcr_func_sel[] = {"Stereo ADC", "Voice ADC", 
+                                       "VoDSP Interface", "PDM Slave Interface"};                                   /*11*/
+#if (RT5625_EQ_FUNC_ENA==1)                                    
+static const char *rt5625_eq_sel[] = {"NORMAL", "CLUB","DANCE", "LIVE","POP",                  /*12*/
+                                       "ROCK", "OPPO", "TREBLE", "BASS"};                                      
+#endif
+
+static const struct soc_enum rt5625_enum[] = {
+
+SOC_ENUM_SINGLE(VIRTUAL_REG_FOR_MISC_FUNC, 0, 4, rt5625_aec_path_sel),         /*0*/
+SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 13, 2, rt5625_spk_out_sel),          /*1*/
+SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 14, 4, rt5625_spk_l_source_sel),     /*2*/
+SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 10, 4, rt5625_spkmux_source_sel),/*3*/
+SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 9, 2, rt5625_hplmux_source_sel),     /*4*/
+SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 8, 2, rt5625_hprmux_source_sel),/*5*/
+SOC_ENUM_SINGLE(RT5625_OUTPUT_MIXER_CTRL, 6, 4, rt5625_auxmux_source_sel),/*6*/
+SOC_ENUM_SINGLE(RT5625_GEN_CTRL_REG1, 1, 6, rt5625_spkamp_ratio_sel),          /*7*/
+SOC_ENUM_SINGLE(RT5625_MIC_CTRL, 10, 4,  rt5625_mic1_boost_sel),                       /*8*/
+SOC_ENUM_SINGLE(RT5625_MIC_CTRL, 8, 4, rt5625_mic2_boost_sel),                         /*9*/
+SOC_ENUM_SINGLE(RT5625_DMIC_CTRL, 0, 8, rt5625_dmic_boost_sel),                                /*10*/
+SOC_ENUM_SINGLE(RT5625_DAC_ADC_VODAC_FUN_SEL, 4, 4, rt5625_adcr_func_sel), /*11*/
+#if (RT5625_EQ_FUNC_ENA==1)
+SOC_ENUM_SINGLE(VIRTUAL_REG_FOR_MISC_FUNC, 12, 9, rt5625_eq_sel),    /*EQ mode select mode 12*/
+#endif
+};
+
+
+
+//*****************************************************************************
+//function:Enable the Voice PCM interface Path
+//*****************************************************************************
+static int ConfigPcmVoicePath(struct snd_soc_codec *codec,unsigned int bEnableVoicePath,unsigned int mode)
+{
+
+       if(bEnableVoicePath)
+        {
+                       //Power on DAC reference
+                       rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD1,PWR_DAC_REF|PWR_VOICE_DF2SE,PWR_DAC_REF|PWR_VOICE_DF2SE);
+                       //Power on Voice DAC/ADC 
+                       rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD2,PWR_VOICE_CLOCK,PWR_VOICE_CLOCK);
+                       //routing voice to HPMixer
+                       rt5625_write_mask(codec,RT5625_VOICE_DAC_OUT_VOL,0,M_V_DAC_TO_HP_MIXER);
+                                       
+               switch(mode)            
+               {
+                       case PCM_SLAVE_MODE_B:  //8kHz sampling rate,16 bits PCM mode and Slave mode,PCM mode is B,MCLK=24.576MHz from Oscillator.
+                                                               //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08C00000,PSKEY_FORMAT=0x0060                         
+
+                               //Enable GPIO 1,3,4,5 to voice interface
+                               //Set I2S to Slave mode
+                               //Voice I2S SYSCLK Source select Main SYSCLK
+                               //Set voice I2S VBCLK Polarity to Invert
+                               //Set Data length to 16 bit
+                               //set Data Fomrat to PCM mode B
+                               //the register 0x36 value's should is 0xC083
+                               rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0xC083);
+
+                               //Set LRCK voice select divide 32
+                               //set voice blck select divide 6 and 8 
+                               //voice filter clock divide 3 and 16
+                               //the register 0x64 value's should is 0x5524
+                               rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524);
+               
+                               break;
+
+                       case PCM_SLAVE_MODE_A:  //8kHz sampling rate,16 bits PCM and Slave mode,PCM mode is A,MCLK=24.576MHz from Oscillator.
+                                                               //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08C00004,PSKEY_FORMAT=0x0060                         
+
+                               //Enable GPIO 1,3,4,5 to voice interface
+                               //Set I2S to Slave mode
+                               //Voice I2S SYSCLK Source select Main SYSCLK
+                               //Set voice i2s VBCLK Polarity to Invert
+                               //Set Data length to 16 bit
+                               //set Data Fomrat to PCM mode A
+                               //the register 0x36 value's should is 0xC082
+                               rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0xC082);
+
+                               //Set LRCK voice select divide 64
+                               //set voice blck select divide 6 and 8 
+                               //voice filter clock divide 3 and 16
+                               //the register 0x64 value's should is 0x5524
+                               rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524);
+               
+                               break;
+
+                       case PCM_MASTER_MODE_B: //8kHz sampling rate,16 bits PCM and Master mode,PCM mode is B,Clock from PLL OUT
+                                                               //CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08000002,PSKEY_FORMAT=0x0060 
+
+                               //Enable GPIO 1,3,4,5 to voice interface
+                               //Set I2S to master mode
+                               //Set voice i2s VBCLK Polarity to Invert
+                               //Set Data length to 16 bit
+                               //set Data Fomrat to PCM mode B
+                               //the register 0x36 value's should is 0x8083
+                               rt5625_write(codec,RT5625_EXTEND_SDP_CTRL,0x8083);
+
+                               //Set LRCK voice select divide 64
+                               //set voice blck select divide 6 and 8 
+                               //voice filter clock divide 3 and 16
+                               //the register 0x64 value's should is 0x5524
+                               rt5625_write(codec,RT5625_VOICE_DAC_PCMCLK_CTRL1,0x5524);
+               
+                               break;
+
+                       default:
+                               //do nothing            
+                               break;
+
+                       }
+               }
+               else
+               {       
+                       //Power down Voice Different to sing-end power
+                       rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD1,0,PWR_VOICE_DF2SE);
+                       //Power down Voice DAC/ADC 
+                       rt5625_write_mask(codec,RT5625_PWR_MANAG_ADD2,0,PWR_VOICE_CLOCK);
+                       //Disable Voice PCM interface   
+                       rt5625_write_mask(codec,RT5625_EXTEND_SDP_CTRL,0,EXT_I2S_FUNC_ENABLE);                  
+               }
+       
+       return 0;
+}
+
+static int init_vodsp_aec(struct snd_soc_codec *codec)
+{
+       int i;
+       int ret = 0;
+
+       /*disable LDO power*/
+       rt5625_write_mask(codec, RT5625_LDO_CTRL,0,LDO_ENABLE);
+       mdelay(20);     
+       rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_NO_PD_MODE_ENA,VODSP_NO_PD_MODE_ENA);
+       /*enable LDO power and set output voltage to 1.2V*/
+       rt5625_write_mask(codec, RT5625_LDO_CTRL,LDO_ENABLE|LDO_OUT_VOL_CTRL_1_20V,LDO_ENABLE|LDO_OUT_VOL_CTRL_MASK);
+       mdelay(20);
+       /*enable power of VODSP I2C interface*/ 
+       rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP);
+       mdelay(1);
+       rt5625_write_mask(codec, RT5625_VODSP_CTL,0,VODSP_NO_RST_MODE_ENA);     /*Reset VODSP*/
+       mdelay(1);
+       rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_NO_RST_MODE_ENA,VODSP_NO_RST_MODE_ENA); /*set VODSP to non-reset status*/               
+       mdelay(20);
+
+       /*initize AEC paramter*/
+       for(i = 0; i < SET_VODSP_REG_INIT_NUM; i++)
+       {
+               ret = rt5625_write_vodsp_reg(codec, VODSP_AEC_Init_Value[i].VoiceDSPIndex,VODSP_AEC_Init_Value[i].VoiceDSPValue);
+               if(ret)
+                       return -EIO;
+       }               
+
+       schedule_timeout_uninterruptible(msecs_to_jiffies(10)); 
+
+       return 0;
+}
+
+//***********************************************************************************************
+//function:Enable/Disable the vodsp interface Path
+//For system clock only suport specific clock,realtek suggest customer to use 24.576Mhz or 22.5792Mhz
+//clock fro MCLK(MCLK=48k*512 or 44.1k*512Mhz)
+//***********************************************************************************************
+static int set_vodsp_aec_path(struct snd_soc_codec *codec, unsigned int mode)
+{
+
+               switch(mode)
+               {
+
+                       case PCM_IN_PCM_OUT:
+                               //set PCM format
+                               ConfigPcmVoicePath(codec,1,PCM_MASTER_MODE_B);
+                               //set AEC path
+                               rt5625_write_mask(codec, 0x26,0x0300,0x0300);
+                               rt5625_write_mask(codec, RT5625_VODSP_PDM_CTL,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_VOICE|VOICE_PCM_S_SEL_AEC_TXDP
+                                                                                                                        ,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|VOICE_PCM_S_SEL_MASK);
+                               rt5625_write_mask(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|VODAC_SOUR_SEL_VODSP_TXDC
+                                                                                                                                       ,ADCR_FUNC_SEL_MASK|VODAC_SOUR_SEL_MASK);
+                               rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_LRCK_SEL_8K,VODSP_LRCK_SEL_MASK);                                               
+                               rt5625_write_mask(codec, 0x26,0x0000,0x0300);
+                               //set input&output path and power
+                               rt5625_write_mask(codec, 0x3a,0x0c8f,0x0c8f);//power on related bit
+                               rt5625_write_mask(codec, 0x3c,0xa4cb,0xa4cb);//power on related bit
+                               rt5625_write_mask(codec, 0x3e,0x3302,0xf302);//power on related bit
+                                               
+                               rt5625_write(codec, 0x10, 0xee0f);//mute DAC to hpmixer
+                               rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode
+                               rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db
+                               rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db
+                               rt5625_write(codec, 0x14, 0x7f3f);//Mic1->ADCMixer_R
+                               rt5625_write(codec, 0x18, 0xa010);//VoDAC to speakerMixer,0db
+                               rt5625_write(codec, 0x1c, 0x8808);//speaker source from speakermixer
+                                                       
+                               rt5625_write_mask(codec, 0x02,0x0000,0x8080);   //unmute speaker 
+
+                               break;
+                       
+                       
+                       case ANALOG_IN_ANALOG_OUT:      
+                               rt5625_write_mask(codec, 0x26,0x0300,0x0300);
+                               rt5625_write_mask(codec, RT5625_VODSP_PDM_CTL,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_ADCL|VOICE_PCM_S_SEL_AEC_TXDP
+                                                                                                                        ,VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|VOICE_PCM_S_SEL_MASK);
+                               rt5625_write_mask(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|VODAC_SOUR_SEL_VODSP_TXDC|DAC_FUNC_SEL_VODSP_TXDP|ADCL_FUNC_SEL_VODSP
+                                                                                                                                       ,ADCR_FUNC_SEL_MASK|VODAC_SOUR_SEL_MASK|DAC_FUNC_SEL_MASK|ADCL_FUNC_SEL_MASK);
+                               rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_LRCK_SEL_16K,VODSP_LRCK_SEL_MASK);      
+                               rt5625_write_mask(codec, 0x26,0x0000,0x0300);
+                               //set input&output path and power
+                               rt5625_write_mask(codec, 0x3a,0xcc8f,0xcc8f);//power on related bit
+                               rt5625_write_mask(codec, 0x3c,0xa7cf,0xa7cf);//power on related bit
+                               rt5625_write_mask(codec, 0x3e,0xf312,0xf312);//power on related bit
+                               
+                               rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode
+                               rt5625_write(codec, 0x08, 0xe800);//set phone in to differential mode
+                               rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db
+                               rt5625_write(codec, 0x14, 0x773f);//Mic1->ADCMixer_R,phone in-->ADCMixer_L
+                               rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db
+                               rt5625_write(codec, 0x1c, 0x88c8);//speaker from spkmixer,monoOut from monoMixer
+                               rt5625_write(codec, 0x18, 0xA010);//unmute VoDAC to spkmixer
+                               rt5625_write(codec, 0x10, 0xee0e);//unmute DAC to monoMixer     
+                               rt5625_write(codec, 0x62, 0x2222);
+                               rt5625_write(codec, 0x64, 0x3122);
+                               rt5625_write_mask(codec, 0x02,0x0000,0x8080);   //unmute speaker 
+                               rt5625_write_mask(codec, 0x06,0x0000,0x8080);   //unmute auxout 
+                               break;
+
+                       case DAC_IN_ADC_OUT:    
+                               rt5625_write_mask(codec, 0x26,0x0300,0x0300);
+                               rt5625_write_mask(codec,RT5625_DAC_ADC_VODAC_FUN_SEL,ADCR_FUNC_SEL_PDM|DAC_FUNC_SEL_VODSP_TXDC
+                                                                                                                                       ,ADCR_FUNC_SEL_MASK|DAC_FUNC_SEL_MASK);
+                               rt5625_write_mask(codec,RT5625_VODSP_PDM_CTL,VODSP_SRC1_PWR|VODSP_SRC2_PWR|VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_SRC1|REC_S_SEL_SRC2,
+                                                                                                                        VODSP_SRC1_PWR|VODSP_SRC2_PWR|VODSP_RXDP_PWR|VODSP_RXDP_S_SEL_MASK|REC_S_SEL_MASK);                                    
+                               rt5625_write_mask(codec,RT5625_VODSP_CTL,VODSP_LRCK_SEL_16K,VODSP_LRCK_SEL_MASK);
+                               rt5625_write_mask(codec, 0x26,0x0000,0x0300);
+                               //set input&output path and power       
+                               rt5625_write_mask(codec, 0x3a,0xcc0f,0xcc0f);//power on related bit
+                               rt5625_write_mask(codec, 0x3c,0xa7cb,0xa7cb);//power on related bit
+                               rt5625_write_mask(codec, 0x3e,0x3302,0x3302);//power on related bit
+                               
+                               rt5625_write(codec, 0x0e, 0x8808);//set Mic1 to differential mode
+                               rt5625_write(codec, 0x22, 0x0000);//Mic boost 0db
+                               rt5625_write(codec, 0x14, 0x7f3f);//Mic1->ADCMixer_R
+                               rt5625_write(codec, 0x12, 0xCBD3);//ADC_Mixer_R boost 10.5 db
+                               rt5625_write(codec, 0x1c, 0x8808);//speaker out from spkMixer
+                               rt5625_write(codec, 0x10, 0xee0d);//unmute DAC to spkMixer      
+                               rt5625_write(codec, 0x60, 0x3075);
+                               rt5625_write(codec, 0x62, 0x1010);                                      
+                               rt5625_write_mask(codec, 0x02,0x0000,0x8080);   //unmute speaker 
+
+                               break;
+
+                       case VODSP_AEC_DISABLE:
+                       default:
+                               rt5625_write_mask(codec, 0x02,0x8080,0x8080);//mute speaker out
+                               rt5625_write_mask(codec, 0x06,0x8080,0x8080);//mute auxout              
+                               rt5625_write(codec, 0x22, 0x0500);//Mic boost 20db by default
+                               rt5625_write(codec, 0x14, 0x3f3f);//record from Mic1 by default
+                               rt5625_write(codec, 0x12, 0xD5D5);//ADC_Mixer_R boost 15 db by default
+                               rt5625_write(codec, 0x1c, 0x0748);//all output from HPmixer by default
+                               rt5625_write(codec, 0x10, 0xee03);//DAC to HPmixer by default
+                               rt5625_write(codec, 0x18, 0xe010);//mute VoDAC to mixer by default
+                               rt5625_write_mask(codec, 0x26,0x0300,0x0300);
+                               /*set stereo DAC&Voice DAC&Stereo ADC function select to default*/ 
+                               rt5625_write(codec, RT5625_DAC_ADC_VODAC_FUN_SEL,0);            
+                               /*set VODSP&PDM Control to default*/ 
+                               rt5625_write(codec, RT5625_VODSP_PDM_CTL,0);
+                               rt5625_write_mask(codec, 0x26,0x0000,0x0300);           
+                               rt5625_write_mask(codec, 0x3e,0x0000,0xf312);//power down related bit
+                               rt5625_write_mask(codec, 0x3a,0x0000,0xcc8d);//power down related bit
+                               rt5625_write_mask(codec, 0x3c,0x0000,0x07cf);//power down related bit
+                               
+                       
+                               break;
+               }               
+
+       return 0;
+}
+
+static int enable_vodsp_aec(struct snd_soc_codec *codec, unsigned int VodspAEC_En, unsigned int AEC_mode)
+{
+       int  ret = 0;
+
+       
+       if (VodspAEC_En != 0)
+       {       
+
+               //enable power of VODSP I2C interface & VODSP interface
+               rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP);
+               //enable power of VODSP I2S interface 
+               rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1,PWR_I2S_INTERFACE,PWR_I2S_INTERFACE);    
+               //select input/output of VODSP AEC
+               set_vodsp_aec_path(codec, AEC_mode);            
+
+       }
+       else
+       {
+               //disable VODSP AEC path
+               set_vodsp_aec_path(codec, VODSP_AEC_DISABLE);
+               //set VODSP AEC to power down mode                      
+               rt5625_write_mask(codec, RT5625_VODSP_CTL,0,VODSP_NO_PD_MODE_ENA);
+               //disable power of VODSP I2C interface & VODSP interface
+               rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3,0,PWR_VODSP_INTERFACE|PWR_I2C_FOR_VODSP);                                
+       }
+
+       return ret;
+}
+
+static void rt5625_aec_config(struct snd_soc_codec *codec, unsigned int mode)
+{
+       printk("rt5625_aec_config %d\n",mode);
+
+       if (mode == VODSP_AEC_DISABLE)
+       {
+               enable_vodsp_aec(codec,0, mode);        
+               /*disable LDO power*/
+               rt5625_write_mask(codec, RT5625_LDO_CTRL,0,LDO_ENABLE);
+       }
+       else
+       {
+               init_vodsp_aec(codec);
+       
+               enable_vodsp_aec(codec,1, mode);                
+       }
+}
+//****************************************************************************************************************
+//*
+//*function:disable rt5625's function.
+//*
+//*
+//****************************************************************************************************************
+static int rt5625_func_aec_disable(struct snd_soc_codec *codec,int mode)
+{
+
+       switch(mode)
+       {
+               case RT5625_AEC_PCM_IN_OUT:
+               case RT5625_AEC_IIS_IN_OUT:
+               case RT5625_AEC_ANALOG_IN_OUT:
+                       
+                       rt5625_aec_config(codec,VODSP_AEC_DISABLE);     //disable AEC function and path
+                       
+               break;
+               
+               default:
+
+               break;
+       }
+
+       return 0;
+}
+
+
+static int rt5625_get_dsp_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+        /*cause we choose bit[0][1] to store the mode type*/
+       int mode = (rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC)) & 0x03;  
+
+       ucontrol->value.integer.value[0] = mode;
+       return 0;
+}
+
+
+static int rt5625_set_dsp_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       u16 Virtual_reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC);
+       int rt5625_mode=(Virtual_reg)&0x03;
+
+       printk("1rt5625_mode=%d,value[0]=%ld,Virtual_reg=%x\n",rt5625_mode,ucontrol->value.integer.value[0],Virtual_reg);
+
+       if ( rt5625_mode == ucontrol->value.integer.value[0])
+               return 0;
+
+       switch(ucontrol->value.integer.value[0])
+       {
+               case RT5625_AEC_PCM_IN_OUT:
+
+                       rt5625_aec_config(codec,PCM_IN_PCM_OUT);//enable AEC PCM in/out function and path
+
+               break;
+
+               case RT5625_AEC_IIS_IN_OUT:
+
+                       rt5625_aec_config(codec,DAC_IN_ADC_OUT);//enable AEC IIS in/out function and path
+
+               break;
+
+               case RT5625_AEC_ANALOG_IN_OUT:
+                       
+                       rt5625_aec_config(codec,ANALOG_IN_ANALOG_OUT);//enable AEC analog in/out function and path
+                       
+               break;
+
+               case RT5625_AEC_DISABLE:
+       
+                       rt5625_func_aec_disable(codec,rt5625_mode);             //disable previous select function.     
+       
+               break;  
+
+               default:
+
+               break;
+       }
+
+       Virtual_reg &= 0xfffc;
+       Virtual_reg |= (ucontrol->value.integer.value[0]);
+       rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, Virtual_reg);
+
+       printk("2rt5625_mode=%d,value[0]=%ld,Virtual_reg=%x\n",rt5625_mode,ucontrol->value.integer.value[0],Virtual_reg);
+       return 0;
+}
+
+static int rt5625_dump_dsp_reg(struct snd_soc_codec *codec)
+{
+       int i;
+
+       rt5625_write_mask(codec, RT5625_VODSP_CTL, VODSP_NO_PD_MODE_ENA,VODSP_NO_PD_MODE_ENA);
+       for (i = 0; i < SET_VODSP_REG_INIT_NUM; i++) {
+               rt5625_read_vodsp_reg(codec, VODSP_AEC_Init_Value[i].VoiceDSPIndex);
+       }
+       return 0;
+}
+
+
+static int rt5625_dump_dsp_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       int mode = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC);
+
+       mode &= ~(0x01 << 8);
+       mode |= (ucontrol->value.integer.value[0] << 8);
+       rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, mode);
+       rt5625_dump_dsp_reg(codec);
+       
+       return 0;
+}
+
+static const struct snd_kcontrol_new rt5625_snd_controls[] = {
+SOC_ENUM_EXT("rt5625 aec mode sel", rt5625_enum[0], rt5625_get_dsp_mode, rt5625_set_dsp_mode),
+SOC_ENUM("SPK Amp Type", rt5625_enum[1]),
+SOC_ENUM("Left SPK Source", rt5625_enum[2]),
+SOC_ENUM("SPK Amp Ratio", rt5625_enum[7]),
+SOC_ENUM("Mic1 Boost", rt5625_enum[8]),
+SOC_ENUM("Mic2 Boost", rt5625_enum[9]),
+SOC_ENUM("Dmic Boost", rt5625_enum[10]),
+SOC_ENUM("ADCR Func", rt5625_enum[11]),
+SOC_DOUBLE("PCM Playback Volume", RT5625_STEREO_DAC_VOL, 8, 0, 63, 1),
+SOC_DOUBLE("LineIn Playback Volume", RT5625_LINE_IN_VOL, 8, 0, 31, 1),
+SOC_SINGLE("Phone Playback Volume", RT5625_PHONEIN_VOL, 8, 31, 1),
+SOC_SINGLE("Mic1 Playback Volume", RT5625_MIC_VOL, 8, 31, 1),
+SOC_SINGLE("Mic2 Playback Volume", RT5625_MIC_VOL, 0, 31, 1),
+SOC_DOUBLE("PCM Capture Volume", RT5625_ADC_REC_GAIN, 8, 0, 31, 1),
+SOC_DOUBLE("SPKOUT Playback Volume", RT5625_SPK_OUT_VOL, 8, 0, 31, 1),
+SOC_DOUBLE("SPKOUT Playback Switch", RT5625_SPK_OUT_VOL, 15, 7, 1, 1),
+SOC_DOUBLE("HPOUT Playback Volume", RT5625_HP_OUT_VOL, 8, 0, 31, 1),
+SOC_DOUBLE("HPOUT Playback Switch", RT5625_HP_OUT_VOL, 15, 7, 1, 1),
+SOC_DOUBLE("AUXOUT Playback Volume", RT5625_AUX_OUT_VOL, 8, 0, 31, 1),
+SOC_DOUBLE("AUXOUT Playback Switch", RT5625_AUX_OUT_VOL, 15, 7, 1, 1),
+SOC_DOUBLE("ADC Record Gain", RT5625_ADC_REC_GAIN, 8, 0, 31, 0),
+SOC_SINGLE_EXT("VoDSP Dump", VIRTUAL_REG_FOR_MISC_FUNC, 8, 1, 0,
+                       snd_soc_get_volsw, rt5625_dump_dsp_put),
+#if (RT5625_EQ_FUNC_ENA==1)                    
+SOC_ENUM_EXT("EQ Mode", rt5625_enum[12], snd_soc_get_enum_double, rt5625_eq_sel_put),                          
+#endif
+};
+
+static int rt5625_add_controls(struct snd_soc_codec *codec)
+{
+       int err, i;
+
+       for (i = 0; i < ARRAY_SIZE(rt5625_snd_controls); i++){
+               err = snd_ctl_add(codec->card, 
+                               snd_soc_cnew(&rt5625_snd_controls[i],
+                                               codec, NULL));
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static void hp_depop_mode2(struct snd_soc_codec *codec)
+{
+        rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN);
+        rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD3, PWR_HP_R_OUT_VOL|PWR_HP_L_OUT_VOL,
+                                                                                               PWR_HP_R_OUT_VOL|PWR_HP_L_OUT_VOL);
+        rt5625_write(codec, RT5625_MISC_CTRL,HP_DEPOP_MODE2_EN);
+               printk(KERN_INFO "delay 500 msec\n");
+        schedule_timeout_uninterruptible(msecs_to_jiffies(500));
+               
+
+        rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_HP_OUT_AMP|PWR_HP_OUT_ENH_AMP,
+                PWR_HP_OUT_AMP|PWR_HP_OUT_ENH_AMP);
+//        rt5625_write_mask(codec, RT5625_MISC_CTRL, 0, HP_DEPOP_MODE2_EN);
+
+}
+
+//enable depop function for mute/unmute
+static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute)
+{
+       if(mute)
+       {
+               rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN);
+               rt5625_write(codec, RT5625_MISC_CTRL,M_UM_DEPOP_EN|HP_R_M_UM_DEPOP_EN|HP_L_M_UM_DEPOP_EN);
+               //Mute headphone right/left channel
+               rt5625_write_mask(codec,RT5625_HP_OUT_VOL,RT_L_MUTE|RT_R_MUTE,RT_L_MUTE|RT_R_MUTE);     
+               mdelay(50);
+       }
+       else
+       {
+               rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD1, PWR_SOFTGEN_EN, PWR_SOFTGEN_EN);
+               rt5625_write(codec, RT5625_MISC_CTRL, M_UM_DEPOP_EN|HP_R_M_UM_DEPOP_EN|HP_L_M_UM_DEPOP_EN);
+               //unMute headphone right/left channel
+               rt5625_write_mask(codec,RT5625_HP_OUT_VOL,0,RT_L_MUTE|RT_R_MUTE);       
+               mdelay(50);
+       }
+
+}
+
+
+/*
+ * _DAPM_ Controls
+ */
+ /*Left ADC Rec mixer*/
+ /*Left ADC Rec mixer*/
+static const struct snd_kcontrol_new rt5625_left_adc_rec_mixer_controls[] = {
+SOC_DAPM_SINGLE("Mic1 Capture Switch", RT5625_ADC_REC_MIXER, 14, 1, 1),
+SOC_DAPM_SINGLE("Mic2 Capture Switch", RT5625_ADC_REC_MIXER, 13, 1, 1),
+SOC_DAPM_SINGLE("LineIn Capture Switch", RT5625_ADC_REC_MIXER, 12, 1, 1),
+SOC_DAPM_SINGLE("Phone Capture Switch", RT5625_ADC_REC_MIXER, 11, 1, 1),
+SOC_DAPM_SINGLE("HP Mixer Capture Switch", RT5625_ADC_REC_MIXER, 10, 1, 1),
+SOC_DAPM_SINGLE("SPK Mixer Capture Switch", RT5625_ADC_REC_MIXER, 9, 1, 1),
+SOC_DAPM_SINGLE("MoNo Mixer Capture Switch", RT5625_ADC_REC_MIXER, 8, 1, 1),
+
+};
+
+/*Left ADC Rec mixer*/
+static const struct snd_kcontrol_new rt5625_right_adc_rec_mixer_controls[] = {
+SOC_DAPM_SINGLE("Mic1 Capture Switch", RT5625_ADC_REC_MIXER, 6, 1, 1),
+SOC_DAPM_SINGLE("Mic2 Capture Switch", RT5625_ADC_REC_MIXER, 5, 1, 1),
+SOC_DAPM_SINGLE("LineIn Capture Switch", RT5625_ADC_REC_MIXER, 4, 1, 1),
+SOC_DAPM_SINGLE("Phone Capture Switch", RT5625_ADC_REC_MIXER, 3, 1, 1),
+SOC_DAPM_SINGLE("HP Mixer Capture Switch", RT5625_ADC_REC_MIXER, 2, 1, 1),
+SOC_DAPM_SINGLE("SPK Mixer Capture Switch", RT5625_ADC_REC_MIXER, 1, 1, 1),
+SOC_DAPM_SINGLE("MoNo Mixer Capture Switch", RT5625_ADC_REC_MIXER, 0, 1, 1),
+};
+
+/*Left hpmixer mixer*/
+static const struct snd_kcontrol_new rt5625_left_hp_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC Playback Switch", RT5625_ADC_REC_GAIN, 15, 1, 1),
+SOC_DAPM_SINGLE("LineIn Playback Switch", HPL_MIXER, 0, 1, 0),
+SOC_DAPM_SINGLE("Phone Playback Switch", HPL_MIXER, 1, 1, 0),
+SOC_DAPM_SINGLE("Mic1 Playback Switch", HPL_MIXER, 2, 1, 0),
+SOC_DAPM_SINGLE("Mic2 Playback Switch", HPL_MIXER, 3, 1, 0),
+SOC_DAPM_SINGLE("Voice DAC Playback Switch", HPL_MIXER, 4, 1, 0),
+SOC_DAPM_SINGLE("HIFI DAC Playback Switch", RT5625_DAC_AND_MIC_CTRL, 3, 1, 1),
+
+};
+
+/*Right hpmixer mixer*/
+static const struct snd_kcontrol_new rt5625_right_hp_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC Playback Switch", RT5625_ADC_REC_GAIN, 7, 1, 1),
+SOC_DAPM_SINGLE("LineIn Playback Switch", HPR_MIXER, 0, 1, 0),
+SOC_DAPM_SINGLE("Phone Playback Switch", HPR_MIXER, 1, 1, 0),
+SOC_DAPM_SINGLE("Mic1 Playback Switch", HPR_MIXER, 2, 1, 0),
+SOC_DAPM_SINGLE("Mic2 Playback Switch", HPR_MIXER, 3, 1, 0),
+SOC_DAPM_SINGLE("Voice DAC Playback Switch", HPR_MIXER, 4, 1, 0),
+SOC_DAPM_SINGLE("HIFI DAC Playback Switch", RT5625_DAC_AND_MIC_CTRL, 2, 1, 1),
+
+};
+
+/*mono mixer*/
+static const struct snd_kcontrol_new rt5625_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADCL Playback Switch", RT5625_ADC_REC_GAIN, 14, 1, 1),
+SOC_DAPM_SINGLE("ADCR Playback Switch", RT5625_ADC_REC_GAIN, 6, 1, 1),
+SOC_DAPM_SINGLE("Line Mixer Playback Switch", RT5625_LINE_IN_VOL, 13, 1, 1),
+SOC_DAPM_SINGLE("Mic1 Playback Switch", RT5625_DAC_AND_MIC_CTRL, 13, 1, 1),
+SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_AND_MIC_CTRL, 9, 1, 1),
+SOC_DAPM_SINGLE("DAC Mixer Playback Switch", RT5625_DAC_AND_MIC_CTRL, 0, 1, 1),
+SOC_DAPM_SINGLE("Voice DAC Playback Switch", RT5625_VOICE_DAC_OUT_VOL, 13, 1, 1),
+};
+
+/*speaker mixer*/
+static const struct snd_kcontrol_new rt5625_spk_mixer_controls[] = {
+SOC_DAPM_SINGLE("Line Mixer Playback Switch", RT5625_LINE_IN_VOL, 14, 1, 1),   
+SOC_DAPM_SINGLE("Phone Playback Switch", RT5625_PHONEIN_VOL, 14, 1, 1),
+SOC_DAPM_SINGLE("Mic1 Playback Switch", RT5625_DAC_AND_MIC_CTRL, 14, 1, 1),
+SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_AND_MIC_CTRL, 10, 1, 1),
+SOC_DAPM_SINGLE("DAC Mixer Playback Switch", RT5625_DAC_AND_MIC_CTRL, 1, 1, 1),
+SOC_DAPM_SINGLE("Voice DAC Playback Switch", RT5625_VOICE_DAC_OUT_VOL, 14, 1, 1),
+};
+
+static int mixer_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       unsigned int l, r;
+
+       printk(KERN_INFO "enter %s\n", __func__);
+
+       l= rt5625_read(codec, HPL_MIXER);
+       r = rt5625_read(codec, HPR_MIXER);
+       
+       if ((l & 0x1) || (r & 0x1))
+               rt5625_write_mask(codec, 0x0a, 0x0000, 0x8000);
+       else
+               rt5625_write_mask(codec, 0x0a, 0x8000, 0x8000);
+
+       if ((l & 0x2) || (r & 0x2))
+               rt5625_write_mask(codec, 0x08, 0x0000, 0x8000);
+       else
+               rt5625_write_mask(codec, 0x08, 0x8000, 0x8000);
+
+       if ((l & 0x4) || (r & 0x4))
+               rt5625_write_mask(codec, 0x10, 0x0000, 0x8000);
+       else
+               rt5625_write_mask(codec, 0x10, 0x8000, 0x8000);
+
+       if ((l & 0x8) || (r & 0x8))
+               rt5625_write_mask(codec, 0x10, 0x0000, 0x0800);
+       else
+               rt5625_write_mask(codec, 0x10, 0x0800, 0x0800);
+
+       if ((l & 0x10) || (r & 0x10))
+               rt5625_write_mask(codec, 0x18, 0x0000, 0x8000);
+       else
+               rt5625_write_mask(codec, 0x18, 0x8000, 0x8000);
+
+       return 0;
+}
+
+
+/*
+ *     bit[0][1] use for aec control
+ *     bit[2][3] for ADCR func
+ *     bit[4] for SPKL pga
+ *     bit[5] for SPKR pga
+ *     bit[6] for hpl pga
+ *     bit[7] for hpr pga
+ */
+static int spk_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+ {
+       struct snd_soc_codec *codec = w->codec;
+       int reg;
+       
+       printk(KERN_INFO "enter %s\n", __func__);
+       reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC) & (0x3 << 4);
+       if ((reg >> 4) != 0x3 && reg != 0)
+               return 0;
+
+       switch (event)
+       {
+               case SND_SOC_DAPM_POST_PMU:
+                       printk(KERN_INFO "after virtual spk power up!\n");
+                       rt5625_write_mask(codec, 0x3e, 0x3000, 0x3000);
+                       rt5625_write_mask(codec, 0x02, 0x0000, 0x8080);
+                       rt5625_write_mask(codec, 0x3a, 0x0400, 0x0400);//power on spk amp
+                       break;
+               case SND_SOC_DAPM_POST_PMD:
+                       printk(KERN_INFO "aftet virtual spk power down!\n");
+                       rt5625_write_mask(codec, 0x3a, 0x0000, 0x0400);//power off spk amp
+                       rt5625_write_mask(codec, 0x02, 0x8080, 0x8080);
+                       rt5625_write_mask(codec, 0x3e, 0x0000, 0x3000);                 
+                       break;
+               default:
+                       return 0;
+       }
+       return 0;
+}
+
+
+
+
+static int hp_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       int reg;
+
+       printk(KERN_INFO "enter %s\n", __func__);
+
+       reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC) & (0x3 << 6);
+       if ((reg >> 6) != 0x3 && reg != 0)
+               return 0;
+       
+       switch (event)
+       {
+               case SND_SOC_DAPM_POST_PMD:
+
+                       printk(KERN_INFO "aftet virtual hp power down!\n");
+
+                       hp_mute_unmute_depop(codec,1);//mute hp
+                       rt5625_write_mask(codec, 0x3a, 0x0000, 0x0300);
+                       rt5625_write_mask(codec, 0x3e, 0x0000, 0x0c00);                 
+                       break;
+
+               case SND_SOC_DAPM_POST_PMU:     
+
+                       printk(KERN_INFO "after virtual hp power up!\n");
+                       hp_depop_mode2(codec);
+                       hp_mute_unmute_depop(codec,0);//unmute hp
+                       break;
+
+               default:
+                       return 0;
+       }       
+
+       return 0;
+}
+
+
+
+static int aux_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+{
+       return 0;
+}
+
+/*SPKOUT Mux*/
+static const struct snd_kcontrol_new rt5625_spkout_mux_out_controls = 
+SOC_DAPM_ENUM("Route", rt5625_enum[3]);
+
+/*HPLOUT MUX*/
+static const struct snd_kcontrol_new rt5625_hplout_mux_out_controls = 
+SOC_DAPM_ENUM("Route", rt5625_enum[4]);
+
+/*HPROUT MUX*/
+static const struct snd_kcontrol_new rt5625_hprout_mux_out_controls = 
+SOC_DAPM_ENUM("Route", rt5625_enum[5]);
+/*AUXOUT MUX*/
+static const struct snd_kcontrol_new rt5625_auxout_mux_out_controls = 
+SOC_DAPM_ENUM("Route", rt5625_enum[6]);
+
+static const struct snd_soc_dapm_widget rt5625_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("Left LineIn"),
+SND_SOC_DAPM_INPUT("Right LineIn"),
+SND_SOC_DAPM_INPUT("Phone"),
+SND_SOC_DAPM_INPUT("Mic1"),
+SND_SOC_DAPM_INPUT("Mic2"),
+
+SND_SOC_DAPM_PGA("Mic1 Boost", RT5625_PWR_MANAG_ADD3, 1, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Mic2 Boost", RT5625_PWR_MANAG_ADD3, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback DAC", RT5625_PWR_MANAG_ADD2, 9, 0),
+SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback DAC", RT5625_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback DAC", RT5625_PWR_MANAG_ADD2, 10, 0),
+
+SND_SOC_DAPM_PGA("Left LineIn PGA", RT5625_PWR_MANAG_ADD3, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right LineIn PGA", RT5625_PWR_MANAG_ADD3, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Phone PGA", RT5625_PWR_MANAG_ADD3, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Mic1 PGA", RT5625_PWR_MANAG_ADD3, 3, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Mic2 PGA", RT5625_PWR_MANAG_ADD3, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA("VoDAC PGA", RT5625_PWR_MANAG_ADD1, 7, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Left Rec Mixer", RT5625_PWR_MANAG_ADD2, 1, 0,
+       &rt5625_left_adc_rec_mixer_controls[0], ARRAY_SIZE(rt5625_left_adc_rec_mixer_controls)),
+SND_SOC_DAPM_MIXER("Right Rec Mixer", RT5625_PWR_MANAG_ADD2, 0, 0,
+       &rt5625_right_adc_rec_mixer_controls[0], ARRAY_SIZE(rt5625_right_adc_rec_mixer_controls)),
+SND_SOC_DAPM_MIXER_E("Left HP Mixer", RT5625_PWR_MANAG_ADD2, 5, 0,
+       &rt5625_left_hp_mixer_controls[0], ARRAY_SIZE(rt5625_left_hp_mixer_controls),
+       mixer_event, SND_SOC_DAPM_POST_REG),
+SND_SOC_DAPM_MIXER_E("Right HP Mixer", RT5625_PWR_MANAG_ADD2, 4, 0,
+       &rt5625_right_hp_mixer_controls[0], ARRAY_SIZE(rt5625_right_hp_mixer_controls),
+       mixer_event, SND_SOC_DAPM_POST_REG),
+SND_SOC_DAPM_MIXER("MoNo Mixer", RT5625_PWR_MANAG_ADD2, 2, 0, 
+       &rt5625_mono_mixer_controls[0], ARRAY_SIZE(rt5625_mono_mixer_controls)),
+SND_SOC_DAPM_MIXER("SPK Mixer", RT5625_PWR_MANAG_ADD2, 3, 0,
+       &rt5625_spk_mixer_controls[0], ARRAY_SIZE(rt5625_spk_mixer_controls)),  
+SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("DAC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_MUX("SPKOUT Mux", SND_SOC_NOPM, 0, 0, &rt5625_spkout_mux_out_controls),
+SND_SOC_DAPM_MUX("HPLOUT Mux", SND_SOC_NOPM, 0, 0, &rt5625_hplout_mux_out_controls),
+SND_SOC_DAPM_MUX("HPROUT Mux", SND_SOC_NOPM, 0, 0, &rt5625_hprout_mux_out_controls),
+SND_SOC_DAPM_MUX("AUXOUT Mux", SND_SOC_NOPM, 0, 0, &rt5625_auxout_mux_out_controls),
+
+SND_SOC_DAPM_PGA_E("SPKL Out PGA", VIRTUAL_REG_FOR_MISC_FUNC, 4, 0, NULL, 0,
+                               spk_pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_PGA_E("SPKR Out PGA", VIRTUAL_REG_FOR_MISC_FUNC, 5, 0, NULL, 0,
+                               spk_pga_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_PGA_E("HPL Out PGA",VIRTUAL_REG_FOR_MISC_FUNC, 6, 0, NULL, 0, 
+                               hp_pga_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("HPR Out PGA",VIRTUAL_REG_FOR_MISC_FUNC, 7, 0, NULL, 0, 
+                               hp_pga_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("AUX Out PGA",RT5625_PWR_MANAG_ADD3, 14, 0, NULL, 0, 
+                               aux_pga_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                               
+SND_SOC_DAPM_ADC("Left ADC", "Left ADC HiFi Capture", RT5625_PWR_MANAG_ADD2, 7, 0),
+SND_SOC_DAPM_ADC("Right ADC", "Right ADC HiFi Capture", RT5625_PWR_MANAG_ADD2, 6, 0),
+SND_SOC_DAPM_OUTPUT("SPKL"),
+SND_SOC_DAPM_OUTPUT("SPKR"),
+SND_SOC_DAPM_OUTPUT("HPL"),
+SND_SOC_DAPM_OUTPUT("HPR"),
+SND_SOC_DAPM_OUTPUT("AUX"),
+SND_SOC_DAPM_MICBIAS("Mic1 Bias", RT5625_PWR_MANAG_ADD1, 3, 0),
+SND_SOC_DAPM_MICBIAS("Mic2 Bias", RT5625_PWR_MANAG_ADD1, 2, 0),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+               /*Input PGA*/
+
+               {"Left LineIn PGA", NULL, "Left LineIn"},
+               {"Right LineIn PGA", NULL, "Right LineIn"},
+               {"Phone PGA", NULL, "Phone"},
+               {"Mic1 Boost", NULL, "Mic1"},
+               {"Mic2 Boost", NULL, "Mic2"},
+               {"Mic1 PGA", NULL, "Mic1"},
+               {"Mic2 PGA", NULL, "Mic2"},
+               {"VoDAC PGA", NULL, "Voice DAC"},
+               
+               /*Left ADC mixer*/
+               {"Left Rec Mixer", "LineIn Capture Switch", "Left LineIn"},
+               {"Left Rec Mixer", "Phone Capture Switch", "Phone"},
+               {"Left Rec Mixer", "Mic1 Capture Switch", "Mic1 Boost"},
+               {"Left Rec Mixer", "Mic2 Capture Switch", "Mic2 Boost"},
+               {"Left Rec Mixer", "HP Mixer Capture Switch", "Left HP Mixer"},
+               {"Left Rec Mixer", "SPK Mixer Capture Switch", "SPK Mixer"},
+               {"Left Rec Mixer", "MoNo Mixer Capture Switch", "MoNo Mixer"},
+
+               /*Right ADC Mixer*/
+               {"Right Rec Mixer", "LineIn Capture Switch", "Right LineIn"},
+               {"Right Rec Mixer", "Phone Capture Switch", "Phone"},
+               {"Right Rec Mixer", "Mic1 Capture Switch", "Mic1 Boost"},
+               {"Right Rec Mixer", "Mic2 Capture Switch", "Mic2 Boost"},
+               {"Right Rec Mixer", "HP Mixer Capture Switch", "Right HP Mixer"},
+               {"Right Rec Mixer", "SPK Mixer Capture Switch", "SPK Mixer"},
+               {"Right Rec Mixer", "MoNo Mixer Capture Switch", "MoNo Mixer"},
+               
+               /*HPL mixer*/
+               {"Left HP Mixer", "ADC Playback Switch", "Left Rec Mixer"},
+               {"Left HP Mixer", "LineIn Playback Switch", "Left LineIn PGA"},
+               {"Left HP Mixer", "Phone Playback Switch", "Phone PGA"},
+               {"Left HP Mixer", "Mic1 Playback Switch", "Mic1 PGA"},
+               {"Left HP Mixer", "Mic2 Playback Switch", "Mic2 PGA"},
+               {"Left HP Mixer", "HIFI DAC Playback Switch", "Left DAC"},
+               {"Left HP Mixer", "Voice DAC Playback Switch", "VoDAC PGA"},
+               
+               /*HPR mixer*/
+               {"Right HP Mixer", "ADC Playback Switch", "Right Rec Mixer"},
+               {"Right HP Mixer", "LineIn Playback Switch", "Right LineIn PGA"},
+               {"Right HP Mixer", "HIFI DAC Playback Switch", "Right DAC"},
+               {"Right HP Mixer", "Phone Playback Switch", "Phone PGA"},
+               {"Right HP Mixer", "Mic1 Playback Switch", "Mic1 PGA"},
+               {"Right HP Mixer", "Mic2 Playback Switch", "Mic2 PGA"},
+               {"Right HP Mixer", "Voice DAC Playback Switch", "VoDAC PGA"},
+
+               /*DAC Mixer*/
+               {"DAC Mixer", NULL, "Left DAC"},
+               {"DAC Mixer", NULL, "Right DAC"},
+
+               /*line mixer*/
+               {"Line Mixer", NULL, "Left LineIn PGA"},
+               {"Line Mixer", NULL, "Right LineIn PGA"},
+
+               /*spk mixer*/
+               {"SPK Mixer", "Line Mixer Playback Switch", "Line Mixer"},
+               {"SPK Mixer", "Phone Playback Switch", "Phone PGA"},
+               {"SPK Mixer", "Mic1 Playback Switch", "Mic1 PGA"},
+               {"SPK Mixer", "Mic2 Playback Switch", "Mic2 PGA"},
+               {"SPK Mixer", "DAC Mixer Playback Switch", "DAC Mixer"},
+               {"SPK Mixer", "Voice DAC Playback Switch", "VoDAC PGA"},
+
+               /*mono mixer*/
+               {"MoNo Mixer", "Line Mixer Playback Switch", "Line Mixer"},
+               {"MoNo Mixer", "ADCL Playback Switch","Left Rec Mixer"},
+               {"MoNo Mixer", "ADCR Playback Switch","Right Rec Mixer"},
+               {"MoNo Mixer", "Mic1 Playback Switch", "Mic1 PGA"},
+               {"MoNo Mixer", "Mic2 Playback Switch", "Mic2 PGA"},
+               {"MoNo Mixer", "DAC Mixer Playback Switch", "DAC Mixer"},
+               {"MoNo Mixer", "Voice DAC Playback Switch", "VoDAC PGA"},
+               
+               /*hp mixer*/
+               {"HP Mixer", NULL, "Left HP Mixer"},
+               {"HP Mixer", NULL, "Right HP Mixer"},
+
+               /*spkout mux*/
+               {"SPKOUT Mux", "HP Mixer", "HP Mixer"},
+               {"SPKOUT Mux", "SPK Mixer", "SPK Mixer"},
+               {"SPKOUT Mux", "Mono Mixer", "MoNo Mixer"},
+               
+               /*hpl out mux*/
+               {"HPLOUT Mux", "HPL Mixer", "Left HP Mixer"},
+               
+               /*hpr out mux*/
+               {"HPROUT Mux", "HPR Mixer", "Right HP Mixer"},
+
+               /*aux out mux*/
+               {"AUXOUT Mux", "HP Mixer", "HP Mixer"},
+               {"AUXOUT Mux", "SPK Mixer", "SPK Mixer"},
+               {"SPKOUT Mux", "Mono Mixer", "MoNo Mixer"},
+
+               /*spkl out pga*/
+               {"SPKL Out PGA", NULL, "SPKOUT Mux"},
+               
+               
+               /*spkr out pga*/
+               {"SPKR Out PGA", NULL, "SPKOUT Mux"},
+               
+               /*hpl out pga*/
+               {"HPL Out PGA", NULL, "HPLOUT Mux"},
+
+               /*hpr out pga*/
+               {"HPR Out PGA", NULL, "HPROUT Mux"},
+
+               /*aux out pga*/
+               {"AUX Out PGA", NULL, "AUXOUT Mux"}, 
+               
+               /*left adc*/
+               {"Left ADC", NULL, "Left Rec Mixer"},
+               
+               /*right adc*/
+               {"Right ADC", NULL, "Right Rec Mixer"},
+               
+               /*output*/
+               {"SPKL", NULL, "SPKL Out PGA"},
+               {"SPKR", NULL, "SPKR Out PGA"},
+               {"HPL", NULL, "HPL Out PGA"},
+               {"HPR", NULL, "HPR Out PGA"},
+               {"AUX", NULL, "AUX Out PGA"},
+};
+
+
+static int rt5625_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, rt5625_dapm_widgets, 
+                               ARRAY_SIZE(rt5625_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+       snd_soc_dapm_new_widgets(codec);
+
+       return 0;
+}
+
+struct _pll_div{
+       u32 pll_in;
+       u32 pll_out;
+       u16 regvalue;
+};
+
+
+/**************************************************************
+  *    watch out!
+  *    our codec support you to select different source as pll input, but if you 
+  *    use both of the I2S audio interface and pcm interface instantially. 
+  *    The two DAI must have the same pll setting params, so you have to offer
+  *    the same pll input, and set our codec's sysclk the same one, we suggest 
+  *    24576000.
+  **************************************************************/
+static const struct _pll_div codec_master_pll1_div[] = {
+               
+       {  2048000,  8192000,   0x0ea0},
+       {  3686400,  8192000,   0x4e27},
+       { 12000000,  8192000,   0x456b},
+       { 13000000,  8192000,   0x495f},
+       { 13100000,      8192000,       0x0320},
+       {  2048000,  11289600,  0xf637},
+       {  3686400,  11289600,  0x2f22},
+       { 12000000,  11289600,  0x3e2f},
+       { 13000000,  11289600,  0x4d5b},
+       { 13100000,      11289600,      0x363b},
+       {  2048000,  16384000,  0x1ea0},
+       {  3686400,  16384000,  0x9e27},
+       { 12000000,  16384000,  0x452b},
+       { 13000000,  16384000,  0x542f},
+       { 13100000,      16384000,      0x03a0},
+       {  2048000,  16934400,  0xe625},
+       {  3686400,  16934400,  0x9126},
+       { 12000000,  16934400,  0x4d2c},
+       { 13000000,  16934400,  0x742f},
+       { 13100000,      16934400,      0x3c27},
+       {  2048000,  22579200,  0x2aa0},
+       {  3686400,  22579200,  0x2f20},
+       { 12000000,  22579200,  0x7e2f},
+       { 13000000,  22579200,  0x742f},
+       { 13100000,      22579200,      0x3c27},
+       {  2048000,  24576000,  0x2ea0},
+       {  3686400,  24576000,  0xee27},
+       { 12000000,  24576000,  0x2915},
+       { 13000000,  24576000,  0x772e},
+       { 13100000,      24576000,      0x0d20},
+       { 26000000,  24576000,  0x2027},
+       { 26000000,  22579200,  0x392f},
+       { 24576000,  22579200,  0x0921},
+       { 24576000,  24576000,  0x02a0},
+};
+
+static const struct _pll_div codec_bclk_pll1_div[] = {
+
+       {   256000,   4096000,  0x3ea0},
+       {       352800,   5644800,      0x3ea0},
+       {       512000,   8192000,      0x3ea0},
+       {       705600,  11289600,      0x3ea0},
+       {  1024000,  16384000,  0x3ea0},        
+       {  1411200,  22579200,  0x3ea0},
+       {  1536000,      24576000,      0x3ea0},        
+       {  2048000,  16384000,  0x1ea0},        
+       {  2822400,  22579200,  0x1ea0},
+       {  3072000,      24576000,      0x1ea0},
+       {       705600,  11289600,      0x3ea0},
+       {       705600,   8467200,      0x3ab0},
+       {  2822400,      11289600,      0x1ee0},
+       {  3072000,      12288000,      0x1ee0},                        
+};
+
+static const struct _pll_div codec_vbclk_pll1_div[] = {
+       {   256000,   4096000,  0x3ea0},
+       {       352800,   5644800,      0x3ea0},
+       {       512000,   8192000,      0x3ea0},
+       {       705600,  11289600,      0x3ea0},
+       {  1024000,  16384000,  0x3ea0},        
+       {  1411200,  22579200,  0x3ea0},
+       {  1536000,      24576000,      0x3ea0},        
+       {  2048000,  16384000,  0x1ea0},        
+       {  2822400,  22579200,  0x1ea0},
+       {  3072000,      24576000,      0x1ea0},
+       {       705600,  11289600,      0x3ea0},
+       {       705600,   8467200,      0x3ab0},
+};
+
+
+struct _coeff_div_stereo {
+       unsigned int mclk;
+       unsigned int rate;
+       unsigned int reg60;
+       unsigned int reg62;
+};
+
+struct _coeff_div_voice {
+       unsigned int mclk;
+       unsigned int rate;
+       unsigned int reg64;
+};
+
+static const struct _coeff_div_stereo coeff_div_stereo[] = {
+               /*bclk is config to 32fs, if codec is choose to be slave mode , input bclk should be 32*fs */
+               {24576000, 48000, 0x3174, 0x1010},      
+               {12288000, 48000, 0x1174, 0x0000},
+               {18432000, 48000, 0x2174, 0x1111},
+               {36864000, 48000, 0x2274, 0x2020},
+               {49152000, 48000, 0xf074, 0x3030},
+        {24576000, 48000, 0x3172,0x1010},
+        {24576000,  8000, 0xB274,0x2424},
+        {24576000, 16000, 0xB174,0x2222},
+        {24576000, 32000, 0xB074,0x2121},
+        {22579200, 11025, 0X3374,0x1414},
+        {22579200, 22050, 0X3274,0x1212},
+        {22579200, 44100, 0X3174,0x1010},
+               
+               {0, 0, 0, 0},
+};
+
+static const struct _coeff_div_voice coeff_div_voice[] = {
+               /*bclk is config to 32fs, if codec is choose to be slave mode , input bclk should be 32*fs */
+               {24576000, 16000, 0x2622}, 
+               {24576000, 8000, 0x2824},
+               {0, 0, 0},
+};
+
+static int get_coeff(unsigned int mclk, unsigned int rate, int mode)
+{
+       int i;
+
+       printk("get_coeff mclk = %d, rate = %d\n", mclk, rate);
+       if (!mode){
+               for (i = 0; i < ARRAY_SIZE(coeff_div_stereo); i++) {
+                       if ((coeff_div_stereo[i].rate == rate) && (coeff_div_stereo[i].mclk == mclk))
+                               return i;
+               }
+       }
+       else {
+               for (i = 0; i< ARRAY_SIZE(coeff_div_voice); i++) {
+                       if ((coeff_div_voice[i].rate == rate) && (coeff_div_voice[i].mclk == mclk))
+                               return i;
+               }
+       }
+
+       return -EINVAL;
+       printk(KERN_ERR "can't find a matched mclk and rate in %s\n", 
+                               (mode ? "coeff_div_voice[]" : "coeff_div_audio[]"));
+}
+
+
+static int rt5625_codec_set_dai_pll(struct snd_soc_dai *codec_dai, 
+               int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+       int i;
+       int ret = -EINVAL;
+       struct snd_soc_codec *codec = codec_dai->codec;
+
+       printk(KERN_DEBUG "enter %s\n", __func__);
+
+       if (pll_id < RT5625_PLL1_FROM_MCLK || pll_id > RT5625_PLL1_FROM_VBCLK)
+               return -EINVAL;
+
+       if (!freq_in || !freq_out)
+               return 0;
+
+       if (RT5625_PLL1_FROM_MCLK == pll_id)
+       {
+               for (i = 0; i < ARRAY_SIZE(codec_master_pll1_div); i ++)
+               {
+                       if ((freq_in == codec_master_pll1_div[i].pll_in) && (freq_out == codec_master_pll1_div[i].pll_out))
+                       {
+                               rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x0000);                                       /*PLL source from MCLK*/
+                               rt5625_write(codec, RT5625_PLL_CTRL, codec_master_pll1_div[i].regvalue);   /*set pll code*/
+                               rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000);                        /*enable pll1 power*/
+                               rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000);
+                               ret = 0;
+                       }
+               }
+       }
+       else if (RT5625_PLL1_FROM_BCLK == pll_id)
+       {
+               for (i = 0; i < ARRAY_SIZE(codec_bclk_pll1_div); i ++)
+               {
+                       if ((freq_in == codec_bclk_pll1_div[i].pll_in) && (freq_out == codec_bclk_pll1_div[i].pll_out))
+                       {
+                               rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x2000);                                      /*PLL source from BCLK*/
+                               rt5625_write(codec, RT5625_PLL_CTRL, codec_bclk_pll1_div[i].regvalue);   /*set pll1 code*/
+                               rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000);         /*enable pll1 power*/
+                               rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000);
+                               ret = 0;
+                       }
+               }
+       }
+       else if (RT5625_PLL1_FROM_VBCLK == pll_id)
+       {
+               for (i = 0; i < ARRAY_SIZE(codec_vbclk_pll1_div); i ++)
+               {
+                       if ((freq_in == codec_vbclk_pll1_div[i].pll_in) && (freq_out == codec_vbclk_pll1_div[i].pll_out))
+                       {
+                               rt5625_write(codec, RT5625_GEN_CTRL_REG2, 0x3000);                                      /*PLL source from VBCLK*/
+                               rt5625_write(codec, RT5625_PLL_CTRL, codec_vbclk_pll1_div[i].regvalue);   /*set pll1 code*/
+                               rt5625_write_mask(codec, RT5625_PWR_MANAG_ADD2, 0x8000, 0x8000);         /*enable pll1 power*/
+                               rt5625_write_mask(codec, RT5625_GEN_CTRL_REG1, 0x8000, 0x8000);
+                               ret = 0;
+                       }
+               }
+       }
+       
+       
+       return 0;
+}
+
+
+static int rt5625_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, 
+               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct rt5625_priv * rt5625 = codec->private_data;
+       printk(KERN_DEBUG "enter %s\n", __func__);
+       
+       if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
+               rt5625->stereo_sysclk = freq;
+               return 0;
+       }
+       
+       printk(KERN_ERR "unsupported sysclk freq %u for audio i2s\n", freq);
+       rt5625->stereo_sysclk=24576000;
+       
+       return 0;
+}
+
+static int rt5625_voice_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, 
+               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct rt5625_priv * rt5625 = codec->private_data;
+       
+
+       if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
+               rt5625->voice_sysclk = freq;
+               return 0;
+       }                       
+
+       printk(KERN_ERR "unsupported sysclk freq %u for voice pcm\n", freq);
+       rt5625->voice_sysclk = 24576000;
+       
+       return 0;
+}
+
+
+static int rt5625_hifi_pcm_hw_params(struct snd_pcm_substream *substream, 
+                       struct snd_pcm_hw_params *params,
+                       struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->card->codec;
+       struct rt5625_priv *rt5625 = codec->private_data;
+
+       unsigned int iface = rt5625_read(codec, RT5625_MAIN_SDP_CTRL) & 0xfff3;
+       int rate = params_rate(params);
+       int coeff = get_coeff(rt5625->stereo_sysclk, rate, 0);
+       
+       printk(KERN_DEBUG "enter %s\n", __func__);
+
+
+       switch (params_format(params))
+       {
+               case SNDRV_PCM_FORMAT_S16_LE:
+                       break;
+               case SNDRV_PCM_FORMAT_S20_3LE:
+                       iface |= 0x0004;
+               case SNDRV_PCM_FORMAT_S24_LE:
+                       iface |= 0x0008;
+               case SNDRV_PCM_FORMAT_S8:
+                       iface |= 0x000c;
+       }
+
+
+       
+       rt5625_write(codec, RT5625_MAIN_SDP_CTRL, iface);
+       rt5625_write_mask(codec, 0x3a, 0xc801, 0xc801);   /*power i2s and dac ref*/
+       if (coeff >= 0) {
+               rt5625_write(codec, RT5625_STEREO_DAC_CLK_CTRL1, coeff_div_stereo[coeff].reg60);
+               rt5625_write(codec, RT5625_STEREO_DAC_CLK_CTRL2, coeff_div_stereo[coeff].reg62);
+       }
+       
+       return 0;
+}
+
+static int rt5625_voice_pcm_hw_params(struct snd_pcm_substream *substream, 
+                       struct snd_pcm_hw_params *params,
+                       struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->card->codec;
+       struct rt5625_priv *rt5625 = codec->private_data;
+       struct snd_soc_dapm_widget *w;
+       unsigned int iface = rt5625_read(codec, RT5625_EXTEND_SDP_CTRL) & 0xfff3;
+       int rate = params_rate(params);
+       int coeff = get_coeff(rt5625->voice_sysclk, rate, 1);
+
+       printk(KERN_DEBUG "enter %s\n", __func__);
+
+       list_for_each_entry(w, &codec->dapm_widgets, list)
+       {
+               if (!w->sname)
+                       continue;
+               if (!strcmp(w->name, "Right ADC"))
+                       strcpy(w->sname, "Right ADC Voice Capture");
+       }
+       
+       switch (params_format(params))
+       {
+               case SNDRV_PCM_FORMAT_S16_LE:
+                       break;
+               case SNDRV_PCM_FORMAT_S20_3LE:
+                       iface |= 0x0004;
+               case SNDRV_PCM_FORMAT_S24_LE:
+                       iface |= 0x0008;
+               case SNDRV_PCM_FORMAT_S8:
+                       iface |= 0x000c;
+       }
+       rt5625_write_mask(codec, 0x3a, 0x0801, 0x0801);   /*power i2s and dac ref*/
+       rt5625_write(codec, RT5625_EXTEND_SDP_CTRL, iface);
+       if (coeff >= 0)
+               rt5625_write(codec, RT5625_VOICE_DAC_PCMCLK_CTRL1, coeff_div_voice[coeff].reg64);
+
+       return 0;
+}
+
+
+static int rt5625_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 iface = 0;
+
+       printk(KERN_DEBUG "enter %s\n", __func__);
+
+       /*set master/slave interface*/
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK)
+       {
+               case SND_SOC_DAIFMT_CBM_CFM:
+                       iface = 0x0000;
+                       break;
+               case SND_SOC_DAIFMT_CBS_CFS:
+                       iface = 0x8000;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       /*interface format*/
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK)
+       {
+               case SND_SOC_DAIFMT_I2S:
+                       iface |= 0x0000;
+                       break;
+               case SND_SOC_DAIFMT_LEFT_J:
+                       iface |= 0x0001;
+                       break;
+               case SND_SOC_DAIFMT_DSP_A:
+                       iface |= 0x0002;
+                       break;
+               case SND_SOC_DAIFMT_DSP_B:
+                       iface |= 0x0003;
+                       break;
+               default:
+                       return -EINVAL;                 
+       }
+
+       /*clock inversion*/
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK)
+       {
+               case SND_SOC_DAIFMT_NB_NF:
+                       iface |= 0x0000;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       iface |= 0x0080;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       rt5625_write(codec, RT5625_MAIN_SDP_CTRL, iface);
+       return 0;
+}
+
+static int rt5625_voice_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       int iface;
+
+       printk(KERN_DEBUG "enter %s\n", __func__);
+       /*set slave/master mode*/
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK)
+       {
+               case SND_SOC_DAIFMT_CBM_CFM:
+                       iface = 0x0000;
+                       break;
+               case SND_SOC_DAIFMT_CBS_CFS:
+                       iface = 0x4000;
+                       break;
+               default:
+                       return -EINVAL;                 
+       }
+
+       switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK)
+       {
+               case SND_SOC_DAIFMT_I2S:
+                       iface |= 0x0000;
+                       break;
+               case SND_SOC_DAIFMT_LEFT_J:
+                       iface |= 0x0001;
+                       break;
+               case SND_SOC_DAIFMT_DSP_A:
+                       iface |= 0x0002;
+                       break;
+               case SND_SOC_DAIFMT_DSP_B:
+                       iface |= 0x0003;
+                       break;
+               default:
+                       return -EINVAL;         
+       }
+
+       /*clock inversion*/
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK)
+       {
+               case SND_SOC_DAIFMT_NB_NF:
+                       iface |= 0x0000;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       iface |= 0x0080;
+                       break;
+               default:
+                       return -EINVAL;                 
+       }
+
+       iface |= 0x8000;      /*enable vopcm*/
+       rt5625_write(codec, RT5625_EXTEND_SDP_CTRL, iface);     
+       return 0;
+}
+
+
+static int rt5625_hifi_codec_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       
+       if (mute) 
+               rt5625_write_mask(codec, RT5625_STEREO_DAC_VOL, 0x8080, 0x8080);
+       else
+               rt5625_write_mask(codec, RT5625_STEREO_DAC_VOL, 0x0000, 0x8080);
+       return 0;
+}
+
+static int rt5625_voice_codec_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+
+       if (mute)
+               rt5625_write_mask(codec, RT5625_VOICE_DAC_OUT_VOL, 0x1000, 0x1000);
+       else 
+               rt5625_write_mask(codec, RT5625_VOICE_DAC_OUT_VOL, 0x0000, 0x1000);
+       return 0;
+}
+
+
+static int rt5625_set_bias_level(struct snd_soc_codec *codec, 
+                       enum snd_soc_bias_level level)
+{
+       switch(level) {
+       case SND_SOC_BIAS_ON:
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               rt5625_write(codec, 0x26, 0x0000);
+               rt5625_write_mask(codec, 0x3c, 0x2000, 0x2000);     
+               rt5625_write_mask(codec, 0x3a, 0x000e, 0x000e);         
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               break;
+       case SND_SOC_BIAS_OFF:
+               rt5625_write_mask(codec, 0x04, 0x8080, 0x8080);        /*mute hp*/
+               rt5625_write_mask(codec, 0x02, 0x8080, 0x8080);        /*mute spk*/
+               rt5625_write(codec, 0x3e, 0x0000);                                      //power off all bit
+               rt5625_write(codec, 0x3a, 0x0000);                                      //power off all bit
+               rt5625_write(codec, 0x3c, 0x0000);                                      //power off all bit
+               
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+
+#define RT5625_STEREO_RATES    SNDRV_PCM_RATE_8000_48000
+
+#define RT5626_VOICE_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000)
+
+#define RT5625_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                       SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE |\
+                       SNDRV_PCM_FMTBIT_S8)
+
+static struct snd_soc_dai_ops rt5625_dai_ops_hifi = {
+
+       .hw_params      = rt5625_hifi_pcm_hw_params,
+//     .digital_mute   = rt5625_hifi_codec_mute,
+       .set_fmt        = rt5625_hifi_codec_set_dai_fmt,
+       .set_pll        = rt5625_codec_set_dai_pll,
+       .set_sysclk     = rt5625_hifi_codec_set_dai_sysclk,
+
+};
+
+
+static struct snd_soc_dai_ops rt5625_dai_ops_voice = {
+
+       .hw_params      = rt5625_voice_pcm_hw_params,
+//     .digital_mute   = rt5625_voice_codec_mute,
+       .set_fmt        = rt5625_voice_codec_set_dai_fmt,
+       .set_pll        = rt5625_codec_set_dai_pll,
+       .set_sysclk     = rt5625_voice_codec_set_dai_sysclk,
+
+};
+
+
+
+struct snd_soc_dai rt5625_dai[] = {
+       /*hifi codec dai*/
+       {
+               .name = "RT5625 HiFi",
+               .id = 1,
+               .playback = {
+                       .stream_name = "HiFi Playback",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = RT5625_STEREO_RATES,
+                       .formats = RT5625_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "HiFi Capture",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = RT5625_STEREO_RATES,
+                       .formats = RT5625_FORMATS,
+               },
+               
+               .ops = &rt5625_dai_ops_hifi,
+       },
+
+       /*voice codec dai*/
+       {
+               .name = "RT5625 Voice",
+               .id = 2,
+               .playback = {
+                       .stream_name = "Voice Playback",
+                       .channels_min = 1,
+                       .channels_max =1,
+                       .rates = RT5626_VOICE_RATES,
+                       .formats = RT5625_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "Voice Capture",
+                       .channels_min = 1,
+                       .channels_max = 1,
+                       .rates = RT5626_VOICE_RATES,
+                       .formats = RT5625_FORMATS,
+               },
+               
+               .ops = &rt5625_dai_ops_voice,
+
+       },
+};
+
+EXPORT_SYMBOL_GPL(rt5625_dai);
+
+
+static void rt5625_work(struct work_struct *work)
+{
+       struct snd_soc_codec *codec =
+                container_of(work, struct snd_soc_codec, delayed_work.work);
+       rt5625_set_bias_level(codec, codec->bias_level);
+}
+
+
+#if defined(CONFIG_SND_HWDEP)
+
+#if REALTEK_HWDEP
+
+#define RT_CE_CODEC_HWDEP_NAME "rt56xx hwdep "
+
+
+static int rt56xx_hwdep_open(struct snd_hwdep *hw, struct file *file)
+{
+       printk("enter %s\n", __func__);
+       return 0;
+}
+
+static int rt56xx_hwdep_release(struct snd_hwdep *hw, struct file *file)
+{
+       printk("enter %s\n", __func__);
+       return 0;
+}
+
+
+static int rt56xx_hwdep_ioctl_common(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct rt56xx_cmd rt56xx;
+       struct rt56xx_cmd __user *_rt56xx = arg;
+       struct rt56xx_reg_state *buf;
+       struct rt56xx_reg_state *p;
+       struct snd_soc_codec *codec = hw->private_data;
+
+       if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx)))
+               return -EFAULT;
+       buf = kmalloc(sizeof(*buf) * rt56xx.number, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+       if (copy_from_user(buf, rt56xx.buf, sizeof(*buf) * rt56xx.number)) {
+               goto err;
+       }
+       switch (cmd) {
+               case RT_READ_CODEC_REG_IOCTL:
+                       for (p = buf; p < buf + rt56xx.number; p++)
+                       {
+                               p->reg_value = codec->read(codec, p->reg_index);
+                       }
+                       if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
+                               goto err;
+                               
+                       break;
+               case RT_WRITE_CODEC_REG_IOCTL:
+                       for (p = buf; p < buf + rt56xx.number; p++)
+                               codec->write(codec, p->reg_index, p->reg_value);
+                       break;
+       }
+
+       kfree(buf);
+       return 0;
+
+err:
+       kfree(buf);
+       return -EFAULT;
+       
+}
+
+static int rt56xx_codec_dump_reg(struct snd_hwdep *hw, struct file *file, unsigned long arg)
+{
+       struct rt56xx_cmd rt56xx;
+       struct rt56xx_cmd __user *_rt56xx = arg;
+       struct rt56xx_reg_state *buf;
+       struct snd_soc_codec *codec = hw->private_data;
+       int number = codec->reg_cache_size;
+       int i;
+
+       printk(KERN_DEBUG "enter %s, number = %d\n", __func__, number); 
+       if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx)))
+               return -EFAULT;
+       
+       buf = kmalloc(sizeof(*buf) * number, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       for (i = 0; i < number; i++)
+       {
+               buf[i].reg_index = i << 1;
+               buf[i].reg_value = codec->read(codec, buf[i].reg_index);
+       }
+       if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * i))
+               goto err;
+       rt56xx.number = number;
+       if (copy_to_user(_rt56xx, &rt56xx, sizeof(rt56xx)))
+               goto err;
+       kfree(buf);
+       return 0;
+err:
+       kfree(buf);
+       return -EFAULT;
+       
+}
+
+static int rt56xx_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       if (cmd == RT_READ_ALL_CODEC_REG_IOCTL)
+       {
+               return rt56xx_codec_dump_reg(hw, file, arg);
+       }
+       else
+       {
+               return rt56xx_hwdep_ioctl_common(hw, file, cmd, arg);
+       }
+}
+
+int realtek_ce_init_hwdep(struct snd_soc_codec *codec)
+{
+       struct snd_hwdep *hw;
+       struct snd_card *card = codec->card;
+       int err;
+
+       if ((err = snd_hwdep_new(card, RT_CE_CODEC_HWDEP_NAME, 0, &hw)) < 0)
+               return err;
+       
+       strcpy(hw->name, RT_CE_CODEC_HWDEP_NAME);
+       hw->private_data = codec;
+       hw->ops.open = rt56xx_hwdep_open;
+       hw->ops.release = rt56xx_hwdep_release;
+       hw->ops.ioctl = rt56xx_hwdep_ioctl;
+       return 0;
+}
+
+#endif
+
+#endif
+
+static int rt5625_init(struct snd_soc_device *socdev)
+{
+
+       struct snd_soc_codec *codec = socdev->card->codec;
+       int ret = 0;
+
+       codec->name = "RT5625";
+       codec->owner = THIS_MODULE;
+       codec->read = rt5625_read;
+       codec->write = rt5625_write;
+       codec->set_bias_level = rt5625_set_bias_level;
+       codec->dai= rt5625_dai;
+       codec->num_dai = 2;
+       codec->reg_cache_step = 2;              
+       codec->reg_cache_size = ARRAY_SIZE(rt5625_reg)*2;
+       codec->reg_cache = kmemdup(rt5625_reg, sizeof(rt5625_reg), GFP_KERNEL);
+       if (codec->reg_cache == NULL)
+               return -ENOMEM;
+
+       rt5625_reset(codec);
+
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0 )
+       {
+               printk(KERN_ERR "rt5625:  failed to create pcms\n");
+               goto pcm_err;
+       }
+       
+       rt5625_write(codec, RT5625_PD_CTRL_STAT, 0);
+       rt5625_write(codec, RT5625_PWR_MANAG_ADD1, PWR_MAIN_BIAS);
+       rt5625_write(codec, RT5625_PWR_MANAG_ADD2, PWR_MIXER_VREF);
+       rt5625_reg_init(codec);
+       rt5625_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+       codec->bias_level = SND_SOC_BIAS_STANDBY;
+       schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(80));
+
+#if (RT5625_EQ_FUNC_ENA==1)    
+       rt5625_update_eqmode(codec,POP);
+#endif
+       
+       rt5625_add_controls(codec);
+       rt5625_add_widgets(codec);
+
+       #if defined(CONFIG_SND_HWDEP)
+
+               #if REALTEK_HWDEP
+
+                realtek_ce_init_hwdep(codec);
+
+               #endif
+
+       #endif
+
+       ret = snd_soc_init_card(socdev);
+
+       if (ret < 0)
+       {
+               printk(KERN_ERR "rt5625: failed to register card\n");
+               goto card_err;
+       }
+       printk(KERN_DEBUG "rt5625: initial ok\n");
+       return 0;
+
+       card_err:
+               snd_soc_free_pcms(socdev);
+               snd_soc_dapm_free(socdev);
+       
+       pcm_err:
+               kfree(codec->reg_cache);
+               return ret;
+       
+       
+}
+
+
+static int rt5625_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+       struct snd_soc_device *socdev = rt5625_socdev;
+       struct snd_soc_codec *codec = socdev->card->codec;
+       int ret;
+
+       i2c_set_clientdata(i2c, codec);
+       codec->control_data = i2c;
+
+       ret = rt5625_init(socdev);
+       if (ret < 0)
+               pr_err("failed to initialise rt5625\n");
+
+       return ret;
+}
+
+static int rt5625_i2c_remove(struct i2c_client *client)
+{
+       struct snd_soc_codec *codec = i2c_get_clientdata(client);
+       kfree(codec->reg_cache);
+       return 0;
+}
+
+static const struct i2c_device_id rt5625_i2c_id[] = {
+               {"rt5625", 0},
+               {}
+};
+MODULE_DEVICE_TABLE(i2c, rt5625_i2c_id);
+static struct i2c_driver rt5625_i2c_driver = {
+       .driver = {
+               .name = "RT5625 I2C Codec",
+               .owner = THIS_MODULE,
+       },
+       .probe =    rt5625_i2c_probe,
+       .remove =   rt5625_i2c_remove,
+       .id_table = rt5625_i2c_id,
+};
+
+
+static int rt5625_add_i2c_device(struct platform_device *pdev,
+                                const struct rt5625_setup_data *setup)
+{
+#if 0
+       struct i2c_board_info info;
+       struct i2c_adapter *adapter;
+       struct i2c_client *client;
+#endif
+       int ret;
+
+       ret = i2c_add_driver(&rt5625_i2c_driver);
+       if (ret != 0) {
+               dev_err(&pdev->dev, "can't add i2c driver\n");
+               return ret;
+       }
+#if 0
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       info.addr = setup->i2c_address;
+       strlcpy(info.type, "rt5625", I2C_NAME_SIZE);
+
+       adapter = i2c_get_adapter(setup->i2c_bus);
+       if (!adapter) {
+               dev_err(&pdev->dev, "can't get i2c adapter %d\n",
+                       setup->i2c_bus);
+               goto err_driver;
+       }
+
+       client = i2c_new_device(adapter, &info);
+       i2c_put_adapter(adapter);
+       if (!client) {
+               dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
+                       (unsigned int)info.addr);
+               goto err_driver;
+       }
+#endif
+       return 0;
+#if 0
+err_driver:
+       i2c_del_driver(&rt5625_i2c_driver);
+       return -ENODEV;
+#endif
+}
+
+
+static int rt5625_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct rt5625_setup_data *setup;
+       struct snd_soc_codec *codec;
+       struct rt5625_priv *rt5625;
+       int ret;
+
+       pr_info("RT5625 Audio Codec %s", RT5625_VERSION);
+
+       if(socdev->codec_data)
+       {
+               setup = socdev->codec_data;             
+       }
+
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+
+       rt5625 = kzalloc(sizeof(struct rt5625_priv), GFP_KERNEL);
+       if (rt5625 == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
+       codec->private_data = rt5625;
+       socdev->card->codec = codec;
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+       rt5625_socdev = socdev;
+       INIT_DELAYED_WORK(&codec->delayed_work, rt5625_work);
+
+       ret = -ENODEV;
+//     if (setup->i2c_address) 
+       {
+               codec->hw_write = (hw_write_t)i2c_master_send;
+               //codec->hw_read = (hw_read_t)i2c_master_recv;
+               ret = rt5625_add_i2c_device(pdev, setup);
+       }
+
+       if (ret != 0) {
+               kfree(codec->private_data);
+               kfree(codec);
+               socdev->card->codec = NULL;
+       }
+       return ret;
+}
+
+static int run_delayed_work(struct delayed_work *dwork)
+{
+       int ret;
+
+       /* cancel any work waiting to be queued. */
+       ret = cancel_delayed_work(dwork);
+
+       /* if there was any work waiting then we run it now and
+        * wait for it's completion */
+       if (ret) {
+               schedule_delayed_work(dwork, 0);
+               flush_scheduled_work();
+       }
+       return ret;
+}
+
+
+static int rt5625_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       if (codec->control_data)
+               rt5625_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       run_delayed_work(&codec->delayed_work);
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+       i2c_unregister_device(codec->control_data);
+       i2c_del_driver(&rt5625_i2c_driver);
+       kfree(codec->private_data);
+       kfree(codec);
+
+       return 0;
+}
+
+
+static int rt5625_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       rt5625_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
+}
+
+static int rt5625_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       
+//     int i;
+//     u8 data[3];
+//     u16 *cache = codec->reg_cache;
+
+#if 1
+       rt5625_reset(codec);
+       rt5625_write(codec, RT5625_PD_CTRL_STAT, 0);
+       rt5625_write(codec, RT5625_PWR_MANAG_ADD1, PWR_MAIN_BIAS);
+       rt5625_write(codec, RT5625_PWR_MANAG_ADD2, PWR_MIXER_VREF);
+       rt5625_reg_init(codec);
+#else
+       /* Sync reg_cache with the hardware */
+       for (i = 0; i < ARRAY_SIZE(rt5625_reg); i++) {
+               if (i == RT5625_RESET)
+                       continue;
+               data[0] = i << 1;
+               data[1] = (0xff00 & cache[i]) >> 8;
+               data[2] = 0x00ff & cache[i];
+               codec->hw_write(codec->control_data, data, 3);
+       }
+
+       rt5625_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+#endif
+
+       /* charge rt5625 caps */
+       if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
+               rt5625_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+               codec->bias_level = SND_SOC_BIAS_ON;
+               schedule_delayed_work(&codec->delayed_work,
+                                       msecs_to_jiffies(100));
+       }
+
+       return 0;
+}
+
+
+struct snd_soc_codec_device soc_codec_dev_rt5625 = {
+       .probe =        rt5625_probe,
+       .remove =       rt5625_remove,
+       .suspend =      rt5625_suspend,
+       .resume =       rt5625_resume,
+};
+
+EXPORT_SYMBOL_GPL(soc_codec_dev_rt5625);
+
+static int __init rt5625_modinit(void)
+{
+       return snd_soc_register_dais(rt5625_dai, ARRAY_SIZE(rt5625_dai));
+}
+
+static void __exit rt5625_exit(void)
+{
+       snd_soc_unregister_dais(rt5625_dai, ARRAY_SIZE(rt5625_dai));
+}
+
+module_init(rt5625_modinit);
+module_exit(rt5625_exit);
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/codecs/rt5625.h b/sound/soc/codecs/rt5625.h
new file mode 100644 (file)
index 0000000..cb4f73e
--- /dev/null
@@ -0,0 +1,742 @@
+#ifndef _RT5625_H
+#define _RT5625_H
+
+#define RT5625_RESET                                           0X00                    //RESET CODEC TO DEFAULT
+#define RT5625_SPK_OUT_VOL                                     0X02                    //SPEAKER OUT VOLUME
+#define RT5625_HP_OUT_VOL                                      0X04                    //HEADPHONE OUTPUT VOLUME
+#define RT5625_AUX_OUT_VOL                                     0X06                    //AUXOUT VOLUME
+#define RT5625_PHONEIN_VOL                                     0X08                    //PHONE INPUT VOLUME
+#define RT5625_LINE_IN_VOL                                     0X0A                    //LINE IN VOLUME
+#define RT5625_STEREO_DAC_VOL                          0X0C                    //STEREO DAC VOLUME
+#define RT5625_MIC_VOL                                         0X0E                    //MICROPHONE VOLUME
+#define RT5625_DAC_AND_MIC_CTRL                                0X10                    //STEREO DAC AND MIC ROUTING CONTROL
+#define RT5625_ADC_REC_GAIN                                    0X12                    //ADC RECORD GAIN
+#define RT5625_ADC_REC_MIXER                           0X14                    //ADC RECORD MIXER CONTROL
+#define RT5625_VOICE_DAC_OUT_VOL                       0X18                    //VOICE DAC OUTPUT VOLUME
+#define RT5625_VODSP_PDM_CTL                           0X1A                    //VODSP & PDM CONTROL
+#define RT5625_OUTPUT_MIXER_CTRL                       0X1C                    //OUTPUT MIXER CONTROL
+#define RT5625_VODSP_CTL                                       0X1E                    //VODSP CONTROL
+#define RT5625_MIC_CTRL                                                0X22                    //MICROPHONE CONTROL
+#define RT5625_DMIC_CTRL                                       0x24
+#define RT5625_PD_CTRL_STAT                                    0X26                    //POWER DOWN CONTROL/STATUS
+#define RT5625_DAC_ADC_VODAC_FUN_SEL           0X2E                    //STEREO DAC,VOICE DAC,STEREO ADC FUNCTION SELECT
+#define        RT5625_MAIN_SDP_CTRL                            0X34                    //MAIN SERIAL DATA PORT CONTROL(STEREO I2S)
+#define RT5625_EXTEND_SDP_CTRL                         0X36                    //EXTEND SERIAL DATA PORT CONTROL(VOICE I2S/PCM)
+#define        RT5625_PWR_MANAG_ADD1                           0X3A                    //POWER MANAGMENT ADDITION 1
+#define RT5625_PWR_MANAG_ADD2                          0X3C                    //POWER MANAGMENT ADDITION 2
+#define RT5625_PWR_MANAG_ADD3                          0X3E                    //POWER MANAGMENT ADDITION 3
+#define RT5625_GEN_CTRL_REG1                           0X40                    //GENERAL PURPOSE CONTROL REGISTER 1
+#define        RT5625_GEN_CTRL_REG2                            0X42                    //GENERAL PURPOSE CONTROL REGISTER 2
+#define RT5625_PLL_CTRL                                                0X44                    //PLL1 CONTROL
+#define RT5625_PLL2_CTRL                                       0X46                    //PLL2 CONTROL
+#define RT5625_LDO_CTRL                                                0X48                    //LDO CONTROL
+#define RT5625_GPIO_PIN_CONFIG                         0X4C                    //GPIO PIN CONFIGURATION
+#define RT5625_GPIO_PIN_POLARITY                       0X4E                    //GPIO PIN POLARITY     
+#define RT5625_GPIO_PIN_STICKY                         0X50                    //GPIO PIN STICKY       
+#define RT5625_GPIO_PIN_WAKEUP                         0X52                    //GPIO PIN WAKE UP
+#define RT5625_GPIO_PIN_STATUS                         0X54                    //GPIO PIN STATUS
+#define RT5625_GPIO_PIN_SHARING                                0X56                    //GPIO PIN SHARING
+#define        RT5625_OVER_TEMP_CURR_STATUS            0X58                    //OVER TEMPERATURE AND CURRENT STATUS
+#define RT5625_SOFT_VOL_CTRL                           0X5A                    //SOFT VOLUME CONTROL SETTING
+#define RT5625_GPIO_OUT_CTRL                           0X5C                    //GPIO OUTPUT PIN CONTRL
+#define RT5625_MISC_CTRL                                       0X5E                    //MISC CONTROL
+#define        RT5625_STEREO_DAC_CLK_CTRL1                     0X60                    //STEREO DAC CLOCK CONTROL 1
+#define RT5625_STEREO_DAC_CLK_CTRL2                    0X62                    //STEREO DAC CLOCK CONTROL 2
+#define RT5625_VOICE_DAC_PCMCLK_CTRL1          0X64                    //VOICE/PCM DAC CLOCK CONTROL 1
+#define RT5625_PSEDUEO_SPATIAL_CTRL                    0X68                    //PSEDUEO STEREO /SPATIAL EFFECT BLOCK CONTROL
+#define RT5625_PRIV_ADDR                                       0X6A                    //PRIVATE ADDRESS
+#define RT5625_PRIV_DATA                                       0X6C                    //PRIVATE DATA 
+#define RT5625_EQ_CTRL_ADC_HPF                         0X6E                    //EQ CONTROL AND STATUS /ADC HPF CONTROL
+#define RT5625_VODSP_REG_ADDR                  0x70                    //VODSP REGISTER ADDRESS
+#define RT5625_VODSP_REG_DATA                  0x72                    //VODSP REGISTER DATA
+#define RT5625_VODSP_REG_CMD                       0x74                        //VODSP REGISTER COMMAND
+
+
+/**************************************************************************************************
+ *Bit define of Codec Register
+ *************************************************************************************************/
+//global definition
+#define RT_L_MUTE                                              (0x1<<15)               //Mute Left Control
+#define RT_L_ZC                                                        (0x1<<14)               //Mute Left Zero-Cross Detector Control
+#define RT_R_MUTE                                              (0x1<<7)                //Mute Right Control
+#define RT_R_ZC                                                        (0x1<<6)                //Mute Right Zero-Cross Detector Control
+#define RT_M_HP_MIXER                                  (0x1<<15)               //Mute source to HP Mixer
+#define RT_M_SPK_MIXER                                 (0x1<<14)               //Mute source to Speaker Mixer
+#define RT_M_MONO_MIXER                                        (0x1<<13)               //Mute source to Mono Mixer
+
+//Phone Input Volume(0x08)
+#define M_PHONEIN_TO_HP_MIXER                  (0x1<<15)               //Mute Phone In volume to HP mixer
+#define M_PHONEIN_TO_SPK_MIXER                 (0x1<<14)               //Mute Phone In volume to speaker mixer
+
+
+//Mic Routing Control(0x10)
+#define M_MIC1_TO_HP_MIXER                             (0x1<<15)               //Mute MIC1 to HP mixer
+#define M_MIC1_TO_SPK_MIXER                            (0x1<<14)               //Mute MiC1 to SPK mixer
+#define M_MIC1_TO_MONO_MIXER                   (0x1<<13)               //Mute MIC1 to MONO mixer
+#define M_MIC2_TO_HP_MIXER                             (0x1<<11)               //Mute MIC2 to HP mixer
+#define M_MIC2_TO_SPK_MIXER                            (0x1<<10)               //Mute MiC2 to SPK mixer
+#define M_MIC2_TO_MONO_MIXER                   (0x1<<9)                //Mute MIC2 to MONO mixer
+#define M_DAC_TO_HPL_MIXER                             (0x1<<3)                //Mute DAC to HP left mixer
+#define M_DAC_TO_HPR_MIXER                             (0x1<<2)                //Mute DAC to HP right mixer
+#define M_DAC_TO_SPK_MIXER                             (0x1<<1)                //Mute DAC to SPK mixer
+#define M_DAC_TO_MONO_MIXER                            (0x1<<0)                //Mute DAC to MONO mixer
+
+
+
+//ADC Record Gain(0x12)
+#define M_ADC_L_TO_HP_MIXER                            (0x1<<15)               //Mute left of ADC to HP Mixer
+#define M_ADC_L_TO_MONO_MIXER                  (0x1<<14)               //Mute left of ADC to MONO Mixer
+#define ADC_L_ZC_DET                                   (0x1<<13)               //ADC Zero-Cross Detector Control
+#define ADC_L_GAIN_MASK                                        (0x1f<<8)               //ADC Record Gain Left channel Mask
+#define M_ADC_R_TO_HP_MIXER                            (0x1<<7)                //Mute right of ADC to HP Mixer
+#define M_ADC_R_TO_MONO_MIXER                  (0x1<<6)                //Mute right of ADC to MONO Mixer
+#define ADC_R_ZC_DET                                   (0x1<<5)                //ADC Zero-Cross Detector Control
+#define ADC_R_GAIN_MASK                                        (0x1f<<0)               //ADC Record Gain Right channel Mask
+
+//Voice DAC Output Volume(0x18)
+#define M_V_DAC_TO_HP_MIXER                            (0x1<<15)
+#define M_V_DAC_TO_SPK_MIXER                   (0x1<<14)
+#define M_V_DAC_TO_MONO_MIXER                  (0x1<<13)
+
+
+//AEC & PDM Control(0x1A)
+#define VODSP_SRC1_PWR                                 (0x1<<15)               //Enable SRC1 Power
+#define VODSP_SRC2_PWR                                 (0x1<<13)               //Enable SRC2 Power
+
+#define VODSP_SRC2_S_SEL_MASK                  (0x1<<12)               
+#define VODSP_SRC2_S_SEL_TXDP                  (0x0<<12)               //SRC2 source select AEC_TXDP
+#define VODSP_SRC2_S_SEL_TXDC                  (0x1<<12)               //SRC2 source select AEC_TXDC
+
+#define VODSP_RXDP_PWR                                 (0x1<<11)               //Enable AEC RXDP Power
+
+#define VODSP_RXDP_S_SEL_MASK                  (0x3<<9)                
+#define VODSP_RXDP_S_SEL_SRC1                  (0x0<<9)                //AEC RxDP source select SRC1 Output
+#define VODSP_RXDP_S_SEL_ADCL                  (0x1<<9)                //AEC RxDP source select ADC Left to AEC Digital Path
+#define VODSP_RXDP_S_SEL_VOICE                 (0x2<<9)                //AEC RxDP source select Voice to Stereo Digital Path
+#define VODSP_RXDP_S_SEL_ADCR                  (0x3<<9)                //AEC RxDP source select ADC Right to AEC Digital Path
+
+#define VODSP_RXDC_PWR                                 (0x1<<8)                //Enable AEC RXDC Power
+
+#define VOICE_PCM_S_SEL_MASK                   (0x1<<7)                
+#define VOICE_PCM_S_SEL_ADC_R                  (0x0<<7)                //VSADC PCM interface source select ADC R
+#define VOICE_PCM_S_SEL_AEC_TXDP               (0x1<<7)                //VSADC PCM interface source select AEC_TXDP
+
+#define REC_S_SEL_MASK                                 (0x3<<4)                
+#define REC_S_SEL_ADC                                  (0x0<<4)                //Main Stereo Record I2S source select ADC L/R
+#define REC_S_SEL_VOICE                                        (0x1<<4)                //Main Stereo Record I2S source select Voice to Stereo Digital Path
+#define REC_S_SEL_SRC2                                 (0x2<<4)                //Main Stereo Record I2S source select SRC2
+
+
+//Output Mixer Control(0x1C)
+#define        SPKOUT_N_SOUR_MASK                              (0x3<<14)       
+#define        SPKOUT_N_SOUR_LN                                (0x2<<14)
+#define        SPKOUT_N_SOUR_RP                                (0x1<<14)
+#define        SPKOUT_N_SOUR_RN                                (0x0<<14)
+
+#define SPKOUT_SEL_CLASS_D                             (0x1<<13)
+#define SPKOUT_SEL_CLASS_AB                            (0x0<<13)
+
+#define SPK_CLASS_AB_S_AMP                             (0x0<<12)
+#define SPK_CALSS_AB_W_AMP                             (0x1<<12)
+
+#define SPKOUT_INPUT_SEL_MASK                  (0x3<<10)
+#define SPKOUT_INPUT_SEL_MONOMIXER             (0x3<<10)
+#define SPKOUT_INPUT_SEL_SPKMIXER              (0x2<<10)
+#define SPKOUT_INPUT_SEL_HPMIXER               (0x1<<10)
+#define SPKOUT_INPUT_SEL_VMID                  (0x0<<10)
+
+#define HPL_INPUT_SEL_HPLMIXER                 (0x1<<9)
+#define HPR_INPUT_SEL_HPRMIXER                 (0x1<<8)        
+
+#define AUXOUT_INPUT_SEL_MASK                  (0x3<<6)
+#define AUXOUT_INPUT_SEL_MONOMIXER             (0x3<<6)
+#define AUXOUT_INPUT_SEL_SPKMIXER              (0x2<<6)
+#define AUXOUT_INPUT_SEL_HPMIXER               (0x1<<6)
+#define AUXOUT_INPUT_SEL_VMID                  (0x0<<6)
+
+
+//Voice DSP Control(0x1E)
+#define VODSP_SYSCLK_S_SEL_MASK                        (0x1<<15)
+#define VODSP_SYSCLK_S_SEL_M_CLK               (0x0<<15)
+#define VODSP_SYSCLK_S_SEL_V_CLK               (0x1<<15)
+
+#define VODSP_LRCK_SEL_MASK                            (0x1<<13)
+#define VODSP_LRCK_SEL_8K                              (0x0<<13)
+#define VODSP_LRCK_SEL_16K                             (0x1<<13)
+
+#define VODSP_TEST_MODE_ENA                            (0x1<<3)
+#define VODSP_NO_BP_MODE_ENA                   (0x1<<2)
+#define VODSP_NO_PD_MODE_ENA                   (0x1<<1)
+#define VODSP_NO_RST_MODE_ENA                  (0x1<<0)
+
+
+
+
+//Micphone Control define(0x22)
+#define MIC1           1
+#define MIC2           2
+#define MIC_BIAS_90_PRECNET_AVDD       1
+#define        MIC_BIAS_75_PRECNET_AVDD        2
+
+#define MIC1_BOOST_CONTROL_MASK                (0x3<<10)
+#define MIC1_BOOST_CONTROL_BYPASS      (0x0<<10)
+#define MIC1_BOOST_CONTROL_20DB                (0x1<<10)
+#define MIC1_BOOST_CONTROL_30DB                (0x2<<10)
+#define MIC1_BOOST_CONTROL_40DB                (0x3<<10)
+
+#define MIC2_BOOST_CONTROL_MASK                (0x3<<8)
+#define MIC2_BOOST_CONTROL_BYPASS      (0x0<<8)
+#define MIC2_BOOST_CONTROL_20DB                (0x1<<8)
+#define MIC2_BOOST_CONTROL_30DB                (0x2<<8)
+#define MIC2_BOOST_CONTROL_40DB                (0x3<<8)
+
+#define MIC1_BIAS_VOLT_CTRL_MASK       (0x1<<5)
+#define MIC1_BIAS_VOLT_CTRL_90P                (0x0<<5)
+#define MIC1_BIAS_VOLT_CTRL_75P                (0x1<<5)
+
+#define MIC2_BIAS_VOLT_CTRL_MASK       (0x1<<4)
+#define MIC2_BIAS_VOLT_CTRL_90P                (0x0<<4)
+#define MIC2_BIAS_VOLT_CTRL_75P                (0x1<<4)
+
+//PowerDown control of register(0x26)
+//power management bits
+#define RT_PWR_PR7                                     (0x1<<15)       //write this bit to power down the Speaker Amplifier
+#define RT_PWR_PR6                                     (0x1<<14)       //write this bit to power down the Headphone Out and MonoOut
+#define RT_PWR_PR5                                     (0x1<<13)       //write this bit to power down the internal clock(without PLL)
+#define RT_PWR_PR3                                     (0x1<<11)       //write this bit to power down the mixer(vref/vrefout out off)
+#define RT_PWR_PR2                                     (0x1<<10)       //write this bit to power down the mixer(vref/vrefout still on)
+#define RT_PWR_PR1                                     (0x1<<9)        //write this bit to power down the dac
+#define RT_PWR_PR0                                     (0x1<<8)        //write this bit to power down the adc
+#define RT_PWR_REF                                     (0x1<<3)        //read only
+#define RT_PWR_ANL                                     (0x1<<2)        //read only     
+#define RT_PWR_DAC                                     (0x1<<1)        //read only
+#define RT_PWR_ADC                                     (0x1)           //read only
+
+
+//Stereo DAC/Voice DAC/Stereo ADC function(0x2E)
+#define DAC_FUNC_SEL_MASK                      (0x3<<12)
+#define DAC_FUNC_SEL_DAC                       (0x0<<12)               
+#define DAC_FUNC_SEL_SRC2                      (0x1<<12)
+#define DAC_FUNC_SEL_VODSP_TXDP                (0x2<<12)
+#define DAC_FUNC_SEL_VODSP_TXDC                (0x3<<12)
+
+#define VODAC_SOUR_SEL_MASK                    (0x7<<8)
+#define VODAC_SOUR_SEL_VOICE           (0x0<<8)        
+#define VODAC_SOUR_SEL_SRC2                    (0x1<<8)
+#define VODAC_SOUR_SEL_VODSP_TXDP      (0x2<<8)
+#define VODAC_SOUR_SEL_VODSP_TXDC      (0x3<<8)
+
+#define ADCR_FUNC_SEL_MASK                     (0x3<<4)
+#define ADCR_FUNC_SEL_ADC                      (0x0<<4)
+#define ADCR_FUNC_SEL_VOADC                    (0x1<<4)
+#define ADCR_FUNC_SEL_VODSP                    (0x2<<4)
+#define ADCR_FUNC_SEL_PDM                      (0x3<<4)
+
+#define ADCL_FUNC_SEL_MASK                     (0x3<<0)
+#define ADCL_FUNC_SEL_ADC                      (0x0<<0)
+#define ADCL_FUNC_SEL_VODSP                    (0x1<<0)
+
+//Main Serial Data Port Control(0x34)                  
+#define MAIN_I2S_MODE_SEL                      (0x1<<15)               //0:Master mode 1:Slave mode
+#define MAIN_I2S_SADLRCK_CTRL          (0x1<<14)               //0:Disable,ADC and DAC use the same fs,1:Enable
+
+#define MAIN_I2S_PCM_MODE                      (0x1<<6)                //0:Normal SADLRCK/SDALRCK,1:Invert SADLRCK/SDALRCK 
+//Data Length Slection
+#define MAIN_I2S_DL_MASK                       (0x3<<2)                //main i2s Data Length mask     
+#define MAIN_I2S_DL_16                         (0x0<<2)                //16 bits
+#define MAIN_I2S_DL_20                         (0x1<<2)                //20 bits
+#define        MAIN_I2S_DL_24                          (0x2<<2)                //24 bits
+#define MAIN_I2S_DL_32                         (0x3<<2)                //8 bits
+
+//PCM Data Format Selection
+#define MAIN_I2S_DF_MASK                       (0x3)                   //main i2s Data Format mask
+#define MAIN_I2S_DF_I2S                                (0x0)                   //I2S FORMAT 
+#define MAIN_I2S_DF_LEFT                       (0x1)                   //LEFT JUSTIFIED format
+#define        MAIN_I2S_DF_PCM_A                       (0x2)                   //PCM Mode A
+#define MAIN_I2S_DF_PCM_B                              (0x3)                   //PCM Mode B
+
+//Extend Serial Data Port Control(0x36)
+#define EXT_I2S_FUNC_ENABLE                    (0x1<<15)               //Enable PCM interface on GPIO 1,3,4,5  0:GPIO function,1:Voice PCM interface
+#define EXT_I2S_MODE_SEL                       (0x1<<14)               //0:Master      ,1:Slave
+#define EXT_I2S_AUTO_CLK_CTRL          (0x1<<13)               //0:Disable,1:Enable
+#define EXT_I2S_BCLK_POLARITY          (0x1<<7)                //0:Normal 1:Invert
+#define EXT_I2S_PCM_MODE                       (0x1<<6)                //0:Normal VSLRCK,1:Invert VSLRCK 
+//Data Length Slection
+#define EXT_I2S_DL_MASK                                (0x3<<2)                //Extend i2s Data Length mask   
+#define EXT_I2S_DL_32                          (0x3<<2)                //8 bits
+#define        EXT_I2S_DL_24                           (0x2<<2)                //24 bits
+#define EXT_I2S_DL_20                          (0x1<<2)                //20 bits
+#define EXT_I2S_DL_16                          (0x0<<2)                //16 bits
+
+//Voice Data Format
+#define EXT_I2S_DF_MASK                                (0x3)                   //Extend i2s Data Format mask
+#define EXT_I2S_DF_I2S                         (0x0)                   //I2S FORMAT 
+#define EXT_I2S_DF_LEFT                                (0x1)                   //LEFT JUSTIFIED format
+#define        EXT_I2S_DF_PCM_A                        (0x2)                   //PCM Mode A
+#define EXT_I2S_DF_PCM_B                       (0x3)                   //PCM Mode B
+
+//Power managment addition 1 (0x3A),0:Disable,1:Enable
+#define PWR_DAC_DF2SE_L                                (0x1<<15)
+#define PWR_DAC_DF2SE_R                                (0x1<<14)
+#define PWR_ZC_DET_PD                          (0x1<<13)
+#define PWR_I2S_INTERFACE                      (0x1<<11)
+#define PWR_AMP_POWER                          (0x1<<10)
+#define PWR_HP_OUT_AMP                         (0x1<<9)
+#define PWR_HP_OUT_ENH_AMP                     (0x1<<8)
+#define PWR_VOICE_DF2SE                                (0x1<<7)
+#define PWR_SOFTGEN_EN                         (0x1<<6)        
+#define        PWR_MIC_BIAS1_DET                       (0x1<<5)
+#define        PWR_MIC_BIAS2_DET                       (0x1<<4)
+#define PWR_MIC_BIAS1                          (0x1<<3)        
+#define PWR_MIC_BIAS2                          (0x1<<2)        
+#define PWR_MAIN_BIAS                          (0x1<<1)
+#define PWR_DAC_REF                                    (0x1)
+
+
+//Power managment addition 2(0x3C),0:Disable,1:Enable
+#define PWR_PLL1                                       (0x1<<15)
+#define PWR_PLL2                                       (0x1<<14)
+#define PWR_MIXER_VREF                         (0x1<<13)
+#define PWR_TEMP_SENSOR                                (0x1<<12)
+#define PWR_AUX_ADC                                    (0x1<<11)
+#define PWR_VOICE_CLOCK                                (0x1<<10)
+#define PWR_L_DAC_CLK                          (0x1<<9)
+#define PWR_R_DAC_CLK                          (0x1<<8)
+#define PWR_L_ADC_CLK                          (0x1<<7)
+#define PWR_R_ADC_CLK                          (0x1<<6)
+#define PWR_L_HP_MIXER                         (0x1<<5)
+#define PWR_R_HP_MIXER                         (0x1<<4)
+#define PWR_SPK_MIXER                          (0x1<<3)
+#define PWR_MONO_MIXER                         (0x1<<2)
+#define PWR_L_ADC_REC_MIXER                    (0x1<<1)
+#define PWR_R_ADC_REC_MIXER                    (0x1)
+
+
+//Power managment addition 3(0x3E),0:Disable,1:Enable
+#define PWR_OSC_EN                                     (0x1<<15)
+#define PWR_AUXOUT_VOL                         (0x1<<14)
+#define PWR_SPK_OUT                                    (0x1<<13)
+#define PWR_SPK_OUT_N                          (0x1<<12)
+#define PWR_HP_L_OUT_VOL                       (0x1<<11)
+#define PWR_HP_R_OUT_VOL                       (0x1<<10)
+#define PWR_VODSP_INTERFACE                    (0x1<<9)
+#define PWR_I2C_FOR_VODSP                      (0x1<<8)
+#define PWR_LINE_IN_L                          (0x1<<7)
+#define PWR_LINE_IN_R                          (0x1<<6)
+#define PWR_PHONE_VOL                          (0x1<<5)
+#define PWR_PHONE_ADMIXER                      (0x1<<4)
+#define PWR_MIC1_VOL_CTRL                      (0x1<<3)
+#define PWR_MIC2_VOL_CTRL                      (0x1<<2)
+#define PWR_MIC1_BOOST                         (0x1<<1)
+#define PWR_MIC2_BOOST                         (0x1)
+
+//General Purpose Control Register 1(0x40)
+#define GP_CLK_FROM_PLL                                (0x1<<15)       
+#define GP_CLK_FROM_MCLK                       (0x0<<15)       
+
+#define GP_DAC_HI_PA_ENA                       (0x1<<10)       //Enable DAC High Pass Filter
+
+#define GP_EXTCLK_S_SEL_PLL2           (0x1<<6)
+#define GP_EXTCLK_S_SEL_PLL1           (0x0<<6)        
+
+#define GP_EXTCLK_DIR_SEL_OUTPUT       (0x1<<5)
+#define GP_EXTCLK_DIR_SEL_INTPUT       (0x0<<5)
+
+#define GP_VOSYS_S_SEL_PLL2                    (0x0<<4)
+#define GP_VOSYS_S_SEL_EXTCLK          (0x1<<4)
+
+#define GP_SPK_AMP_CTRL_MASK           (0x7<<1)
+#define GP_SPK_AMP_CTRL_RATIO_225      (0x0<<1)                //2.25 Vdd
+#define GP_SPK_AMP_CTRL_RATIO_200      (0x1<<1)                //2.00 Vdd
+#define GP_SPK_AMP_CTRL_RATIO_175      (0x2<<1)                //1.75 Vdd
+#define GP_SPK_AMP_CTRL_RATIO_150      (0x3<<1)                //1.50 Vdd
+#define GP_SPK_AMP_CTRL_RATIO_125      (0x4<<1)                //1.25 Vdd      
+#define GP_SPK_AMP_CTRL_RATIO_100      (0x5<<1)                //1.00 Vdd
+
+//General Purpose Control Register 2(0x42)
+#define GP2_PLL1_SOUR_SEL_MASK         (0x3<<12)
+#define GP2_PLL1_SOUR_SEL_MCLK         (0x0<<12)
+#define GP2_PLL1_SOUR_SEL_BCLK         (0x2<<12)
+#define GP2_PLL1_SOUR_SEL_VBCLK                (0x3<<12)
+
+//PLL Control(0x44)
+#define PLL_M_CODE_MASK                                0xF                             //PLL M code mask
+#define PLL_K_CODE_MASK                                (0x7<<4)                //PLL K code mask
+#define PLL_BYPASS_N                           (0x1<<7)                //bypass PLL N code
+#define PLL_N_CODE_MASK                                (0xFF<<8)               //PLL N code mask
+
+#define PLL_CTRL_M_VAL(m)              ((m)&0xf)
+#define PLL_CTRL_K_VAL(k)              (((k)&0x7)<<4)
+#define PLL_CTRL_N_VAL(n)              (((n)&0xff)<<8)
+
+//PLL2 CONTROL
+#define PLL2_ENA                                       (0x1<<15)
+#define PLL_2_RATIO_8X                         (0x0)
+#define PLL_2_RATIO_16X                                (0x1)
+
+//LDO Control(0x48)
+#define LDO_ENABLE                                     (0x1<<15)
+
+#define LDO_OUT_VOL_CTRL_MASK          (0xf<<0)
+#define LDO_OUT_VOL_CTRL_1_55V         (0xf<<0)
+#define LDO_OUT_VOL_CTRL_1_50V         (0xe<<0)
+#define LDO_OUT_VOL_CTRL_1_45V         (0xd<<0)
+#define LDO_OUT_VOL_CTRL_1_40V         (0xc<<0)
+#define LDO_OUT_VOL_CTRL_1_35V         (0xb<<0)
+#define LDO_OUT_VOL_CTRL_1_30V         (0xa<<0)
+#define LDO_OUT_VOL_CTRL_1_25V         (0x9<<0)
+#define LDO_OUT_VOL_CTRL_1_20V         (0x8<<0)
+#define LDO_OUT_VOL_CTRL_1_15V         (0x7<<0)
+#define LDO_OUT_VOL_CTRL_1_05V         (0x6<<0)
+#define LDO_OUT_VOL_CTRL_1_00V         (0x5<<0)
+#define LDO_OUT_VOL_CTRL_0_95V         (0x4<<0)
+#define LDO_OUT_VOL_CTRL_0_90V         (0x3<<0)
+#define LDO_OUT_VOL_CTRL_0_85V         (0x2<<0)
+#define LDO_OUT_VOL_CTRL_0_80V         (0x1<<0)
+#define LDO_OUT_VOL_CTRL_0_75V         (0x0<<0)
+
+
+
+//GPIO Pin Configuration(0x4C)
+#define GPIO_1                                         (0x1<<1)
+#define        GPIO_2                                          (0x1<<2)
+#define        GPIO_3                                          (0x1<<3)
+#define GPIO_4                                         (0x1<<4)
+#define GPIO_5                                         (0x1<<5)
+
+
+////INTERRUPT CONTROL(0x5E)
+#define DISABLE_FAST_VREG                      (0x1<<15)
+
+#define AVC_TARTGET_SEL_MASK           (0x3<<12)
+#define        AVC_TARTGET_SEL_NONE            (0x0<<12)
+#define        AVC_TARTGET_SEL_R                       (0x1<<12)
+#define        AVC_TARTGET_SEL_L                       (0x2<<12)
+#define        AVC_TARTGET_SEL_BOTH            (0x3<<12)
+
+#define HP_DEPOP_MODE2_EN                      (0x1<<8)
+#define HP_DEPOP_MODE1_EN                      (0x1<<9)
+#define HP_L_M_UM_DEPOP_EN                     (0x1<<7)
+#define HP_R_M_UM_DEPOP_EN                     (0x1<<6)
+#define M_UM_DEPOP_EN                          (0x1<<5)
+
+//Stereo DAC Clock Control 1(0x60)
+#define STEREO_BCLK_DIV1_MASK          (0xF<<12)
+#define STEREO_BCLK_DIV1_1                     (0x0<<12)
+#define STEREO_BCLK_DIV1_2                     (0x1<<12)
+#define STEREO_BCLK_DIV1_3                     (0x2<<12)
+#define STEREO_BCLK_DIV1_4                     (0x3<<12)
+#define STEREO_BCLK_DIV1_5                     (0x4<<12)
+#define STEREO_BCLK_DIV1_6                     (0x5<<12)
+#define STEREO_BCLK_DIV1_7                     (0x6<<12)
+#define STEREO_BCLK_DIV1_8                     (0x7<<12)
+#define STEREO_BCLK_DIV1_9                     (0x8<<12)
+#define STEREO_BCLK_DIV1_10                    (0x9<<12)
+#define STEREO_BCLK_DIV1_11                    (0xA<<12)
+#define STEREO_BCLK_DIV1_12                    (0xB<<12)
+#define STEREO_BCLK_DIV1_13                    (0xC<<12)
+#define STEREO_BCLK_DIV1_14                    (0xD<<12)
+#define STEREO_BCLK_DIV1_15                    (0xE<<12)
+#define STEREO_BCLK_DIV1_16                    (0xF<<12)
+
+#define STEREO_BCLK_DIV2_MASK          (0x7<<8)
+#define STEREO_BCLK_DIV2_2                     (0x0<<8)
+#define STEREO_BCLK_DIV2_4                     (0x1<<8)
+#define STEREO_BCLK_DIV2_8                     (0x2<<8)
+#define STEREO_BCLK_DIV2_16                    (0x3<<8)
+#define STEREO_BCLK_DIV2_32                    (0x4<<8)
+
+#define STEREO_AD_LRCK_DIV1_MASK       (0xF<<4)
+#define STEREO_AD_LRCK_DIV1_1          (0x0<<4)
+#define STEREO_AD_LRCK_DIV1_2          (0x1<<4)
+#define STEREO_AD_LRCK_DIV1_3          (0x2<<4)
+#define STEREO_AD_LRCK_DIV1_4          (0x3<<4)
+#define STEREO_AD_LRCK_DIV1_5          (0x4<<4)
+#define STEREO_AD_LRCK_DIV1_6          (0x5<<4)
+#define STEREO_AD_LRCK_DIV1_7          (0x6<<4)
+#define STEREO_AD_LRCK_DIV1_8          (0x7<<4)
+#define STEREO_AD_LRCK_DIV1_9          (0x8<<4)
+#define STEREO_AD_LRCK_DIV1_10         (0x9<<4)
+#define STEREO_AD_LRCK_DIV1_11         (0xA<<4)
+#define STEREO_AD_LRCK_DIV1_12         (0xB<<4)
+#define STEREO_AD_LRCK_DIV1_13         (0xC<<4)
+#define STEREO_AD_LRCK_DIV1_14         (0xD<<4)
+#define STEREO_AD_LRCK_DIV1_15         (0xE<<4)
+#define STEREO_AD_LRCK_DIV1_16         (0xF<<4)
+
+#define STEREO_AD_LRCK_DIV2_MASK       (0x7<<1)
+#define STEREO_AD_LRCK_DIV2_2          (0x0<<1)
+#define STEREO_AD_LRCK_DIV2_4          (0x1<<1)
+#define STEREO_AD_LRCK_DIV2_8          (0x2<<1)
+#define STEREO_AD_LRCK_DIV2_16         (0x3<<1)
+#define STEREO_AD_LRCK_DIV2_32         (0x4<<1)
+
+#define STEREO_DA_LRCK_DIV_MASK                (1)
+#define STEREO_DA_LRCK_DIV_32          (0)
+#define STEREO_DA_LRCK_DIV_64          (1)
+
+//Stereo DAC Clock Control 2(0x62)
+#define STEREO_DA_FILTER_DIV1_MASK     (0xF<<12)
+#define STEREO_DA_FILTER_DIV1_1                (0x0<<12)
+#define STEREO_DA_FILTER_DIV1_2                (0x1<<12)
+#define STEREO_DA_FILTER_DIV1_3                (0x2<<12)
+#define STEREO_DA_FILTER_DIV1_4                (0x3<<12)
+#define STEREO_DA_FILTER_DIV1_5                (0x4<<12)
+#define STEREO_DA_FILTER_DIV1_6                (0x5<<12)
+#define STEREO_DA_FILTER_DIV1_7                (0x6<<12)
+#define STEREO_DA_FILTER_DIV1_8                (0x7<<12)
+#define STEREO_DA_FILTER_DIV1_9                (0x8<<12)
+#define STEREO_DA_FILTER_DIV1_10       (0x9<<12)
+#define STEREO_DA_FILTER_DIV1_11       (0xA<<12)
+#define STEREO_DA_FILTER_DIV1_12       (0xB<<12)
+#define STEREO_DA_FILTER_DIV1_13       (0xC<<12)
+#define STEREO_DA_FILTER_DIV1_14       (0xD<<12)
+#define STEREO_DA_FILTER_DIV1_15       (0xE<<12)
+#define STEREO_DA_FILTER_DIV1_16       (0xF<<12)
+
+#define STEREO_DA_FILTER_DIV2_MASK     (0x7<<9)
+#define STEREO_DA_FILTER_DIV2_2                (0x0<<9)
+#define STEREO_DA_FILTER_DIV2_4                (0x1<<9)
+#define STEREO_DA_FILTER_DIV2_8                (0x2<<9)
+#define STEREO_DA_FILTER_DIV2_16       (0x3<<9)
+#define STEREO_DA_FILTER_DIV2_32       (0x4<<9)
+
+#define STEREO_AD_FILTER_DIV1_MASK     (0xF<<4)
+#define STEREO_AD_FILTER_DIV1_1                (0x0<<4)
+#define STEREO_AD_FILTER_DIV1_2                (0x1<<4)
+#define STEREO_AD_FILTER_DIV1_3                (0x2<<4)
+#define STEREO_AD_FILTER_DIV1_4                (0x3<<4)
+#define STEREO_AD_FILTER_DIV1_5                (0x4<<4)
+#define STEREO_AD_FILTER_DIV1_6                (0x5<<4)
+#define STEREO_AD_FILTER_DIV1_7                (0x6<<4)
+#define STEREO_AD_FILTER_DIV1_8                (0x7<<4)
+#define STEREO_AD_FILTER_DIV1_9                (0x8<<4)
+#define STEREO_AD_FILTER_DIV1_10       (0x9<<4)
+#define STEREO_AD_FILTER_DIV1_11       (0xA<<4)
+#define STEREO_AD_FILTER_DIV1_12       (0xB<<4)
+#define STEREO_AD_FILTER_DIV1_13       (0xC<<4)
+#define STEREO_AD_FILTER_DIV1_14       (0xD<<4)
+#define STEREO_AD_FILTER_DIV1_15       (0xE<<4)
+#define STEREO_AD_FILTER_DIV1_16       (0xF<<4)
+
+#define STEREO_AD_FILTER_DIV2_MASK     (0x7<<1)
+#define STEREO_AD_FILTER_DIV2_1                (0x0<<1)
+#define STEREO_AD_FILTER_DIV2_2                (0x1<<1)
+#define STEREO_AD_FILTER_DIV2_4                (0x2<<1)
+#define STEREO_AD_FILTER_DIV2_8                (0x3<<1)
+#define STEREO_AD_FILTER_DIV2_16       (0x4<<1)
+#define STEREO_AD_FILTER_DIV2_32       (0x5<<1)
+
+
+//Voice DAC PCM Clock Control 1(0x64)
+#define VOICE_BCLK_DIV1_MASK           (0xF<<12)
+#define VOICE_BCLK_DIV1_1                      (0x0<<12)
+#define VOICE_BCLK_DIV1_2                      (0x1<<12)
+#define VOICE_BCLK_DIV1_3                      (0x2<<12)
+#define VOICE_BCLK_DIV1_4                      (0x3<<12)
+#define VOICE_BCLK_DIV1_5                      (0x4<<12)
+#define VOICE_BCLK_DIV1_6                      (0x5<<12)
+#define VOICE_BCLK_DIV1_7                      (0x6<<12)
+#define VOICE_BCLK_DIV1_8                      (0x7<<12)
+#define VOICE_BCLK_DIV1_9                      (0x8<<12)
+#define VOICE_BCLK_DIV1_10                     (0x9<<12)
+#define VOICE_BCLK_DIV1_11                     (0xA<<12)
+#define VOICE_BCLK_DIV1_12                     (0xB<<12)
+#define VOICE_BCLK_DIV1_13                     (0xC<<12)
+#define VOICE_BCLK_DIV1_14                     (0xD<<12)
+#define VOICE_BCLK_DIV1_15                     (0xE<<12)
+#define VOICE_BCLK_DIV1_16                     (0xF<<12)
+
+#define VOICE_BCLK_DIV2_MASK           (0x7<<8)
+#define VOICE_BCLK_DIV2_2                      (0x0<<8)
+#define VOICE_BCLK_DIV2_4                      (0x1<<8)
+#define VOICE_BCLK_DIV2_8                      (0x2<<8)
+#define VOICE_BCLK_DIV2_16                     (0x3<<8)
+#define VOICE_BCLK_DIV2_32                     (0x4<<8)
+
+#define VOICE_AD_LRCK_DIV1_MASK        (0xF<<4)
+#define VOICE_AD_LRCK_DIV1_1           (0x0<<4)
+#define VOICE_AD_LRCK_DIV1_2           (0x1<<4)
+#define VOICE_AD_LRCK_DIV1_3           (0x2<<4)
+#define VOICE_AD_LRCK_DIV1_4           (0x3<<4)
+#define VOICE_AD_LRCK_DIV1_5           (0x4<<4)
+#define VOICE_AD_LRCK_DIV1_6           (0x5<<4)
+#define VOICE_AD_LRCK_DIV1_7           (0x6<<4)
+#define VOICE_AD_LRCK_DIV1_8           (0x7<<4)
+#define VOICE_AD_LRCK_DIV1_9           (0x8<<4)
+#define VOICE_AD_LRCK_DIV1_10          (0x9<<4)
+#define VOICE_AD_LRCK_DIV1_11          (0xA<<4)
+#define VOICE_AD_LRCK_DIV1_12          (0xB<<4)
+#define VOICE_AD_LRCK_DIV1_13          (0xC<<4)
+#define VOICE_AD_LRCK_DIV1_14          (0xD<<4)
+#define VOICE_AD_LRCK_DIV1_15          (0xE<<4)
+#define VOICE_AD_LRCK_DIV1_16          (0xF<<4)
+
+#define VOICE_AD_LRCK_DIV2_MASK        (0x7<<1)
+#define VOICE_AD_LRCK_DIV2_2           (0x0<<1)
+#define VOICE_AD_LRCK_DIV2_4           (0x1<<1)
+#define VOICE_AD_LRCK_DIV2_8           (0x2<<1)
+#define VOICE_AD_LRCK_DIV2_16          (0x3<<1)
+#define VOICE_AD_LRCK_DIV2_32          (0x4<<1)
+
+#define VOICE_DA_LRCK_DIV_MASK         (1)
+#define VOICE_DA_LRCK_DIV_32           (0)
+#define VOICE_DA_LRCK_DIV_64           (1)
+
+
+//Psedueo Stereo & Spatial Effect Block Control(0x68)
+#define SPATIAL_CTRL_EN                                (0x1<<15)
+#define ALL_PASS_FILTER_EN                     (0x1<<14)
+#define PSEUDO_STEREO_EN                       (0x1<<13)
+#define STEREO_EXPENSION_EN                    (0x1<<12)
+
+#define SPATIAL_3D_GAIN1_MASK                  (0x3<<10)
+#define SPATIAL_3D_GAIN1_1_0                   (0x0<<10)
+#define SPATIAL_3D_GAIN1_1_5                   (0x1<<10)
+#define SPATIAL_3D_GAIN1_2_0                   (0x2<<10)
+
+#define SPATIAL_3D_RATIO1_MASK                 (0x3<<8)
+#define SPATIAL_3D_RATIO1_0_0                  (0x0<<8)
+#define SPATIAL_3D_RATIO1_0_66                 (0x1<<8)
+#define SPATIAL_3D_RATIO1_1_0                  (0x2<<8)
+
+#define SPATIAL_3D_GAIN2_MASK                  (0x3<<6)
+#define SPATIAL_3D_GAIN2_1_0                   (0x0<<6)
+#define SPATIAL_3D_GAIN2_1_5                   (0x1<<6)
+#define SPATIAL_3D_GAIN2_2_0                   (0x2<<6)
+
+#define SPATIAL_3D_RATIO2_MASK                 (0x3<<4)
+#define SPATIAL_3D_RATIO2_0_0                  (0x0<<4)
+#define SPATIAL_3D_RATIO2_0_66                 (0x1<<4)
+#define SPATIAL_3D_RATIO2_1_0                  (0x2<<4)
+
+#define APF_MASK                                       (0x3)
+#define APF_FOR_48K                                    (0x3)
+#define APF_FOR_44_1K                          (0x2)
+#define APF_FOR_32K                                    (0x1)
+
+//EQ Control and Status /ADC HPF Control(0x6E)
+#define EN_HW_EQ_BLK                   (0x1<<15)               //HW EQ block control
+
+#define EQ_SOUR_SEL_DAC                        (0x0<<14)
+#define EQ_SOUR_SEL_ADC                        (0x1<<14)
+
+#define EQ_CHANGE_EN                   (0x1<<7)                //EQ parameter update control
+#define EN_HW_EQ_HPF                   (0x1<<4)                //EQ High Pass Filter Control
+#define EN_HW_EQ_BP3                   (0x1<<3)                //EQ Band-3 Control
+#define EN_HW_EQ_BP2                   (0x1<<2)                //EQ Band-2 Control
+#define EN_HW_EQ_BP1                   (0x1<<1)                //EQ Band-1 Control
+#define EN_HW_EQ_LPF                   (0x1<<0)                //EQ Low Pass Filter Control
+
+
+//AEC register command(0x74)
+
+#define VODSP_BUSY                                     (0x1<<15)       //VODSP I2C busy flag
+
+#define VODSP_S_FROM_VODSP_RD          (0x0<<14)
+#define VODSP_S_FROM_MX72                      (0x1<<14)
+
+#define VODSP_CLK_SEL_MASK                     (0x3<<12)       //VODSP CLK select Mask
+#define VODSP_CLK_SEL_12_288M          (0x0<<12)       //VODSP CLK select 12.288Mhz
+#define VODSP_CLK_SEL_6_144M           (0x1<<12)       //VODSP CLK select 6.144Mhz
+#define VODSP_CLK_SEL_3_072M           (0x2<<12)       //VODSP CLK select 3.072Mhz
+#define VODSP_CLK_SEL_2_048M           (0x3<<12)       //VODSP CLK select 2.0488Mhz
+
+#define VODSP_READ_ENABLE                      (0x1<<9)        //VODSP Read Enable
+#define VODSP_WRITE_ENABLE                     (0x1<<8)        //VODSP Write Enable
+
+#define VODSP_CMD_MASK                         (0xFF<<0)
+#define VODSP_CMD_MW                           (0x3B<<0)               //Memory Write
+#define VODSP_CMD_MR                           (0x37<<0)               //Memory Read
+#define VODSP_CMD_RR                           (0x60<<0)               //Register Read
+#define VODSP_CMD_RW                           (0x68<<0)               //Register Write
+
+
+/*************************************************************************************************
+  *Index register of codec
+  *************************************************************************************************/
+/*Index(0x20) for Auto Volume Control*/ 
+#define        AVC_CH_SEL_MASK                         (0x1<<7)
+#define AVC_CH_SEL_L_CH                                (0x0<<7)
+#define AVC_CH_SEL_R_CH                                (0x1<<7)
+#define ENABLE_AVC_GAIN_CTRL           (0x1<<15)
+//*************************************************************************************************
+//*************************************************************************************************
+
+#define REALTEK_HWDEP 0
+
+#if REALTEK_HWDEP
+
+struct rt56xx_reg_state
+{
+       unsigned int reg_index;
+       unsigned int reg_value;
+};
+
+struct rt56xx_cmd
+{
+       size_t number;
+       struct rt56xx_reg_state __user *buf;            
+};
+
+
+enum 
+{
+       RT_READ_CODEC_REG_IOCTL = _IOR('R', 0x01, struct rt56xx_cmd),
+       RT_READ_ALL_CODEC_REG_IOCTL = _IOR('R', 0x02, struct rt56xx_cmd),
+       RT_WRITE_CODEC_REG_IOCTL = _IOW('R', 0x03, struct rt56xx_cmd),
+};
+
+#endif
+
+
+enum pll_sel
+{
+       RT5625_PLL1_FROM_MCLK = 0,
+       RT5625_PLL1_FROM_BCLK,
+       RT5625_PLL1_FROM_VBCLK,
+};
+
+enum AEC_MODE
+{
+       PCM_IN_PCM_OUT = 0,
+       ANALOG_IN_ANALOG_OUT,
+       DAC_IN_ADC_OUT,
+       VODSP_AEC_DISABLE               
+};
+
+enum
+{
+       PCM_MASTER_MODE_A=0,
+       PCM_MASTER_MODE_B,
+       PCM_SLAVE_MODE_A,
+       PCM_SLAVE_MODE_B,
+};
+
+
+enum RT5625_FUNC_SEL
+{
+       RT5625_AEC_DISABLE =0,
+       RT5625_AEC_PCM_IN_OUT,
+       RT5625_AEC_IIS_IN_OUT,
+       RT5625_AEC_ANALOG_IN_OUT,
+
+};
+
+
+struct rt5625_setup_data {
+       int i2c_bus;
+       int i2c_address;
+};
+
+typedef struct 
+{ 
+       unsigned short int VoiceDSPIndex;
+       unsigned short int VoiceDSPValue;
+
+}Voice_DSP_Reg;
+
+extern struct snd_soc_dai rt5625_dai[];
+extern struct snd_soc_codec_device soc_codec_dev_rt5625;
+
+#endif
index 2eeac425d9b587aab49b83dc894121096382daa2..7d5c97f7066c0841c5523686e30dc0f45fa2b0e7 100644 (file)
@@ -56,6 +56,16 @@ config SND_RK29_SOC_alc5631
        help
          Say Y if you want to add support for SoC audio on rockchip
          with the alc5631.
+
+config SND_RK29_SOC_RT5625
+       tristate "SoC I2S Audio support for rockchip - RT5625"
+       depends on SND_RK29_SOC && I2C_RK29
+       select SND_RK29_SOC_I2S
+       select SND_SOC_RT5625
+       help
+         Say Y if you want to add support for SoC audio on rockchip
+         with the RT5625.
+
 config SND_RK29_SOC_WM8994
        tristate "SoC I2S Audio support for rockchip - WM8994"
        depends on SND_RK29_SOC && I2C_RK29
@@ -74,7 +84,7 @@ config SND_RK29_SOC_RK1000
          Say Y if you want to add support for SoC audio on rockchip
          with the RK1000.       
           
-if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_alc5621 || SND_RK29_SOC_alc5631
+if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_alc5621 || SND_RK29_SOC_alc5631 || SND_RK29_SOC_RT5625
 choice
   prompt "Set i2s type"
        config SND_RK29_CODEC_SOC_MASTER
index 17e5b941e799717aa564f862d4983d6e6741b6b1..f4a9f8c4e333a482a269e46caad54552be0e9e67 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_SND_RK29_SOC_I2S) += snd-soc-rockchip-i2s.o
 snd-soc-wm8900-objs := rk29_wm8900.o
 snd-soc-alc5621-objs := rk29_alc5621.o
 snd-soc-alc5631-objs := rk29_rt5631.o
+snd-soc-rt5625-objs := rk29_rt5625.o
 snd-soc-wm8988-objs := rk29_wm8988.o
 snd-soc-rk1000-objs := rk29_rk1000codec.o
 snd-soc-wm8994-objs := rk29_wm8994.o
@@ -18,4 +19,5 @@ obj-$(CONFIG_SND_RK29_SOC_WM8988) += snd-soc-wm8988.o
 obj-$(CONFIG_SND_RK29_SOC_WM8900) += snd-soc-wm8900.o
 obj-$(CONFIG_SND_RK29_SOC_alc5621) += snd-soc-alc5621.o
 obj-$(CONFIG_SND_RK29_SOC_alc5631) += snd-soc-alc5631.o
+obj-$(CONFIG_SND_RK29_SOC_RT5625) += snd-soc-rt5625.o
 obj-$(CONFIG_SND_RK29_SOC_RK1000) += snd-soc-rk1000.o
diff --git a/sound/soc/rk29/rk29_rt5625.c b/sound/soc/rk29/rk29_rt5625.c
new file mode 100644 (file)
index 0000000..afca882
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * rk29_rt5625.c  --  SoC audio for rockchip
+ *
+ * Driver for rockchip rt5625 audio
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/rk29_iomap.h>
+#include "../codecs/rt5625.h"
+#include "rk29_pcm.h"
+#include "rk29_i2s.h"
+
+#if 0
+#define        DBG(x...)       printk(KERN_INFO x)
+#else
+#define        DBG(x...)
+#endif
+
+static int rk29_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+        struct snd_soc_pcm_runtime *rtd = substream->private_data;
+        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+        unsigned int pll_out = 0; 
+        int ret;
+          
+        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
+        /*by Vincent Hsiung for EQ Vol Change*/
+        #define HW_PARAMS_FLAG_EQVOL_ON 0x21
+        #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
+        if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
+        {
+               ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent
+               DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+        }
+        else
+        {
+                
+                /* set codec DAI configuration */
+                #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
+                ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+                                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+                #endif 
+                #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
+                ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+                                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); 
+                #endif
+                if (ret < 0)
+                  return ret; 
+
+                /* set cpu DAI configuration */
+                #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
+                ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+                                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+                #endif 
+                #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
+                ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+                                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);        
+                #endif         
+                if (ret < 0)
+                  return ret;
+
+        }
+
+
+        switch(params_rate(params)) {
+        case 8000:
+        case 16000:
+        case 24000:
+        case 32000:
+        case 48000:
+                pll_out = 12288000;
+                break;
+        case 11025:
+        case 22050:
+        case 44100:
+                pll_out = 11289600;
+                break;
+        default:
+                DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
+                return -EINVAL;
+                break;
+        }
+        DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
+
+               #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
+#if 0          //use pll from blck
+          /*Set the pll of rt5625,the Pll source from BITCLK on CPU is master mode*/
+         //bitclk is 64fs           
+                   ret=snd_soc_dai_set_pll(codec_dai,0,params_rate(params)*64,pll_out);
+                   if (ret < 0)
+                   { 
+                      DBG("rk29_hw_params_rt5625:failed to set the pll for codec side\n"); 
+                          return ret;
+                   }
+#endif     
+                  /*Set the system clk for codec*/
+                   ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN);
+                   if (ret < 0)
+                   {
+                      DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); 
+                          return ret;
+                       }           
+               #endif
+  
+/*
+        #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
+
+                  if((24576000%params_rate(params))==0)        //for 8k,16k,32k,48k
+                       {
+                               snd_soc_dai_set_pll(codec_dai,0,pll_out, 24576000);
+                               snd_soc_dai_set_sysclk(codec_dai,0, 24576000, SND_SOC_CLOCK_IN);                        
+                       }
+                  else if((22579200%params_rate(params))==0)   //for 11k,22k,44k
+                       {
+                               snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200);
+                               snd_soc_dai_set_sysclk(codec_dai,0, 22579200, SND_SOC_CLOCK_IN);                        
+                       }
+      
+        #endif
+*/
+
+        #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
+        snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
+        snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);
+        snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);
+        #endif
+
+        DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params));
+        
+        return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5625_dapm_widgets[] = {
+       
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+       SND_SOC_DAPM_SPK("Ext Spk", NULL),
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+
+};
+
+static const struct snd_soc_dapm_route audio_map[]={
+
+       /* Mic Jack --> MIC_IN*/
+       {"Mic1 Bias", NULL, "Mic Jack"},
+       {"Mic1", NULL, "Mic1 Bias"},
+       /* HP_OUT --> Headphone Jack */
+       {"Headphone Jack", NULL, "HPL"},
+       {"Headphone Jack", NULL, "HPR"},
+       /* LINE_OUT --> Ext Speaker */
+       {"Ext Spk", NULL, "SPKL"},
+       {"Ext Spk", NULL, "SPKR"},
+
+} ;
+
+/*
+ * Logic for a rt5625 as connected on a rockchip board.
+ */
+static int rk29_rt5625_init(struct snd_soc_codec *codec)
+{
+        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+
+        /* Add specific widgets */
+       snd_soc_dapm_new_controls(codec, rt5625_dapm_widgets,
+                                 ARRAY_SIZE(rt5625_dapm_widgets));
+       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+        /* Set up specific audio path audio_mapnects */
+        snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+//        snd_soc_dapm_nc_pin(codec, "HP_L");
+        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+//     snd_soc_dapm_nc_pin(codec, "HP_R");
+       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+        snd_soc_dapm_sync(codec);
+        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+
+        return 0;
+}
+
+static struct snd_soc_ops rk29_ops = {
+         .hw_params = rk29_hw_params,
+};
+
+static struct snd_soc_dai_link rk29_dai = {
+         .name = "RT5625",
+         .stream_name = "RT5625 PCM",
+         .cpu_dai = &rk29_i2s_dai[0],
+         .codec_dai = &rt5625_dai[0],
+         .init = rk29_rt5625_init,
+         .ops = &rk29_ops,
+};
+
+static struct snd_soc_card snd_soc_card_rk29 = {
+         .name = "RK29_RT5625",
+         .platform = &rk29_soc_platform,
+         .dai_link = &rk29_dai,
+         .num_links = 1,
+};
+
+
+static struct snd_soc_device rk29_snd_devdata = {
+         .card = &snd_soc_card_rk29,
+         .codec_dev = &soc_codec_dev_rt5625,
+};
+
+static struct platform_device *rk29_snd_device;
+
+static int __init audio_card_init(void)
+{
+       int ret =0;     
+        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+       rk29_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!rk29_snd_device) {
+                 DBG("platform device allocation failed\n");
+                 ret = -ENOMEM;
+                 return ret;
+       }
+       platform_set_drvdata(rk29_snd_device, &rk29_snd_devdata);
+       rk29_snd_devdata.dev = &rk29_snd_device->dev;
+       ret = platform_device_add(rk29_snd_device);
+       if (ret) {
+               DBG("platform device add failed\n");
+               platform_device_put(rk29_snd_device);
+       }
+       return ret;
+}
+
+static void __exit audio_card_exit(void)
+{
+       platform_device_unregister(rk29_snd_device);
+}
+
+module_init(audio_card_init);
+module_exit(audio_card_exit);
+/* Module information */
+MODULE_AUTHOR("rockchip");
+MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
+MODULE_LICENSE("GPL");