phonepad: modify codec rt5625 driver for kernel3.0
author宋秀杰 <sxj@rock-chips.com>
Tue, 6 Mar 2012 12:17:40 +0000 (20:17 +0800)
committer宋秀杰 <sxj@rock-chips.com>
Tue, 6 Mar 2012 12:17:40 +0000 (20:17 +0800)
sound/soc/codecs/rt5625.c
sound/soc/codecs/rt5625.h
sound/soc/rk29/rk29_rt5625.c

index 129acc4c5d790f6430ea63667da52db914547300..c2704cbbc508a26c0f5844239ffd08b70fb79ab8 100644 (file)
@@ -1,14 +1,22 @@
+/*
+ * rt5625.c  --  RT5625 ALSA SoC audio codec driver
+ *
+ * Copyright 2011 Realtek Semiconductor Corp.
+ * Author: Johnny Hsu <johnnyhsu@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #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-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>
-
+#define RT5625_PROC
+#ifdef RT5625_PROC
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+char debug_write_read = 0;
 #endif
 
-#if 0
+#if 1
 #define DBG(x...) printk(KERN_INFO x)
 #else
 #define DBG(x...) do { } while (0)
 #endif
 
-#define AUDIO_NAME "rt5625"
-#define RT5625_VERSION "0.03 alsa 1.0.21"
-#define ALSA_SOC_VERSION "1.0.21"
+static struct snd_soc_codec *rt5625_codec;
 
-#define RT5625_EQ_FUNC_ENA  0
+#define RT5625_REG_RW 1 /* for debug */
+//#define RT5625_DEMO 1        /* only for demo; please remove it */
 
-static void hp_depop_mode2(struct snd_soc_codec *codec);
-static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute); 
+#define RT5625_F_SMT_PHO
+#define RT5625_PLY_BIT 0
+#define RT5625_PLY_MASK (0x1)
+#define RT5625_REC_BIT 1
+#define RT5625_REC_MASK (0x1 << RT5625_REC_BIT)
+#define RT5625_3G_BIT 2
+#define RT5625_3G_MASK (0x1 << RT5625_3G_BIT)
+#define RT5625_BT_BIT 3
+#define RT5625_BT_MASK (0x1 << RT5625_BT_BIT)
+#define RT5625_VOIP_BIT 4
+#define RT5625_VOIP_MASK (0x1 << RT5625_VOIP_BIT)
 
 struct rt5625_priv {
        unsigned int stereo_sysclk;
        unsigned int voice_sysclk;
-};
 
-struct rt5625_init_reg {
-       u8 reg_index;
-       u16 reg_value;  
+       int vodsp_fun;
+#ifdef RT5625_F_SMT_PHO
+       int app_bmp;/* bit{0, 1, 2, 3, 4} = {play, rec, 3g, bt, voip} */
+       int pll_sel;
+       int pll2_sel;
+       int dac_active;
+       int adc_active;
+       int headset;
+       int vodsp_fun_bak;
+#endif
 };
 
-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
-
+#ifdef RT5625_F_SMT_PHO
+static u16 rt5625_voip_back[][2] = {
+       {RT5625_VODSP_PDM_CTL, 0x0000},
+       {RT5625_F_DAC_ADC_VDAC, 0x0000},
 };
+#define RT5625_VOIP_BK_NUM \
+       (sizeof(rt5625_voip_back) / sizeof(rt5625_voip_back[0]))
+#endif
 
-#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    
+#ifdef RT5625_DEMO
+struct rt5625_init_reg {
+       u8 reg;
+       u16 val;
 };
 
-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},
-       
+static struct rt5625_init_reg init_list[] = {
+       {RT5625_HP_OUT_VOL              , 0x8888},      //default is -12db
+       {RT5625_SPK_OUT_VOL             , 0x8080},      //default is 0db
+       {RT5625_PHONEIN_VOL     , 0xe800},      //phone differential
+       {RT5625_DAC_MIC_CTRL    , 0xee01},      //DAC to hpmixer & spkmixer
+       {RT5625_OUTMIX_CTRL             , 0x2bc8},      //spk from spkmixer; hp from hpmixer; aux from monomixer; classAB
+       {RT5625_ADC_REC_MIXER   , 0x1f1f},      //record source from mic1 & mic2
+       {RT5625_GEN_CTRL1               , 0x0c08},      //speaker vdd ratio is 1; 1.25VDD ratio
 };
+#define RT5625_INIT_REG_LEN ARRAY_SIZE(init_list)
 
+static int rt5625_reg_init(struct snd_soc_codec *codec)
+{
+       int i;
+       for (i = 0; i < RT5625_INIT_REG_LEN; i++)
+               snd_soc_write(codec, init_list[i].reg, init_list[i].val);
+       return 0;
+}
 #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*/
+static const u16 rt5625_reg[0x80] = {
+       [RT5625_RESET] = 0x59b4,
+       [RT5625_SPK_OUT_VOL] = 0x8080,
+       [RT5625_HP_OUT_VOL] = 0x8080,
+       [RT5625_AUX_OUT_VOL] = 0x8080,
+       [RT5625_PHONEIN_VOL] = 0xc800,
+       [RT5625_LINE_IN_VOL] = 0xe808,
+       [RT5625_DAC_VOL] = 0x1010,
+       [RT5625_MIC_VOL] = 0x0808,
+       [RT5625_DAC_MIC_CTRL] = 0xee0f,
+       [RT5625_ADC_REC_GAIN] = 0xcbcb,
+       [RT5625_ADC_REC_MIXER] = 0x7f7f,
+       [RT5625_VDAC_OUT_VOL] = 0xe010,
+       [RT5625_OUTMIX_CTRL] = 0x8008,
+       [RT5625_VODSP_CTL] = 0x2007,
+       [RT5625_DMIC_CTRL] = 0x00c0,
+       [RT5625_PD_CTRL] = 0xef00,
+       [RT5625_GEN_CTRL1] = 0x0c0a,
+       [RT5625_LDO_CTRL] = 0x0029,
+       [RT5625_GPIO_CONFIG] = 0xbe3e,
+       [RT5625_GPIO_POLAR] = 0x3e3e,
+       [RT5625_GPIO_STATUS] = 0x803a,
+       [RT5625_SOFT_VOL_CTRL] = 0x0009,
+       [RT5625_DAC_CLK_CTRL1] = 0x3075,
+       [RT5625_DAC_CLK_CTRL2] = 0x1010,
+       [RT5625_VDAC_CLK_CTRL1] = 0x3110,
+       [RT5625_PS_CTRL] = 0x0553,
+       [RT5625_VENDOR_ID1] = 0x10ec,
+       [RT5625_VENDOR_ID2] = 0x5c02,
 };
 
-
-Voice_DSP_Reg VODSP_AEC_Init_Value[]=
-{
+rt5625_dsp_reg rt5625_dsp_init[] = {
        {0x232C, 0x0025},
        {0x230B, 0x0001},
        {0x2308, 0x007F},
@@ -168,13 +150,13 @@ Voice_DSP_Reg VODSP_AEC_Init_Value[]=
        {0x2304, 0x00FA},
        {0x2305, 0x0500},
        {0x2306, 0x4000},
-       {0x230D, 0x0900},
+       {0x230D, 0x0300},
        {0x230E, 0x0280},
        {0x2312, 0x00B1},
        {0x2314, 0xC000},
        {0x2316, 0x0041},
-       {0x2317, 0x2200},
-       {0x2318, 0x0C00},
+       {0x2317, 0x2800},
+       {0x2318, 0x0800},
        {0x231D, 0x0050},
        {0x231F, 0x4000},
        {0x2330, 0x0008},
@@ -193,1770 +175,2631 @@ Voice_DSP_Reg VODSP_AEC_Init_Value[]=
        {0x22D4, 0x2800},
        {0x22D5, 0x3000},
        {0x2399, 0x2800},
-       {0x230C, 0x0000},       //to enable VODSP AEC function
+       {0x230C, 0x0000},       
 };
-
-
-#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)
+#define RT5625_DSP_INIT_NUM ARRAY_SIZE(rt5625_dsp_init)
+
+static int rt5625_volatile_register(
+       struct snd_soc_codec *codec, unsigned int reg)
+{
+       switch (reg) {
+       case RT5625_RESET:
+       case RT5625_PD_CTRL:
+       case RT5625_GPIO_STATUS:
+       case RT5625_OTC_STATUS:
+       case RT5625_PRIV_DATA:
+       case RT5625_EQ_CTRL:
+       case RT5625_DSP_DATA:
+       case RT5625_DSP_CMD:
+       case RT5625_VENDOR_ID1:
+       case RT5625_VENDOR_ID2:
+               return 1;
+       default:
                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];
-
-       DBG(KERN_INFO "rt5625_read ok, reg = %x, value = %x\n", reg, value);
-
-       return value;   
+static int rt5625_readable_register(
+       struct snd_soc_codec *codec, unsigned int reg)
+{
+       switch (reg) {
+       case RT5625_RESET:
+       case RT5625_SPK_OUT_VOL:
+       case RT5625_HP_OUT_VOL:
+       case RT5625_AUX_OUT_VOL:
+       case RT5625_PHONEIN_VOL:
+       case RT5625_LINE_IN_VOL:
+       case RT5625_DAC_VOL:
+       case RT5625_MIC_VOL:
+       case RT5625_DAC_MIC_CTRL:
+       case RT5625_ADC_REC_GAIN:
+       case RT5625_ADC_REC_MIXER:
+       case RT5625_VDAC_OUT_VOL:
+       case RT5625_VODSP_PDM_CTL:
+       case RT5625_OUTMIX_CTRL:
+       case RT5625_VODSP_CTL:
+       case RT5625_MIC_CTRL:
+       case RT5625_DMIC_CTRL:
+       case RT5625_PD_CTRL:
+       case RT5625_F_DAC_ADC_VDAC:
+       case RT5625_SDP_CTRL:
+       case RT5625_EXT_SDP_CTRL:
+       case RT5625_PWR_ADD1:
+       case RT5625_PWR_ADD2:
+       case RT5625_PWR_ADD3:
+       case RT5625_GEN_CTRL1:
+       case RT5625_GEN_CTRL2:
+       case RT5625_PLL_CTRL:
+       case RT5625_PLL2_CTRL:
+       case RT5625_LDO_CTRL:
+       case RT5625_GPIO_CONFIG:
+       case RT5625_GPIO_POLAR:
+       case RT5625_GPIO_STICKY:
+       case RT5625_GPIO_WAKEUP:
+       case RT5625_GPIO_STATUS:
+       case RT5625_GPIO_SHARING:
+       case RT5625_OTC_STATUS:
+       case RT5625_SOFT_VOL_CTRL:
+       case RT5625_GPIO_OUT_CTRL:
+       case RT5625_MISC_CTRL:
+       case RT5625_DAC_CLK_CTRL1:
+       case RT5625_DAC_CLK_CTRL2:
+       case RT5625_VDAC_CLK_CTRL1:
+       case RT5625_PS_CTRL:
+       case RT5625_PRIV_INDEX:
+       case RT5625_PRIV_DATA:
+       case RT5625_EQ_CTRL:
+       case RT5625_DSP_ADDR:
+       case RT5625_DSP_DATA:
+       case RT5625_DSP_CMD:
+       case RT5625_VENDOR_ID1:
+       case RT5625_VENDOR_ID2:
+               return 1;
+       default:
+               return 0;
+       }
 }
 
-
-static unsigned int rt5625_read(struct snd_soc_codec *codec, unsigned int reg)
+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);
-}
+       unsigned int val;
 
-
-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;
+       val = codec->hw_read(codec, reg);
+       return val;
 }
 
 static int rt5625_write(struct snd_soc_codec *codec, unsigned int reg,
        unsigned int value)
 {
+       unsigned int val;
        u8 data[3];
-       unsigned int *regvalue = NULL;
 
        data[0] = reg;
-       data[1] = (value & 0xff00) >> 8;
-       data[2] = value & 0x00ff;
+       data[1] = (value >> 8) & 0xff;
+       data[2] = value & 0xff;
        
-       if ((reg == 0x80)
-               || (reg == 0x82)
-               || (reg == 0x84))
-       {               
-               regvalue = ((reg == 0x80) ? &reg80 : ((reg == 0x82) ? &reg82 : &reg84));
-               *regvalue = value;
-               DBG("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)
-       {
-               DBG("rt5625_write ok, reg = %x, value = %x\n", reg, value);
-               return 0;
-       }
-       else 
-       {
-               printk("rt5625_write fail\n");
-               return -EIO;
-       }
+       val = codec->hw_write(codec->control_data, data, 3);
+       return val;
 }
 
-int rt5625_write_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask)
+static int rt5625_reset(struct snd_soc_codec *codec)
 {
-       
-       unsigned char RetVal=0;
-       unsigned  int CodecData;
-
-       DBG("rt5625_write_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask);
+       return snd_soc_write(codec, RT5625_RESET, 0);
+}
 
-       if(!mask)
-               return 0; 
+/**
+ * rt5625_index_write - Write private register.
+ * @codec: SoC audio codec device.
+ * @reg: Private register index.
+ * @value: Private register Data.
+ *
+ * Modify private register for advanced setting. It can be written through
+ * private index (0x6a) and data (0x6c) register.
+ *
+ * Returns 0 for success or negative error code.
+ */
+static int rt5625_index_write(struct snd_soc_codec *codec,
+               unsigned int reg, unsigned int value)
+{
+       int ret;
 
-       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);
+       ret = snd_soc_write(codec, RT5625_PRIV_INDEX, reg);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set private addr: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_PRIV_DATA, value);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set private value: %d\n", ret);
+               goto err;
        }
+       return 0;
 
-       return RetVal;
+err:
+       return ret;
 }
 
-
-void rt5625_write_index(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
+/**
+ * rt5625_index_read - Read private register.
+ * @codec: SoC audio codec device.
+ * @reg: Private register index.
+ *
+ * Read advanced setting from private register. It can be read through
+ * private index (0x6a) and data (0x6c) register.
+ *
+ * Returns private register value or negative error code.
+ */
+static unsigned int rt5625_index_read(
+       struct snd_soc_codec *codec, unsigned int reg)
 {
-       
-       rt5625_write(codec,0x6a,reg);
-       rt5625_write(codec,0x6c,value); 
-}
+       int ret;
 
-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;
+       ret = snd_soc_write(codec, RT5625_PRIV_INDEX, reg);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set private addr: %d\n", ret);
+               return ret;
+       }
+       return snd_soc_read(codec, RT5625_PRIV_DATA);
 }
 
-void rt5625_write_index_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask)
+/**
+ * rt5625_index_update_bits - update private register bits
+ * @codec: Audio codec
+ * @reg: Private register index.
+ * @mask: Register mask
+ * @value: New value
+ *
+ * Writes new register value.
+ *
+ * Returns 1 for change, 0 for no change, or negative error code.
+ */
+static int rt5625_index_update_bits(struct snd_soc_codec *codec,
+       unsigned int reg, unsigned int mask, unsigned int value)
 {
-       
-//     unsigned char RetVal=0;
-       unsigned  int CodecData;
-
-       DBG("rt5625_write_index_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask);
+       unsigned int old, new;
+       int change, ret;
 
-       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);
+       ret = rt5625_index_read(codec, reg);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read private reg: %d\n", ret);
+               goto err;
        }
-}
 
-//#define rt5625_write_mask(c, reg, value, mask) snd_soc_update_bits(c, reg, mask, value)
+       old = ret;
+       new = (old & ~mask) | (value & mask);
+       change = old != new;
+       if (change) {
+               ret = rt5625_index_write(codec, reg, new);
+               if (ret < 0) {
+                       dev_err(codec->dev,
+                               "Failed to write private reg: %d\n", ret);
+                       goto err;
+               }
+       }
+       return change;
 
-#define rt5625_reset(c) rt5625_write(c, RT5625_RESET, 0)
+err:
+       return ret;
+}
 
-/*read/write dsp reg*/
-static int rt5625_wait_vodsp_i2c_done(struct snd_soc_codec *codec)
+/**
+ * rt5625_dsp_done - Wait until DSP is ready.
+ * @codec: SoC Audio Codec device.
+ *
+ * To check voice DSP status and confirm it's ready for next work.
+ *
+ * Returns 0 for success or negative error code.
+ */
+static int rt5625_dsp_done(struct snd_soc_codec *codec)
 {
-       unsigned int checkcount = 0, vodsp_data;
+       unsigned int count = 0, dsp_val;
 
-       vodsp_data = rt5625_read(codec, RT5625_VODSP_REG_CMD);
-       while(vodsp_data & VODSP_BUSY)
-       {
-               if(checkcount > 10)
+       dsp_val = snd_soc_read(codec, RT5625_DSP_CMD);
+       while(dsp_val & RT5625_DSP_BUSY_MASK) {
+               if(count > 10)
                        return -EBUSY;
-               vodsp_data = rt5625_read(codec, RT5625_VODSP_REG_CMD);
-               checkcount ++;          
+               dsp_val = snd_soc_read(codec, RT5625_DSP_CMD);
+               count ++;               
        }
+
        return 0;
 }
 
-static int rt5625_write_vodsp_reg(struct snd_soc_codec *codec, unsigned int vodspreg, unsigned int value)
+/**
+ * rt5625_dsp_write - Write DSP register.
+ * @codec: SoC audio codec device.
+ * @reg: DSP register index.
+ * @value: DSP register Data.
+ *
+ * Modify voice DSP register for sound effect. The DSP can be controlled
+ * through DSP addr (0x70), data (0x72) and cmd (0x74) register. It has
+ * to wait until the DSP is ready.
+ *
+ * Returns 0 for success or negative error code.
+ */
+static int rt5625_dsp_write(struct snd_soc_codec *codec,
+               unsigned int reg, unsigned int value)
 {
-       int ret = 0;
-
-       if(ret != rt5625_wait_vodsp_i2c_done(codec))
-               return -EBUSY;
+       int ret;
 
-       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);
+       ret = rt5625_dsp_done(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "DSP is busy: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_DSP_ADDR, reg);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_DSP_DATA, value);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP data reg: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_DSP_CMD,
+               RT5625_DSP_W_EN | RT5625_DSP_CMD_MW);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
+               goto err;
+       }
        mdelay(10);
-       return ret;
+       return 0;
        
+err:
+       return ret;
 }
 
-static unsigned int rt5625_read_vodsp_reg(struct snd_soc_codec *codec, unsigned int vodspreg)
+/**
+ * rt5625_dsp_read - Read DSP register.
+ * @codec: SoC audio codec device.
+ * @reg: DSP register index.
+ *
+ * Read DSP setting value from voice DSP. The DSP can be controlled
+ * through DSP addr (0x70), data (0x72) and cmd (0x74) register. Each
+ * command has to wait until the DSP is ready.
+ *
+ * Returns DSP register value or negative error code.
+ */
+static unsigned int rt5625_dsp_read(
+       struct snd_soc_codec *codec, unsigned int reg)
 {
+       unsigned int val_h, val_l;
        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);
+       ret = rt5625_dsp_done(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "DSP is busy: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_DSP_ADDR, reg);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_DSP_CMD,
+               RT5625_DSP_R_EN | RT5625_DSP_CMD_MR);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
+               goto err;
+       }
+
+       /* Read DSP high byte data */
+       ret = rt5625_dsp_done(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "DSP is busy: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_DSP_ADDR, 0x26);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_DSP_CMD,
+               RT5625_DSP_R_EN | RT5625_DSP_CMD_RR);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
+               goto err;
+       }
+       ret = rt5625_dsp_done(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "DSP is busy: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_read(codec, RT5625_DSP_DATA);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read DSP data reg: %d\n", ret);
+               goto err;
+       }
+       val_h = ret;
 
-       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);
+       /* Read DSP low byte data */
+       ret = snd_soc_write(codec, RT5625_DSP_ADDR, 0x25);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_write(codec, RT5625_DSP_CMD,
+               RT5625_DSP_R_EN | RT5625_DSP_CMD_RR);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
+               goto err;
+       }
+       ret = rt5625_dsp_done(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "DSP is busy: %d\n", ret);
+               goto err;
+       }
+       ret = snd_soc_read(codec, RT5625_DSP_DATA);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read DSP data reg: %d\n", ret);
+               goto err;
+       }
+       val_l = ret;
 
-       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);
+       return ((val_h & 0xff) << 8) |(val_l & 0xff);
 
-       if(ret != rt5625_wait_vodsp_i2c_done(codec))
-               return -EBUSY;
-       nDataL = rt5625_read(codec, RT5625_VODSP_REG_DATA);
-       value = ((nDataH & 0xff) << 8) |(nDataL & 0xff);
-       DBG("%s vodspreg=0x%x, value=0x%x\n", __func__, vodspreg, value);
-       return value;
+err:
+       return ret;
 }
 
-static int rt5625_reg_init(struct snd_soc_codec *codec)
-{
-       int i;
+/* ADCR function select */
+static const char *adcr_fun_sel[] = {
+       "Stereo ADC", "Voice ADC", "VoDSP", "PDM Slave"};
 
-       for (i = 0; i < RT5625_INIT_REG_NUM; i++)
-               rt5625_write(codec, rt5625_init_list[i].reg_index, rt5625_init_list[i].reg_value);
+static const struct soc_enum adcr_fun_sel_enum =
+       SOC_ENUM_SINGLE(RT5625_F_DAC_ADC_VDAC, RT5625_ADCR_F_SFT,
+                               ARRAY_SIZE(adcr_fun_sel), adcr_fun_sel);
 
-       return 0;
-}
+/* ADCL function select */
+static const char *adcl_fun_sel[] = {"Stereo ADC", "VoDSP"};
 
-//*************************************************************************************************
-//*************************************************************************************************
-#if (RT5625_EQ_FUNC_ENA==1)    
-//eq function
-static void rt5625_update_eqmode(struct snd_soc_codec *codec, int mode)
-{
-       u16 HwEqIndex=0;
+static const struct soc_enum adcl_fun_sel_enum =
+       SOC_ENUM_SINGLE(RT5625_F_DAC_ADC_VDAC, RT5625_ADCL_F_SFT,
+                       ARRAY_SIZE(adcl_fun_sel), adcl_fun_sel);
 
-       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]); 
-               }               
+/* Voice DSP */
+static const char *rt5625_aec_fun[] = {"Disable", "Enable"};
 
-               //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 const SOC_ENUM_SINGLE_DECL(rt5625_aec_fun_enum, 0, 0, rt5625_aec_fun);
 
+static const char *rt5625_dsp_lrck[] = {"8KHz", "16KHz"};
 
-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;
+static const SOC_ENUM_SINGLE_DECL(rt5625_dsp_lrck_enum,
+       RT5625_VODSP_CTL, RT5625_DSP_LRCK_SFT, rt5625_dsp_lrck);
 
-       rt5625_update_eqmode(codec, ucontrol->value.enumerated.item[0]);
+static const char *rt5625_bp_ctrl[] = {"Bypass", "Normal"};
 
-       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 SOC_ENUM_SINGLE_DECL(rt5625_bp_ctrl_enum,
+       RT5625_VODSP_CTL, RT5625_DSP_BP_SFT, rt5625_bp_ctrl);
 
-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
-};
+static const char *rt5625_pd_ctrl[] = {"Power down", "Normal"};
+
+static const SOC_ENUM_SINGLE_DECL(rt5625_pd_ctrl_enum,
+       RT5625_VODSP_CTL, RT5625_DSP_PD_SFT, rt5625_pd_ctrl);
+
+static const char *rt5625_rst_ctrl[] = {"Reset", "Normal"};
+
+static const SOC_ENUM_SINGLE_DECL(rt5625_rst_ctrl_enum,
+       RT5625_VODSP_CTL, RT5625_DSP_RST_SFT, rt5625_rst_ctrl);
+/* Speaker */
+static const char *rt5625_spk_out[] = {"Class AB", "Class D"};
 
+static const SOC_ENUM_SINGLE_DECL(rt5625_spk_out_enum,
+       RT5625_OUTMIX_CTRL, RT5625_SPK_T_SFT, rt5625_spk_out);
 
+static const char *rt5625_spkl_src[] = {"LPRN", "LPRP", "LPLN", "MM"};
 
-//*****************************************************************************
-//function:Enable the Voice PCM interface Path
-//*****************************************************************************
-static int ConfigPcmVoicePath(struct snd_soc_codec *codec,unsigned int bEnableVoicePath,unsigned int mode)
+static const SOC_ENUM_SINGLE_DECL(rt5625_spkl_src_enum,
+       RT5625_OUTMIX_CTRL, RT5625_SPKN_S_SFT, rt5625_spkl_src);
+
+static const char *rt5625_spkamp_ratio[] = {"2.25 Vdd", "2.00 Vdd",
+               "1.75 Vdd", "1.50 Vdd", "1.25 Vdd", "1.00 Vdd"};
+
+static const SOC_ENUM_SINGLE_DECL(rt5625_spkamp_ratio_enum,
+       RT5625_GEN_CTRL1, RT5625_SPK_R_SFT, rt5625_spkamp_ratio);
+
+/* Output/Input Mode */
+//static const char *rt5625_auxout_mode[] = {"Differential", "Single ended"};
+
+//static const SOC_ENUM_SINGLE_DECL(rt5625_auxout_mode_enum,
+//     RT5625_OUTMIX_CTRL, RT5625_AUXOUT_MODE_SFT, rt5625_auxout_mode);
+
+//static const char *rt5625_input_mode[] = {"Single ended", "Differential"};
+
+//static const SOC_ENUM_SINGLE_DECL(rt5625_phone_mode_enum,
+//     RT5625_PHONEIN_VOL, RT5625_PHO_DIFF_SFT, rt5625_input_mode);
+
+//static const SOC_ENUM_SINGLE_DECL(rt5625_mic1_mode_enum,
+//     RT5625_MIC_VOL, RT5625_MIC1_DIFF_SFT, rt5625_input_mode);
+
+//static const SOC_ENUM_SINGLE_DECL(rt5625_mic2_mode_enum,
+//     RT5625_MIC_VOL, RT5625_MIC2_DIFF_SFT, rt5625_input_mode);
+
+static int rt5625_adcr_fun_sel_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
 {
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       unsigned int val, mask, bitmask;
 
-       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;
+       for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
+               ;
+       if (ucontrol->value.enumerated.item[0] > e->max - 1)
+               return -EINVAL;
+       val = ucontrol->value.enumerated.item[0] << e->shift_l;
+       mask = (bitmask - 1) << e->shift_l;
+
+       snd_soc_update_bits(codec, RT5625_PD_CTRL,
+               RT5625_PWR_PR0, RT5625_PWR_PR0);
+       if ((rt5625->app_bmp & RT5625_3G_MASK) &&
+               rt5625->vodsp_fun == RT5625_AEC_EN) {
+               snd_soc_update_bits(codec, e->reg, mask, RT5625_ADCR_F_PDM);
+       } else if (rt5625->app_bmp & RT5625_VOIP_MASK &&
+               rt5625->vodsp_fun == RT5625_AEC_EN) {
+               snd_soc_update_bits(codec, e->reg, mask, RT5625_ADCR_F_PDM);
+       } else if (rt5625->app_bmp & RT5625_BT_MASK) {
+               snd_soc_update_bits(codec, e->reg, mask, RT5625_ADCR_F_VADC);
+       } else {
+               snd_soc_update_bits(codec, e->reg, mask, val);
+       }
+       snd_soc_update_bits(codec, RT5625_PD_CTRL, RT5625_PWR_PR0, 0);
 
-                       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;
+       return 0;
+}
 
-                       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;
+static int rt5625_adcl_fun_sel_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       unsigned int val, mask, bitmask;
 
-                       default:
-                               //do nothing            
-                               break;
+       for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
+               ;
+       if (ucontrol->value.enumerated.item[0] > e->max - 1)
+               return -EINVAL;
+       val = ucontrol->value.enumerated.item[0] << e->shift_l;
+       mask = (bitmask - 1) << e->shift_l;
+
+       snd_soc_update_bits(codec, RT5625_PD_CTRL,
+               RT5625_PWR_PR0, RT5625_PWR_PR0);
+       if ((rt5625->app_bmp & RT5625_3G_MASK) &&
+               rt5625->vodsp_fun == RT5625_AEC_EN) {
+               snd_soc_update_bits(codec, e->reg, mask, RT5625_ADCL_F_DSP);
+       } else {
+               snd_soc_update_bits(codec, e->reg, mask, val);
+       }
+       snd_soc_update_bits(codec, RT5625_PD_CTRL, RT5625_PWR_PR0, 0);
 
-                       }
-               }
-               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)
+static int rt5625_init_vodsp_aec(struct snd_soc_codec *codec)
 {
-       int i;
-       int ret = 0;
+       int i, ret = 0;
 
        /*disable LDO power*/
-       rt5625_write_mask(codec, RT5625_LDO_CTRL,0,LDO_ENABLE);
+       snd_soc_update_bits(codec, RT5625_LDO_CTRL,
+               RT5625_LDO_MASK, RT5625_LDO_DIS);
        mdelay(20);     
-       rt5625_write_mask(codec, RT5625_VODSP_CTL,VODSP_NO_PD_MODE_ENA,VODSP_NO_PD_MODE_ENA);
+       snd_soc_update_bits(codec, RT5625_VODSP_CTL,
+               RT5625_DSP_PD_MASK, RT5625_DSP_PD_NOR);
        /*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);
+       snd_soc_update_bits(codec, RT5625_LDO_CTRL,
+               RT5625_LDO_MASK | RT5625_LDO_VC_MASK,
+               RT5625_LDO_EN | RT5625_LDO_VC_1_20V);
        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);
+       snd_soc_update_bits(codec, RT5625_PWR_ADD3, RT5625_P_DSP_IF |
+               RT5625_P_DSP_I2C, RT5625_P_DSP_IF | RT5625_P_DSP_I2C);
        mdelay(1);
-       rt5625_write_mask(codec, RT5625_VODSP_CTL,0,VODSP_NO_RST_MODE_ENA);     /*Reset VODSP*/
+       /*Reset VODSP*/
+       snd_soc_update_bits(codec, RT5625_VODSP_CTL,
+               RT5625_DSP_RST_MASK, RT5625_DSP_RST_EN);
        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*/               
+       /*set VODSP to non-reset status*/
+       snd_soc_update_bits(codec, RT5625_VODSP_CTL,
+               RT5625_DSP_RST_MASK, RT5625_DSP_RST_NOR);
        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);
+       for(i = 0; i < RT5625_DSP_INIT_NUM; i++) {
+               ret = rt5625_dsp_write(codec, rt5625_dsp_init[i].index,
+                                       rt5625_dsp_init[i].value);
                if(ret)
                        return -EIO;
        }               
-
-       schedule_timeout_uninterruptible(msecs_to_jiffies(10)); 
+       mdelay(10);     
+       //printk("[DSP poweron] 0x%04x: 0x%04x\n", 0x230C, rt5625_dsp_read(codec, 0x230C));
 
        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)
+static int rt5625_aec_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-               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 
+       ucontrol->value.integer.value[0] = rt5625->vodsp_fun;
+       return 0;
+}
 
-                               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 
+static int rt5625_aec_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{ 
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-                               break;
+       if(ucontrol->value.integer.value[0] == rt5625->vodsp_fun)
+               return 0;
+       rt5625->vodsp_fun = ucontrol->value.integer.value[0];
 
-                       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;
-               }               
+       switch(rt5625->vodsp_fun) {
+       case RT5625_AEC_EN:
+               break;
+       case RT5625_AEC_DIS:
+               if (!(rt5625->app_bmp & RT5625_3G_MASK) ||
+                       ((rt5625->app_bmp & RT5625_3G_MASK) && rt5625->headset)) {
+                       snd_soc_update_bits(codec, RT5625_VODSP_CTL,
+                               RT5625_DSP_PD_MASK, RT5625_DSP_PD_EN);
+                       snd_soc_update_bits(codec, RT5625_PWR_ADD3,
+                               RT5625_P_DSP_IF | RT5625_P_DSP_I2C, 0);
+                       snd_soc_update_bits(codec, RT5625_LDO_CTRL,
+                               RT5625_LDO_MASK, RT5625_LDO_DIS);
+               }
+               break;
+       default:
+               break;
+       }
 
        return 0;
 }
 
-static int enable_vodsp_aec(struct snd_soc_codec *codec, unsigned int VodspAEC_En, unsigned int AEC_mode)
+#ifdef RT5625_F_SMT_PHO
+static int rt5625_app_get(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
 {
-       int  ret = 0;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-       
-       if (VodspAEC_En != 0)
-       {       
+       pr_info("App status: %x\n", rt5625->app_bmp);
 
-               //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);            
+       return 0;
+}
 
+static int rt5625_cap_voip_chk_put(struct snd_kcontrol *kcontrol, 
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int i, upd;
+
+       /* VoIP start up if record & playback all turn on, or AEC       *
+        * is disabled. otherwise, cheat dapm.                  */
+       if ((rt5625->app_bmp & RT5625_REC_MASK) == 0 ||
+               (rt5625->app_bmp & RT5625_PLY_MASK) == 0) {
+               /* backup registers for voip routing */
+               for(i = 0; i < RT5625_VOIP_BK_NUM; i++)
+                       rt5625_voip_back[i][1] =
+                               snd_soc_read(codec, rt5625_voip_back[i][0]);
+               /* cheat dapm */
+               snd_soc_update_bits(codec, RT5625_VODSP_PDM_CTL,
+                       RT5625_REC_IIS_S_MASK, RT5625_REC_IIS_S_SRC2);
+               return 0;
        }
-       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);                                
+
+       if (rt5625->headset) {
+               /* backup registers for voip routing */
+               for(i = 0; i < RT5625_VOIP_BK_NUM; i++)
+                       rt5625_voip_back[i][1] =
+                               snd_soc_read(codec, rt5625_voip_back[i][0]);
+               /* cheat dapm */
+               snd_soc_update_bits(codec, RT5625_VODSP_PDM_CTL,
+                       RT5625_REC_IIS_S_MASK, RT5625_REC_IIS_S_SRC2);
+       } else
+               rt5625->vodsp_fun = RT5625_AEC_EN;
+
+       upd = (rt5625->app_bmp & ~RT5625_VOIP_MASK) |
+               (ucontrol->value.integer.value[0] << RT5625_VOIP_BIT);
+       if (rt5625->app_bmp != upd) {
+               rt5625->app_bmp = upd;
+               rt5625->app_bmp &= ~(RT5625_3G_MASK | RT5625_BT_MASK);
        }
 
-       return ret;
+       return 0;
 }
 
-static void rt5625_aec_config(struct snd_soc_codec *codec, unsigned int mode)
+static int rt5625_cap_voip_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
 {
-       DBG("rt5625_aec_config %d\n",mode);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int i;
 
-       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);                
+       if (rt5625->app_bmp & RT5625_VOIP_MASK) {
+               if (rt5625->headset) {
+                       snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_MIC1 | RT5625_M_RM_R_MIC1 | RT5625_M_RM_L_PHO,
+                               RT5625_M_RM_L_MIC1 | RT5625_M_RM_R_MIC1 | RT5625_M_RM_L_PHO);
+                       /* recover all changes by voip */
+                       for(i = 0; i < RT5625_VOIP_BK_NUM; i++)
+                               snd_soc_write(codec, rt5625_voip_back[i][0],
+                                               rt5625_voip_back[i][1]);
+                       snd_soc_update_bits(codec, RT5625_VODSP_PDM_CTL,
+                               RT5625_SRC1_PWR | RT5625_SRC2_PWR, 0);
+               } else {
+                       snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_MIC1 | RT5625_M_RM_L_MIC2 | RT5625_M_RM_R_MIC2 | RT5625_M_RM_L_PHO,
+                               RT5625_M_RM_L_MIC1 | RT5625_M_RM_L_MIC2 | RT5625_M_RM_R_MIC2 | RT5625_M_RM_L_PHO);
+                       rt5625->vodsp_fun = RT5625_AEC_EN;
+                       /* Mic1 & Mic2 boost 0db */
+                       snd_soc_update_bits(codec, RT5625_MIC_CTRL,
+                               RT5625_MIC1_BST_MASK | RT5625_MIC2_BST_MASK,
+                               RT5625_MIC1_BST_BYPASS | RT5625_MIC2_BST_BYPASS);
+                       /* Capture volume gain 9db */
+                       snd_soc_update_bits(codec, RT5625_ADC_REC_GAIN,
+                               RT5625_G_ADCL_MASK | RT5625_G_ADCR_MASK, (0x11 << 8 ) | 0x11);
+               }
+       } else {
+               /* recover all changes by voip */
+               for(i = 0; i < RT5625_VOIP_BK_NUM; i++)
+                       snd_soc_write(codec, rt5625_voip_back[i][0],
+                                       rt5625_voip_back[i][1]);
+               snd_soc_update_bits(codec, RT5625_VODSP_PDM_CTL,
+                       RT5625_SRC1_PWR | RT5625_SRC2_PWR, 0);
+               if (rt5625->app_bmp & RT5625_3G_MASK &&
+                       rt5625->vodsp_fun ==  RT5625_AEC_EN) {
+                       /* Mic1 boost 0db */
+                       snd_soc_update_bits(codec, RT5625_MIC_CTRL,
+                               RT5625_MIC1_BST_MASK, RT5625_MIC1_BST_BYPASS);
+                       /* Capture volume gain 9db */
+                       snd_soc_update_bits(codec, RT5625_ADC_REC_GAIN,
+                               RT5625_G_ADCR_MASK, 0x11);
+               }
        }
-}
-//****************************************************************************************************************
-//*
-//*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:
+       return 0;
+}
 
-               break;
+static int rt5625_hs_voip_chk_put(struct snd_kcontrol *kcontrol, 
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int i, upd;
+
+       rt5625->headset = true;
+       if ((rt5625->app_bmp & RT5625_REC_MASK) == 0 ||
+               (rt5625->app_bmp & RT5625_PLY_MASK) == 0) {
+               /* backup registers for voip routing */
+               for(i = 0; i < RT5625_VOIP_BK_NUM; i++)
+                       rt5625_voip_back[i][1] =
+                               snd_soc_read(codec, rt5625_voip_back[i][0]);
+               rt5625->vodsp_fun_bak = rt5625->vodsp_fun;
+               /* cheat dapm */
+               snd_soc_update_bits(codec, RT5625_VODSP_PDM_CTL,
+                       RT5625_REC_IIS_S_MASK | RT5625_RXDP_PWR, RT5625_REC_IIS_S_ADC);
+               return 0;
+       }
+
+       upd = (rt5625->app_bmp & ~RT5625_VOIP_MASK) |
+               (ucontrol->value.integer.value[0] << RT5625_VOIP_BIT);
+       if (rt5625->app_bmp != upd) {
+               rt5625->app_bmp = upd;
+               rt5625->app_bmp &= ~(RT5625_3G_MASK | RT5625_BT_MASK);
        }
 
        return 0;
 }
 
-
-static int rt5625_get_dsp_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int rt5625_hs_voip_put(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;  
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int i;
+
+       if (rt5625->app_bmp & RT5625_VOIP_MASK) {
+               snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                       RT5625_M_RM_R_MIC1 | RT5625_M_RM_L_PHO,
+                       RT5625_M_RM_R_MIC1 | RT5625_M_RM_L_PHO);
+               /* Mic1 & Mic2 boost 0db */
+               snd_soc_update_bits(codec, RT5625_MIC_CTRL,
+                       RT5625_MIC1_BST_MASK | RT5625_MIC2_BST_MASK,
+                       RT5625_MIC1_BST_BYPASS | RT5625_MIC2_BST_BYPASS);
+               /* Capture volume gain 9db */
+               snd_soc_update_bits(codec, RT5625_ADC_REC_GAIN,
+                       RT5625_G_ADCL_MASK | RT5625_G_ADCR_MASK, (0x11 << 8 ) | 0x11);
+       } else {
+               /* recover all changes by voip */
+               for(i = 0; i < RT5625_VOIP_BK_NUM; i++)
+                       snd_soc_write(codec, rt5625_voip_back[i][0],
+                                       rt5625_voip_back[i][1]);
+               rt5625->vodsp_fun = rt5625->vodsp_fun_bak;
+               if ((rt5625->app_bmp & RT5625_3G_MASK) && rt5625->vodsp_fun == RT5625_AEC_EN) {
+                       snd_soc_update_bits(codec, RT5625_F_DAC_ADC_VDAC,
+                               RT5625_ADCR_F_MASK, RT5625_ADCR_F_PDM);
+               } else if (rt5625->app_bmp & RT5625_BT_MASK) {
+                       snd_soc_update_bits(codec, RT5625_F_DAC_ADC_VDAC,
+                               RT5625_ADCR_F_MASK, RT5625_ADCR_F_VADC);
+               } else {
+                       snd_soc_update_bits(codec, RT5625_F_DAC_ADC_VDAC,
+                               RT5625_ADCR_F_MASK, RT5625_ADCR_F_ADC);
+               }
+       }
 
-       ucontrol->value.integer.value[0] = mode;
        return 0;
 }
 
-
-static int rt5625_set_dsp_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int rt5625_voip_chk_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)&0x03;
-
-       DBG("rt5625_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])
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int i, upd;
+
+       rt5625->headset = false;
+       /* voip start-up if record is on-going; otherwise, cheat dapm */
+       if ((rt5625->app_bmp & RT5625_REC_MASK) == 0 ||
+               (rt5625->app_bmp & RT5625_PLY_MASK) == 0) {
+               /* backup registers for voip routing */
+               for(i = 0; i < RT5625_VOIP_BK_NUM; i++)
+                       rt5625_voip_back[i][1] =
+                               snd_soc_read(codec, rt5625_voip_back[i][0]);
+               rt5625->vodsp_fun_bak = rt5625->vodsp_fun;
+               /* cheat dapm */
+               snd_soc_update_bits(codec, RT5625_VODSP_PDM_CTL,
+                       RT5625_RXDP_S_MASK | RT5625_REC_IIS_S_MASK | RT5625_RXDP_PWR,
+                       RT5625_RXDP_S_SRC1 | RT5625_REC_IIS_S_SRC2);
                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
+       upd = (rt5625->app_bmp & ~RT5625_VOIP_MASK) |
+               (ucontrol->value.integer.value[0] << RT5625_VOIP_BIT);
+       if (rt5625->app_bmp != upd) {
+               rt5625->app_bmp = upd;
+               rt5625->app_bmp &= ~(RT5625_3G_MASK | RT5625_BT_MASK);
+       }
 
-               break;
+       return 0;
+}
 
-               case RT5625_AEC_IIS_IN_OUT:
+static int rt5625_voip_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int i;
 
-                       rt5625_aec_config(codec,DAC_IN_ADC_OUT);//enable AEC IIS in/out function and path
+       if (rt5625->app_bmp & RT5625_VOIP_MASK) {
+               snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                       RT5625_M_RM_R_MIC2 | RT5625_M_RM_L_PHO,
+                       RT5625_M_RM_R_MIC2 | RT5625_M_RM_L_PHO);
+               /* Mic1 & Mic2 boost 0db */
+               snd_soc_update_bits(codec, RT5625_MIC_CTRL,
+                       RT5625_MIC1_BST_MASK | RT5625_MIC2_BST_MASK,
+                       RT5625_MIC1_BST_BYPASS | RT5625_MIC2_BST_BYPASS);
+               /* Capture volume gain 9db */
+               snd_soc_update_bits(codec, RT5625_ADC_REC_GAIN,
+                       RT5625_G_ADCL_MASK | RT5625_G_ADCR_MASK, (0x11 << 8 ) | 0x11);
+       } else {
+               /* recover all changes by voip */
+               for(i = 0; i < RT5625_VOIP_BK_NUM; i++)
+                       snd_soc_write(codec, rt5625_voip_back[i][0],
+                                       rt5625_voip_back[i][1]);
+               rt5625->vodsp_fun = rt5625->vodsp_fun_bak;
+               snd_soc_update_bits(codec, RT5625_VODSP_PDM_CTL,
+                       RT5625_SRC1_PWR | RT5625_SRC2_PWR, 0);
+               if ((rt5625->app_bmp & RT5625_3G_MASK) && rt5625->vodsp_fun == RT5625_AEC_EN) {
+                       snd_soc_update_bits(codec, RT5625_F_DAC_ADC_VDAC,
+                               RT5625_ADCR_F_MASK, RT5625_ADCR_F_PDM);
+               } else if (rt5625->app_bmp & RT5625_BT_MASK) {
+                       snd_soc_update_bits(codec, RT5625_F_DAC_ADC_VDAC,
+                               RT5625_ADCR_F_MASK, RT5625_ADCR_F_VADC);
+               } else {
+                       snd_soc_update_bits(codec, RT5625_F_DAC_ADC_VDAC,
+                               RT5625_ADCR_F_MASK, RT5625_ADCR_F_ADC);
+               }
+       }
 
-               break;
+       return 0;
+}
 
-               case RT5625_AEC_ANALOG_IN_OUT:
-                       
-                       rt5625_aec_config(codec,ANALOG_IN_ANALOG_OUT);//enable AEC analog in/out function and path
-                       
-               break;
+static int rt5625_voip_get(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-               case RT5625_AEC_DISABLE:
-       
-                       rt5625_func_aec_disable(codec,rt5625_mode);             //disable previous select function.     
-       
-               break;  
+       ucontrol->value.integer.value[0] =
+               (rt5625->app_bmp & RT5625_VOIP_MASK) >> RT5625_VOIP_BIT;
 
-               default:
+       return 0;
+}
 
-               break;
-       }
+static int rt5625_play_get(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-       Virtual_reg &= 0xfffc;
-       Virtual_reg |= (ucontrol->value.integer.value[0]);
-       rt5625_write(codec, VIRTUAL_REG_FOR_MISC_FUNC, Virtual_reg);
+       ucontrol->value.integer.value[0] =
+               (rt5625->app_bmp & RT5625_PLY_MASK) >> RT5625_PLY_BIT;
 
-       DBG("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)
+static int rt5625_play_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
 {
-       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);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int upd;
+
+       upd = (rt5625->app_bmp & ~RT5625_PLY_MASK) |
+               (ucontrol->value.integer.value[0] << RT5625_PLY_BIT);
+       if (rt5625->app_bmp != upd)
+               rt5625->app_bmp = upd;
+
+       if (!(rt5625->app_bmp & RT5625_3G_MASK) ||
+               ((rt5625->app_bmp & RT5625_3G_MASK) && rt5625->headset)) {
+               snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                       RT5625_M_RM_L_PHO, RT5625_M_RM_L_PHO);
        }
+
        return 0;
 }
 
-
-static int rt5625_dump_dsp_put(struct snd_kcontrol *kcontrol, 
+static int rt5625_rec_get(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);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] =
+               (rt5625->app_bmp & RT5625_REC_MASK) >> RT5625_REC_BIT;
 
-       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)
+static int rt5625_rec_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
 {
-       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;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int upd;
+
+       upd = (rt5625->app_bmp & ~RT5625_REC_MASK) |
+               (ucontrol->value.integer.value[0] << RT5625_REC_BIT);
+       if (rt5625->app_bmp != upd)
+               rt5625->app_bmp = upd;
+
+       if (!(rt5625->app_bmp & RT5625_3G_MASK) ||
+               ((rt5625->app_bmp & RT5625_3G_MASK) && rt5625->headset)) {
+               snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                       RT5625_M_RM_L_PHO, RT5625_M_RM_L_PHO);
        }
+
+
        return 0;
 }
 
-static void hp_depop_mode2(struct snd_soc_codec *codec)
+static int rt5625_bt_get(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
 {
-        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);
-
-       DBG("delay 500 msec\n");
-
-        schedule_timeout_uninterruptible(msecs_to_jiffies(500));
-               
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-        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);
+       ucontrol->value.integer.value[0] =
+               (rt5625->app_bmp & RT5625_BT_MASK) >> RT5625_BT_BIT;
 
+       return 0;
 }
 
-//enable depop function for mute/unmute
-static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute)
+static int rt5625_bt_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
 {
-       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);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int upd;
+
+       if (!(rt5625->app_bmp & RT5625_REC_MASK)) {
+               snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                       RT5625_M_RM_L_MIC1 | RT5625_M_RM_L_MIC2 |
+                       RT5625_M_RM_R_MIC1 | RT5625_M_RM_R_MIC2,
+                       RT5625_M_RM_L_MIC1 | RT5625_M_RM_L_MIC2 |
+                       RT5625_M_RM_R_MIC1 | RT5625_M_RM_R_MIC2);
        }
-       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);
+
+       upd = (rt5625->app_bmp & ~RT5625_BT_MASK) |
+               (ucontrol->value.integer.value[0] << RT5625_BT_BIT);
+       if (rt5625->app_bmp != upd) {
+               rt5625->app_bmp = upd;
+               rt5625->app_bmp &= ~(RT5625_3G_MASK | RT5625_VOIP_MASK);
        }
 
+       return 0;
 }
 
+static int rt5625_3g_get(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       
+       ucontrol->value.integer.value[0] =
+               (rt5625->app_bmp & RT5625_3G_MASK) >> RT5625_3G_BIT;
 
-/*
- * _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),
+       return 0;
+}
 
-};
+static int rt5625_3g_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int upd;
+
+       rt5625->headset = false;
+       if (!(rt5625->app_bmp & RT5625_REC_MASK)) {
+               snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                       RT5625_M_RM_L_MIC1 | RT5625_M_RM_L_MIC2 | RT5625_M_RM_R_MIC2,
+                       RT5625_M_RM_L_MIC1 | RT5625_M_RM_L_MIC2 | RT5625_M_RM_R_MIC2);
+       }
 
-/*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),
-};
+       upd = (rt5625->app_bmp & ~RT5625_3G_MASK) |
+               (ucontrol->value.integer.value[0] << RT5625_3G_BIT);
+       if (rt5625->app_bmp != upd) {
+               rt5625->app_bmp = upd;
+               rt5625->app_bmp &= ~(RT5625_BT_MASK | RT5625_VOIP_MASK);
+       }
 
-/*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),
+       return 0;
+}
 
-};
+static int rt5625_hs_3g_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int upd;
+
+       rt5625->headset = true;
+       if (!(rt5625->app_bmp & RT5625_REC_MASK)) {
+               snd_soc_update_bits(codec, RT5625_ADC_REC_MIXER,
+                       RT5625_M_RM_L_MIC1 | RT5625_M_RM_L_MIC2 |
+                       RT5625_M_RM_R_MIC1 | RT5625_M_RM_R_MIC2,
+                       RT5625_M_RM_L_MIC1 | RT5625_M_RM_L_MIC2 |
+                       RT5625_M_RM_R_MIC1 | RT5625_M_RM_R_MIC2);
+       }
+       upd = (rt5625->app_bmp & ~RT5625_3G_MASK) |
+               (ucontrol->value.integer.value[0] << RT5625_3G_BIT);
+       if (rt5625->app_bmp != upd) {
+               rt5625->app_bmp = upd;
+               rt5625->app_bmp &= ~(RT5625_BT_MASK | RT5625_VOIP_MASK);
+       }
 
-/*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),
+       return 0;
+}
 
-};
+static int rt5625_dump_dsp_get(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       int i;
+       u16 val;
 
-/*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),
-};
+       pr_info("\n[ RT5625 DSP Register ]\n");
+       for (i = 0; i < RT5625_DSP_INIT_NUM; i++) {
+               val = rt5625_dsp_read(codec, rt5625_dsp_init[i].index);
+               if (val) pr_info("    0x%x: 0x%x\n",
+                       rt5625_dsp_init[i].index, val);
+       }
+       return 0;
+}
 
-/*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 rt5625_dac_active_get(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-static int mixer_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+       ucontrol->value.integer.value[0] = rt5625->dac_active;
+       return 0;
+}
+
+static int rt5625_dac_active_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = w->codec;
-       unsigned int l, r;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       struct snd_soc_dapm_widget *w;
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-       DBG("enter %s\n", __func__);
+       if(ucontrol->value.integer.value[0] == rt5625->dac_active)
+               return 0;
+       rt5625->dac_active = ucontrol->value.integer.value[0];
 
-       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);
+       /* playback is on-going; do nothing when turn off BT */
+       if (rt5625->dac_active == 0 && rt5625->app_bmp & RT5625_PLY_MASK)
+               return 0;
 
-       if ((l & 0x2) || (r & 0x2))
-               rt5625_write_mask(codec, 0x08, 0x0000, 0x8000);
-       else
-               rt5625_write_mask(codec, 0x08, 0x8000, 0x8000);
+       list_for_each_entry(w, &dapm->card->widgets, list)
+       {
+               if (!w->sname || w->dapm != dapm)
+                       continue;
+               if (strstr(w->sname, "Playback")) {
+                       pr_info("widget %s %s %s\n", w->name, w->sname,
+                               rt5625->dac_active ? "active" : "inactive");
+                       w->active = rt5625->dac_active;
+               }
+       }
 
-       if ((l & 0x4) || (r & 0x4))
-               rt5625_write_mask(codec, 0x10, 0x0000, 0x8000);
-       else
-               rt5625_write_mask(codec, 0x10, 0x8000, 0x8000);
+       if (!(rt5625->dac_active))
+               snd_soc_dapm_sync(dapm);
 
-       if ((l & 0x8) || (r & 0x8))
-               rt5625_write_mask(codec, 0x10, 0x0000, 0x0800);
-       else
-               rt5625_write_mask(codec, 0x10, 0x0800, 0x0800);
+       return 0;
+}
 
-       if ((l & 0x10) || (r & 0x10))
-               rt5625_write_mask(codec, 0x18, 0x0000, 0x8000);
-       else
-               rt5625_write_mask(codec, 0x18, 0x8000, 0x8000);
+static int rt5625_adc_active_get(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
+       ucontrol->value.integer.value[0] = rt5625->adc_active;
        return 0;
 }
 
+static int rt5625_adc_active_put(struct snd_kcontrol *kcontrol, 
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       struct snd_soc_dapm_widget *w;
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-/*
- *     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;
-       
-       DBG("enter %s\n", __func__);
-       reg = rt5625_read(codec, VIRTUAL_REG_FOR_MISC_FUNC) & (0x3 << 4);
-       if ((reg >> 4) != 0x3 && reg != 0)
+       if(ucontrol->value.integer.value[0] == rt5625->adc_active)
                return 0;
+       rt5625->adc_active = ucontrol->value.integer.value[0];
 
-       switch (event)
+       /* record is on-going; do nothing when turn off BT */
+       if (rt5625->adc_active == 0 && rt5625->app_bmp & RT5625_REC_MASK)
+               return 0;
+       
+       list_for_each_entry(w, &dapm->card->widgets, list)
        {
-               case SND_SOC_DAPM_POST_PMU:
-                       DBG("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:
-                       DBG("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;
+               if (!w->sname || w->dapm != dapm)
+                       continue;
+               if (strstr(w->sname, "Capture")) {
+                       pr_info("widget %s %s %s\n", w->name, w->sname,
+                               rt5625->adc_active ? "active" : "inactive");
+                       w->active = rt5625->adc_active;
+               }
        }
-       return 0;
-}
-
 
+       if (!(rt5625->adc_active))
+               snd_soc_dapm_sync(dapm);
 
+       return 0;
+}
 
-static int hp_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+static int rt5625_pll_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = w->codec;
-       int reg;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-       DBG("enter %s\n", __func__);
+       ucontrol->value.integer.value[0] = rt5625->pll_sel;
+       return 0;
+}
 
-       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:
 
-                       DBG("aftet virtual hp power down!\n");
+static int rt5625_pll_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{ 
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-                       hp_mute_unmute_depop(codec,1);//mute hp
-                       rt5625_write_mask(codec, 0x3a, 0x0000, 0x0300);
-                       rt5625_write_mask(codec, 0x3e, 0x0000, 0x0c00);                 
-                       break;
+       if(ucontrol->value.integer.value[0] == rt5625->pll_sel)
+               return 0;
+       rt5625->pll_sel = ucontrol->value.integer.value[0];
+
+       switch(rt5625->pll_sel) {
+       case RT5625_PLL_DIS:
+               pr_info("%s(): Disable\n", __func__);
+               snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                                       RT5625_SCLK_PLL1, 0);
+               snd_soc_write(codec, RT5625_DAC_CLK_CTRL2, 0);
+               break;
 
-               case SND_SOC_DAPM_POST_PMU:     
+       case RT5625_PLL_112896_225792:
+               pr_info("%s(): 11.2896>22.5792\n", __func__);
+               snd_soc_write(codec, RT5625_GEN_CTRL2, 0x0000);
+               snd_soc_write(codec, RT5625_PLL_CTRL, 0x06a0);
+               snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                       RT5625_SCLK_PLL1, RT5625_SCLK_PLL1);
+               snd_soc_write(codec, RT5625_DAC_CLK_CTRL2, 0x0210);
+               break;
 
-                       DBG("after virtual hp power up!\n");
-                       hp_depop_mode2(codec);
-                       hp_mute_unmute_depop(codec,0);//unmute hp
-                       break;
+       case RT5625_PLL_112896_24576:
+               pr_info("%s(): 11.2896->24.576\n", __func__);
+               snd_soc_write(codec, RT5625_GEN_CTRL2, 0x0000);
+               snd_soc_write(codec, RT5625_PLL_CTRL, 0x922f);
+               snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                       RT5625_SCLK_PLL1, RT5625_SCLK_PLL1);
+               snd_soc_write(codec, RT5625_DAC_CLK_CTRL2, 0x0210);
+               break;
 
-               default:
-                       return 0;
-       }       
+       default:
+               break;
+       }
 
        return 0;
 }
 
-
-
-static int aux_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+static int rt5625_pll2_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = rt5625->pll2_sel;
        return 0;
 }
 
-/*SPKOUT Mux*/
-static const struct snd_kcontrol_new rt5625_spkout_mux_out_controls = 
-SOC_DAPM_ENUM("Route", rt5625_enum[3]);
+static int rt5625_pll2_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
 
-/*HPLOUT MUX*/
-static const struct snd_kcontrol_new rt5625_hplout_mux_out_controls = 
-SOC_DAPM_ENUM("Route", rt5625_enum[4]);
+       if(ucontrol->value.integer.value[0] == rt5625->pll2_sel)
+               return 0;
+       rt5625->pll2_sel = ucontrol->value.integer.value[0];
+
+       if(rt5625->pll2_sel != RT5625_PLL_DIS) {
+               snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                       RT5625_VSCLK_MASK, RT5625_VSCLK_PLL2);
+               snd_soc_write(codec, RT5625_PLL2_CTRL, RT5625_PLL2_EN);
+               snd_soc_write(codec, RT5625_VDAC_CLK_CTRL1,
+                               RT5625_VBCLK_DIV1_4);
+               snd_soc_update_bits(codec, RT5625_EXT_SDP_CTRL,
+                       RT5625_PCM_CS_MASK, RT5625_PCM_CS_VSCLK);
+       }
 
-/*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]);
+       return 0;
+}
 
-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 char *rt5625_pll_sel[] = {"Disable", "11.2896->22.5792", "11.2896->24.576"};
 
-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"},
+static const SOC_ENUM_SINGLE_DECL(rt5625_pll_sel_enum, 0, 0, rt5625_pll_sel);
 
-               /*aux out mux*/
-               {"AUXOUT Mux", "HP Mixer", "HP Mixer"},
-               {"AUXOUT Mux", "SPK Mixer", "SPK Mixer"},
-               {"AUXOUT Mux", "Mono Mixer", "MoNo Mixer"},
+static const char *rt5625_pll2_sel[] = {"Disable", "Enable"};
 
-               /*spkl out pga*/
-               {"SPKL Out PGA", NULL, "SPKOUT Mux"},
+static const SOC_ENUM_SINGLE_DECL(rt5625_pll2_sel_enum, 0, 0, rt5625_pll2_sel);
+#endif
 
-               /*spkr out pga*/
-               {"SPKR Out PGA", NULL, "SPKOUT Mux"},
-               
-               /*hpl out pga*/
-               {"HPL Out PGA", NULL, "HPLOUT Mux"},
+static const char *rt5625_AUXOUT_mode[] = {"Differential mode", "Single-ended mode"}; 
+static const char *rt5625_Differential_Input_Control[] = {"Disable", "Enable"};  
 
-               /*hpr out pga*/
-               {"HPR Out PGA", NULL, "HPROUT Mux"},
+static const struct soc_enum rt5625_differential_enum[] = {
+SOC_ENUM_SINGLE(RT5625_OUTMIX_CTRL, 4, 2, rt5625_AUXOUT_mode),         /*0*/
+SOC_ENUM_SINGLE(RT5625_PHONEIN_VOL, 13, 2, rt5625_Differential_Input_Control),/*1*/
+SOC_ENUM_SINGLE(RT5625_MIC_VOL, 15, 2, rt5625_Differential_Input_Control),        /*2*/
+SOC_ENUM_SINGLE(RT5625_MIC_VOL, 7, 2, rt5625_Differential_Input_Control),         /*3*/
+};
 
-               /*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 const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -3525, 75, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dmic_bst_tlv, 0, 600, 0);
+/* {0, +20, +30, +40} dB */
+static unsigned int mic_bst_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+       1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
 };
 
+#ifdef RT5625_REG_RW
+#define REGVAL_MAX 0xffff
+static unsigned int regctl_addr = 0x3e;
+static int rt5625_regctl_info(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = REGVAL_MAX;
+       return 0;
+}
 
-static int rt5625_add_widgets(struct snd_soc_codec *codec)
+static int rt5625_regctl_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
 {
-       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);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] = regctl_addr;
+       ucontrol->value.integer.value[1] = snd_soc_read(codec, regctl_addr);
+       return 0;
+}
 
+static int rt5625_regctl_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       regctl_addr = ucontrol->value.integer.value[0];
+       if(ucontrol->value.integer.value[1] <= REGVAL_MAX)
+               snd_soc_write(codec, regctl_addr, ucontrol->value.integer.value[1]);
        return 0;
 }
+#endif
 
-struct _pll_div{
-       u32 pll_in;
-       u32 pll_out;
-       u16 regvalue;
+static const struct snd_kcontrol_new rt5625_snd_controls[] = {
+       SOC_DOUBLE_TLV("SPKOUT Playback Volume", RT5625_SPK_OUT_VOL,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
+       SOC_DOUBLE("SPKOUT Playback Switch", RT5625_SPK_OUT_VOL,
+                       RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       SOC_ENUM("SPK Amp Type", rt5625_spk_out_enum),
+       SOC_ENUM("Left SPK Source", rt5625_spkl_src_enum),
+       SOC_ENUM("SPK Amp Ratio", rt5625_spkamp_ratio_enum),
+       //SOC_DOUBLE_TLV("Headphone Playback Volume", RT5625_HP_OUT_VOL,
+       //      RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
+       //SOC_DOUBLE("Headphone Playback Switch", RT5625_HP_OUT_VOL,
+       //              RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       //SOC_ENUM("AUXOUT Mode Control", rt5625_auxout_mode_enum),
+       SOC_DOUBLE_TLV("AUXOUT Playback Volume", RT5625_AUX_OUT_VOL,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
+       SOC_DOUBLE("AUXOUT Playback Switch", RT5625_AUX_OUT_VOL,
+                       RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       SOC_DOUBLE_TLV("PCM Playback Volume", RT5625_DAC_VOL,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 63, 1, dmic_bst_tlv),
+       //SOC_ENUM("Phone Mode Control", rt5625_phone_mode_enum),
+       SOC_SINGLE_TLV("Phone Playback Volume", RT5625_PHONEIN_VOL,
+               RT5625_L_VOL_SFT, 31, 1, in_vol_tlv),
+       //SOC_ENUM("MIC1 Mode Control", rt5625_mic1_mode_enum),
+       SOC_SINGLE_TLV("MIC1 Boost", RT5625_MIC_CTRL,
+               RT5625_MIC1_BST_SFT, 3, 0, mic_bst_tlv),
+       SOC_SINGLE_TLV("Mic1 Playback Volume", RT5625_MIC_VOL,
+               RT5625_L_VOL_SFT, 31, 1, in_vol_tlv),
+       //SOC_ENUM("MIC2 Mode Control", rt5625_mic2_mode_enum),
+       SOC_SINGLE_TLV("MIC2 Boost", RT5625_MIC_CTRL,
+               RT5625_MIC2_BST_SFT, 3, 0, mic_bst_tlv),
+       SOC_SINGLE_TLV("Mic2 Playback Volume", RT5625_MIC_VOL,
+               RT5625_R_VOL_SFT, 31, 1, in_vol_tlv),
+       SOC_SINGLE_TLV("Dmic Boost", RT5625_DMIC_CTRL,
+               RT5625_DIG_BST_SFT, 7, 0, dmic_bst_tlv),
+       SOC_DOUBLE_TLV("LineIn Playback Volume", RT5625_LINE_IN_VOL,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, in_vol_tlv),
+       SOC_DOUBLE_TLV("PCM Capture Volume", RT5625_ADC_REC_GAIN,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 0, adc_vol_tlv),
+       //SOC_DOUBLE_TLV("ADC Record Gain", RT5625_ADC_REC_GAIN,
+       //      RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 0, adc_vol_tlv),
+       /* This item does'nt affect path connected; only for clock choosen */
+       SOC_ENUM_EXT("ADCR fun select Control", adcr_fun_sel_enum,
+               snd_soc_get_enum_double, rt5625_adcr_fun_sel_put),
+       SOC_ENUM_EXT("ADCL fun select Control", adcl_fun_sel_enum,
+               snd_soc_get_enum_double, rt5625_adcl_fun_sel_put),
+
+       /* Voice DSP */
+       SOC_ENUM_EXT("VoDSP AEC", rt5625_aec_fun_enum,
+               rt5625_aec_get, rt5625_aec_put),
+       SOC_ENUM("VoDSP LRCK Control",  rt5625_dsp_lrck_enum),
+       SOC_ENUM("VoDSP BP Pin Control",  rt5625_bp_ctrl_enum),
+       SOC_ENUM("VoDSP Power Down Pin Control",  rt5625_pd_ctrl_enum),
+       SOC_ENUM("VoDSP Reset Pin Control",  rt5625_rst_ctrl_enum),
+
+#ifdef RT5625_F_SMT_PHO
+       SOC_SINGLE_EXT("VoDSP Dump", 0, 0, 1, 0, rt5625_dump_dsp_get, NULL),
+       SOC_SINGLE_EXT("DAC Switch", 0, 0, 1, 0, rt5625_dac_active_get, rt5625_dac_active_put),
+       SOC_SINGLE_EXT("ADC Switch", 0, 0, 1, 0, rt5625_adc_active_get, rt5625_adc_active_put),
+       SOC_ENUM_EXT("PLL Switch", rt5625_pll_sel_enum, rt5625_pll_get, rt5625_pll_put),
+       SOC_ENUM_EXT("PLL2 Switch", rt5625_pll2_sel_enum, rt5625_pll2_get, rt5625_pll2_put),
+       SOC_SINGLE_EXT("VoIP Check", 0, 0, 1, 0, rt5625_voip_get, rt5625_voip_chk_put),
+       SOC_SINGLE_EXT("VoIP Switch", 0, 0, 1, 0, rt5625_voip_get, rt5625_voip_put),
+       SOC_SINGLE_EXT("Capture VoIP Check", 0, 0, 1, 0, rt5625_voip_get, rt5625_cap_voip_chk_put),
+       SOC_SINGLE_EXT("Capture VoIP Switch", 0, 0, 1, 0, rt5625_voip_get, rt5625_cap_voip_put),
+       SOC_SINGLE_EXT("Headset VoIP Check", 0, 0, 1, 0, rt5625_voip_get, rt5625_hs_voip_chk_put),
+       SOC_SINGLE_EXT("Headset VoIP Switch", 0, 0, 1, 0, rt5625_voip_get, rt5625_hs_voip_put),
+       SOC_SINGLE_EXT("Playback Switch", 0, 0, 1, 0, rt5625_play_get, rt5625_play_put),
+       SOC_SINGLE_EXT("Record Switch", 0, 0, 1, 0, rt5625_rec_get, rt5625_rec_put),
+       SOC_SINGLE_EXT("BT Switch", 0, 0, 1, 0, rt5625_bt_get, rt5625_bt_put),
+       SOC_SINGLE_EXT("3G Switch", 0, 0, 1, 0, rt5625_3g_get, rt5625_3g_put),
+       SOC_SINGLE_EXT("Headset 3G Switch", 0, 0, 1, 0, rt5625_3g_get, rt5625_hs_3g_put),
+       SOC_SINGLE_EXT("APP disp", 0, 0, 1, 0, rt5625_app_get, NULL),
+#endif
+       //SOC_DOUBLE_TLV("SPKOUT Playback Volume", RT5625_SPK_OUT_VOL,
+       //      RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
+       //SOC_DOUBLE("SPKOUT Playback Switch", RT5625_SPK_OUT_VOL,
+       //              RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       SOC_DOUBLE_TLV("HPOUT Playback Volume", RT5625_HP_OUT_VOL,
+               RT5625_L_VOL_SFT, RT5625_R_VOL_SFT, 31, 1, out_vol_tlv),
+       SOC_DOUBLE("HPOUT Playback Switch", RT5625_HP_OUT_VOL,
+                       RT5625_L_MUTE_SFT, RT5625_R_MUTE_SFT, 1, 1),
+       SOC_ENUM("AUXOUT mode switch", rt5625_differential_enum[0]),
+       SOC_ENUM("Phone Differential Input Control", rt5625_differential_enum[1]),
+       SOC_ENUM("MIC1 Differential Input Control", rt5625_differential_enum[2]),
+       SOC_ENUM("MIC2 Differential Input Control", rt5625_differential_enum[3]),
+
+#ifdef RT5625_REG_RW
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Register Control",
+               .info = rt5625_regctl_info,
+               .get = rt5625_regctl_get,
+               .put = rt5625_regctl_put,
+       },
+#endif
 };
 
 
-/**************************************************************
-  *    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},
-       {  11289600,  24576000,  0x950F},
-       {  12000000,  24576000,  0x2915},
-       {  12288000,  24576000,  0x0600},
-       {  13000000,  24576000,  0x772e},
-       {  13100000,  24576000,  0x0d20},
-       {  26000000,  24576000,  0x2027},
-       {  26000000,  22579200,  0x392f},
-       {  24576000,  22579200,  0x0921},
-       {  24576000,  24576000,  0x02a0},
+ /*Left ADC Rec mixer*/
+static const struct snd_kcontrol_new rt5625_adcl_rec_mixer[] = {
+       SOC_DAPM_SINGLE("Mic1 Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_MIC1_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Mic2 Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_MIC2_SFT, 1, 1),
+       SOC_DAPM_SINGLE("LineIn Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_LINE_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Phone Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_PHO_SFT, 1, 1),
+       SOC_DAPM_SINGLE("HP Mixer Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_HM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("SPK Mixer Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_SM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("MoNo Mixer Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_L_MM_SFT, 1, 1),
 };
 
-static const struct _pll_div codec_bclk_pll1_div[] = {
+/*Right ADC Rec mixer*/
+static const struct snd_kcontrol_new rt5625_adcr_rec_mixer[] = {
+       SOC_DAPM_SINGLE("Mic1 Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_R_MIC1_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Mic2 Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_R_MIC2_SFT, 1, 1),
+       SOC_DAPM_SINGLE("LineIn Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_R_LINE_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Phone Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_R_PHO_SFT, 1, 1),
+       SOC_DAPM_SINGLE("HP Mixer Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_R_HM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("SPK Mixer Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_R_SM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("MoNo Mixer Capture Switch", RT5625_ADC_REC_MIXER,
+                               RT5625_M_RM_R_MM_SFT, 1, 1),
+};
 
-       {   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},                        
+/* HP Mixer for mono input */
+static const struct snd_kcontrol_new rt5625_hp_mixer[] = {
+       SOC_DAPM_SINGLE("LineIn Playback Switch", RT5625_LINE_IN_VOL,
+                               RT5625_M_LI_HM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Phone Playback Switch", RT5625_PHONEIN_VOL,
+                               RT5625_M_PHO_HM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Mic1 Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_MIC1_HM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_MIC2_HM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Voice DAC Playback Switch", RT5625_VDAC_OUT_VOL,
+                               RT5625_M_VDAC_HM_SFT, 1, 1),
 };
 
-static const struct _pll_div codec_vbclk_pll1_div[] = {
+/* Left HP Mixer */
+static const struct snd_kcontrol_new rt5625_hpl_mixer[] = {
+       SOC_DAPM_SINGLE("ADC Playback Switch", RT5625_ADC_REC_GAIN,
+                               RT5625_M_ADCL_HM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("DAC Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_DACL_HM_SFT, 1, 1),
+};
 
-       {   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},
+/* Right HP Mixer */
+static const struct snd_kcontrol_new rt5625_hpr_mixer[] = {
+       SOC_DAPM_SINGLE("ADC Playback Switch", RT5625_ADC_REC_GAIN,
+                               RT5625_M_ADCR_HM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("DAC Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_DACR_HM_SFT, 1, 1),
 };
 
+/* Mono Mixer */
+static const struct snd_kcontrol_new rt5625_mono_mixer[] = {
+       SOC_DAPM_SINGLE("ADCL Playback Switch", RT5625_ADC_REC_GAIN,
+                               RT5625_M_ADCL_MM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("ADCR Playback Switch", RT5625_ADC_REC_GAIN,
+                               RT5625_M_ADCR_MM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Line Mixer Playback Switch", RT5625_LINE_IN_VOL,
+                               RT5625_M_LI_MM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Mic1 Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_MIC1_MM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_MIC2_MM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("DAC Mixer Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_DAC_MM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Voice DAC Playback Switch", RT5625_VDAC_OUT_VOL,
+                               RT5625_M_VDAC_MM_SFT, 1, 1),
+};
 
-struct _coeff_div_stereo {
-       unsigned int mclk;
-       unsigned int rate;
-       unsigned int reg60;
-       unsigned int reg62;
+/* Speaker Mixer */
+static const struct snd_kcontrol_new rt5625_spk_mixer[] = {
+       SOC_DAPM_SINGLE("Line Mixer Playback Switch", RT5625_LINE_IN_VOL,
+                               RT5625_M_LI_SM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Phone Playback Switch", RT5625_PHONEIN_VOL,
+                               RT5625_M_PHO_SM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Mic1 Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_MIC1_SM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Mic2 Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_MIC2_SM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("DAC Mixer Playback Switch", RT5625_DAC_MIC_CTRL,
+                               RT5625_M_DAC_SM_SFT, 1, 1),
+       SOC_DAPM_SINGLE("Voice DAC Playback Switch", RT5625_VDAC_OUT_VOL,
+                               RT5625_M_VDAC_SM_SFT, 1, 1),
 };
 
-struct _coeff_div_voice {
-       unsigned int mclk;
+static int rt5625_dac_func_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_REG:
+               snd_soc_update_bits(codec, RT5625_PD_CTRL,
+                       RT5625_PWR_PR1, RT5625_PWR_PR1);
+               break;
+
+       case SND_SOC_DAPM_POST_REG:
+               snd_soc_update_bits(codec, RT5625_PD_CTRL,
+                       RT5625_PWR_PR1, 0);
+               break;
+
+       default:
+               return 0;
+       }       
+
+       return 0;
+}
+
+static int rt5625_hpmix_event(struct snd_soc_dapm_widget *w,
+               struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMD:
+               snd_soc_update_bits(codec, RT5625_PWR_ADD2,
+                       RT5625_P_HM_L | RT5625_P_HM_R, 0);
+               break;
+
+       case SND_SOC_DAPM_POST_PMU:
+               snd_soc_update_bits(codec, RT5625_PWR_ADD2,
+                       RT5625_P_HM_L | RT5625_P_HM_R,
+                       RT5625_P_HM_L | RT5625_P_HM_R);
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
+static int rt5625_vodsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMD:
+               //pr_info("%s(): PMD\n", __func__);
+               snd_soc_update_bits(codec, RT5625_VODSP_CTL,
+                       RT5625_DSP_PD_MASK, RT5625_DSP_PD_EN);
+               snd_soc_update_bits(codec, RT5625_PWR_ADD3,
+                       RT5625_P_DSP_IF | RT5625_P_DSP_I2C, 0);
+               snd_soc_update_bits(codec, RT5625_LDO_CTRL,
+                       RT5625_LDO_MASK, RT5625_LDO_DIS);
+               break;
+
+       case SND_SOC_DAPM_POST_PMU:
+               //pr_info("%s(): PMU\n", __func__);
+               if(rt5625->vodsp_fun == RT5625_AEC_EN)
+                       rt5625_init_vodsp_aec(codec);
+               //pr_info("[DSP poweron] 0x%04x: 0x%04x\n", 0x230C, rt5625_dsp_read(codec, 0x230C));
+               break;
+
+       default:
+               return 0;
+       }       
+
+       return 0;
+}
+
+
+static void hp_depop_mode2(struct snd_soc_codec *codec)
+{
+       snd_soc_update_bits(codec, RT5625_PWR_ADD1,
+               RT5625_P_SG_EN, RT5625_P_SG_EN);
+       snd_soc_update_bits(codec, RT5625_PWR_ADD3,
+               RT5625_P_HPL_VOL | RT5625_P_HPR_VOL,
+               RT5625_P_HPL_VOL | RT5625_P_HPR_VOL);
+       snd_soc_write(codec, RT5625_MISC_CTRL, RT5625_HP_DEPOP_M2);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(500));
+       snd_soc_update_bits(codec, RT5625_PWR_ADD1,
+               RT5625_P_HPO_AMP | RT5625_P_HPO_ENH,
+               RT5625_P_HPO_AMP | RT5625_P_HPO_ENH);
+}
+
+/* enable depop function for mute/unmute */
+static void hp_mute_unmute_depop(struct snd_soc_codec *codec,int mute)
+{
+       if(mute) {
+               snd_soc_update_bits(codec, RT5625_PWR_ADD1,
+                       RT5625_P_SG_EN, RT5625_P_SG_EN);
+               snd_soc_write(codec, RT5625_MISC_CTRL, RT5625_MUM_DEPOP |
+                       RT5625_HPR_MUM_DEPOP | RT5625_HPL_MUM_DEPOP);
+               snd_soc_update_bits(codec, RT5625_HP_OUT_VOL,
+                       RT5625_L_MUTE | RT5625_R_MUTE,
+                       RT5625_L_MUTE | RT5625_R_MUTE);
+               mdelay(50);
+               snd_soc_update_bits(codec, RT5625_PWR_ADD1, RT5625_P_SG_EN, 0);
+       } else {
+               snd_soc_update_bits(codec, RT5625_PWR_ADD1,
+                       RT5625_P_SG_EN, RT5625_P_SG_EN);
+               snd_soc_write(codec, RT5625_MISC_CTRL, RT5625_MUM_DEPOP |
+                       RT5625_HPR_MUM_DEPOP | RT5625_HPL_MUM_DEPOP);
+               snd_soc_update_bits(codec,RT5625_HP_OUT_VOL,
+                       RT5625_L_MUTE | RT5625_R_MUTE, 0);
+               mdelay(50);
+       }
+}
+
+static int rt5625_hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMD:
+               hp_mute_unmute_depop(codec,1);
+               snd_soc_update_bits(codec, RT5625_PWR_ADD1,
+                       RT5625_P_HPO_AMP | RT5625_P_HPO_ENH, 0);
+               snd_soc_update_bits(codec, RT5625_PWR_ADD3,
+                       RT5625_P_HPL_VOL | RT5625_P_HPR_VOL, 0);
+               break;
+
+       case SND_SOC_DAPM_POST_PMU:
+               hp_depop_mode2(codec);
+               hp_mute_unmute_depop(codec,0);
+               break;
+
+       default:
+               return 0;
+       }       
+
+       return 0;
+}
+
+/* DAC function select MUX */
+static const char *dac_fun_sel[] = {
+       "Stereo DAC", "SRC2 Out", "TxDP", "TxDC"};
+
+static const struct soc_enum dac_fun_sel_enum =
+       SOC_ENUM_SINGLE(RT5625_F_DAC_ADC_VDAC, RT5625_DAC_F_SFT,
+                               ARRAY_SIZE(dac_fun_sel), dac_fun_sel);
+
+static const struct snd_kcontrol_new dac_fun_sel_mux =
+       SOC_DAPM_ENUM("DAC Function Select Mux", dac_fun_sel_enum);
+
+/* Voice DAC source select MUX */
+static const char *vdac_src_sel[] = {
+       "Voice PCM", "SRC2 Out", "TxDP", "TxDC"};
+
+static const struct soc_enum vdac_src_sel_enum =
+       SOC_ENUM_SINGLE(RT5625_F_DAC_ADC_VDAC, RT5625_VDAC_S_SFT,
+                               ARRAY_SIZE(vdac_src_sel), vdac_src_sel);
+
+static const struct snd_kcontrol_new vdac_src_sel_mux =
+       SOC_DAPM_ENUM("Voice DAC Source Mux", vdac_src_sel_enum);
+
+/* SRC1 power switch */
+static const struct snd_kcontrol_new src1_pwr_sw_control =
+       SOC_DAPM_SINGLE("Switch", RT5625_VODSP_PDM_CTL,
+                               RT5625_SRC1_PWR_SFT, 1, 0);
+
+/* SRC2 power switch */
+static const struct snd_kcontrol_new src2_pwr_sw_control =
+       SOC_DAPM_SINGLE("Switch", RT5625_VODSP_PDM_CTL,
+                               RT5625_SRC2_PWR_SFT, 1, 0);
+
+/* SRC2 source select MUX */
+static const char *src2_src_sel[] = {"TxDP", "TxDC"};
+
+static const struct soc_enum src2_src_sel_enum =
+       SOC_ENUM_SINGLE(RT5625_VODSP_PDM_CTL, RT5625_SRC2_S_SFT,
+                       ARRAY_SIZE(src2_src_sel), src2_src_sel);
+
+static const struct snd_kcontrol_new src2_src_sel_mux =
+       SOC_DAPM_ENUM("SRC2 Source Mux", src2_src_sel_enum);
+
+/* VoDSP RxDP power switch */
+static const struct snd_kcontrol_new rxdp_pwr_sw_control =
+       SOC_DAPM_SINGLE("Switch", RT5625_VODSP_PDM_CTL,
+                               RT5625_RXDP_PWR_SFT, 1, 0);
+/* VoDSP RxDC power switch */
+static const struct snd_kcontrol_new rxdc_pwr_sw_control =
+       SOC_DAPM_SINGLE("Switch", RT5625_VODSP_PDM_CTL,
+                               RT5625_RXDC_PWR_SFT, 1, 0);
+
+/* VoDSP RxDP source select MUX */
+static const char *rxdp_src_sel[] = {"SRC1 Output", "ADCL to VoDSP",
+                       "Voice to Stereo", "ADCR to VoDSP"};
+
+static const struct soc_enum rxdp_src_sel_enum =
+       SOC_ENUM_SINGLE(RT5625_VODSP_PDM_CTL, RT5625_RXDP_S_SFT,
+                       ARRAY_SIZE(rxdp_src_sel), rxdp_src_sel);
+
+static const struct snd_kcontrol_new rxdp_src_sel_mux =
+       SOC_DAPM_ENUM("RxDP Source Mux", rxdp_src_sel_enum);
+
+/* PCM source select MUX */
+static const char *pcm_src_sel[] = {"ADCR", "TxDP"};
+
+static const struct soc_enum pcm_src_sel_enum =
+       SOC_ENUM_SINGLE(RT5625_VODSP_PDM_CTL, RT5625_PCM_S_SFT,
+                       ARRAY_SIZE(pcm_src_sel), pcm_src_sel);
+
+static const struct snd_kcontrol_new pcm_src_sel_mux =
+       SOC_DAPM_ENUM("PCM Source Mux", pcm_src_sel_enum);
+
+/* Main stereo record I2S source select MUX */
+static const char *rec_iis_src_sel[] = {"ADC", "Voice to Stereo", "SRC2 Output"};
+
+static const struct soc_enum rec_iis_src_enum =
+       SOC_ENUM_SINGLE(RT5625_VODSP_PDM_CTL, RT5625_REC_IIS_S_SFT,
+                       ARRAY_SIZE(rec_iis_src_sel), rec_iis_src_sel);
+
+static const struct snd_kcontrol_new rec_iis_src_mux =
+       SOC_DAPM_ENUM("REC I2S Source Mux", rec_iis_src_enum);
+
+/* SPK volume input select MUX */
+static const char *spkvol_input_sel[] = {"VMID", "HP Mixer", "SPK Mixer", "Mono Mixer"};
+
+static const struct soc_enum spkvol_input_enum =
+       SOC_ENUM_SINGLE(RT5625_OUTMIX_CTRL, RT5625_SPKVOL_S_SFT,
+                       ARRAY_SIZE(spkvol_input_sel), spkvol_input_sel);
+
+static const struct snd_kcontrol_new spkvol_input_mux =
+       SOC_DAPM_ENUM("SPK Vol Input Mux", spkvol_input_enum);
+
+/* HP volume input select MUX */
+static const char *hpvol_input_sel[] = {"VMID", "HP Mixer"};
+
+static const struct soc_enum hplvol_input_enum =
+       SOC_ENUM_SINGLE(RT5625_OUTMIX_CTRL, RT5625_HPVOL_L_S_SFT,
+                       ARRAY_SIZE(hpvol_input_sel), hpvol_input_sel);
+
+static const struct snd_kcontrol_new hplvol_input_mux =
+       SOC_DAPM_ENUM("HPL Vol Input Mux", hplvol_input_enum);
+
+static const struct soc_enum hprvol_input_enum =
+       SOC_ENUM_SINGLE(RT5625_OUTMIX_CTRL, RT5625_HPVOL_R_S_SFT,
+                       ARRAY_SIZE(hpvol_input_sel), hpvol_input_sel);
+
+static const struct snd_kcontrol_new hprvol_input_mux =
+       SOC_DAPM_ENUM("HPR Vol Input Mux", hprvol_input_enum);
+
+/* AUX volume input select MUX */
+static const struct soc_enum auxvol_input_enum =
+       SOC_ENUM_SINGLE(RT5625_OUTMIX_CTRL, RT5625_AUXVOL_S_SFT,
+                       ARRAY_SIZE(spkvol_input_sel), spkvol_input_sel);
+
+static const struct snd_kcontrol_new auxvol_input_mux =
+       SOC_DAPM_ENUM("AUX Vol Input Mux", auxvol_input_enum);
+
+static const struct snd_soc_dapm_widget rt5625_dapm_widgets[] = {
+       /* supply */
+       SND_SOC_DAPM_SUPPLY("IIS Interface", RT5625_PWR_ADD1,
+                               RT5625_P_I2S_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("PLL1", RT5625_PWR_ADD2,
+                               RT5625_P_PLL1_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("PLL2", RT5625_PWR_ADD2,
+                               RT5625_P_PLL2_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_VMID("VMID"),
+       SND_SOC_DAPM_SUPPLY("DAC Ref", RT5625_PWR_ADD1,
+                               RT5625_P_DAC_REF_BIT, 0, NULL, 0),
+       /* microphone bias */
+       SND_SOC_DAPM_MICBIAS("Mic1 Bias", RT5625_PWR_ADD1,
+                                       RT5625_P_MB1_BIT, 0),
+       SND_SOC_DAPM_MICBIAS("Mic2 Bias", RT5625_PWR_ADD1,
+                                       RT5625_P_MB2_BIT, 0),
+
+       /* Input */
+       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_ADD3,
+                       RT5625_P_MIC1_BST_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Mic2 Boost", RT5625_PWR_ADD3,
+                       RT5625_P_MIC2_BST_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Phone Rec Mixer", RT5625_PWR_ADD3,
+                       RT5625_P_PH_ADMIX_BIT, 0, NULL, 0),
+
+       SND_SOC_DAPM_MIXER("Left Rec Mixer", RT5625_PWR_ADD2,
+               RT5625_P_ADCL_RM_BIT, 0, rt5625_adcl_rec_mixer,
+               ARRAY_SIZE(rt5625_adcl_rec_mixer)),
+       SND_SOC_DAPM_MIXER("Right Rec Mixer", RT5625_PWR_ADD2,
+               RT5625_P_ADCR_RM_BIT, 0, rt5625_adcr_rec_mixer,
+               ARRAY_SIZE(rt5625_adcr_rec_mixer)),
+
+       SND_SOC_DAPM_ADC("Left ADC", NULL, RT5625_PWR_ADD2,
+                                       RT5625_P_ADCL_BIT, 0),
+       SND_SOC_DAPM_ADC("Right ADC", NULL, RT5625_PWR_ADD2,
+                                       RT5625_P_ADCR_BIT, 0),
+       SND_SOC_DAPM_MUX("PCM src select Mux", SND_SOC_NOPM, 0, 0,
+                               &pcm_src_sel_mux),
+       SND_SOC_DAPM_MUX("IIS src select Mux", SND_SOC_NOPM, 0, 0,
+                               &rec_iis_src_mux),
+
+       /* Input Stream Audio Interface */
+       SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Voice Capture", 0, SND_SOC_NOPM, 0, 0),
+
+       /* Voice DSP */
+       SND_SOC_DAPM_MUX("SRC2 src select Mux", SND_SOC_NOPM, 0, 0,
+                               &src2_src_sel_mux),
+       SND_SOC_DAPM_SWITCH("SRC1 Enable", SND_SOC_NOPM, 0, 0,
+                               &src1_pwr_sw_control),
+       SND_SOC_DAPM_SWITCH("SRC2 Enable", SND_SOC_NOPM, 0, 0,
+                               &src2_pwr_sw_control),
+       SND_SOC_DAPM_SWITCH("RxDP Enable", SND_SOC_NOPM, 0, 0,
+                               &rxdp_pwr_sw_control),
+       SND_SOC_DAPM_SWITCH("RxDC Enable", SND_SOC_NOPM, 0, 0,
+                               &rxdc_pwr_sw_control),
+
+       SND_SOC_DAPM_MUX("RxDP src select Mux", SND_SOC_NOPM, 0, 0,
+                               &rxdp_src_sel_mux),
+
+       SND_SOC_DAPM_PGA("TxDP", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("TxDC", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("PDM", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("RxDP", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("RxDC", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_E("Voice DSP", SND_SOC_NOPM,
+               0, 0, NULL, 0, rt5625_vodsp_event,
+               SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+       /* Output */
+       /* Output Stream Audio Interface */
+       SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 HiFi Playback",
+                               0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Voice Playback",
+                               0, SND_SOC_NOPM, 0, 0),
+
+       /* DAC function select Mux */
+       SND_SOC_DAPM_MUX_E("DAC fun Mux", SND_SOC_NOPM, 0, 0,
+               &dac_fun_sel_mux, rt5625_dac_func_event,
+               SND_SOC_DAPM_PRE_REG | SND_SOC_DAPM_POST_REG),
+       /* VDAC source select Mux */
+       SND_SOC_DAPM_MUX_E("VDAC src Mux", SND_SOC_NOPM, 0, 0,
+               &vdac_src_sel_mux, rt5625_dac_func_event,
+               SND_SOC_DAPM_PRE_REG | SND_SOC_DAPM_POST_REG),
+
+       SND_SOC_DAPM_DAC("Left DAC", NULL, RT5625_PWR_ADD2,
+                                       RT5625_P_DACL_BIT, 0),
+       SND_SOC_DAPM_DAC("Right DAC", NULL, RT5625_PWR_ADD2,
+                                       RT5625_P_DACR_BIT, 0),
+       SND_SOC_DAPM_DAC("Voice DAC", NULL, RT5625_PWR_ADD2,
+                                       RT5625_P_VDAC_BIT, 0),
+
+       SND_SOC_DAPM_PGA("Mic1 Volume", RT5625_PWR_ADD3,
+                               RT5625_P_MIC1_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Mic2 Volume", RT5625_PWR_ADD3,
+                               RT5625_P_MIC2_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Left LineIn Volume", RT5625_PWR_ADD3,
+                               RT5625_P_LV_L_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Right LineIn Volume", RT5625_PWR_ADD3,
+                               RT5625_P_LV_R_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Phone Volume", RT5625_PWR_ADD3,
+                               RT5625_P_PH_VOL_BIT, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("Left DAC To Mixer", RT5625_PWR_ADD1,
+                               RT5625_P_DACL_MIX_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Right DAC To Mixer", RT5625_PWR_ADD1,
+                               RT5625_P_DACR_MIX_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Voice DAC To Mixer", RT5625_PWR_ADD1,
+                               RT5625_P_VDAC_MIX_BIT, 0, NULL, 0),
+
+       SND_SOC_DAPM_MIXER("SPK Mixer", RT5625_PWR_ADD2,
+               RT5625_P_SM_BIT, 0, rt5625_spk_mixer,
+               ARRAY_SIZE(rt5625_spk_mixer)),  
+       SND_SOC_DAPM_MIXER("Mono HP Mixer", SND_SOC_NOPM, 0, 0,
+               rt5625_hp_mixer, ARRAY_SIZE(rt5625_hp_mixer)),
+       SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
+               rt5625_hpl_mixer, ARRAY_SIZE(rt5625_hpl_mixer)),
+       SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0,
+               rt5625_hpr_mixer, ARRAY_SIZE(rt5625_hpr_mixer)),
+       SND_SOC_DAPM_MIXER("Mono Mixer", RT5625_PWR_ADD2,
+               RT5625_P_MM_BIT, 0, rt5625_mono_mixer,
+               ARRAY_SIZE(rt5625_mono_mixer)),
+
+       SND_SOC_DAPM_MIXER_E("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0,
+               rt5625_hpmix_event, SND_SOC_DAPM_PRE_PMD |
+               SND_SOC_DAPM_POST_PMU),
+
+       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("SPK Vol Input Mux", SND_SOC_NOPM,
+                       0, 0, &spkvol_input_mux),
+       SND_SOC_DAPM_SUPPLY("SPKL Vol", RT5625_PWR_ADD3,
+                       RT5625_P_SPKL_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("SPKR Vol", RT5625_PWR_ADD3,
+                       RT5625_P_SPKR_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_MUX("HPL Vol Input Mux", RT5625_PWR_ADD3,
+                       RT5625_P_HPL_VOL_BIT, 0, &hplvol_input_mux),
+       SND_SOC_DAPM_MUX("HPR Vol Input Mux", RT5625_PWR_ADD3,
+                       RT5625_P_HPR_VOL_BIT, 0, &hprvol_input_mux),
+       SND_SOC_DAPM_MUX("AUX Vol Input Mux", RT5625_PWR_ADD3,
+                       RT5625_P_AUX_VOL_BIT, 0, &auxvol_input_mux),
+
+       SND_SOC_DAPM_SUPPLY("SPK Amp", RT5625_PWR_ADD1,
+                               RT5625_P_SPK_AMP_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_E("HP Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
+               rt5625_hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+                               
+       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"),
+};
+
+static const struct snd_soc_dapm_route rt5625_dapm_routes[] = {
+       {"DAC Ref", NULL, "IIS Interface"},
+       {"DAC Ref", NULL, "PLL1"},
+       {"DAC Ref", NULL, "PLL2"},
+
+       /* Input */
+       {"Phone Rec Mixer", NULL, "Phone"},
+       {"Mic1 Boost", NULL, "Mic1"},
+       {"Mic2 Boost", NULL, "Mic2"},
+
+       {"Left Rec Mixer", "LineIn Capture Switch", "Left LineIn"},
+       {"Left Rec Mixer", "Phone Capture Switch", "Phone Rec Mixer"},
+       {"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 Rec Mixer", "LineIn Capture Switch", "Right LineIn"},
+       {"Right Rec Mixer", "Phone Capture Switch", "Phone Rec Mixer"},
+       {"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"},
+
+       {"Left ADC", NULL, "DAC Ref"},
+       {"Left ADC", NULL, "Left Rec Mixer"},
+       {"Right ADC", NULL, "DAC Ref"},
+       {"Right ADC", NULL, "Right Rec Mixer"},
+
+       {"PCM src select Mux", "TxDP", "TxDP"},
+       {"PCM src select Mux", "ADCR", "Right ADC"},
+
+       {"IIS src select Mux", "ADC", "Left ADC"},
+       {"IIS src select Mux", "ADC", "Right ADC"},
+       {"IIS src select Mux", "Voice to Stereo", "AIF2RX"},
+       {"IIS src select Mux", "SRC2 Output", "SRC2 Enable"},
+
+       {"AIF2TX", NULL, "IIS Interface"},
+       {"AIF2TX", NULL, "PCM src select Mux"},
+       {"AIF1TX", NULL, "IIS Interface"},
+       {"AIF1TX", NULL, "IIS src select Mux"},
+
+       /* Output */
+       {"AIF1RX", NULL, "IIS Interface"},
+       {"AIF2RX", NULL, "IIS Interface"},
+
+       {"DAC fun Mux", "SRC2 Out", "SRC2 Enable"},
+       {"DAC fun Mux", "TxDP", "TxDP"},
+       {"DAC fun Mux", "TxDC", "TxDC"},
+       {"DAC fun Mux", "Stereo DAC", "AIF1RX"},
+
+       {"VDAC src Mux", "SRC2 Out", "SRC2 Enable"},
+       {"VDAC src Mux", "TxDP", "TxDP"},
+       {"VDAC src Mux", "TxDC", "TxDC"},
+       {"VDAC src Mux", "Voice PCM", "AIF2RX"},
+
+       {"Left DAC", NULL, "DAC Ref"},
+       {"Left DAC", NULL, "DAC fun Mux"},
+       {"Right DAC", NULL, "DAC Ref"},
+       {"Right DAC", NULL, "DAC fun Mux"},
+       {"Voice DAC", NULL, "DAC Ref"},
+       {"Voice DAC", NULL, "VDAC src Mux"},
+
+       {"Left LineIn Volume", NULL, "Left LineIn"},
+       {"Right LineIn Volume", NULL, "Right LineIn"},
+       {"Phone Volume", NULL, "Phone"},
+       {"Mic1 Volume", NULL, "Mic1 Boost"},
+       {"Mic2 Volume", NULL, "Mic2 Boost"},
+
+       {"Left DAC To Mixer", NULL, "Left DAC"},
+       {"Right DAC To Mixer", NULL, "Right DAC"},
+       {"Voice DAC To Mixer", NULL, "Voice DAC"},
+
+       {"DAC Mixer", NULL, "Left DAC To Mixer"},
+       {"DAC Mixer", NULL, "Right DAC To Mixer"},
+       {"Line Mixer", NULL, "Left LineIn Volume"},
+       {"Line Mixer", NULL, "Right LineIn Volume"},
+
+       {"Mono HP Mixer", "LineIn Playback Switch", "Line Mixer"},
+       {"Mono HP Mixer", "Phone Playback Switch", "Phone Volume"},
+       {"Mono HP Mixer", "Mic1 Playback Switch", "Mic1 Volume"},
+       {"Mono HP Mixer", "Mic2 Playback Switch", "Mic2 Volume"},
+       {"Mono HP Mixer", "Voice DAC Playback Switch", "Voice DAC To Mixer"},
+       {"Left HP Mixer", "ADC Playback Switch", "Left Rec Mixer"},
+       {"Left HP Mixer", "DAC Playback Switch", "Left DAC To Mixer"},
+       {"Right HP Mixer", "ADC Playback Switch", "Right Rec Mixer"},
+       {"Right HP Mixer", "DAC Playback Switch", "Right DAC To Mixer"},
+
+       {"SPK Mixer", "Line Mixer Playback Switch", "Line Mixer"},
+       {"SPK Mixer", "Phone Playback Switch", "Phone Volume"},
+       {"SPK Mixer", "Mic1 Playback Switch", "Mic1 Volume"},
+       {"SPK Mixer", "Mic2 Playback Switch", "Mic2 Volume"},
+       {"SPK Mixer", "DAC Mixer Playback Switch", "DAC Mixer"},
+       {"SPK Mixer", "Voice DAC Playback Switch", "Voice DAC To 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 Volume"},
+       {"Mono Mixer", "Mic2 Playback Switch", "Mic2 Volume"},
+       {"Mono Mixer", "DAC Mixer Playback Switch", "DAC Mixer"},
+       {"Mono Mixer", "Voice DAC Playback Switch", "Voice DAC To Mixer"},
+
+       {"HP Mixer", NULL, "Mono HP Mixer"},
+       {"HP Mixer", NULL, "Left HP Mixer"},
+       {"HP Mixer", NULL, "Right HP Mixer"},
+
+       {"SPK Vol Input Mux", "VMID", "VMID"},
+       {"SPK Vol Input Mux", "HP Mixer", "HP Mixer"},
+       {"SPK Vol Input Mux", "SPK Mixer", "SPK Mixer"},
+       {"SPK Vol Input Mux", "Mono Mixer", "Mono Mixer"},
+       {"SPK Vol Input Mux", NULL, "SPKL Vol"},
+       {"SPK Vol Input Mux", NULL, "SPKR Vol"},
+       
+       {"HPL Vol Input Mux", "HP Mixer", "HP Mixer"},
+       {"HPL Vol Input Mux", "VMID", "VMID"},
+       {"HP Amp", NULL, "HPL Vol Input Mux"},
+       {"HPR Vol Input Mux", "HP Mixer", "HP Mixer"},
+       {"HPR Vol Input Mux", "VMID", "VMID"},
+       {"HP Amp", NULL, "HPR Vol Input Mux"},
+
+       {"AUX Vol Input Mux", "VMID", "VMID"},
+       {"AUX Vol Input Mux", "HP Mixer", "HP Mixer"},
+       {"AUX Vol Input Mux", "SPK Mixer", "SPK Mixer"},
+       {"AUX Vol Input Mux", "Mono Mixer", "Mono Mixer"},
+
+       {"SPKL", NULL, "SPK Amp"},
+       {"SPKL", NULL, "SPK Vol Input Mux"},
+       {"SPKR", NULL, "SPK Amp"},
+       {"SPKR", NULL, "SPK Vol Input Mux"},
+       {"HPL", NULL, "HP Amp"},
+       {"HPR", NULL, "HP Amp"},
+       {"AUX", NULL, "AUX Vol Input Mux"},
+
+       /* Voice DSP */
+       {"SRC1 Enable", "Switch", "AIF1RX"},
+
+       {"RxDP src select Mux", "Voice to Stereo", "AIF2RX"},
+       {"RxDP src select Mux", "ADCL to VoDSP", "Left ADC"},
+       {"RxDP src select Mux", "SRC1 Output", "SRC1 Enable"},
+       {"RxDP src select Mux", "ADCR to VoDSP", "Right ADC"},
+
+       {"RxDP Enable", "Switch", "RxDP src select Mux"},
+       {"RxDC Enable", "Switch", "Left ADC"},
+
+       {"RxDP", NULL, "RxDP Enable"},
+       {"RxDC", NULL, "RxDC Enable"},
+       {"PDM", NULL, "Right ADC"},
+
+       {"Voice DSP", NULL, "RxDP"},
+       {"Voice DSP", NULL, "RxDC"},
+       {"Voice DSP", NULL, "PDM"},
+
+       {"TxDP", NULL, "Voice DSP"},
+       {"TxDC", NULL, "Voice DSP"},
+
+       {"SRC2 src select Mux", "TxDP", "TxDP"},
+       {"SRC2 src select Mux", "TxDC", "TxDC"},
+       {"SRC2 Enable", "Switch", "SRC2 src select Mux"},
+};
+
+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},
+       { 11289600,  24576000,  0x950F},
+       { 12000000,  24576000,  0x2915},
+       { 12288000,  24576000,  0x0600},
+       { 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;
 };
 
+/* bclk is config to 32fs, if codec is choose to be slave mode,
+input bclk should be 32*fs */
 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},
+       {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},
+       {12288000,  8000, 0xB174, 0x2222},
+       {11289600, 44100, 0X3072, 0x0000},
 };
 
+/* bclk is config to 32fs, if codec is choose to be slave mode,
+input bclk should be 32*fs */
 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},
+       {24576000, 16000, 0x2622}, 
+       {24576000, 8000, 0x2824},
+       {2048000,8000,0x3000},
 };
 
 static int get_coeff(unsigned int mclk, unsigned int rate, int mode)
 {
        int i;
 
-       DBG("get_coeff mclk = %d, rate = %d, mode = %d\n", mclk, rate, mode);
+       pr_info("mclk = %d, rate = %d, mode = %d\n", mclk, rate, mode);
 
-       if (!mode) {
+       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))
+                       if ((coeff_div_stereo[i].rate == rate) &&
+                               (coeff_div_stereo[i].mclk == mclk))
                                return i;
                }
-       } else {
+       else
                for (i = 0; i< ARRAY_SIZE(coeff_div_voice); i++) {
-                       if ((coeff_div_voice[i].rate == rate) && (coeff_div_voice[i].mclk == mclk))
+                       if ((coeff_div_voice[i].rate == rate) &&
+                               (coeff_div_voice[i].mclk == mclk))
                                return i;
                }
-       }
 
-       printk("can't find a matched mclk and rate in %s\n", 
+       pr_err("can't find a matched mclk and rate in %s\n",
               (mode ? "coeff_div_voice[]" : "coeff_div_audio[]"));
 
        return -EINVAL;
 }
 
 
-static int rt5625_codec_set_dai_pll(struct snd_soc_dai *codec_dai, 
-               int pll_id, unsigned int freq_in, unsigned int freq_out)
+static int rt5625_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+                       unsigned int freq_in, unsigned int freq_out)
 {
-       int i;
-       int ret = -EINVAL;
-       struct snd_soc_codec *codec = codec_dai->codec;
-
-       DBG("enter %s pll_id = %d freq_in = %d freq_out = %d\n",
-              __func__, pll_id, freq_in, freq_out);
+       struct snd_soc_codec *codec = dai->codec;
+       int i, ret = -EINVAL;
 
-       if (pll_id < RT5625_PLL1_FROM_MCLK || pll_id > RT5625_PLL1_FROM_VBCLK)
+       if (pll_id < RT5625_PLL_MCLK || pll_id > RT5625_PLL_VBCLK)
                return -EINVAL;
 
-       if (!freq_in || !freq_out)
+       if (!freq_in || !freq_out) {
+               dev_info(dai->dev, "PLL is closed\n");
+               snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                       RT5625_SCLK_MASK, RT5625_SCLK_MCLK);
                return 0;
+       }
 
-       if (RT5625_PLL1_FROM_MCLK == pll_id) {
-
+       if (RT5625_PLL_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)) {
+                               snd_soc_write(codec, RT5625_GEN_CTRL2,
+                                       RT5625_PLL1_S_MCLK);
+                               snd_soc_write(codec, RT5625_PLL_CTRL,
+                                       codec_master_pll1_div[i].regvalue);
+                               snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                                       RT5625_SCLK_MASK, RT5625_SCLK_PLL1);
+                               ret = 0;
+                               break;
+                       }
+       } else if (RT5625_PLL_MCLK_TO_VSYSCLK == 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);
+                               snd_soc_write(codec, RT5625_GEN_CTRL2, 0x0000);  /*PLL source from MCLK*/
+                               snd_soc_write(codec, RT5625_PLL_CTRL, codec_master_pll1_div[i].regvalue);  /*set pll code*/
+                               snd_soc_update_bits(codec, RT5625_GEN_CTRL1, 0x0030, 0x0030);  /* Voice SYSCLK source from FLL1 */
                                ret = 0;
                        }
                }
-       } else if (RT5625_PLL1_FROM_BCLK == pll_id) {
-
+       }else if (RT5625_PLL_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);
+                       if ((freq_in == codec_bclk_pll1_div[i].pll_in) &&
+                               (freq_out == codec_bclk_pll1_div[i].pll_out)) {
+                               snd_soc_write(codec, RT5625_GEN_CTRL2,
+                                       RT5625_PLL1_S_BCLK);
+                               snd_soc_write(codec, RT5625_PLL_CTRL,
+                                       codec_bclk_pll1_div[i].regvalue);
+                               snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                                       RT5625_SCLK_MASK, RT5625_SCLK_PLL1);
                                ret = 0;
+                               break;
                        }
-               }
-       } else if (RT5625_PLL1_FROM_VBCLK == pll_id) {
-
+       } else if (RT5625_PLL_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);
+                       if ((freq_in == codec_vbclk_pll1_div[i].pll_in) &&
+                               (freq_out == codec_vbclk_pll1_div[i].pll_out)) {
+                               snd_soc_write(codec, RT5625_GEN_CTRL2,
+                                       RT5625_PLL1_S_VBCLK);
+                               snd_soc_write(codec, RT5625_PLL_CTRL,
+                                       codec_vbclk_pll1_div[i].regvalue);
+                               snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                                       RT5625_SCLK_MASK, RT5625_SCLK_PLL1);
                                ret = 0;
+                               break;
                        }
-               }
        }
-       return 0;
+
+       return ret;
 }
 
 
-static int rt5625_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, 
+static int rt5625_set_dai_sysclk(struct snd_soc_dai *dai, 
                int clk_id, unsigned int freq, int dir)
 {
-       struct snd_soc_codec *codec = codec_dai->codec;
-       struct rt5625_priv * rt5625 = codec->private_data;
+       struct snd_soc_codec *codec = dai->codec;
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       unsigned int val = 0;
 
-       DBG("sysclk freq %u for audio i2s\n", freq);
-       
-       if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
+       switch (dai->id) {
+       case RT5625_AIF1:
+               if (freq == rt5625->stereo_sysclk)
+                       return 0;
                rt5625->stereo_sysclk = freq;
-               return 0;
+               break;
+
+       case RT5625_AIF2:
+               if (freq == rt5625->voice_sysclk)
+                       return 0;
+               rt5625->voice_sysclk = freq;
+               break;
+
+       default:
+               return -EINVAL;
        }
-       
-       printk("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;
+       switch (clk_id) {
+       case RT5625_SCLK_S_MCLK:
+               break;
 
-       DBG("sysclk freq %u for voice pcm\n", freq);
+       case RT5625_SCLK_S_PLL:
+               val |= RT5625_SCLK_PLL1;
+               break;
 
-       if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
-               rt5625->voice_sysclk = freq;
-               return 0;
-       }                       
+       default:
+               dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+               return -EINVAL;
+       }
+       snd_soc_update_bits(codec, RT5625_GEN_CTRL1,
+                       RT5625_SCLK_MASK, val);
 
-       printk("unsupported sysclk freq %u for voice pcm\n", freq);
-              rt5625->voice_sysclk = 24576000;
+       dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
        
        return 0;
 }
 
-
-static int rt5625_hifi_pcm_hw_params(struct snd_pcm_substream *substream, 
+static int rt5625_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_codec *codec = rtd->codec;
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       unsigned int iface = 0, rate = params_rate(params), coeff;
 
-       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);
-       
-       DBG("enter %s rate = %d \n", __func__, rate);
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
 
-       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);
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface |= RT5625_I2S_DL_20;
+               break;
+
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface |= RT5625_I2S_DL_24;
+               break;
+
+       case SNDRV_PCM_FORMAT_S8:
+               iface |= RT5625_I2S_DL_8;
+               break;
+
+       default:
+               return -EINVAL;
        }
-       
-       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);
+       switch (dai->id) {
+       case RT5625_AIF1:
+               coeff = get_coeff(rt5625->stereo_sysclk, rate, 0);
+               if (coeff < 0) {
+                       dev_err(codec->dev, "Unsupported clock setting\n");
+                       return -EINVAL;
+               }
+               snd_soc_write(codec, RT5625_DAC_CLK_CTRL1,
+                               coeff_div_stereo[coeff].reg60);
+               snd_soc_write(codec, RT5625_DAC_CLK_CTRL2,
+                               coeff_div_stereo[coeff].reg62);
+               snd_soc_update_bits(codec, RT5625_SDP_CTRL,
+                               RT5625_I2S_DL_MASK, iface);
+               break;
 
-       DBG("enter %s rate = %d \n", __func__, rate);
+       case RT5625_AIF2:
+               rate = 8000;
+               coeff = get_coeff(rt5625->voice_sysclk, rate, 1);
+               if (coeff < 0) {
+                       dev_err(codec->dev, "Unsupported clock setting\n");
+                       return -EINVAL;
+               }
+               snd_soc_write(codec, RT5625_VDAC_CLK_CTRL1,
+                               coeff_div_voice[coeff].reg64);
+               iface |= 0x0100; //Voice SYSCLK source from FLL1
+               snd_soc_update_bits(codec, RT5625_EXT_SDP_CTRL,
+                               RT5625_I2S_DL_MASK, iface);
+               break;
 
-       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");
+       default:
+               return -EINVAL;
        }
-       
-       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);
+
+#ifdef RT5625_F_SMT_PHO
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               rt5625->app_bmp |= RT5625_PLY_MASK;
+       else
+               rt5625->app_bmp |= RT5625_REC_MASK;
+#endif
 
        return 0;
 }
 
-
-static int rt5625_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+static int rt5625_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
+       struct snd_soc_codec *codec = dai->codec;
+       unsigned int iface = 0;
+       bool slave;
 
-       struct snd_soc_codec *codec = codec_dai->codec;
-       u16 iface = 0;
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               slave = false;
+               break;
 
-       DBG("enter %s fmt = %d\n", __func__, fmt);
+       case SND_SOC_DAIFMT_CBS_CFS:
+               slave = true;
+               break;
 
-       /*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;
+       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;
-       }
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               break;
 
-       rt5625_write(codec, RT5625_MAIN_SDP_CTRL, iface);
-       return 0;
-}
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface |= RT5625_I2S_DF_LEFT;
+               break;
 
-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;
+       case SND_SOC_DAIFMT_DSP_A:
+               iface |= RT5625_I2S_DF_PCM_A;
+               break;
 
-       DBG("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;                 
-       }
+       case SND_SOC_DAIFMT_DSP_B:
+               iface |= RT5625_I2S_DF_PCM_B;
+               break;
 
-       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;                 
+       default:
+               return -EINVAL;                 
        }
 
-       iface |= 0x8000;      /*enable vopcm*/
-       rt5625_write(codec, RT5625_EXTEND_SDP_CTRL, iface);     
-       return 0;
-}
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
 
+       case SND_SOC_DAIFMT_IB_NF:
+               iface |= RT5625_I2S_BP_INV;
+               break;
 
-static int rt5625_hifi_codec_mute(struct snd_soc_dai *dai, int mute)
-{
-       struct snd_soc_codec *codec = dai->codec;
+       default:
+               return -EINVAL;
+       }
+       iface |= 0x8000;      /*enable vopcm*/
+       
+       switch (dai->id) {
+       case RT5625_AIF1:
+               if (slave)
+                       iface |= RT5625_I2S_M_SLV;
+               snd_soc_update_bits(codec, RT5625_SDP_CTRL,
+                       RT5625_I2S_M_MASK | RT5625_I2S_BP_MASK |
+                       RT5625_I2S_DF_MASK, iface);
+               break;
 
-       if (mute) 
-               rt5625_write_mask(codec, RT5625_STEREO_DAC_VOL, 0x8080, 0x8080);
-       else
-               rt5625_write_mask(codec, RT5625_STEREO_DAC_VOL, 0x0000, 0x8080);
+       case RT5625_AIF2:
+               if (slave)
+                       iface |= RT5625_PCM_M_SLV;
+               snd_soc_update_bits(codec, RT5625_EXT_SDP_CTRL,
+                       RT5625_PCM_M_MASK | RT5625_I2S_BP_MASK |
+                       RT5625_I2S_DF_MASK, iface);
+               break;
+
+       default:
+               return -EINVAL;
+       }
        return 0;
 }
 
-static int rt5625_voice_codec_mute(struct snd_soc_dai *dai, int mute)
+#ifdef RT5625_F_SMT_PHO
+static int rt5625_trigger(struct snd_pcm_substream *substream,
+       int cmd, struct snd_soc_dai *dai)
 {
-       struct snd_soc_codec *codec = dai->codec;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct rt5625_priv *rt5625 = snd_soc_codec_get_drvdata(codec);
+       int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               if (capture)
+                       rt5625->app_bmp |= RT5625_REC_MASK;
+               else
+                       rt5625->app_bmp |= RT5625_PLY_MASK;
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (capture)
+                       rt5625->app_bmp &= ~RT5625_REC_MASK;
+               else
+                       rt5625->app_bmp &= ~RT5625_PLY_MASK;
+               rt5625->app_bmp &= ~RT5625_VOIP_MASK;
+               break;
+
+       default:
+               break;
+       }
 
-       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;
 }
-
+#endif
 
 static int rt5625_set_bias_level(struct snd_soc_codec *codec, 
                        enum snd_soc_bias_level level)
 {
        switch(level) {
        case SND_SOC_BIAS_ON:
+#ifdef RT5625_DEMO
+               snd_soc_update_bits(codec, RT5625_HP_OUT_VOL,
+                               RT5625_L_MUTE | RT5625_R_MUTE, 0);
+               snd_soc_update_bits(codec, RT5625_SPK_OUT_VOL,
+                               RT5625_L_MUTE | RT5625_R_MUTE, 0);
+#endif
                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);         
+               snd_soc_write(codec, RT5625_PD_CTRL, 0x0000);
+               snd_soc_update_bits(codec, RT5625_PWR_ADD1,
+                               RT5625_P_MB1 | RT5625_P_MB2,
+                               RT5625_P_MB1 | RT5625_P_MB2);
                break;
+
        case SND_SOC_BIAS_STANDBY:
+#ifdef RT5625_DEMO
+               snd_soc_update_bits(codec, RT5625_HP_OUT_VOL,
+                       RT5625_L_MUTE | RT5625_R_MUTE,
+                       RT5625_L_MUTE | RT5625_R_MUTE);
+               snd_soc_update_bits(codec, RT5625_SPK_OUT_VOL,
+                       RT5625_L_MUTE | RT5625_R_MUTE,
+                       RT5625_L_MUTE | RT5625_R_MUTE);
+               snd_soc_update_bits(codec, RT5625_PWR_ADD1,
+                               RT5625_P_MB1 | RT5625_P_MB2, 0);
+#endif
+               if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
+                       snd_soc_write(codec, RT5625_PD_CTRL, 0);
+                       snd_soc_write(codec, RT5625_PWR_ADD1,
+                                       RT5625_P_MAIN_BIAS);
+                       snd_soc_write(codec, RT5625_PWR_ADD2, RT5625_P_VREF);
+                       codec->cache_only = false;
+                       snd_soc_cache_sync(codec);
+               }
                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
+#ifdef RT5625_DEMO
+               snd_soc_update_bits(codec, RT5625_HP_OUT_VOL,
+                       RT5625_L_MUTE | RT5625_R_MUTE,
+                       RT5625_L_MUTE | RT5625_R_MUTE);
+               snd_soc_update_bits(codec, RT5625_SPK_OUT_VOL,
+                       RT5625_L_MUTE | RT5625_R_MUTE,
+                       RT5625_L_MUTE | RT5625_R_MUTE);
+#endif
+               snd_soc_write(codec, RT5625_PWR_ADD1, 0x0000);
+               snd_soc_write(codec, RT5625_PWR_ADD2, 0x0000);
+               snd_soc_write(codec, RT5625_PWR_ADD3, 0x0000);
                
                break;
        }
-       codec->bias_level = level;
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
+
+#ifdef RT5625_PROC     
+static int rt5625_proc_init(void);
+#endif
+
+static int rt5625_probe(struct snd_soc_codec *codec)
+{
+       int ret;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+       
+       #ifdef RT5625_PROC      
+       rt5625_proc_init();
+       #endif
+       
+       rt5625_reset(codec);
+       snd_soc_write(codec, RT5625_PD_CTRL, 0);
+       snd_soc_write(codec, RT5625_PWR_ADD1, RT5625_P_MAIN_BIAS);
+       snd_soc_write(codec, RT5625_PWR_ADD2, RT5625_P_VREF);
+#ifdef RT5625_DEMO
+       rt5625_reg_init(codec);
+#endif
+       codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
+       rt5625_codec = codec;
        return 0;
 }
 
+static int rt5625_remove(struct snd_soc_codec *codec)
+{
+       rt5625_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
 
-#define RT5625_STEREO_RATES    SNDRV_PCM_RATE_8000_48000
+#ifdef CONFIG_PM
+static int rt5625_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+       rt5625_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
 
-#define RT5626_VOICE_RATES SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000
+static int rt5625_resume(struct snd_soc_codec *codec)
+{
+       rt5625_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+#else
+#define rt5625_suspend NULL
+#define rt5625_resume NULL
+#endif
 
+#define RT5625_STEREO_RATES SNDRV_PCM_RATE_8000_48000
+#define RT5625_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_ops rt5625_aif_dai_ops = {
+#ifdef RT5625_F_SMT_PHO
+       .trigger = rt5625_trigger,
+#endif
+       .hw_params = rt5625_hw_params,
+       .set_fmt = rt5625_set_dai_fmt,
+       .set_sysclk = rt5625_set_dai_sysclk,
+       .set_pll = rt5625_set_dai_pll,
 };
 
-
-
-struct snd_soc_dai rt5625_dai[] = {
-       /*hifi codec dai*/
+struct snd_soc_dai_driver rt5625_dai[] = {
        {
-               .name = "RT5625 HiFi",
-               .id = 1,
+               .name = "rt5625-aif1",
+               .id = RT5625_AIF1,
                .playback = {
                        .stream_name = "HiFi Playback",
                        .channels_min = 1,
@@ -1971,489 +2814,226 @@ struct snd_soc_dai rt5625_dai[] = {
                        .rates = RT5625_STEREO_RATES,
                        .formats = RT5625_FORMATS,
                },
-               
-               .ops = &rt5625_dai_ops_hifi,
+               .ops = &rt5625_aif_dai_ops,
        },
-
-       /*voice codec dai*/
        {
-               .name = "RT5625 Voice",
-               .id = 2,
+               .name = "rt5625-aif2",
+               .id = RT5625_AIF2,
                .playback = {
                        .stream_name = "Voice Playback",
                        .channels_min = 1,
-                       .channels_max = 1,
-                       .rates = RT5626_VOICE_RATES,
+                       .channels_max = 2,
+                       .rates = RT5625_VOICE_RATES,
                        .formats = RT5625_FORMATS,
                },
                .capture = {
                        .stream_name = "Voice Capture",
                        .channels_min = 1,
-                       .channels_max = 1,
-                       .rates = RT5626_VOICE_RATES,
+                       .channels_max = 2,
+                       .rates = RT5625_VOICE_RATES,
                        .formats = RT5625_FORMATS,
                },
-               
-               .ops = &rt5625_dai_ops_voice,
-
+               .ops = &rt5625_aif_dai_ops,
        },
 };
 
-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)
-{
-       DBG("enter %s\n", __func__);
-       return 0;
-}
-
-static int rt56xx_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
-       DBG("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;
+static struct snd_soc_codec_driver soc_codec_dev_rt5625 = {
+       .probe = rt5625_probe,
+       .remove = rt5625_remove,
+       .suspend = rt5625_suspend,
+       .resume = rt5625_resume,
+       .set_bias_level = rt5625_set_bias_level,
+       .reg_cache_size = 0x80,
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = rt5625_reg,
+       .volatile_register = rt5625_volatile_register,
+       .readable_register = rt5625_readable_register,
+       .reg_cache_step = 1,
+       .controls = rt5625_snd_controls,
+       .num_controls = ARRAY_SIZE(rt5625_snd_controls),
+       .dapm_widgets = rt5625_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(rt5625_dapm_widgets),
+       .dapm_routes = rt5625_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(rt5625_dapm_routes),
+};
 
-err:
-       kfree(buf);
-       return -EFAULT;
-       
-}
+static const struct i2c_device_id rt5625_i2c_id[] = {
+       { "rt5625", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5625_i2c_id);
 
-static int rt56xx_codec_dump_reg(struct snd_hwdep *hw, struct file *file, unsigned long arg)
+static int rt5625_i2c_probe(struct i2c_client *i2c,
+                   const struct i2c_device_id *id)
 {
-       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;
+       struct rt5625_priv *rt5625;
+       int ret;
 
-       DBG("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)
+       rt5625 = kzalloc(sizeof(struct rt5625_priv), GFP_KERNEL);
+       if (NULL == rt5625)
                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
+       i2c_set_clientdata(i2c, rt5625);
 
-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;
-       }
-       DBG("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);
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5625,
+                       rt5625_dai, ARRAY_SIZE(rt5625_dai));
        if (ret < 0)
-               pr_err("failed to initialise rt5625\n");
+               kfree(rt5625);
 
        return ret;
 }
 
-static int rt5625_i2c_remove(struct i2c_client *client)
+static __devexit int rt5625_i2c_remove(struct i2c_client *i2c)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
+       snd_soc_unregister_codec(&i2c->dev);
+       kfree(i2c_get_clientdata(i2c));
        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 = {
+struct i2c_driver rt5625_i2c_driver = {
        .driver = {
-               .name = "RT5625 I2C Codec",
+               .name = "rt5625",
                .owner = THIS_MODULE,
        },
-       .probe =    rt5625_i2c_probe,
-       .remove =   rt5625_i2c_remove,
+       .probe = rt5625_i2c_probe,
+       .remove   = __devexit_p(rt5625_i2c_remove),
        .id_table = rt5625_i2c_id,
 };
 
-
-static int rt5625_add_i2c_device(struct platform_device *pdev,
-                                const struct rt5625_setup_data *setup)
+static int __init rt5625_modinit(void)
 {
-#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;
-       }
+       return i2c_add_driver(&rt5625_i2c_driver);
+}
+module_init(rt5625_modinit);
 
-       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:
+static void __exit rt5625_modexit(void)
+{
        i2c_del_driver(&rt5625_i2c_driver);
-       return -ENODEV;
-#endif
 }
+module_exit(rt5625_modexit);
 
+MODULE_DESCRIPTION("ASoC RT5625 driver");
+MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>");
+MODULE_LICENSE("GPL");
 
-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);
+#ifdef RT5625_PROC
 
-       if(socdev->codec_data)
+static ssize_t rt5625_proc_write(struct file *file, const char __user *buffer,
+                          unsigned long len, void *data)
+{
+       char *cookie_pot; 
+       char *p;
+       int reg;
+       int value;
+       
+       cookie_pot = (char *)vmalloc( len );
+       if (!cookie_pot) 
        {
-               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) 
+       } 
+       else 
        {
-               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 (copy_from_user( cookie_pot, buffer, len )) 
+                       return -EFAULT;
        }
 
-       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;
+       switch(cookie_pot[0])
+       {
+       case 'd':
+       case 'D':
+               debug_write_read ++;
+               debug_write_read %= 2;
+               if(debug_write_read != 0)
+                       printk("Debug read and write reg on\n");
+               else    
+                       printk("Debug read and write reg off\n");       
+               break;  
+       case 'r':
+       case 'R':
+               printk("Read reg debug\n");             
+               if(cookie_pot[1] ==':')
+               {
+                       debug_write_read = 1;
+                       strsep(&cookie_pot,":");
+                       while((p=strsep(&cookie_pot,",")))
+                       {
+                               reg = simple_strtol(p,NULL,16);
+                               value = rt5625_read(rt5625_codec,reg);
+                               printk("rt5625_read:0x%04x = 0x%04x\n",reg,value);
+                       }
+                       debug_write_read = 0;
+                       printk("\n");
+               }
+               else
+               {
+                       printk("Error Read reg debug.\n");
+                       printk("For example: echo r:22,23,24,25>rt5625_ts\n");
+               }
+               break;
+       case 'w':
+       case 'W':
+               printk("Write reg debug\n");            
+               if(cookie_pot[1] ==':')
+               {
+                       debug_write_read = 1;
+                       strsep(&cookie_pot,":");
+                       while((p=strsep(&cookie_pot,"=")))
+                       {
+                               reg = simple_strtol(p,NULL,16);
+                               p=strsep(&cookie_pot,",");
+                               value = simple_strtol(p,NULL,16);
+                               rt5625_write(rt5625_codec,reg,value);
+                               printk("rt5625_write:0x%04x = 0x%04x\n",reg,value);
+                       }
+                       debug_write_read = 0;
+                       printk("\n");
+               }
+               else
+               {
+                       printk("Error Write reg debug.\n");
+                       printk("For example: w:22=0,23=0,24=0,25=0>rt5625_ts\n");
+               }
+               break;
+       case 'a':
+               printk("Dump reg \n");          
 
-       /* cancel any work waiting to be queued. */
-       ret = cancel_delayed_work(dwork);
+               for(reg = 0; reg < 0x6e; reg+=2)
+               {
+                       value = rt5625_read(rt5625_codec,reg);
+                       printk("rt5625_read:0x%04x = 0x%04x\n",reg,value);
+               }
 
-       /* 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();
+               break;          
+       default:
+               printk("Help for rt5625_ts .\n-->The Cmd list: \n");
+               printk("-->'d&&D' Open or Off the debug\n");
+               printk("-->'r&&R' Read reg debug,Example: echo 'r:22,23,24,25'>rt5625_ts\n");
+               printk("-->'w&&W' Write reg debug,Example: echo 'w:22=0,23=0,24=0,25=0'>rt5625_ts\n");
+               break;
        }
-       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;
+       return len;
 }
 
+static const struct file_operations rt5625_proc_fops = {
+       .owner          = THIS_MODULE,
+};
 
-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)
+static int rt5625_proc_init(void)
 {
-       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);
+       struct proc_dir_entry *rt5625_proc_entry;
+       rt5625_proc_entry = create_proc_entry("driver/rt5625_ts", 0777, NULL);
+       if(rt5625_proc_entry != NULL)
+       {
+               rt5625_proc_entry->write_proc = rt5625_proc_write;
+               return 0;
        }
-
-       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));
+       else
+       {
+               printk("create proc error !\n");
+               return -1;
        }
-
-       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");
+#endif
 
index cb4f73e8bccaf99db0aa34c2b79f321acaa064be..f61e439426dcbd7263d3c3d95e334bc300189cbc 100644 (file)
-#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;
+/*
+ * rt5625.h  --  RT5625 ALSA SoC audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ * Author: Johnny Hsu <johnnyhsu@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __RT5625_H__
+#define __RT5625_H__
+
+#define RT5625_RESET                           0x00
+#define RT5625_SPK_OUT_VOL                     0x02
+#define RT5625_HP_OUT_VOL                      0x04
+#define RT5625_AUX_OUT_VOL                     0x06
+#define RT5625_PHONEIN_VOL                     0x08
+#define RT5625_LINE_IN_VOL                     0x0a
+#define RT5625_DAC_VOL                         0x0c
+#define RT5625_MIC_VOL                         0x0e
+#define RT5625_DAC_MIC_CTRL                    0x10
+#define RT5625_ADC_REC_GAIN                    0x12
+#define RT5625_ADC_REC_MIXER                   0x14
+#define RT5625_VDAC_OUT_VOL                    0x18
+#define RT5625_VODSP_PDM_CTL                   0x1a
+#define RT5625_OUTMIX_CTRL                     0x1c
+#define RT5625_VODSP_CTL                       0x1e
+#define RT5625_MIC_CTRL                                0x22
+#define RT5625_DMIC_CTRL                       0x24
+#define RT5625_PD_CTRL                         0x26
+#define RT5625_F_DAC_ADC_VDAC                  0x2e
+#define RT5625_SDP_CTRL                                0x34
+#define RT5625_EXT_SDP_CTRL                    0x36
+#define RT5625_PWR_ADD1                        0x3a
+#define RT5625_PWR_ADD2                        0x3c
+#define RT5625_PWR_ADD3                        0x3e
+#define RT5625_GEN_CTRL1                       0x40
+#define RT5625_GEN_CTRL2                       0x42
+#define RT5625_PLL_CTRL                                0x44
+#define RT5625_PLL2_CTRL                       0x46
+#define RT5625_LDO_CTRL                                0x48
+#define RT5625_GPIO_CONFIG                     0x4c
+#define RT5625_GPIO_POLAR                      0x4e
+#define RT5625_GPIO_STICKY                     0x50
+#define RT5625_GPIO_WAKEUP                     0x52
+#define RT5625_GPIO_STATUS                     0x54
+#define RT5625_GPIO_SHARING                    0x56
+#define RT5625_OTC_STATUS                      0x58
+#define RT5625_SOFT_VOL_CTRL                   0x5a
+#define RT5625_GPIO_OUT_CTRL                   0x5c
+#define RT5625_MISC_CTRL                       0x5e
+#define RT5625_DAC_CLK_CTRL1                   0x60
+#define RT5625_DAC_CLK_CTRL2                   0x62
+#define RT5625_VDAC_CLK_CTRL1                  0x64
+#define RT5625_PS_CTRL                         0x68
+#define RT5625_PRIV_INDEX                      0x6a
+#define RT5625_PRIV_DATA                       0x6c
+#define RT5625_EQ_CTRL                         0x6e
+#define RT5625_DSP_ADDR                        0x70
+#define RT5625_DSP_DATA                        0x72
+#define RT5625_DSP_CMD                         0x74
+#define RT5625_VENDOR_ID1                      0x7c
+#define RT5625_VENDOR_ID2                      0x7e
+
+/* global definition */
+#define RT5625_L_MUTE                          (0x1 << 15)
+#define RT5625_L_MUTE_SFT                      15
+#define RT5625_L_ZC                            (0x1 << 14)
+#define RT5625_L_VOL_MASK                      (0x1f << 8)
+#define RT5625_L_HVOL_MASK                     (0x3f << 8)
+#define RT5625_L_VOL_SFT                       8
+#define RT5625_R_MUTE                          (0x1 << 7)
+#define RT5625_R_MUTE_SFT                      7
+#define RT5625_R_ZC                            (0x1 << 6)
+#define RT5625_R_VOL_MASK                      (0x1f)
+#define RT5625_R_HVOL_MASK                     (0x3f)
+#define RT5625_R_VOL_SFT                       0
+#define RT5625_M_HPMIX                         (0x1 << 15)
+#define RT5625_M_SPKMIX                        (0x1 << 14)
+#define RT5625_M_MONOMIX                       (0x1 << 13)
+
+/* Phone Input (0x08) */
+#define RT5625_M_PHO_HM                        (0x1 << 15)
+#define RT5625_M_PHO_HM_SFT                    15
+#define RT5625_M_PHO_SM                        (0x1 << 14)
+#define RT5625_M_PHO_SM_SFT                    14
+#define RT5625_PHO_DIFF                                (0x1 << 13)
+#define RT5625_PHO_DIFF_SFT                    13
+#define RT5625_PHO_DIFF_DIS                    (0x0 << 13)
+#define RT5625_PHO_DIFF_EN                     (0x1 << 13)
+
+/* Linein Volume (0x0a) */
+#define RT5625_M_LI_HM                         (0x1 << 15)
+#define RT5625_M_LI_HM_SFT                     15
+#define RT5625_M_LI_SM                         (0x1 << 14)
+#define RT5625_M_LI_SM_SFT                     14
+#define RT5625_M_LI_MM                         (0x1 << 13)
+#define RT5625_M_LI_MM_SFT                     13
+
+/* MIC Input Volume (0x0e) */
+#define RT5625_MIC1_DIFF_MASK                  (0x1 << 15)
+#define RT5625_MIC1_DIFF_SFT                   15
+#define RT5625_MIC1_DIFF_DIS                   (0x0 << 15)
+#define RT5625_MIC1_DIFF_EN                    (0x1 << 15)
+#define RT5625_MIC2_DIFF_MASK                  (0x1 << 7)
+#define RT5625_MIC2_DIFF_SFT                   7
+#define RT5625_MIC2_DIFF_DIS                   (0x0 << 7)
+#define RT5625_MIC2_DIFF_EN                    (0x1 << 7)
+
+/* Stereo DAC and MIC Routing Control (0x10) */
+#define RT5625_M_MIC1_HM                       (0x1 << 15)
+#define RT5625_M_MIC1_HM_SFT                   15
+#define RT5625_M_MIC1_SM                       (0x1 << 14)
+#define RT5625_M_MIC1_SM_SFT                   14
+#define RT5625_M_MIC1_MM                       (0x1 << 13)
+#define RT5625_M_MIC1_MM_SFT                   13
+#define RT5625_M_MIC2_HM                       (0x1 << 11)
+#define RT5625_M_MIC2_HM_SFT                   11
+#define RT5625_M_MIC2_SM                       (0x1 << 10)
+#define RT5625_M_MIC2_SM_SFT                   10
+#define RT5625_M_MIC2_MM                       (0x1 << 9)
+#define RT5625_M_MIC2_MM_SFT                   9
+#define RT5625_M_DACL_HM                       (0x1 << 3)
+#define RT5625_M_DACL_HM_SFT                   3
+#define RT5625_M_DACR_HM                       (0x1 << 2)
+#define RT5625_M_DACR_HM_SFT                   2
+#define RT5625_M_DAC_SM                        (0x1 << 1)
+#define RT5625_M_DAC_SM_SFT                    1
+#define RT5625_M_DAC_MM                        (0x1)
+#define RT5625_M_DAC_MM_SFT                    0
+
+/* ADC Record Gain (0x12) */
+#define RT5625_M_ADCL_HM                       (0x1 << 15)
+#define RT5625_M_ADCL_HM_SFT                   15
+#define RT5625_M_ADCL_MM                       (0x1 << 14)
+#define RT5625_M_ADCL_MM_SFT                   14
+#define RT5625_ADCL_ZCD                        (0x1 << 13)
+#define RT5625_G_ADCL_MASK                     (0x1f << 8)
+#define RT5625_M_ADCR_HM                       (0x1 << 7)
+#define RT5625_M_ADCR_HM_SFT                   7
+#define RT5625_M_ADCR_MM                       (0x1 << 6)
+#define RT5625_M_ADCR_MM_SFT                   6
+#define RT5625_ADCR_ZCD                        (0x1 << 5)
+#define RT5625_G_ADCR_MASK                     (0x1f)
+
+/* ADC Record Mixer Control (0x14) */
+#define RT5625_M_RM_L_MIC1                     (0x1 << 14)
+#define RT5625_M_RM_L_MIC1_SFT         14
+#define RT5625_M_RM_L_MIC2                     (0x1 << 13)
+#define RT5625_M_RM_L_MIC2_SFT         13
+#define RT5625_M_RM_L_LINE                     (0x1 << 12)
+#define RT5625_M_RM_L_LINE_SFT                 12
+#define RT5625_M_RM_L_PHO                      (0x1 << 11)
+#define RT5625_M_RM_L_PHO_SFT                  11
+#define RT5625_M_RM_L_HM                       (0x1 << 10)
+#define RT5625_M_RM_L_HM_SFT                   10
+#define RT5625_M_RM_L_SM                       (0x1 << 9)
+#define RT5625_M_RM_L_SM_SFT                   9
+#define RT5625_M_RM_L_MM                       (0x1 << 8)
+#define RT5625_M_RM_L_MM_SFT                   8
+#define RT5625_M_RM_R_MIC1                     (0x1 << 6)
+#define RT5625_M_RM_R_MIC1_SFT         6
+#define RT5625_M_RM_R_MIC2                     (0x1 << 5)
+#define RT5625_M_RM_R_MIC2_SFT         5
+#define RT5625_M_RM_R_LINE                     (0x1 << 4)
+#define RT5625_M_RM_R_LINE_SFT                 4
+#define RT5625_M_RM_R_PHO                      (0x1 << 3)
+#define RT5625_M_RM_R_PHO_SFT                  3
+#define RT5625_M_RM_R_HM                       (0x1 << 2)
+#define RT5625_M_RM_R_HM_SFT                   2
+#define RT5625_M_RM_R_SM                       (0x1 << 1)
+#define RT5625_M_RM_R_SM_SFT                   1
+#define RT5625_M_RM_R_MM                       (0x1)
+#define RT5625_M_RM_R_MM_SFT                   0
+
+/* Voice DAC Volume (0x18) */
+#define RT5625_M_VDAC_HM                       (0x1 << 15)
+#define RT5625_M_VDAC_HM_SFT                   15
+#define RT5625_M_VDAC_SM                       (0x1 << 14)
+#define RT5625_M_VDAC_SM_SFT                   14
+#define RT5625_M_VDAC_MM                       (0x1 << 13)
+#define RT5625_M_VDAC_MM_SFT                   13
+
+/* AEC & PDM Control (0x1a) */
+#define RT5625_SRC1_PWR                        (0x1 << 15)
+#define RT5625_SRC1_PWR_SFT                    15
+#define RT5625_SRC2_PWR                        (0x1 << 13)
+#define RT5625_SRC2_PWR_SFT                    13
+#define RT5625_SRC2_S_MASK                     (0x1 << 12)             
+#define RT5625_SRC2_S_SFT                      12              
+#define RT5625_SRC2_S_TXDP                     (0x0 << 12)
+#define RT5625_SRC2_S_TXDC                     (0x1 << 12)
+#define RT5625_RXDP_PWR                        (0x1 << 11)
+#define RT5625_RXDP_PWR_SFT                    11
+#define RT5625_RXDP_S_MASK                     (0x3 << 9)              
+#define RT5625_RXDP_S_SFT                      9
+#define RT5625_RXDP_S_SRC1                     (0x0 << 9)
+#define RT5625_RXDP_S_ADCL                     (0x1 << 9)
+#define RT5625_RXDP_S_VOICE                    (0x2 << 9)
+#define RT5625_RXDP_S_ADCR                     (0x3 << 9)
+#define RT5625_RXDC_PWR                        (0x1 << 8)
+#define RT5625_RXDC_PWR_SFT                    8
+#define RT5625_PCM_S_MASK                      (0x1 << 7)              
+#define RT5625_PCM_S_SFT                       7
+#define RT5625_PCM_S_ADCR                      (0x0 << 7)
+#define RT5625_PCM_S_TXDP                      (0x1 << 7)
+#define RT5625_REC_IIS_S_MASK                  (0x3 << 4)
+#define RT5625_REC_IIS_S_SFT                   4
+#define RT5625_REC_IIS_S_ADC                   (0x0 << 4)
+#define RT5625_REC_IIS_S_VOICE                 (0x1 << 4)
+#define RT5625_REC_IIS_S_SRC2                  (0x2 << 4)
+
+/* Output Mixer Control (0x1c) */
+#define RT5625_SPKN_S_MASK                     (0x3 << 14)
+#define RT5625_SPKN_S_SFT                      14
+#define RT5625_SPKN_S_LN                       (0x2 << 14)
+#define RT5625_SPKN_S_RP                       (0x1 << 14)
+#define RT5625_SPKN_S_RN                       (0x0 << 14)
+#define RT5625_SPK_T_MASK                      (0x1 << 13)
+#define RT5625_SPK_T_SFT                       13
+#define RT5625_SPK_T_CLS_D                     (0x1 << 13)
+#define RT5625_SPK_T_CLS_AB                    (0x0 << 13)
+#define RT5625_CLS_AB_MASK                     (0x1 << 12)
+#define RT5625_CLS_AB_SFT                      12
+#define RT5625_CLS_AB_S_AMP                    (0x0 << 12)
+#define RT5625_CLS_AB_W_AMP                    (0x1 << 12)
+#define RT5625_SPKVOL_S_MASK                   (0x3 << 10)
+#define RT5625_SPKVOL_S_SFT                    10
+#define RT5625_SPKVOL_S_MM                     (0x3 << 10)
+#define RT5625_SPKVOL_S_SM                     (0x2 << 10)
+#define RT5625_SPKVOL_S_HM                     (0x1 << 10)
+#define RT5625_SPKVOL_S_VMID                   (0x0 << 10)
+#define RT5625_HPVOL_L_S_MASK                  (0x1 << 9)
+#define RT5625_HPVOL_L_S_SFT                   9
+#define RT5625_HPVOL_L_S_HM                    (0x1 << 9)
+#define RT5625_HPVOL_L_S_VMID                  (0x0 << 9)
+#define RT5625_HPVOL_R_S_MASK                  (0x1 << 8)
+#define RT5625_HPVOL_R_S_SFT                   8
+#define RT5625_HPVOL_R_S_HM                    (0x1 << 8)      
+#define RT5625_HPVOL_R_S_VMID                  (0x0 << 8)
+#define RT5625_AUXVOL_S_MASK                   (0x3 << 6)
+#define RT5625_AUXVOL_S_SFT                    6
+#define RT5625_AUXVOL_S_MM                     (0x3 << 6)
+#define RT5625_AUXVOL_S_SM                     (0x2 << 6)
+#define RT5625_AUXVOL_S_HM                     (0x1 << 6)
+#define RT5625_AUXVOL_S_VMID                   (0x0 << 6)
+#define RT5625_AUXOUT_MODE                     (0x1 << 4)
+#define RT5625_AUXOUT_MODE_SFT         4
+#define RT5625_DACL_HP_MASK                    (0x1 << 1)
+#define RT5625_DACL_HP_SFT                     1
+#define RT5625_DACL_HP_MUTE                    (0x0 << 1)
+#define RT5625_DACL_HP_ON                      (0x1 << 1)
+#define RT5625_DACR_HP_MASK                    (0x1)
+#define RT5625_DACR_HP_SFT                     0
+#define RT5625_DACR_HP_MUTE                    (0x0)
+#define RT5625_DACR_HP_ON                      (0x1)
+
+/* VoDSP Control (0x1e) */
+#define RT5625_DSP_SCLK_S_MASK         (0x1 << 15)
+#define RT5625_DSP_SCLK_S_SFT                  15
+#define RT5625_DSP_SCLK_S_MCLK         (0x0 << 15)
+#define RT5625_DSP_SCLK_S_VCLK                 (0x1 << 15)
+#define RT5625_DSP_LRCK_MASK                   (0x1 << 13)
+#define RT5625_DSP_LRCK_SFT                    13
+#define RT5625_DSP_LRCK_8K                     (0x0 << 13)
+#define RT5625_DSP_LRCK_16K                    (0x1 << 13)
+#define RT5625_DSP_TP_MASK                     (0x1 << 3)
+#define RT5625_DSP_TP_SFT                      3
+#define RT5625_DSP_TP_NOR                      (0x0 << 3)
+#define RT5625_DSP_TP_TEST                     (0x1 << 3)
+#define RT5625_DSP_BP_MASK                     (0x1 << 2)
+#define RT5625_DSP_BP_SFT                      2
+#define RT5625_DSP_BP_EN                       (0x0 << 2)
+#define RT5625_DSP_BP_NOR                      (0x1 << 2)
+#define RT5625_DSP_PD_MASK                     (0x1 << 1)
+#define RT5625_DSP_PD_SFT                      1
+#define RT5625_DSP_PD_EN                       (0x0 << 1)
+#define RT5625_DSP_PD_NOR                      (0x1 << 1)
+#define RT5625_DSP_RST_MASK                    (0x1)
+#define RT5625_DSP_RST_SFT                     0
+#define RT5625_DSP_RST_EN                      (0x0)
+#define RT5625_DSP_RST_NOR                     (0x1)
+
+/* Microphone Control (0x22) */
+#define RT5625_MIC1_BST_MASK                   (0x3 << 10)
+#define RT5625_MIC1_BST_SFT                    10
+#define RT5625_MIC1_BST_BYPASS         (0x0 << 10)
+#define RT5625_MIC1_BST_20DB                   (0x1 << 10)
+#define RT5625_MIC1_BST_30DB                   (0x2 << 10)
+#define RT5625_MIC1_BST_40DB                   (0x3 << 10)
+#define RT5625_MIC2_BST_MASK                   (0x3 << 8)
+#define RT5625_MIC2_BST_SFT                    8
+#define RT5625_MIC2_BST_BYPASS         (0x0 << 8)
+#define RT5625_MIC2_BST_20DB                   (0x1 << 8)
+#define RT5625_MIC2_BST_30DB                   (0x2 << 8)
+#define RT5625_MIC2_BST_40DB                   (0x3 << 8)
+#define RT5625_MB1_OV_MASK                     (0x1 << 5)
+#define RT5625_MB1_OV_90P                      (0x0 << 5)
+#define RT5625_MB1_OV_75P                      (0x1 << 5)
+#define RT5625_MB2_OV_MASK                     (0x1 << 4)
+#define RT5625_MB2_OV_90P                      (0x0 << 4)
+#define RT5625_MB2_OV_75P                      (0x1 << 4)
+#define RT5625_SCD_THD_MASK                    (0x3)
+#define RT5625_SCD_THD_600UA                   (0x0)
+#define RT5625_SCD_THD_1500UA                  (0x1)
+#define RT5625_SCD_THD_2000UA                  (0x2)
+
+/* Digital Boost Control (0x24) */
+#define RT5625_DIG_BST_MASK                    (0x7)
+#define RT5625_DIG_BST_SFT                     0
+
+/* Power Down Control/Status (0x26) */
+#define RT5625_PWR_PR7                         (0x1 << 15)
+#define RT5625_PWR_PR6                         (0x1 << 14)
+#define RT5625_PWR_PR5                         (0x1 << 13)
+#define RT5625_PWR_PR3                         (0x1 << 11)
+#define RT5625_PWR_PR2                         (0x1 << 10)
+#define RT5625_PWR_PR1                         (0x1 << 9)
+#define RT5625_PWR_PR0                         (0x1 << 8)
+#define RT5625_PWR_REF_ST                      (0x1 << 3)
+#define RT5625_PWR_AM_ST                       (0x1 << 2)
+#define RT5625_PWR_DAC_ST                      (0x1 << 1)
+#define RT5625_PWR_ADC_ST                      (0x1)
+
+/* Stereo DAC/Voice DAC/Stereo ADC Function Select (0x2e) */
+#define RT5625_DAC_F_MASK                      (0x3 << 12)
+#define RT5625_DAC_F_SFT                       12
+#define RT5625_DAC_F_DAC                       (0x0 << 12)             
+#define RT5625_DAC_F_SRC2                      (0x1 << 12)
+#define RT5625_DAC_F_TXDP                      (0x2 << 12)
+#define RT5625_DAC_F_TXDC                      (0x3 << 12)
+#define RT5625_VDAC_S_MASK                     (0x7 << 8)
+#define RT5625_VDAC_S_SFT                      8
+#define RT5625_VDAC_S_VOICE                    (0x0 << 8)      
+#define RT5625_VDAC_S_SRC2                     (0x1 << 8)
+#define RT5625_VDAC_S_TXDP                     (0x2 << 8)
+#define RT5625_VDAC_S_TXDC                     (0x3 << 8)
+#define RT5625_ADCR_F_MASK                     (0x3 << 4)
+#define RT5625_ADCR_F_SFT                      4
+#define RT5625_ADCR_F_ADC                      (0x0 << 4)
+#define RT5625_ADCR_F_VADC                     (0x1 << 4)
+#define RT5625_ADCR_F_DSP                      (0x2 << 4)
+#define RT5625_ADCR_F_PDM                      (0x3 << 4)
+#define RT5625_ADCL_F_MASK                     (0x1)
+#define RT5625_ADCL_F_SFT                      0
+#define RT5625_ADCL_F_ADC                      (0x0)
+#define RT5625_ADCL_F_DSP                      (0x1)
+
+/* Main Serial Data Port Control (Stereo IIS) (0x34) */
+#define RT5625_I2S_M_MASK                      (0x1 << 15)
+#define RT5625_I2S_M_SFT                       15
+#define RT5625_I2S_M_MST                       (0x0 << 15)
+#define RT5625_I2S_M_SLV                       (0x1 << 15)
+#define RT5625_I2S_SAD_MASK                    (0x1 << 14)
+#define RT5625_I2S_SAD_SFT                     14
+#define RT5625_I2S_SAD_DIS                     (0x0 << 14)
+#define RT5625_I2S_SAD_EN                      (0x1 << 14)
+#define RT5625_I2S_S_MASK                      (0x1 << 8)
+#define RT5625_I2S_S_SFT                       8
+#define RT5625_I2S_S_MSCLK                     (0x0 << 8)
+#define RT5625_I2S_S_VSCLK                     (0x1 << 8)
+#define RT5625_I2S_BP_MASK                     (0x1 << 7)
+#define RT5625_I2S_BP_SFT                      7
+#define RT5625_I2S_BP_NOR                      (0x0 << 7)
+#define RT5625_I2S_BP_INV                      (0x1 << 7)
+#define RT5625_I2S_LRCK_MASK                   (0x1 << 6)
+#define RT5625_I2S_LRCK_SFT                    6
+#define RT5625_I2S_LRCK_NOR                    (0x0 << 6)
+#define RT5625_I2S_LRCK_INV                    (0x1 << 6)
+#define RT5625_I2S_DL_MASK                     (0x3 << 2)
+#define RT5625_I2S_DL_SFT                      2
+#define RT5625_I2S_DL_16                       (0x0 << 2)
+#define RT5625_I2S_DL_20                       (0x1 << 2)
+#define RT5625_I2S_DL_24                       (0x2 << 2)
+#define RT5625_I2S_DL_8                                (0x3 << 2)
+#define RT5625_I2S_DF_MASK                     (0x3)
+#define RT5625_I2S_DF_SFT                      0
+#define RT5625_I2S_DF_I2S                      (0x0)
+#define RT5625_I2S_DF_LEFT                     (0x1)
+#define RT5625_I2S_DF_PCM_A                    (0x2)
+#define RT5625_I2S_DF_PCM_B                    (0x3)
+
+/* Extend Serial Data Port Control (0x36) */
+#define RT5625_PCM_F_MASK                      (0x1 << 15)
+#define RT5625_PCM_F_SFT                       15
+#define RT5625_PCM_F_GPIO                      (0x0 << 15)
+#define RT5625_PCM_F_PCM                       (0x1 << 15)
+#define RT5625_PCM_M_MASK                      (0x1 << 14)
+#define RT5625_PCM_M_SFT                       14
+#define RT5625_PCM_M_MST                       (0x0 << 14)
+#define RT5625_PCM_M_SLV                       (0x1 << 14)
+#define RT5625_PCM_CS_MASK                     (0x1 << 8)
+#define RT5625_PCM_CS_SFT                      8
+#define RT5625_PCM_CS_SCLK                     (0x0 << 8)
+#define RT5625_PCM_CS_VSCLK                    (0x1 << 8)
+
+/* Power Management Addition 1 (0x3a) */
+#define RT5625_P_DACL_MIX                      (0x1 << 15)
+#define RT5625_P_DACL_MIX_BIT                  15
+#define RT5625_P_DACR_MIX                      (0x1 << 14)
+#define RT5625_P_DACR_MIX_BIT                  14
+#define RT5625_P_ZCD                           (0x1 << 13)
+#define RT5625_P_ZCD_BIT                       13
+#define RT5625_P_I2S                           (0x1 << 11)
+#define RT5625_P_I2S_BIT                       11
+#define RT5625_P_SPK_AMP                       (0x1 << 10)
+#define RT5625_P_SPK_AMP_BIT                   10
+#define RT5625_P_HPO_AMP                       (0x1 << 9)
+#define RT5625_P_HPO_AMP_BIT                   9
+#define RT5625_P_HPO_ENH                       (0x1 << 8)
+#define RT5625_P_HPO_ENH_BIT                   8
+#define RT5625_P_VDAC_MIX                      (0x1 << 7)
+#define RT5625_P_VDAC_MIX_BIT                  7
+#define RT5625_P_SG_EN                         (0x1 << 6)      
+#define RT5625_P_SG_EN_BIT                     6       
+#define RT5625_P_MB1_SCD                       (0x1 << 5)
+#define RT5625_P_MB1_SCD_BIT                   5
+#define RT5625_P_MB2_SCD                       (0x1 << 4)
+#define RT5625_P_MB2_SCD_BIT                   4
+#define RT5625_P_MB1                           (0x1 << 3)      
+#define RT5625_P_MB1_BIT                       3       
+#define RT5625_P_MB2                           (0x1 << 2)      
+#define RT5625_P_MB2_BIT                       2       
+#define RT5625_P_MAIN_BIAS                     (0x1 << 1)
+#define RT5625_P_MAIN_BIAS_BIT                 1
+#define RT5625_P_DAC_REF                       (0x1)
+#define RT5625_P_DAC_REF_BIT                   0
+
+/* Power Management Addition 2 (0x3c) */
+#define RT5625_P_PLL1                          (0x1 << 15)
+#define RT5625_P_PLL1_BIT                              15
+#define RT5625_P_PLL2                          (0x1 << 14)
+#define RT5625_P_PLL2_BIT                              14
+#define RT5625_P_VREF                          (0x1 << 13)
+#define RT5625_P_VREF_BIT                      13
+#define RT5625_P_OVT                           (0x1 << 12)
+#define RT5625_P_OVT_BIT                       12
+#define RT5625_P_AUX_ADC                       (0x1 << 11)
+#define RT5625_P_AUX_ADC_BIT                   11
+#define RT5625_P_VDAC                          (0x1 << 10)
+#define RT5625_P_VDAC_BIT                      10
+#define RT5625_P_DACL                          (0x1 << 9)
+#define RT5625_P_DACL_BIT                      9
+#define RT5625_P_DACR                          (0x1 << 8)
+#define RT5625_P_DACR_BIT                      8
+#define RT5625_P_ADCL                          (0x1 << 7)
+#define RT5625_P_ADCL_BIT                      7
+#define RT5625_P_ADCR                          (0x1 << 6)
+#define RT5625_P_ADCR_BIT                      6
+#define RT5625_P_HM_L                          (0x1 << 5)
+#define RT5625_P_HM_L_BIT                      5
+#define RT5625_P_HM_R                          (0x1 << 4)
+#define RT5625_P_HM_R_BIT                      4
+#define RT5625_P_SM                            (0x1 << 3)
+#define RT5625_P_SM_BIT                                3
+#define RT5625_P_MM                            (0x1 << 2)
+#define RT5625_P_MM_BIT                        2
+#define RT5625_P_ADCL_RM                       (0x1 << 1)
+#define RT5625_P_ADCL_RM_BIT                   1
+#define RT5625_P_ADCR_RM                       (0x1)
+#define RT5625_P_ADCR_RM_BIT                   0
+
+/* Power Management Addition 3 (0x3e) */
+#define RT5625_P_OSC_EN                        (0x1 << 15)
+#define RT5625_P_OSC_EN_BIT                    15
+#define RT5625_P_AUX_VOL                       (0x1 << 14)
+#define RT5625_P_AUX_VOL_BIT                   14
+#define RT5625_P_SPKL_VOL                      (0x1 << 13)
+#define RT5625_P_SPKL_VOL_BIT                  13
+#define RT5625_P_SPKR_VOL                      (0x1 << 12)
+#define RT5625_P_SPKR_VOL_BIT                  12
+#define RT5625_P_HPL_VOL                       (0x1 << 11)
+#define RT5625_P_HPL_VOL_BIT                   11
+#define RT5625_P_HPR_VOL                       (0x1 << 10)
+#define RT5625_P_HPR_VOL_BIT                   10
+#define RT5625_P_DSP_IF                                (0x1 << 9)
+#define RT5625_P_DSP_IF_BIT                    9
+#define RT5625_P_DSP_I2C                       (0x1 << 8)
+#define RT5625_P_DSP_I2C_BIT                   8
+#define RT5625_P_LV_L                          (0x1 << 7)
+#define RT5625_P_LV_L_BIT                      7
+#define RT5625_P_LV_R                          (0x1 << 6)
+#define RT5625_P_LV_R_BIT                      6
+#define RT5625_P_PH_VOL                        (0x1 << 5)
+#define RT5625_P_PH_VOL_BIT                    5
+#define RT5625_P_PH_ADMIX                      (0x1 << 4)
+#define RT5625_P_PH_ADMIX_BIT                  4
+#define RT5625_P_MIC1_VOL                      (0x1 << 3)
+#define RT5625_P_MIC1_VOL_BIT                  3
+#define RT5625_P_MIC2_VOL                      (0x1 << 2)
+#define RT5625_P_MIC2_VOL_BIT                  2
+#define RT5625_P_MIC1_BST                      (0x1 << 1)
+#define RT5625_P_MIC1_BST_BIT                  1
+#define RT5625_P_MIC2_BST                      (0x1)
+#define RT5625_P_MIC2_BST_BIT                  0
+
+/* General Purpose Control Register 1 (0x40) */
+#define RT5625_SCLK_MASK                       (0x1 << 15)
+#define RT5625_SCLK_SFT                                15
+#define RT5625_SCLK_MCLK                       (0x0 << 15)
+#define RT5625_SCLK_PLL1                       (0x1 << 15)
+#define RT5625_VSCLK_MASK                      (0x1 << 4)
+#define RT5625_VSCLK_SFT                       4
+#define RT5625_VSCLK_PLL2                      (0x0<<4)
+#define RT5625_VSCLK_EXTCLK                    (0x1<<4)
+#define RT5625_SPK_R_MASK                      (0x7 << 1)
+#define RT5625_SPK_R_SFT                       1
+#define RT5625_SPK_R_225V                      (0x0 << 1)
+#define RT5625_SPK_R_200V                      (0x1 << 1)
+#define RT5625_SPK_R_175V                      (0x2 << 1)
+#define RT5625_SPK_R_150V                      (0x3 << 1)
+#define RT5625_SPK_R_125V                      (0x4 << 1)
+#define RT5625_SPK_R_100V                      (0x5 << 1)
+
+/* General Purpose Control Register 2 (0x42) */
+#define RT5625_PLL1_S_MASK                     (0x3 << 12)
+#define RT5625_PLL1_S_SFT                      12
+#define RT5625_PLL1_S_MCLK                     (0x0 << 12)
+#define RT5625_PLL1_S_BCLK                     (0x2 << 12)
+#define RT5625_PLL1_S_VBCLK                    (0x3 << 12)
+
+/* PLL2 Control (0x46) */
+#define RT5625_PLL2_MASK                       (0x1 << 15)
+#define RT5625_PLL2_DIS                                (0x0 << 15)
+#define RT5625_PLL2_EN                         (0x1 << 15)
+#define RT5625_PLL2_R_MASK                     (0x1)
+#define RT5625_PLL2_R_8X                       (0x0)
+#define RT5625_PLL2_R_16X                      (0x1)
+
+/* LDO Control (0x48) */
+#define RT5625_LDO_MASK                        (0x1 << 15)
+#define RT5625_LDO_DIS                         (0x0 << 15)
+#define RT5625_LDO_EN                          (0x1 << 15)
+#define RT5625_LDO_VC_MASK                     (0xf)
+#define RT5625_LDO_VC_1_55V                    (0xf<<0)
+#define RT5625_LDO_VC_1_50V                    (0xe<<0)
+#define RT5625_LDO_VC_1_45V                    (0xd<<0)
+#define RT5625_LDO_VC_1_40V                    (0xc<<0)
+#define RT5625_LDO_VC_1_35V                    (0xb<<0)
+#define RT5625_LDO_VC_1_30V                    (0xa<<0)
+#define RT5625_LDO_VC_1_25V                    (0x9<<0)
+#define RT5625_LDO_VC_1_20V                    (0x8<<0)
+#define RT5625_LDO_VC_1_15V                    (0x7<<0)
+#define RT5625_LDO_VC_1_05V                    (0x6<<0)
+#define RT5625_LDO_VC_1_00V                    (0x5<<0)
+#define RT5625_LDO_VC_0_95V                    (0x4<<0)
+#define RT5625_LDO_VC_0_90V                    (0x3<<0)
+#define RT5625_LDO_VC_0_85V                    (0x2<<0)
+#define RT5625_LDO_VC_0_80V                    (0x1<<0)
+#define RT5625_LDO_VC_0_75V                    (0x0<<0)
+
+/* GPIO Pin Configuration (0x4c) */
+#define RT5625_GPIO_5                          (0x1 << 5)
+#define RT5625_GPIO_4                          (0x1 << 4)
+#define RT5625_GPIO_3                          (0x1 << 3)
+#define RT5625_GPIO_2                          (0x1 << 2)
+#define RT5625_GPIO_1                          (0x1 << 1)
+
+/* MISC Control (0x5e) */
+#define RT5625_FAST_VREF_MASK                  (0x1 << 15)
+#define RT5625_FAST_VREF_EN                    (0x0 << 15)
+#define RT5625_FAST_VREF_DIS                   (0x1 << 15)
+#define RT5625_HP_DEPOP_M2                     (0x1 << 8)
+#define RT5625_HP_DEPOP_M1                     (0x1 << 9)
+#define RT5625_HPL_MUM_DEPOP                   (0x1 << 7)
+#define RT5625_HPR_MUM_DEPOP                   (0x1 << 6)
+#define RT5625_MUM_DEPOP                       (0x1 << 5)
+
+/* Stereo DAC Clock Control 1 (0x60) */
+#define RT5625_BCLK_DIV1_MASK                  (0xf << 12)
+#define RT5625_BCLK_DIV1_1                     (0x0 << 12)
+#define RT5625_BCLK_DIV1_2                     (0x1 << 12)
+#define RT5625_BCLK_DIV1_3                     (0x2 << 12)
+#define RT5625_BCLK_DIV1_4                     (0x3 << 12)
+#define RT5625_BCLK_DIV1_5                     (0x4 << 12)
+#define RT5625_BCLK_DIV1_6                     (0x5 << 12)
+#define RT5625_BCLK_DIV1_7                     (0x6 << 12)
+#define RT5625_BCLK_DIV1_8                     (0x7 << 12)
+#define RT5625_BCLK_DIV1_9                     (0x8 << 12)
+#define RT5625_BCLK_DIV1_10                    (0x9 << 12)
+#define RT5625_BCLK_DIV1_11                    (0xa << 12)
+#define RT5625_BCLK_DIV1_12                    (0xb << 12)
+#define RT5625_BCLK_DIV1_13                    (0xc << 12)
+#define RT5625_BCLK_DIV1_14                    (0xd << 12)
+#define RT5625_BCLK_DIV1_15                    (0xe << 12)
+#define RT5625_BCLK_DIV1_16                    (0xf << 12)
+#define RT5625_BCLK_DIV2_MASK                  (0x7 << 8)
+#define RT5625_BCLK_DIV2_2                     (0x0 << 8)
+#define RT5625_BCLK_DIV2_4                     (0x1 << 8)
+#define RT5625_BCLK_DIV2_8                     (0x2 << 8)
+#define RT5625_BCLK_DIV2_16                    (0x3 << 8)
+#define RT5625_BCLK_DIV2_32                    (0x4 << 8)
+#define RT5625_AD_LRCK_DIV1_MASK               (0xf << 4)
+#define RT5625_AD_LRCK_DIV1_1                  (0x0 << 4)
+#define RT5625_AD_LRCK_DIV1_2                  (0x1 << 4)
+#define RT5625_AD_LRCK_DIV1_3                  (0x2 << 4)
+#define RT5625_AD_LRCK_DIV1_4                  (0x3 << 4)
+#define RT5625_AD_LRCK_DIV1_5                  (0x4 << 4)
+#define RT5625_AD_LRCK_DIV1_6                  (0x5 << 4)
+#define RT5625_AD_LRCK_DIV1_7                  (0x6 << 4)
+#define RT5625_AD_LRCK_DIV1_8                  (0x7 << 4)
+#define RT5625_AD_LRCK_DIV1_9                  (0x8 << 4)
+#define RT5625_AD_LRCK_DIV1_10                 (0x9 << 4)
+#define RT5625_AD_LRCK_DIV1_11                 (0xa << 4)
+#define RT5625_AD_LRCK_DIV1_12                 (0xb << 4)
+#define RT5625_AD_LRCK_DIV1_13                 (0xc << 4)
+#define RT5625_AD_LRCK_DIV1_14                 (0xd << 4)
+#define RT5625_AD_LRCK_DIV1_15                 (0xe << 4)
+#define RT5625_AD_LRCK_DIV1_16                 (0xf << 4)
+#define RT5625_AD_LRCK_DIV2_MASK               (0x7 << 1)
+#define RT5625_AD_LRCK_DIV2_2                  (0x0 << 1)
+#define RT5625_AD_LRCK_DIV2_4                  (0x1 << 1)
+#define RT5625_AD_LRCK_DIV2_8                  (0x2 << 1)
+#define RT5625_AD_LRCK_DIV2_16                 (0x3 << 1)
+#define RT5625_AD_LRCK_DIV2_32                 (0x4 << 1)
+#define RT5625_DA_LRCK_DIV_MASK                (1)
+#define RT5625_DA_LRCK_DIV_32                  (0)
+#define RT5625_DA_LRCK_DIV_64                  (1)
+
+/* Stereo DAC Clock Control 2 (0x62) */
+#define RT5625_DF_DIV1_MASK                    (0xF << 12)
+#define RT5625_DF_DIV1_1                       (0x0 << 12)
+#define RT5625_DF_DIV1_2                       (0x1 << 12)
+#define RT5625_DF_DIV1_3                       (0x2 << 12)
+#define RT5625_DF_DIV1_4                       (0x3 << 12)
+#define RT5625_DF_DIV1_5                       (0x4 << 12)
+#define RT5625_DF_DIV1_6                       (0x5 << 12)
+#define RT5625_DF_DIV1_7                       (0x6 << 12)
+#define RT5625_DF_DIV1_8                       (0x7 << 12)
+#define RT5625_DF_DIV1_9                       (0x8 << 12)
+#define RT5625_DF_DIV1_10                      (0x9 << 12)
+#define RT5625_DF_DIV1_11                      (0xA << 12)
+#define RT5625_DF_DIV1_12                      (0xB << 12)
+#define RT5625_DF_DIV1_13                      (0xC << 12)
+#define RT5625_DF_DIV1_14                      (0xD << 12)
+#define RT5625_DF_DIV1_15                      (0xE << 12)
+#define RT5625_DF_DIV1_16                      (0xF << 12)
+#define RT5625_DF_DIV2_MASK                    (0x7 << 9)
+#define RT5625_DF_DIV2_2                       (0x0 << 9)
+#define RT5625_DF_DIV2_4                       (0x1 << 9)
+#define RT5625_DF_DIV2_8                       (0x2 << 9)
+#define RT5625_DF_DIV2_16                      (0x3 << 9)
+#define RT5625_DF_DIV2_32                      (0x4 << 9)
+#define RT5625_AF_DIV1_MASK                    (0xF << 4)
+#define RT5625_AF_DIV1_1                       (0x0 << 4)
+#define RT5625_AF_DIV1_2                       (0x1 << 4)
+#define RT5625_AF_DIV1_3                       (0x2 << 4)
+#define RT5625_AF_DIV1_4                       (0x3 << 4)
+#define RT5625_AF_DIV1_5                       (0x4 << 4)
+#define RT5625_AF_DIV1_6                       (0x5 << 4)
+#define RT5625_AF_DIV1_7                       (0x6 << 4)
+#define RT5625_AF_DIV1_8                       (0x7 << 4)
+#define RT5625_AF_DIV1_9                       (0x8 << 4)
+#define RT5625_AF_DIV1_10                      (0x9 << 4)
+#define RT5625_AF_DIV1_11                      (0xA << 4)
+#define RT5625_AF_DIV1_12                      (0xB << 4)
+#define RT5625_AF_DIV1_13                      (0xC << 4)
+#define RT5625_AF_DIV1_14                      (0xD << 4)
+#define RT5625_AF_DIV1_15                      (0xE << 4)
+#define RT5625_AF_DIV1_16                      (0xF << 4)
+#define RT5625_AF_DIV2_MASK                    (0x7 << 1)
+#define RT5625_AF_DIV2_1                       (0x0 << 1)
+#define RT5625_AF_DIV2_2                       (0x1 << 1)
+#define RT5625_AF_DIV2_4                       (0x2 << 1)
+#define RT5625_AF_DIV2_8                       (0x3 << 1)
+#define RT5625_AF_DIV2_16                      (0x4 << 1)
+#define RT5625_AF_DIV2_32                      (0x5 << 1)
+
+/* Voice DAC PCM Clock Control 1 (0x64) */
+#define RT5625_VBCLK_DIV1_MASK         (0xF << 12)
+#define RT5625_VBCLK_DIV1_1                    (0x0 << 12)
+#define RT5625_VBCLK_DIV1_2                    (0x1 << 12)
+#define RT5625_VBCLK_DIV1_3                    (0x2 << 12)
+#define RT5625_VBCLK_DIV1_4                    (0x3 << 12)
+#define RT5625_VBCLK_DIV1_5                    (0x4 << 12)
+#define RT5625_VBCLK_DIV1_6                    (0x5 << 12)
+#define RT5625_VBCLK_DIV1_7                    (0x6 << 12)
+#define RT5625_VBCLK_DIV1_8                    (0x7 << 12)
+#define RT5625_VBCLK_DIV1_9                    (0x8 << 12)
+#define RT5625_VBCLK_DIV1_10                   (0x9 << 12)
+#define RT5625_VBCLK_DIV1_11                   (0xA << 12)
+#define RT5625_VBCLK_DIV1_12                   (0xB << 12)
+#define RT5625_VBCLK_DIV1_13                   (0xC << 12)
+#define RT5625_VBCLK_DIV1_14                   (0xD << 12)
+#define RT5625_VBCLK_DIV1_15                   (0xE << 12)
+#define RT5625_VBCLK_DIV1_16                   (0xF << 12)
+#define RT5625_VBCLK_DIV2_MASK         (0x7 << 8)
+#define RT5625_VBCLK_DIV2_2                    (0x0 << 8)
+#define RT5625_VBCLK_DIV2_4                    (0x1 << 8)
+#define RT5625_VBCLK_DIV2_8                    (0x2 << 8)
+#define RT5625_VBCLK_DIV2_16                   (0x3 << 8)
+#define RT5625_VBCLK_DIV2_32                   (0x4 << 8)
+#define RT5625_AD_VLRCK_DIV1_MASK              (0xF << 4)
+#define RT5625_AD_VLRCK_DIV1_1                 (0x0 << 4)
+#define RT5625_AD_VLRCK_DIV1_2                 (0x1 << 4)
+#define RT5625_AD_VLRCK_DIV1_3                 (0x2 << 4)
+#define RT5625_AD_VLRCK_DIV1_4                 (0x3 << 4)
+#define RT5625_AD_VLRCK_DIV1_5                 (0x4 << 4)
+#define RT5625_AD_VLRCK_DIV1_6                 (0x5 << 4)
+#define RT5625_AD_VLRCK_DIV1_7                 (0x6 << 4)
+#define RT5625_AD_VLRCK_DIV1_8                 (0x7 << 4)
+#define RT5625_AD_VLRCK_DIV1_9                 (0x8 << 4)
+#define RT5625_AD_VLRCK_DIV1_10                (0x9 << 4)
+#define RT5625_AD_VLRCK_DIV1_11                (0xA << 4)
+#define RT5625_AD_VLRCK_DIV1_12                (0xB << 4)
+#define RT5625_AD_VLRCK_DIV1_13                (0xC << 4)
+#define RT5625_AD_VLRCK_DIV1_14                (0xD << 4)
+#define RT5625_AD_VLRCK_DIV1_15                (0xE << 4)
+#define RT5625_AD_VLRCK_DIV1_16                (0xF << 4)
+#define RT5625_AD_VLRCK_DIV2_MASK              (0x7 << 1)
+#define RT5625_AD_VLRCK_DIV2_2                 (0x0 << 1)
+#define RT5625_AD_VLRCK_DIV2_4                 (0x1 << 1)
+#define RT5625_AD_VLRCK_DIV2_8                 (0x2 << 1)
+#define RT5625_AD_VLRCK_DIV2_16                (0x3 << 1)
+#define RT5625_AD_VLRCK_DIV2_32                (0x4 << 1)
+#define RT5625_DA_VLRCK_DIV_MASK               (1)
+#define RT5625_DA_VLRCK_DIV_32                 (0)
+#define RT5625_DA_VLRCK_DIV_64                 (1)
+
+/* Psedueo Stereo & Spatial Effect Block Control (0x68) */
+#define RT5625_SP_CTRL_EN                      (0x1 << 15)
+#define RT5625_APF_EN                          (0x1 << 14)
+#define RT5625_PS_EN                           (0x1 << 13)
+#define RT5625_STO_EXP_EN                      (0x1 << 12)
+#define RT5625_SP_3D_G1_MASK                   (0x3 << 10)
+#define RT5625_SP_3D_G1_1_0                    (0x0 << 10)
+#define RT5625_SP_3D_G1_1_5                    (0x1 << 10)
+#define RT5625_SP_3D_G1_2_0                    (0x2 << 10)
+#define RT5625_SP_3D_R1_MASK                   (0x3 << 8)
+#define RT5625_SP_3D_R1_0_0                    (0x0 << 8)
+#define RT5625_SP_3D_R1_0_66                   (0x1 << 8)
+#define RT5625_SP_3D_R1_1_0                    (0x2 << 8)
+#define RT5625_SP_3D_G2_MASK                   (0x3 << 6)
+#define RT5625_SP_3D_G2_1_0                    (0x0 << 6)
+#define RT5625_SP_3D_G2_1_5                    (0x1 << 6)
+#define RT5625_SP_3D_G2_2_0                    (0x2 << 6)
+#define RT5625_SP_3D_R2_MASK                   (0x3 << 4)
+#define RT5625_SP_3D_R2_0_0                    (0x0 << 4)
+#define RT5625_SP_3D_R2_0_66                   (0x1 << 4)
+#define RT5625_SP_3D_R2_1_0                    (0x2 << 4)
+#define RT5625_APF_MASK                        (0x3)
+#define RT5625_APF_48K                         (0x3)
+#define RT5625_APF_44_1K                       (0x2)
+#define RT5625_APF_32K                         (0x1)
+
+/* EQ Control and Status /ADC HPF Control (0x6E) */
+#define RT5625_EN_HW_EQ_BLK                    (0x1 << 15)
+#define RT5625_EQ_SRC_DAC                      (0x0 << 14)
+#define RT5625_EQ_SRC_ADC                      (0x1 << 14)
+#define RT5625_EQ_CHG_EN                       (0x1 << 7)
+#define RT5625_EN_HW_EQ_HPF                    (0x1 << 4)
+#define RT5625_EN_HW_EQ_BP3                    (0x1 << 3)
+#define RT5625_EN_HW_EQ_BP2                    (0x1 << 2)
+#define RT5625_EN_HW_EQ_BP1                    (0x1 << 1)
+#define RT5625_EN_HW_EQ_LPF                    (0x1 << 0)
+
+/* VoDSP Register Command (0x74) */
+#define RT5625_DSP_BUSY_MASK                   (0x1 << 15)
+#define RT5625_DSP_DS_MASK                     (0x1 << 14)
+#define RT5625_DSP_DS_VODSP                    (0x0 << 14)
+#define RT5625_DSP_DS_REG72                    (0x1 << 14)
+#define RT5625_DSP_CLK_MASK                    (0x3 << 12)
+#define RT5625_DSP_CLK_12_288M         (0x0 << 12)
+#define RT5625_DSP_CLK_6_144M                  (0x1 << 12)
+#define RT5625_DSP_CLK_3_072M                  (0x2 << 12)
+#define RT5625_DSP_CLK_2_048M                  (0x3 << 12)
+#define RT5625_DSP_R_EN                                (0x1 << 9)
+#define RT5625_DSP_W_EN                        (0x1 << 8)
+#define RT5625_DSP_CMD_MASK                    (0xff)
+#define RT5625_DSP_CMD_SFT                     0
+#define RT5625_DSP_CMD_MW                      (0x3B)  /* Memory Write */
+#define RT5625_DSP_CMD_MR                      (0x37)  /* Memory Read */
+#define RT5625_DSP_CMD_RR                      (0x60)  /* Register Read */
+#define RT5625_DSP_CMD_RW                      (0x68)  /* Register Write */
+
+
+/* Index(0x20) for Auto Volume Control */
+#define RT5625_AVC_CH_MASK                     (0x1 << 7)
+#define RT5625_AVC_CH_L_CH                     (0x0 << 7)
+#define RT5625_AVC_CH_R_CH                     (0x1 << 7)
+#define RT5625_AVC_GAIN_EN                     (0x1 << 15)
+
+
+
+enum {
+       RT5625_AIF1,
+       RT5625_AIF2,
 };
 
-struct rt56xx_cmd
-{
-       size_t number;
-       struct rt56xx_reg_state __user *buf;            
+/* System Clock Source */
+enum {
+       RT5625_SCLK_S_MCLK,
+       RT5625_SCLK_S_PLL,
 };
 
-
-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 pll_sel {
+       RT5625_PLL_MCLK = 0,
+       RT5625_PLL_MCLK_TO_VSYSCLK,
+       RT5625_PLL_BCLK,
+       RT5625_PLL_VBCLK,
 };
 
-enum AEC_MODE
-{
-       PCM_IN_PCM_OUT = 0,
-       ANALOG_IN_ANALOG_OUT,
-       DAC_IN_ADC_OUT,
-       VODSP_AEC_DISABLE               
+enum {
+       RT5625_AEC_DIS,
+       RT5625_AEC_EN,
 };
 
-enum
-{
-       PCM_MASTER_MODE_A=0,
-       PCM_MASTER_MODE_B,
-       PCM_SLAVE_MODE_A,
-       PCM_SLAVE_MODE_B,
+//#ifdef RT5625_F_SMT_PHO
+enum {
+       RT5625_PLL_DIS,
+       RT5625_PLL_112896_225792,
+       RT5625_PLL_112896_24576,
 };
+//#endif
 
-
-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;
+typedef struct { 
+       unsigned short index;
+       unsigned short value;
+} rt5625_dsp_reg;
 
 #endif
index fda7169c582e5c13e6c9fff5f8cf6901e4553143..9a72e440ceb41482b1c68d23f08695f44d9f2a23 100644 (file)
-/*
- * 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 (codec_dai->ops->hw_params && ((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));
-
-       /*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;
-       }
-
-       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);
-
-       DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %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));
-
-       /* Set up specific audio path audio_mapnects */
-       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
-       //snd_soc_dapm_nc_pin(codec, "HP_L");
-       //snd_soc_dapm_nc_pin(codec, "HP_R");
-       snd_soc_dapm_sync(codec);
-
-       return 0;
-}
-
-static int rt5625_voice_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__);    
-       
-       /* set codec DAI configuration */
-       /*#if defined (CONFIG_SND_CODEC_SOC_SLAVE) 
-       DBG("Enter::%s----codec slave\n",__FUNCTION__);
-
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-       #endif*/
-       //#if defined (CONFIG_SND_CODEC_SOC_MASTER) 
-       DBG("Enter::%s----codec master\n",__FUNCTION__);
-
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
-               SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); 
-       //#endif
-
-       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;
-       }
-
-       snd_soc_dai_set_pll(codec_dai, RT5625_PLL1_FROM_MCLK, pll_out, 24576000);
-
-       /*Set the system clk for codec*/
-       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN);
-
-       if (ret < 0) {
-               printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); 
-               return ret;
-       }
-
-       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
-       return 0;
-}
-
-static struct snd_soc_ops rk29_ops = {
-       .hw_params = rk29_hw_params,
-};
-
-static struct snd_soc_ops rt5625_voice_ops = {
-       .hw_params = rt5625_voice_hw_params,
-};
-
-static struct snd_soc_dai_link rk29_dai[] = {
-       {
-               .name = "RT5625-1",
-               .stream_name = "RT5625 PCM-1",
-               .cpu_dai = &rk29_i2s_dai,
-               .codec_dai = &rt5625_dai[0],
-               .init = rk29_rt5625_init,
-               .ops = &rk29_ops,
-       },
-       {
-               .name = "RT5625-2",
-               .stream_name = "RT5625 PCM-2",
-               .cpu_dai = &rk29_i2s_dai,
-               .codec_dai = &rt5625_dai[1],
-               .init = rk29_rt5625_init,
-               .ops = &rt5625_voice_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");
+/*\r
+ * rk29_rt5625.c  --  SoC audio for rockchip\r
+ *\r
+ * Driver for rockchip rt5625 audio\r
+ *\r
+ *  This program is free software; you can redistribute  it and/or modify it\r
+ *  under  the terms of  the GNU General  Public License as published by the\r
+ *  Free Software Foundation;  either version 2 of the  License, or (at your\r
+ *  option) any later version.\r
+ *\r
+ *\r
+ */\r
+\r
+#include <linux/module.h>\r
+#include <linux/device.h>\r
+#include <sound/core.h>\r
+#include <sound/pcm.h>\r
+#include <sound/soc.h>\r
+#include <sound/soc-dapm.h>\r
+#include <asm/io.h>\r
+#include <mach/hardware.h>\r
+#include <mach/rk29_iomap.h>\r
+#include "../codecs/rt5625.h"\r
+#include "rk29_pcm.h"\r
+#include "rk29_i2s.h"\r
+\r
+#if 1\r
+#define        DBG(x...)       printk(KERN_INFO x)\r
+#else\r
+#define        DBG(x...)\r
+#endif\r
+\r
+static int rk29_hw_params(struct snd_pcm_substream *substream,\r
+       struct snd_pcm_hw_params *params)\r
+{\r
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
+       unsigned int pll_out = 0;\r
+       int ret;\r
+\r
+       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    \r
+       /*by Vincent Hsiung for EQ Vol Change*/\r
+       #define HW_PARAMS_FLAG_EQVOL_ON 0x21\r
+       #define HW_PARAMS_FLAG_EQVOL_OFF 0x22\r
+       if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF)))\r
+       {\r
+               ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent\r
+               DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
+       } else {\r
+                \r
+               /* set codec DAI configuration */\r
+               #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) \r
+\r
+               ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
+                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
+               #endif  \r
+               #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) \r
+\r
+               ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
+                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
+               #endif\r
+               if (ret < 0)\r
+                       return ret; \r
+\r
+               /* set cpu DAI configuration */\r
+               #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) \r
+               ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
+                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);\r
+               #endif  \r
+               #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) \r
+               ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
+                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); \r
+               #endif          \r
+               if (ret < 0)\r
+                       return ret;\r
+       }\r
+\r
+       switch(params_rate(params)) {\r
+               case 8000:\r
+               case 16000:\r
+               case 24000:\r
+               case 32000:\r
+               case 48000:\r
+                       pll_out = 12288000;\r
+                       break;\r
+               case 11025:\r
+               case 22050:\r
+               case 44100:\r
+                       pll_out = 11289600;\r
+                       break;\r
+               default:\r
+                       DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+                       return -EINVAL;\r
+                       break;\r
+       }\r
+\r
+       DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+\r
+       /*Set the system clk for codec*/\r
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);\r
+       if (ret < 0)\r
+       {\r
+                      DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
+               return ret;\r
+       }\r
+\r
+       snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
+       snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);\r
+       snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);\r
+\r
+       DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));\r
\r
+       return 0;\r
+}\r
+\r
+static int rt5625_voice_hw_params(struct snd_pcm_substream *substream,\r
+       struct snd_pcm_hw_params *params)\r
+{\r
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
+       unsigned int pll_out = 0;\r
+       int ret;\r
+\r
+       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    \r
+       \r
+       /* set codec DAI configuration */\r
+       //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) \r
+       DBG("Enter::%s----codec slave\n",__FUNCTION__);\r
+\r
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
+                               SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
+       /*#endif\r
+       //#if defined (CONFIG_SND_CODEC_SOC_MASTER) \r
+       DBG("Enter::%s----codec master\n",__FUNCTION__);\r
+\r
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
+               SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
+       #endif*/\r
+\r
+       switch(params_rate(params)) {\r
+               case 8000:\r
+               case 16000:\r
+               case 24000:\r
+               case 32000:\r
+               case 48000:\r
+                       pll_out = 12288000;\r
+                       break;\r
+               case 11025:\r
+               case 22050:\r
+               case 44100:\r
+                       pll_out = 11289600;\r
+                       break;\r
+               default:\r
+                       DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+                       return -EINVAL;\r
+                       break;\r
+       }\r
+\r
+       snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000);\r
+\r
+       /*Set the system clk for codec*/\r
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN);\r
+\r
+       if (ret < 0) {\r
+               printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
+               return ret;\r
+       }\r
+\r
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
\r
+       return 0;\r
+}\r
+\r
+static struct snd_soc_ops rk29_ops = {\r
+       .hw_params = rk29_hw_params,\r
+};\r
+\r
+static struct snd_soc_ops rt5625_voice_ops = {\r
+       .hw_params = rt5625_voice_hw_params,\r
+};\r
+\r
+static struct snd_soc_dai_link rk29_dai[] = {\r
+       {\r
+               .name = "RT5625 I2S1",\r
+               .stream_name = "RT5625 PCM",\r
+               .codec_name = "rt5625.0-001f",\r
+               .platform_name = "rockchip-audio",\r
+               .cpu_dai_name = "rk29_i2s.0",\r
+               .codec_dai_name = "rt5625-aif1",\r
+               .ops = &rk29_ops,\r
+       },\r
+       {\r
+               .name = "RT5625 I2S2",\r
+               .stream_name = "RT5625 PCM",\r
+               .codec_name = "rt5625.0-001f",\r
+               .platform_name = "rockchip-audio",\r
+               .cpu_dai_name = "rk29_i2s.0",\r
+               .codec_dai_name = "rt5625-aif2",\r
+               .ops = &rt5625_voice_ops,\r
+       },\r
+};\r
+\r
+static struct snd_soc_card snd_soc_card_rk29 = {\r
+       .name = "RK29_RT5625",\r
+       .dai_link = rk29_dai,\r
+       .num_links = 2,\r
+};\r
+\r
+static struct platform_device *rk29_snd_device;\r
+\r
+static int __init audio_card_init(void)\r
+{\r
+       int ret =0;\r
+\r
+       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
+\r
+       rk29_snd_device = platform_device_alloc("soc-audio", -1);\r
+       if (!rk29_snd_device) {\r
+                 printk("platform device allocation failed\n");\r
+                 return -ENOMEM;\r
+       }\r
+\r
+       platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);\r
+       ret = platform_device_add(rk29_snd_device);\r
+       if (ret) {\r
+               printk("platform device add failed\n");\r
+\r
+               platform_device_put(rk29_snd_device);\r
+               return ret;\r
+       }\r
+               \r
+        return ret;\r
+}\r
+\r
+static void __exit audio_card_exit(void)\r
+{\r
+       platform_device_unregister(rk29_snd_device);\r
+}\r
+\r
+module_init(audio_card_init);\r
+module_exit(audio_card_exit);\r
+/* Module information */\r
+MODULE_AUTHOR("rockchip");\r
+MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");\r
+MODULE_LICENSE("GPL");\r