newton:update cs42l52 driver
author蔡枫 <cf@rock-chips.com>
Tue, 26 Jul 2011 03:07:48 +0000 (11:07 +0800)
committer蔡枫 <cf@rock-chips.com>
Tue, 26 Jul 2011 03:07:48 +0000 (11:07 +0800)
sound/soc/codecs/cs42l52.c
sound/soc/rk29/rk29_cs42l52.c

index 36c4cc9265351bf478329d448ecad0c64d953272..cf736ec14a1b51bd39597e7d95e558fb04079cd8 100755 (executable)
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#include       <linux/types.h>
-#include       <linux/device.h>
-#include       <asm/io.h>
+#include <linux/types.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
 #include "cs42l52.h"
 #include <mach/board.h>
+
 //#include "cs42L52_control.h"
-//#define DEBUG
+
+
+#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
+       #define AUTO_DETECT_DISABLE
+#else
+       //#define AUTO_DETECT_DISABLE
+       #undef AUTO_DETECT_DISABLE
+#endif
+
+#define DEBUG
 #ifdef DEBUG
 #define SOCDBG(fmt, arg...)    printk(KERN_ERR "%s: %s() " fmt, SOC_CS42L52_NAME, __FUNCTION__, ##arg)
 #else
-#define SOCDBG(fmt, arg...)
+#define SOCDBG(fmt, arg...)    do { } while (0)
 #endif
 #define SOCINF(fmt, args...)   printk(KERN_INFO "%s: " fmt, SOC_CS42L52_NAME,  ##args)
 #define SOCERR(fmt, args...)   printk(KERN_ERR "%s: " fmt, SOC_CS42L52_NAME,  ##args)
 
+
+
 static void soc_cs42l52_work(struct work_struct *work);
-static int soc_cs42l52_set_bias_level(struct snd_soc_codec *codec,
-                               enum snd_soc_bias_level level);
-static int soc_cs42l52_pcm_hw_params(struct snd_pcm_substream *substream,
-                        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai);
-static int soc_cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
-                        int clk_id, u_int freq, int dir);
 
-static int soc_cs42l52_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
-                                               int div_id, int div);
+static struct snd_soc_codec *cs42l52_codec;
 
-static int soc_cs42l52_digital_mute(struct snd_soc_dai *dai, int mute);
-static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
-                        u_int fmt);
-static unsigned int soc_cs42l52_read(struct snd_soc_codec *codec,
-                               u_int reg);
+//added for suspend
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+static struct early_suspend cs42l52_early_suspend;
+#endif
 
 /**
  * snd_soc_get_volsw - single mixer get callback
@@ -105,6 +111,7 @@ int snd_soc_cs42l5x_get_volsw(struct snd_kcontrol *kcontrol,
 int snd_soc_cs42l5x_put_volsw(struct snd_kcontrol *kcontrol,
     struct snd_ctl_elem_value *ucontrol)
 {
+SOCDBG("i am here\n");
     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
     int reg = kcontrol->private_value & 0xff;
     int shift = (kcontrol->private_value >> 8) & 0x0f;
@@ -247,7 +254,6 @@ int snd_soc_cs42l5x_put_volsw_2r(struct snd_kcontrol *kcontrol,
 /*
  * CS42L52 register default value
  */
-
 static const u8 soc_cs42l52_reg_default[] = {
        0x00, 0xE0, 0x01, 0x07, 0x05, /*4*/
        0xa0, 0x00, 0x00, 0x81, /*8*/
@@ -290,8 +296,8 @@ static int soc_cs42l52_write(struct snd_soc_codec *codec,
        int i,num, ret = 0;
        struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)codec->private_data;
 
-       datas[0] = reg & 0xff; /*reg addr*/
-       datas[1] = val & 0xff; /*reg val*/
+       datas[0] = reg & 0xff;
+       datas[1] = val & 0xff;
        codec->num_dai = 1;
        if(info->flags & SOC_CS42L52_ALL_IN_ONE)
        {
@@ -315,7 +321,6 @@ static int soc_cs42l52_write(struct snd_soc_codec *codec,
                        ret = -EIO;
        }
 
-       printk(KERN_INFO"soc_cs42l52_write---reg=%d--val=%d\n",reg,val);
        if(ret >= 0)
                soc_cs42l52_write_reg_cache(codec, reg, val);
 
@@ -328,69 +333,99 @@ static int soc_cs42l52_write(struct snd_soc_codec *codec,
 static unsigned int soc_cs42l52_read(struct snd_soc_codec *codec,
                u_int reg)
 {
-#if 0//commented out @20110706, for audio recording commit
-       u8 data;
-       u8 addr;
-        int i, ret = 0;
-
-        struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)codec->private_data;
-#ifndef CONFIG_CS42L52_DEBUG
-       if(reg == CODEC_CS42L52_SPK_STATUS)
-       {
-
-#endif
-               addr = reg & 0xff;
-               if(info->flags & SOC_CS42L52_ALL_IN_ONE)
-               {
-                       codec->num_dai = 1;
-                       for(i = 0; i < codec->num_dai; i++)
-                       {
-                               if(codec->hw_write(codec->control_data, &addr, 1) == 1)
-                               {
-//                                     if(codec->hw_read(codec->control_data, &data, 1) == 1)
-                                       {
-//                                             ret |= data << (i * 8);
-                                       }
-                               }
-                               else{
-                                       ret = -EIO;
-                                       break;
-                               }
-
-                               }       
-               }
-#ifndef CONFIG_CS42L52_DEBUG
-       }
-       else{
-
-
-               u8 *cache = codec->reg_cache;
-               u8 retval;
-               retval = reg > SOC_CS42L52_REG_NUM ? -EINVAL : cache[reg];
-/*             SOCDBG("%s (cache) 0x%x = %02x (%d)\n", reg, retval, retval); */
-               return retval;
-       }               
-#endif
-//     SOCDBG("0x%x = %02x (%d)\n", reg, ret, ret); 
-       return ret;
-#else
-       //return codec->read(codec, reg);
-
+#if 1
        u8 data;
-       if(i2c_master_reg8_recv(codec->control_data,reg,&data,1,50*1000)>0)
-       {
-               printk("cs42l52  read  reg%x = %d\n",reg,data);
+       if(i2c_master_reg8_recv(codec->control_data,reg,&data,1,50*1000)>0) {
                return data;
        }
-       else
-       {
+       else {
                printk("cs42l52  read error\n");
                return -1;
        }
+#else
+       return codec->read(codec, reg);
+#endif 
+}
+
+struct soc_cs42l52_clk_para {
+       u32 mclk;
+       u32 rate;
+       u8 speed;
+       u8 group;
+       u8 videoclk;
+       u8 ratio;
+       u8 mclkdiv2;
+};
+
+static const struct soc_cs42l52_clk_para clk_map_table[] = {
+       /*8k*/
+       {12288000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {18432000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {12000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
+       {24000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
+       {27000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0}, /*4*/
+
+       /*11.025k*/
+       {11289600, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {16934400, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       
+       /*16k*/
+       {12288000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {18432000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {12000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},/*9*/
+       {24000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
+       {27000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1},
+
+       /*22.05k*/
+       {11289600, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {16934400, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
        
+       /* 32k */
+       {12288000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*14*/
+       {18432000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {12000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
+       {24000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
+       {27000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0},
 
+       /* 44.1k */
+       {11289600, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*19*/
+       {16934400, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {12000000, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_136, 0},
 
-#endif 
+       /* 48k */
+       {12288000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {18432000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {12000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
+       {24000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},/*25*/
+       {27000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1},
+
+       /* 88.2k */
+       {11289600, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {16934400, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+
+       /* 96k */
+       {12288000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       {18432000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*30*/
+       {12000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
+       {24000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
+};
+
+static int soc_cs42l52_get_clk(int mclk, int rate)
+{
+       int i , ret = 0;
+       u_int mclk1, mclk2 = 0;
+
+       for(i = 0; i < ARRAY_SIZE(clk_map_table); i++){
+               if(clk_map_table[i].rate == rate){
+                       mclk1 = clk_map_table[i].mclk;
+                       if(abs(mclk - mclk1) < abs(mclk - mclk2)){
+                               mclk2 = mclk1;
+                               ret = i;
+                       }
+               }
+       }
+
+       return ret < ARRAY_SIZE(clk_map_table) ? ret : -EINVAL;
 }
 
 static const char *cs42l52_mic_bias[] = {"0.5VA", "0.6VA", "0.7VA", "0.8VA", "0.83VA", "0.91VA"};
@@ -530,7 +565,8 @@ static int soc_cs42l52_add_controls(struct snd_soc_codec *codec)
        for(i = 0; i < ARRAY_SIZE(soc_cs42l52_controls); i++)
        {
                ret = snd_ctl_add(codec->card,
-                       snd_soc_cnew(&soc_cs42l52_controls[i], codec, NULL));
+               snd_soc_cnew(&soc_cs42l52_controls[i], codec, NULL));
+
                if(ret < 0)
                {
                        SOCDBG("add cs42l52 controls failed\n");
@@ -574,11 +610,12 @@ static const struct snd_kcontrol_new cs42l52_hpb_mux =
 SOC_DAPM_ENUM("Route", soc_cs42l52_enum[21]);
 
 static const struct snd_soc_dapm_widget soc_cs42l52_dapm_widgets[] = {
-#if 0 //20110706
+
        /* Input path */
        SND_SOC_DAPM_ADC("ADC Left", "Capture", CODEC_CS42L52_PWCTL1, 1, 1),
-       SND_SOC_DAPM_ADC("ADC Right", "Capture", CODEC_CS42L52_PWCTL1, 2, 1),
-#endif 
+       //SND_SOC_DAPM_ADC("ADC Right", "Capture", CODEC_CS42L52_PWCTL1, 2, 1),
+
+       
        SND_SOC_DAPM_MUX("MICA Mux Capture Switch", SND_SOC_NOPM, 0, 0, &cs42l52_mica_mux),
        SND_SOC_DAPM_MUX("MICB Mux Capture Switch", SND_SOC_NOPM, 0, 0, &cs42l52_micb_mux),
        SND_SOC_DAPM_MUX("MICA Stereo Mux Capture Switch", SND_SOC_NOPM, 1, 0, &cs42l52_mica_stereo_mux),
@@ -587,7 +624,7 @@ static const struct snd_soc_dapm_widget soc_cs42l52_dapm_widgets[] = {
        SND_SOC_DAPM_MUX("ADC Mux Left Capture Switch", SND_SOC_NOPM, 1, 1, &cs42l52_adca_mux),
        SND_SOC_DAPM_MUX("ADC Mux Right Capture Switch", SND_SOC_NOPM, 2, 1, &cs42l52_adcb_mux),
 
-#if 0//20110706
+
        /* Sum switches */
        SND_SOC_DAPM_PGA("AIN1A Switch", CODEC_CS42L52_ADC_PGA_A, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("AIN2A Switch", CODEC_CS42L52_ADC_PGA_A, 1, 0, NULL, 0),
@@ -612,7 +649,7 @@ static const struct snd_soc_dapm_widget soc_cs42l52_dapm_widgets[] = {
        /* PGA Power */
        SND_SOC_DAPM_PGA("PGA Left", CODEC_CS42L52_PWCTL1, PWCTL1_PDN_PGAA_SHIFT, 1, NULL, 0),
        SND_SOC_DAPM_PGA("PGA Right", CODEC_CS42L52_PWCTL1, PWCTL1_PDN_PGAB_SHIFT, 1, NULL, 0),
-#endif
+
        /* Output path */
        SND_SOC_DAPM_MUX("Passthrough Left Playback Switch", SND_SOC_NOPM, 0, 0, &cs42l52_hpa_mux),
        SND_SOC_DAPM_MUX("Passthrough Right Playback Switch", SND_SOC_NOPM, 0, 0, &cs42l52_hpb_mux),
@@ -620,11 +657,11 @@ static const struct snd_soc_dapm_widget soc_cs42l52_dapm_widgets[] = {
        SND_SOC_DAPM_DAC("DAC Left", "Playback", SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_DAC("DAC Right", "Playback", SND_SOC_NOPM, 0, 0),
 
-       // SND_SOC_DAPM_PGA("HP Amp Left", CODEC_CS42L52_PWCTL3, 4, 1, NULL, 0),
-       // SND_SOC_DAPM_PGA("HP Amp Right", CODEC_CS42L52_PWCTL3, 6, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("HP Amp Left", CODEC_CS42L52_PWCTL3, 4, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("HP Amp Right", CODEC_CS42L52_PWCTL3, 6, 1, NULL, 0),
 
-       // SND_SOC_DAPM_PGA("SPK Pwr Left", CODEC_CS42L52_PWCTL3, 0, 1, NULL, 0),
-       // SND_SOC_DAPM_PGA("SPK Pwr Right", CODEC_CS42L52_PWCTL3, 2, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("SPK Pwr Left", CODEC_CS42L52_PWCTL3, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("SPK Pwr Right", CODEC_CS42L52_PWCTL3, 2, 0, NULL, 0),
 
        SND_SOC_DAPM_OUTPUT("HPA"),
        SND_SOC_DAPM_OUTPUT("HPB"),
@@ -650,54 +687,54 @@ static const struct snd_soc_dapm_route soc_cs42l52_audio_map[] = {
        {"ADC Mux Left Capture Switch", "AIN1", "INPUT1A"},
        {"ADC Mux Right Capture Switch", "AIN1", "INPUT1B"},
        {"ADC Mux Left Capture Switch", "AIN2", "INPUT2A"},
-        {"ADC Mux Right Capture Switch", "AIN2", "INPUT2B"},
+       {"ADC Mux Right Capture Switch", "AIN2", "INPUT2B"},
        {"ADC Mux Left Capture Switch", "AIN3", "INPUT3A"},
-        {"ADC Mux Right Capture Switch", "AIN3", "INPUT3B"},
+       {"ADC Mux Right Capture Switch", "AIN3", "INPUT3B"},
        {"ADC Mux Left Capture Switch", "AIN4", "INPUT4A"},
-        {"ADC Mux Right Capture Switch", "AIN4", "INPUT4B"},
+       {"ADC Mux Right Capture Switch", "AIN4", "INPUT4B"},
 
        /* left capture part */
-        {"AIN1A Switch", NULL, "INPUT1A"},
-        {"AIN2A Switch", NULL, "INPUT2A"},
-        {"AIN3A Switch", NULL, "INPUT3A"},
-        {"AIN4A Switch", NULL, "INPUT4A"},
-        {"MICA Switch",  NULL, "MICA"},
-        {"PGA MICA", NULL, "MICA Switch"},
-
-        {"PGA Left", NULL, "AIN1A Switch"},
-        {"PGA Left", NULL, "AIN2A Switch"},
-        {"PGA Left", NULL, "AIN3A Switch"},
-        {"PGA Left", NULL, "AIN4A Switch"},
-        {"PGA Left", NULL, "PGA MICA"},
+       {"AIN1A Switch", NULL, "INPUT1A"},
+       {"AIN2A Switch", NULL, "INPUT2A"},
+       {"AIN3A Switch", NULL, "INPUT3A"},
+       {"AIN4A Switch", NULL, "INPUT4A"},
+       {"MICA Switch",  NULL, "MICA"},
+       {"PGA MICA", NULL, "MICA Switch"},
+
+       {"PGA Left", NULL, "AIN1A Switch"},
+       {"PGA Left", NULL, "AIN2A Switch"},
+       {"PGA Left", NULL, "AIN3A Switch"},
+       {"PGA Left", NULL, "AIN4A Switch"},
+       {"PGA Left", NULL, "PGA MICA"},
 
        /* right capture part */
-        {"AIN1B Switch", NULL, "INPUT1B"},
-        {"AIN2B Switch", NULL, "INPUT2B"},
-        {"AIN3B Switch", NULL, "INPUT3B"},
-        {"AIN4B Switch", NULL, "INPUT4B"},
-        {"MICB Switch",  NULL, "MICB"},
-        {"PGA MICB", NULL, "MICB Switch"},
-
-        {"PGA Right", NULL, "AIN1B Switch"},
-        {"PGA Right", NULL, "AIN2B Switch"},
-        {"PGA Right", NULL, "AIN3B Switch"},
-        {"PGA Right", NULL, "AIN4B Switch"},
-        {"PGA Right", NULL, "PGA MICB"},
+       {"AIN1B Switch", NULL, "INPUT1B"},
+       {"AIN2B Switch", NULL, "INPUT2B"},
+       {"AIN3B Switch", NULL, "INPUT3B"},
+       {"AIN4B Switch", NULL, "INPUT4B"},
+       {"MICB Switch",  NULL, "MICB"},
+       {"PGA MICB", NULL, "MICB Switch"},
+
+       {"PGA Right", NULL, "AIN1B Switch"},
+       {"PGA Right", NULL, "AIN2B Switch"},
+       {"PGA Right", NULL, "AIN3B Switch"},
+       {"PGA Right", NULL, "AIN4B Switch"},
+       {"PGA Right", NULL, "PGA MICB"},
 
        {"ADC Mux Left Capture Switch", "PGA", "PGA Left"},
-        {"ADC Mux Right Capture Switch", "PGA", "PGA Right"},
+       {"ADC Mux Right Capture Switch", "PGA", "PGA Right"},
        {"ADC Left", NULL, "ADC Mux Left Capture Switch"},
        {"ADC Right", NULL, "ADC Mux Right Capture Switch"},
 
        /* Mic Bias */
-        {"Mic Bias Capture Switch", "On", "PGA MICA"},
-        {"Mic Bias Capture Switch", "On", "PGA MICB"},
+       {"Mic Bias Capture Switch", "On", "PGA MICA"},
+       {"Mic Bias Capture Switch", "On", "PGA MICB"},
        {"Mic-Bias", NULL, "Mic Bias Capture Switch"},
        {"Mic-Bias", NULL, "Mic Bias Capture Switch"},
-        {"ADC Mux Left Capture Switch",  "PGA", "Mic-Bias"},
-        {"ADC Mux Right Capture Switch", "PGA", "Mic-Bias"},
-        {"Passthrough Left Playback Switch",  "On", "Mic-Bias"},
-        {"Passthrough Right Playback Switch", "On", "Mic-Bias"},
+       {"ADC Mux Left Capture Switch",  "PGA", "Mic-Bias"},
+       {"ADC Mux Right Capture Switch", "PGA", "Mic-Bias"},
+       {"Passthrough Left Playback Switch",  "On", "Mic-Bias"},
+       {"Passthrough Right Playback Switch", "On", "Mic-Bias"},
 
        /* loopback path */
        {"Passthrough Left Playback Switch",  "On",  "PGA Left"},
@@ -705,7 +742,7 @@ static const struct snd_soc_dapm_route soc_cs42l52_audio_map[] = {
        {"Passthrough Left Playback Switch",  "Off", "DAC Left"},
        {"Passthrough Right Playback Switch", "Off", "DAC Right"},
 
-/* Output map */
+       /* Output map */
        /* Headphone */
        {"HP Amp Left",  NULL, "Passthrough Left Playback Switch"},
        {"HP Amp Right", NULL, "Passthrough Right Playback Switch"},
@@ -713,14 +750,13 @@ static const struct snd_soc_dapm_route soc_cs42l52_audio_map[] = {
        {"HPB", NULL, "HP Amp Right"},
 
        /* Speakers */
-       
        {"SPK Pwr Left",  NULL, "DAC Left"},
        {"SPK Pwr Right", NULL, "DAC Right"},
        {"SPKA", NULL, "SPK Pwr Left"},
        {"SPKB", NULL, "SPK Pwr Right"},
 
        /* terminator */
-     //   {NULL, NULL, NULL},
+       //{NULL, NULL, NULL},
 };
 
 static int soc_cs42l52_add_widgets(struct snd_soc_codec *soc_codec)
@@ -739,171 +775,79 @@ static int soc_cs42l52_add_widgets(struct snd_soc_codec *soc_codec)
                             SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
                             SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
                             SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
-                            SNDRV_PCM_RATE_96000 ) /*refer to cs42l52 datasheet page35*/
+                            SNDRV_PCM_RATE_96000 )
 
 #define SOC_CS42L52_FORMATS ( SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
                               SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \
                               SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
                               SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE )
 
-static int soc_cs42l52_trigger(struct snd_pcm_substream *substream,
-                         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;
 
+/*
+ *----------------------------------------------------------------------------
+ * Function : soc_cs42l52_set_bias_level
+ * Purpose  : This function is to get triggered when dapm events occurs.
+ *            
+ *----------------------------------------------------------------------------
+ */
+int soc_cs42l52_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level)
+{
+       u8 pwctl1 = soc_cs42l52_read(codec, CODEC_CS42L52_PWCTL1) & 0x9f;
+       u8 pwctl2 = soc_cs42l52_read(codec, CODEC_CS42L52_PWCTL2) & 0x07;
 
-       if(status == 1 || status == 0){
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
-                       codec_dai->playback.active = status;
-               }else{
-                       codec_dai->capture.active = status;
-               }
-       }
+       switch (level) {
+        case SND_SOC_BIAS_ON: /* full On */
+               SOCDBG("full on\n");
+               break;
+        case SND_SOC_BIAS_PREPARE: /* partial On */
+               SOCDBG("partial on\n");
+               pwctl1 &= ~(PWCTL1_PDN_CHRG | PWCTL1_PDN_CODEC);
+                soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1);
+                break;
+        case SND_SOC_BIAS_STANDBY: /* Off, with power */
+               SOCDBG("off with power\n");
+               pwctl1 &= ~(PWCTL1_PDN_CHRG | PWCTL1_PDN_CODEC);
+                soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1);
+                break;
+        case SND_SOC_BIAS_OFF: /* Off, without power */
+               SOCDBG("off without power\n");
+              soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1 | 0x9f);
+               soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL2, pwctl2 | 0x07);
+                break;
+        }
+        codec->bias_level = level;
 
-       return 0;
+        return 0;
 }
 
-
-static struct snd_soc_dai_ops cs42l52_ops = {
-                       .hw_params = soc_cs42l52_pcm_hw_params,
-                       .set_sysclk = soc_cs42l52_set_sysclk,
-                       .set_fmt = soc_cs42l52_set_fmt,
-                       .digital_mute = soc_cs42l52_digital_mute,
-                       .set_clkdiv = soc_cs42l52_set_dai_clkdiv,
-                       .trigger  =  soc_cs42l52_trigger,  //20110706, add for audio recording
-};
-
-
-struct  snd_soc_dai soc_cs42l52_dai = {
-                .name = SOC_CS42L52_NAME,
-                .playback = {
-                        .stream_name = "Playback",
-                        .channels_min = 1,
-                        .channels_max = SOC_CS42L52_DEFAULT_MAX_CHANS,
-                        .rates = SOC_CS42L52_RATES,
-                        .formats = SOC_CS42L52_FORMATS,
-                },
-                .capture = {
-                        .stream_name = "Capture",
-                        .channels_min = 1,
-                        .channels_max = SOC_CS42L52_DEFAULT_MAX_CHANS,
-                        .rates = SOC_CS42L52_RATES,
-                        .formats = SOC_CS42L52_FORMATS,
-                },
-                               .ops = &cs42l52_ops,    
-#if 0
-                .ops = {
-                        .hw_params = soc_cs42l52_pcm_hw_params,
-                        .set_sysclk = soc_cs42l52_set_sysclk,
-                        .set_fmt = soc_cs42l52_set_fmt,
-                        .digital_mute = soc_cs42l52_digital_mute,
-                },
-#endif
-};
-
-EXPORT_SYMBOL_GPL(soc_cs42l52_dai);
-
-/* #define CONFIG_MANUAL_CLK */
-
-/* page 37 from cs42l52 datasheet */
-static void soc_cs42l52_required_setup(struct snd_soc_codec *codec)
+/*
+ *----------------------------------------------------------------------------
+ * Function : cs42l52_power_init
+ * Purpose  : This function is toinit codec to a normal status
+ *   
+ *----------------------------------------------------------------------------
+ */
+static void cs42l52_power_init (struct snd_soc_codec *soc_codec)
 {
-       u8 data;
-       soc_cs42l52_write(codec, 0x00, 0x99);
-       soc_cs42l52_write(codec, 0x3e, 0xba);
-       soc_cs42l52_write(codec, 0x47, 0x80);
-       data = soc_cs42l52_read(codec, 0x32);
-       soc_cs42l52_write(codec, 0x32, data | 0x80);
-       soc_cs42l52_write(codec, 0x32, data & 0x7f);
-       soc_cs42l52_write(codec, 0x00, 0x00);
-}
-
-
-static struct snd_soc_codec *cs42l52_codec;
-
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
-
-
-static int cs42l52_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
-{      
-   struct snd_soc_codec *soc_codec;
-       struct soc_codec_cs42l52 * info;
-       struct cs42l52_platform_data *pdata = i2c->dev.platform_data;
-       unsigned int reg;
-       int i, ret = 0;
-       printk(KERN_INFO"cs42l52_i2c_probe\n");
-       
-       soc_codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (soc_codec == NULL)
-               return -ENOMEM;
-
-       soc_codec->name = SOC_CS42L52_NAME;
-       soc_codec->owner = THIS_MODULE;
-       soc_codec->write = soc_cs42l52_write;
-       soc_codec->read = soc_cs42l52_read;
-       soc_codec->hw_write = (hw_write_t)i2c_master_send;
-       mutex_init(&soc_codec->mutex);
-       INIT_LIST_HEAD(&soc_codec->dapm_widgets);
-       INIT_LIST_HEAD(&soc_codec->dapm_paths);
-       
-       soc_codec->set_bias_level = soc_cs42l52_set_bias_level;
-       soc_codec->dai = &soc_cs42l52_dai;
-       soc_codec->dai->playback.channels_max = 2;
-       soc_codec->dai->capture.channels_max = 2;
-       soc_codec->num_dai = 1;
-       soc_codec->control_data = i2c;
-       soc_codec->dev = &i2c->dev;     
-       soc_codec->pcm_devs = 0;  /*pcm device num index*/
-       soc_codec->pop_time = 2;
-       soc_codec->dai[0].codec = soc_codec;
-
-       soc_codec->reg_cache_size = sizeof(soc_cs42l52_reg_default);
-
-       soc_codec->reg_cache = kmemdup(soc_cs42l52_reg_default, sizeof(soc_cs42l52_reg_default), GFP_KERNEL);
-
-       info = (struct soc_codec_cs42l52 *)kmalloc(sizeof(struct soc_codec_cs42l52),GFP_KERNEL);
-
-       if (info == NULL) {
-               kfree(soc_codec);
-               return -ENOMEM;
-       }
-
-       info->sysclk = SOC_CS42L52_DEFAULT_CLK;
-       info->format = SOC_CS42L52_DEFAULT_FORMAT;
-
-       soc_codec->private_data =(void*)info;   
-       
-       printk(KERN_INFO"soc_cs42l52_setup1\n");
-       if(!soc_codec->reg_cache)
-       {
-               SOCERR("%s: err out of memory\n", __FUNCTION__);
-               ret = -ENOMEM;
-               goto err;
-       }
-       if (pdata->init_platform_hw)                              
-               pdata->init_platform_hw();
+       int i,ret;
 
-       /*initialize codec*/
-       for(i = 0; i < soc_codec->num_dai; i++) //while(1) //
+       SOCDBG("\n");
+       for(i = 0; i < soc_codec->num_dai; i++)
        {
-       
                SOCINF("Cirrus CS42L52 codec , revision %d\n", ret & CHIP_REV_MASK);
+
                /*set hp default volume*/
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPA_VOL, DEFAULT_HP_VOL);
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPB_VOL, DEFAULT_HP_VOL);
 
-       
                /*set spk default volume*/
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_SPKA_VOL, DEFAULT_SPK_VOL);
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_SPKB_VOL, DEFAULT_SPK_VOL);
 
-               
                /*set output default powerstate*/
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL3, 5);
-#ifdef CONFIG_MANUAL_CLK
+
+#ifdef AUTO_DETECT_DISABLE
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, 
                                (soc_cs42l52_read(soc_codec, CODEC_CS42L52_CLK_CTL) 
                                 & ~CLK_CTL_AUTODECT_ENABLE));
@@ -912,172 +856,155 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id
                                (soc_cs42l52_read(soc_codec, CODEC_CS42L52_CLK_CTL)
                                 |CLK_CTL_AUTODECT_ENABLE));
 #endif
-       
+
                /*default output stream configure*/
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1,
                                (soc_cs42l52_read(soc_codec, CODEC_CS42L52_PB_CTL1)
-                               | (PB_CTL1_HP_GAIN_07099 << PB_CTL1_HP_GAIN_SHIFT)));
+                               | (PB_CTL1_HP_GAIN_06047 << PB_CTL1_HP_GAIN_SHIFT)));
 
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_MISC_CTL,
                                (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MISC_CTL))
                                | (MISC_CTL_DEEMPH | MISC_CTL_DIGZC | MISC_CTL_DIGSFT));
-       
-               /*default input stream configure*/
-               //soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_A, info->adc_sel1); 
-               //soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_A, 0<<6);          //20110706 
-
-                               //soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_B, info->adc_sel2);
-               //soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_B, 1<<7);          //20110706
 
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICA_CTL,
                                (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MICA_CTL)
                                | 0<<6));/*pre-amplifer 16db*/
                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICB_CTL,
-                                (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MICB_CTL)
-                               | 0<<6));
-#if 0 //20110706, commented out, for audio recording commit
-                /*default input stream path configure*/
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_ANALOG_HPF_CTL, 
-//                              (soc_cs42l52_read(soc_codec, CODEC_CS42L52_ANALOG_HPF_CTL)
-//                              | HPF_CTL_ANLGSFTB | HPF_CTL_ANLGSFTA));
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_PGAA_CTL, PGAX_CTL_VOL_6DB);
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_PGAB_CTL, PGAX_CTL_VOL_6DB); /*PGA volume*/
-
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADCA_VOL, ADCX_VOL_12DB);
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADCB_VOL, ADCX_VOL_12DB); /*ADC volume*/
-
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_ALC_CTL,
-//                              (ALC_CTL_ALCB_ENABLE | ALC_CTL_ALCA_ENABLE)); /*enable ALC*/
-
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_ALC_THRESHOLD,
-//                              ((ALC_RATE_0DB << ALC_MAX_RATE_SHIFT)
-//                               | (ALC_RATE_3DB << ALC_MIN_RATE_SHIFT)));/*ALC max and min threshold*/
-
-
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_NOISE_GATE_CTL,
-//                              (NG_ENABLE | (NG_MIN_70DB << NG_THRESHOLD_SHIFT)
-//                               | (NG_DELAY_100MS << NG_DELAY_SHIFT))); /*Noise Gate enable*/
-
-//              soc_cs42l52_write(soc_codec, CODEC_CS42L52_BEEP_VOL, BEEP_VOL_12DB);
-
-
-                //soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADCA_MIXER_VOL, 0x80 | ADC_MIXER_VOL_12DB);
-                //soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADCB_MIXER_VOL, 0x80 | ADC_MIXER_VOL_12DB);
-#endif
+                               (soc_cs42l52_read(soc_codec, CODEC_CS42L52_MICB_CTL)
+                               | 0<<6));/*pre-amplifer 16db*/
 
-                // add by koffu
                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL2, 0x00);
                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_A, 0x90); 
                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_PGA_B, 0x90); 
 
-                soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICA_CTL, 0x2c); //za yin contrl mic volume by koffu
+                soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICA_CTL, 0x2c);
                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_MICB_CTL, 0x2c);
 
                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PGAA_CTL, 0x00);  //0dB PGA
                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_PGAB_CTL, 0x00);  //0dB PGA
 
                 soc_cs42l52_write(soc_codec, CODEC_CS42L52_ADC_HPF_FREQ, 0x0F);  //enable 464Hz HPF
-//for speaker
-
                         
-                
-                soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERA_VOL, 0x12); //contrl spekers volume by  koffu
-                soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERB_VOL, 0x12);
+               //soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERA_VOL, 0x12);
+               //soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERB_VOL, 0x12);
 
-                
-                soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPA_VOL, 0xe0); //contrl spekers volume by  koffu
-                soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPB_VOL, 0xe0);
+               //soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPA_VOL, 0xc0);
+               //soc_cs42l52_write(soc_codec, CODEC_CS42L52_HPB_VOL, 0xc0);
 
-               soc_cs42l52_write(soc_codec, CODEC_CS42L52_BEEP_TONE_CTL, 0X07);  //enab
+               soc_cs42l52_write(soc_codec, CODEC_CS42L52_BEEP_TONE_CTL, 0X07);
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_TONE_CTL, 0X8f);
-//for headphone
-/*              soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERA_VOL, 0x00); //contrl spekers volume by  koffu
-                soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERB_VOL, 0x00);
 
-               soc_cs42l52_write(soc_codec, CODEC_CS42L52_BEEP_TONE_CTL, 0X00);  //enab
-               soc_cs42l52_write(soc_codec, CODEC_CS42L52_TONE_CTL, 0X00);
-*/
-               
-               soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL1, 0x00); // init  by you
+               /*      
+               soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERA_VOL, 0x00);
+               soc_cs42l52_write(soc_codec, CODEC_CS42L52_MASTERB_VOL, 0x00);
 
+               soc_cs42l52_write(soc_codec, CODEC_CS42L52_BEEP_TONE_CTL, 0X00);
+               soc_cs42l52_write(soc_codec, CODEC_CS42L52_TONE_CTL, 0X00);
+               */
        }
-       soc_cs42l52_dai.dev = &i2c->dev;
 
-       cs42l52_codec = soc_codec;
-
-       ret = snd_soc_register_codec(soc_codec);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
-               goto err;
-       }
-
-    INIT_DELAYED_WORK(&soc_codec->delayed_work, soc_cs42l52_work);
+       return;
+}
 
-       ret = snd_soc_register_dai(&soc_cs42l52_dai);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
+/*
+ *----------------------------------------------------------------------------
+ * Function : soc_cs42l52_work
+ * Purpose  : This function is to power on bias.
+ *            
+ *----------------------------------------------------------------------------
+ */
+static void soc_cs42l52_work(struct work_struct *work)
+{
+       struct snd_soc_codec *codec =
+                container_of(work, struct snd_soc_codec, delayed_work.work);
 
-       return ret;
+       soc_cs42l52_set_bias_level(codec, codec->bias_level);
 
-err_codec:
-       snd_soc_unregister_codec(soc_codec);
-err:
-       kfree(cs42l52_codec);
-       cs42l52_codec = NULL;
-       return ret;
+       return;
 }
 
-static int cs42l52_i2c_remove(struct i2c_client *client)
-{
-        
-       snd_soc_unregister_dai(&soc_cs42l52_dai);
-       snd_soc_unregister_codec(cs42l52_codec);
+/*
+ *----------------------------------------------------------------------------
+ * Function : soc_cs42l52_trigger
+ * Purpose  : This function is to respond to trigger.
+ *            
+ *----------------------------------------------------------------------------
+ */
+static int soc_cs42l52_trigger(struct snd_pcm_substream *substream,
+                         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;
 
-       soc_cs42l52_set_bias_level(cs42l52_codec, SND_SOC_BIAS_OFF);
+       SOCDBG ("substream->stream:%s status:%d\n",
+                  substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE", status);
 
-       soc_cs42l52_dai.dev = NULL;
-       if(cs42l52_codec->reg_cache)            
-               kfree(cs42l52_codec->reg_cache);
-       if(cs42l52_codec->private_data)         
-               kfree(cs42l52_codec->private_data);
-       kfree(cs42l52_codec);
-       cs42l52_codec = NULL;
+       if(status == 1 || status == 0){
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
+                       codec_dai->playback.active = status;
+               }else{
+                       codec_dai->capture.active = status;
+               }
+       }
 
        return 0;
 }
 
-static const struct i2c_device_id cs42l52_i2c_id[] = {
-       { "cs42l52", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, cs42l52_i2c_id);
+/*
+ *----------------------------------------------------------------------------
+ * Function : soc_cs42l52_hw_params
+ * Purpose  : This function is to set the hardware parameters for CS42L52.
+ *            The functions set the sample rate and audio serial data word 
+ *            length.
+ *            
+ *----------------------------------------------------------------------------
+ */
+static int soc_cs42l52_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *soc_dev = rtd->socdev;
+       struct snd_soc_codec *soc_codec = soc_dev->card->codec;
+       struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
 
-static struct i2c_driver cs42l52_i2c_drv = {
-       .driver = {
-               .name = "CS42L52",
-               .owner = THIS_MODULE,
-       },
-       .probe =    cs42l52_i2c_probe,
-       .remove =   cs42l52_i2c_remove,
-       .id_table = cs42l52_i2c_id,
+       u32 clk = 0;
+       int ret = 0;
+       int index = soc_cs42l52_get_clk(info->sysclk, params_rate(params));
 
-};
+       SOCDBG("----------sysclk=%d,rate=%d\n",info->sysclk, params_rate(params));
 
+       if(index >= 0)
+       {
+               info->sysclk = clk_map_table[index].mclk;
+               clk |= (clk_map_table[index].speed << CLK_CTL_SPEED_SHIFT) | 
+                     (clk_map_table[index].group << CLK_CTL_32K_SR_SHIFT) | 
+                     (clk_map_table[index].videoclk << CLK_CTL_27M_MCLK_SHIFT) | 
+                     (clk_map_table[index].ratio << CLK_CTL_RATIO_SHIFT) | 
+                     clk_map_table[index].mclkdiv2;
+
+#ifdef AUTO_DETECT_DISABLE
+               soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, clk);
+#else
+               soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, 0xa0);
 #endif
-#if 1 
-static int soc_cs42l52_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
-               int div_id, int div)
-{
-       struct snd_soc_codec *codec = codec_dai->codec;
-       u16 reg;
-       
-       printk("soc_cs42l52_set_dai_clkdiv\n");
-       return 0;
+       }
+       else{
+               SOCDBG("can't find out right mclk\n");
+               ret = -EINVAL;
+       }
+
+       return ret;
 }
 
-#endif
+/*
+ *----------------------------------------------------------------------------
+ * Function : soc_cs42l52_set_sysclk
+ * Purpose  : This function is to set the DAI system clock
+ *            
+ *----------------------------------------------------------------------------
+ */
 static int soc_cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
                        int clk_id, u_int freq, int dir)
 {
@@ -1085,18 +1012,26 @@ static int soc_cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *soc_codec = codec_dai->codec;
        struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
 
-       if((freq >= SOC_CS42L52_MIN_CLK) && (freq <= SOC_CS42L52_MAX_CLK))
-       {
+       SOCDBG("sysclk=%dHz,freq=%d\n", info->sysclk,freq);
+
+       if((freq >= SOC_CS42L52_MIN_CLK) && (freq <= SOC_CS42L52_MAX_CLK)){
                info->sysclk = freq;
-               SOCDBG("sysclk %d\n", info->sysclk);
+               SOCDBG("info->sysclk set to %d Hz\n", info->sysclk);
        }
        else{
-               SOCDBG("invalid paramter\n");
+               printk("invalid paramter\n");
                ret = -EINVAL;
        }
        return ret;
 }
 
+/*
+ *----------------------------------------------------------------------------
+ * Function : soc_cs42l52_set_fmt
+ * Purpose  : This function is to set the DAI format
+ *            
+ *----------------------------------------------------------------------------
+ */
 static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
                        u_int fmt)
 {
@@ -1106,8 +1041,7 @@ static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
        u8 iface = 0;
 
        /* set master/slave audio interface */
-        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
                SOCDBG("codec dai fmt master\n");
                iface = IFACE_CTL1_MASTER;
@@ -1122,8 +1056,7 @@ static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
        }
 
         /* interface format */
-        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
                SOCDBG("codec dai fmt i2s\n");
                iface |= (IFACE_CTL1_ADC_FMT_I2S | IFACE_CTL1_DAC_FMT_I2S);
@@ -1151,8 +1084,7 @@ static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
        }
 
        /* clock inversion */
-        switch (fmt & SND_SOC_DAIFMT_INV_MASK) { /*tonyliu*/
-
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
                SOCDBG("codec dai fmt normal sclk\n");
                break;
@@ -1172,192 +1104,257 @@ static int soc_cs42l52_set_fmt(struct snd_soc_dai *codec_dai,
 
        info->format = iface;
 done:
-       soc_cs42l52_write(soc_codec, CODEC_CS42L52_IFACE_CTL1, info->format);     //20110706
-       return ret;
+       soc_cs42l52_write(soc_codec, CODEC_CS42L52_IFACE_CTL1, info->format);
 
+       return ret;
 }
 
+/*
+ *----------------------------------------------------------------------------
+ * Function : soc_cs42l52_digital_mute
+ * Purpose  : This function is to mute DAC or not
+ *            
+ *----------------------------------------------------------------------------
+ */
 static int soc_cs42l52_digital_mute(struct snd_soc_dai *dai, int mute)
 {
-
        struct snd_soc_codec *soc_codec = dai->codec;
        u8 mute_val = soc_cs42l52_read(soc_codec, CODEC_CS42L52_PB_CTL1) & PB_CTL1_MUTE_MASK;
 
-       if(mute)
-       {
-               printk(KERN_INFO"soc_cs42l52_digital_mute=1 %d\n",mute_val);
+       SOCDBG("%d\n",mute);
 
-               soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1, mute_val | PB_CTL1_MSTB_MUTE | PB_CTL1_MSTA_MUTE);
+       if(mute) {
+               soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1, mute_val \
+                       | PB_CTL1_MSTB_MUTE | PB_CTL1_MSTA_MUTE);
        }
-       else{
-               printk(KERN_INFO"soc_cs42l52_digital_mute=0 %d\n",mute_val);
+       else {
                soc_cs42l52_write(soc_codec, CODEC_CS42L52_PB_CTL1, mute_val );
        }
 
        return 0;
 }
 
-struct soc_cs42l52_clk_para {
-       u32 mclk;
-       u32 rate;
-       u8 speed;
-       u8 group;
-       u8 videoclk;
-       u8 ratio;
-       u8 mclkdiv2;
+static struct snd_soc_dai_ops cs42l52_ops = {
+                       .hw_params              = soc_cs42l52_hw_params,
+                       .set_sysclk             = soc_cs42l52_set_sysclk,
+                       .set_fmt                = soc_cs42l52_set_fmt,
+                       .trigger                = soc_cs42l52_trigger,
+                       .digital_mute   = soc_cs42l52_digital_mute,
 };
+/*
+ *----------------------------------------------------------------------------
+ * @struct  soc_cs42l52_dai |
+ *          It is SoC Codec DAI structure which has DAI capabilities viz., 
+ *          playback and capture, DAI runtime information viz. state of DAI 
+ *                     and pop wait state, and DAI private data. 
+ *          The AIC3111 rates ranges from 8k to 192k
+ *          The PCM bit format supported are 16, 20, 24 and 32 bits
+ *----------------------------------------------------------------------------
+ */
+struct  snd_soc_dai soc_cs42l52_dai = {
+            .name = SOC_CS42L52_NAME,
+            .playback = {
+                    .stream_name = "Playback",
+                    .channels_min = 1,
+                    .channels_max = SOC_CS42L52_DEFAULT_MAX_CHANS,
+                    .rates = SOC_CS42L52_RATES,
+                    .formats = SOC_CS42L52_FORMATS,
+            },
+            .capture = {
+                    .stream_name = "Capture",
+                    .channels_min = 1,
+                    .channels_max = SOC_CS42L52_DEFAULT_MAX_CHANS,
+                    .rates = SOC_CS42L52_RATES,
+                    .formats = SOC_CS42L52_FORMATS,
+            },
+                       .ops = &cs42l52_ops,
+};
+EXPORT_SYMBOL_GPL(soc_cs42l52_dai);
 
-static const struct soc_cs42l52_clk_para clk_map_table[] = {
-       /*8k*/
-       {12288000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {18432000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {12000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
-       {24000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
-       {27000000, 8000, CLK_CTL_S_QS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0}, /*4*/
-
-       /*11.025k*/
-       {11289600, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {16934400, 11025, CLK_CTL_S_QS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       
-       /*16k*/
-       {12288000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {18432000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {12000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},/*9*/
-       {24000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
-       {27000000, 16000, CLK_CTL_S_HS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1},
 
-       /*22.05k*/
-       {11289600, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {16934400, 22050, CLK_CTL_S_HS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       
-       /* 32k */
-       {12288000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*14*/
-       {18432000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {12000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
-       {24000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
-       {27000000, 32000, CLK_CTL_S_SS_MODE, CLK_CTL_32K_SR, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 0},
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+static int cs42l52_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{      
+       struct snd_soc_codec *soc_codec;
+       struct soc_codec_cs42l52 * info;
+       struct cs42l52_platform_data *pdata = i2c->dev.platform_data;
+       int ret = 0;
 
-       /* 44.1k */
-       {11289600, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*19*/
-       {16934400, 44100, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       soc_codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (soc_codec == NULL)
+               return -ENOMEM;
 
-       /* 48k */
-       {12288000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {18432000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {12000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
-       {24000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},/*24*/
-       {27000000, 48000, CLK_CTL_S_SS_MODE, CLK_CTL_NOT_32K, CLK_CTL_27M_MCLK, CLK_CTL_RATIO_125, 1},
+       soc_codec->name = SOC_CS42L52_NAME;
+       soc_codec->owner = THIS_MODULE;
+       soc_codec->write = soc_cs42l52_write;
+       soc_codec->read = soc_cs42l52_read;
+       soc_codec->hw_write = (hw_write_t)i2c_master_send;
+       mutex_init(&soc_codec->mutex);
+       INIT_LIST_HEAD(&soc_codec->dapm_widgets);
+       INIT_LIST_HEAD(&soc_codec->dapm_paths);
+       
+       soc_codec->set_bias_level = soc_cs42l52_set_bias_level;
+       soc_codec->dai = &soc_cs42l52_dai;
+       soc_codec->dai->playback.channels_max = 2;
+       soc_codec->dai->capture.channels_max = 2;
+       soc_codec->num_dai = 1;
+       soc_codec->control_data = i2c;
+       soc_codec->dev = &i2c->dev;     
+       soc_codec->pcm_devs = 0;
+       soc_codec->pop_time = 2;
+       soc_codec->dai[0].codec = soc_codec;
 
-       /* 88.2k */
-       {11289600, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {16934400, 88200, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
+       soc_codec->reg_cache_size = sizeof(soc_cs42l52_reg_default);
 
-       /* 96k */
-       {12288000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},
-       {18432000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_128, 0},/*29*/
-       {12000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 0},
-       {24000000, 96000, CLK_CTL_S_DS_MODE, CLK_CTL_NOT_32K, CLK_CTL_NOT_27M, CLK_CTL_RATIO_125, 1},
-};
+       soc_codec->reg_cache = kmemdup(soc_cs42l52_reg_default, sizeof(soc_cs42l52_reg_default), GFP_KERNEL);
 
-static int soc_cs42l52_get_clk(int mclk, int rate)
-{
+       info = (struct soc_codec_cs42l52 *)kmalloc(sizeof(struct soc_codec_cs42l52),GFP_KERNEL);
+       if (info == NULL) {
+               kfree(soc_codec);
+               return -ENOMEM;
+       }
 
-       int i , ret = 0;
-       u_int mclk1, mclk2 = 0;
+       info->sysclk = SOC_CS42L52_DEFAULT_CLK;
+       info->format = SOC_CS42L52_DEFAULT_FORMAT;
 
-       for(i = 0; i < ARRAY_SIZE(clk_map_table); i++)
-       {
-               if(clk_map_table[i].rate == rate)
-               {
-                       mclk1 = clk_map_table[i].mclk;
-                       {
-                               if(abs(mclk - mclk1) < abs(mclk - mclk2))
-                               {
-                                       mclk2 = mclk1;
-                                       ret = i;
-                               }
-                       }
-               }
+       soc_codec->private_data =(void*)info;   
+       if(!soc_codec->reg_cache) {
+               SOCERR("%s: err out of memory\n", __FUNCTION__);
+               ret = -ENOMEM;
+               goto err;
        }
 
-       return ret < ARRAY_SIZE(clk_map_table) ? ret : -EINVAL;
-}
-
-static int soc_cs42l52_pcm_hw_params(struct snd_pcm_substream *substream,
-                        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
-{
-       int ret = 0;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *soc_dev = rtd->socdev;
-       struct snd_soc_codec *soc_codec = soc_dev->card->codec;
-       struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*)soc_codec->private_data;
+       if (pdata->init_platform_hw)                              
+               pdata->init_platform_hw();
 
-       u32 clk = 0;
-       int index = soc_cs42l52_get_clk(info->sysclk, params_rate(params));
+       /*initialize codec*/
+       cs42l52_power_init(soc_codec);
 
-       if(index >= 0)
-       {
-               info->sysclk = clk_map_table[index].mclk;
-               clk |= (clk_map_table[index].speed << CLK_CTL_SPEED_SHIFT) | 
-                     (clk_map_table[index].group << CLK_CTL_32K_SR_SHIFT) | 
-                     (clk_map_table[index].videoclk << CLK_CTL_27M_MCLK_SHIFT) | 
-                     (clk_map_table[index].ratio << CLK_CTL_RATIO_SHIFT) | 
-                     clk_map_table[index].mclkdiv2;
-#ifdef CONFIG_MANUAL_CLK
-               soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, clk);
-#else
-               soc_cs42l52_write(soc_codec, CODEC_CS42L52_CLK_CTL, 0xa0);
-#endif
+    INIT_DELAYED_WORK(&soc_codec->delayed_work, soc_cs42l52_work);
 
+       soc_cs42l52_dai.dev = &i2c->dev;
+       cs42l52_codec = soc_codec;
 
+       ret = snd_soc_register_codec(soc_codec);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+               goto err;
        }
-       else{
-               SOCDBG("can't find out right mclk\n");
-               ret = -EINVAL;
+
+       ret = snd_soc_register_dai(&soc_cs42l52_dai);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
+               goto err_codec;
        }
 
        return ret;
+
+err_codec:
+       snd_soc_unregister_codec(soc_codec);
+err:
+       kfree(cs42l52_codec);
+       cs42l52_codec = NULL;
+       return ret;
 }
 
-int soc_cs42l52_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level)
+static int cs42l52_i2c_remove(struct i2c_client *client)
 {
-       u8 pwctl1 = soc_cs42l52_read(codec, CODEC_CS42L52_PWCTL1) & 0x9f;
-       u8 pwctl2 = soc_cs42l52_read(codec, CODEC_CS42L52_PWCTL2) & 0x07;
+       snd_soc_unregister_dai(&soc_cs42l52_dai);
+       snd_soc_unregister_codec(cs42l52_codec);
 
-       switch (level) {
-        case SND_SOC_BIAS_ON: /* full On */
-               SOCDBG("full on\n");
-               break;
-        case SND_SOC_BIAS_PREPARE: /* partial On */
-               SOCDBG("partial on\n");
-               pwctl1 &= ~(PWCTL1_PDN_CHRG | PWCTL1_PDN_CODEC);
-                soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1);
-                break;
-        case SND_SOC_BIAS_STANDBY: /* Off, with power */
-               SOCDBG("off with power\n");
-               pwctl1 &= ~(PWCTL1_PDN_CHRG | PWCTL1_PDN_CODEC);
-                soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1);
-                break;
-        case SND_SOC_BIAS_OFF: /* Off, without power */
-               SOCDBG("off without power\n");
-//                soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL1, pwctl1 | 0x9f);
-//             soc_cs42l52_write(codec, CODEC_CS42L52_PWCTL2, pwctl2 | 0x07);
-                break;
-        }
-        codec->bias_level = level;
-        return 0;
+       soc_cs42l52_set_bias_level(cs42l52_codec, SND_SOC_BIAS_OFF);
+
+       soc_cs42l52_dai.dev = NULL;
+       if(cs42l52_codec->reg_cache)            
+               kfree(cs42l52_codec->reg_cache);
+       if(cs42l52_codec->private_data)         
+               kfree(cs42l52_codec->private_data);
+       kfree(cs42l52_codec);
+       cs42l52_codec = NULL;
+
+       return 0;
 }
 
-static void soc_cs42l52_work(struct work_struct *work)
+
+static int cs42l52_i2c_shutdown(struct i2c_client *client)
 {
-       struct snd_soc_codec *codec =
-                container_of(work, struct snd_soc_codec, delayed_work.work);
-//added by koffu
-       codec->bias_level = SND_SOC_BIAS_ON;    //20110706
+       SOCDBG("i am here\n");        
+       snd_soc_unregister_dai(&soc_cs42l52_dai);
+       snd_soc_unregister_codec(cs42l52_codec);
 
-       soc_cs42l52_set_bias_level(codec, codec->bias_level);
+       soc_cs42l52_set_bias_level(cs42l52_codec, SND_SOC_BIAS_OFF);
+
+       soc_cs42l52_dai.dev = NULL;
+       if(cs42l52_codec->reg_cache)            
+               kfree(cs42l52_codec->reg_cache);
+       if(cs42l52_codec->private_data)         
+               kfree(cs42l52_codec->private_data);
+       kfree(cs42l52_codec);
+       cs42l52_codec = NULL;
+
+       return 0;
 }
 
+static const struct i2c_device_id cs42l52_i2c_id[] = {
+       { "cs42l52", 0 },
+};
+MODULE_DEVICE_TABLE(i2c, cs42l52_i2c_id);
+
+static struct i2c_driver cs42l52_i2c_drv = {
+       .driver = {
+               .name = "CS42L52",
+               .owner = THIS_MODULE,
+       },
+       .probe =    cs42l52_i2c_probe,
+       .remove =   cs42l52_i2c_remove,
+       .shutdown =  cs42l52_i2c_shutdown,
+       .id_table = cs42l52_i2c_id,
+};
+
+#endif
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static int soc_cs42l52_suspend(struct early_suspend *h)
+{
+       
+       soc_cs42l52_write(cs42l52_codec, CODEC_CS42L52_PWCTL1, PWCTL1_PDN_CODEC);
+       soc_cs42l52_set_bias_level(cs42l52_codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int soc_cs42l52_resume(struct early_suspend *h)
+{
+       struct snd_soc_codec *soc_codec = cs42l52_codec;
+       struct soc_codec_cs42l52 *info = (struct soc_codec_cs42l52*) soc_codec->private_data;
+       int i, reg;
+       u8 data[2];
+       u8 *reg_cache = (u8*) soc_codec->reg_cache;
+       soc_codec->num_dai = 1;
+       /* Sync reg_cache with the hardware */
+       for(i = 0; i < soc_codec->num_dai; i++) {
+
+           for(reg = 0; reg < ARRAY_SIZE(soc_cs42l52_reg_default); reg++) {
+               data[0] = reg;
+               data[1] = reg_cache[reg];
+               if(soc_codec->hw_write(soc_codec->control_data, data, 2) != 2)
+                   break;
+           }
+       }
+
+       soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_STANDBY);
+
+       /*charge cs42l52 codec*/
+       if(soc_codec->suspend_bias_level == SND_SOC_BIAS_ON)
+       {
+               soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_PREPARE);
+               soc_codec->bias_level = SND_SOC_BIAS_ON;
+               schedule_delayed_work(&soc_codec->delayed_work, msecs_to_jiffies(1000));
+       }
+       return 0;
+
+}
+#else
 static int soc_cs42l52_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct snd_soc_device *soc_dev = (struct snd_soc_device*)platform_get_drvdata(pdev);
@@ -1365,7 +1362,6 @@ static int soc_cs42l52_suspend(struct platform_device *pdev, pm_message_t state)
        
        soc_cs42l52_write(soc_codec, CODEC_CS42L52_PWCTL1, PWCTL1_PDN_CODEC);
        soc_cs42l52_set_bias_level(soc_codec, SND_SOC_BIAS_OFF);
-
        return 0;
 }
 
@@ -1398,11 +1394,10 @@ static int soc_cs42l52_resume(struct platform_device *pdev)
                soc_codec->bias_level = SND_SOC_BIAS_ON;
                schedule_delayed_work(&soc_codec->delayed_work, msecs_to_jiffies(1000));
        }
-
        return 0;
 
 }
-
+#endif
 static int soc_cs42l52_probe(struct platform_device *pdev)
 {
        struct snd_soc_device *soc_dev = platform_get_drvdata(pdev);
@@ -1416,17 +1411,15 @@ static int soc_cs42l52_probe(struct platform_device *pdev)
 
        soc_dev->card->codec = cs42l52_codec;
        soc_codec = cs42l52_codec;
-                
-               ret = snd_soc_new_pcms(soc_dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+
+       ret = snd_soc_new_pcms(soc_dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if(ret)
        {
                SOCERR("%s: add new pcms failed\n",__FUNCTION__);
                goto pcm_err;
        }
-       /*init done*/
 
        soc_cs42l52_add_controls(soc_codec);
-
        soc_cs42l52_add_widgets(soc_codec);
 
        ret = snd_soc_init_card(soc_dev);
@@ -1439,6 +1432,11 @@ static int soc_cs42l52_probe(struct platform_device *pdev)
                goto card_err;
        }
 
+#ifdef CONFIG_HAS_EARLYSUSPEND   
+       cs42l52_early_suspend.suspend =soc_cs42l52_suspend;  
+       cs42l52_early_suspend.resume =soc_cs42l52_resume;//   cs42l52_early_suspend.level = 0x2;    
+       register_early_suspend(&cs42l52_early_suspend);
+#endif
        return ret;
 
 card_err:
@@ -1455,33 +1453,90 @@ static int soc_cs42l52_remove(struct platform_device *pdev)
 
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
-
+#ifdef CONFIG_HAS_EARLYSUSPEND         
+       unregister_early_suspend(&cs42l52_early_suspend);
+#endif 
        return 0;
 }
 
 struct snd_soc_codec_device soc_codec_dev_cs42l52 = {
        .probe = soc_cs42l52_probe,
        .remove = soc_cs42l52_remove,
+#ifndef        CONFIG_HAS_EARLYSUSPEND
        .suspend = soc_cs42l52_suspend,
        .resume = soc_cs42l52_resume,
+#endif 
 };
 
 EXPORT_SYMBOL_GPL(soc_codec_dev_cs42l52);
 
 static int __init cs42l52_modinit(void)
 {
-       printk(KERN_INFO"cs42l52_i2c_probe\n");
        return i2c_add_driver(&cs42l52_i2c_drv);
 }
 module_init(cs42l52_modinit);
 
 static void __exit cs42l52_exit(void)
 {
-       printk(KERN_INFO"cs42l52_i2c_probe\n");
        i2c_del_driver(&cs42l52_i2c_drv);
 }
 module_exit(cs42l52_exit);
 
+
+
 MODULE_DESCRIPTION("ALSA SoC CS42L52 Codec");
 MODULE_AUTHOR("Bo Liu, Bo.Liu@cirrus.com, www.cirrus.com");
 MODULE_LICENSE("GPL");
+
+
+
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+static int proc_cs42l52_show (struct seq_file *s, void *v)
+{
+       struct snd_soc_codec *codec = cs42l52_codec;
+       int reg;
+
+       seq_printf (s, "    cs42l52 registers:\n");
+       for (reg = 0; reg < 53; reg++) {
+               if (reg%10 == 0) 
+                       seq_printf (s, "\n            ");
+               seq_printf (s, "0x%02x ", soc_cs42l52_read(codec, reg));
+       }
+       seq_printf (s, "\n\n");
+
+#if 0//for check cache
+       u8 *cache = codec->reg_cache;
+       seq_printf (s, "            cache:\n");
+       for (reg = 0; reg < 53; reg++) {
+               if (reg%10 == 0) 
+                       seq_printf (s, "\n            ");
+               seq_printf (s, "0x%02x ", cache[reg]);
+       }
+       seq_printf (s, "\n\n");
+#endif
+
+       return 0;
+}
+
+static int proc_cs42l52_open (struct inode *inode, struct file *file)
+{
+       return single_open (file, proc_cs42l52_show, NULL);
+}
+
+static const struct file_operations proc_cs42l52_fops = {
+       .open           = proc_cs42l52_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int __init codec_proc_init (void)
+{
+       proc_create ("cs42l52", 0, NULL, &proc_cs42l52_fops);
+       return 0;
+}
+late_initcall (codec_proc_init);
+#endif /* CONFIG_PROC_FS */
index d4c92cbf90bd5f5944c0cc87ea0249bb5145e49e..29b9b249360ef293498961694b56656beb339ec2 100755 (executable)
@@ -13,6 +13,7 @@
 
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/clk.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include "rk29_pcm.h"
 #include "rk29_i2s.h"
 
-#if 0
+#if 1
 #define        DBG(x...)       printk(KERN_INFO x)
 #else
 #define        DBG(x...)
 #endif
 
+
 static int rk29_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
@@ -38,6 +40,8 @@ static int rk29_hw_params(struct snd_pcm_substream *substream,
         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
         unsigned int pll_out = 0; 
         unsigned int lrclk = 0;
+               int div_bclk,div_mclk;
+               struct clk      *general_pll;
         int ret;
           
         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);    
@@ -50,34 +54,33 @@ static int rk29_hw_params(struct snd_pcm_substream *substream,
                DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
         }
         else
-        {
-                
-                /* set codec DAI configuration */
-                #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
-                ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-                                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-                #endif 
-                #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
-                ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-                                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); 
-                #endif
-                if (ret < 0)
-                  return ret; 
-
-                /* set cpu DAI configuration */
-                #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
-                ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-                                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-                #endif 
-                #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
-                ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-                                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);        
-                #endif         
-                if (ret < 0)
-                  return ret;
+       {       
+            /* set codec DAI configuration */
+            #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
+            ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+                            SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+            #endif     
+            #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
+            ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+                            SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+            #endif
+            if (ret < 0)
+              return ret; 
 
-        }
+            /* set cpu DAI configuration */
+            #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
+            ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+                            SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+            #endif     
+            #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
+            ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+                            SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
 
+            #endif             
+            if (ret < 0)
+              return ret;
+        }
+               DBG("Enter:%s, rate=%d\n",__FUNCTION__,params_rate(params));
 
         switch(params_rate(params)) {
         case 8000:
@@ -93,23 +96,48 @@ static int rk29_hw_params(struct snd_pcm_substream *substream,
                 pll_out = 11289600;
                 break;
         default:
-                DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
+                DBG("Enter:%s, Error rate=%d\n",__FUNCTION__,params_rate(params));
                 return -EINVAL;
                 break;
         }
-        DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
+
+               //pll_out = 12000000;
 
         #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
-         //
-         //
+               pll_out = 11289600;
+               snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0);
+               snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
         #endif
 
         #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
-        snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
-        snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);
-        snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);
+               general_pll=clk_get(NULL, "general_pll");
+               if(clk_get_rate(general_pll)>260000000)
+               {
+                       div_bclk=(pll_out/4)/params_rate(params)-1;
+                       //div_bclk= 63;
+                       div_mclk= 3;
+               }
+               else if(clk_get_rate(general_pll)>130000000)
+               {
+                       div_bclk=(pll_out/2)/params_rate(params)-1;
+                       div_mclk=1;
+               }
+               else
+               {
+                       pll_out=pll_out/4;
+                       div_bclk=(pll_out)/params_rate(params)-1;
+                       div_mclk=0;
+               }
+               DBG("func is%s,gpll=%ld,pll_out=%ld,div_mclk=%ld,div_bclk=%ld\n",
+                       __FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk,div_bclk);
+
+               //snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0);
+               snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
+        snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk);
+        snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk);
+        DBG("Enter:%s, LRCK=%d\n",__FUNCTION__,(pll_out/4)/params_rate(params));
         #endif
-        DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params));
+
         
         return 0;
 }
@@ -140,20 +168,31 @@ static int rk29_cs42l52_init(struct snd_soc_codec *codec)
        int ret;
          
         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-
+#if 0
         /* Add specific widgets */
        snd_soc_dapm_new_controls(codec, cs42l52_dapm_widgets,
                                  ARRAY_SIZE(cs42l52_dapm_widgets));
+
+
        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
         /* Set up specific audio path audio_mapnects */
         snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
-        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-        snd_soc_dapm_nc_pin(codec, "HPA");
-        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-       snd_soc_dapm_nc_pin(codec, "HPB");
-       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+#endif         
+
+       snd_soc_dapm_nc_pin(codec, "INPUT1A");
+       snd_soc_dapm_nc_pin(codec, "INPUT2A");
+
+       snd_soc_dapm_nc_pin(codec, "INPUT3A");
+       snd_soc_dapm_nc_pin(codec, "INPUT4A");
+
+       snd_soc_dapm_nc_pin(codec, "INPUT1B");
+       snd_soc_dapm_nc_pin(codec, "INPUT2B");
+       snd_soc_dapm_nc_pin(codec, "INPUT3B");
+       snd_soc_dapm_nc_pin(codec, "INPUT4B");
+       snd_soc_dapm_nc_pin(codec, "MICB");
+       
         snd_soc_dapm_sync(codec);
-        DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+               
         return 0;
 }