asoc:codecs: aic326x: change alsa ctrls for headphone driver
[linux-2.6.git] / sound / soc / codecs / tlv320aic326x.c
index 988d290..ce8b5bc 100644 (file)
@@ -54,6 +54,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
 #include <asm/div64.h>
@@ -62,7 +63,7 @@
 #include <linux/spi/spi.h>
 
 #include "tlv320aic326x.h"
-
+#include <linux/gpio.h>
 /*
  *****************************************************************************
  * Global Variable
@@ -165,6 +166,7 @@ static int aic3262_multi_i2s_asi1_mute(struct snd_soc_dai *dai, int mute);
 static int aic3262_multi_i2s_asi2_mute(struct snd_soc_dai *dai, int mute);
 
 static int aic3262_multi_i2s_asi3_mute(struct snd_soc_dai *dai, int mute);
+
 #if 0
 static const char *wclk1_pincontrol[] = {
        "ASI1 Word Clock Input/Output", "CLKOUT output"};
@@ -558,7 +560,7 @@ static int __new_control_info(struct snd_kcontrol *kcontrol,
  *----------------------------------------------------------------------------
  */
 static int __new_control_get(struct snd_kcontrol *kcontrol,
-                            struct snd_ctl_elem_value *ucontrol)
+               struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        u32 val;
@@ -576,7 +578,7 @@ static int __new_control_get(struct snd_kcontrol *kcontrol,
  *----------------------------------------------------------------------------
  */
 static int __new_control_put(struct snd_kcontrol *kcontrol,
-                            struct snd_ctl_elem_value *ucontrol)
+               struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
@@ -621,17 +623,16 @@ static const DECLARE_TLV_DB_SCALE(beep_gen_volume_tlv, -6300, 100, 0);
 
 /* Chip-level Input and Output CM Mode Controls */
 static const char *input_common_mode_text[] = {
-    "0.9v", "0.75v" };
+       "0.9v", "0.75v" };
 
 static const char *output_common_mode_text[] = {
-    "Input CM", "1.25v", "1.5v", "1.65v" };
+       "Input CM", "1.25v", "1.5v", "1.65v" };
 
 static const struct soc_enum input_cm_mode =
-    SOC_ENUM_SINGLE(CM_REG, 2, 2, input_common_mode_text);
+       SOC_ENUM_SINGLE(CM_REG, 2, 2, input_common_mode_text);
 
 static const struct soc_enum output_cm_mode =
-    SOC_ENUM_SINGLE(CM_REG, 0, 4, output_common_mode_text);
-
+       SOC_ENUM_SINGLE(CM_REG, 0, 4, output_common_mode_text);
 
 /*
  *****************************************************************************
@@ -732,14 +733,8 @@ static const struct snd_kcontrol_new aic3262_snd_controls[] = {
                                        RAGC_CNTL_R7, 0, 0x0F, 0),
 
        SOC_SINGLE("DAC PRB Selection",DAC_PRB, 0, 25, 0),
-
-       SOC_SINGLE("INTERRUPT FLAG - Read only", 46, 0, 255,0),
-       SOC_SINGLE("INTERRUPT STICKY FLAG - Read only", 44, 0, 255,0),
-       SOC_SINGLE("INT1 CONTROL", 48, 0, 255,0),
-       SOC_SINGLE("GPIO1 CONTROL", GPIO1_IO_CNTL, 0, 255,0),
        SOC_SINGLE("HP_DEPOP", HP_DEPOP, 0, 255,0),
        SOC_DOUBLE("IN1 LO BYPASS VOLUME" , LINE_AMP_CNTL_R2, 3, 0, 3, 1),
-
        SOC_ENUM("Input CM mode", input_cm_mode),
        SOC_ENUM("Output CM mode", output_cm_mode),
 };
@@ -775,6 +770,8 @@ static const struct aic3262_rate_divs aic3262_divs[] = {
 #ifdef CONFIG_MINI_DSP
        {12000000, 16000, 1, 8, 1920, 384, 4, 4, 128, 4, 12, 12,
                {{0, 60, 0}, {0, 61, 0} } },
+       {12288000, 16000, 1, 9, 0, 216, 2, 16, 72, 2, 48, 27,
+               {{0, 60, 0}, {0, 61, 0} } },
 #else
        {12000000, 16000, 1, 8, 1920, 128, 8, 6, 128, 8, 6, 4,
                {{0, 60, 1}, {0, 61, 1} } },
@@ -816,6 +813,8 @@ static const struct aic3262_rate_divs aic3262_divs[] = {
 #ifdef CONFIG_MINI_DSP
        {12288000, 48000, 1, 8, 52, 128, 2, 8, 128, 2, 8, 4,
                {{0, 60, 0}, {0, 61, 0} } },
+       {12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4,
+         {{0, 60, 0}, {0, 61, 0}}},
 #else
        /* 48k rate */
        {12000000, 48000, 1, 8, 1920, 128, 8, 2, 128, 8, 2, 4,
@@ -1592,6 +1591,9 @@ static int aic3262_asi2_clk_config(struct snd_soc_codec *codec,
        minidspA_data |= aic3262->asiCtxt[1].adc_input;
        snd_soc_write(codec, ASI2_ADC_INPUT_CNTL, minidspA_data);
 
+       /* NO Manual configuration of WCLK and BCLK for Master Mode.
+       * DAPM Handles all the required modifications.
+       */
        if (aic3262->asiCtxt[1].master == 1) {
                DBG(KERN_INFO
                "#%s: Codec Master on ASI2 Port. Enabling BCLK WCLK Divider.\n",
@@ -1602,6 +1604,7 @@ static int aic3262_asi2_clk_config(struct snd_soc_codec *codec,
                wclk_N_value = snd_soc_read(codec, ASI2_WCLK_N);
                snd_soc_write(codec, ASI2_WCLK_N, (wclk_N_value | 0xA0));
        }
+
        return 0;
 
 }
@@ -2106,6 +2109,51 @@ err:
        return 0;
 }
 
+
+/*
+*
+* aic3262_multi_i2s_set_clkdiv
+*
+*/
+static int aic3262_multi_i2s_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div)
+{
+       int value;
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
+
+
+       value = snd_soc_read(codec, div_id);
+       snd_soc_write(codec, div_id, (value | div));
+
+       printk(KERN_INFO "#%s: DAI ID %d Page %d Register %d Divider_Val %d Final_Value 0x%x\n",
+                       __func__, codec_dai->id, (div_id /128), (div_id%128), div,
+                       (value | div));
+
+       /* Store the Clock Divider inside the Private Structure */
+       switch(codec_dai->id) {
+       case 1:
+               if (div_id == ASI1_BCLK_N)
+               aic3262->asiCtxt[0].bclk_div = div;
+               if (div_id == ASI1_WCLK_N)
+               aic3262->asiCtxt[0].wclk_div = div;
+       break;
+       case 2:
+               if (div_id == ASI2_BCLK_N)
+               aic3262->asiCtxt[1].bclk_div = div;
+               if (div_id == ASI2_WCLK_N)
+               aic3262->asiCtxt[1].wclk_div = div;
+       break;
+       case 3:
+               if (div_id == ASI3_BCLK_N)
+               aic3262->asiCtxt[2].bclk_div = div;
+               if (div_id == ASI3_WCLK_N)
+               aic3262->asiCtxt[2].wclk_div = div;
+       break;
+       }
+       return 0;
+}
+
+
 /*
  *----------------------------------------------------------------------------
  * @struct  snd_soc_codec_dai |
@@ -2123,6 +2171,7 @@ struct snd_soc_dai_ops aic3262_multi_i2s_dai_ops = {
        .set_pll        = aic3262_multi_i2s_set_dai_pll,
        .set_sysclk     = aic3262_multi_i2s_set_dai_sysclk,
        .shutdown        = aic3262_multi_i2s_shutdown,
+       .set_clkdiv      = aic3262_multi_i2s_set_clkdiv,
 };
 
 
@@ -2132,13 +2181,13 @@ static struct snd_soc_dai_driver tlv320aic3262_dai[] = {
        .name = "aic3262-asi1",
        .id = 1,
        .playback = {
-               .stream_name = "Playback",
+               .stream_name = "ASI1 Playback",
                .channels_min = 1,
                .channels_max = 2,
                .rates = AIC3262_RATES,
                .formats = AIC3262_FORMATS},
        .capture = { /* dummy for fast DAI switching */
-               .stream_name = "Capture",
+               .stream_name = "ASI1 Capture",
                .channels_min = 1,
                .channels_max = 2,
                .rates = AIC3262_RATES,
@@ -2150,13 +2199,13 @@ static struct snd_soc_dai_driver tlv320aic3262_dai[] = {
        .name = "aic3262-asi2",
        .id = 2,
        .playback = {
-               .stream_name = "Playback",
+               .stream_name = "ASI2 Playback",
                .channels_min = 1,
                .channels_max = 2,
                .rates = AIC3262_RATES,
                .formats = AIC3262_FORMATS,},
        .capture = {
-               .stream_name = "Capture",
+               .stream_name = "ASI2 Capture",
                .channels_min = 1,
                .channels_max = 2,
                .rates = AIC3262_RATES,
@@ -2169,13 +2218,13 @@ static struct snd_soc_dai_driver tlv320aic3262_dai[] = {
        .name = "aic3262-asi3",
        .id = 3,
        .playback = {
-               .stream_name = "Playback",
+               .stream_name = "ASI3 Playback",
                .channels_min = 1,
                .channels_max = 2,
                .rates = AIC3262_RATES,
                .formats = AIC3262_FORMATS, },
        .capture = {
-               .stream_name = "Capture",
+               .stream_name = "ASI3 Capture",
                .channels_min = 1,
                .channels_max = 2,
                .rates = AIC3262_RATES,
@@ -2384,8 +2433,8 @@ static const struct aic3262_configs aic3262_reg_init[] = {
        /* set default volumes */
        {0, DAC_LVOL, 0x01},
        {0, DAC_RVOL, 0x01},
-       {0, HPL_VOL,  0x3a},
-       {0, HPR_VOL,  0x3a},
+       {0, HPL_VOL,  0x80},
+       {0, HPR_VOL,  0x80},
        {0, SPK_AMP_CNTL_R2, 0x14},
        {0, SPK_AMP_CNTL_R3, 0x14},
        {0, SPK_AMP_CNTL_R4, 0x33},
@@ -2416,43 +2465,44 @@ static const struct aic3262_configs aic3262_reg_init[] = {
        {0, PLL_PR_POW_REG, 0x11},      /*PLL Power=0-down, P=1, R=1 vals*/
        {0, 0x3d, 1},
 
-       {0, LMIC_PGA_PIN, 0x55},        /*IN1_L select - - 10k -LMICPGA_P*/
+       {0, LMIC_PGA_PIN, 0x0}, /*IN1_L select - - 10k -LMICPGA_P*/
        {0, LMIC_PGA_MIN, 0x40},        /*CM to LMICPGA-M*/
-       {0, RMIC_PGA_PIN, 0x55},        /*IN1_R select - - 10k -RMIC_PGA_P*/
-       {0, RMIC_PGA_MIN, 0x40},        /*CM to RMICPGA_M*/
+       {0, RMIC_PGA_PIN, 0x0}, /*IN1_R select - - 10k -RMIC_PGA_P*/
+       {0, RMIC_PGA_MIN, 0x0}, /*CM to RMICPGA_M*/
        {0, MIC_PWR_DLY , 33},  /*LMIC-PGA-POWERUP-DELAY - default*/
        {0, REF_PWR_DLY, 1},    /*FIXMELATER*/
 
 
-       {0, ADC_CHANNEL_POW, 0xc2}, /*ladc, radc ON , SOFT STEP disabled*/
+       {0, ADC_CHANNEL_POW, 0x0}, /*ladc, radc ON , SOFT STEP disabled*/
        {0, ADC_FINE_GAIN, 0x00},   /*ladc - unmute, radc - unmute*/
-       {0, MICL_PGA, 0x4f},
-       {0, MICR_PGA, 0x4f},
+       {0, MICL_PGA, 0x3f},
+       {0, MICR_PGA, 0x3f},
        /*controls MicBias ext power based on B0_P1_R51_D6*/
        {0, MIC_BIAS_CNTL, 0x80},
        /*   ASI1 Configuration */
        {0, ASI1_BUS_FMT, 0},
        {0, ASI1_BWCLK_CNTL_REG, 0x00},         /* originaly 0x24*/
        {0, ASI1_BCLK_N_CNTL, 1},
-       {0, ASI1_BCLK_N, 0x84},
+       {0, ASI1_BCLK_N, 0x04},
 
        {0, MA_CNTL, 0},                        /* Mixer Amp disabled */
        {0, LINE_AMP_CNTL_R2, 0x00},            /* Line Amp Cntl disabled */
 
        /* ASI2 Configuration */
        {0, ASI2_BUS_FMT, 0},
-       {0, ASI2_BCLK_N_CNTL, 1},
-       {0, ASI2_BCLK_N, 0x84},
+       {0, ASI2_BCLK_N_CNTL, 0x01},
+       {0, ASI2_BCLK_N, 0x04},
        {0, ASI2_BWCLK_OUT_CNTL, 0x20},
 
        {0, BEEP_CNTL_R1, 0x05},
        {0, BEEP_CNTL_R2, 0x04},
 
        /* Interrupt config for headset detection */
-       {0, INT1_CNTL, 0x80},
+       {0,HEADSET_TUNING1_REG,0x7f},
+       {0, INT1_CNTL, 0x40},
+       /*{0, TIMER_REG, 0x8c},*/
        {0, INT_FMT, 0x40},
        {0, GPIO1_IO_CNTL, 0x14},
-       /* enables debounce with 512ms*/
        {0, HP_DETECT, 0x96},
 
 #if defined(CONFIG_MINI_DSP)
@@ -2497,13 +2547,13 @@ static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
        SOC_DAPM_SINGLE("MAL Switch", HP_AMP_CNTL_R1, 7, 1, 0),
        SOC_DAPM_SINGLE("LDAC Switch", HP_AMP_CNTL_R1, 5, 1, 0),
        SOC_DAPM_SINGLE_TLV("LOL-B1 Volume", HP_AMP_CNTL_R2, 0,
-                                                       0x7f, 1, lo_hp_tlv),
+                                                       0x7f, 0, lo_hp_tlv),
 };
 
 /* Right HPR Mixer */
 static const struct snd_kcontrol_new hpr_output_mixer_controls[] = {
        SOC_DAPM_SINGLE_TLV("LOR-B1 Volume", HP_AMP_CNTL_R3, 0,
-                                                       0x7f, 1, lo_hp_tlv),
+                                                       0x7f, 0, lo_hp_tlv),
        SOC_DAPM_SINGLE("LDAC Switch", HP_AMP_CNTL_R1,   2, 1, 0),
        SOC_DAPM_SINGLE("RDAC Switch", HP_AMP_CNTL_R1, 4, 1, 0),
        SOC_DAPM_SINGLE("MAR Switch", HP_AMP_CNTL_R1, 6, 1, 0),
@@ -2643,6 +2693,28 @@ SOC_ENUM_SINGLE_DECL(dacminidspin1_enum, MINIDSP_PORT_CNTL_REG, 4, dacminidspin1
 static const struct snd_kcontrol_new dacminidspin1_control =
        SOC_DAPM_ENUM("DAC MiniDSP IN1 Route", dacminidspin1_enum);
 
+static const char *dacminidspin2_text[] = {
+       "ASI1 In", "ASI2 In","ASI3 In"
+};
+
+//static const struct soc_enum dacminidspin1_enum =
+//       SOC_ENUM_SINGLE(MINIDSP_DATA_PORT_CNTL, 5, 2, dacminidspin1_text);
+SOC_ENUM_SINGLE_DECL(dacminidspin2_enum, MINIDSP_PORT_CNTL_REG, 2, dacminidspin2_text);
+
+static const struct snd_kcontrol_new dacminidspin2_control =
+       SOC_DAPM_ENUM("DAC MiniDSP IN2 Route", dacminidspin2_enum);
+
+static const char *dacminidspin3_text[] = {
+       "ASI1 In", "ASI2 In","ASI3 In"
+};
+
+//static const struct soc_enum dacminidspin1_enum =
+//       SOC_ENUM_SINGLE(MINIDSP_DATA_PORT_CNTL, 5, 2, dacminidspin1_text);
+SOC_ENUM_SINGLE_DECL(dacminidspin3_enum, MINIDSP_PORT_CNTL_REG, 0, dacminidspin3_text);
+
+static const struct snd_kcontrol_new dacminidspin3_control =
+SOC_DAPM_ENUM("DAC MiniDSP IN3 Route", dacminidspin3_enum);
+
 static const char *asi1out_text[] = {
        "Off",
        "ASI1 Out",
@@ -2684,6 +2756,29 @@ static const char *asi1bclk_text[] = {
        "ADC_MOD_CLK",
 };
 
+SOC_ENUM_SINGLE_DECL(asi1bclk_enum, ASI1_BCLK_N_CNTL, 0, asi1bclk_text);
+static const struct snd_kcontrol_new asi1bclk_control =
+       SOC_DAPM_ENUM("ASI1_BCLK Route", asi1bclk_enum);
+
+static const char *asi2bclk_text[] = {
+       "DAC_CLK",
+       "DAC_MOD_CLK",
+       "ADC_CLK",
+       "ADC_MOD_CLK",
+};
+SOC_ENUM_SINGLE_DECL(asi2bclk_enum, ASI2_BCLK_N_CNTL, 0, asi2bclk_text);
+static const struct snd_kcontrol_new asi2bclk_control =
+       SOC_DAPM_ENUM("ASI2_BCLK Route", asi2bclk_enum);
+static const char *asi3bclk_text[] = {
+       "DAC_CLK",
+       "DAC_MOD_CLK",
+       "ADC_CLK",
+       "ADC_MOD_CLK",
+};
+SOC_ENUM_SINGLE_DECL(asi3bclk_enum, ASI3_BCLK_N_CNTL, 0, asi3bclk_text);
+static const struct snd_kcontrol_new asi3bclk_control =
+       SOC_DAPM_ENUM("ASI3_BCLK Route", asi3bclk_enum);
+
 static int aic326x_hp_event(struct snd_soc_dapm_widget *w,
                struct snd_kcontrol *kcontrol, int event)
 {
@@ -2698,15 +2793,173 @@ static int pll_power_on_event(struct snd_soc_dapm_widget *w,
        }
        return 0;
 }
+
+static int polling_loop(struct snd_soc_codec *codec, unsigned int reg,
+                       int mask, int on_off)
+{
+       unsigned int counter, status;
+
+       counter = 0;
+       switch(on_off) {
+               case 0: /*off*/
+                       do {
+                               status = snd_soc_read(codec, reg);
+                               counter++;
+                       } while ((counter < 500) && ((status & mask) == mask));
+               break;
+               case 1: /*on*/
+                       do {
+                               status = snd_soc_read(codec, reg);
+                               counter++;
+                       } while ((counter < 500) && ((status & mask) != mask));
+               break;
+               default:
+                       printk("%s: unknown arguement\n", __func__);
+                       break;
+       }
+
+       printk("%s: exiting with count value %d \n", __func__, counter);
+       if(counter >= 500)
+               return -1;
+       return 0;
+}
+
+int poll_dac(struct snd_soc_codec *codec, int left_right, int on_off)
+{
+       int ret = 0;
+
+       aic3262_change_page(codec, 0);
+       aic3262_change_book(codec, 0);
+
+       switch(on_off) {
+
+               case 0:/*power off polling*/
+                       /*DAC power polling logic*/
+                       switch(left_right) {
+                               case 0: /*left dac polling*/
+                                       ret = polling_loop(codec, DAC_FLAG_R1, LDAC_POW_FLAG_MASK, 0);
+                                       break;
+                               case 1:/*right dac polling*/
+                                       ret = polling_loop(codec, DAC_FLAG_R1, RDAC_POW_FLAG_MASK, 0);
+                                       break;
+                       }
+                       break;
+               case 1:/*power on polling*/
+                       /*DAC power polling logic*/
+                       switch(left_right) {
+                               case 0: /*left dac polling*/
+                                       ret = polling_loop(codec, DAC_FLAG_R1, LDAC_POW_FLAG_MASK, 1);
+                                       break;
+                               case 1:/*right dac polling*/
+                                       ret = polling_loop(codec, DAC_FLAG_R1, RDAC_POW_FLAG_MASK, 1);
+                                       break;
+                       }
+               break;
+               default:
+                       printk("%s:unknown arguement\n", __func__);
+                       break;
+               }
+       if(ret)
+               printk("%s: power %s %s failure", __func__, left_right?"right":"left", on_off?"on":"off");
+       return ret;
+}
+
+int poll_adc(struct snd_soc_codec *codec, int left_right, int on_off)
+{
+       int ret = 0;
+
+       aic3262_change_page(codec, 0);
+       aic3262_change_book(codec, 0);
+
+       switch(on_off) {
+
+               case 0:/*power off polling*/
+                       /*DAC power polling logic*/
+                       switch(left_right) {
+                               case 0: /*left dac polling*/
+                                       ret = polling_loop(codec, ADC_FLAG_R1, LADC_POW_FLAG_MASK, 0);
+                                       break;
+                               case 1:/*right dac polling*/
+                                       ret = polling_loop(codec, ADC_FLAG_R1, RADC_POW_FLAG_MASK, 0);
+                                       break;
+       }
+                       break;
+               case 1:/*power on polling*/
+                       /*DAC power polling logic*/
+                       switch(left_right) {
+                               case 0: /*left dac polling*/
+                                       ret = polling_loop(codec, ADC_FLAG_R1, LADC_POW_FLAG_MASK, 1);
+                                       break;
+                               case 1:/*right dac polling*/
+                                       ret = polling_loop(codec, ADC_FLAG_R1, RADC_POW_FLAG_MASK, 1);
+                                       break;
+               }
+                       break;
+               default:
+                       printk("%s:unknown arguement\n", __func__);
+                       break;
+       }
+
+       if(ret)
+               printk("%s: power %s %s failure", __func__, left_right?"right":"left", on_off?"on":"off");
+       return ret;
+}
+
+static int  slave_dac_event(struct snd_soc_dapm_widget *w,
+                              struct snd_kcontrol *kcontrol, int event)
+
+{
+       struct snd_soc_codec *codec = w->codec;
+
+       if (event & SND_SOC_DAPM_POST_PMU) {
+               /* Poll for DAC Power-up first */
+               poll_dac(codec, 0, 1);
+               poll_dac(codec, 1, 1);
+       }
+
+       if (event & SND_SOC_DAPM_POST_PMD) {
+               poll_dac(codec, 0, 0);
+               poll_dac(codec, 1, 0);
+       }
+       return 0;
+}
+
+
+static int  slave_adc_event(struct snd_soc_dapm_widget *w,
+                              struct snd_kcontrol *kcontrol, int event)
+
+{
+       struct snd_soc_codec *codec = w->codec;
+
+       if (event & SND_SOC_DAPM_POST_PMU) {
+
+               /* Poll for ADC Power-up first */
+               poll_adc(codec, 0, 1);
+               poll_adc(codec, 1, 1);
+       }
+
+
+       if (event & SND_SOC_DAPM_POST_PMD) {
+               poll_adc(codec, 0, 0);
+               poll_adc(codec, 1, 0);
+       }
+
+       return 0;
+}
+
 static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
        /* TODO: Can we switch these off ? */
        SND_SOC_DAPM_AIF_IN("ASI1IN", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_IN("ASI2IN", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_IN("ASI3IN", "ASI3 Playback", 0, SND_SOC_NOPM, 0, 0),
 
-       SND_SOC_DAPM_DAC("Left DAC", NULL, PASI_DAC_DP_SETUP, 7, 0),
-       SND_SOC_DAPM_DAC("Right DAC", NULL, PASI_DAC_DP_SETUP, 6, 0),
 
+       SND_SOC_DAPM_DAC_E("Left DAC", NULL, PASI_DAC_DP_SETUP, 7, 0,
+                       slave_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD |
+                       SND_SOC_DAPM_PRE_PMD),
+       SND_SOC_DAPM_DAC_E("Right DAC", NULL, PASI_DAC_DP_SETUP, 6, 0,
+                       slave_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD |
+                       SND_SOC_DAPM_PRE_PMD),
 
        /* dapm widget (path domain) for HPL Output Mixer */
        SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0,
@@ -2800,7 +3053,10 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
 
        SND_SOC_DAPM_MUX("DAC MiniDSP IN1 Route",
                        SND_SOC_NOPM, 0, 0, &dacminidspin1_control),
-
+SND_SOC_DAPM_MUX("DAC MiniDSP IN2 Route",
+                       SND_SOC_NOPM, 0, 0, &dacminidspin2_control),
+       SND_SOC_DAPM_MUX("DAC MiniDSP IN3 Route",
+                       SND_SOC_NOPM, 0, 0, &dacminidspin3_control),
 
        SND_SOC_DAPM_PGA("CM", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("CM1L", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -2827,9 +3083,13 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("ADC MiniDSP OUT3", SND_SOC_NOPM, 0, 0, NULL, 0),
 
 
-       SND_SOC_DAPM_ADC("Left ADC", NULL, ADC_CHANNEL_POW, 7, 0),
-       SND_SOC_DAPM_ADC("Right ADC", NULL, ADC_CHANNEL_POW, 6, 0),
 
+       SND_SOC_DAPM_ADC_E("Left ADC", NULL, ADC_CHANNEL_POW, 7, 0,
+                       slave_adc_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD |
+                       SND_SOC_DAPM_PRE_PMD),
+       SND_SOC_DAPM_ADC_E("Right ADC", NULL, ADC_CHANNEL_POW, 6, 0,
+                       slave_adc_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD |
+                       SND_SOC_DAPM_PRE_PMD),
 
        SND_SOC_DAPM_PGA("Left MicPGA",MICL_PGA, 7, 1, NULL, 0),
        SND_SOC_DAPM_PGA("Right MicPGA",MICR_PGA, 7, 1, NULL, 0),
@@ -2883,29 +3143,67 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
 
        SND_SOC_DAPM_SUPPLY("PLLCLK",PLL_PR_POW_REG,7,0,pll_power_on_event,
                                                SND_SOC_DAPM_POST_PMU),
-       SND_SOC_DAPM_SUPPLY("NDAC",NDAC_DIV_POW_REG,7,0, NULL, 0),
-       SND_SOC_DAPM_SUPPLY("MDAC",MDAC_DIV_POW_REG,7,0, NULL, 0),
-       SND_SOC_DAPM_SUPPLY("NADC",NADC_DIV_POW_REG,7,0, NULL, 0),
-       SND_SOC_DAPM_SUPPLY("MADC",MADC_DIV_POW_REG,7,0, NULL, 0),
-
-
+       SND_SOC_DAPM_SUPPLY("DACCLK",NDAC_DIV_POW_REG,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("CODEC_CLK_IN",SND_SOC_NOPM,0,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("DAC_MOD_CLK",MDAC_DIV_POW_REG,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ADCCLK",NADC_DIV_POW_REG,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ADC_MOD_CLK",MADC_DIV_POW_REG,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI1_BCLK",ASI1_BCLK_N,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI1_WCLK",ASI1_WCLK_N,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI2_BCLK",ASI2_BCLK_N,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI2_WCLK",ASI2_WCLK_N,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI3_BCLK",ASI3_BCLK_N,7,0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI3_WCLK",ASI3_WCLK_N,7,0, NULL, 0),
+       SND_SOC_DAPM_MUX("ASI1_BCLK Route",
+               SND_SOC_NOPM, 0, 0, &asi1bclk_control),
+       SND_SOC_DAPM_MUX("ASI2_BCLK Route", SND_SOC_NOPM, 0, 0, &asi2bclk_control),
+       SND_SOC_DAPM_MUX("ASI3_BCLK Route", SND_SOC_NOPM, 0, 0, &asi3bclk_control),
 };
 
 static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
-/* TODO: Do we need only DACCLK for ASIIN's and ADCCLK for ASIOUT??? */
-/* Clock portion */
-       {"NDAC", NULL, "PLLCLK"},
-       {"MDAC", NULL, "NDAC"},
-       {"ASI1IN", NULL , "NDAC"},
-       {"ASI1IN", NULL , "NADC"},
-       {"ASI1IN", NULL , "MDAC"},
-       {"ASI1IN", NULL , "MADC"},
-
-       {"ASI1OUT", NULL , "NDAC"},
-       {"ASI1OUT", NULL , "NADC"},
-       {"ASI1OUT", NULL , "MDAC"},
-       {"ASI1OUT", NULL , "MADC"},
+       /* TODO: Do we need only DACCLK for ASIIN's and ADCCLK for ASIOUT??? */
+       /* Clock portion */
+       {"CODEC_CLK_IN", NULL, "PLLCLK"},
+       {"DACCLK", NULL, "CODEC_CLK_IN"},
+       {"ADCCLK", NULL, "CODEC_CLK_IN"},
+       {"DAC_MOD_CLK", NULL, "DACCLK"},
+#ifdef AIC3262_SYNC_MODE
+       {"ADC_MOD_CLK", NULL,"DACCLK"},
+#else
+       {"ADC_MOD_CLK", NULL, "ADCCLK"},
+#endif
 
+       {"ASI1_BCLK Route","DAC_CLK","DACCLK"},
+       {"ASI1_BCLK Route","DAC_MOD_CLK","DAC_MOD_CLK"},
+       {"ASI1_BCLK Route","ADC_CLK","ADCCLK"},
+       {"ASI1_BCLK Route","ADC_MOD_CLK","ADC_MOD_CLK"},
+
+       {"ASI2_BCLK Route","DAC_CLK","DACCLK"},
+       {"ASI2_BCLK Route","DAC_MOD_CLK","DAC_MOD_CLK"},
+       {"ASI2_BCLK Route","ADC_CLK","ADCCLK"},
+       {"ASI2_BCLK Route","ADC_MOD_CLK","ADC_MOD_CLK"},
+
+       {"ASI3_BCLK Route","DAC_CLK","DACCLK"},
+       {"ASI3_BCLK Route","DAC_MOD_CLK","DAC_MOD_CLK"},
+       {"ASI3_BCLK Route","ADC_CLK","ADCCLK"},
+       {"ASI3_BCLK Route","ADC_MOD_CLK","ADC_MOD_CLK"},
+
+       {"ASI1_BCLK", NULL, "ASI1_BCLK Route"},
+       {"ASI2_BCLK", NULL, "ASI2_BCLK Route"},
+       {"ASI3_BCLK", NULL, "ASI3_BCLK Route"},
+
+
+       {"ASI1IN", NULL , "PLLCLK"},
+       {"ASI1IN", NULL , "DACCLK"},
+       {"ASI1IN", NULL , "ADCCLK"},
+       {"ASI1IN", NULL , "DAC_MOD_CLK"},
+       {"ASI1IN", NULL , "ADC_MOD_CLK"},
+
+       {"ASI1OUT", NULL , "PLLCLK"},
+       {"ASI1OUT", NULL , "DACCLK"},
+       {"ASI1OUT", NULL , "ADCCLK"},
+       {"ASI1OUT", NULL , "DAC_MOD_CLK"},
+       {"ASI1OUT", NULL , "ADC_MOD_CLK"},
 #ifdef AIC3262_ASI1_MASTER
        {"ASI1IN", NULL , "ASI1_BCLK"},
        {"ASI1OUT", NULL , "ASI1_BCLK"},
@@ -2914,15 +3212,18 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
 #else
 
 #endif
-       {"ASI2IN", NULL , "NDAC"},
-       {"ASI2IN", NULL , "NADC"},
-       {"ASI2IN", NULL , "MDAC"},
-       {"ASI2IN", NULL , "MADC"},
 
-       {"ASI2OUT", NULL , "NDAC"},
-       {"ASI2OUT", NULL , "NADC"},
-       {"ASI2OUT", NULL , "MDAC"},
-       {"ASI2OUT", NULL , "MADC"},
+       {"ASI2IN", NULL , "PLLCLK"},
+       {"ASI2IN", NULL , "DACCLK"},
+       {"ASI2IN", NULL , "ADCCLK"},
+       {"ASI2IN", NULL , "DAC_MOD_CLK"},
+       {"ASI2IN", NULL , "ADC_MOD_CLK"},
+
+       {"ASI2OUT", NULL , "PLLCLK"},
+       {"ASI2OUT", NULL , "DACCLK"},
+       {"ASI2OUT", NULL , "ADCCLK"},
+       {"ASI2OUT", NULL , "DAC_MOD_CLK"},
+       {"ASI2OUT", NULL , "ADC_MOD_CLK"},
 
 #ifdef AIC3262_ASI2_MASTER
        {"ASI2IN", NULL , "ASI2_BCLK"},
@@ -2932,15 +3233,18 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
 #else
 
 #endif
-       {"ASI3IN", NULL , "NDAC"},
-       {"ASI3IN", NULL , "NADC"},
-       {"ASI3IN", NULL , "MDAC"},
-       {"ASI3IN", NULL , "MADC"},
+       {"ASI3IN", NULL , "PLLCLK"},
+       {"ASI3IN", NULL , "DACCLK"},
+       {"ASI3IN", NULL , "ADCCLK"},
+       {"ASI3IN", NULL , "DAC_MOD_CLK"},
+       {"ASI3IN", NULL , "ADC_MOD_CLK"},
 
-       {"ASI3OUT", NULL , "NDAC"},
-       {"ASI3OUT", NULL , "NADC"},
-       {"ASI3OUT", NULL , "MDAC"},
-       {"ASI3OUT", NULL , "MADC"},
+
+       {"ASI3OUT", NULL , "PLLCLK"},
+       {"ASI3OUT", NULL , "DACCLK"},
+       {"ASI3OUT", NULL , "ADCCLK"},
+       {"ASI3OUT", NULL , "DAC_MOD_CLK"},
+       {"ASI3OUT", NULL , "ADC_MOD_CLK"},
 
 #ifdef AIC3262_ASI3_MASTER
        {"ASI3IN", NULL , "ASI3_BCLK"},
@@ -2949,6 +3253,7 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
        {"ASI3OUT", NULL , "ASI3_WCLK"},
 #else
 #endif
+
 /* Playback (DAC) Portion */
        {"HPL Output Mixer","LDAC Switch","Left DAC"},
        {"HPL Output Mixer","MAL Switch","MAL PGA"},
@@ -3055,9 +3360,23 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
        {"DAC MiniDSP IN1 Route","ASI3 In","ASI3IN Port"},
        {"DAC MiniDSP IN1 Route","ADC MiniDSP Out","ADC MiniDSP OUT1"},
 
+       {"DAC MiniDSP IN2 Route","ASI1 In","ASI1IN Port"},
+       {"DAC MiniDSP IN2 Route","ASI2 In","ASI2IN Port"},
+       {"DAC MiniDSP IN2 Route","ASI3 In","ASI3IN Port"},
+
+       {"DAC MiniDSP IN3 Route","ASI1 In","ASI1IN Port"},
+       {"DAC MiniDSP IN3 Route","ASI2 In","ASI2IN Port"},
+       {"DAC MiniDSP IN3 Route","ASI3 In","ASI3IN Port"},
+
        {"Left DAC", "NULL", "DAC MiniDSP IN1 Route"},
        {"Right DAC", "NULL", "DAC MiniDSP IN1 Route"},
 
+       {"Left DAC", "NULL","DAC MiniDSP IN2 Route"},
+       {"Right DAC", "NULL","DAC MiniDSP IN2 Route"},
+
+       {"Left DAC", "NULL","DAC MiniDSP IN3 Route"},
+       {"Right DAC", "NULL","DAC MiniDSP IN3 Route"},
+
 
 /* Mixer Amplifier */
 
@@ -3115,6 +3434,10 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
 /* ASI Output Routing */
        {"ADC MiniDSP OUT1", NULL, "Left ADC"},
        {"ADC MiniDSP OUT1", NULL, "Right ADC"},
+       {"ADC MiniDSP OUT2", NULL, "Left ADC"},
+       {"ADC MiniDSP OUT2", NULL, "Right ADC"},
+       {"ADC MiniDSP OUT3", NULL, "Left ADC"},
+       {"ADC MiniDSP OUT3", NULL, "Right ADC"},
 
        {"ASI1OUT Route", "ASI1 Out","ADC MiniDSP OUT1"},// Port 1
        {"ASI1OUT Route", "ASI1In Bypass","ASI1IN Port"},
@@ -3662,9 +3985,7 @@ static irqreturn_t aic3262_jack_handler(int irq, void *data)
        struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
        unsigned int value;
        unsigned int micbits, hsbits = 0;
-
-       //DBG("%s++\n", __func__);
-
+       DBG(KERN_INFO "%s++\n", __func__);
 
        aic3262_change_page(codec, 0);
 
@@ -3672,41 +3993,41 @@ static irqreturn_t aic3262_jack_handler(int irq, void *data)
        value = snd_soc_read(codec, STICKY_FLAG2);
        DBG(KERN_INFO "reg44 0x%x\n", value);
 
+
        value = snd_soc_read(codec, INT_FLAG2);
-       DBG("reg46 0x%x\n", value);
+       DBG(KERN_INFO "reg46 0x%x\n", value);
 
        value = snd_soc_read(codec, DAC_FLAG_R1);
-       DBG("reg37 0x%x\n", value);
+       DBG(KERN_INFO "reg37 0x%x\n", value);
 
        micbits = value & DAC_FLAG_MIC_MASKBITS;
-       DBG("micbits 0x%x\n", micbits);
+       DBG(KERN_INFO "micbits 0x%x\n", micbits);
 
        hsbits = value & DAC_FLAG_HS_MASKBITS;
-       DBG("hsbits 0x%x\n", hsbits);
+       DBG(KERN_INFO "hsbits 0x%x\n", hsbits);
 
 
        /* No Headphone or Headset*/
        if (!micbits && !hsbits) {
-               DBG("no headset/headphone\n");
+               DBG(KERN_INFO "no headset/headphone\n");
                snd_soc_jack_report(aic3262->headset_jack,
                                0, SND_JACK_HEADSET);
        }
 
        /* Headphone Detected */
        if ((micbits == DAC_FLAG_R1_NOMIC) || (hsbits)) {
-               DBG("headphone\n");
+               DBG(KERN_INFO "headphone\n");
                snd_soc_jack_report(aic3262->headset_jack,
                                SND_JACK_HEADPHONE, SND_JACK_HEADSET);
        }
 
        /* Headset Detected - only with capless */
        if (micbits == DAC_FLAG_R1_MIC) {
-               DBG("headset\n");
+               DBG(KERN_INFO "headset\n");
                snd_soc_jack_report(aic3262->headset_jack,
                                SND_JACK_HEADSET, SND_JACK_HEADSET);
        }
-
-       DBG("%s--\n", __func__);
+       DBG(KERN_INFO "%s--\n", __func__);
        return IRQ_HANDLED;
 }
 
@@ -3719,16 +4040,34 @@ int aic326x_headset_detect(struct snd_soc_codec *codec,
        struct snd_soc_jack *jack, int jack_type)
 {
        struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       aic3262->headset_jack = jack;
 
-       /*TODO*/
-       aic3262_jack_handler(aic3262->irq, codec);
+       aic3262->headset_jack = jack;
+       /*Enable the Headset Interrupts*/
+       snd_soc_write(codec, INT1_CNTL, 0x80);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(aic326x_headset_detect);
 
+int aic326x_headset_button_init(struct snd_soc_codec *codec,
+       struct snd_soc_jack *jack, int jack_type)
+{
+       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
 
+       aic3262->button_dev = input_allocate_device();
+       aic3262->button_dev->name = "aic326x_headset_button";
+       aic3262->button_dev->phys = "codec/input0";
+       aic3262->button_dev->dev.parent = snd_card_get_device_link(codec->card->snd_card);
+       input_set_capability(aic3262->button_dev, EV_KEY, KEY_MEDIA);
+
+       if (input_register_device(aic3262->button_dev))
+       {
+          printk( "Unable to register input device headset button");
+       }
+
+       aic3262_jack_handler(aic3262->irq, codec);
+       return 0;
+}
 #ifdef AIC3262_MULTI_I2S
 /*
 * aic3262_asi_default_config
@@ -4143,10 +4482,6 @@ static int __devexit aic3262_spi_remove(struct spi_device *spi)
 
 }
 
-static const struct spi_device_id tlv320aic3262_id[] = {
-       {"aic3262-codec", 0},
-       {}
-};
 static struct spi_driver aic3262_spi_driver = {
        .driver = {
                .name   = "aic3262-codec",
@@ -4155,7 +4490,6 @@ static struct spi_driver aic3262_spi_driver = {
        },
        .probe          = aic3262_spi_probe,
        .remove         = __devexit_p(aic3262_spi_remove),
-       .id_table = tlv320aic3262_id,
 };
 #endif
 static int __init tlv320aic3262_modinit(void)