update wm8994 driver
author陈金泉 <chenjq@rock-chips.com>
Mon, 8 Aug 2011 08:47:29 +0000 (16:47 +0800)
committer陈金泉 <chenjq@rock-chips.com>
Mon, 8 Aug 2011 08:47:29 +0000 (16:47 +0800)
arch/arm/configs/rk29_phonepadsdk_defconfig
arch/arm/mach-rk29/board-rk29phonepadsdk.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/rk29/Kconfig

index 55b92af5a0c8d2a081a9d2ba09a84fbe938f3d6d..cafb2b439fb12f4fbcbdde210266229c28fc9c30 100644 (file)
@@ -1510,6 +1510,20 @@ CONFIG_SND_RK29_SOC_I2S_8CH=y
 # CONFIG_SND_RK29_SOC_alc5631 is not set
 # CONFIG_SND_RK29_SOC_RT5625 is not set
 CONFIG_SND_RK29_SOC_WM8994=y
+# CONFIG_SND_INSIDE_EARPIECE is not set
+# CONFIG_SND_OUTSIDE_EARPIECE is not set
+CONFIG_SND_NO_EARPIECE=y
+CONFIG_SND_BB_NORMAL_INPUT=y
+# CONFIG_SND_BB_DIFFERENTIAL_INPUT is not set
+CONFIG_WM8994_SPEAKER_INCALL_VOL=15
+CONFIG_WM8994_SPEAKER_INCALL_MIC_VOL=15
+CONFIG_WM8994_SPEAKER_NORMAL_VOL=15
+CONFIG_WM8994_HEADSET_INCALL_VOL=6
+CONFIG_WM8994_HEADSET_INCALL_MIC_VOL=30
+CONFIG_WM8994_HEADSET_NORMAL_VOL=15
+CONFIG_WM8994_BT_INCALL_VOL=30
+CONFIG_WM8994_BT_INCALL_MIC_VOL=-20
+CONFIG_WM8994_RECORDER_VOL=40
 # CONFIG_SND_RK29_SOC_CS42L52 is not set
 # CONFIG_SND_RK29_CODEC_SOC_MASTER is not set
 CONFIG_SND_RK29_CODEC_SOC_SLAVE=y
index 5e10e9a6c34c5c2d490f4cbfbdcbbdb14912a3f5..e1c21f3c836b45cf61bbd0ad279c30c42cc1b074 100755 (executable)
@@ -764,6 +764,13 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = {
                .flags                  = 0,
        },
 #endif
+#if defined (CONFIG_SND_SOC_WM8994)
+        {
+                .type                   = "wm8994",
+                .addr           = 0x1A,
+                .flags                  = 0,
+        },
+#endif
 #if defined (CONFIG_BATTERY_STC3100)
        {
                .type                   = "stc3100",
index e4e8dc12fd45d0e07236dc47778911703f14a800..b4d1cf8427d29eae0d049113b90e7660a7fb1c61 100755 (executable)
@@ -26,8 +26,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
-#include <linux/wakelock.h>
-#include <linux/earlysuspend.h>
 
 #include <mach/iomux.h>
 #include <mach/gpio.h>
 #include "wm8994.h"
 #include <linux/miscdevice.h>
 #include <linux/circ_buf.h>
-#include <linux/mfd/wm8994/core.h>
-#include <linux/mfd/wm8994/registers.h>
-#include <linux/mfd/wm8994/pdata.h>
-#include <linux/mfd/wm8994/gpio.h>
 
 #define WM8994_PROC
 #ifdef WM8994_PROC
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/vmalloc.h>
-char debug_write_read = 0;
 #endif
 
-
-/* If digital BB is used,open this define. 
- Define what kind of digital BB is used. */
+/* If digital BB is used,open this define. */
 //#define PCM_BB
+
+/* Define what kind of digital BB is used. */
 #ifdef PCM_BB
 #define TD688_MODE  
 //#define MU301_MODE
@@ -65,39 +57,44 @@ char debug_write_read = 0;
 #define DBG(x...) do { } while (0)
 #endif
 
-static struct snd_soc_codec *wm8994_codec;
+#define wm8994_mic_VCC 0x0010
+#define WM8994_DELAY 50
 
+/* For audio stream type */
+#define VOICE_CALL     0
+#define BLUETOOTH_SCO  6
 
+/* For wm8994 delay work type  */
+#define WM8994_WORK_NULL       0
+#define WM8994_WORK_FIRSTINCALL        1
+#define WM8994_WORK_SHUTDOWN   2
+#define WM8994_WORK_STARTUP    3
 
 enum wm8994_codec_mode
 {
-  wm8994_AP_to_headset,
-  wm8994_AP_to_speakers,
-  wm8994_AP_to_speakers_and_headset,
-  wm8994_recorder_and_AP_to_headset,
-  wm8994_recorder_and_AP_to_speakers,
-  wm8994_FM_to_headset,
-  wm8994_FM_to_headset_and_record,
-  wm8994_FM_to_speakers,
-  wm8994_FM_to_speakers_and_record,
-  wm8994_handsetMIC_to_baseband_to_headset,
-  wm8994_mainMIC_to_baseband_to_headset,
-  wm8994_handsetMIC_to_baseband_to_headset_and_record,
-  wm8994_mainMIC_to_baseband_to_earpiece,
-  wm8994_mainMIC_to_baseband_to_earpiece_and_record,
-  wm8994_mainMIC_to_baseband_to_speakers,
-  wm8994_mainMIC_to_baseband_to_speakers_and_record,
-  wm8994_BT_baseband,
-  wm8994_BT_baseband_and_record,
-  null
-};
-/* wm8994_current_mode:save current wm8994 mode */
-unsigned char wm8994_current_mode=null;
-enum stream_type_wm8994
-{
-       VOICE_CALL      =0,
-       BLUETOOTH_SCO   =6,
+       wm8994_AP_to_headset,
+       wm8994_AP_to_speakers,
+       wm8994_AP_to_speakers_and_headset,
+       wm8994_recorder_and_AP_to_headset,
+       wm8994_recorder_and_AP_to_speakers,
+       wm8994_FM_to_headset,
+       wm8994_FM_to_headset_and_record,
+       wm8994_FM_to_speakers,
+       wm8994_FM_to_speakers_and_record,
+       wm8994_handsetMIC_to_baseband_to_headset,
+       wm8994_mainMIC_to_baseband_to_headset,
+       wm8994_handsetMIC_to_baseband_to_headset_and_record,
+       wm8994_mainMIC_to_baseband_to_earpiece,
+       wm8994_mainMIC_to_baseband_to_earpiece_and_record,
+       wm8994_mainMIC_to_baseband_to_speakers,
+       wm8994_mainMIC_to_baseband_to_speakers_and_record,
+       wm8994_BT_baseband,
+       wm8994_BT_baseband_and_record,
+       null,
+       wm8994_powerdown_speakers,
+       wm8994_powerdown_headset
 };
+
 /* For voice device route set, add by phc  */
 enum VoiceDeviceSwitch
 {
@@ -126,235 +123,173 @@ enum VoiceDeviceSwitch
        ALL_CLOSED
 };
 
-//5:0 000000 0x3F
-unsigned short headset_vol_table[6]    ={0x012D,0x0133,0x0136,0x0139,0x013B,0x013D};
-unsigned short speakers_vol_table[6]   ={0x012D,0x0133,0x0136,0x0139,0x013B,0x013D};
-unsigned short earpiece_vol_table[6]   ={0x0127,0x012D,0x0130,0x0135,0x0139,0x013D};//normal
-unsigned short BT_vol_table[16]                ={0x01DB,0x01DC,0x01DD,0x01DE,0x01DF,0x01E0,
-                                                                               0x01E1,0x01E2,0x01E3,0x01E4,0x01E5,0x01E6,
-                                                                               0x01E7,0x01E8,0x01E9,0x01EA};
+static struct i2c_client *wm8994_client;
+static bool isWM8994SetChannel = true, isSetChannelErr = false;
+static void wm8994_work(struct work_struct *work);
+static struct workqueue_struct *wm8994_workq;
+static DECLARE_DELAYED_WORK(delayed_work, wm8994_work);
+static int reg_send_data(struct i2c_client *client, unsigned short *reg, unsigned short *data, u32 scl_rate);
+static int reg_recv_data(struct i2c_client *client, unsigned short *reg, unsigned short *buf, u32 scl_rate);
+static void wm8994_set_volume(unsigned char wm8994_mode,unsigned char volume,unsigned char max_volume);
+static void wm8994_set_channel_vol(void);
+//bool isHSKey_MIC(void);
+/* wm8994_current_mode:save current wm8994 mode */
+static unsigned char wm8994_current_mode = null, wm8994_work_type = WM8994_WORK_NULL;
+
+#ifdef WM8994_PROC
+static char wm8994_current_route = SPEAKER_NORMAL;
+#endif
+
+#define WM_EN_PIN RK29_PIN5_PA1
+#define call_maxvol 5
+#define BT_call_maxvol 15
+
+/* call_vol:  save all kinds of system volume value. */
+unsigned char call_vol = 5, BT_call_vol = 15;
+int vol;
+//static unsigned short headset_vol_table[6]   ={0x012D,0x0133,0x0136,0x0139,0x013B,0x013D};
+//static unsigned short headset_vol_table[6]   ={0x012D,0x013B,0x013C,0x013D,0x013E,0x013F};
+static unsigned short speakers_vol_table[6]    ={0x012D,0x0133,0x0136,0x0139,0x013B,0x013D};
+#ifdef CONFIG_RAHO_CTA
+static unsigned short earpiece_vol_table[6]    ={0x0127,0x012D,0x0130,0x0135,0x0137,0x0135};//for cta
+static unsigned short headset_vol_table[6]   ={0x012D,0x013B,0x013C,0x013D,0x013E,0x013F};
+#elif defined(CONFIG_MACH_K300) || defined(CONFIG_MACH_BENGO_V2) || defined(CONFIG_MACH_USG1)
+static unsigned short earpiece_vol_table[6]    ={0x013a,0x013b,0x013c,0x013d,0x013e,0x013F};//giayee.
+static unsigned short headset_vol_table[6]   ={0x012D,0x013B,0x013C,0x013D,0x013E,0x013F};
+#elif defined(CONFIG_MACH_Z5_V2)
+static unsigned short earpiece_vol_table[6]    ={0x0120,0x0126,0x0129,0x012E,0x0132,0x0136};//normal
+unsigned short headset_vol_table[6]   ={0x0116,0x0119,0x011C,0x011F,0x0128,0x012A}; //normal
+#else
+static unsigned short earpiece_vol_table[6]    ={0x0127,0x012D,0x0130,0x0135,0x0139,0x013D};//normal
+static unsigned short headset_vol_table[6]   ={0x012D,0x013B,0x013C,0x013D,0x013E,0x013F};
+#endif
+static unsigned short BT_vol_table[16]         ={0x01DB,0x01DC,0x01DD,0x01DE,0x01DF,0x01E0,
+                                       0x01E1,0x01E2,0x01E3,0x01E4,0x01E5,0x01E6,
+                                       0x01E7,0x01E8,0x01E9,0x01EA};
+
+int speaker_incall_vol = CONFIG_WM8994_SPEAKER_INCALL_VOL,
+speaker_incall_mic_vol = CONFIG_WM8994_SPEAKER_INCALL_MIC_VOL,
+speaker_normal_vol = CONFIG_WM8994_SPEAKER_NORMAL_VOL,
+#if defined(CONFIG_SND_INSIDE_EARPIECE)||defined(CONFIG_SND_OUTSIDE_EARPIECE)
+earpiece_incall_vol = CONFIG_WM8994_EARPIECE_INCALL_VOL,
+#endif
+headset_incall_vol = CONFIG_WM8994_HEADSET_INCALL_VOL,
+headset_incall_mic_vol = CONFIG_WM8994_HEADSET_INCALL_MIC_VOL,
+headset_normal_vol = CONFIG_WM8994_HEADSET_NORMAL_VOL,
+BT_incall_vol = CONFIG_WM8994_BT_INCALL_VOL,
+BT_incall_mic_vol = CONFIG_WM8994_BT_INCALL_MIC_VOL,
+recorder_vol = CONFIG_WM8994_RECORDER_VOL,
+bank_vol[6] = {0,0,-3,3,-6,3};
 
+/*
+ * wm8994 register cache
+ * We can't read the WM8994 register space when we
+ * are using 2 wire for device control, so we cache them instead.
+ */
+static const u16 wm8994_reg[] = {
+       0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
+       0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
+       0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
+       0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
+       0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
+       0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
+       0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
+       0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
+       0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
+       0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
+       0x0079, 0x0079, 0x0079,          /* 40 */
+};
 
 /* codec private data */
 struct wm8994_priv {
-       struct mutex io_lock;
-       struct mutex route_lock;
-       int sysclk;
-       int mclk;
-       int fmt;//master or salve
-       int rate;//Sampling rate
+       unsigned int sysclk;
        struct snd_soc_codec codec;
-       struct snd_kcontrol *kcontrol;//The current working path
-       char RW_status;                         //ERROR = -1, TRUE = 0;
-       struct wm8994_pdata *pdata;
-       
-       struct delayed_work wm8994_delayed_work;
-       int work_type;
-
-       unsigned int playback_active:1;
-       unsigned int capture_active:1;
-       /* call_vol:  save all kinds of system volume value. */
-       unsigned char call_vol;
-       unsigned char BT_call_vol;      
-
-       struct wake_lock        wm8994_on_wake;
+       struct snd_pcm_hw_constraint_list *sysclk_constraints;
+       u16 reg_cache[WM8994_NUM_REG];
 };
 
-int reg_send_data(struct i2c_client *client, unsigned short *reg, unsigned short *data, u32 scl_rate)
-{
-       int ret;
-       struct i2c_adapter *adap = client->adapter;
-       struct i2c_msg msg;
-       char tx_buf[4];
-
-       memcpy(tx_buf, reg, 2);
-       memcpy(tx_buf+2, data, 2);
-       msg.addr = client->addr;
-       msg.buf = tx_buf;
-       msg.len = 4;
-       msg.flags = client->flags;
-       msg.scl_rate = scl_rate;
-       msg.read_type = 0;
-       ret = i2c_transfer(adap, &msg, 1);
-
-       return ret;
-}
-
-int reg_recv_data(struct i2c_client *client, unsigned short *reg, unsigned short *buf, u32 scl_rate)
+bool wm8994_set_status(void)
 {
-       int ret;
-       struct i2c_adapter *adap = client->adapter;
-       struct i2c_msg msgs[2];
-
-       msgs[0].addr = client->addr;
-       msgs[0].buf = (char *)reg;
-       msgs[0].flags = client->flags;
-       msgs[0].len = 2;
-       msgs[0].scl_rate = scl_rate;
-       msgs[0].read_type = 2;
-
-       msgs[1].addr = client->addr;
-       msgs[1].buf = (char *)buf;
-       msgs[1].flags = client->flags | I2C_M_RD;
-       msgs[1].len = 2;
-       msgs[1].scl_rate = scl_rate;
-       msgs[1].read_type = 2;
-
-       ret = i2c_transfer(adap, msgs, 2);
-
-       return ret;
+        return isWM8994SetChannel;
 }
 
-int wm8994_set_status(void)
-{
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;        
-       int ret = 1;
-       mutex_lock(&wm8994->route_lock);
-       
-       if(wm8994->work_type == SNDRV_PCM_TRIGGER_SUSPEND)
-               ret = -2;
-       
-       mutex_unlock(&wm8994->route_lock);      
-       return ret;
-}
 EXPORT_SYMBOL_GPL(wm8994_set_status);
 
 static int wm8994_read(unsigned short reg,unsigned short *value)
 {
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
-       
        unsigned short regs=((reg>>8)&0x00FF)|((reg<<8)&0xFF00),values;
        char i = 2;
-       mutex_lock(&wm8994->io_lock);
-       if(wm8994->RW_status == ERROR) goto out;
 
-       while(i > 0)
-       {
+       if (isSetChannelErr)return -EIO;
+
+       while(i > 0) {
                i--;
-               if (reg_recv_data(wm8994_codec->control_data,&regs,&values,400000) > 0)
-               {
+               if (reg_recv_data(wm8994_client,&regs,&values,400000) > 0) {
                        *value=((values>>8)& 0x00FF)|((values<<8)&0xFF00);
-               #ifdef WM8994_PROC      
-                       if(debug_write_read != 0)
-                               DBG("%s:0x%04x = 0x%04x",__FUNCTION__,reg,*value);
-               #endif
-                       mutex_unlock(&wm8994->io_lock);
                        return 0;
                }
        }
+       isSetChannelErr = true;
        
-       wm8994->RW_status = ERROR;      
        printk("%s---line->%d:Codec read error! reg = 0x%x , value = 0x%x\n",__FUNCTION__,__LINE__,reg,*value);
-out:   
-       mutex_unlock(&wm8994->io_lock);
+
        return -EIO;
 }
        
 static int wm8994_write(unsigned short reg,unsigned short value)
 {
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
-
        unsigned short regs=((reg>>8)&0x00FF)|((reg<<8)&0xFF00),values=((value>>8)&0x00FF)|((value<<8)&0xFF00);
        char i = 2;
-       
-       mutex_lock(&wm8994->io_lock);
 
-       if(wm8994->RW_status == ERROR) goto out;
+       if (isSetChannelErr)return -EIO;
 
-#ifdef WM8994_PROC     
-       if(debug_write_read != 0)
-               DBG("%s:0x%04x = 0x%04x\n",__FUNCTION__,reg,value);
-#endif         
-       while(i > 0)
-       {
+       while(i > 0) {
                i--;
-               if (reg_send_data(wm8994_codec->control_data,&regs,&values,400000) > 0) 
-               {
-                       mutex_unlock(&wm8994->io_lock);
+               if (reg_send_data(wm8994_client,&regs,&values,400000) > 0) {
+                       if (reg == 0x302) {
+                               wm8994_read(0x406, &values);
+                               wm8994_write(0x406, values);
+                               wm8994_read(reg, &values);
+
+                               DBG("read 0x302 = 0x%x write 0x302 = 0x%x \n", values, value);
+
+                               if (values != value)
+                                       isSetChannelErr = true;
+                       }
                        return 0;
-               }       
+               }
        }
-       
-       wm8994->RW_status = ERROR;
+       isSetChannelErr = true;
+
        printk("%s---line->%d:Codec write error! reg = 0x%x , value = 0x%x\n",__FUNCTION__,__LINE__,reg,value);
 
-out:   
-       mutex_unlock(&wm8994->io_lock);
        return -EIO;
 }
 
-static void wm8994_set_volume(unsigned char wm8994_mode,unsigned char volume,unsigned char max_volume)
+static void wm8994_codec_first_incall(void)
 {
-       unsigned short lvol=0,rvol=0;
-//     DBG("%s::volume = %d \n",__FUNCTION__,volume);
+       if (wm8994_current_mode == wm8994_AP_to_speakers_and_headset ||
+       wm8994_current_mode == wm8994_recorder_and_AP_to_headset ||
+       wm8994_current_mode == wm8994_recorder_and_AP_to_speakers ||
+       wm8994_current_mode == wm8994_powerdown_headset ||
+       wm8994_current_mode == wm8994_powerdown_speakers) {
 
-       if(volume>max_volume)
-               volume=max_volume;
-       
-       switch(wm8994_mode)
-       {
-               case wm8994_handsetMIC_to_baseband_to_headset_and_record:
-               case wm8994_handsetMIC_to_baseband_to_headset:
-               case wm8994_mainMIC_to_baseband_to_headset:
-                       wm8994_read(0x001C, &lvol);
-                       wm8994_read(0x001D, &rvol);
-                       //HPOUT1L_VOL bit 0~5 /-57dB to +6dB in 1dB steps
-                       wm8994_write(0x001C, (lvol&~0x003f)|headset_vol_table[volume]); 
-                       //HPOUT1R_VOL bit 0~5 /-57dB to +6dB in 1dB steps
-                       wm8994_write(0x001D, (rvol&~0x003f)|headset_vol_table[volume]); 
-                       break;
-               case wm8994_mainMIC_to_baseband_to_speakers_and_record:
-               case wm8994_mainMIC_to_baseband_to_speakers:
-                       wm8994_read(0x0026, &lvol);
-                       wm8994_read(0x0027, &rvol);
-                       //SPKOUTL_VOL bit 0~5 /-57dB to +6dB in 1dB steps
-                       wm8994_write(0x0026, (lvol&~0x003f)|speakers_vol_table[volume]);
-                       //SPKOUTR_VOL bit 0~5 /-57dB to +6dB in 1dB steps
-                       wm8994_write(0x0027, (rvol&~0x003f)|speakers_vol_table[volume]);
-                       break;
-               case wm8994_mainMIC_to_baseband_to_earpiece:
-               case wm8994_mainMIC_to_baseband_to_earpiece_and_record:
-                       wm8994_read(0x0020, &lvol);
-                       wm8994_read(0x0021, &rvol);
-                       //MIXOUTL_VOL bit 0~5 /-57dB to +6dB in 1dB steps
-                       wm8994_write(0x0020, (lvol&~0x003f)|earpiece_vol_table[volume]);
-                       //MIXOUTR_VOL bit 0~5 /-57dB to +6dB in 1dB steps
-                       wm8994_write(0x0021, (rvol&~0x003f)|earpiece_vol_table[volume]);
-                       break;
-               case wm8994_BT_baseband:
-               case wm8994_BT_baseband_and_record:
-                       //bit 0~4 /-16.5dB to +30dB in 1.5dB steps
-                       DBG("BT_vol_table[volume] = 0x%x\n",BT_vol_table[volume]);
-                       wm8994_write(0x0500, BT_vol_table[volume]);
-                       wm8994_write(0x0501, 0x0100);           
-                       break;
-               default:
-               //      DBG("Set all volume\n");
-                       wm8994_read(0x001C, &lvol);
-                       wm8994_read(0x001D, &rvol);
-                       wm8994_write(0x001C, (lvol&~0x003f)|headset_vol_table[volume]); 
-                       wm8994_write(0x001D, (rvol&~0x003f)|headset_vol_table[volume]); 
-                       wm8994_read(0x0026, &lvol);
-                       wm8994_read(0x0027, &rvol);
-                       wm8994_write(0x0026, (lvol&~0x003f)|speakers_vol_table[volume]);
-                       wm8994_write(0x0027, (rvol&~0x003f)|speakers_vol_table[volume]);        
-                       wm8994_read(0x0020, &lvol);
-                       wm8994_read(0x0021, &rvol);
-                       wm8994_write(0x0020, (lvol&~0x003f)|earpiece_vol_table[volume]);
-                       wm8994_write(0x0021, (rvol&~0x003f)|earpiece_vol_table[volume]);
-                       break;
+               cancel_delayed_work_sync(&delayed_work);
+
+               wm8994_work_type = WM8994_WORK_FIRSTINCALL;
+               queue_delayed_work(wm8994_workq, &delayed_work,
+                       msecs_to_jiffies(1500));
        }
 }
 
 static void wm8994_set_all_mute(void)
 {
        int i;
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
 
-       if(wm8994->call_vol < 0)
+       if (call_vol < 0)
                return;
 
-       for (i = wm8994->call_vol; i >= 0; i--)        
+       for (i = call_vol; i >= 0; i-=2)        
                wm8994_set_volume(null,i,call_maxvol);
 
 }
@@ -362,461 +297,224 @@ static void wm8994_set_all_mute(void)
 static void wm8994_set_level_volume(void)
 {
        int i;
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
        
-       for (i = 0; i <= wm8994->call_vol; i++)
+       for (i = 0; i <= call_vol; i++) {
                wm8994_set_volume(wm8994_current_mode,i,call_maxvol);
-       
-}
-
-static void PA_ctrl(unsigned char ctrl)
-{
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
-       struct wm8994_pdata *pdata = wm8994->pdata;
-       
-       if(pdata->PA_control_pin > 0)
-       {
-               if(ctrl == GPIO_HIGH)
-               {
-                       DBG("enable PA_control\n");
-                       gpio_request(pdata->PA_control_pin, NULL);              //AUDIO_PA_ON    
-                       gpio_direction_output(pdata->PA_control_pin,GPIO_HIGH);                 
-                       gpio_free(pdata->PA_control_pin);
-               }
-               else
-               {
-                       DBG("disable PA_control\n");
-                       gpio_request(pdata->PA_control_pin, NULL);              //AUDIO_PA_ON    
-                       gpio_direction_output(pdata->PA_control_pin,GPIO_LOW);          
-                       gpio_free(pdata->PA_control_pin);                       
-               }
        }
 }
 
-/* The size in bits of the FLL divide multiplied by 10
- * to allow rounding later */
-#define FIXED_FLL_SIZE ((1 << 16) * 10)
-
-struct fll_div {
-       u16 outdiv;
-       u16 n;
-       u16 k;
-       u16 clk_ref_div;
-       u16 fll_fratio;
-};
+#define wm8994_reset() wm8994_set_all_mute();\
+                                               wm8994_write(WM8994_RESET, 0)
 
-static int wm8994_get_fll_config(struct fll_div *fll,
-                                int freq_in, int freq_out)
+static void AP_to_headset(void)
 {
-       u64 Kpart;
-       unsigned int K, Ndiv, Nmod;
-
-//     DBG("FLL input=%dHz, output=%dHz\n", freq_in, freq_out);
-
-       /* Scale the input frequency down to <= 13.5MHz */
-       fll->clk_ref_div = 0;
-       while (freq_in > 13500000) {
-               fll->clk_ref_div++;
-               freq_in /= 2;
-
-               if (fll->clk_ref_div > 3)
-                       return -EINVAL;
-       }
-//     DBG("CLK_REF_DIV=%d, Fref=%dHz\n", fll->clk_ref_div, freq_in);//0 12m
-
-       /* Scale the output to give 90MHz<=Fvco<=100MHz */
-       fll->outdiv = 3;
-       while (freq_out * (fll->outdiv + 1) < 90000000) {
-               fll->outdiv++;
-               if (fll->outdiv > 63)
-                       return -EINVAL;
-       }
-       freq_out *= fll->outdiv + 1;
-//     DBG("OUTDIV=%d, Fvco=%dHz\n", fll->outdiv, freq_out);//8 98.304MHz
+       DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if (freq_in > 1000000) {
-               fll->fll_fratio = 0;
-       } else {
-               fll->fll_fratio = 3;
-               freq_in *= 8;
-       }
-//     DBG("FLL_FRATIO=%d, Fref=%dHz\n", fll->fll_fratio, freq_in);//0 12M
+       if (wm8994_current_mode == wm8994_AP_to_headset)return;
+       wm8994_current_mode = wm8994_AP_to_headset;
+       wm8994_reset();
+       msleep(WM8994_DELAY);
 
-       /* Now, calculate N.K */
-       Ndiv = freq_out / freq_in;
+       wm8994_write(0x700, 0xA101);
+       wm8994_write(0x39,  0x006C);
+       wm8994_write(0x01,  0x0023);
+       wm8994_write(0x200, 0x0000);
+       mdelay(WM8994_DELAY);
 
-       fll->n = Ndiv;
-       Nmod = freq_out % freq_in;
-//     DBG("Nmod=%d\n", Nmod);
+       wm8994_write(0x220, 0x0000);
+       wm8994_write(0x221, 0x0700);
+       wm8994_write(0x222, 0x3126);
+       wm8994_write(0x223, 0x0100);
 
-       /* Calculate fractional part - scale up so we can round. */
-       Kpart = FIXED_FLL_SIZE * (long long)Nmod;
+       wm8994_write(0x220, 0x0004);
+       msleep(10);
+       wm8994_write(0x220, 0x0005);
+       msleep(5);
 
-       do_div(Kpart, freq_in);
+       wm8994_write(0x200, 0x0010);
+       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x210, 0x0083); // SR=48KHz
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
+       wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
+       wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
+       wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
+       wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
+       wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
+       wm8994_write(0x300, 0x4010); // i2s 16 bits
+#endif
+       wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
+  
+       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1/ q
+       wm8994_write(0x05,  0x0303);   
+       wm8994_write(0x2D,  0x0100);
+       wm8994_write(0x2E,  0x0100);
+       
+       wm8994_write(0x4C,  0x9F25);
+       msleep(5);
+       wm8994_write(0x01,  0x0323);
+       msleep(50);
+       wm8994_write(0x60,  0x0022);
+       wm8994_write(0x60,  0x00FF);
 
-       K = Kpart & 0xFFFFFFFF;
+       wm8994_write(0x420, 0x0000);
+       wm8994_write(0x601, 0x0001);
+       wm8994_write(0x602, 0x0001);
+    
+       wm8994_write(0x610, 0x01A0);  //DAC1 Left Volume bit0~7                 
+       wm8994_write(0x611, 0x01A0);  //DAC1 Right Volume bit0~7        
+       wm8994_write(0x03,  0x3030);
+       wm8994_write(0x22,  0x0000);
+       wm8994_write(0x23,  0x0100);
+       wm8994_write(0x36,  0x0003);
+       wm8994_write(0x1C,  0x017F);  //HPOUT1L Volume
+       wm8994_write(0x1D,  0x017F);  //HPOUT1R Volume
+}
 
-       if ((K % 10) >= 5)
-               K += 5;
+static void AP_to_speakers(void)
+{
+       DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       /* Move down to proper range now rounding is done */
-       fll->k = K / 10;
+       if (wm8994_current_mode == wm8994_AP_to_speakers)return;
+       wm8994_current_mode = wm8994_AP_to_speakers;
+       wm8994_reset();
+       msleep(WM8994_DELAY);
 
-//     DBG("N=%x K=%x\n", fll->n, fll->k);//8 3127
+       wm8994_write(0x700, 0xA101);
+       wm8994_write(0x39,  0x006C);
+       wm8994_write(0x01,  0x0023);
+       wm8994_write(0x200, 0x0000);
+       mdelay(WM8994_DELAY);
 
-       return 0;
-}
+       wm8994_write(0x220, 0x0000);
+       wm8994_write(0x221, 0x0700);
+       wm8994_write(0x222, 0x3126);
+       wm8994_write(0x223, 0x0100);
 
-static int wm8994_set_fll(unsigned int freq_in, unsigned int freq_out)                           
-{
-       int ret;
-       struct fll_div fll;
-       u16 reg=0;
-//     DBG("Enter %s::%s---%d\n",__FILE__,__FUNCTION__,__LINE__);
-       wm8994_write(0x220, 0x0000); 
-       /* If we're stopping the FLL redo the old config - no
-        * registers will actually be written but we avoid GCC flow
-        * analysis bugs spewing warnings.
-        */
-       ret = wm8994_get_fll_config(&fll, freq_in, freq_out);
-       if (ret < 0)
-               return ret;
-
-       reg = (fll.outdiv << WM8994_FLL1_OUTDIV_SHIFT) |(fll.fll_fratio << WM8994_FLL1_FRATIO_SHIFT);
-       wm8994_write(0x221, reg);//0x221  DIV
-       wm8994_write(0x222, fll.k);//0x222      K
-       wm8994_write(0x223,     fll.n << WM8994_FLL1_N_SHIFT);//0x223           N
-       wm8994_write(0x224, fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT);//0x224    
-
-       wm8994_write(0x220, 0x0004); 
+       wm8994_write(0x220, 0x0004);
        msleep(10);
-       wm8994_write(0x220, 0x0005);                    
+       wm8994_write(0x220, 0x0005);
        msleep(5);
-       wm8994_write(0x200, 0x0010); // sysclk = MCLK1  
-       return 0;
-}
 
-static int wm8994_sysclk_config(void)
-{
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
-       unsigned int freq_in,freq_out;
-       
-       wm8994_write(0x200, 0x0000); 
-       freq_in =       wm8994->mclk;
-       switch(wm8994->mclk)
-       {
-       case 12288000:
-       case 11289600:
-               freq_out = wm8994->mclk;
-               break;
-       case 3072000:
-       case 2822400:   
-               freq_out = wm8994->mclk * 4;
-               break;
-       default:
-               printk("wm8994->mclk error = %d\n",wm8994->mclk);
-               return -1;
-       }
-       
-       switch(wm8994->sysclk)
-       {
-       case WM8994_SYSCLK_FLL1: 
-               wm8994_set_fll(freq_in,freq_out);
-               break;
-       case WM8994_SYSCLK_FLL2:
-               break;
-       case WM8994_SYSCLK_MCLK2:
-               wm8994_write(0x701, 0x0000);//MCLK2
-       case WM8994_SYSCLK_MCLK1:
-               if(freq_out == freq_in)
-                       break;
-       default:
-               printk("wm8994->sysclk error = %d\n",wm8994->sysclk);
-               return -1;
-       }
-       
+       wm8994_write(0x200, 0x0010);
        wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
-       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1     
-       
-       switch(wm8994->rate)
-       {
-       case 8000:
-               printk("wm8994->rate = %d!!!!\n",wm8994->rate);
-               break;
-       case 44100:
-               wm8994_write(0x210, 0x0073); // SR=48KHz
-               break;
-       case 48000:
-               wm8994_write(0x210, 0x0083); // SR=48KHz
-               break;
-       case 11025:
-       case 16000:
-       case 22050:
-       case 32000:             
-       default:
-               printk("wm8994->rate error = %d\n",wm8994->rate);
-               return -1;
-       }       
-       
-       switch(wm8994->fmt)
-       {
-       case SND_SOC_DAIFMT_CBS_CFS:
-       case SND_SOC_DAIFMT_CBM_CFM:
-               break;
-       default:
-               printk("wm8994->fmt error = %d\n",wm8994->fmt);
-               return -1;
-       }
-       
-       wm8994_write(0x200, wm8994->sysclk << 3|0x01); 
-       return 0;
-}
+       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x210, 0x0083); // SR=48KHz
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
+       wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
+       wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
+       wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
+       wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
+       wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
+       wm8994_write(0x300, 0xC010); // i2s 16 bits
+#endif
+       wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
+  
+       wm8994_write(0x01,  0x3023);
+       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
+       wm8994_write(0x05,  0x0303);   
+       wm8994_write(0x2D,  0x0100);
+       wm8994_write(0x2E,  0x0100);
+       wm8994_write(0x4C,  0x9F25);
+       wm8994_write(0x60,  0x00EE);
+       wm8994_write(0x420, 0x0000); 
 
-static void wm8994_set_AIF1DAC_EQ(void)
-{
-       //100HZ. 300HZ.  875HZ  2400HZ    6900HZ
-//     int bank_vol[6] = {0,0,-3,3,-6,3};//-12DB ~ 12DB   default 0DB
-       int bank_vol[6] = {6,2,0,0,0,0};//-12DB ~ 12DB   default 0DB    
-       wm8994_write(0x0480, 0x0001|((bank_vol[1]+12)<<11)|
-               ((bank_vol[2]+12)<<6)|((bank_vol[3]+12)<<1));
-       wm8994_write(0x0481, 0x0000|((bank_vol[4]+12)<<11)|
-               ((bank_vol[5]+12)<<6));
+       wm8994_write(0x601, 0x0001);
+       wm8994_write(0x602, 0x0001);
+
+       wm8994_write(0x610, 0x01c0);  //DAC1 Left Volume bit0~7 
+       wm8994_write(0x611, 0x01c0);  //DAC1 Right Volume bit0~7        
+       wm8994_write(0x03,  0x0330);
+       wm8994_write(0x22,  0x0000);
+       wm8994_write(0x23,  0x0100);
+       wm8994_write(0x36,  0x0003);
+       wm8994_write(0x26,  0x017F);  //Speaker Left Output Volume
+       wm8994_write(0x27,  0x017F);  //Speaker Right Output Volume
 }
 
-static int wm8994_reset_ldo(void)
+static void AP_to_speakers_and_headset(void)
 {
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;        
-       struct wm8994_pdata *pdata = wm8994->pdata;
-       unsigned short value;
+       DBG("%s::%d\n",__FUNCTION__,__LINE__);
        
-       if(wm8994->RW_status == TRUE)
-               return 0;
-               
-       gpio_request(pdata->Power_EN_Pin, NULL);
-       gpio_direction_output(pdata->Power_EN_Pin,GPIO_LOW);
-       gpio_free(pdata->Power_EN_Pin); 
-       msleep(50);
-       gpio_request(pdata->Power_EN_Pin, NULL);
-       gpio_direction_output(pdata->Power_EN_Pin,GPIO_HIGH);
-       gpio_free(pdata->Power_EN_Pin);         
-       msleep(50);
-       
-       wm8994->RW_status = TRUE;
-       wm8994_read(0x00,  &value);
-
-       if(value == 0x8994)
-               DBG("wm8994_reset_ldo Read ID = 0x%x\n",value);
-       else
-       {
-               wm8994->RW_status = ERROR;
-               printk("wm8994_reset_ldo Read ID error value = 0x%x\n",value);
-               return -1;
-       }       
-               
-       return 0;       
-}
-//Set the volume of each channel (including recording)
-static void wm8994_set_channel_vol(void)
-{
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
-       struct wm8994_pdata *pdata = wm8994->pdata;     
-       int vol;
-
-       switch(wm8994_current_mode){
-       case wm8994_AP_to_speakers_and_headset:
-               MAX_MIN(-57,pdata->speaker_normal_vol,6);
-               MAX_MIN(-57,pdata->headset_normal_vol,6);
-               DBG("headset_normal_vol = %ddB \n",pdata->headset_normal_vol);
-               DBG("speaker_normal_vol = %ddB \n",pdata->speaker_normal_vol);
-               
-               vol = pdata->speaker_normal_vol;
-               wm8994_write(0x26,  320+vol+57);  //-57dB~6dB
-               wm8994_write(0x27,  320+vol+57);  //-57dB~6dB
-
-               vol = pdata->headset_normal_vol-4;
-               //for turn off headset volume when ringtone
-               if(vol >= -48)
-                       vol -= 14;
-               else
-                       vol = -57;
-
-               wm8994_write(0x1C,  320+vol+57);  //-57dB~6dB
-               wm8994_write(0x1D,  320+vol+57);  //-57dB~6dB
-
-               wm8994_set_AIF1DAC_EQ();
-               break;
-
-       case wm8994_recorder_and_AP_to_headset:
-               MAX_MIN(-57,pdata->headset_normal_vol,6);
-               MAX_MIN(-16,pdata->recorder_vol,60);
-               DBG("recorder_vol = %ddB \n",pdata->recorder_vol);
-               DBG("headset_normal_vol = %ddB \n",pdata->headset_normal_vol);
+       if (wm8994_current_mode == wm8994_AP_to_speakers_and_headset)return;
+       wm8994_current_mode = wm8994_AP_to_speakers_and_headset;
+       wm8994_reset();
+       mdelay(WM8994_DELAY);
+       wm8994_write(0x700, 0xA101);
+       wm8994_write(0x39,  0x006C);
+       wm8994_write(0x01,  0x0023);
+       wm8994_write(0x200, 0x0000);
+       mdelay(WM8994_DELAY);
+       wm8994_write(0x220, 0x0000);
+       wm8994_write(0x221, 0x0700);
+       wm8994_write(0x222, 0x3126);
+       wm8994_write(0x223, 0x0100);
 
-               vol = pdata->recorder_vol;
-               if(vol<30)
-                       wm8994_write(0x1A,  320+(vol+16)*10/15);  //mic vol
-               else
-               {
-                       wm8994_write(0x2A,  0x0030);
-                       wm8994_write(0x1A,  320+(vol-14)*10/15);  //mic vol
-               }
-               vol = pdata->headset_normal_vol;
-               wm8994_write(0x1C,  320+vol+57);  //-57dB~6dB
-               wm8994_write(0x1D,  320+vol+57);  //-57dB~6dB
-       //      wm8994_set_AIF1DAC_EQ();
-               break;
+       wm8994_write(0x220, 0x0004);
+       msleep(10);
+       wm8994_write(0x220, 0x0005);
+       msleep(5);
 
-       case wm8994_recorder_and_AP_to_speakers:
-       case wm8994_FM_to_speakers:
-               MAX_MIN(-57,pdata->speaker_normal_vol,6);
-               MAX_MIN(-16,pdata->recorder_vol,60);
-               DBG("speaker_normal_vol = %ddB \n",pdata->speaker_normal_vol);
-               DBG("recorder_vol = %ddB \n",pdata->recorder_vol);
-
-               vol = pdata->recorder_vol;
-               if(vol<30)
-                       wm8994_write(0x1A,  320+(vol+16)*10/15);  //mic vol
-               else
-               {
-                       wm8994_write(0x2A,  0x0030);
-                       wm8994_write(0x1A,  320+(vol-14)*10/15);  //mic vol
-               }
+       wm8994_write(0x200, 0x0010);
+       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x210, 0x0083); // SR=48KHz
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
+       wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
+       wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
+       wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
+       wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
+       wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
+       wm8994_write(0x300, 0xC010); // i2s 16 bits
+#endif
+       wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
 
-               vol = pdata->speaker_normal_vol;
-               wm8994_write(0x26,  320+vol+57);  //-57dB~6dB
-               wm8994_write(0x27,  320+vol+57);  //-57dB~6dB
+       wm8994_write(0x610, 0x0100);  //DAC1 Left Volume bit0~7 
+       wm8994_write(0x611, 0x0100);  //DAC1 Right Volume bit0~7
 
-               wm8994_set_AIF1DAC_EQ();
-               break;
-       case wm8994_handsetMIC_to_baseband_to_headset:
-               MAX_MIN(-12,pdata->headset_incall_vol,6);
-               MAX_MIN(-22,pdata->headset_incall_mic_vol,30);
-               DBG("headset_incall_mic_vol = %ddB \n",pdata->headset_incall_mic_vol);
-               DBG("headset_incall_vol = %ddB \n",pdata->headset_incall_vol);
-
-               vol = pdata->headset_incall_mic_vol;
-               if(vol<-16)
-               {
-                       wm8994_write(0x1E,  0x0016);  //mic vol
-                       wm8994_write(0x18,  320+(vol+22)*10/15);  //mic vol     
-               }
-               else
-               {
-                       wm8994_write(0x1E,  0x0006);  //mic vol
-                       wm8994_write(0x18,  320+(vol+16)*10/15);  //mic vol
-               }
-               break;
-       case wm8994_mainMIC_to_baseband_to_headset:
-               MAX_MIN(-12,pdata->headset_incall_vol,6);
-               MAX_MIN(-22,pdata->speaker_incall_mic_vol,30);
-               DBG("speaker_incall_mic_vol = %ddB \n",pdata->speaker_incall_mic_vol);
-               DBG("headset_incall_vol = %ddB \n",pdata->headset_incall_vol);
-
-               vol=pdata->speaker_incall_mic_vol;
-               if(vol<-16)
-               {
-                       wm8994_write(0x1E,  0x0016);  //mic vol
-                       wm8994_write(0x1A,  320+(vol+22)*10/15);  //mic vol     
-               }
-               else
-               {
-                       wm8994_write(0x1E,  0x0006);  //mic vol
-                       wm8994_write(0x1A,  320+(vol+16)*10/15);  //mic vol
-               }
-               break;
+       wm8994_write(0x24,  0x0018);
+       wm8994_set_channel_vol();
+       //wm8994_write(0x25,  0x003F);
 
-       case wm8994_mainMIC_to_baseband_to_earpiece:
-               MAX_MIN(-22,pdata->speaker_incall_mic_vol,30);
-               MAX_MIN(-21,pdata->earpiece_incall_vol,6);
-               DBG("earpiece_incall_vol = %ddB \n",pdata->earpiece_incall_vol);
-               DBG("speaker_incall_mic_vol = %ddB \n",pdata->speaker_incall_mic_vol);
-
-               vol = pdata->earpiece_incall_vol;
-               if(vol>=0)
-               {
-                       wm8994_write(0x33,  0x0018);  //6dB
-                       wm8994_write(0x31,  (((6-vol)/3)<<3)+(6-vol)/3);  //-21dB
-               }
-               else
-               {
-                       wm8994_write(0x33,  0x0010);
-                       wm8994_write(0x31,  (((-vol)/3)<<3)+(-vol)/3);  //-21dB
-               }
-               vol = pdata->speaker_incall_mic_vol;
-               if(vol<-16)
-               {
-                       wm8994_write(0x1E,  0x0016);
-                       wm8994_write(0x1A,  320+(vol+22)*10/15);        
-               }
-               else
-               {
-                       wm8994_write(0x1E,  0x0006);
-                       wm8994_write(0x1A,  320+(vol+16)*10/15);
-               }
-               break;
+       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
+       wm8994_write(0x05,  0x0303);   
+       wm8994_write(0x2D,  0x0100);
+       wm8994_write(0x2E,  0x0100);
 
-       case wm8994_mainMIC_to_baseband_to_speakers:
-               MAX_MIN(-22,pdata->speaker_incall_mic_vol,30);
-               MAX_MIN(-21,pdata->speaker_incall_vol,12);
-               DBG("speaker_incall_vol = %ddB \n",pdata->speaker_incall_vol);
-               DBG("speaker_incall_mic_vol = %ddB \n",pdata->speaker_incall_mic_vol);
-
-               vol = pdata->speaker_incall_mic_vol;
-               if(vol<-16)
-               {
-                       wm8994_write(0x1E,  0x0016);
-                       wm8994_write(0x1A,  320+(vol+22)*10/15);        
-               }
-               else
-               {
-                       wm8994_write(0x1E,  0x0006);
-                       wm8994_write(0x1A,  320+(vol+16)*10/15);
-               }
-               vol = pdata->speaker_incall_vol;
-               if(vol<=0)
-               {
-                       wm8994_write(0x31,  (((-vol)/3)<<3)+(-vol)/3);
-               }
-               else if(vol <= 9)
-               {
-                       wm8994_write(0x25,  ((vol*10/15)<<3)+vol*10/15);
-               }
-               else
-               {
-                       wm8994_write(0x25,  0x003F);
-               }
-               break;
+       wm8994_write(0x4C,  0x9F25);
+       mdelay(5);
+       wm8994_write(0x01,  0x3303);
+       mdelay(50);
+       wm8994_write(0x60,  0x0022);
+       wm8994_write(0x60,  0x00EE);
 
-       case wm8994_BT_baseband:
-               MAX_MIN(-16,pdata->BT_incall_vol,30);
-               MAX_MIN(-57,pdata->BT_incall_mic_vol,6);
-               DBG("BT_incall_mic_vol = %ddB \n",pdata->BT_incall_mic_vol);
-               DBG("BT_incall_vol = %ddB \n",pdata->BT_incall_vol);
-               vol = pdata->BT_incall_mic_vol;
-               wm8994_write(0x20,  320+vol+57);
-               vol = pdata->BT_incall_vol;
-               wm8994_write(0x19, 0x0500+(vol+16)*10/15);
-               break;
-       default:
-               printk("route error !\n");
-       }
+       wm8994_write(0x420, 0x0000); 
+       
+       wm8994_write(0x601, 0x0001);
+       wm8994_write(0x602, 0x0001);
+       
+       wm8994_write(0x03,  0x3330);
+       wm8994_write(0x22,  0x0000);
+       wm8994_write(0x23,  0x0100);
+       wm8994_write(0x36,  0x0003);
+       wm8994_write(0x01,  0x3323);
 
+       wm8994_write(0x610, 0x01C0);  //DAC1 Left Volume bit0~7 
+       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
 }
 
-#define wm8994_reset() wm8994_set_all_mute();\
-                                               wm8994_write(WM8994_RESET, 0)                                   
-
-void AP_to_headset(void)
+static void recorder_and_AP_to_headset(void)
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_AP_to_headset)return;
-       wm8994_current_mode=wm8994_AP_to_headset;
+       if (wm8994_current_mode == wm8994_recorder_and_AP_to_headset)return;
+       wm8994_current_mode = wm8994_recorder_and_AP_to_headset;
        wm8994_reset();
        msleep(WM8994_DELAY);
 
        wm8994_write(0x700, 0xA101);
-       wm8994_write(0x01,  0x0023);
+       wm8994_write(0x39,  0x006C);
+       wm8994_write(0x01,  0x0003);
        wm8994_write(0x200, 0x0000);
        mdelay(WM8994_DELAY);
 
@@ -834,55 +532,66 @@ void AP_to_headset(void)
        wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
        wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
        wm8994_write(0x210, 0x0083); // SR=48KHz
-#ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
        wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
        wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
        wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
        wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
        wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
-       wm8994_write(0x300, 0x4010); // i2s 16 bits
+       wm8994_write(0x300, 0xC050); // i2s 16 bits
 #endif
        wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
-  
-       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1/ q
-       wm8994_write(0x05,  0x0303);   
-       wm8994_write(0x2D,  0x0100);
-       wm8994_write(0x2E,  0x0100);
-       
+
+       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
+       wm8994_write(0x05,  0x0303); // AIF1DAC1L_ENA=1, AIF1DAC1R_ENA=1, DAC1L_ENA=1, DAC1R_ENA=1
+       wm8994_write(0x2D,  0x0100); // DAC1L_TO_HPOUT1L=1
+       wm8994_write(0x2E,  0x0100); // DAC1R_TO_HPOUT1R=1
+
        wm8994_write(0x4C,  0x9F25);
-       msleep(5);
-       wm8994_write(0x01,  0x0323);
-       msleep(50);
+       mdelay(5);
+       wm8994_write(0x01,  0x0303);
+       mdelay(50);
        wm8994_write(0x60,  0x0022);
        wm8994_write(0x60,  0x00FF);
 
-       wm8994_write(0x420, 0x0000);
-       wm8994_write(0x601, 0x0001);
-       wm8994_write(0x602, 0x0001);
-    
-       wm8994_write(0x610, 0x01A0);  //DAC1 Left Volume bit0~7                 
-       wm8994_write(0x611, 0x01A0);  //DAC1 Right Volume bit0~7        
+       wm8994_write(0x610, 0x0100); // DAC1_VU=1, DAC1L_VOL=1100_0000
+       wm8994_write(0x611, 0x0100); // DAC1_VU=1, DAC1R_VOL=1100_0000
+
+       wm8994_write(0x25,  0x003F);
+       wm8994_write(0x28,  0x0003); // IN1RP_TO_IN1R=1, IN1RN_TO_IN1R=1
+       wm8994_write(0x606, 0x0002); // ADC1L_TO_AIF1ADC1L=1
+       wm8994_write(0x607, 0x0002); // ADC1R_TO_AIF1ADC1R=1
+       wm8994_write(0x620, 0x0000); 
+
+       wm8994_write(0x402, 0x01FF); // AIF1ADC1L_VOL [7:0]
+       wm8994_write(0x403, 0x01FF); // AIF1ADC1R_VOL [7:0]
+       wm8994_write(0x440, 0x01BF);
+       wm8994_write(0x450, 0x01BF);
+       wm8994_write(0x420, 0x0000); 
+
+       wm8994_write(0x01,  0x0333);
+       wm8994_write(0x02,  0x6110); // TSHUT_ENA=1, TSHUT_OPDIS=1, MIXINR_ENA=1,IN1R_ENA=1
        wm8994_write(0x03,  0x3030);
-       wm8994_write(0x22,  0x0000);
-       wm8994_write(0x23,  0x0100);
-       wm8994_write(0x36,  0x0003);
-       wm8994_write(0x1C,  0x017F);  //HPOUT1L Volume
-       wm8994_write(0x1D,  0x017F);  //HPOUT1R Volume
+
+       wm8994_write(0x601, 0x0001); // AIF1DAC1L_TO_DAC1L=1
+       wm8994_write(0x602, 0x0001); // AIF1DAC1R_TO_DAC1R=1
+       wm8994_write(0x610, 0x01A0); // DAC1_VU=1, DAC1L_VOL=1100_0000
+       wm8994_write(0x611, 0x01A0); // DAC1_VU=1, DAC1R_VOL=1100_0000
+       wm8994_set_channel_vol();
 }
 
-void AP_to_speakers(void)
+static void recorder_and_AP_to_speakers(void)
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_AP_to_speakers)return;
-       wm8994_current_mode=wm8994_AP_to_speakers;
-//     wm8994_reset();
-       wm8994_write(0,0);
+       if (wm8994_current_mode == wm8994_recorder_and_AP_to_speakers)return;
+       wm8994_current_mode = wm8994_recorder_and_AP_to_speakers;
+       wm8994_reset();
        msleep(WM8994_DELAY);
 
-//     wm8994_write(0x700, 0xA101);
-//     wm8994_write(0x39,  0x006C);
-       wm8994_write(0x01,  0x0023);
+       wm8994_write(0x700, 0xA101);
+       wm8994_write(0x39,  0x006C);
+       wm8994_write(0x01,  0x0003);
        wm8994_write(0x200, 0x0000);
        mdelay(WM8994_DELAY);
 
@@ -900,57 +609,64 @@ void AP_to_speakers(void)
        wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
        wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
        wm8994_write(0x210, 0x0083); // SR=48KHz
-#ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
        wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
        wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
        wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
        wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
        wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
-       wm8994_write(0x300, 0xC010); // i2s 16 bits
+       wm8994_write(0x300, 0xC050); // i2s 16 bits
 #endif
        wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
-  
-       wm8994_write(0x01,  0x3023);
-       wm8994_write(0x03,  0x0330);
-       wm8994_write(0x05,  0x0303);   
-       wm8994_write(0x22,  0x0000);
-       wm8994_write(0x23,  0x0100);    
-       wm8994_write(0x2D,  0x0001);
-       wm8994_write(0x2E,  0x0000);
-       wm8994_write(0x36,  0x000C);    
-       wm8994_write(0x4C,  0x9F25);
-       wm8994_write(0x60,  0x00EE);
-       wm8994_write(0x420, 0x0000); 
 
-       wm8994_write(0x601, 0x0001);
-       wm8994_write(0x602, 0x0001);
+       wm8994_write(0x610, 0x0100); // DAC1_VU=1, DAC1L_VOL=1100_0000
+       wm8994_write(0x611, 0x0100); // DAC1_VU=1, DAC1R_VOL=1100_0000
+       wm8994_set_channel_vol();
+       wm8994_write(0x24,  0x0018);
+       wm8994_write(0x25,  0x001D);
 
-       wm8994_write(0x610, 0x01c0);  //DAC1 Left Volume bit0~7 
-       wm8994_write(0x611, 0x01c0);  //DAC1 Right Volume bit0~7        
+       wm8994_write(0x02,  0x6110); // TSHUT_ENA=1, TSHUT_OPDIS=1, MIXINR_ENA=1,IN1R_ENA=1
+       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
+       wm8994_write(0x28,  0x0003); // IN1RP_TO_IN1R=1, IN1RN_TO_IN1R=1
 
-       wm8994_write(0x26,  0x017F);  //Speaker Left Output Volume
-       wm8994_write(0x27,  0x017F);  //Speaker Right Output Volume
+       wm8994_write(0x606, 0x0002); // ADC1L_TO_AIF1ADC1L=1
+       wm8994_write(0x607, 0x0002); // ADC1R_TO_AIF1ADC1R=1
+       wm8994_write(0x620, 0x0000); 
+
+       wm8994_write(0x402, 0x01FF); // AIF1ADC1L_VOL [7:0]
+       wm8994_write(0x403, 0x01FF); // AIF1ADC1R_VOL [7:0]
+
+       wm8994_write(0x03,  0x0330); // SPKRVOL_ENA=1, SPKLVOL_ENA=1, MIXOUTL_ENA=1, MIXOUTR_ENA=1  
+       wm8994_write(0x05,  0x0303); // AIF1DAC1L_ENA=1, AIF1DAC1R_ENA=1, DAC1L_ENA=1, DAC1R_ENA=1
+       wm8994_write(0x22,  0x0000);
+       wm8994_write(0x23,  0x0100); // SPKOUT_CLASSAB=1
+
+       wm8994_write(0x2D,  0x0001); // DAC1L_TO_MIXOUTL=1
+       wm8994_write(0x2E,  0x0001); // DAC1R_TO_MIXOUTR=1
+       wm8994_write(0x4C,  0x9F25);
+       wm8994_write(0x60,  0x00EE);
+       wm8994_write(0x36,  0x000C); // MIXOUTL_TO_SPKMIXL=1, MIXOUTR_TO_SPKMIXR=1
+       wm8994_write(0x440, 0x01BF);
+       wm8994_write(0x450, 0x01BF);
+       wm8994_write(0x610, 0x01C0); // DAC1_VU=1, DAC1L_VOL=1100_0000
+       wm8994_write(0x611, 0x01C0); // DAC1_VU=1, DAC1R_VOL=1100_0000
+       wm8994_write(0x601, 0x0001); // AIF1DAC1L_TO_DAC1L=1
+       wm8994_write(0x602, 0x0001); // AIF1DAC1R_TO_DAC1R=1
+       wm8994_write(0x420, 0x0000);
+       wm8994_write(0x01,  0x3003);
+       msleep(20);
+       wm8994_write(0x01,  0x3033);
 }
 
-void FM_to_headset(void)
+static void FM_to_headset(void)
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode == wm8994_FM_to_headset)return;
+       if (wm8994_current_mode == wm8994_FM_to_headset)return;
        wm8994_current_mode = wm8994_FM_to_headset;
-       wm8994_write(0,0);
+       wm8994_reset();
        msleep(WM8994_DELAY);
 
-//clk
-//     wm8994_write(0x701, 0x0000);//MCLK2
-       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
-       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
-       wm8994_write(0x210, 0x0083); // SR=48KHz
-       wm8994_write(0x300, 0xC010); // i2s 16 bits
-       wm8994_write(0x200, 0x0001); // sysclk = MCLK1
-//     wm8994_write(0x200, 0x0009); // sysclk = MCLK2
-       wm8994_set_channel_vol();
-       
        wm8994_write(0x01,  0x0303); 
        wm8994_write(0x02,  0x03A0);  
        wm8994_write(0x03,  0x0030);    
@@ -972,11 +688,11 @@ void FM_to_headset(void)
        wm8994_write(0x1D,  0x01F9);  //RIGHT OUTPUT VOLUME
 }
 
-void FM_to_headset_and_record(void)
+static void FM_to_headset_and_record(void)
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode == wm8994_FM_to_headset_and_record)return;
+       if (wm8994_current_mode == wm8994_FM_to_headset_and_record)return;
        wm8994_current_mode = wm8994_FM_to_headset_and_record;
        wm8994_reset();
        msleep(WM8994_DELAY);
@@ -985,7 +701,7 @@ void FM_to_headset_and_record(void)
        msleep(WM8994_DELAY);
        wm8994_write(0x221,  0x1900);  //8~13BIT div
 
-#ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
        wm8994_write(0x302,  0x4000);  // master = 0x4000 // slave= 0x0000
        wm8994_write(0x303,  0x0040);  // master  0x0050 lrck 7.94kHz bclk 510KHz
 #endif
@@ -1018,85 +734,45 @@ void FM_to_headset_and_record(void)
        wm8994_write(0x620,  0x0000);
 }
 
-void FM_test(void)
+static void FM_to_speakers(void)
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode == wm8994_FM_to_speakers)return;
+       if (wm8994_current_mode == wm8994_FM_to_speakers)return;
        wm8994_current_mode = wm8994_FM_to_speakers;
        wm8994_reset();
        msleep(WM8994_DELAY);
 
-//clk
-//     wm8994_write(0x701, 0x0000);//MCLK2
-       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
-       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
-       wm8994_write(0x210, 0x0083); // SR=48KHz
-       wm8994_write(0x300, 0xC010); // i2s 16 bits
-       wm8994_write(0x200, 0x0001); // sysclk = MCLK1
-//     wm8994_write(0x200, 0x0009); // sysclk = MCLK2
-       wm8994_set_channel_vol();
-       
-       wm8994_write(0x20,   0x013F);
-       wm8994_write(0x21,   0x013F);
-//path
-       wm8994_write(0x28,   0x0044);//IN2RN_TO_IN2R IN2LN_TO_IN2L
-       wm8994_write(0x29,   0x0107);//IN2L PGA Output to MIXINL UnMute
-       wm8994_write(0x2A,   0x0107);//IN2R PGA Output to MIXINR UnMute
-       wm8994_write(0x2D,   0x0040);//MIXINL_TO_MIXOUTL
-       wm8994_write(0x2E,   0x0040);//MIXINR_TO_MIXOUTR
-       wm8994_write(0x36,   0x000C);//MIXOUTL_TO_SPKMIXL   MIXOUTR_TO_SPKMIXR
-//volume
-       wm8994_write(0x22,   0x0000);
-       wm8994_write(0x23,   0x0000);
-       wm8994_write(0x19,   0x013F);  //LEFT LINE INPUT 3&4 VOLUME
-       wm8994_write(0x1B,   0x013F);  //RIGHT LINE INPUT 3&4 VOLUME            
-//power
        wm8994_write(0x01,   0x3003);
        wm8994_write(0x02,   0x03A0);
-       wm8994_write(0x03,   0x0330);   
-}
+       wm8994_write(0x03,   0x0330);
+       wm8994_write(0x19,   0x010B);  //LEFT LINE INPUT 3&4 VOLUME
+       wm8994_write(0x1B,   0x010B);  //RIGHT LINE INPUT 3&4 VOLUME
+  
+       wm8994_write(0x22,   0x0000);
+       wm8994_write(0x23,   0x0000);
+       wm8994_write(0x36,   0x000C);
 
-void FM_to_speakers(void)
-{
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
-       if(wm8994_current_mode == wm8994_FM_to_speakers)return;
-       wm8994_current_mode = wm8994_FM_to_speakers;
-       wm8994_reset();
-       msleep(WM8994_DELAY);
-       wm8994_write(0x01,  0x0003);
-       msleep(WM8994_DELAY);
-//clk
-//     wm8994_write(0x701, 0x0000);//MCLK2
-       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
-       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
-       wm8994_write(0x210, 0x0083); // SR=48KHz
-       wm8994_write(0x300, 0xC010); // i2s 16 bits
-       wm8994_write(0x200, 0x0001); // sysclk = MCLK1
-//     wm8994_write(0x200, 0x0009); // sysclk = MCLK2
-       wm8994_set_channel_vol();
-       
-//path
-       wm8994_write(0x22,  0x0000);
-       wm8994_write(0x23,  0x0100);
-       wm8994_write(0x2D,  0x0030);  //bit 1 IN2LP_TO_MIXOUTL bit 12 DAC1L_TO_HPOUT1L  0x0102 
-       wm8994_write(0x2E,  0x0030);  //bit 1 IN2RP_TO_MIXOUTR bit 12 DAC1R_TO_HPOUT1R  0x0102
-       wm8994_write(0x36,  0x000C);//MIXOUTL_TO_SPKMIXL        MIXOUTR_TO_SPKMIXR
-//volume
-       wm8994_write(0x25,  0x003F);
-       wm8994_write(0x610, 0x01C0);  //DAC1 Left Volume bit0~7 
-       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
-//power
-       wm8994_write(0x01,  0x3003);    
-       wm8994_write(0x03,  0x0330);
-       wm8994_write(0x05,  0x0003);
+       wm8994_write(0x28,   0x0044);
+       wm8994_write(0x29,   0x0100);
+       wm8994_write(0x2A,   0x0100);
+       wm8994_write(0x2D,   0x0040);
+       wm8994_write(0x2E,   0x0040);
+
+       wm8994_write(0x220,  0x0003);
+       wm8994_write(0x221,  0x0700);
+       wm8994_write(0x224,  0x0CC0);
+
+       wm8994_write(0x200,  0x0011);
+       wm8994_write(0x20,   0x01F9);
+       wm8994_write(0x21,   0x01F9);
 }
 
-void FM_to_speakers_and_record(void)
+static void FM_to_speakers_and_record(void)
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode == wm8994_FM_to_speakers_and_record)return;
+       if (wm8994_current_mode == wm8994_FM_to_speakers_and_record)return;
        wm8994_current_mode = wm8994_FM_to_speakers_and_record;
        wm8994_reset();
        msleep(WM8994_DELAY);
@@ -1104,7 +780,7 @@ void FM_to_speakers_and_record(void)
        wm8994_write(0x01,   0x0003);  
        msleep(WM8994_DELAY);
 
-#ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
        wm8994_write(0x302,  0x4000);  // master = 0x4000 // slave= 0x0000
        wm8994_write(0x303,  0x0090);  //
 #endif
@@ -1142,294 +818,170 @@ void FM_to_speakers_and_record(void)
        wm8994_write(0x607,  0x0002);
        wm8994_write(0x620,  0x0000);
 }
-
-void record_only(void)
+#ifndef PCM_BB
+static void handsetMIC_to_baseband_to_headset(void)
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
-       wm8994_write(0,0);
-       msleep(WM8994_DELAY);
-
-       wm8994_write(0x01,  0x0003);
-       msleep(WM8994_DELAY);
-//clk
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); //AIF1ADCL_SRC=1, AIF1ADCR_SRC=1, AIF1_WL=00, AIF1_FMT=10
-//     wm8994_write(0x300, 0xC050); // AIF1ADCL_SRC=1, AIF1ADCR_SRC=1, AIF1_WL=10, AIF1_FMT=10
-       
-//path
-       wm8994_write(0x28,  0x0003); // IN1RP_TO_IN1R=1, IN1RN_TO_IN1R=1
-       wm8994_write(0x2A,  0x0030); //IN1R_TO_MIXINR   IN1R_MIXINR_VOL
-       wm8994_write(0x606, 0x0002); // ADC1L_TO_AIF1ADC1L=1
-       wm8994_write(0x607, 0x0002); // ADC1R_TO_AIF1ADC1R=1
-       wm8994_write(0x620, 0x0000); //ADC_OSR128=0, DAC_OSR128=0       
-//DRC
-       wm8994_write(0x440, 0x01BF);
-       wm8994_write(0x450, 0x01BF);    
-//valume
-       wm8994_write(0x1A,  0x014B);//IN1_VU=1, IN1R_MUTE=0, IN1R_ZC=1, IN1R_VOL=0_1011
-       wm8994_write(0x402, 0x01FF); // AIF1ADC1L_VOL [7:0]
-       wm8994_write(0x403, 0x01FF); // AIF1ADC1R_VOL [7:0]
-       
-//power
-       wm8994_write(0x02,  0x6110); // TSHUT_ENA=1, TSHUT_OPDIS=1, MIXINR_ENA=1,IN1R_ENA=1
-       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1        
-       wm8994_write(0x01,  0x3033);
-}
 
-void AP_to_speakers_and_headset(void)
-{
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
-       if(wm8994_current_mode==wm8994_AP_to_speakers_and_headset)return;
-       wm8994_current_mode=wm8994_AP_to_speakers_and_headset;
+       if (wm8994_current_mode == wm8994_handsetMIC_to_baseband_to_headset)return;
+       wm8994_codec_first_incall();
+       wm8994_current_mode = wm8994_handsetMIC_to_baseband_to_headset;
        wm8994_reset();
        msleep(WM8994_DELAY);
-
+       wm8994_write(0x700, 0xA101);
        wm8994_write(0x39,  0x006C);
-       wm8994_write(0x01,  0x0023);
-       msleep(WM8994_DELAY);
-//clk
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); // i2s 16 bits     
-//path
-       wm8994_write(0x2D,  0x0100);
-       wm8994_write(0x2E,  0x0100);
-       wm8994_write(0x60,  0x0022);
-       wm8994_write(0x60,  0x00EE);
-       wm8994_write(0x420, 0x0000);    
-       wm8994_write(0x601, 0x0001);
-       wm8994_write(0x602, 0x0001);
-       wm8994_write(0x36,  0x0003);
-//     wm8994_write(0x24,  0x0011);    
-//other
-       wm8994_write(0x4C,  0x9F25);
-//volume
-       wm8994_write(0x22,  0x0000);
-       wm8994_write(0x23,  0x0100);
-       wm8994_write(0x610, 0x01C0);  //DAC1 Left Volume bit0~7 
-       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
-//     wm8994_write(0x25,  0x003F);    
-       wm8994_set_channel_vol();
-//power
-       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
-       wm8994_write(0x05,  0x0303);  
-       wm8994_write(0x03,  0x3330);    
-       wm8994_write(0x01,  0x3303);
-       msleep(50); 
-       wm8994_write(0x01,  0x3333);    
-}
-
-void recorder_and_AP_to_headset(void)
-{
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
-
-       if(wm8994_current_mode==wm8994_recorder_and_AP_to_headset)return;
-       wm8994_current_mode=wm8994_recorder_and_AP_to_headset;
-       wm8994_reset();
-       msleep(WM8994_DELAY);
-       
-       wm8994_write(0x39, 0x006C);
-
-       wm8994_write(0x01, 0x0003);
-       msleep(35);     
-       wm8994_write(0xFF, 0x0000);
-       msleep(5);
-       wm8994_write(0x4C, 0x9F25);
-       msleep(5);
-       wm8994_write(0x01, 0x0303);
-       wm8994_write(0x60, 0x0022);
-       msleep(5);      
-       wm8994_write(0x54, 0x0033);//
-       
-//     wm8994_write(0x01,  0x0003);    
+       wm8994_write(0x01,  0x0003);
        wm8994_write(0x200, 0x0000);
-       msleep(WM8994_DELAY);
-//clk
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); // i2s 16 bits     
-//recorder
-       wm8994_write(0x28,  0x0003); // IN1RP_TO_IN1R=1, IN1RN_TO_IN1R=1
-       wm8994_write(0x606, 0x0002); // ADC1L_TO_AIF1ADC1L=1
-       wm8994_write(0x607, 0x0002); // ADC1R_TO_AIF1ADC1R=1
-       wm8994_write(0x620, 0x0001); 
-       wm8994_write(0x402, 0x01FF); // AIF1ADC1L_VOL [7:0]
-       wm8994_write(0x403, 0x01FF); // AIF1ADC1R_VOL [7:0]
-//DRC  
-       wm8994_write(0x440, 0x01BF);
-       wm8994_write(0x450, 0x01BF);
-//path 
-       wm8994_write(0x2D,  0x0100); // DAC1L_TO_HPOUT1L=1   
-       wm8994_write(0x2E,  0x0100); // DAC1R_TO_HPOUT1R=1   
-       wm8994_write(0x60,  0x0022);
-       wm8994_write(0x60,  0x00FF);
-       wm8994_write(0x420, 0x0000); 
-       wm8994_write(0x601, 0x0001); // AIF1DAC1L_TO_DAC1L=1
-       wm8994_write(0x602, 0x0001); // AIF1DAC1R_TO_DAC1R=1
-//volume       
-       wm8994_write(0x610, 0x01FF); // DAC1_VU=1, DAC1L_VOL=1100_0000
-       wm8994_write(0x611, 0x01FF); // DAC1_VU=1, DAC1R_VOL=1100_0000
-       wm8994_set_channel_vol();       
-//other
-//     wm8994_write(0x4C,  0x9F25);            
-//power
-       wm8994_write(0x01,  0x0333);
-       wm8994_write(0x02,  0x6110); // TSHUT_ENA=1, TSHUT_OPDIS=1, MIXINR_ENA=1,IN1R_ENA=1
-       wm8994_write(0x03,  0x3030);
-       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
-       wm8994_write(0x05,  0x0303); // AIF1DAC1L_ENA=1, AIF1DAC1R_ENA=1, DAC1L_ENA=1, DAC1R_ENA=1
+       mdelay(WM8994_DELAY);
 
-}
+       wm8994_write(0x220, 0x0000);
+       wm8994_write(0x221, 0x0700);
+       wm8994_write(0x222, 0x3126);
+       wm8994_write(0x223, 0x0100);
 
-void recorder_and_AP_to_speakers(void)
-{
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
+       wm8994_write(0x220, 0x0004);
+       msleep(10);
+       wm8994_write(0x220, 0x0005);
+       msleep(5);
 
-       if(wm8994_current_mode==wm8994_recorder_and_AP_to_speakers)return;
-       wm8994_current_mode=wm8994_recorder_and_AP_to_speakers;
-       wm8994_reset();
-       msleep(WM8994_DELAY);
+       wm8994_write(0x200, 0x0010);
+       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x210, 0x0083); // SR=48KHz
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
+       wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
+       wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
+       wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
+       wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
+       wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
+       wm8994_write(0x300, 0xC010); // i2s 16 bits
+#endif
+       wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
 
-       wm8994_write(0x39,  0x006C);
-       wm8994_write(0x01,  0x0023);
-       msleep(WM8994_DELAY);
-//clk
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); // i2s 16 bits     
-//recorder
-       wm8994_write(0x02,  0x6110); // TSHUT_ENA=1, TSHUT_OPDIS=1, MIXINR_ENA=1,IN1R_ENA=1
-       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
-       wm8994_write(0x28,  0x0003); // IN1RP_TO_IN1R=1, IN1RN_TO_IN1R=1        
-       wm8994_write(0x606, 0x0002); // ADC1L_TO_AIF1ADC1L=1
-       wm8994_write(0x607, 0x0002); // ADC1R_TO_AIF1ADC1R=1
-       wm8994_write(0x620, 0x0000); 
-       wm8994_write(0x402, 0x01FF); // AIF1ADC1L_VOL [7:0]
-       wm8994_write(0x403, 0x01FF); // AIF1ADC1R_VOL [7:0]
-//path
-       wm8994_write(0x2D,  0x0001); // DAC1L_TO_MIXOUTL=1
-       wm8994_write(0x2E,  0x0001); // DAC1R_TO_MIXOUTR=1
-       wm8994_write(0x36,  0x000C); // MIXOUTL_TO_SPKMIXL=1, MIXOUTR_TO_SPKMIXR=1
-       wm8994_write(0x601, 0x0001); // AIF1DAC1L_TO_DAC1L=1
-       wm8994_write(0x602, 0x0001); // AIF1DAC1R_TO_DAC1R=1
-       wm8994_write(0x420, 0x0000);
-//     wm8994_write(0x24,  0x001f);    
-//volume
-       wm8994_write(0x22,  0x0000);
-       wm8994_write(0x23,  0x0100); // SPKOUT_CLASSAB=1        
-       wm8994_write(0x610, 0x01C0); // DAC1_VU=1, DAC1L_VOL=1100_0000
-       wm8994_write(0x611, 0x01C0); // DAC1_VU=1, DAC1R_VOL=1100_0000  
-       wm8994_write(0x25,  0x003F);
-       wm8994_set_channel_vol();
-//other
+       wm8994_write(0x04,  0x0300); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1
+       wm8994_write(0x05,  0x0303);
+#ifdef CONFIG_SND_BB_DIFFERENTIAL_INPUT
+       wm8994_write(0x2D,  0x0041);  //bit 1 MIXINL_TO_MIXOUTL bit 12 DAC1L_TO_MIXOUTL 
+       wm8994_write(0x2E,  0x0081);  //bit 1 MIXINL_TO_MIXOUTR bit 12 DAC1R_TO_MIXOUTR
+#endif
+#ifdef CONFIG_SND_BB_NORMAL_INPUT
+       wm8994_write(0x2D,  0x0003);  //bit 1 IN2LP_TO_MIXOUTL bit 12 DAC1L_TO_MIXOUTL
+       wm8994_write(0x2E,  0x0003);  //bit 1 IN2RP_TO_MIXOUTR bit 12 DAC1R_TO_MIXOUTR
+#endif
        wm8994_write(0x4C,  0x9F25);
-//DRC
-       wm8994_write(0x440, 0x01BF);
-       wm8994_write(0x450, 0x01BF);            
-//power
-       wm8994_write(0x03,  0x0330); // SPKRVOL_ENA=1, SPKLVOL_ENA=1, MIXOUTL_ENA=1, MIXOUTR_ENA=1  
-       wm8994_write(0x05,  0x0303); // AIF1DAC1L_ENA=1, AIF1DAC1R_ENA=1, DAC1L_ENA=1, DAC1R_ENA=1      
-       wm8994_write(0x01,  0x3003);
-       msleep(50);
-       wm8994_write(0x01,  0x3033);
-}
+       mdelay(5);
+       wm8994_write(0x01,  0x0303);
+       mdelay(50);
+       wm8994_write(0x60,  0x0022);
+       wm8994_write(0x60,  0x00FF);
 
-#ifndef PCM_BB
-void handsetMIC_to_baseband_to_headset(void)
-{//
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
+       wm8994_write(0x610, 0x0100);  //DAC1 Left Volume bit0~7 
+       wm8994_write(0x611, 0x0100);  //DAC1 Right Volume bit0~7
+       wm8994_set_volume(wm8994_current_mode,0,call_maxvol);
+       wm8994_set_channel_vol();
 
-       if(wm8994_current_mode == wm8994_handsetMIC_to_baseband_to_headset)return;
-       wm8994_current_mode = wm8994_handsetMIC_to_baseband_to_headset;
-       wm8994_reset();
-       msleep(WM8994_DELAY);
-       
-       wm8994_write(0x01,  0x0023); 
-       wm8994_write(0x200, 0x0000);
-       msleep(WM8994_DELAY);
-//clk
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); // i2s 16 bits     
-//path
-       wm8994_write(0x22,  0x0000);
-       wm8994_write(0x23,  0x0100);
        wm8994_write(0x02,  0x6240);
        wm8994_write(0x28,  0x0030);  //IN1LN_TO_IN1L IN1LP_TO_IN1L
-       wm8994_write(0x2D,  0x0003);  //bit 1 IN2LP_TO_MIXOUTL bit 12 DAC1L_TO_HPOUT1L  0x0102 
-       wm8994_write(0x2E,  0x0003);  //bit 1 IN2RP_TO_MIXOUTR bit 12 DAC1R_TO_HPOUT1R  0x0102
        wm8994_write(0x34,  0x0002);  //IN1L_TO_LINEOUT1P
-       wm8994_write(0x36,  0x0003);
-       wm8994_write(0x60,  0x0022);
-       wm8994_write(0x60,  0x00EE);
        wm8994_write(0x420, 0x0000);
-       wm8994_write(0x601, 0x0001);
-       wm8994_write(0x602, 0x0001);
-//volume
+
+       wm8994_write(0x01,  0x0323);
+       msleep(20);
+       wm8994_write(0x03,  0x3030);
+       if (wm8994_work_type != WM8994_WORK_FIRSTINCALL) {
+               wm8994_write(0x601, 0x0001);
+               wm8994_write(0x602, 0x0001);
+       }
        wm8994_write(0x610, 0x01A0);  //DAC1 Left Volume bit0~7                 
        wm8994_write(0x611, 0x01A0);  //DAC1 Right Volume bit0~7
-       wm8994_set_channel_vol();       
-//other
-       wm8994_write(0x4C,  0x9F25);    
-//power
-       wm8994_write(0x03,  0x3030);
-       wm8994_write(0x04,  0x0300); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1
-       wm8994_write(0x05,  0x0303);
-       wm8994_write(0x01,  0x0303);
-       msleep(50);
-       wm8994_write(0x01,  0x0333);    
-       
        wm8994_set_level_volume();
 }
 
-void mainMIC_to_baseband_to_headset(void)
-{//
+static void mainMIC_to_baseband_to_headset(void)
+{
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode == wm8994_mainMIC_to_baseband_to_headset)return;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_headset)return;
+       wm8994_codec_first_incall();
        wm8994_current_mode = wm8994_mainMIC_to_baseband_to_headset;
        wm8994_reset();
        msleep(WM8994_DELAY);
 
-       wm8994_write(0x01,  0x0023);
+       wm8994_write(0x700, 0xA101);
+       wm8994_write(0x39,  0x006C);
+       wm8994_write(0x01,  0x0003);
        wm8994_write(0x200, 0x0000);
        mdelay(WM8994_DELAY);
-//clk
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); // i2s 16 bits     
-//path
-       wm8994_write(0x22,  0x0000);
-       wm8994_write(0x23,  0x0100);
-       wm8994_write(0x02,  0x6210);
-       wm8994_write(0x28,  0x0003);  //IN1RN_TO_IN1R IN1RP_TO_IN1R
+
+       wm8994_write(0x220, 0x0000);
+       wm8994_write(0x221, 0x0700);
+       wm8994_write(0x222, 0x3126);
+       wm8994_write(0x223, 0x0100);
+
+       wm8994_write(0x220, 0x0004);
+       msleep(10);
+       wm8994_write(0x220, 0x0005);
+       msleep(5);
+
+       wm8994_write(0x200, 0x0010);
+       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x210, 0x0083); // SR=48KHz
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
+       wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
+       wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
+       wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
+       wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
+       wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
+       wm8994_write(0x300, 0xC010); // i2s 16 bits
+#endif
+       wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
+
+       wm8994_write(0x04,  0x0300); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1
+       wm8994_write(0x05,  0x0303);
+#ifdef CONFIG_SND_BB_DIFFERENTIAL_INPUT
+       wm8994_write(0x2D,  0x0041);  //bit 1 MIXINL_TO_MIXOUTL bit 12 DAC1L_TO_HPOUT1L  0x0102 
+       wm8994_write(0x2E,  0x0081);  //bit 1 MIXINL_TO_MIXOUTR bit 12 DAC1R_TO_HPOUT1R  0x0102
+#endif
+#ifdef CONFIG_SND_BB_NORMAL_INPUT
        wm8994_write(0x2D,  0x0003);  //bit 1 IN2LP_TO_MIXOUTL bit 12 DAC1L_TO_HPOUT1L  0x0102 
        wm8994_write(0x2E,  0x0003);  //bit 1 IN2RP_TO_MIXOUTR bit 12 DAC1R_TO_HPOUT1R  0x0102
-       wm8994_write(0x34,  0x0004);  //IN1R_TO_LINEOUT1P
-       wm8994_write(0x36,  0x0003);
+#endif
+
+       wm8994_write(0x4C,  0x9F25);
+       mdelay(5);
+       wm8994_write(0x01,  0x0303);
+       mdelay(50);
        wm8994_write(0x60,  0x0022);
-       wm8994_write(0x60,  0x00EE);
+       wm8994_write(0x60,  0x00FF);
+
+       wm8994_write(0x610, 0x0100);  //DAC1 Left Volume bit0~7 
+       wm8994_write(0x611, 0x0100);  //DAC1 Right Volume bit0~7
+       wm8994_set_volume(wm8994_current_mode,0,call_maxvol);
+       wm8994_set_channel_vol();
+
+       wm8994_write(0x02,  0x6210);
+       wm8994_write(0x28,  0x0003);  //IN1RN_TO_IN1R IN1RP_TO_IN1R
+       wm8994_write(0x34,  0x0004);  //IN1R_TO_LINEOUT1P
        wm8994_write(0x420, 0x0000);
-       wm8994_write(0x601, 0x0001);
-       wm8994_write(0x602, 0x0001);
-//volume
+
+       wm8994_write(0x01,  0x0333);
+       msleep(20);
+       wm8994_write(0x03,  0x3030);
+       if (wm8994_work_type != WM8994_WORK_FIRSTINCALL) {
+               wm8994_write(0x601, 0x0001);
+               wm8994_write(0x602, 0x0001);
+       }
        wm8994_write(0x610, 0x01A0);  //DAC1 Left Volume bit0~7                 
        wm8994_write(0x611, 0x01A0);  //DAC1 Right Volume bit0~7
-       wm8994_set_channel_vol();       
-//other
-       wm8994_write(0x4C,  0x9F25);    
-//power
-       wm8994_write(0x03,  0x3030);
-       wm8994_write(0x04,  0x0300); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1
-       wm8994_write(0x05,  0x0303);
-       wm8994_write(0x01,  0x0303);
-       msleep(50);
-       wm8994_write(0x01,  0x0333);    
-       
        wm8994_set_level_volume();
 }
 
-void handsetMIC_to_baseband_to_headset_and_record(void)
+static void handsetMIC_to_baseband_to_headset_and_record(void)
 {
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode == wm8994_handsetMIC_to_baseband_to_headset_and_record)return;
+       if (wm8994_current_mode == wm8994_handsetMIC_to_baseband_to_headset_and_record)return;
        wm8994_current_mode = wm8994_handsetMIC_to_baseband_to_headset_and_record;
        wm8994_reset();
        msleep(WM8994_DELAY);
@@ -1440,7 +992,7 @@ void handsetMIC_to_baseband_to_headset_and_record(void)
        wm8994_write(0x04,  0x0303); 
        wm8994_write(0x18,  0x014B);  //volume
        wm8994_write(0x19,  0x014B);  //volume
-       wm8994_set_volume(wm8994_current_mode,wm8994->call_vol,call_maxvol);
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
        wm8994_write(0x1E,  0x0006); 
        wm8994_write(0x28,  0x00B0);  //IN2LP_TO_IN2L
        wm8994_write(0x29,  0x0120); 
@@ -1453,7 +1005,7 @@ void handsetMIC_to_baseband_to_headset_and_record(void)
        wm8994_write(0x208, 0x000A); 
        wm8994_write(0x300, 0x0050); 
 
-#ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
        wm8994_write(0x302, 0x4000);  // master = 0x4000 // slave= 0x0000
        wm8994_write(0x303, 0x0090);  // master lrck 16k
 #endif
@@ -1463,53 +1015,95 @@ void handsetMIC_to_baseband_to_headset_and_record(void)
        wm8994_write(0x620, 0x0000);
 }
 
-void mainMIC_to_baseband_to_earpiece(void)
-{//
+static void mainMIC_to_baseband_to_earpiece(void)
+{
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode == wm8994_mainMIC_to_baseband_to_earpiece)return;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_earpiece)return;
+       wm8994_codec_first_incall();
        wm8994_current_mode = wm8994_mainMIC_to_baseband_to_earpiece;
        wm8994_reset();
        msleep(WM8994_DELAY);
 
-       wm8994_write(0x01,  0x0023);
+       wm8994_write(0x700, 0xA101);
+       wm8994_write(0x39,  0x006C);
+       wm8994_write(0x01,  0x0003);
        wm8994_write(0x200, 0x0000);
-       msleep(WM8994_DELAY);
-//clk
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); // i2s 16 bits     
-//path
+       mdelay(WM8994_DELAY);
+
+       wm8994_write(0x220, 0x0000);
+       wm8994_write(0x221, 0x0700);
+       wm8994_write(0x222, 0x3126);
+       wm8994_write(0x223, 0x0100);
+
+       wm8994_write(0x220, 0x0004);
+       msleep(10);
+       wm8994_write(0x220, 0x0005);
+       msleep(5);
+
+       wm8994_write(0x200, 0x0010);
+       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x210, 0x0083); // SR=48KHz
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
+       wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
+       wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
+       wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
+       wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
+       wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
+       wm8994_write(0x300, 0x4010); // i2s 16 bits
+#endif
+       wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
+
+       wm8994_set_volume(wm8994_current_mode,0,call_maxvol);
+       wm8994_write(0x01,  0x0803); //HPOUT2_ENA=1, VMID_SEL=01, BIAS_ENA=1
+       wm8994_write(0x4C,  0x9F25);
+       
+       wm8994_write(0x02,  0x6250); //bit4 IN1R_ENV bit6 IN1L_ENV 
+       wm8994_write(0x03,  0x30F0);
+       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
+       wm8994_write(0x05,  0x0303);
+       wm8994_write(0x1F,  0x0000);
+
+#if defined(CONFIG_SND_INSIDE_EARPIECE)||defined(CONFIG_SND_OUTSIDE_EARPIECE)
+       wm8994_set_channel_vol();
+#ifdef CONFIG_SND_INSIDE_EARPIECE
        wm8994_write(0x28,  0x0003); //IN1RP_TO_IN1R IN1RN_TO_IN1R
        wm8994_write(0x34,  0x0004); //IN1R_TO_LINEOUT1P
+#endif
+#ifdef CONFIG_SND_OUTSIDE_EARPIECE
+       wm8994_write(0x28,  0x0030); //IN1LP_TO_IN1L IN1LN_TO_IN1L
+       wm8994_write(0x34,  0x0002); //IN1L_TO_LINEOUT1P
+#endif
+#endif
+#ifdef CONFIG_SND_BB_NORMAL_INPUT
        wm8994_write(0x2D,  0x0003);  //bit 1 IN2LP_TO_MIXOUTL bit 12 DAC1L_TO_HPOUT1L  0x0102 
        wm8994_write(0x2E,  0x0003);  //bit 1 IN2RP_TO_MIXOUTR bit 12 DAC1R_TO_HPOUT1R  0x0102
-       wm8994_write(0x601, 0x0001); //AIF1DAC1L_TO_DAC1L=1
-       wm8994_write(0x602, 0x0001); //AIF1DAC1R_TO_DAC1R=1
-       wm8994_write(0x420, 0x0000);
-//volume
+#endif
+#ifdef CONFIG_SND_BB_DIFFERENTIAL_INPUT
+       wm8994_write(0x2B,  0x0007);  //VRX_MIXINL_VOL
+       wm8994_write(0x2D,  0x0041);  //bit 1 MIXINL_TO_MIXOUTL bit 12 DAC1L_TO_HPOUT1L  0x0102 
+       wm8994_write(0x2E,  0x0081);  //bit 1 MIXINL_TO_MIXOUTR bit 12 DAC1R_TO_HPOUT1R  0x0102
+#endif
+       if (wm8994_work_type != WM8994_WORK_FIRSTINCALL) {
+               wm8994_write(0x601, 0x0001); //AIF1DAC1L_TO_DAC1L=1
+               wm8994_write(0x602, 0x0001); //AIF1DAC1R_TO_DAC1R=1
+       }
+       wm8994_write(0x01,  0x0833);
        wm8994_write(0x610, 0x01C0); //DAC1_VU=1, DAC1L_VOL=1100_0000
        wm8994_write(0x611, 0x01C0); //DAC1_VU=1, DAC1R_VOL=1100_0000
-       wm8994_write(0x1F,  0x0000);//HPOUT2
-       wm8994_set_channel_vol();       
-//other
-       wm8994_write(0x4C,  0x9F25);            
-//power
-       wm8994_write(0x01,  0x0833); //HPOUT2_ENA=1, VMID_SEL=01, BIAS_ENA=1
-       wm8994_write(0x02,  0x6250); //bit4 IN1R_ENV bit6 IN1L_ENV 
-       wm8994_write(0x03,  0x30F0);
-       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
-       wm8994_write(0x05,  0x0303);
+
+       wm8994_write(0x420, 0x0000);
        
-       wm8994_set_level_volume();      
+       wm8994_set_level_volume();
 }
 
-void mainMIC_to_baseband_to_earpiece_and_record(void)
+static void mainMIC_to_baseband_to_earpiece_and_record(void)
 {
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_mainMIC_to_baseband_to_earpiece_and_record)return;
-       wm8994_current_mode=wm8994_mainMIC_to_baseband_to_earpiece_and_record;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_earpiece_and_record)return;
+       wm8994_current_mode = wm8994_mainMIC_to_baseband_to_earpiece_and_record;
        wm8994_reset();
        msleep(WM8994_DELAY);
 
@@ -1517,7 +1111,8 @@ void mainMIC_to_baseband_to_earpiece_and_record(void)
        wm8994_write(0x02  ,0x6310);
        wm8994_write(0x03  ,0x30A0);
        wm8994_write(0x04  ,0x0303);
-       wm8994_write(0x1A  ,0x014F);
+       //wm8994_write(0x1A  ,0x014F);
+       wm8994_write(0x1A  ,0x0147);
        wm8994_write(0x1E  ,0x0006);
        wm8994_write(0x1F  ,0x0000);
        wm8994_write(0x28  ,0x0003);  //MAINMIC_TO_IN1R
@@ -1530,9 +1125,9 @@ void mainMIC_to_baseband_to_earpiece_and_record(void)
        wm8994_write(0x200 ,0x0001);
        wm8994_write(0x208 ,0x000A);
        wm8994_write(0x300 ,0xC050);
-       wm8994_set_volume(wm8994_current_mode,wm8994->call_vol,call_maxvol);
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
 
-#ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
        wm8994_write(0x302, 0x4000);  // master = 0x4000 // slave= 0x0000
        wm8994_write(0x303, 0x0090);  // master lrck 16k
 #endif
@@ -1542,63 +1137,94 @@ void mainMIC_to_baseband_to_earpiece_and_record(void)
        wm8994_write(0x620 ,0x0000);
 }
 
-void mainMIC_to_baseband_to_speakers(void)
-{//
+static void mainMIC_to_baseband_to_speakers(void)
+{
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_mainMIC_to_baseband_to_speakers)return;
-
-       wm8994_current_mode=wm8994_mainMIC_to_baseband_to_speakers;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_speakers)return;
+       wm8994_codec_first_incall();
+       wm8994_current_mode = wm8994_mainMIC_to_baseband_to_speakers;
        wm8994_reset();
        msleep(WM8994_DELAY);
-
+       wm8994_write(0x700, 0xA101);
        wm8994_write(0x39,  0x006C);
        wm8994_write(0x01,  0x0023);
        wm8994_write(0x200, 0x0000);
-       msleep(WM8994_DELAY);
-//clk
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); // i2s 16 bits     
-//path
+       mdelay(WM8994_DELAY);
+
+       wm8994_write(0x220, 0x0000);
+       wm8994_write(0x221, 0x0700);
+       wm8994_write(0x222, 0x3126);
+       wm8994_write(0x223, 0x0100);
+
+       wm8994_write(0x220, 0x0004);
+       msleep(10);
+       wm8994_write(0x220, 0x0005);
+       msleep(5);
+
+       wm8994_write(0x200, 0x0010);
+       wm8994_write(0x208, 0x0008); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x208, 0x000A); //DSP_FS1CLK_ENA=1, DSP_FSINTCLK_ENA=1
+       wm8994_write(0x210, 0x0083); // SR=48KHz
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
+       wm8994_write(0x302, 0x3000); // AIF1_MSTR=1
+       wm8994_write(0x302, 0x7000); // AIF1_MSTR=1
+       wm8994_write(0x303, 0x0040); // AIF1 BCLK DIV--------AIF1CLK/4
+       wm8994_write(0x304, 0x0040); // AIF1 ADCLRCK DIV-----BCLK/64
+       wm8994_write(0x305, 0x0040); // AIF1 DACLRCK DIV-----BCLK/64
+       wm8994_write(0x300, 0xC010); // i2s 16 bits
+#endif
+       wm8994_write(0x200, 0x0011); // sysclk = fll (bit4 =1)   0x0011
+
+       wm8994_write(0x610, 0x0100);
+       wm8994_write(0x611, 0x0100);
+       wm8994_set_volume(wm8994_current_mode,0,call_maxvol);
+       wm8994_set_channel_vol();
+
+       wm8994_write(0x02,  0x6210);
+       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
+
        wm8994_write(0x22,  0x0000);
        wm8994_write(0x23,  0x0100);
+       wm8994_write(0x24,  0x0018);
        wm8994_write(0x28,  0x0003);  //IN1LN_TO_IN1L IN1LP_TO_IN1L
        wm8994_write(0x29,  0x0030);
+#ifdef CONFIG_SND_BB_NORMAL_INPUT
        wm8994_write(0x2D,  0x0003);  //bit 1 IN2LP_TO_MIXOUTL bit 12 DAC1L_TO_HPOUT1L  0x0102 
        wm8994_write(0x2E,  0x0003);  //bit 1 IN2RP_TO_MIXOUTR bit 12 DAC1R_TO_HPOUT1R  0x0102
+#endif
+#ifdef CONFIG_SND_BB_DIFFERENTIAL_INPUT
+       wm8994_write(0x2B,  0x0005);  //VRX_MIXINL_VOL
+       wm8994_write(0x2D,  0x0041);  //bit 1 MIXINL_TO_MIXOUTL bit 12 DAC1L_TO_HPOUT1L  0x0102 
+       wm8994_write(0x2E,  0x0081);  //bit 1 MIXINL_TO_MIXOUTR bit 12 DAC1R_TO_HPOUT1R  0x0102
+#endif
        wm8994_write(0x34,  0x000C);  //IN1L_TO_LINEOUT1P
-       wm8994_write(0x60,  0x0022);
-       wm8994_write(0x36,  0x000C);    
-       wm8994_write(0x60,  0x00EE);
+       wm8994_write(0x36,  0x000C);
        wm8994_write(0x420, 0x0000);
-       wm8994_write(0x601, 0x0001);
-       wm8994_write(0x602, 0x0001);
-       wm8994_write(0x24,  0x0011);    
-//volume
-//     wm8994_write(0x25,  0x003F);
-       wm8994_write(0x610, 0x01C0);  //DAC1 Left Volume bit0~7 
-       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
-       wm8994_set_channel_vol();       
-//other
-       wm8994_write(0x4C,  0x9F25);            
-//power
-       wm8994_write(0x01,  0x3003);
        msleep(50);
-       wm8994_write(0x01,  0x3033);    
-       wm8994_write(0x02,  0x6210);
        wm8994_write(0x03,  0x1330);
-       wm8994_write(0x04,  0x0303); // AIF1ADC1L_ENA=1, AIF1ADC1R_ENA=1, ADCL_ENA=1, ADCR_ENA=1
-       wm8994_write(0x05,  0x0303);    
-       wm8994_set_level_volume();              
+       wm8994_write(0x05,  0x0303);
+
+       if (wm8994_work_type != WM8994_WORK_FIRSTINCALL) {      
+               wm8994_write(0x601, 0x0001);
+               wm8994_write(0x602, 0x0001);
+       }
+       wm8994_write(0x01,  0x3003);
+       msleep(20);
+       wm8994_write(0x01,  0x3033);
+
+       wm8994_write(0x610, 0x01C0);  //DAC1 Left Volume bit0~7 
+       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
+
+       wm8994_set_level_volume();
 }
 
-void mainMIC_to_baseband_to_speakers_and_record(void)
+static void mainMIC_to_baseband_to_speakers_and_record(void)
 {
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_mainMIC_to_baseband_to_speakers_and_record)return;
-       wm8994_current_mode=wm8994_mainMIC_to_baseband_to_speakers_and_record;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_speakers_and_record)return;
+       wm8994_current_mode = wm8994_mainMIC_to_baseband_to_speakers_and_record;
        wm8994_reset();
        msleep(WM8994_DELAY);
 
@@ -1620,9 +1246,9 @@ void mainMIC_to_baseband_to_speakers_and_record(void)
        wm8994_write(0x200, 0x0001);
        wm8994_write(0x208, 0x000A);
        wm8994_write(0x300, 0xC050);
-       wm8994_set_volume(wm8994_current_mode,wm8994->call_vol,call_maxvol);
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
 
-#ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
        wm8994_write(0x302, 0x4000);  // master = 0x4000 // slave= 0x0000
        wm8994_write(0x303, 0x0090);  // master lrck 16k
 #endif
@@ -1632,63 +1258,67 @@ void mainMIC_to_baseband_to_speakers_and_record(void)
        wm8994_write(0x620, 0x0000);
 }
 
-void BT_baseband(void)
-{//
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
+static void BT_baseband(void)
+{
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_BT_baseband)return;
-
-       wm8994_current_mode=wm8994_BT_baseband;
+       if (wm8994_current_mode == wm8994_BT_baseband)return;
+       wm8994_codec_first_incall();
+       wm8994_current_mode = wm8994_BT_baseband;
        wm8994_reset();
        msleep(WM8994_DELAY);
 
+       wm8994_write(0x700, 0xA101);
+       wm8994_write(0x705, 0xA101);
+       wm8994_write(0x39,  0x006C);
        wm8994_write(0x01,  0x0023);
        wm8994_write(0x200, 0x0000);
        msleep(WM8994_DELAY);
-//CLK  
-       //AIF1CLK
-       wm8994_sysclk_config();
-       wm8994_write(0x300, 0xC010); // i2s 16 bits     
-       //AIF2CLK use FLL2
+
+       //roger_chen@20100524
+       //8KHz, BCLK=8KHz*128=1024KHz, Fout=2.048MHz
+       wm8994_write(0x220, 0x0000);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (1)(220H):  0005  FLL1_FRACN_ENA=0, FLL1_OSC_ENA=0, FLL1_ENA=0
+       wm8994_write(0x221, 0x0700);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (2)(221H):  0700  FLL1_OUTDIV=2Fh, FLL1_CTRL_RATE=000, FLL1_FRATIO=000
+       wm8994_write(0x222, 0x3126);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (3)(222H):  8FD5  FLL1_K=3126h
+       wm8994_write(0x223, 0x0100);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (4)(223H):  00E0  FLL1_N=8h, FLL1_GAIN=0000
+
+       wm8994_write(0x220, 0x0004);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (1)(220H):  0005  FLL1_FRACN_ENA=1, FLL1_OSC_ENA=0, FLL1_ENA=0
+       msleep(10);
+       wm8994_write(0x220, 0x0005);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (1)(220H):  0005  FLL1_FRACN_ENA=1, FLL1_OSC_ENA=0, FLL1_ENA=1
+       msleep(5);
+
+       wm8994_write(0x200, 0x0010);
+       wm8994_write(0x208, 0x0008);
+       wm8994_write(0x208, 0x000A);
+
+       wm8994_write(0x210, 0x0083);    // SMbus_16inx_16dat     Write  0x34      * SR=48KHz
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
+       wm8994_write(0x302, 0x3000); 
+       msleep(30);
+       wm8994_write(0x302, 0x7000); 
+       wm8994_write(0x303, 0x0040);
+       wm8994_write(0x304, 0x0040);
+       wm8994_write(0x305, 0x0040);
+       wm8994_write(0x300, 0xC050);    //DSP/PCM; 16bits; ADC L channel = R channel;MODE A
+#endif
+       wm8994_write(0x200, 0x0011);
+
        wm8994_write(0x204, 0x0000);
        msleep(WM8994_DELAY);
        wm8994_write(0x240, 0x0000);
-       switch(wm8994->mclk)
-       {
-       case 12288000:
-               wm8994_write(0x241, 0x2F00);//48
-               wm8994_write(0x242, 0);
-               wm8994_write(0x243, 0x0100);            
-               break;
-       case 11289600:
-               wm8994_write(0x241, 0x2b00);
-               wm8994_write(0x242, 0xfb5b);
-               wm8994_write(0x243, 0x00e0);    
-               break;
-       case 3072000:
-               wm8994_write(0x241, 0x2F00);//48
-               wm8994_write(0x242, 0);
-               wm8994_write(0x243, 0x0400);
-               break;
-       case 2822400:
-               wm8994_write(0x241, 0x2b00);
-               wm8994_write(0x242, 0xed6d);
-               wm8994_write(0x243, 0x03e0);
-               break;
-       default:
-               printk("wm8994->mclk error = %d\n",wm8994->mclk);
-               return;
-       }       
-       
+       wm8994_write(0x241, 0x2F00);
+       wm8994_write(0x242, 0x3126);
+       wm8994_write(0x243, 0x0100);
+
        wm8994_write(0x240, 0x0004);
        msleep(10);
        wm8994_write(0x240, 0x0005);
        msleep(5);
+
        wm8994_write(0x204, 0x0018);    // SMbus_16inx_16dat     Write  0x34      * AIF2 Clocking (1)(204H): 0011  AIF2CLK_SRC=10, AIF2CLK_INV=0, AIF2CLK_DIV=0, AIF2CLK_ENA=1
        wm8994_write(0x208, 0x000E);
        wm8994_write(0x211, 0x0003); 
-       
+#ifdef CONFIG_SND_CODEC_SOC_MASTER
        wm8994_write(0x312, 0x3000);    // SMbus_16inx_16dat     Write  0x34      * AIF2 Master/Slave(312H): 7000  AIF2_TRI=0, AIF2_MSTR=1, AIF2_CLK_FRC=0, AIF2_LRCLK_FRC=0
        msleep(30);
        wm8994_write(0x312, 0x7000);
@@ -1696,161 +1326,57 @@ void BT_baseband(void)
        wm8994_write(0x314, 0x0080);    // SMbus_16inx_16dat     Write  0x34      * AIF2 ADCLRCK DIV-----BCLK/128
        wm8994_write(0x315, 0x0080);
        wm8994_write(0x310, 0x0118);    //DSP/PCM; 16bits; ADC L channel = R channel;MODE A
-       
+#endif
        wm8994_write(0x204, 0x0019);    // SMbus_16inx_16dat     Write  0x34      * AIF2 Clocking (1)(204H): 0011  AIF2CLK_SRC=10, AIF2CLK_INV=0, AIF2CLK_DIV=0, AIF2CLK_ENA=1
-/*     
-       wm8994_write(0x310, 0x0118); 
-       wm8994_write(0x204, 0x0001);    
-       wm8994_write(0x208, 0x000F);    
-       wm8994_write(0x211, 0x0009);    
-       wm8994_write(0x312, 0x7000);    
-       wm8994_write(0x313, 0x00F0); 
-*/     
-//GPIO
+
+       //roger_chen@20100519
+       //enable AIF2 BCLK,LRCK
+       //Rev.B and Rev.D is different
        wm8994_write(0x702, 0x2100);
        wm8994_write(0x703, 0x2100);
+
        wm8994_write(0x704, 0xA100);
        wm8994_write(0x707, 0xA100);
        wm8994_write(0x708, 0x2100);
        wm8994_write(0x709, 0x2100);
        wm8994_write(0x70A, 0x2100);
-       wm8994_write(0x06,   0x000A);
-//path
-       wm8994_write(0x29,   0x0100);
-       wm8994_write(0x2A,   0x0100);
-       wm8994_write(0x28,   0x00C0);   
-       wm8994_write(0x24,   0x0009);
-       wm8994_write(0x29,   0x0130);
-       wm8994_write(0x2A,   0x0130);
-       wm8994_write(0x2D,   0x0001);
-       wm8994_write(0x2E,   0x0001);
-       wm8994_write(0x34,   0x0001);
-       wm8994_write(0x36,   0x0004);
-       wm8994_write(0x601, 0x0004);
-       wm8994_write(0x602, 0x0001);
-       wm8994_write(0x603, 0x000C);
-       wm8994_write(0x604, 0x0010);
-       wm8994_write(0x605, 0x0010);
-       wm8994_write(0x620, 0x0000);
-       wm8994_write(0x420, 0x0000);
-//DRC&&EQ
-       wm8994_write(0x440, 0x0018);
-       wm8994_write(0x450, 0x0018);
-       wm8994_write(0x540, 0x01BF); //open nosie gate
-       wm8994_write(0x550, 0x01BF); //open nosie gate
-       wm8994_write(0x480, 0x0000);
-       wm8994_write(0x481, 0x0000);
-       wm8994_write(0x4A0, 0x0000);
-       wm8994_write(0x4A1, 0x0000);
-       wm8994_write(0x520, 0x0000);
-       wm8994_write(0x540, 0x0018);
-       wm8994_write(0x580, 0x0000);
-       wm8994_write(0x581, 0x0000);
-//volume
-       wm8994_set_volume(wm8994_current_mode,wm8994->call_vol,call_maxvol);
-       wm8994_write(0x1E,   0x0006);
-       wm8994_set_channel_vol();
-       wm8994_write(0x22,   0x0000);
-       wm8994_write(0x23,   0x0100);   
-       wm8994_write(0x610, 0x01C0);
-       wm8994_write(0x611, 0x01C0);
-       wm8994_write(0x612, 0x01C0);
-       wm8994_write(0x613, 0x01C0);    
-//other
-       wm8994_write(0x4C,   0x9F25);
-       wm8994_write(0x60,   0x00EE);
-       msleep(5);
-//power        
-       wm8994_write(0x01,   0x3033);
+       
+       wm8994_write(0x01,   0x3003);
        wm8994_write(0x02,   0x63A0);
        wm8994_write(0x03,   0x33F0);
        wm8994_write(0x04,   0x3303);
-       wm8994_write(0x05,   0x3303);   
-}
-
-void BT_baseband_old(void)
-{
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;        
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
-
-       if(wm8994_current_mode==wm8994_BT_baseband)return;
-
-       wm8994_current_mode=wm8994_BT_baseband;
-       wm8994_reset();
-       msleep(WM8994_DELAY);
-
-       wm8994_write(0x01, 0x3003);
-       wm8994_write(0x02, 0x63A0);
-       wm8994_write(0x03, 0x33F0);
-       wm8994_write(0x04, 0x3303);
-       wm8994_write(0x05, 0x3303);
-       wm8994_write(0x06, 0x000A);
-       wm8994_set_volume(wm8994_current_mode,wm8994->call_vol,call_maxvol);
-       wm8994_write(0x1E, 0x0006);
-       wm8994_write(0x29, 0x0100);
-       wm8994_write(0x2A, 0x0100);
+       wm8994_write(0x05,   0x3303);
+       wm8994_write(0x06,   0x000A);
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
+       wm8994_write(0x1E,   0x0006);
+       wm8994_write(0x29,   0x0100);
+       wm8994_write(0x2A,   0x0100);
 
        wm8994_set_channel_vol();
 
 #ifdef CONFIG_SND_BB_NORMAL_INPUT
-       wm8994_write(0x28, 0x00C0);
+       wm8994_write(0x28,   0x00C0);
 #endif
 #ifdef CONFIG_SND_BB_DIFFERENTIAL_INPUT
        /*vol = BT_incall_vol;
-       if(vol>6)vol=6;
-       if(vol<-12)vol=-12;
+       if (vol>6)vol=6;
+       if (vol<-12)vol=-12;
        wm8994_write(0x2B, (vol+12)/3 + 1);*/
-       wm8994_write(0x28, 0x00CC);
+       wm8994_write(0x28,   0x00CC);
 #endif
-       wm8994_write(0x22, 0x0000);
-       wm8994_write(0x23, 0x0100);
-       wm8994_write(0x24, 0x0009);
-       wm8994_write(0x29, 0x0130);
-       wm8994_write(0x2A, 0x0130);
-       wm8994_write(0x2D, 0x0001);
-       wm8994_write(0x2E, 0x0001);
-       wm8994_write(0x34, 0x0001);
-       wm8994_write(0x36, 0x0004);
-       wm8994_write(0x4C, 0x9F25);
-       wm8994_write(0x60, 0x00EE);
-       wm8994_write(0x01, 0x3023);
-       //roger_chen@20100524
-       //8KHz, BCLK=8KHz*128=1024KHz, Fout=2.048MHz
-       wm8994_write(0x200, 0x0001);
-       wm8994_write(0x204, 0x0001);    // SMbus_16inx_16dat     Write  0x34      * AIF2 Clocking (1)(204H): 0011  AIF2CLK_SRC=00, AIF2CLK_INV=0, AIF2CLK_DIV=0, AIF2CLK_ENA=1
-       wm8994_write(0x208, 0x000E);
-       wm8994_write(0x220, 0x0000);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (1)(220H):  0005  FLL1_FRACN_ENA=0, FLL1_OSC_ENA=0, FLL1_ENA=0
-       wm8994_write(0x221, 0x0700);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (2)(221H):  0700  FLL1_OUTDIV=2Fh, FLL1_CTRL_RATE=000, FLL1_FRATIO=000
-       wm8994_write(0x222, 0x3126);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (3)(222H):  8FD5  FLL1_K=3126h
-       wm8994_write(0x223, 0x0100);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (4)(223H):  00E0  FLL1_N=8h, FLL1_GAIN=0000
-
-       wm8994_write(0x303, 0x0040);
-       wm8994_write(0x304, 0x0040);
-       wm8994_write(0x305, 0x0040);
-       wm8994_write(0x300, 0xC050);    //DSP/PCM; 16bits; ADC L channel = R channel;MODE A
-
-       wm8994_write(0x210, 0x0083);    // SMbus_16inx_16dat     Write  0x34      * SR=48KHz
-       wm8994_write(0x220, 0x0004);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (1)(220H):  0005  FLL1_FRACN_ENA=1, FLL1_OSC_ENA=0, FLL1_ENA=0
-       msleep(50);
-       wm8994_write(0x220, 0x0005);    // SMbus_16inx_16dat     Write  0x34      * FLL1 Control (1)(220H):  0005  FLL1_FRACN_ENA=1, FLL1_OSC_ENA=0, FLL1_ENA=1
-
-       wm8994_write(0x240, 0x0000);
-       wm8994_write(0x241, 0x2F00);
-       wm8994_write(0x242, 0x3126);
-       wm8994_write(0x243, 0x0100);
-
-       wm8994_write(0x313, 0x0020);    // SMbus_16inx_16dat     Write  0x34      * AIF2 BCLK DIV--------AIF1CLK/2
-       wm8994_write(0x314, 0x0080);    // SMbus_16inx_16dat     Write  0x34      * AIF2 ADCLRCK DIV-----BCLK/128
-       wm8994_write(0x315, 0x0080);
-       wm8994_write(0x310, 0x0118);    //DSP/PCM; 16bits; ADC L channel = R channel;MODE A
-
-       wm8994_write(0x211, 0x0003);    // SMbus_16inx_16dat     Write  0x34      * SR=8KHz
-       wm8994_write(0x240, 0x0004);
-       msleep(50);
-       wm8994_write(0x240, 0x0005);
+       wm8994_write(0x22,   0x0000);
+       wm8994_write(0x23,   0x0100);
+       wm8994_write(0x24,   0x0009);
+       wm8994_write(0x29,   0x0130);
+       wm8994_write(0x2A,   0x0130);
+       wm8994_write(0x2D,   0x0001);
+       wm8994_write(0x2E,   0x0001);
+       wm8994_write(0x34,   0x0001);
+       wm8994_write(0x36,   0x0004);
+       wm8994_write(0x4C,   0x9F25);
+       wm8994_write(0x60,   0x00EE);
+       wm8994_write(0x01,   0x3023);
 
-       wm8994_write(0x200, 0x0011);
-       wm8994_write(0x204, 0x0019);    // SMbus_16inx_16dat     Write  0x34      * AIF2 Clocking (1)(204H): 0011  AIF2CLK_SRC=10, AIF2CLK_INV=0, AIF2CLK_DIV=0, AIF2CLK_ENA=1
        wm8994_write(0x440, 0x0018);
        wm8994_write(0x450, 0x0018);
        wm8994_write(0x540, 0x01BF); //open nosie gate
@@ -1864,9 +1390,9 @@ void BT_baseband_old(void)
        wm8994_write(0x580, 0x0000);
        wm8994_write(0x581, 0x0000);
        wm8994_write(0x601, 0x0004);
-
-       wm8994_write(0x602, 0x0001);
-
+       if (wm8994_work_type != WM8994_WORK_FIRSTINCALL) {
+               wm8994_write(0x602, 0x0001);
+       }
        wm8994_write(0x603, 0x000C);
        wm8994_write(0x604, 0x0010);
        wm8994_write(0x605, 0x0010);
@@ -1876,38 +1402,15 @@ void BT_baseband_old(void)
        wm8994_write(0x613, 0x01C0);
        wm8994_write(0x620, 0x0000);
        wm8994_write(0x420, 0x0000);
-
-       //roger_chen@20100519
-       //enable AIF2 BCLK,LRCK
-       //Rev.B and Rev.D is different
-       wm8994_write(0x702, 0x2100);
-       wm8994_write(0x703, 0x2100);
-
-       wm8994_write(0x704, 0xA100);
-       wm8994_write(0x707, 0xA100);
-       wm8994_write(0x708, 0x2100);
-       wm8994_write(0x709, 0x2100);
-       wm8994_write(0x70A, 0x2100);
-#ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER
-       wm8994_write(0x700, 0xA101);
-       wm8994_write(0x705, 0xA101);
-       wm8994_write(0x302, 0x3000); 
-       msleep(30);
-       wm8994_write(0x302, 0x7000); 
-       msleep(30);
-       wm8994_write(0x312, 0x3000);    // SMbus_16inx_16dat     Write  0x34      * AIF2 Master/Slave(312H): 7000  AIF2_TRI=0, AIF2_MSTR=1, AIF2_CLK_FRC=0, AIF2_LRCLK_FRC=0
-       msleep(30);
-       wm8994_write(0x312, 0x7000); 
-#endif
 }
 
-void BT_baseband_and_record(void)
+
+static void BT_baseband_and_record(void)
 {
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_BT_baseband_and_record)return;
-       wm8994_current_mode=wm8994_BT_baseband_and_record;
+       if (wm8994_current_mode == wm8994_BT_baseband_and_record)return;
+       wm8994_current_mode = wm8994_BT_baseband_and_record;
        wm8994_reset();
        msleep(WM8994_DELAY);
 
@@ -1917,7 +1420,7 @@ void BT_baseband_and_record(void)
        wm8994_write(0x04, 0x3303);
        wm8994_write(0x05, 0x3002);
        wm8994_write(0x06, 0x000A);
-       wm8994_set_volume(wm8994_current_mode,wm8994->call_vol,call_maxvol);
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
        wm8994_write(0x1E, 0x0006);
        wm8994_write(0x28, 0x00CC);
        wm8994_write(0x29, 0x0100);
@@ -1985,12 +1488,12 @@ void BT_baseband_and_record(void)
 
 /******************PCM BB BEGIN*****************/
 
-void handsetMIC_to_baseband_to_headset(void) //pcmbaseband
+static void handsetMIC_to_baseband_to_headset(void) //pcmbaseband
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_handsetMIC_to_baseband_to_headset)return;
-       wm8994_current_mode=wm8994_handsetMIC_to_baseband_to_headset;
+       if (wm8994_current_mode == wm8994_handsetMIC_to_baseband_to_headset)return;
+       wm8994_current_mode = wm8994_handsetMIC_to_baseband_to_headset;
        wm8994_reset();
        msleep(50);
        
@@ -2065,15 +1568,15 @@ void handsetMIC_to_baseband_to_headset(void) //pcmbaseband
        wm8994_write(0x317, 0x0003);
        wm8994_write(0x312, 0x0000); /// as slave  ///0x4000);  //AIF2 SET AS MASTER
        
-
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
 }
 
-void handsetMIC_to_baseband_to_headset_and_record(void) //pcmbaseband
+static void handsetMIC_to_baseband_to_headset_and_record(void) //pcmbaseband
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_handsetMIC_to_baseband_to_headset_and_record)return;
-       wm8994_current_mode=wm8994_handsetMIC_to_baseband_to_headset_and_record;
+       if (wm8994_current_mode == wm8994_handsetMIC_to_baseband_to_headset_and_record)return;
+       wm8994_current_mode = wm8994_handsetMIC_to_baseband_to_headset_and_record;
        wm8994_reset();
        msleep(50);
 
@@ -2151,15 +1654,15 @@ void handsetMIC_to_baseband_to_headset_and_record(void) //pcmbaseband
        wm8994_write(0x602,  0x0001);
        wm8994_write(0x700,  0x8140);//SYNC issue, AIF1 ADCLRC1 from FLL after AIF1 MASTER!!!
        
-       
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
 }
 
-void mainMIC_to_baseband_to_earpiece(void) //pcmbaseband
+static void mainMIC_to_baseband_to_earpiece(void) //pcmbaseband
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_mainMIC_to_baseband_to_earpiece)return;
-       wm8994_current_mode=wm8994_mainMIC_to_baseband_to_earpiece;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_earpiece)return;
+       wm8994_current_mode = wm8994_mainMIC_to_baseband_to_earpiece;
        wm8994_reset();
        msleep(50);
 
@@ -2235,15 +1738,15 @@ void mainMIC_to_baseband_to_earpiece(void) //pcmbaseband
        wm8994_write(0x317, 0x0003);
        wm8994_write(0x312, 0x0000);  //AIF2 SET AS MASTER
        
-       
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
 }
 
-void mainMIC_to_baseband_to_earpiece_and_record(void) //pcmbaseband
+static void mainMIC_to_baseband_to_earpiece_and_record(void) //pcmbaseband
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_mainMIC_to_baseband_to_earpiece_and_record)return;
-       wm8994_current_mode=wm8994_mainMIC_to_baseband_to_earpiece_and_record;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_earpiece_and_record)return;
+       wm8994_current_mode = wm8994_mainMIC_to_baseband_to_earpiece_and_record;
        wm8994_reset();
        msleep(50);
 
@@ -2261,7 +1764,8 @@ void mainMIC_to_baseband_to_earpiece_and_record(void) //pcmbaseband
        wm8994_write(0x03,  0x00F0);
        wm8994_write(0x04,  0x3003);
        wm8994_write(0x05,  0x3003); 
-       wm8994_write(0x1A,  0x010B); 
+       //wm8994_write(0x1A,  0x010B); 
+       wm8994_write(0x1A,  0x0101);
        wm8994_write(0x1F,  0x0000); 
        wm8994_write(0x28,  0x0003);
        wm8994_write(0x2A,  0x0020);
@@ -2319,15 +1823,15 @@ void mainMIC_to_baseband_to_earpiece_and_record(void) //pcmbaseband
        wm8994_write(0x602,  0x0001);
        wm8994_write(0x700,  0x8140);//SYNC issue, AIF1 ADCLRC1 from FLL after AIF1 MASTER!!!
        
-       
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
 }
 
-void mainMIC_to_baseband_to_speakers(void) //pcmbaseband
+static void mainMIC_to_baseband_to_speakers(void) //pcmbaseband
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_mainMIC_to_baseband_to_speakers)return;
-       wm8994_current_mode=wm8994_mainMIC_to_baseband_to_speakers;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_speakers)return;
+       wm8994_current_mode = wm8994_mainMIC_to_baseband_to_speakers;
        wm8994_reset();
        msleep(50);
 
@@ -2348,7 +1852,7 @@ void mainMIC_to_baseband_to_speakers(void) //pcmbaseband
        wm8994_write(0x1A,  0x011F);
        wm8994_write(0x22,  0x0000);
        wm8994_write(0x23,  0x0100);  ///0x0000);
-       //wm8994_write(0x25,  0x0152);
+       wm8994_write(0x25,  0x0152);
        wm8994_write(0x28,  0x0003);
        wm8994_write(0x2A,  0x0020);
        wm8994_write(0x2D,  0x0001);
@@ -2405,15 +1909,15 @@ void mainMIC_to_baseband_to_speakers(void) //pcmbaseband
        wm8994_write(0x317, 0x0003);
        wm8994_write(0x312, 0x0000);  //AIF2 SET AS MASTER
 
-
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
 }
 
-void mainMIC_to_baseband_to_speakers_and_record(void) //pcmbaseband
+static void mainMIC_to_baseband_to_speakers_and_record(void) //pcmbaseband
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_mainMIC_to_baseband_to_speakers_and_record)return;
-       wm8994_current_mode=wm8994_mainMIC_to_baseband_to_speakers_and_record;
+       if (wm8994_current_mode == wm8994_mainMIC_to_baseband_to_speakers_and_record)return;
+       wm8994_current_mode = wm8994_mainMIC_to_baseband_to_speakers_and_record;
        wm8994_reset();
        msleep(50);
 
@@ -2490,14 +1994,15 @@ void mainMIC_to_baseband_to_speakers_and_record(void) //pcmbaseband
        wm8994_write(0x602,  0x0001);
        wm8994_write(0x700,  0x8140);//SYNC issue, AIF1 ADCLRC1 from FLL after AIF1 MASTER!!!
        
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
 }
 
-void BT_baseband(void) //pcmbaseband
+static void BT_baseband(void) //pcmbaseband
 {
        DBG("%s::%d\n",__FUNCTION__,__LINE__);
 
-       if(wm8994_current_mode==wm8994_BT_baseband)return;
-       wm8994_current_mode=wm8994_BT_baseband;
+       if (wm8994_current_mode == wm8994_BT_baseband)return;
+       wm8994_current_mode = wm8994_BT_baseband;
        wm8994_reset();
        msleep(50);
 
@@ -2517,141 +2022,616 @@ void BT_baseband(void) //pcmbaseband
        wm8994_write(0x210 ,0x0009);// LRCK=8KHz, Rate=MCLK/1536
        wm8994_write(0x300 ,0x4018);// DSP/PCM 16bits
 
-       wm8994_write(0x204 ,0x0011);// AIF2 MCLK=FLL1
-       wm8994_write(0x211 ,0x0009);// LRCK=8KHz, Rate=MCLK/1536
-       wm8994_write(0x310 ,0x4118);// DSP/PCM 16bits
-       wm8994_write(0x208 ,0x000F); 
+       wm8994_write(0x204 ,0x0011);// AIF2 MCLK=FLL1
+       wm8994_write(0x211 ,0x0009);// LRCK=8KHz, Rate=MCLK/1536
+       wm8994_write(0x310 ,0x4118);// DSP/PCM 16bits
+       wm8994_write(0x208 ,0x000F); 
+
+/////AIF1
+       wm8994_write(0x700 ,0x8101);
+/////AIF2
+       wm8994_write(0x702 ,0xC100);
+       wm8994_write(0x703 ,0xC100);
+       wm8994_write(0x704 ,0xC100);
+       wm8994_write(0x706 ,0x4100);
+/////AIF3
+       wm8994_write(0x707 ,0xA100); 
+       wm8994_write(0x708 ,0xA100);
+       wm8994_write(0x709 ,0xA100); 
+       wm8994_write(0x70A ,0xA100);
+
+       wm8994_write(0x06 ,0x0001);
+
+       wm8994_write(0x02 ,0x0300);
+       wm8994_write(0x03 ,0x0030);
+       wm8994_write(0x04 ,0x3301);//ADCL off
+       wm8994_write(0x05 ,0x3301);//DACL off
+
+       wm8994_write(0x2A ,0x0005);
+
+       wm8994_write(0x313 ,0x00F0);
+       wm8994_write(0x314 ,0x0020);
+       wm8994_write(0x315 ,0x0020);
+
+       wm8994_write(0x2E ,0x0001);
+       wm8994_write(0x420 ,0x0000);
+       wm8994_write(0x520 ,0x0000);
+       wm8994_write(0x601 ,0x0001);
+       wm8994_write(0x602 ,0x0001);
+       wm8994_write(0x604 ,0x0001);
+       wm8994_write(0x605 ,0x0001);
+       wm8994_write(0x607 ,0x0002);
+       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
+       wm8994_write(0x612, 0x01C0);  //DAC2 Left Volume bit0~7 
+       wm8994_write(0x613, 0x01C0);  //DAC2 Right Volume bit0~7
+
+
+       wm8994_write(0x312 ,0x4000);
+
+       wm8994_write(0x606 ,0x0001);
+       wm8994_write(0x607 ,0x0003);//R channel for data mix/CPU record data
+
+
+////////////HP output test
+       wm8994_write(0x01 ,0x0303);
+       wm8994_write(0x4C ,0x9F25);
+       wm8994_write(0x60 ,0x00EE);
+///////////end HP test
+
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
+}
+
+static void BT_baseband_and_record(void) //pcmbaseband
+{
+       DBG("%s::%d\n",__FUNCTION__,__LINE__);
+
+       if (wm8994_current_mode == wm8994_BT_baseband_and_record)return;
+       wm8994_current_mode = wm8994_BT_baseband_and_record;
+       wm8994_reset();
+       msleep(50);
+
+       wm8994_write(0x01  ,0x0003);
+       msleep (50);
+
+       wm8994_write(0x200 ,0x0001);
+       wm8994_write(0x221 ,0x0700);//MCLK=12MHz
+       wm8994_write(0x222 ,0x3127);
+       wm8994_write(0x223 ,0x0100);
+       wm8994_write(0x220 ,0x0004);
+       msleep (50);
+       wm8994_write(0x220 ,0x0005); 
+
+       wm8994_write(0x02 ,0x0000); 
+       wm8994_write(0x200 ,0x0011);// AIF1 MCLK=FLL1
+       wm8994_write(0x210 ,0x0009);// LRCK=8KHz, Rate=MCLK/1536
+       wm8994_write(0x300 ,0x4018);// DSP/PCM 16bits
+
+       wm8994_write(0x204 ,0x0011);// AIF2 MCLK=FLL1
+       wm8994_write(0x211 ,0x0009);// LRCK=8KHz, Rate=MCLK/1536
+       wm8994_write(0x310 ,0x4118);// DSP/PCM 16bits
+       wm8994_write(0x208 ,0x000F); 
+
+/////AIF1
+       wm8994_write(0x700 ,0x8101);
+/////AIF2
+       wm8994_write(0x702 ,0xC100);
+       wm8994_write(0x703 ,0xC100);
+       wm8994_write(0x704 ,0xC100);
+       wm8994_write(0x706 ,0x4100);
+/////AIF3
+       wm8994_write(0x707 ,0xA100); 
+       wm8994_write(0x708 ,0xA100);
+       wm8994_write(0x709 ,0xA100); 
+       wm8994_write(0x70A ,0xA100);
+
+       wm8994_write(0x06 ,0x0001);
+       wm8994_write(0x02 ,0x0300);
+       wm8994_write(0x03 ,0x0030);
+       wm8994_write(0x04 ,0x3301);//ADCL off
+       wm8994_write(0x05 ,0x3301);//DACL off
+       wm8994_write(0x2A ,0x0005);
+
+       wm8994_write(0x313 ,0x00F0);
+       wm8994_write(0x314 ,0x0020);
+       wm8994_write(0x315 ,0x0020);
+
+       wm8994_write(0x2E  ,0x0001);
+       wm8994_write(0x420 ,0x0000);
+       wm8994_write(0x520 ,0x0000);
+       wm8994_write(0x602 ,0x0001);
+       wm8994_write(0x604 ,0x0001);
+       wm8994_write(0x605 ,0x0001);
+       wm8994_write(0x607 ,0x0002);
+       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
+       wm8994_write(0x612, 0x01C0);  //DAC2 Left Volume bit0~7 
+       wm8994_write(0x613, 0x01C0);  //DAC2 Right Volume bit0~7
+
+       wm8994_write(0x312 ,0x4000);
+
+       wm8994_write(0x606 ,0x0001);
+       wm8994_write(0x607 ,0x0003);//R channel for data mix/CPU record data
+////////////HP output test
+       wm8994_write(0x01 ,0x0303);
+       wm8994_write(0x4C ,0x9F25); 
+       wm8994_write(0x60 ,0x00EE); 
+///////////end HP test
+
+       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
+}
+#endif //PCM_BB
+
+
+typedef void (wm8994_codec_fnc_t) (void);
+
+static wm8994_codec_fnc_t *wm8994_codec_sequence[] = {
+       AP_to_headset,
+       AP_to_speakers,
+       AP_to_speakers_and_headset,
+       recorder_and_AP_to_headset,
+       recorder_and_AP_to_speakers,
+       FM_to_headset,
+       FM_to_headset_and_record,
+       FM_to_speakers,
+       FM_to_speakers_and_record,
+       handsetMIC_to_baseband_to_headset,
+       mainMIC_to_baseband_to_headset,
+       handsetMIC_to_baseband_to_headset_and_record,
+       mainMIC_to_baseband_to_earpiece,
+       mainMIC_to_baseband_to_earpiece_and_record,
+       mainMIC_to_baseband_to_speakers,
+       mainMIC_to_baseband_to_speakers_and_record,
+       BT_baseband,
+       BT_baseband_and_record,
+};
+
+static void wm8994_set_AIF1DAC_EQ(void) {
+
+       wm8994_write(0x0480, 0x0001|((bank_vol[1]+12)<<11)|
+               ((bank_vol[2]+12)<<6)|((bank_vol[3]+12)<<1));
+       wm8994_write(0x0481, 0x0000|((bank_vol[4]+12)<<11)|
+               ((bank_vol[5]+12)<<6));
+}
+
+static void wm8994_set_channel_vol(void)
+{
+       switch(wm8994_current_mode) {
+       case wm8994_AP_to_speakers_and_headset:
+               if (speaker_normal_vol > 6)
+                       speaker_normal_vol = 6;
+               else if (speaker_normal_vol < -57)
+                       speaker_normal_vol = -57;
+               if (headset_normal_vol > 6)
+                       headset_normal_vol = 6;
+               else if (headset_normal_vol < -57)
+                       headset_normal_vol = -57;
+
+               DBG("headset_normal_vol = %ddB \n",headset_normal_vol);
+               DBG("speaker_normal_vol = %ddB \n",speaker_normal_vol);
+
+               vol = speaker_normal_vol;
+               if (vol<=6) {
+                       wm8994_write(0x26,  320+vol+57);  //-57dB~6dB
+                       wm8994_write(0x27,  320+vol+57);  //-57dB~6dB
+               } else {
+                       wm8994_write(0x25,  0x003F);      //0~12dB
+                       wm8994_write(0x26,  320+vol+45);  //-57dB~6dB
+                       wm8994_write(0x27,  320+vol+45);  //-57dB~6dB
+               }
+               vol = headset_normal_vol-4;
+
+               /* for turn down headset volume when ringtone */
+               if (vol >= -48)
+                       vol -= 14;
+               else
+                       vol = -57;
+
+               wm8994_write(0x1C,  320+vol+57);  //-57dB~6dB
+               wm8994_write(0x1D,  320+vol+57);  //-57dB~6dB
+
+               wm8994_set_AIF1DAC_EQ();
+               break;
+
+       case wm8994_recorder_and_AP_to_headset:
+               if (headset_normal_vol > 6)
+                       headset_normal_vol = 6;
+               else if (headset_normal_vol < -57)
+                       headset_normal_vol = -57;
+               if (recorder_vol > 60)
+                       recorder_vol = 60;
+               else if (recorder_vol < -16)
+                       recorder_vol = -16;
+
+               DBG("recorder_vol = %ddB \n",recorder_vol);
+               DBG("headset_normal_vol = %ddB \n",headset_normal_vol);
+
+               vol = recorder_vol;
+               if (vol<30) {
+                       wm8994_write(0x1A,  320+(vol+16)*10/15);  //mic vol
+               } else {
+                       wm8994_write(0x2A,  0x0030);
+                       wm8994_write(0x1A,  320+(vol-14)*10/15);  //mic vol
+               }
+               vol = headset_normal_vol;
+               wm8994_write(0x1C,  320+vol+57);  //-57dB~6dB
+               wm8994_write(0x1D,  320+vol+57);  //-57dB~6dB
+               break;
+
+       case wm8994_recorder_and_AP_to_speakers:
+               if (recorder_vol > 60)
+                       recorder_vol = 60;
+               else if (recorder_vol < -16)
+                       recorder_vol = -16;
+               if (speaker_normal_vol > 6)
+                       speaker_normal_vol = 6;
+               else if (speaker_normal_vol < -57)
+                       speaker_normal_vol = -57;
+
+               DBG("speaker_normal_vol = %ddB \n",speaker_normal_vol);
+               DBG("recorder_vol = %ddB \n",recorder_vol);
+
+               vol = recorder_vol;
+               if (vol<30) {
+                       wm8994_write(0x1A,  320+(vol+16)*10/15);  //mic vol
+               } else {
+                       wm8994_write(0x2A,  0x0030);
+                       wm8994_write(0x1A,  320+(vol-14)*10/15);  //mic vol
+               }
+
+               vol = speaker_normal_vol;
+               wm8994_write(0x26,  320+vol+57);  //-57dB~6dB
+               wm8994_write(0x27,  320+vol+57);  //-57dB~6dB
+
+               wm8994_set_AIF1DAC_EQ();
+               break;
+
+       case wm8994_handsetMIC_to_baseband_to_headset:
+               if (headset_incall_vol > 6)
+                       headset_incall_vol = 6;
+               else if (headset_incall_vol < -12)
+                       headset_incall_vol = -12;
+               if (headset_incall_mic_vol > 30)
+                       headset_incall_mic_vol = 30;
+               else if (headset_incall_mic_vol < -22)
+                       headset_incall_mic_vol = -22;
+
+               DBG("headset_incall_mic_vol = %ddB \n",headset_incall_mic_vol);
+               DBG("headset_incall_vol = %ddB \n",headset_incall_vol);
+
+               vol = headset_incall_mic_vol;
+               if (vol<-16) {
+                       wm8994_write(0x1E,  0x0016);  //mic vol
+                       wm8994_write(0x18,  320+(vol+22)*10/15);  //mic vol     
+               } else {
+                       wm8994_write(0x1E,  0x0006);  //mic vol
+                       wm8994_write(0x18,  320+(vol+16)*10/15);  //mic vol
+               }
+#ifdef CONFIG_SND_BB_DIFFERENTIAL_INPUT
+               vol = headset_incall_vol;
+               wm8994_write(0x2B,  (vol+12)/3+1);  //-12~6dB
+#endif
+               break;
+
+       case wm8994_mainMIC_to_baseband_to_headset:
+               if (headset_incall_vol > 6)
+                       headset_incall_vol = 6;
+               else if (headset_incall_vol < -12)
+                       headset_incall_vol = -12;
+               if (speaker_incall_mic_vol > 30)
+                       speaker_incall_mic_vol = 30;
+               else if (speaker_incall_mic_vol < -22)
+                       speaker_incall_mic_vol = -22;
+
+               DBG("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
+               DBG("headset_incall_vol = %ddB \n",headset_incall_vol);
+
+               vol=speaker_incall_mic_vol;
+               if (vol<-16) {
+                       wm8994_write(0x1E,  0x0016);  //mic vol
+                       wm8994_write(0x1A,  320+(vol+22)*10/15);  //mic vol     
+               } else {
+                       wm8994_write(0x1E,  0x0006);  //mic vol
+                       wm8994_write(0x1A,  320+(vol+16)*10/15);  //mic vol
+               }
+#ifdef CONFIG_SND_BB_DIFFERENTIAL_INPUT
+               vol = headset_incall_vol;
+               wm8994_write(0x2B,  (vol+12)/3+1);  //-12~6dB
+#endif
+               break;
+
+#if defined(CONFIG_SND_INSIDE_EARPIECE)||defined(CONFIG_SND_OUTSIDE_EARPIECE)
+       case wm8994_mainMIC_to_baseband_to_earpiece:
+               if (speaker_incall_mic_vol > 30)
+                       speaker_incall_mic_vol = 30;
+               else if (speaker_incall_mic_vol < -22)
+                       speaker_incall_mic_vol = -22;
+               if (earpiece_incall_vol>6)
+                       earpiece_incall_vol = 6;
+               else if (earpiece_incall_vol<-21)
+                       earpiece_incall_vol = -21;
+
+               DBG("earpiece_incall_vol = %ddB \n",earpiece_incall_vol);
+               DBG("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
+
+               vol = earpiece_incall_vol;
+               if (vol>=0) {
+                       wm8994_write(0x33,  0x0018);  //6dB
+                       wm8994_write(0x31,  (((6-vol)/3)<<3)+(6-vol)/3);  //-21dB
+               } else {
+                       wm8994_write(0x33,  0x0010);
+                       wm8994_write(0x31,  (((-vol)/3)<<3)+(-vol)/3);  //-21dB
+               }
+#ifdef CONFIG_SND_INSIDE_EARPIECE
+               vol = speaker_incall_mic_vol;
+               if (vol<-16) {
+                       wm8994_write(0x1E,  0x0016);
+                       wm8994_write(0x1A,  320+(vol+22)*10/15);        
+               } else {
+                       wm8994_write(0x1E,  0x0006);
+                       wm8994_write(0x1A,  320+(vol+16)*10/15);
+               }
+#endif
+#ifdef CONFIG_SND_OUTSIDE_EARPIECE
+               vol = headset_incall_mic_vol;
+               if (vol<-16) {
+                       wm8994_write(0x1E,  0x0016);  //mic vol
+                       wm8994_write(0x18,  320+(vol+22)*10/15);  //mic vol     
+               } else {
+                       wm8994_write(0x1E,  0x0006);  //mic vol
+                       wm8994_write(0x18,  320+(vol+16)*10/15);  //mic vol
+               }
+#endif
+               break;
+#endif
+       case wm8994_mainMIC_to_baseband_to_speakers:
+               if (speaker_incall_mic_vol > 30)
+                       speaker_incall_mic_vol = 30;
+               else if (speaker_incall_mic_vol < -22)
+                       speaker_incall_mic_vol = -22;
+               if (speaker_incall_vol > 12)
+                       speaker_incall_vol = 12;
+               else if (speaker_incall_vol < -21)
+                       speaker_incall_vol = -21;
+
+               DBG("speaker_incall_vol = %ddB \n",speaker_incall_vol);
+               DBG("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
+
+               vol = speaker_incall_mic_vol;
+               if (vol<-16) {
+                       wm8994_write(0x1E,  0x0016);
+                       wm8994_write(0x1A,  320+(vol+22)*10/15);        
+               } else {
+                       wm8994_write(0x1E,  0x0006);
+                       wm8994_write(0x1A,  320+(vol+16)*10/15);
+               }
+               vol = speaker_incall_vol;
+               if (vol<=0) {
+                       wm8994_write(0x31,  (((-vol)/3)<<3)+(-vol)/3);
+               } else if (vol <= 9) {
+                       wm8994_write(0x25,  ((vol*10/15)<<3)+vol*10/15);
+               } else {
+                       wm8994_write(0x25,  0x003F);
+               }
+               break;
+
+       case wm8994_BT_baseband:
+               if (BT_incall_vol > 30)
+                       BT_incall_vol = 30;
+               else if (BT_incall_vol < -16)
+                       BT_incall_vol = -16;
+               if (BT_incall_mic_vol > 6)
+                       BT_incall_mic_vol = 6;
+               else if (BT_incall_mic_vol < -57)
+                       BT_incall_mic_vol = -57;
+
+               DBG("BT_incall_mic_vol = %ddB \n",BT_incall_mic_vol);
+               DBG("BT_incall_vol = %ddB \n",BT_incall_vol);
+
+               vol = BT_incall_mic_vol;
+               wm8994_write(0x20,  320+vol+57);
+
+               vol = BT_incall_vol;
+               wm8994_write(0x19, 0x0500+(vol+16)*10/15);
+               break;
+       default:
+               printk("route error !\n");
+       }
+
+}
+
+void wm8994_codec_set_volume(unsigned char system_type,unsigned char volume)
+{
+       DBG("%s:: system_type = %d volume = %d \n",__FUNCTION__,system_type,volume);
+
+       if (system_type == VOICE_CALL)
+       {
+               if (volume <= call_maxvol)
+                       call_vol=volume;
+               else {
+                       printk("%s----%d::max value is 7\n",__FUNCTION__,__LINE__);
+                       call_vol=call_maxvol;
+               }
+               if (wm8994_current_mode <= wm8994_mainMIC_to_baseband_to_speakers_and_record&&
+               wm8994_current_mode >= wm8994_handsetMIC_to_baseband_to_headset)
+                       wm8994_set_volume(wm8994_current_mode,call_vol,call_maxvol);
+       } else if (system_type == BLUETOOTH_SCO) {
+               if (volume <= BT_call_maxvol)
+                       BT_call_vol = volume;
+               else {
+                       printk("%s----%d::max value is 15\n",__FUNCTION__,__LINE__);
+                       BT_call_vol = BT_call_maxvol;
+               }
+               if (wm8994_current_mode<null&&
+               wm8994_current_mode >= wm8994_BT_baseband)
+                       wm8994_set_volume(wm8994_current_mode,BT_call_vol,BT_call_maxvol);
+       }else {
+               return;
+               printk("%s----%d::system type error!\n",__FUNCTION__,__LINE__);
+       }
+}
+
+static void wm8994_set_volume(unsigned char wm8994_mode,unsigned char volume,unsigned char max_volume)
+{
+       unsigned short lvol=0,rvol=0;
+
+       DBG("%s::volume = %d \n",__FUNCTION__,volume);
 
-/////AIF1
-       wm8994_write(0x700 ,0x8101);
-/////AIF2
-       wm8994_write(0x702 ,0xC100);
-       wm8994_write(0x703 ,0xC100);
-       wm8994_write(0x704 ,0xC100);
-       wm8994_write(0x706 ,0x4100);
-/////AIF3
-       wm8994_write(0x707 ,0xA100); 
-       wm8994_write(0x708 ,0xA100);
-       wm8994_write(0x709 ,0xA100); 
-       wm8994_write(0x70A ,0xA100);
+       if (volume>max_volume)volume=max_volume;
+       
+       if (wm8994_mode == wm8994_handsetMIC_to_baseband_to_headset_and_record||
+       wm8994_mode == wm8994_handsetMIC_to_baseband_to_headset||
+       wm8994_mode == wm8994_mainMIC_to_baseband_to_headset)
+       {
+               wm8994_read(0x001C, &lvol);
+               wm8994_read(0x001D, &rvol);
+               //HPOUT1L_VOL bit 0~5 /-57dB to +6dB in 1dB steps
+               wm8994_write(0x001C, (lvol&~0x003f)|headset_vol_table[volume]); 
+               //HPOUT1R_VOL bit 0~5 /-57dB to +6dB in 1dB steps
+               wm8994_write(0x001D, (rvol&~0x003f)|headset_vol_table[volume]); 
+       } else if (wm8994_mode == wm8994_mainMIC_to_baseband_to_speakers_and_record||
+       wm8994_mode == wm8994_mainMIC_to_baseband_to_speakers)
+       {
+               wm8994_read(0x0026, &lvol);
+               wm8994_read(0x0027, &rvol);
+               //SPKOUTL_VOL bit 0~5 /-57dB to +6dB in 1dB steps
+               wm8994_write(0x0026, (lvol&~0x003f)|speakers_vol_table[volume]);
+               //SPKOUTR_VOL bit 0~5 /-57dB to +6dB in 1dB steps
+               wm8994_write(0x0027, (rvol&~0x003f)|speakers_vol_table[volume]);
+       } else if (wm8994_mode == wm8994_mainMIC_to_baseband_to_earpiece||
+       wm8994_mode == wm8994_mainMIC_to_baseband_to_earpiece_and_record)
+       {
+               wm8994_read(0x0020, &lvol);
+               wm8994_read(0x0021, &rvol);
+
+               //MIXOUTL_VOL bit 0~5 /-57dB to +6dB in 1dB steps
+               wm8994_write(0x0020, (lvol&~0x003f)|earpiece_vol_table[volume]);
+               //MIXOUTR_VOL bit 0~5 /-57dB to +6dB in 1dB steps
+               wm8994_write(0x0021, (rvol&~0x003f)|earpiece_vol_table[volume]);
+       } else if (wm8994_mode == wm8994_BT_baseband||wm8994_mode == wm8994_BT_baseband_and_record)
+       {
+               //bit 0~4 /-16.5dB to +30dB in 1.5dB steps
+               DBG("BT_vol_table[volume] = 0x%x\n",BT_vol_table[volume]);
+               wm8994_write(0x0500, BT_vol_table[volume]);
+               wm8994_write(0x0501, 0x0100);
+       } else if (wm8994_mode == null)
+       {
+               wm8994_read(0x001C, &lvol);
+               wm8994_read(0x001D, &rvol);
+               wm8994_write(0x001C, (lvol&~0x003f)|headset_vol_table[volume]); 
+               wm8994_write(0x001D, (rvol&~0x003f)|headset_vol_table[volume]); 
+               wm8994_read(0x0026, &lvol);
+               wm8994_read(0x0027, &rvol);
+               wm8994_write(0x0026, (lvol&~0x003f)|speakers_vol_table[volume]);
+               wm8994_write(0x0027, (rvol&~0x003f)|speakers_vol_table[volume]);        
+               wm8994_read(0x0020, &lvol);
+               wm8994_read(0x0021, &rvol);
+               wm8994_write(0x0020, (lvol&~0x003f)|earpiece_vol_table[volume]);
+               wm8994_write(0x0021, (rvol&~0x003f)|earpiece_vol_table[volume]);                
+       }
+}
 
-       wm8994_write(0x06 ,0x0001);
+static void wm8994_check_channel(void)
+{
+       wm8994_codec_fnc_t **wm8994_fnc_ptr = wm8994_codec_sequence;
+       unsigned char wm8994_mode = wm8994_current_mode;
 
-       wm8994_write(0x02 ,0x0300);
-       wm8994_write(0x03 ,0x0030);
-       wm8994_write(0x04 ,0x3301);//ADCL off
-       wm8994_write(0x05 ,0x3301);//DACL off
+       DBG("%s--%d::Enter\n",__FUNCTION__,__LINE__);
 
-       wm8994_write(0x2A ,0x0005);
+       if (wm8994_mode < wm8994_AP_to_headset ||
+               wm8994_mode > wm8994_BT_baseband_and_record)
+       {
+               wm8994_mode = wm8994_recorder_and_AP_to_speakers;
+               printk("%s--%d--: Wm8994 set channel with null mode\n",__FUNCTION__,__LINE__);
+       }
 
-       wm8994_write(0x313 ,0x00F0);
-       wm8994_write(0x314 ,0x0020);
-       wm8994_write(0x315 ,0x0020);
+       wm8994_fnc_ptr += wm8994_mode;
 
-       wm8994_write(0x2E ,0x0001);
-       wm8994_write(0x420 ,0x0000);
-       wm8994_write(0x520 ,0x0000);
-       wm8994_write(0x601 ,0x0001);
-       wm8994_write(0x602 ,0x0001);
-       wm8994_write(0x604 ,0x0001);
-       wm8994_write(0x605 ,0x0001);
-       wm8994_write(0x607 ,0x0002);
-       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
-       wm8994_write(0x612, 0x01C0);  //DAC2 Left Volume bit0~7 
-       wm8994_write(0x613, 0x01C0);  //DAC2 Right Volume bit0~7
+       while(isSetChannelErr) {
+               gpio_request(WM_EN_PIN, NULL);
+               gpio_direction_output(WM_EN_PIN,GPIO_LOW);
+               gpio_free(WM_EN_PIN);
 
+               msleep(50);
 
-       wm8994_write(0x312 ,0x4000);
+               gpio_request(WM_EN_PIN, NULL);
+               gpio_direction_output(WM_EN_PIN,GPIO_HIGH);
+               gpio_free(WM_EN_PIN);
 
-       wm8994_write(0x606 ,0x0001);
-       wm8994_write(0x607 ,0x0003);//R channel for data mix/CPU record data
+               msleep(50);
 
+               wm8994_current_mode = null;
+               isSetChannelErr = false;
 
-////////////HP output test
-       wm8994_write(0x01 ,0x0303);
-       wm8994_write(0x4C ,0x9F25);
-       wm8994_write(0x60 ,0x00EE);
-///////////end HP test
+               (*wm8994_fnc_ptr)() ;
+       }
 
+       DBG("%s--%d::Exit\n",__FUNCTION__,__LINE__);
 }
 
-void BT_baseband_and_record(void) //pcmbaseband
+static int wm8994_powerdown(void)
 {
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
+       printk("Power down wm8994\n");
 
-       if(wm8994_current_mode==wm8994_BT_baseband_and_record)return;
-       wm8994_current_mode=wm8994_BT_baseband_and_record;
-       wm8994_reset();
-       msleep(50);
+       isWM8994SetChannel = true;
 
-       wm8994_write(0x01  ,0x0003);
-       msleep (50);
+       wm8994_write(0x00, 0x0000);
+       msleep(50);
 
-       wm8994_write(0x200 ,0x0001);
-       wm8994_write(0x221 ,0x0700);//MCLK=12MHz
-       wm8994_write(0x222 ,0x3127);
-       wm8994_write(0x223 ,0x0100);
-       wm8994_write(0x220 ,0x0004);
-       msleep (50);
-       wm8994_write(0x220 ,0x0005); 
+       wm8994_write(0x01, 0x0003);
+       msleep(50);
+       wm8994_write(0x01, 0x0023);
 
-       wm8994_write(0x02 ,0x0000); 
-       wm8994_write(0x200 ,0x0011);// AIF1 MCLK=FLL1
-       wm8994_write(0x210 ,0x0009);// LRCK=8KHz, Rate=MCLK/1536
-       wm8994_write(0x300 ,0x4018);// DSP/PCM 16bits
+       if (wm8994_current_mode == wm8994_AP_to_headset ||
+          wm8994_current_mode == wm8994_AP_to_speakers_and_headset ||
+          wm8994_current_mode == wm8994_recorder_and_AP_to_headset) {
+               wm8994_current_mode = wm8994_powerdown_headset;
+       } else if (wm8994_current_mode == wm8994_AP_to_speakers ||
+                wm8994_current_mode == wm8994_recorder_and_AP_to_speakers) {
+               wm8994_current_mode = wm8994_powerdown_speakers;
+       } else {
+               wm8994_current_mode = wm8994_powerdown_speakers;
+       }
 
-       wm8994_write(0x204 ,0x0011);// AIF2 MCLK=FLL1
-       wm8994_write(0x211 ,0x0009);// LRCK=8KHz, Rate=MCLK/1536
-       wm8994_write(0x310 ,0x4118);// DSP/PCM 16bits
-       wm8994_write(0x208 ,0x000F); 
+       isWM8994SetChannel = false;
+       return 0;
+}
 
-/////AIF1
-       wm8994_write(0x700 ,0x8101);
-/////AIF2
-       wm8994_write(0x702 ,0xC100);
-       wm8994_write(0x703 ,0xC100);
-       wm8994_write(0x704 ,0xC100);
-       wm8994_write(0x706 ,0x4100);
-/////AIF3
-       wm8994_write(0x707 ,0xA100); 
-       wm8994_write(0x708 ,0xA100);
-       wm8994_write(0x709 ,0xA100); 
-       wm8994_write(0x70A ,0xA100);
+static void  wm8994_work(struct work_struct *work)
+{
+       DBG("Enter::wm8994 work\n");
 
-       wm8994_write(0x06 ,0x0001);
-       wm8994_write(0x02 ,0x0300);
-       wm8994_write(0x03 ,0x0030);
-       wm8994_write(0x04 ,0x3301);//ADCL off
-       wm8994_write(0x05 ,0x3301);//DACL off
-       wm8994_write(0x2A ,0x0005);
+       switch(wm8994_work_type) {
+       case WM8994_WORK_FIRSTINCALL:
+               if (wm8994_current_mode == wm8994_BT_baseband) {
+                       wm8994_write(0x602, 0x0001);
+               } else {
+                       wm8994_write(0x601, 0x0001);
+                       wm8994_write(0x602, 0x0001);
+               }
+               break;
 
-       wm8994_write(0x313 ,0x00F0);
-       wm8994_write(0x314 ,0x0020);
-       wm8994_write(0x315 ,0x0020);
+       case WM8994_WORK_SHUTDOWN:
+               wm8994_powerdown();//close codec
+               break;
 
-       wm8994_write(0x2E  ,0x0001);
-       wm8994_write(0x420 ,0x0000);
-       wm8994_write(0x520 ,0x0000);
-       wm8994_write(0x602 ,0x0001);
-       wm8994_write(0x604 ,0x0001);
-       wm8994_write(0x605 ,0x0001);
-       wm8994_write(0x607 ,0x0002);
-       wm8994_write(0x611, 0x01C0);  //DAC1 Right Volume bit0~7
-       wm8994_write(0x612, 0x01C0);  //DAC2 Left Volume bit0~7 
-       wm8994_write(0x613, 0x01C0);  //DAC2 Right Volume bit0~7
+       case WM8994_WORK_STARTUP:
+               isWM8994SetChannel = true;
 
-       wm8994_write(0x312 ,0x4000);
+               if (wm8994_current_mode == wm8994_powerdown_speakers) {
+                       recorder_and_AP_to_speakers();
+               } else if (wm8994_current_mode == wm8994_powerdown_headset) {
+                       recorder_and_AP_to_headset();
+               }
 
-       wm8994_write(0x606 ,0x0001);
-       wm8994_write(0x607 ,0x0003);//R channel for data mix/CPU record data
-////////////HP output test
-       wm8994_write(0x01 ,0x0303);
-       wm8994_write(0x4C ,0x9F25); 
-       wm8994_write(0x60 ,0x00EE); 
-///////////end HP test
+               wm8994_check_channel();
+               isWM8994SetChannel = false;
+               break;
 
+       default:
+               break;
+       }
+       
+       wm8994_work_type = WM8994_WORK_NULL;
 }
-#endif //PCM_BB
 
 #define SOC_DOUBLE_SWITCH_WM8994CODEC(xname, route) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -2679,121 +2659,114 @@ int snd_soc_get_route(struct snd_kcontrol *kcontrol,
 int snd_soc_put_route(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
        char route = kcontrol->private_value & 0xff;
-       wake_lock(&wm8994->wm8994_on_wake);
-       mutex_lock(&wm8994->route_lock);
-       wm8994->kcontrol = kcontrol;//save rount
 
-       //before set the route -- disable PA
-       PA_ctrl(GPIO_LOW);
+       DBG("%s--%d::Enter : route = %d \n",__FUNCTION__, __LINE__, route);
+
+#ifdef WM8994_PROC
+       wm8994_current_route = route;
+#endif
+
+       if (wm8994_work_type != WM8994_WORK_FIRSTINCALL) {
+               cancel_delayed_work_sync(&delayed_work);
+               wm8994_work_type = WM8994_WORK_NULL;
+       }
 
-       //set rount
+       isWM8994SetChannel = true;
        switch(route)
        {
-               case SPEAKER_NORMAL:                                            //AP-> 8994Codec -> Speaker
-               case SPEAKER_RINGTONE:                  
-               case EARPIECE_RINGTONE: 
+               /* Speaker*/
+               case SPEAKER_NORMAL: //AP-> 8994Codec -> Speaker
                        recorder_and_AP_to_speakers();
                        break;
-               case SPEAKER_INCALL:                                            //BB-> 8994Codec -> Speaker
+
+               case SPEAKER_INCALL: //BB-> 8994Codec -> Speaker
                        mainMIC_to_baseband_to_speakers();
-                       break;                                  
-               case HEADSET_NORMAL:                                            //AP-> 8994Codec -> Headset
+                       break;          
+                       
+               /* Headset */   
+               case HEADSET_NORMAL:    //AP-> 8994Codec -> Headset
                        recorder_and_AP_to_headset();
                        break;
-               case HEADSET_INCALL:                                            //AP-> 8994Codec -> Headset
-                       if(Headset_isMic())
+               case HEADSET_INCALL:    //AP-> 8994Codec -> Headset
+                       //if (isHSKey_MIC())
                                handsetMIC_to_baseband_to_headset();
-                       else
-                               mainMIC_to_baseband_to_headset();
-                       break;      
-               case EARPIECE_INCALL:                                           //BB-> 8994Codec -> EARPIECE
+                       //else
+                       //      mainMIC_to_baseband_to_headset();
+                       break;              
+
+               /* Earpiece*/                       
+               case EARPIECE_INCALL:   //:BB-> 8994Codec -> EARPIECE
+#ifdef CONFIG_SND_NO_EARPIECE
+                       mainMIC_to_baseband_to_speakers();
+#else
                        mainMIC_to_baseband_to_earpiece();
+#endif
                        break;
-               case EARPIECE_NORMAL:                                           //BB-> 8994Codec -> EARPIECE
-                       switch(wm8994_current_mode)
-                       {
-                               case wm8994_handsetMIC_to_baseband_to_headset:
-                               case wm8994_mainMIC_to_baseband_to_headset:
-                                       recorder_and_AP_to_headset();
-                                       break;
-                               default:
-                                       recorder_and_AP_to_speakers();  
-                                       break;
-                       }
-                       break;          
-               case BLUETOOTH_SCO_INCALL:                                      //BB-> 8994Codec -> BLUETOOTH_SCO 
+
+               case EARPIECE_NORMAL:   //:BB-> 8994Codec -> EARPIECE
+                       if (wm8994_current_mode == wm8994_handsetMIC_to_baseband_to_headset||
+                       wm8994_mainMIC_to_baseband_to_headset)
+                               recorder_and_AP_to_headset();
+                       else if (wm8994_current_mode == wm8994_recorder_and_AP_to_speakers||
+                               wm8994_current_mode == wm8994_recorder_and_AP_to_speakers)
+                               break;
+                       else {
+                               recorder_and_AP_to_speakers();
+                               printk("%s--%d--: wm8994 with null mode\n",__FUNCTION__,__LINE__);
+                       }       
+                       break;
+
+
+               /* BLUETOOTH_SCO*/                      
+               case BLUETOOTH_SCO_INCALL:      //BB-> 8994Codec -> BLUETOOTH_SCO  
                        BT_baseband();
-                       break;   
+                       break;
+
+               /* BLUETOOTH_A2DP*/                         
+               case BLUETOOTH_A2DP_NORMAL:     //AP-> 8994Codec -> BLUETOOTH_A2DP
+                       break;
+                   
                case MIC_CAPTURE:
-                       switch(wm8994_current_mode)
-                       {
-                               case wm8994_AP_to_headset:
-                                       recorder_and_AP_to_headset();
-                                       break;
-                               case wm8994_AP_to_speakers:
-                                       recorder_and_AP_to_speakers();
-                                       break;
-                               case wm8994_recorder_and_AP_to_speakers:
-                               case wm8994_recorder_and_AP_to_headset:
-                                       break;
-                               default:
-                                       recorder_and_AP_to_speakers();  
-                                       break;
+                       if (wm8994_current_mode == wm8994_AP_to_headset ||
+                          wm8994_current_mode == wm8994_recorder_and_AP_to_headset ||
+                          wm8994_current_mode == wm8994_powerdown_headset)
+                               recorder_and_AP_to_headset();
+                       else if (wm8994_current_mode == wm8994_AP_to_speakers ||
+                               wm8994_current_mode == wm8994_recorder_and_AP_to_speakers ||
+                               wm8994_current_mode == wm8994_powerdown_speakers)
+                               recorder_and_AP_to_speakers();
+                       else {
+                               printk("%s--%d--: wm8994 with error mode\n",__FUNCTION__,__LINE__);
+                               recorder_and_AP_to_speakers();
                        }
                        break;
+
+               case EARPIECE_RINGTONE:
+                       recorder_and_AP_to_speakers();
+                       break;
+
                case HEADSET_RINGTONE:
                        AP_to_speakers_and_headset();
                        break;
-               case BLUETOOTH_A2DP_NORMAL:                                     //AP-> 8994Codec -> BLUETOOTH_A2DP
-               case BLUETOOTH_A2DP_INCALL:
-               case BLUETOOTH_SCO_NORMAL:
-                       printk("this route not use\n");
-                       break;                                  
-               default:
-                       printk("wm8994 error route!!!\n");
-                       goto out;
-       }
 
-       if(wm8994->RW_status == ERROR)
-       {//Failure to read or write, will re-power on wm8994
-               cancel_delayed_work_sync(&wm8994->wm8994_delayed_work);
-               wm8994->work_type = SNDRV_PCM_TRIGGER_PAUSE_PUSH;
-               schedule_delayed_work(&wm8994->wm8994_delayed_work, msecs_to_jiffies(10));
-               goto out;
-       }
-       //after set the route -- enable PA
-       switch(route)
-       {
-               case MIC_CAPTURE:
-                       if(wm8994_current_mode == wm8994_AP_to_headset)
-                               break;
-               case EARPIECE_NORMAL:
-                       if(wm8994_current_mode == wm8994_handsetMIC_to_baseband_to_headset||
-                               wm8994_current_mode == wm8994_mainMIC_to_baseband_to_headset)
-                               break;
-               case SPEAKER_NORMAL:    
                case SPEAKER_RINGTONE:
-               case SPEAKER_INCALL:                    
-               case EARPIECE_RINGTONE: 
-               case HEADSET_RINGTONE:
-                       msleep(50);
-                       PA_ctrl(GPIO_HIGH);                             
+                       recorder_and_AP_to_speakers();
                        break;
-               default:                
+
+               default:
+                       //codec_daout_route();
                        break;
-       }       
-out:   
-       mutex_unlock(&wm8994->route_lock);      
-       wake_unlock(&wm8994->wm8994_on_wake);   
+       }
+       wm8994_check_channel();
+
+       isWM8994SetChannel = false;
+
        return 0;
 }
 
-/*
- * WM8994 Controls
- */
 static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+
 SOC_DOUBLE_SWITCH_WM8994CODEC("Speaker incall Switch", SPEAKER_INCALL),        
 SOC_DOUBLE_SWITCH_WM8994CODEC("Speaker normal Switch", SPEAKER_NORMAL),
 
@@ -2816,263 +2789,82 @@ SOC_DOUBLE_SWITCH_WM8994CODEC("Speaker ringtone Switch",SPEAKER_RINGTONE),
 SOC_DOUBLE_SWITCH_WM8994CODEC("Headset ringtone Switch",HEADSET_RINGTONE),
 };
 
-static void wm8994_codec_set_volume(unsigned char system_type,unsigned char volume)
-{
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
-//     DBG("%s:: system_type = %d volume = %d \n",__FUNCTION__,system_type,volume);
-
-       if(system_type == VOICE_CALL)
-       {
-               if(volume <= call_maxvol)
-                       wm8994->call_vol=volume;
-               else
-               {
-                       printk("%s----%d::max value is 5\n",__FUNCTION__,__LINE__);
-                       wm8994->call_vol=call_maxvol;
-               }
-               if(wm8994_current_mode<=wm8994_mainMIC_to_baseband_to_speakers_and_record&&
-                       wm8994_current_mode>=wm8994_handsetMIC_to_baseband_to_headset)
-                       wm8994_set_volume(wm8994_current_mode,wm8994->call_vol,call_maxvol);
-       }
-       else if(system_type == BLUETOOTH_SCO)
-       {
-               if(volume <= BT_call_maxvol)
-                       wm8994->BT_call_vol = volume;
-               else
-               {
-                       printk("%s----%d::max value is 15\n",__FUNCTION__,__LINE__);
-                       wm8994->BT_call_vol = BT_call_maxvol;
-               }
-               if(wm8994_current_mode<null&&
-                       wm8994_current_mode>=wm8994_BT_baseband)
-                       wm8994_set_volume(wm8994_current_mode,wm8994->BT_call_vol,BT_call_maxvol);
-       }
-       else
-       {
-               printk("%s----%d::system type error!\n",__FUNCTION__,__LINE__);
-               return;
-       }
-}
-
-/*
- * Note that this should be called from init rather than from hw_params.
- */
-static int wm8994_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 wm8994_priv *wm8994 = codec->private_data;
-       
-//     DBG("%s----%d\n",__FUNCTION__,__LINE__);
-
-       switch (clk_id) {
-       case WM8994_SYSCLK_MCLK1:
-               wm8994->sysclk = WM8994_SYSCLK_MCLK1;
-               wm8994->mclk = freq;
-       //      DBG("AIF1 using MCLK1 at %uHz\n", freq);
-               break;
-
-       case WM8994_SYSCLK_MCLK2:
-               //TODO: Set GPIO AF 
-               wm8994->sysclk = WM8994_SYSCLK_MCLK2;
-               wm8994->mclk = freq;
-       //      DBG("AIF1 using MCLK2 at %uHz\n",freq);
-               break;
-
-       case WM8994_SYSCLK_FLL1:
-               wm8994->sysclk = WM8994_SYSCLK_FLL1;
-               wm8994->mclk = freq;
-       //      DBG("AIF1 using FLL1 at %uHz\n",freq);
-               break;
-
-       case WM8994_SYSCLK_FLL2:
-               wm8994->sysclk = WM8994_SYSCLK_FLL2;
-               wm8994->mclk = freq;
-       //      DBG("AIF1 using FLL2 at %uHz\n",freq);
-               break;
-
-       default:
-               DBG("ERROR:AIF3 shares clocking with AIF1/2. \n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int wm8994_set_dai_fmt(struct snd_soc_dai *codec_dai,
-               unsigned int fmt)
-{
-       struct snd_soc_codec *codec = codec_dai->codec;
-       struct wm8994_priv *wm8994 = codec->private_data;
-//     DBG("Enter %s---%d\n",__FUNCTION__,__LINE__);
-
-       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-       case SND_SOC_DAIFMT_CBS_CFS:
-               wm8994->fmt = SND_SOC_DAIFMT_CBS_CFS;
-               break;
-       case SND_SOC_DAIFMT_CBM_CFM:
-               wm8994->fmt = SND_SOC_DAIFMT_CBM_CFM;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-
-       return 0;       
-}
-
-static int wm8994_pcm_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params,
-                               struct snd_soc_dai *dai)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct wm8994_priv *wm8994 = codec->private_data;
-
-//     DBG("Enter %s::%s---%d\n",__FILE__,__FUNCTION__,__LINE__);      
-
-       wm8994->rate = params_rate(params);
-//     DBG("Sample rate is %dHz\n",wm8994->rate);
-
-       return 0;
-}
-
-static int wm8994_mute(struct snd_soc_dai *dai, int mute)
-{
-       return 0;
-}
-
 static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
+       codec->bias_level = level;
        return 0;
 }
 
 static int wm8994_trigger(struct snd_pcm_substream *substream,
-                         int cmd,
+                         int status,
                          struct snd_soc_dai *dai)
 {
-//     struct snd_soc_pcm_runtime *rtd = substream->private_data;
-//     struct snd_soc_dai_link *machine = rtd->dai;
-//     struct snd_soc_dai *codec_dai = machine->codec_dai;
-       struct snd_soc_codec *codec = dai->codec;
-       struct wm8994_priv *wm8994 = codec->private_data;
-       
-       if(wm8994_current_mode >= wm8994_handsetMIC_to_baseband_to_headset && wm8994_current_mode != null)
-               return 0;
-//     DBG("%s::%d status = %d substream->stream '%s'\n",__FUNCTION__,__LINE__,
-//         cmd, substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE");
-       
-       switch(cmd)
-       {
-               case SNDRV_PCM_TRIGGER_STOP:
-               case SNDRV_PCM_TRIGGER_START:
-                       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                       {
-                               if(wm8994->playback_active == cmd)
-                                       return 0;
-                               wm8994->playback_active = cmd;
-                       }       
-                       else
-                       {
-                               if(wm8994->capture_active == cmd)
-                                       return 0;
-                               wm8994->capture_active = cmd;   
-                       }       
-                       break;
-               default:
-                       return 0;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai_link *machine = rtd->dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
+       unsigned int playback_active = codec_dai->playback.active, capture_active = codec_dai->capture.active;
+
+       DBG("%s::%d status = %d substream->stream '%s'\n",__FUNCTION__,__LINE__,
+           status, substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE");
+
+       if (status == 1 || status == 0) {
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+                       codec_dai->playback.active = status;
+               }else {
+
+                       codec_dai->capture.active = status;
+               }
        }
 
-       if (!wm8994->playback_active && 
-               !wm8994->capture_active )
-       {//suspend
+       if (!codec_dai->playback.active && !codec_dai->capture.active
+       && (playback_active || capture_active)
+       && (wm8994_current_mode < wm8994_handsetMIC_to_baseband_to_headset)) {
                DBG("It's going to power down wm8994\n");
-               cancel_delayed_work_sync(&wm8994->wm8994_delayed_work);         
-               wm8994->work_type = SNDRV_PCM_TRIGGER_STOP;
-               schedule_delayed_work(&wm8994->wm8994_delayed_work, msecs_to_jiffies(2000));
-       } 
-       else if (wm8994->playback_active 
-                       || wm8994->capture_active) 
-       {//resume
-               DBG("Power up wm8994\n");       
-               if(wm8994->work_type == SNDRV_PCM_TRIGGER_STOP)
-                       cancel_delayed_work_sync(&wm8994->wm8994_delayed_work);
-               wm8994->work_type = SNDRV_PCM_TRIGGER_START;
-               schedule_delayed_work(&wm8994->wm8994_delayed_work, msecs_to_jiffies(0));               
-       }
 
-       return 0;
-}
+               cancel_delayed_work_sync(&delayed_work);
 
-static void wm8994_work_fun(struct work_struct *work)
-{      
-       struct snd_soc_codec *codec = wm8994_codec;
-       struct wm8994_priv *wm8994 = codec->private_data;
-       struct wm8994_pdata *pdata = wm8994->pdata;
-       int error_count = 5;
-//     DBG("Enter %s---%d = %d\n",__FUNCTION__,__LINE__,wm8994_current_mode);
+               wm8994_work_type = WM8994_WORK_SHUTDOWN;
+               /* when codec is not using , close it */
 
-       switch(wm8994->work_type)
-       {
-       case SNDRV_PCM_TRIGGER_STOP:
-               if(wm8994_current_mode > wm8994_FM_to_speakers_and_record)
-                       return; 
-       //      DBG("wm8994 shutdown\n");
-               mutex_lock(&wm8994->route_lock);
-               PA_ctrl(GPIO_LOW);
-               msleep(50);
-               wm8994_write(0,0);
-               msleep(50);
-               wm8994_write(0x01, 0x0033);     
-               wm8994_current_mode = null;//Automatically re-set the wake-up time      
-               mutex_unlock(&wm8994->route_lock);      
-               break;
-       case SNDRV_PCM_TRIGGER_START:
-               break;
-       case SNDRV_PCM_TRIGGER_RESUME:  
-               msleep(100);
-               gpio_request(pdata->Power_EN_Pin, NULL);
-               gpio_direction_output(pdata->Power_EN_Pin,GPIO_HIGH);
-               gpio_free(pdata->Power_EN_Pin);         
-               msleep(100);
-               wm8994_current_mode = null;
-               snd_soc_put_route(wm8994->kcontrol,NULL);
-               break;
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:      
-               while(error_count)
-               {
-                       if( wm8994_reset_ldo() ==  0)
-                       {
-                               wm8994_current_mode = null;
-                               snd_soc_put_route(wm8994->kcontrol,NULL);
-                               break;
-                       }
-                       error_count --;
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+                       queue_delayed_work(wm8994_workq, &delayed_work,
+                               msecs_to_jiffies(1000));
+               } else {
+                       queue_delayed_work(wm8994_workq, &delayed_work,
+                               msecs_to_jiffies(3000));
                }
-               if(error_count == 0)
-               {
-                       PA_ctrl(GPIO_LOW);
-                       printk("wm8994 Major problems, give me log,tks, -- qjb\n");
-               }       
-               break;
 
-       default:
-               break;
+       } else if (codec_dai->playback.active || codec_dai->capture.active) {
+
+               if (wm8994_work_type == WM8994_WORK_SHUTDOWN)
+                       cancel_delayed_work_sync(&delayed_work);
+
+               if (wm8994_current_mode == wm8994_powerdown_speakers ||
+                   wm8994_current_mode == wm8994_powerdown_headset) {
+                       
+                       printk("Power up wm8994\n");
+
+                       wm8994_work_type = WM8994_WORK_STARTUP;
+                       queue_delayed_work(wm8994_workq, &delayed_work,
+                               msecs_to_jiffies(0));
+               }
        }
+
+       return 0;
 }
 
-#define WM8994_RATES SNDRV_PCM_RATE_8000_48000
+#define WM8994_RATES SNDRV_PCM_RATE_48000
+
 #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
 static struct snd_soc_dai_ops wm8994_ops = {
-       .hw_params = wm8994_pcm_hw_params,
-       .set_fmt = wm8994_set_dai_fmt,
-       .set_sysclk = wm8994_set_dai_sysclk,
-       .digital_mute = wm8994_mute,
-       .trigger        = wm8994_trigger,
        /*add by qiuen for volume*/
-       .set_volume = wm8994_codec_set_volume,
+       .set_volume     = wm8994_codec_set_volume,
+       .trigger        = wm8994_trigger,
 };
 
 struct snd_soc_dai wm8994_dai = {
@@ -3100,23 +2892,21 @@ static int wm8994_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;
-       struct wm8994_priv *wm8994 = codec->private_data;
-       struct wm8994_pdata *pdata = wm8994->pdata;
-       
-       cancel_delayed_work_sync(&wm8994->wm8994_delayed_work); 
-       
-       if(wm8994_current_mode>wm8994_FM_to_speakers_and_record &&
-               wm8994_current_mode< null )//incall status,wm8994 not suspend           
-               return 0;               
-       DBG("%s----%d\n",__FUNCTION__,__LINE__);
-       
-       wm8994->work_type = SNDRV_PCM_TRIGGER_SUSPEND;
-       PA_ctrl(GPIO_LOW);
+
+       cancel_delayed_work_sync(&delayed_work);
+
+       wm8994_work_type = WM8994_WORK_NULL;
+
+       isWM8994SetChannel = true;
+
+       wm8994_set_bias_level(codec,SND_SOC_BIAS_OFF);
        wm8994_write(0x00, 0x00);
-       
-       gpio_request(pdata->Power_EN_Pin, NULL);
-       gpio_direction_output(pdata->Power_EN_Pin,GPIO_LOW);
-       gpio_free(pdata->Power_EN_Pin); 
+       msleep(50);
+
+       gpio_request(WM_EN_PIN, NULL);
+       gpio_direction_output(WM_EN_PIN,GPIO_LOW);
+       gpio_free(WM_EN_PIN);
+
        msleep(50);
 
        return 0;
@@ -3126,228 +2916,502 @@ static int wm8994_resume(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->card->codec;
-       struct wm8994_priv *wm8994 = codec->private_data;
-//     struct wm8994_pdata *pdata = wm8994->pdata;
-       if(wm8994_current_mode>wm8994_FM_to_speakers_and_record &&
-               wm8994_current_mode< null )//incall status,wm8994 not suspend
-               return 0;               
-       DBG("%s----%d\n",__FUNCTION__,__LINE__);
 
-       cancel_delayed_work_sync(&wm8994->wm8994_delayed_work); 
-       wm8994->work_type = SNDRV_PCM_TRIGGER_RESUME;
-       schedule_delayed_work(&wm8994->wm8994_delayed_work, msecs_to_jiffies(0));       
+       gpio_request(WM_EN_PIN, NULL);
+       gpio_direction_output(WM_EN_PIN,GPIO_HIGH);
+       gpio_free(WM_EN_PIN);
+
+       msleep(50);
+
+       wm8994_set_bias_level(codec,SND_SOC_BIAS_STANDBY);
+
+       wm8994_powerdown();
 
+       isWM8994SetChannel = false;
        return 0;
 }
 
+static struct snd_soc_codec *wm8994_codec;
+
 #ifdef WM8994_PROC
-static ssize_t wm8994_proc_write(struct file *file, const char __user *buffer,
-                          unsigned long len, void *data)
-{
-       char *cookie_pot; 
-       char *p;
-       int reg;
-       int value;
-       struct snd_kcontrol kcontrol;
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
-       struct wm8994_pdata *pdata = wm8994->pdata;
-       
-       cookie_pot = (char *)vmalloc( len );
-       if (!cookie_pot) 
-       {
-               return -ENOMEM;
-       } 
-       else 
-       {
-               if (copy_from_user( cookie_pot, buffer, len )) 
-                       return -EFAULT;
-       }
-       
-       switch(cookie_pot[0])
-       {
-       case 'd':
-       case 'D':
-               debug_write_read ++;
-               debug_write_read %= 2;
-               if(debug_write_read != 0)
-                       DBG("Debug read and write reg on\n");
-               else    
-                       DBG("Debug read and write reg off\n");  
-               break;  
+
+void wm8994_read_printk(unsigned short reg) {
+       unsigned short value;
+       wm8994_read(reg, &value);
+       printk("wm8994_read_printk :: reg = 0x%x, value = 0x%x\n", reg, value);
+}
+
+void read_test(void) {
+       wm8994_read_printk(0x200);
+       wm8994_read_printk(0x220);
+       wm8994_read_printk(0x221);
+       wm8994_read_printk(0x222);
+       wm8994_read_printk(0x223);
+       wm8994_read_printk(0x210);
+       wm8994_read_printk(0x300);
+       wm8994_read_printk(0x303);
+       wm8994_read_printk(0x304);
+       wm8994_read_printk(0x305);
+       wm8994_read_printk(0x302);
+       wm8994_read_printk(0x700);
+       wm8994_read_printk(0x208);
+}
+
+static int CheckCommand(const char __user *buffer)
+{
+       char procadd = 0;
+       unsigned short eqvol;
+       unsigned char wm8994_proc_mode;
+       wm8994_codec_fnc_t **wm8994_fnc_ptr = wm8994_codec_sequence;
+
+       switch(*buffer) {
        case 'r':
        case 'R':
-               DBG("Read reg debug\n");                
-               if(cookie_pot[1] ==':')
-               {
-                       debug_write_read = 1;
-                       strsep(&cookie_pot,":");
-                       while((p=strsep(&cookie_pot,",")))
-                       {
-                               wm8994_read(simple_strtol(p,NULL,16),(unsigned short *)&value);
-                       }
-                       debug_write_read = 0;;
-                       DBG("\n");              
+               read_test();
+               return 0;
+               break;
+
+       case 'n':
+       case 'N':
+               if (*(buffer+1)=='+') {
+                       procadd = 3;
+               } else if (*(buffer+1)=='-') {
+                       procadd = -3;
+               } else {
+                       printk("Please press '+' or '-' follow 'n'!\n");
+                       return -1;
                }
-               else
-               {
-                       DBG("Error Read reg debug.\n");
-                       DBG("For example: echo 'r:22,23,24,25'>wm8994_ts\n");
+               switch(wm8994_current_route) {
+               case HEADSET_NORMAL:
+                       if (procadd == 3)
+                               headset_normal_vol += 3;
+                       else
+                               headset_normal_vol -= 3;
+
+                       if (headset_normal_vol > 6)
+                               headset_normal_vol = 6;
+                       else if (headset_normal_vol < -57)
+                               headset_normal_vol = -57;
+
+                       printk("headset_normal_vol = %ddB \n",headset_normal_vol);
+                       break;
+
+               case SPEAKER_NORMAL:
+               case EARPIECE_NORMAL:
+               case SPEAKER_RINGTONE:
+               case EARPIECE_RINGTONE:
+               case BLUETOOTH_SCO_INCALL:
+                       if (procadd == 3)
+                               speaker_normal_vol += 3;
+                       else
+                               speaker_normal_vol -= 3;
+
+                       if (speaker_normal_vol > 6)
+                               speaker_normal_vol = 6;
+                       else if (speaker_normal_vol < -57)
+                               speaker_normal_vol = -57;
+
+                       printk("speaker_normal_vol = %ddB \n",speaker_normal_vol);
+                       break;
+
+               case HEADSET_RINGTONE:
+                       if (procadd == 3) {
+                               headset_normal_vol += 3;
+                               speaker_normal_vol += 3;
+                       } else {
+                               headset_normal_vol -= 3;
+                               speaker_normal_vol -= 3;
+                       }
+
+                       if (speaker_normal_vol > 6)
+                               speaker_normal_vol = 6;
+                       else if (speaker_normal_vol < -57)
+                               speaker_normal_vol = -57;
+                       if (headset_normal_vol > 6)
+                               headset_normal_vol = 6;
+                       else if (headset_normal_vol < -57)
+                               headset_normal_vol = -57;
+
+                       printk("headset_normal_vol = %ddB \n",headset_normal_vol);
+                       printk("speaker_normal_vol = %ddB \n",speaker_normal_vol);
+                       break;
+
+               default:
+                       printk("Current channel does not match to normal mode!\n");
+                       return -1;
                }
                break;
-       case 'w':
-       case 'W':
-               DBG("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);
-                               wm8994_write(reg,value);
-                       }
-                       debug_write_read = 0;;
-                       DBG("\n");
+
+       case 'i':
+       case 'I':
+               if (*(buffer+1)=='+') {
+                       procadd = 3;
+               } else if (*(buffer+1)=='-') {
+                       procadd = -3;
+               } else {
+                       printk("Please press '+' or '-' follow 'i'!\n");
+                       return -1;
                }
-               else
-               {
-                       DBG("Error Write reg debug.\n");
-                       DBG("For example: w:22=0,23=0,24=0,25=0\n");
+
+               switch(wm8994_current_route) {
+               case HEADSET_INCALL:
+                       if (procadd == 3)
+                               headset_incall_vol += 3;
+                       else
+                               headset_incall_vol -= 3;
+
+                       if (headset_incall_vol > 6)
+                               headset_incall_vol = 6;
+                       else if (headset_incall_vol < -12)
+                               headset_incall_vol = -12;
+
+                       printk("headset_incall_vol = %ddB \n",headset_incall_vol);
+                       break;
+
+#if defined(CONFIG_SND_INSIDE_EARPIECE)||defined(CONFIG_SND_OUTSIDE_EARPIECE)
+               case EARPIECE_INCALL:
+                       if (procadd == 3)
+                               earpiece_incall_vol += 3;
+                       else
+                               earpiece_incall_vol -= 3;
+
+                       if (earpiece_incall_vol>6)
+                               earpiece_incall_vol = 6;
+                       else if (earpiece_incall_vol<-21)
+                               earpiece_incall_vol = -21;
+
+                       printk("earpiece_incall_vol = %ddB \n",earpiece_incall_vol);
+                       break;
+#endif
+               case SPEAKER_INCALL:
+                       if (procadd == 3)
+                               speaker_incall_vol += 3;
+                       else
+                               speaker_incall_vol -= 3;
+
+                       if (speaker_incall_vol > 12)
+                               speaker_incall_vol = 12;
+                       else if (speaker_incall_vol < -21)
+                               speaker_incall_vol = -21;
+
+                       printk("speaker_incall_vol = %ddB \n",speaker_incall_vol);
+                       break;
+
+               case BLUETOOTH_SCO_INCALL:
+                       if (procadd == 3)
+                               BT_incall_vol += 3;
+                       else
+                               BT_incall_vol -= 3;
+
+                       if (BT_incall_vol > 30)
+                               BT_incall_vol = 30;
+                       else if (BT_incall_vol < -16)
+                               BT_incall_vol = -16;
+
+                       printk("BT_incall_vol = %ddB \n",BT_incall_vol);
+                       break;
+
+               default:
+                       printk("Current channel does not match to incall mode!\n");
+                       return -1;
                }
-               break;  
-       case 'p':
-       case 'P':
-               if(cookie_pot[1] =='-')
-               {
-                       kcontrol.private_value = simple_strtol(&cookie_pot[2],NULL,10);
-                       printk("kcontrol.private_value = %ld\n",kcontrol.private_value);
-                       if(kcontrol.private_value<SPEAKER_INCALL || kcontrol.private_value>HEADSET_RINGTONE)
-                       {
-                               printk("route error\n");
-                               goto help;
-                       }       
-                       snd_soc_put_route(&kcontrol,NULL);
+               break;
+
+       case 'm':
+       case 'M':
+               if (*(buffer+1)=='+') {
+                       procadd = 3;
+               } else if (*(buffer+1)=='-') {
+                       procadd = -3;
+               } else {
+                       printk("Please press '+' or '-' follow 'm'!\n");
+                       return -1;
+               }
+               switch(wm8994_current_route) {
+               case HEADSET_INCALL:
+                       if (procadd == 3)
+                               headset_incall_mic_vol += 3;
+                       else
+                               headset_incall_mic_vol -= 3;
+
+                       if (speaker_incall_mic_vol > 30)
+                               speaker_incall_mic_vol = 30;
+                       else if (speaker_incall_mic_vol < -22)
+                               speaker_incall_mic_vol = -22;
+
+                       printk("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
                        break;
-               }       
-               else if(cookie_pot[1] ==':')
-               {
-                       strsep(&cookie_pot,":");
-                       while((p=strsep(&cookie_pot,",")))
-                       {
-                               kcontrol.private_value = simple_strtol(p,NULL,10);
-                               printk("kcontrol.private_value = %ld\n",kcontrol.private_value);
-                               if(kcontrol.private_value<SPEAKER_INCALL || kcontrol.private_value>HEADSET_RINGTONE)
-                               {
-                                       printk("route error\n");
-                                       goto help;
-                               }       
-                               snd_soc_put_route(&kcontrol,NULL);
-                       }
+
+               case EARPIECE_INCALL:
+                       if (procadd == 3)
+                               speaker_incall_mic_vol += 3;
+                       else
+                               speaker_incall_mic_vol -= 3;
+
+                       if (speaker_incall_mic_vol > 30)
+                               speaker_incall_mic_vol = 30;
+                       else if (speaker_incall_mic_vol < -22)
+                               speaker_incall_mic_vol = -22;
+
+                       printk("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
                        break;
-               }               
-               else
-               {
-                       goto help;
+
+               case SPEAKER_INCALL:
+                       if (procadd == 3)
+                               speaker_incall_mic_vol += 3;
+                       else
+                               speaker_incall_mic_vol -= 3;
+
+                       if (speaker_incall_mic_vol > 30)
+                               speaker_incall_mic_vol = 30;
+                       else if (speaker_incall_mic_vol < -22)
+                               speaker_incall_mic_vol = -22;
+
+                       printk("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
+                       break;
+
+               case BLUETOOTH_SCO_INCALL:
+                       if (procadd == 3)
+                               BT_incall_mic_vol += 3;
+                       else
+                               BT_incall_mic_vol -= 3;
+
+                       if (BT_incall_mic_vol > 6)
+                               BT_incall_mic_vol = 6;
+                       else if (BT_incall_mic_vol < -57)
+                               BT_incall_mic_vol = -57;
+
+                       printk("BT_incall_mic_vol = %ddB \n",BT_incall_mic_vol);
+                       break;
+
+               case MIC_CAPTURE:
+                       if (procadd == 3)
+                               recorder_vol += 3;
+                       else
+                               recorder_vol -= 3;
+
+                       if (recorder_vol > 60)
+                               recorder_vol = 60;
+                       else if (recorder_vol < -16)
+                               recorder_vol = -16;
+
+                       printk("recorder_vol = %ddB \n",recorder_vol);
+                       break;
+
+               default:
+                       printk("Current channel does not match to mic mode!\n");
+                       return -1;
                }
-               help:
-                       printk("snd_soc_put_route list\n");
-                       printk("SPEAKER_INCALL--\"p-0\",\nSPEAKER_NORMAL--\"p-1\",\nHEADSET_INCALL--\"p-2\",\
-                       \nHEADSET_NORMAL--\"p-3\",\nEARPIECE_INCALL--\"p-4\",\nEARPIECE_NORMAL--\"p-5\",\
-                       \nBLUETOOTH_SCO_INCALL--\"p-6\",\nMIC_CAPTURE--\"p-10\",\nEARPIECE_RINGTONE--\"p-11\",\
-                       \nSPEAKER_RINGTONE--\"p-12\",\nHEADSET_RINGTONE--\"p-13\"\n");                  
                break;
-       case 'F':
-       case 'f':
-               PA_ctrl(GPIO_HIGH);             
-               FM_to_speakers();
+
+       case 'l':
+       case 'L':
+               printk("headset_normal_vol = %ddB \n",headset_normal_vol);
+               printk("speaker_normal_vol = %ddB \n",speaker_normal_vol);
+               printk("headset_incall_vol = %ddB \n",headset_incall_vol);
+#if defined(CONFIG_SND_INSIDE_EARPIECE)||defined(CONFIG_SND_OUTSIDE_EARPIECE)
+               printk("earpiece_incall_vol = %ddB \n",earpiece_incall_vol);
+#endif
+               printk("speaker_incall_vol = %ddB \n",speaker_incall_vol);
+               printk("BT_incall_vol = %ddB \n",BT_incall_vol);
+               printk("headset_incall_mic_vol = %ddB \n",headset_incall_mic_vol);
+               printk("speaker_incall_mic_vol = %ddB \n",speaker_incall_mic_vol);
+               printk("BT_incall_mic_vol = %ddB \n",BT_incall_mic_vol);
+               printk("recorder_vol = %ddB \n",recorder_vol);
+               printk("bank_vol[1] = %ddB \n",bank_vol[1]);
+               printk("bank_vol[2] = %ddB \n",bank_vol[2]);
+               printk("bank_vol[3] = %ddB \n",bank_vol[3]);
+               printk("bank_vol[4] = %ddB \n",bank_vol[4]);
+               printk("bank_vol[5] = %ddB \n",bank_vol[5]);
+               return 0;
                break;
-       case 'S':
-       case 's':
-               printk("Debug : Set volume begin\n");
-               switch(cookie_pot[1])
-               {
-                       case '+':
-                               if(cookie_pot[2] == '\n')
-                               {
-                               
-                               }
-                               else
-                               {
-                                       value = simple_strtol(&cookie_pot[2],NULL,10);
-                                       printk("value = %d\n",value);
-
-                               }
-                               break;
-                       case '-':
-                               if(cookie_pot[2] == '\n')
-                               {
-                                       
-                               }
-                               else
-                               {
-                                       value = simple_strtol(&cookie_pot[2],NULL,10);
-                                       printk("value = %d\n",value);
-                               }
-                               break;
-                       default:
-                               if(cookie_pot[1] == '=')
-                               {
-                                       value = simple_strtol(&cookie_pot[2],NULL,10);
-                                       printk("value = %d\n",value);
-                               }       
-                               else
-                                       printk("Help the set volume,Example: echo s+**>wm8994_ts,s=**>wm8994_ts,s-**>wm8994_ts\n");
-
-                               break;                          
-               }               
-               break;  
-       case '1':
-               gpio_request(pdata->Power_EN_Pin, NULL);
-               gpio_direction_output(pdata->Power_EN_Pin,GPIO_LOW);
-               gpio_free(pdata->Power_EN_Pin); 
+
+       case 'c':
+       case 'C':
+               if (((*(buffer+1) == 't') || (*(buffer+1) == 'T')) &&
+               ((*(buffer+2) == 'a') || (*(buffer+2) == 'A'))) {
+                       if (earpiece_vol_table[5] == 0x013D) {
+                               earpiece_vol_table[0] = 0x0127;//for cta
+                               earpiece_vol_table[1] = 0x012D;
+                               earpiece_vol_table[2] = 0x0130;
+                               earpiece_vol_table[3] = 0x0135;
+                               earpiece_vol_table[4] = 0x0137;
+                               earpiece_vol_table[5] = 0x0135;
+                               printk("CTA on,earpiece table value is:0x0127,0x012D,0x0130,0x0135,0x0137,0x0135\n");
+                       }
+                       return 0;
+                       break;
+               }
+
+               cancel_delayed_work_sync(&delayed_work);
+               wm8994_work_type = WM8994_WORK_NULL;
+               isWM8994SetChannel = true;
+
+               if (*(buffer+1) == '+') {
+                       wm8994_proc_mode = wm8994_current_mode+1;
+
+                       if (wm8994_proc_mode > wm8994_BT_baseband)
+                               wm8994_proc_mode = wm8994_AP_to_headset;
+               } else if (*(buffer+1) == '-') {
+                       wm8994_proc_mode = wm8994_current_mode-1;
+
+                       if (wm8994_proc_mode > wm8994_BT_baseband)
+                               wm8994_proc_mode = wm8994_BT_baseband;
+               } else {
+                       if (wm8994_current_mode > wm8994_BT_baseband) {
+                               wm8994_proc_mode = wm8994_recorder_and_AP_to_speakers;
+                       }
+                       wm8994_proc_mode = wm8994_current_mode;
+                       wm8994_current_mode = null;
+               }
+
+               wm8994_fnc_ptr += wm8994_proc_mode;
+               (*wm8994_fnc_ptr)();
+               isWM8994SetChannel = false;
+
+               return 0;
                break;
-       case '2':       
-               gpio_request(pdata->Power_EN_Pin, NULL);
-               gpio_direction_output(pdata->Power_EN_Pin,GPIO_HIGH);
-               gpio_free(pdata->Power_EN_Pin);                 
+
+       case 'e':
+       case 'E':
+               if (*(buffer+1)=='+') {
+                       procadd = 3;
+               } else if (*(buffer+1)=='-') {
+                       procadd = -3;
+               } else if (*(buffer+1)=='c') {
+                       wm8994_write(0x0480, 0x0000);
+                       return 0;
+               } else if (*(buffer+1)=='o') {
+                       wm8994_write(0x0480, 0x0001|((bank_vol[1]+12)<<11)|
+                       ((bank_vol[2]+12)<<6)|((bank_vol[3]+12)<<1));
+                       wm8994_write(0x0481, 0x0000|((bank_vol[4]+12)<<11)|
+                       ((bank_vol[5]+12)<<6));
+                       return 0;
+               }else {
+                       printk("Please press '+' '-' 'o' 'c' follow 'e'!\n");
+                       return -1;
+               }
+
+               switch(*(buffer+2)) {
+               case '1':
+                       if (procadd == 3)
+                               bank_vol[1] += 3;
+                       else
+                               bank_vol[1] -= 3;
+
+                       if (bank_vol[1] > 12)bank_vol[1] = 12;
+                       if (bank_vol[1] < -12)bank_vol[1] = -12;
+
+                       wm8994_read(0x0480, &eqvol);
+                       wm8994_write(0x0480, (eqvol&0x07FF)|((bank_vol[1]+12)<<11)); 
+
+                       printk("bank_vol[1] = %ddB \n",bank_vol[1]);
+                       break;
+
+               case '2':
+                       if (procadd == 3)
+                               bank_vol[2] += 3;
+                       else
+                               bank_vol[2] -= 3;
+
+                       if (bank_vol[2] > 12)bank_vol[2] = 12;
+                       if (bank_vol[2] < -12)bank_vol[2] = -12;
+
+                       wm8994_read(0x0480, &eqvol);
+                       wm8994_write(0x0480, (eqvol&0xF83F)|((bank_vol[2]+12)<<6));
+                       printk("bank_vol[2] = %ddB \n",bank_vol[2]);
+                       break;
+
+               case '3':
+                       if (procadd == 3)
+                               bank_vol[3] += 3;
+                       else
+                               bank_vol[3] -= 3;
+
+                       if (bank_vol[3] > 12)bank_vol[3] = 12;
+                       if (bank_vol[3] < -12)bank_vol[3] = -12;
+
+                       wm8994_read(0x0480, &eqvol);
+                       wm8994_write(0x0480, (eqvol&0xFFC1)|((bank_vol[3]+12)<<1)); 
+
+                       printk("bank_vol[3] = %ddB \n",bank_vol[3]);
+                       break;
+
+               case '4':
+                       if (procadd == 3)
+                               bank_vol[4] += 3;
+                       else
+                               bank_vol[4] -= 3;
+
+                       if (bank_vol[4] > 12)bank_vol[4] = 12;
+                       if (bank_vol[4] < -12)bank_vol[4] = -12;
+
+                       wm8994_read(0x0481, &eqvol);
+                       wm8994_write(0x0481, (eqvol&0x07FF)|((bank_vol[4]+12)<<11)); 
+
+                       printk("bank_vol[4] = %ddB \n",bank_vol[4]);
+                       break;
+
+               case '5':
+                       if (procadd == 3)
+                               bank_vol[5] += 3;
+                       else
+                               bank_vol[5] -= 3;
+
+                       if (bank_vol[5] > 12)bank_vol[5] = 12;
+                       if (bank_vol[5] < -12)bank_vol[5] = -12;
+
+                       wm8994_read(0x0481, &eqvol);
+                       wm8994_write(0x0481, (eqvol&0xF83F)|((bank_vol[5]+12)<<6)); 
+
+                       printk("bank_vol[5] = %ddB \n",bank_vol[5]);
+                       break;
+
+               default:
+                       printk("Please press bank '1' to '5' follow 'e+' or 'e-'!\n");
+                       return -1;
+               }
+               return 0;
                break;
+
        default:
-               DBG("Help for wm8994_ts .\n-->The Cmd list: \n");
-               DBG("-->'d&&D' Open or close the debug\n");
-               DBG("-->'r&&R' Read reg debug,Example: echo 'r:22,23,24,25'>wm8994_ts\n");
-               DBG("-->'w&&W' Write reg debug,Example: echo 'w:22=0,23=0,24=0,25=0'>wm8994_ts\n");
-               DBG("-->'ph&&Ph' cat snd_soc_put_route list\n");
-               break;
+               printk("Please press 'n' 'i' 'm' 'l' 'c' 'e' !\n");
+               return -1;
        }
 
-       return len;
+       wm8994_set_channel_vol();
+
+       return 0;
 }
 
+static int wm8994_proc_write(struct file *file, const char __user *buffer,
+                          unsigned long count, void *data)
+{
+       if (CheckCommand(buffer) != 0) {
+               printk("Write proc error !\n");
+               return -1;
+       }
+
+       return sizeof(buffer);
+}
 static const struct file_operations wm8994_proc_fops = {
        .owner          = THIS_MODULE,
-       //.open         = snd_mem_proc_open,
-       //.read         = seq_read,
-//#ifdef CONFIG_PCI
        .write          = wm8994_proc_write,
-//#endif
-       //.llseek       = seq_lseek,
-       //.release      = single_release,
 };
 
-static int wm8994_proc_init(void){
+static int wm8994_proc_init(void) {
 
        struct proc_dir_entry *wm8994_proc_entry;
 
        wm8994_proc_entry = create_proc_entry("driver/wm8994_ts", 0777, NULL);
 
-       if(wm8994_proc_entry != NULL){
+       if (wm8994_proc_entry != NULL) {
 
                wm8994_proc_entry->write_proc = wm8994_proc_write;
 
                return -1;
-       }else{
+       }else {
                printk("create proc error !\n");
        }
 
@@ -3360,10 +3424,7 @@ static int wm8994_probe(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec;
-       struct wm8994_priv *wm8994;
-       struct wm8994_pdata *pdata;
        int ret = 0;
-       
 
 #ifdef WM8994_PROC
        wm8994_proc_init();
@@ -3376,13 +3437,18 @@ static int wm8994_probe(struct platform_device *pdev)
 
        socdev->card->codec = wm8994_codec;
        codec = wm8994_codec;
-       wm8994 = codec->private_data;
-       pdata = wm8994->pdata;
-       //disable power_EN
-       gpio_request(pdata->Power_EN_Pin, NULL);                         
-       gpio_direction_output(pdata->Power_EN_Pin,GPIO_LOW);            
-       gpio_free(pdata->Power_EN_Pin); 
-       
+
+       recorder_and_AP_to_speakers();
+
+       isWM8994SetChannel = false;
+
+       wm8994_workq = create_freezeable_workqueue("wm8994");
+       if (wm8994_workq == NULL) {
+               kfree(codec->private_data);
+               kfree(codec);
+               return -ENOMEM;
+       }
+
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if (ret < 0) {
@@ -3399,13 +3465,6 @@ static int wm8994_probe(struct platform_device *pdev)
                goto card_err;
        }
 
-       PA_ctrl(GPIO_LOW);
-       //enable power_EN
-       msleep(50);
-       gpio_request(pdata->Power_EN_Pin, NULL);                         
-       gpio_direction_output(pdata->Power_EN_Pin,GPIO_HIGH);           
-       gpio_free(pdata->Power_EN_Pin); 
-
        return ret;
 
 card_err:
@@ -3454,13 +3513,13 @@ static int wm8994_register(struct wm8994_priv *wm8994,
        codec->owner = THIS_MODULE;
        codec->dai = &wm8994_dai;
        codec->num_dai = 1;
-//     codec->reg_cache_size = ARRAY_SIZE(wm8994->reg_cache);
-//     codec->reg_cache = &wm8994->reg_cache;
+       codec->reg_cache_size = ARRAY_SIZE(wm8994->reg_cache);
+       codec->reg_cache = &wm8994->reg_cache;
        codec->bias_level = SND_SOC_BIAS_OFF;
        codec->set_bias_level = wm8994_set_bias_level;
 
-//     memcpy(codec->reg_cache, wm8994_reg,
-//            sizeof(wm8994_reg));
+       memcpy(codec->reg_cache, wm8994_reg,
+              sizeof(wm8994_reg));
 
        ret = snd_soc_codec_set_cache_io(codec,7, 9, control);
        if (ret < 0) {
@@ -3516,6 +3575,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
 {
        struct wm8994_priv *wm8994;
        struct snd_soc_codec *codec;
+       wm8994_client=i2c;
 
        wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
        if (wm8994 == NULL)
@@ -3527,16 +3587,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
-       wm8994->pdata = i2c->dev.platform_data;//add
-       wm8994->RW_status = TRUE;//add
-       wm8994->capture_active = 0;
-       wm8994->playback_active = 0;
-       wm8994->call_vol = call_maxvol;
-       wm8994->BT_call_vol = BT_call_maxvol;
-       INIT_DELAYED_WORK(&wm8994->wm8994_delayed_work, wm8994_work_fun);
-       mutex_init(&wm8994->io_lock);   
-       mutex_init(&wm8994->route_lock);
-       wake_lock_init(&wm8994->wm8994_on_wake, WAKE_LOCK_SUSPEND, "wm8994_on_wake");
+
        return wm8994_register(wm8994, SND_SOC_I2C);
 }
 
@@ -3562,18 +3613,6 @@ static int wm8994_i2c_resume(struct i2c_client *client)
 #define wm8994_i2c_resume NULL
 #endif
 
-static void wm8994_i2c_shutdown(struct i2c_client *client)
-{
-       struct wm8994_priv *wm8994 = wm8994_codec->private_data;
-       struct wm8994_pdata *pdata = wm8994->pdata;
-       DBG("%s----%d\n",__FUNCTION__,__LINE__);
-       //disable PA
-       PA_ctrl(GPIO_LOW);      
-       gpio_request(pdata->Power_EN_Pin, NULL);
-       gpio_direction_output(pdata->Power_EN_Pin,GPIO_LOW);
-       gpio_free(pdata->Power_EN_Pin); 
-}
-
 static const struct i2c_device_id wm8994_i2c_id[] = {
        { "wm8994", 0 },
        { }
@@ -3590,9 +3629,53 @@ static struct i2c_driver wm8994_i2c_driver = {
        .suspend = wm8994_i2c_suspend,
        .resume = wm8994_i2c_resume,
        .id_table = wm8994_i2c_id,
-       .shutdown = wm8994_i2c_shutdown,
 };
 
+int reg_send_data(struct i2c_client *client, unsigned short *reg, unsigned short *data, u32 scl_rate)
+{
+       int ret;
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msg;
+       char tx_buf[4];
+
+       memcpy(tx_buf, reg, 2);
+       memcpy(tx_buf+2, data, 2);
+       msg.addr = client->addr;
+       msg.buf = tx_buf;
+       msg.len = 4;
+       msg.flags = client->flags;
+       msg.scl_rate = scl_rate;
+       msg.read_type = 0;//I2C_NORMAL;
+       ret = i2c_transfer(adap, &msg, 1);
+
+       return ret;
+}
+
+int reg_recv_data(struct i2c_client *client, unsigned short *reg, unsigned short *buf, u32 scl_rate)
+{
+       int ret;
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msgs[2];
+
+       msgs[0].addr = client->addr;
+       msgs[0].buf = (char *)reg;
+       msgs[0].flags = client->flags;
+       msgs[0].len = 2;
+       msgs[0].scl_rate = scl_rate;
+       msgs[0].read_type = 2;//I2C_NO_STOP;
+
+       msgs[1].addr = client->addr;
+       msgs[1].buf = (char *)buf;
+       msgs[1].flags = client->flags | I2C_M_RD;
+       msgs[1].len = 2;
+       msgs[1].scl_rate = scl_rate;
+       msgs[1].read_type = 2;//I2C_NO_STOP;
+
+       ret = i2c_transfer(adap, msgs, 2);
+
+       return ret;
+}
+
 #endif
 
 #if defined(CONFIG_SPI_MASTER)
@@ -3682,5 +3765,5 @@ module_exit(wm8994_exit);
 
 
 MODULE_DESCRIPTION("ASoC WM8994 driver");
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_AUTHOR("chenjq chenjq@rock-chips.com");
 MODULE_LICENSE("GPL");
index ebf3a6115b5d3936d294188b4cf443795e244a18..8dc225bdcc50d102a6da900710948acaf2ff3433 100755 (executable)
@@ -14,6 +14,8 @@
 #ifndef _WM8994_H
 #define _WM8994_H
 
+#define WM8994_NUM_REG   0x44
+
 /* WM8994 register space */
 #define WM8994_RESET     0x00
 #define wm8994_SYSCLK_3072M 0
index a6ac20ef821464307c20d6c2b7dbbb3b6fe5e8fd..ea7a320c48123e2c85686bbcf62d98ccc0410172 100644 (file)
@@ -75,6 +75,94 @@ config SND_RK29_SOC_WM8994
          Say Y if you want to add support for SoC audio on rockchip
          with the WM8994.  
 
+if SND_SOC_WM8994
+choice
+  prompt "Chose earpiece type"
+
+       config SND_INSIDE_EARPIECE
+               tristate  "Inside earpiece"
+
+       config SND_OUTSIDE_EARPIECE
+               tristate  "Outside earpiece"
+
+       config SND_NO_EARPIECE
+               tristate  "No earpiece"
+endchoice
+
+choice
+  prompt "Chose BB input signal type"
+
+       config SND_BB_NORMAL_INPUT
+               tristate  "BB normal singnal input"
+
+       config SND_BB_DIFFERENTIAL_INPUT
+               tristate  "BB differential singnal input"
+
+endchoice
+
+config WM8994_SPEAKER_INCALL_VOL  
+       default 15
+       int "Setting the wm8994 speaker incall vol"
+       help
+         -21dB to 12dB
+
+config WM8994_SPEAKER_INCALL_MIC_VOL  
+       default 15
+       int "Setting the wm8994 speaker incall mic vol"
+       help
+         -22dB to 30dB
+
+config WM8994_SPEAKER_NORMAL_VOL  
+       default 15
+       int "Setting the wm8994 speaker normal vol"
+       help
+         -57dB to 18dB
+
+if SND_INSIDE_EARPIECE||SND_OUTSIDE_EARPIECE
+config WM8994_EARPIECE_INCALL_VOL  
+       default 0
+       int "Setting the wm8994 earpiece incall vol(normal)"
+       help
+         -27dB to 30dB
+endif
+
+config WM8994_HEADSET_INCALL_VOL
+       default 6
+       int "Setting the wm8994 headset incall vol"
+       help
+         -12dB to 6dB
+
+config WM8994_HEADSET_INCALL_MIC_VOL  
+       default 30
+       int "Setting the wm8994 headset incall mic vol"
+       help
+         -22dB to 30dB
+
+config WM8994_HEADSET_NORMAL_VOL  
+       default 15
+       int "Setting the wm8994 headset normal vol"
+       help
+         -57dB to 6dB
+
+config WM8994_BT_INCALL_VOL  
+       default 30
+       int "Setting the wm8994 BT incall vol"
+       help
+         0dB or 30dB
+
+config WM8994_BT_INCALL_MIC_VOL  
+       default -20
+       int "Setting the wm8994 BT incall mic vol"
+       help
+         -57dB to 6dB
+
+config WM8994_RECORDER_VOL  
+       default 40
+       int "Setting the wm8994 recorder vol"
+       help
+         -16dB to 60dB
+endif
+
 config SND_RK29_SOC_CS42L52
        tristate "SoC I2S Audio support for rockchip - CS42L52"
        depends on SND_RK29_SOC && I2C_RK29