asoc: codecs: Add TI aic326x driver
Manoj Gangwal [Wed, 22 Aug 2012 09:58:01 +0000 (14:58 +0530)]
Add latest TI aic326x driver.

Bug 1034241

Change-Id: I8457538025b2989c4baa5eaefef48bdd5535def9
Signed-off-by: Manoj Gangwal <mgangwal@nvidia.com>
Reviewed-on: http://git-master/r/125167
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Lokesh Pathak <lpathak@nvidia.com>

12 files changed:
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/aic3262_codec_ops.c [new file with mode: 0644]
sound/soc/codecs/aic3262_codec_ops.h [new file with mode: 0644]
sound/soc/codecs/aic326x_tiload.c
sound/soc/codecs/aic326x_tiload.h
sound/soc/codecs/aic3xxx_cfw.h [new file with mode: 0644]
sound/soc/codecs/aic3xxx_cfw_ops.c [new file with mode: 0644]
sound/soc/codecs/aic3xxx_cfw_ops.h [new file with mode: 0644]
sound/soc/codecs/tlv320aic3262_default_fw.h [new file with mode: 0644]
sound/soc/codecs/tlv320aic326x.c
sound/soc/codecs/tlv320aic326x.h

index 7d5a661..8946925 100644 (file)
@@ -256,6 +256,7 @@ config SND_SOC_TLV320AIC3X
        tristate
 
 config SND_SOC_TLV320AIC326X
+       select AIC3262_CODEC
        tristate "TI AIC326x Codec"
 
 config SND_SOC_TLV320DAC33
index d80b7bb..dc89ee4 100644 (file)
@@ -35,7 +35,8 @@ snd-soc-stac9766-objs := stac9766.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
-snd-soc-tlv320aic326x-objs := tlv320aic326x.o
+snd-soc-tlv320aic326x-objs := tlv320aic326x.o aic3xxx_cfw_ops.o
+snd-soc-tlv320aic326x-objs += aic3262_codec_ops.o aic326x_tiload.o
 snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
 snd-soc-tlv320dac33-objs := tlv320dac33.o
 snd-soc-twl4030-objs := twl4030.o
diff --git a/sound/soc/codecs/aic3262_codec_ops.c b/sound/soc/codecs/aic3262_codec_ops.c
new file mode 100644 (file)
index 0000000..45686c7
--- /dev/null
@@ -0,0 +1,424 @@
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/mfd/tlv320aic3262-core.h>
+#include <linux/mfd/tlv320aic3262-registers.h>
+#include <sound/soc.h>
+#include "aic3xxx_cfw.h"
+#include "aic3xxx_cfw_ops.h"
+#include "tlv320aic326x.h"
+#include "aic3262_codec_ops.h"
+
+int aic3262_ops_reg_read(void *p, unsigned int reg)
+{
+       struct aic3262_priv *ps = p;
+       union cfw_register *c = (union cfw_register *) &reg;
+       union aic326x_reg_union mreg;
+
+       mreg.aic326x_register.offset = c->offset;
+       mreg.aic326x_register.page = c->page;
+       mreg.aic326x_register.book = c->book;
+       mreg.aic326x_register.reserved = 0;
+
+       return aic3262_reg_read(ps->codec->control_data,
+                               mreg.aic326x_register_int);
+
+}
+int aic3262_ops_reg_write(void  *p, unsigned int reg, unsigned char mval)
+{
+       struct aic3262_priv *ps = p;
+       union aic326x_reg_union mreg;
+       union cfw_register *c = (union cfw_register *) &reg;
+
+       mreg.aic326x_register.offset = c->offset;
+       mreg.aic326x_register.page = c->page;
+       mreg.aic326x_register.book = c->book;
+       mreg.aic326x_register.reserved = 0;
+       mval = c->data;
+       DBG("reg_write:page %d book %d offset %d mval : %#x\n",
+               mreg.aic326x_register.page, mreg.aic326x_register.book,
+               mreg.aic326x_register.offset, mval);
+       return aic3262_reg_write(ps->codec->control_data,
+                               mreg.aic326x_register_int, mval);
+}
+
+int aic3262_ops_set_bits(void *p, unsigned int reg,
+                        unsigned char mask, unsigned char val)
+{
+       struct aic3262_priv *ps = p;
+
+       union aic326x_reg_union mreg;
+       union cfw_register *c = (union cfw_register *) &reg;
+       mreg.aic326x_register.offset = c->offset;
+       mreg.aic326x_register.page = c->page;
+       mreg.aic326x_register.book = c->book;
+       mreg.aic326x_register.reserved = 0;
+       DBG("set_bits:page %d book %d offset %d mask %#x val %#x\n",
+           mreg.aic326x_register.page, mreg.aic326x_register.book,
+           mreg.aic326x_register.offset, mask, val);
+
+       return aic3262_set_bits(ps->codec->control_data,
+                               mreg.aic326x_register_int, mask, val);
+
+}
+
+int aic3262_ops_bulk_read(void *p, unsigned int reg, int count, u8 *buf)
+{
+       struct aic3262_priv *ps = p;
+
+       union aic326x_reg_union mreg;
+       union cfw_register *c = (union cfw_register *) &reg;
+       mreg.aic326x_register.offset = c->offset;
+       mreg.aic326x_register.page = c->page;
+       mreg.aic326x_register.book = c->book;
+       mreg.aic326x_register.reserved = 0;
+
+       return aic3262_bulk_read(ps->codec->control_data,
+                                mreg.aic326x_register_int, count, buf);
+}
+
+int aic3262_ops_bulk_write(void *p, unsigned int reg, int count, const u8 *buf)
+{
+       struct aic3262_priv *ps = p;
+       union aic326x_reg_union mreg;
+       union cfw_register *c = (union cfw_register *) &reg;
+
+       mreg.aic326x_register.offset = c->offset;
+       mreg.aic326x_register.page = c->page;
+       mreg.aic326x_register.book = c->book;
+       mreg.aic326x_register.reserved = 0;
+       DBG("bulk_write: ncmd %d page %d book %d offset %d data[0] %d\n",
+           count, mreg.aic326x_register.page, mreg.aic326x_register.book,
+           mreg.aic326x_register.offset, buf[0]);
+
+       return aic3262_bulk_write(ps->codec->control_data,
+                                 mreg.aic326x_register_int, count, buf);
+}
+/*****************************************************************************
+Function Name  : aic3262_ops_dlock_lock
+Argument       : pointer argument to the codec
+Return value   : Integer
+Purpose                : To Read the run state of the DAC and ADC
+by reading the codec and returning the run state
+
+Run state Bit format
+
+------------------------------------------------------
+D31|..........| D7 | D6|  D5  |  D4  | D3 | D2 | D1  |   D0  |
+R               R    R   LADC   RADC    R    R   LDAC   RDAC
+------------------------------------------------------
+
+*******************************************************************************/
+
+int aic3262_ops_lock(void *pv)
+{
+       int run_state = 0;
+       struct aic3262_priv *aic3262 = (struct aic3262_priv *)pv;
+       mutex_lock(&aic3262->codec->mutex);
+
+       /* Reading the run state of adc and dac */
+       run_state = get_runstate(aic3262->codec->control_data);
+
+       return run_state;
+}
+/*******************************************************************************
+Function name  : aic3262_ops_dlock_unlock
+Argument       : pointer argument to the codec
+Return Value   : integer returning 0
+Purpose                : To unlock the mutex acqiured for reading
+run state of the codec
+ ******************************************************************************/
+int aic3262_ops_unlock(void *pv)
+{
+       /*Releasing the lock of mutex */
+       struct aic3262_priv *aic3262 = (struct aic3262_priv *)pv;
+
+       mutex_unlock(&aic3262->codec->mutex);
+       return 0;
+}
+/*******************************************************************************
+Function Name  : aic3262_ops_dlock_stop
+Argument       : pointer Argument to the codec
+mask tells us the bit format of the
+codec running state
+
+Bit Format:
+------------------------------------------------------
+D31|..........| D7 | D6| D5 | D4 | D3 | D2 | D1 | D0 |
+R               R    R   AL   AR    R    R   DL   DR
+------------------------------------------------------
+R  - Reserved
+A  - minidsp_A
+D  - minidsp_D
+ ******************************************************************************/
+int aic3262_ops_stop(void *pv, int mask)
+{
+       int run_state = 0;
+       int limask = 0;
+       struct aic3262_priv *aic3262 = (struct aic3262_priv *)pv;
+       int ret_wbits = 0;
+
+       mutex_lock(&aic3262->codec->mutex);
+       run_state = get_runstate(aic3262->codec->control_data);
+
+       limask = mask & AIC3XX_COPS_MDSP_A;
+       if (limask != 0)
+               aic3262_set_bits(aic3262->codec->control_data,
+                                AIC3262_ADC_DATAPATH_SETUP, 0xC0, 0);
+
+       limask = mask & AIC3XX_COPS_MDSP_D;
+       if (limask != 0)
+               aic3262_set_bits(aic3262->codec->control_data,
+                                AIC3262_DAC_DATAPATH_SETUP, 0xC0, 0);
+
+       limask = mask & AIC3XX_COPS_MDSP_A;
+       if (limask != 0) {
+               ret_wbits =
+                   aic3262_wait_bits(aic3262->codec->control_data,
+                                     AIC3262_ADC_FLAG, AIC3262_ADC_POWER_MASK,
+                                     0, TIME_DELAY, DELAY_COUNTER);
+               if (!ret_wbits)
+                       dev_err(aic3262->codec->dev,
+                               "at line %d function %s, ADC powerdown"
+                               "wait_bits timedout\n",
+                               __LINE__, __func__);
+       }
+
+       limask = mask & AIC3XX_COPS_MDSP_D;
+       if (limask != 0) {
+               ret_wbits =
+                   aic3262_wait_bits(aic3262->codec->control_data,
+                                     AIC3262_DAC_FLAG, AIC3262_DAC_POWER_MASK,
+                                     0, TIME_DELAY, DELAY_COUNTER);
+               if (!ret_wbits)
+                       dev_err(aic3262->codec->dev,
+                               "at line %d function %s, DAC powerdown"
+                               "wait_bits timedout\n",
+                               __LINE__, __func__);
+       }
+
+       return run_state;
+
+}
+/****************************************************************************
+Function name  : aic3262_ops_dlock_restore
+Argument       : pointer argument to the codec,run_state
+Return Value   : integer returning 0
+Purpose                : To unlock the mutex acqiured for reading
+run state of the codec and to restore the states of the dsp
+******************************************************************************/
+int aic3262_ops_restore(void *pv, int run_state)
+{
+       int sync_state;
+       struct aic3262_priv *aic3262 = (struct aic3262_priv *)pv;
+
+       /*      This is for read the sync mode register state  */
+       sync_state = SYNC_STATE(aic3262);
+
+       /*checking whether the sync mode has been set or
+          not and checking the current state */
+       if (((run_state & 0x30) && (run_state & 0x03)) && (sync_state & 0x80))
+               aic3262_restart_dsps_sync(pv, run_state);
+       else
+               aic3262_dsp_pwrup(pv, run_state);
+
+       mutex_unlock(&aic3262->codec->mutex);
+
+       return 0;
+}
+
+/*****************************************************************************
+Function name  : aic3262_ops_adaptivebuffer_swap
+Argument       : pointer argument to the codec,mask tells us which dsp has to
+be chosen for swapping
+Return Value   : integer returning 0
+Purpose                : To swap the coefficient buffers of minidsp according to mask
+******************************************************************************/
+
+int aic3262_ops_adaptivebuffer_swap(void *pv, int mask)
+{
+       struct aic3262_priv *aic3262 = (struct aic3262_priv *)pv;
+       int ret_wbits = 0;
+
+       if (mask & AIC3XX_ABUF_MDSP_A) {
+               aic3262_set_bits(aic3262->codec->control_data,
+                                AIC3262_ADC_ADAPTIVE_CRAM_REG, 0x1, 0x1);
+               ret_wbits =
+                   aic3262_wait_bits(aic3262->codec->control_data,
+                                     AIC3262_ADC_ADAPTIVE_CRAM_REG, 0x1, 0, 15,
+                                     1);
+               if (!ret_wbits)
+                       dev_err(aic3262->codec->dev,
+                               "at line %d function %s, miniDSP_A buffer swap failed\n",
+                               __LINE__, __func__);
+       }
+
+       if (mask & AIC3XX_ABUF_MDSP_D1) {
+               aic3262_set_bits(aic3262->codec->control_data,
+                                AIC3262_DAC_ADAPTIVE_BANK1_REG, 0x1, 0x1);
+               ret_wbits =
+                   aic3262_wait_bits(aic3262->codec->control_data,
+                                     AIC3262_DAC_ADAPTIVE_BANK1_REG, 0x1, 0,
+                                     15, 1);
+               if (!ret_wbits)
+                       dev_err(aic3262->codec->dev,
+                               "at line %d function %s, miniDSP_D buffer1 swap failed\n",
+                               __LINE__, __func__);
+       }
+
+       if (mask & AIC3XX_ABUF_MDSP_D2) {
+               aic3262_set_bits(aic3262->codec->control_data,
+                                AIC3262_DAC_ADAPTIVE_BANK2_REG, 0x1, 0x1);
+               ret_wbits =
+                   aic3262_wait_bits(aic3262->codec->control_data,
+                                     AIC3262_DAC_ADAPTIVE_BANK2_REG, 0x1, 0,
+                                     15, 1);
+               if (!ret_wbits)
+                       dev_err(aic3262->codec->dev,
+                               "at line %d function %s, miniDSP_D buffer2 swap failed\n",
+                               __LINE__, __func__);
+       }
+
+       return 0;
+}
+
+/*****************************************************************************
+Function name  : get_runstate
+Argument       : pointer argument to the codec
+Return Value   : integer returning the runstate
+Purpose                : To read the current state of the dac's and adc's
+******************************************************************************/
+
+int get_runstate(void *ps)
+{
+       struct aic3262 *pr = ps;
+       int run_state = 0;
+       int DAC_state = 0, ADC_state = 0;
+       /* Read the run state */
+       DAC_state = aic3262_reg_read(pr, AIC3262_DAC_FLAG);
+       ADC_state = aic3262_reg_read(pr, AIC3262_ADC_FLAG);
+
+       DSP_STATUS(run_state, ADC_state, 6, 5);
+       DSP_STATUS(run_state, ADC_state, 2, 4);
+       DSP_STATUS(run_state, DAC_state, 7, 1);
+       DSP_STATUS(run_state, DAC_state, 3, 0);
+
+       return run_state;
+
+}
+/****************************************************************************
+Function name  : aic3262_dsp_pwrdwn_status
+Argument       : pointer argument to the codec , cur_state of dac's and adc's
+Return Value   : integer returning 0
+Purpose                : To read the status of dsp's
+******************************************************************************/
+
+int aic3262_dsp_pwrdwn_status(void *pv)
+{
+       struct aic3262_priv *aic3262 = pv;
+       int ret_wbits = 0;
+
+       aic3262_set_bits(aic3262->codec->control_data,
+                        AIC3262_ADC_DATAPATH_SETUP, 0XC0, 0);
+       aic3262_set_bits(aic3262->codec->control_data,
+                        AIC3262_DAC_DATAPATH_SETUP, 0XC0, 0);
+
+       ret_wbits =
+           aic3262_wait_bits(aic3262->codec->control_data, AIC3262_ADC_FLAG,
+                             AIC3262_ADC_POWER_MASK, 0, TIME_DELAY,
+                             DELAY_COUNTER);
+       if (!ret_wbits)
+               dev_err(aic3262->codec->dev, "ADC Power down timedout\n");
+
+       aic3262_wait_bits(aic3262->codec->control_data, AIC3262_DAC_FLAG,
+                         AIC3262_DAC_POWER_MASK, 0, TIME_DELAY, DELAY_COUNTER);
+       if (!ret_wbits)
+               dev_err(aic3262->codec->dev, "DAC Power down timedout\n");
+
+       return 0;
+}
+
+int aic3262_dsp_pwrup(void *pv, int state)
+{
+       struct aic3262_priv *aic3262 = (struct aic3262_priv *)pv;
+       int adc_reg_mask = 0;
+       int adc_power_mask = 0;
+       int dac_reg_mask = 0;
+       int dac_power_mask = 0;
+       int ret_wbits;
+
+       if (state & AIC3262_COPS_MDSP_A_L) {
+               adc_reg_mask |= 0x80;
+               adc_power_mask |= AIC3262_LADC_POWER_MASK;
+       }
+       if (state & AIC3262_COPS_MDSP_A_R) {
+               adc_reg_mask |= 0x40;
+               adc_power_mask |= AIC3262_RADC_POWER_MASK;
+       }
+
+       if (state & AIC3262_COPS_MDSP_A)
+               aic3262_set_bits(aic3262->codec->control_data,
+                                AIC3262_ADC_DATAPATH_SETUP, 0XC0,
+                                adc_reg_mask);
+
+       if (state & AIC3262_COPS_MDSP_D_L) {
+               dac_reg_mask |= 0x80;
+               dac_power_mask |= AIC3262_LDAC_POWER_MASK;
+       }
+       if (state & AIC3262_COPS_MDSP_D_R) {
+               dac_reg_mask |= 0x40;
+               dac_power_mask |= AIC3262_RDAC_POWER_MASK;
+       }
+
+       if (state & AIC3262_COPS_MDSP_D)
+               aic3262_set_bits(aic3262->codec->control_data,
+                                AIC3262_DAC_DATAPATH_SETUP, 0XC0,
+                                dac_reg_mask);
+
+       if (state & AIC3262_COPS_MDSP_A) {
+               ret_wbits =
+                   aic3262_wait_bits(aic3262->codec->control_data,
+                                     AIC3262_ADC_FLAG, AIC3262_ADC_POWER_MASK,
+                                     adc_power_mask, TIME_DELAY,
+                                     DELAY_COUNTER);
+               if (!ret_wbits)
+                       dev_err(aic3262->codec->dev,
+                               "ADC Power down timedout\n");
+       }
+
+       if (state & AIC3262_COPS_MDSP_D) {
+               ret_wbits =
+                   aic3262_wait_bits(aic3262->codec->control_data,
+                                     AIC3262_DAC_FLAG, AIC3262_DAC_POWER_MASK,
+                                     dac_power_mask, TIME_DELAY,
+                                     DELAY_COUNTER);
+               if (!ret_wbits)
+                       dev_err(aic3262->codec->dev,
+                               "ADC Power down timedout\n");
+       }
+
+       return 0;
+}
+
+int aic3262_restart_dsps_sync(void *pv, int run_state)
+{
+
+       aic3262_dsp_pwrdwn_status(pv);
+       aic3262_dsp_pwrup(pv, run_state);
+
+       return 0;
+}
+
+const struct aic3xxx_codec_ops aic3262_cfw_codec_ops = {
+       .reg_read  =    aic3262_ops_reg_read,
+       .reg_write =    aic3262_ops_reg_write,
+       .set_bits  =    aic3262_ops_set_bits,
+       .bulk_read =    aic3262_ops_bulk_read,
+       .bulk_write =   aic3262_ops_bulk_write,
+       .lock      =    aic3262_ops_lock,
+       .unlock    =    aic3262_ops_unlock,
+       .stop      =    aic3262_ops_stop,
+       .restore   =    aic3262_ops_restore,
+       .bswap     =    aic3262_ops_adaptivebuffer_swap,
+};
+
diff --git a/sound/soc/codecs/aic3262_codec_ops.h b/sound/soc/codecs/aic3262_codec_ops.h
new file mode 100644 (file)
index 0000000..bec0dc8
--- /dev/null
@@ -0,0 +1,44 @@
+#define SYNC_STATE(p) aic3262_reg_read(p->codec->control_data, AIC3262_DAC_PRB)
+
+#define DSP_STATUS(rs, adc_dac, rpos, rspos)  (rs |= \
+               (((adc_dac>>rpos) & 1) << rspos))
+
+#define AIC3262_COPS_MDSP_A    0x30
+#define AIC3262_COPS_MDSP_A_L  0x20
+#define AIC3262_COPS_MDSP_A_R  0x10
+
+#define AIC3262_COPS_MDSP_D    0x03
+#define AIC3262_COPS_MDSP_D_L  0x02
+#define AIC3262_COPS_MDSP_D_R  0x01
+
+int get_runstate(void *);
+
+int aic3262_dsp_pwrup(void *, int);
+
+int aic3262_pwr_down(void *, int, int, int, int);
+
+int aic3262_dsp_pwrdwn_status(void *);
+
+int aic3262_ops_reg_read(void *p, unsigned int reg);
+
+int aic3262_ops_reg_write(void *p, unsigned int reg, unsigned char mval);
+
+int aic3262_ops_set_bits(void *p, unsigned int reg, unsigned char mask,
+                        unsigned char val);
+
+int aic3262_ops_bulk_read(void *p, unsigned int reg, int count, u8 *buf);
+
+int aic3262_ops_bulk_write(void *p, unsigned int reg, int count,
+                          const u8 *buf);
+
+int aic3262_ops_lock(void *pv);
+
+int aic3262_ops_unlock(void *pv);
+
+int aic3262_ops_stop(void *pv, int mask);
+
+int aic3262_ops_restore(void *pv, int run_state);
+
+int aic3262_ops_adaptivebuffer_swap(void *pv, int mask);
+
+int aic3262_restart_dsps_sync(void *pv, int run_state);
index 07615dc..781a6cb 100644 (file)
@@ -16,9 +16,9 @@
  *
  * History:
  *
- * Rev 0.1      Tiload support          16-09-2010
+ * Rev 0.1     Tiload support          TI      16-09-2010
  *
- *          The Tiload programming support is added to AIC3262.
+ * The Tiload programming support is added to AIC3262.
  *
  */
 
 #include <linux/platform_device.h>
 #include <sound/soc.h>
 #include <sound/control.h>
+#include <linux/switch.h>
+#include <sound/jack.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
 
+#include <linux/mfd/tlv320aic3262-core.h>
 #include "tlv320aic326x.h"
 #include "aic326x_tiload.h"
 
 /* enable debug prints in the driver */
-#define DEBUG
-//#undef DEBUG
+/*#define DEBUG */
+#undef DEBUG
 
 #ifdef DEBUG
-#define dprintk(x...)  printk(x)
+#define dprintk(x...)  printk(x)
 #else
 #define dprintk(x...)
 #endif
 static void aic3262_dump_page(struct i2c_client *i2c, u8 page);
 #endif
 
-/* externs */
-extern int aic3262_change_page(struct snd_soc_codec *codec, u8 new_page);
-extern int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book);
-extern int aic3262_write(struct snd_soc_codec *codec, unsigned int reg,
-                                               unsigned int value);
-int aic3262_driver_init(struct snd_soc_codec *codec);
 /************** Dynamic aic3262 driver, TI LOAD support  ***************/
 
 static struct cdev *aic3262_cdev;
-static int aic3262_major = 0;  /* Dynamic allocation of Mjr No. */
-static int aic3262_opened = 0; /* Dynamic allocation of Mjr No. */
+static union aic326x_reg_union aic_reg;
+static int aic3262_major;      /* Dynamic allocation of Mjr No. */
+static int aic3262_opened;     /* Dynamic allocation of Mjr No. */
 static struct snd_soc_codec *aic3262_codec;
 struct class *tiload_class;
 static unsigned int magic_num = 0xE0;
@@ -77,10 +77,12 @@ static unsigned int magic_num = 0xE0;
 
 #ifdef REG_DUMP_aic3262
 /*
- *----------------------------------------------------------------------------
- * Function : aic3262_dump_page
- * Purpose  : Read and display one codec register page, for debugging purpose
- *----------------------------------------------------------------------------
+ * aic3262_dump_page: Read and display one codec register page, for
+       debugging purpose
+ * @i2c; i2c_client identifies a single device (i.e. aic3262) connected
+       to an i2c bus.
+ * @page: page number
+ *
  */
 static void aic3262_dump_page(struct i2c_client *i2c, u8 page)
 {
@@ -88,103 +90,99 @@ static void aic3262_dump_page(struct i2c_client *i2c, u8 page)
        u8 data;
        u8 test_page_array[8];
 
-       dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
-       aic3262_change_page(codec, page);
+       dprintk("TiLoad DRIVER : %s\n", __func__);
 
        data = 0x0;
-
        i2c_master_send(i2c, data, 1);
        i2c_master_recv(i2c, test_page_array, 8);
 
-       printk("\n------- aic3262 PAGE %d DUMP --------\n", page);
-       for (i = 0; i < 8; i++) {
-               printk(" [ %d ] = 0x%x\n", i, test_page_array[i]);
-       }
+       dprintk("\n------- aic3262 PAGE %d DUMP --------\n", page);
+       for (i = 0; i < 8; i++)
+               dprintk(" [ %d ] = 0x%x\n", i, test_page_array[i]);
 }
 #endif
 
-/*
- *----------------------------------------------------------------------------
- * Function : tiload_open
+/**
+ * tiload_open: open method for aic3262-tiload programming interface
+ * @in: Pointer to inode
+ * @filp: pointer to file
  *
- * Purpose  : open method for aic3262-tiload programming interface
- *----------------------------------------------------------------------------
+ * Return: Return 0 if success.
  */
 static int tiload_open(struct inode *in, struct file *filp)
 {
-       dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
+       dprintk("TiLoad DRIVER : %s\n", __func__);
        if (aic3262_opened) {
-               printk("%s device is already opened\n", "aic3262");
-               printk("%s: only one instance of driver is allowed\n",
-                      "aic3262");
+               dprintk("%s device is already opened\n", "aic3262");
+               dprintk("%s: only one instance of driver is allowed\n",
+                       "aic3262");
                return -1;
        }
        aic3262_opened++;
        return 0;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : tiload_release
+/**
+ * tiload_release close method for aic3262_tilaod programming interface
+ * @in: Pointer to inode
+ * @filp: pointer to file
  *
- * Purpose  : close method for aic3262_tilaod programming interface
- *----------------------------------------------------------------------------
+ * Return: Return 0 if success.
  */
 static int tiload_release(struct inode *in, struct file *filp)
 {
-       dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
+       dprintk("TiLoad DRIVER : %s\n", __func__);
        aic3262_opened--;
        return 0;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : tiload_read
+/**
+ * tiload_read: read method for mini dsp programming interface
+ * @file: pointer to file
+ * @buf: pointer to user
+ * @count: number of byte to be read
+ * @offset: offset address
  *
- * Purpose  : read method for mini dsp programming interface
- *----------------------------------------------------------------------------
+ * Return: return value read
  */
-static ssize_t tiload_read(struct file *file, char __user * buf,
-                          size_t count, loff_t * offset)
+static ssize_t tiload_read(struct file *file, char __user *buf,
+                          size_t count, loff_t *offset)
 {
-       static char rd_data[8];
+       static char rd_data[128];
        char reg_addr;
        size_t size;
-       #ifdef DEBUG
+#ifdef DEBUG
        int i;
-       #endif
-       struct i2c_client *i2c = aic3262_codec->control_data;
+#endif
+       struct aic3262 *control = aic3262_codec->control_data;
 
-       dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
+       dprintk("TiLoad DRIVER : %s\n", __func__);
        if (count > 128) {
-               printk("Max 128 bytes can be read\n");
+               dprintk("Max 128 bytes can be read\n");
                count = 128;
        }
 
        /* copy register address from user space  */
        size = copy_from_user(&reg_addr, buf, 1);
        if (size != 0) {
-               printk("read: copy_from_user failure\n");
+               dprintk("read: copy_from_user failure\n");
                return -1;
        }
        /* Send the address to device thats is to be read */
 
-       if (i2c_master_send(i2c, &reg_addr, 1) != 1) {
-               dprintk("Can not write register address\n");
-               return -1;
-       }
-       /* read the codec device registers */
-       size = i2c_master_recv(i2c, rd_data, count);
+       aic_reg.aic326x_register.offset = reg_addr;
+       size =
+           aic3262_bulk_read(control, aic_reg.aic326x_register_int, count,
+                               rd_data);
+
 #ifdef DEBUG
-       printk(KERN_ERR "read size = %d, reg_addr= %x , count = %d\n",
-              (int)size, reg_addr, (int)count);
-       for (i = 0; i < (int)size; i++) {
-               printk(KERN_ERR "rd_data[%d]=%x\n", i, rd_data[i]);
-       }
+       pr_err(KERN_ERR "read size = %d, reg_addr= %x , count = %d\n",
+               (int)size, reg_addr, (int)count);
+       for (i = 0; i < (int)size; i++)
+               dprintk("rd_data[%d]=%x\n", i, rd_data[i]);
 #endif
-       if (size != count) {
-               printk("read %d registers from the codec\n", size);
-       }
+       if (size != count)
+               dprintk("read %d registers from the codec\n", size);
 
        if (copy_to_user(buf, rd_data, size) != 0) {
                dprintk("copy_to_user failed\n");
@@ -194,58 +192,71 @@ static ssize_t tiload_read(struct file *file, char __user * buf,
        return size;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : tiload_write
+/**
+ * tiload_write: write method for aic3262_tiload programming interface
+ * @file: pointer to file
+ * @buf: pointer to user
+ * @count: number of byte to be read
+ * @offset: offset address
  *
- * Purpose  : write method for aic3262_tiload programming interface
- *----------------------------------------------------------------------------
+ * Return: return byte written
  */
-static ssize_t tiload_write(struct file *file, const char __user * buf,
-                           size_t count, loff_t * offset)
+static ssize_t tiload_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *offset)
 {
-       static char wr_data[8];
-       u8 pg_no;
-       #ifdef DEBUG
+       static char wr_data[128];
+#ifdef DEBUG
        int i;
-       #endif
-       struct i2c_client *i2c = aic3262_codec->control_data;
-       struct aic3262_priv *aic3262_private = snd_soc_codec_get_drvdata(aic3262_codec);
+#endif
+       struct aic3262 *control = aic3262_codec->control_data;
 
-       dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
+       dprintk("TiLoad DRIVER : %s\n", __func__);
        /* copy buffer from user space  */
        if (copy_from_user(wr_data, buf, count)) {
-               printk("copy_from_user failure\n");
+               dprintk("copy_from_user failure\n");
                return -1;
        }
 #ifdef DEBUG
-       printk(KERN_ERR "write size = %d\n", (int)count);
-       for (i = 0; i < (int)count; i++) {
-               printk(KERN_INFO "\nwr_data[%d]=%x\n", i, wr_data[i]);
-       }
+       dprintk("write size = %d\n", (int)count);
+       for (i = 0; i < (int)count; i++)
+               dprintk("\nwr_data[%d]=%x\n", i, wr_data[i]);
 #endif
        if (wr_data[0] == 0) {
-               aic3262_change_page(aic3262_codec, wr_data[1]);
+               /*change of page seen, but will only be registered */
+               aic_reg.aic326x_register.page = wr_data[1];
+               return count;
+
+       } else
+           if (wr_data[0] == 127) {
+               /* change of book seen, but will not be sent for I2C write */
+               aic_reg.aic326x_register.book = wr_data[1];
                return count;
-       }
-       pg_no = aic3262_private->page_no;
 
-       if ((wr_data[0] == 127) && (pg_no == 0)) {
-               aic3262_change_book(aic3262_codec, wr_data[1]);
+       } else {
+               aic_reg.aic326x_register.offset = wr_data[0];
+               aic3262_bulk_write(control, aic_reg.aic326x_register_int,
+                                  count - 1, &wr_data[1]);
                return count;
        }
-       return i2c_master_send(i2c, wr_data, count);
 }
 
-static long tiload_ioctl(struct file *filp,
-                       unsigned int cmd, unsigned long arg)
+/**
+ * tiload_ioctl: copy data to user and from user
+ * @filp: pointer to file
+ * @cmd: integer of type command
+ * @arg: argument type
+ *
+ * Return: Return 0 on success
+ */
+static long tiload_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        int num = 0;
        void __user *argp = (void __user *)arg;
+
        if (_IOC_TYPE(cmd) != aic3262_IOC_MAGIC)
                return -ENOTTY;
 
-       dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
+       dprintk("TiLoad DRIVER : %s\n", __func__);
        switch (cmd) {
        case aic3262_IOMAGICNUM_GET:
                num = copy_to_user(argp, &magic_num, sizeof(int));
@@ -257,7 +268,7 @@ static long tiload_ioctl(struct file *filp,
        return num;
 }
 
-/*********** File operations structure for aic3262-tiload programming *************/
+/******* File operations structure for aic3262-tiload programming *********/
 static struct file_operations aic3262_fops = {
        .owner = THIS_MODULE,
        .open = tiload_open,
@@ -267,46 +278,48 @@ static struct file_operations aic3262_fops = {
        .unlocked_ioctl = tiload_ioctl,
 };
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_driver_init
+/**
+ * aic3262_driver_init: Register a char driver for dynamic aic3262-tiload programming
+ * @codec: pointer variable to codec having codec information
  *
- * Purpose  : Register a char driver for dynamic aic3262-tiload programming
- *----------------------------------------------------------------------------
+ * Return: Return 0 on seccess
  */
 int aic3262_driver_init(struct snd_soc_codec *codec)
 {
        int result;
 
        dev_t dev = MKDEV(aic3262_major, 0);
-       printk("TiLoad DRIVER : %s\n", __FUNCTION__);
+       dprintk("TiLoad DRIVER : %s\n", __func__);
        aic3262_codec = codec;
 
-       printk("allocating dynamic major number\n");
+       dprintk("allocating dynamic major number\n");
 
        result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
        if (result < 0) {
-               printk("cannot allocate major number %d\n", aic3262_major);
+               dprintk("cannot allocate major number %d\n", aic3262_major);
                return result;
        }
+
        tiload_class = class_create(THIS_MODULE, DEVICE_NAME);
        aic3262_major = MAJOR(dev);
-       printk("allocated Major Number: %d\n", aic3262_major);
+       dprintk("allocated Major Number: %d\n", aic3262_major);
 
        aic3262_cdev = cdev_alloc();
        cdev_init(aic3262_cdev, &aic3262_fops);
        aic3262_cdev->owner = THIS_MODULE;
        aic3262_cdev->ops = &aic3262_fops;
 
+       aic_reg.aic326x_register.page = 0;
+       aic_reg.aic326x_register.book = 0;
+
        if (cdev_add(aic3262_cdev, dev, 1) < 0) {
-               dprintk("aic3262_driver: cdev_add failed \n");
+               dprintk("aic3262_driver: cdev_add failed\n");
                unregister_chrdev_region(dev, 1);
                aic3262_cdev = NULL;
                return 1;
        }
-       printk("Registered aic3262 TiLoad driver, Major number: %d \n",
-              aic3262_major);
-       //class_device_create(tiload_class, NULL, dev, NULL, DEVICE_NAME, 0);
+       dprintk("Registered aic3262 TiLoad driver, Major number: %d\n",
+               aic3262_major);
        return 0;
 }
 
index 6621a41..c11d8a2 100644 (file)
@@ -2,7 +2,7 @@
  * linux/sound/soc/codecs/aic3262_tiload.h
  *
  *
- * Copyright (C) 2012 Texas Instruments, Inc.
+ * Copyright (C) 2011 Texas Instruments Inc.
  *
  *
  *
@@ -24,9 +24,6 @@
 #ifndef _AIC3262_TILOAD_H
 #define _AIC3262_TILOAD_H
 
-/* typedefs required for the included header files */
-typedef char *string;
-
 /* defines */
 #define DEVICE_NAME            "tiload_node"
 #define aic3262_IOC_MAGIC      0xE0
diff --git a/sound/soc/codecs/aic3xxx_cfw.h b/sound/soc/codecs/aic3xxx_cfw.h
new file mode 100644 (file)
index 0000000..12bc855
--- /dev/null
@@ -0,0 +1,427 @@
+/**
+ * \file Codec Firmware Declarations
+ */
+
+#ifndef CFW_FIRMWARE_H_
+#define CFW_FIRMWARE_H_
+/** \defgroup bt Basic Types */
+/* @{ */
+#ifndef AIC3XXX_CFW_HOST_BLD
+#include <asm-generic/int-ll64.h>
+#else
+typedef unsigned char u8;
+typedef unsigned short int u16;
+typedef unsigned long  int u32;
+#endif
+
+#define CFW_FW_MAGIC 0xC0D1F1ED
+
+/** defgroup pd Arbitrary Limitations */
+
+#ifndef CFW_MAX_ID
+#define CFW_MAX_ID       (64)    /* Max length of string identifies */
+#endif
+
+#ifndef CFW_MAX_DESC
+#define  CFW_MAX_DESC  (512)   /* Max length of description */
+#endif
+/* <Max number of overlays per PFW */
+#ifndef CFW_MAX_NOVLY
+#define CFW_MAX_NOVLY          (4)
+#endif
+
+#ifndef CFW_MAX_NCFG
+#define CFW_MAX_NCFG   (16)    /* Max number of configurations per PFW */
+#endif
+
+#ifndef CFW_MAX_TRANSITIONS
+#define CFW_MAX_TRANSITIONS (32)    /* max number of pre-defined transition */
+#endif
+
+#ifndef CFW_MAX_NPFW
+#define CFW_MAX_NPFW   (16)    /* Max number fo process flows */
+#endif
+
+#ifndef CFW_MAX_MODES
+#define CFW_MAX_MODES       (32)    /* Max number of modes */
+#endif
+
+#ifndef CFW_MAX_ASI
+#define CFW_MAX_ASI     (4)     /* Max number ASIs in a single device */
+#endif
+
+
+#ifndef CFW_MAX_CTRL
+#define CFW_MAX_CTRL   (16)    /* Max number of control per pfw */
+#endif
+
+/** defgroup st Enums, Flags, Macros and Supporting Types */
+
+/**
+ * Sample rate bitmask
+ *
+ */
+enum cfw_fs {
+       CFW_FS_8KHZ     = 0x0001u,
+       CFW_FS_11KHZ    = 0x0002u,
+       CFW_FS_16KHZ    = 0x0004u,
+       CFW_FS_22KHZ    = 0x0008u,
+       CFW_FS_24KHZ    = 0x0010u,
+       CFW_FS_32KHZ    = 0x0020u,
+       CFW_FS_44KHZ    = 0x0040u,
+       CFW_FS_48KHZ    = 0x0080u,
+       CFW_FS_88KHZ    = 0x0100u,
+       CFW_FS_96KHZ    = 0x0200u,
+       CFW_FS_176KHZ   = 0x0400u,
+       CFW_FS_192KHZ   = 0x0800u,
+       CFW_FS_ANY      = 0x8000u,
+       CFW_FS_ALL      = 0x0FFFu,
+};
+
+/**
+ * Sample rate index
+ *
+ */
+enum cfw_fsi {
+       CFW_FSI_8KHZ,
+       CFW_FSI_11KHZ,
+       CFW_FSI_16KHZ,
+       CFW_FSI_22KHZ,
+       CFW_FSI_24KHZ,
+       CFW_FSI_32KHZ,
+       CFW_FSI_44KHZ,
+       CFW_FSI_48KHZ,
+       CFW_FSI_88KHZ,
+       CFW_FSI_96KHZ,
+       CFW_FSI_176KHZ,
+       CFW_FSI_192KHZ,
+       CFW_FSI_ANY = 15,
+};
+
+/**
+ * Device Family Identifier
+ *
+ */
+enum __attribute__ ((__packed__)) cfw_dfamily {
+       CFW_DFM_TYPE_A,
+       CFW_DFM_TYPE_B,
+       CFW_DFM_TYPE_C
+};
+
+/**
+ * Device Identifier
+ *
+ */
+enum __attribute__ ((__packed__)) cfw_device {
+       CFW_DEV_DAC3120,
+       CFW_DEV_DAC3100,
+
+       CFW_DEV_AIC3120,
+       CFW_DEV_AIC3100,
+       CFW_DEV_AIC3110,
+       CFW_DEV_AIC3111,
+
+       CFW_DEV_AIC36,
+
+       CFW_DEV_AIC3206,
+       CFW_DEV_AIC3204,
+       CFW_DEV_AIC3254,
+       CFW_DEV_AIC3256,
+       CFW_DEV_AIC3253,
+
+       CFW_DEV_AIC3212,
+       CFW_DEV_AIC3262,
+       CFW_DEV_AIC3017,
+       CFW_DEV_AIC3008,
+
+};
+
+/**
+ * Transition Sequence Identifier
+ *
+ */
+enum cfw_transition_t {
+       CFW_TRN_INIT,
+       CFW_TRN_RESUME,
+       CFW_TRN_NEUTRAL,
+       CFW_TRN_A_MUTE,
+       CFW_TRN_D_MUTE,
+       CFW_TRN_AD_MUTE,
+       CFW_TRN_A_UNMUTE,
+       CFW_TRN_D_UNMUTE,
+       CFW_TRN_AD_UNMUTE,
+       CFW_TRN_SUSPEND,
+       CFW_TRN_EXIT,
+       CFW_TRN_N
+};
+
+static const char * const cfw_transition_id[] = {
+       [CFW_TRN_INIT] "INIT",
+       [CFW_TRN_RESUME] "RESUME",
+       [CFW_TRN_NEUTRAL] "NEUTRAL",
+       [CFW_TRN_A_MUTE] "A_MUTE",
+       [CFW_TRN_D_MUTE] "D_MUTE",
+       [CFW_TRN_AD_MUTE] "AD_MUTE",
+       [CFW_TRN_A_UNMUTE] "A_UNMUTE",
+       [CFW_TRN_D_UNMUTE] "D_UNMUTE",
+       [CFW_TRN_AD_UNMUTE] "AD_UNMUTE",
+       [CFW_TRN_SUSPEND] "SUSPEND",
+       [CFW_TRN_EXIT] "EXIT",
+};
+
+/** defgroup ds Data Structures */
+
+/**
+* CFW Meta Command
+* These commands do not appear in the register
+* set of the device.
+* Mainly delay, wait and set_bits.
+*/
+enum __attribute__ ((__packed__)) cfw_meta_cmd {
+       CFW_META_DELAY = 0x80,
+       CFW_META_UPDTBITS,
+       CFW_META_WAITBITS,
+       CFW_META_LOCK,
+};
+
+/**
+* CFW Delay
+* Used for the meta command delay
+* Has one parameter of delay time in ms
+*/
+struct cfw_meta_delay {
+       u16 delay;
+       enum cfw_meta_cmd mcmd;
+       u8      unused1;
+};
+
+/**
+* CFW set_bits or wait
+* Both these meta commands have same arguments
+* mcmd will be used to specify which command it is
+* has parameters of book, page, offset and mask
+*/
+struct cfw_meta_bitop {
+       u16 unused1;
+       enum cfw_meta_cmd mcmd;
+       u8   mask;
+};
+
+/**
+* CFW meta register
+* Contains the data structures for the meta commands
+*/
+union cfw_meta_register {
+       struct {
+               u16 unused1;
+               enum cfw_meta_cmd mcmd;
+               u8 unused2;
+       };
+       struct cfw_meta_delay delay;
+       struct cfw_meta_bitop bitop;
+};
+
+/**
+ * CFW Register
+ *
+ * A single reg write
+ *
+ */
+union cfw_register {
+       struct {
+               u8 book;
+               u8 page;
+               u8 offset;
+               u8 data;
+       };
+       u32 bpod;
+       union cfw_meta_register meta;
+};
+
+/**
+ * CFW Burst
+ *
+ * A single I2C/SPI burst write sequence
+ *
+ */
+struct cfw_burst {
+       u32 length;
+       union {
+               union cfw_register reg;
+               struct {
+                       u8 bpo[3];
+                       u8 data[1];
+               };
+       };
+};
+
+/**
+ * CFW Command
+ *
+ * Can be a either a
+ *      -# single register write,
+ *      -# a burst write, or
+ *      -# meta-command
+ *
+ */
+union cfw_cmd {
+       union cfw_register reg;
+       struct cfw_burst    *burst;
+};
+
+/**
+ * CFW Block Type
+ *
+ * Block identifier
+ *
+ */
+enum __attribute__ ((__packed__)) cfw_block_t {
+       CFW_BLOCK_SYSTEM_PRE,
+       CFW_BLOCK_A_INST,
+       CFW_BLOCK_A_A_COEF,
+       CFW_BLOCK_A_B_COEF,
+       CFW_BLOCK_A_F_COEF,
+       CFW_BLOCK_D_INST,
+       CFW_BLOCK_D_A1_COEF,
+       CFW_BLOCK_D_B1_COEF,
+       CFW_BLOCK_D_A2_COEF,
+       CFW_BLOCK_D_B2_COEF,
+       CFW_BLOCK_D_F_COEF,
+       CFW_BLOCK_SYSTEM_POST,
+       CFW_BLOCK_N,
+       CFW_BLOCK_INVALID,
+       CFW_BLOCK_BURSTS = 0x80
+};
+#define CFW_BLOCK_BURSTS(x) ((x)&CFW_BLOCK_BURSTS)
+#define CFW_BLOCK_TYPE(x) ((x)&(~CFW_BLOCK_BURSTS))
+#define CFW_BLOCK_D_A_COEF CFW_BLOCK_D_A1_COEF
+#define CFW_BLOCK_D_B_COEF CFW_BLOCK_D_B1_COEF
+
+/**
+ * CFW Block
+ *
+ * A block of logically grouped sequences/commands/meta-commands
+ *
+ */
+struct cfw_block {
+       enum cfw_block_t type;
+       int ncmds;
+       union cfw_cmd cmd[];
+};
+
+/**
+ * CFW Image
+ *
+ * A downloadable image
+ */
+struct cfw_image {
+       char name[CFW_MAX_ID];  /* Name of the pfw/overlay/configuration */
+       char desc[CFW_MAX_DESC];        /* User string */
+       int  mute_flags;
+       struct cfw_block *block[CFW_BLOCK_N];
+};
+
+struct cfw_control {
+       char name[CFW_MAX_ID];  /* Control identifier */
+       char desc[CFW_MAX_DESC];/* User string */
+       int  mute_flags;
+
+       int  min;              /* Min value of control (*100) */
+       int  max;              /* Max  value of control (*100) */
+       int  step;            /* Control step size (*100) */
+
+       int  imax;            /* Max index into controls array */
+       int  ireset;        /* Reset control to defaults */
+       int  icur;            /* Last value set */
+       struct cfw_block **output;     /* Array of sequences to send */
+};
+
+/**
+ * Process flow
+ *
+ * Complete description of a process flow
+ */
+struct cfw_pfw {
+       char name[CFW_MAX_ID];  /* Name of the process flow */
+       char desc[CFW_MAX_DESC];    /* User string */
+       u32 version;
+       u8  prb_a;
+       u8  prb_d;
+       int novly;            /* Number of overlays (1 or more) */
+       int ncfg;              /* Number of configurations (0 or more) */
+       int nctrl;            /* Number of run-time controls */
+       struct cfw_block *pll;
+       struct cfw_image *base; /* Base sequence */
+       /* Overlay and cfg */
+       struct cfw_image *ovly_cfg[CFW_MAX_NOVLY][CFW_MAX_NCFG];
+       /* Array of run-time controls */
+       struct cfw_control *ctrl[CFW_MAX_CTRL];
+};
+
+/**
+ * Process transition
+ *
+ * Sequence for specific state transisitions within the driver
+ *
+ */
+struct cfw_transition {
+       char name[CFW_MAX_ID];          /* Name of the transition */
+       char desc[CFW_MAX_DESC];        /* User string */
+       struct cfw_block *block;
+};
+
+/**
+ * Device audio mode
+ *
+ * Structure linking various operating modes to process flows,
+ * configurations and sequences
+ *
+ */
+struct cfw_mode {
+       char name[CFW_MAX_ID];
+       char desc[CFW_MAX_DESC];    /* User string */
+       u32 flags;
+       u8  pfw;
+       u8  ovly;
+       u8  cfg;
+       struct cfw_block *entry;
+       struct cfw_block *exit;
+};
+
+struct cfw_asoc_toc_entry {
+       char etext[CFW_MAX_ID];
+       int mode;
+       int cfg;
+};
+
+struct cfw_asoc_toc {
+       int nentries;
+       struct cfw_asoc_toc_entry entry[];
+};
+
+/**
+ * CFW Project
+ *
+ * Top level structure describing the CFW project
+ */
+struct cfw_project {
+       u32 magic;
+       u32 bmagic;
+       u32 size;
+       u32 cksum;
+       u32 version;
+       u32 tstamp;
+       char name[CFW_MAX_ID];      /* Project name */
+       char desc[CFW_MAX_DESC];    /* User string */
+       enum cfw_dfamily dfamily;
+       enum cfw_device  device;
+       u32  flags;
+       struct cfw_transition *transition[CFW_MAX_TRANSITIONS];
+       u16  npfw;                 /* Number of process flows */
+       u16  nmode;               /* Number of operating modes */
+       struct cfw_pfw *pfw[CFW_MAX_NPFW]; /* Indices to PFW locations */
+       struct cfw_mode *mode[CFW_MAX_MODES];
+       struct cfw_asoc_toc *asoc_toc;
+};
+
+#endif /* CFW_FIRMWARE_H_ */
diff --git a/sound/soc/codecs/aic3xxx_cfw_ops.c b/sound/soc/codecs/aic3xxx_cfw_ops.c
new file mode 100644 (file)
index 0000000..83bcdf1
--- /dev/null
@@ -0,0 +1,922 @@
+#ifndef AIC3XXX_CFW_HOST_BLD
+#   include <linux/module.h>
+#   include <linux/delay.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <linux/slab.h>
+#include <sound/tlv.h>
+#   define warn(fmt, ...) printk(fmt "\n", ##__VA_ARGS__)
+#   define error(fmt, ...) printk(fmt "\n", ##__VA_ARGS__)
+
+#else
+#   define _GNU_SOURCE
+#   include <stdlib.h>
+#   include "utils.h"
+#   include <string.h>
+#   include <assert.h>
+#   define EINVAL 1
+
+#endif
+
+#include "aic3xxx_cfw.h"
+#include "aic3xxx_cfw_ops.h"
+#ifndef AIC3XXX_CFW_HOST_BLD
+static struct cfw_project *aic3xxx_cfw_unpickle(void *pcfw, int n);
+#endif
+
+
+/*
+ * Firmware version numbers are used to make sure that the
+ * host and target code stay in sync.  It is _not_ recommended
+ * to provide this number from the outside (E.g., from a makefile)
+ * Instead, a set of automated tools are relied upon to keep the numbers
+ * in sync at the time of host testing.
+ */
+#define CFW_FW_VERSION 0x000100B3
+
+static int aic3xxx_cfw_dlimage(struct cfw_state *ps, struct cfw_image *pim);
+static int aic3xxx_cfw_dlcfg(struct cfw_state *ps, struct cfw_image *pim);
+static int aic3xxx_cfw_dlctl(struct cfw_state *ps, struct cfw_block *pb,
+                           u32 mute_flags);
+static void aic3xxx_cfw_dlcmds(struct cfw_state *ps, struct cfw_block *pb);
+static void aic3xxx_wait(struct cfw_state *ps, unsigned int reg, u8 mask,
+                       u8 data);
+static int aic3xxx_cfw_set_mode_id(struct cfw_state *ps);
+static int aic3xxx_cfw_mute(struct cfw_state *ps, int mute, u32 flags);
+static int aic3xxx_cfw_setmode_cfg_u(struct cfw_state *ps, int mode, int cfg);
+static int aic3xxx_cfw_setcfg_u(struct cfw_state *ps, int cfg);
+static int aic3xxx_cfw_transition_u(struct cfw_state *ps, char *ttype);
+static int aic3xxx_cfw_set_pll_u(struct cfw_state *ps, int asi);
+static int aic3xxx_cfw_control_u(struct cfw_state *ps, char *cname, int param);
+
+
+#if defined(AIC3XXX_CFW_HOST_BLD)
+
+static int mutex_init(struct mutex *m)
+{
+       m->lock = 0;
+       return 0;
+}
+
+static int mutex_lock(struct mutex *m)
+{
+       assert(m->lock == 0);
+       m->lock = 1;
+       return 0;
+}
+
+static int mutex_unlock(struct mutex *m)
+{
+       assert(m->lock == 1);
+       m->lock = 0;
+       return 0;
+}
+/*
+static void mdelay(int val)
+{
+       int i;
+       for (i = 0; i < (val * 10); i++);
+}
+*/
+#endif
+
+int aic3xxx_cfw_init(struct cfw_state *ps, struct aic3xxx_codec_ops const *ops,
+                   void *ops_obj)
+{
+       ps->ops = ops;
+       ps->ops_obj = ops_obj;
+       ps->pjt = NULL;
+       mutex_init(&ps->mutex);
+       return 0;
+}
+
+int aic3xxx_cfw_lock(struct cfw_state *ps, int lock)
+{
+       if (lock)
+               mutex_lock(&ps->mutex);
+       else
+               mutex_unlock(&ps->mutex);
+       return 0;
+}
+
+int aic3xxx_cfw_reload(struct cfw_state *ps, void *pcfw, int n)
+{
+       ps->pjt = aic3xxx_cfw_unpickle(pcfw, n);
+       ps->cur_mode_id =
+           ps->cur_mode = ps->cur_pfw = ps->cur_ovly = ps->cur_cfg = -1;
+       if (ps->pjt == NULL)
+               return -1;
+       return 0;
+}
+
+int aic3xxx_cfw_setmode(struct cfw_state *ps, int mode)
+{
+       struct cfw_project *pjt;
+       int ret;
+
+       aic3xxx_cfw_lock(ps, 1);
+       pjt = ps->pjt;
+       if (pjt == NULL) {
+               aic3xxx_cfw_lock(ps, 0);
+               return -1;
+       }
+       ret = aic3xxx_cfw_setmode_cfg_u(ps, mode, pjt->mode[mode]->cfg);
+       aic3xxx_cfw_lock(ps, 0);
+       return ret;
+}
+
+int aic3xxx_cfw_setcfg(struct cfw_state *ps, int cfg)
+{
+       int ret;
+
+       aic3xxx_cfw_lock(ps, 1);
+       ret = aic3xxx_cfw_setcfg_u(ps, cfg);
+       aic3xxx_cfw_lock(ps, 0);
+       return ret;
+}
+
+static int aic3xxx_cfw_setcfg_u(struct cfw_state *ps, int cfg)
+{
+       struct cfw_project *pjt = ps->pjt;
+       struct cfw_pfw *pfw;
+
+       if (pjt == NULL)
+               return -1;
+       if (ps->cur_pfw < 0 || ps->cur_pfw >= pjt->npfw)
+               return -1;
+       if (ps->cur_cfg == cfg)
+               return 0;
+       pfw = pjt->pfw[ps->cur_pfw];
+       if (pfw->ncfg == 0 && cfg != 0)
+               return -1;
+       if (cfg > 0 && cfg >= pfw->ncfg)
+               return -1;
+       ps->cur_cfg = cfg;
+       aic3xxx_cfw_set_mode_id(ps);
+       if (pfw->ncfg != 0)
+               return aic3xxx_cfw_dlcfg(ps,
+                                        pfw->ovly_cfg[ps->cur_ovly][ps->
+                                                                    cur_cfg]);
+       return 0;
+}
+
+int aic3xxx_cfw_setmode_cfg(struct cfw_state *ps, int mode, int cfg)
+{
+       int ret;
+
+       aic3xxx_cfw_lock(ps, 1);
+       ret = aic3xxx_cfw_setmode_cfg_u(ps, mode, cfg);
+       aic3xxx_cfw_lock(ps, 0);
+       return ret;
+}
+
+static int aic3xxx_cfw_setmode_cfg_u(struct cfw_state *ps, int mode, int cfg)
+{
+       struct cfw_project *pjt = ps->pjt;
+       int which = 0;
+       struct cfw_pfw *pfw;
+       struct cfw_image *im;
+
+       if (pjt == NULL)
+               return -1;
+       if ((mode < 0) || (mode >= pjt->nmode))
+               return -1;
+       if (cfg < 0)
+               return -1;
+       if (mode == ps->cur_mode)
+               return aic3xxx_cfw_setcfg_u(ps, cfg);
+
+       /* Apply exit sequence for previous mode if present */
+       if (ps->cur_mode >= 0 && pjt->mode[ps->cur_mode]->exit)
+               aic3xxx_cfw_dlcmds(ps, pjt->mode[ps->cur_mode]->exit);
+
+       if (pjt->mode[mode]->pfw < pjt->npfw) {
+               /* New mode uses miniDSP */
+               pfw = pjt->pfw[pjt->mode[mode]->pfw];
+               /* Make sure cfg is valid and supported in this mode */
+               if (pfw->ncfg == 0 && cfg != 0)
+                       return -1;
+               if (cfg > 0 && cfg >= pfw->ncfg)
+                       return -1;
+               /*
+                * Decisions about which miniDSP to stop/restart are taken
+                * on the basis of sections present in the _base_ image
+                * This allows for correct sync mode operation even in cases
+                * where the base PFW uses both miniDSPs where a particular
+                * overlay applies only to one
+                */
+               im = pfw->base;
+               if (im->block[CFW_BLOCK_A_INST])
+                       which |= AIC3XX_COPS_MDSP_A;
+               if (im->block[CFW_BLOCK_D_INST])
+                       which |= AIC3XX_COPS_MDSP_D;
+
+               /* New mode requires different PFW */
+               if (pjt->mode[mode]->pfw != ps->cur_pfw) {
+                       ps->cur_pfw = pjt->mode[mode]->pfw;
+                       ps->cur_ovly = 0;
+                       ps->cur_cfg = 0;
+
+                       which = ps->ops->stop(ps->ops_obj, which);
+                       aic3xxx_cfw_dlimage(ps, im);
+                       if (pjt->mode[mode]->ovly
+                               && pjt->mode[mode]->ovly < pfw->novly) {
+                               /* New mode uses ovly */
+                               if (pfw->ovly_cfg[pjt->mode[mode]
+                                       ->ovly][cfg] != NULL)
+                                       aic3xxx_cfw_dlimage(ps,
+                                                       pfw->ovly_cfg[pjt->
+                                                       mode[mode]->
+                                                       ovly][cfg]);
+                       } else if (pfw->ncfg > 0) {
+                               /* new mode needs only a cfg change */
+                               aic3xxx_cfw_dlimage(ps, pfw->ovly_cfg[0][cfg]);
+                       }
+                       ps->ops->restore(ps->ops_obj, which);
+
+               } else if (pjt->mode[mode]->ovly != ps->cur_ovly) {
+                       /* New mode requires only an ovly change */
+                       which = ps->ops->stop(ps->ops_obj, which);
+                       aic3xxx_cfw_dlimage(ps,
+                                           pfw->ovly_cfg[pjt->mode[mode]->
+                                                         ovly][cfg]);
+                       ps->ops->restore(ps->ops_obj, which);
+               } else if (pfw->ncfg > 0 && cfg != ps->cur_cfg) {
+                               /* New mode requires only a cfg change */
+                       aic3xxx_cfw_dlcfg(ps,
+                                         pfw->ovly_cfg[pjt->mode[mode]->
+                                                       ovly][cfg]);
+               }
+               ps->cur_ovly = pjt->mode[mode]->ovly;
+               ps->cur_cfg = cfg;
+
+               ps->cur_mode = mode;
+               aic3xxx_cfw_set_pll_u(ps, 0);
+
+       } else if (pjt->mode[mode]->pfw != 0xFF) {
+               warn("Bad pfw setting detected (%d).  Max pfw=%d",
+                    pjt->mode[mode]->pfw, pjt->npfw);
+       }
+       ps->cur_mode = mode;
+       aic3xxx_cfw_set_mode_id(ps);
+       /* Transition to netural mode */
+       aic3xxx_cfw_transition_u(ps, "NEUTRAL");
+       /* Apply entry sequence if present */
+       if (pjt->mode[mode]->entry)
+               aic3xxx_cfw_dlcmds(ps, pjt->mode[mode]->entry);
+       DBG("setmode_cfg: DONE (mode=%d pfw=%d ovly=%d cfg=%d)", ps->cur_mode,
+           ps->cur_pfw, ps->cur_ovly, ps->cur_cfg);
+       return 0;
+}
+
+int aic3xxx_cfw_transition(struct cfw_state *ps, char *ttype)
+{
+       int ret;
+
+       aic3xxx_cfw_lock(ps, 1);
+       ret = aic3xxx_cfw_transition_u(ps, ttype);
+       aic3xxx_cfw_lock(ps, 0);
+       return ret;
+}
+
+static int aic3xxx_cfw_transition_u(struct cfw_state *ps, char *ttype)
+{
+       int i;
+
+       if (ps->pjt == NULL)
+               return -1;
+       for (i = 0; i < CFW_TRN_N; ++i) {
+               if (!strcasecmp(ttype, cfw_transition_id[i])) {
+                       DBG("Sending transition %s[%d]", ttype, i);
+                       if (ps->pjt->transition[i]) {
+                               aic3xxx_cfw_dlcmds(ps,
+                                                  ps->pjt->transition[i]->
+                                                  block);
+                       }
+                       return 0;
+               }
+       }
+       warn("Transition %s not present or invalid", ttype);
+       return 0;
+}
+
+int aic3xxx_cfw_set_pll(struct cfw_state *ps, int asi)
+{
+       int ret;
+
+       aic3xxx_cfw_lock(ps, 1);
+       ret = aic3xxx_cfw_set_pll_u(ps, asi);
+       aic3xxx_cfw_lock(ps, 0);
+       return ret;
+}
+
+static int aic3xxx_cfw_set_pll_u(struct cfw_state *ps, int asi)
+{
+       struct cfw_project *pjt = ps->pjt;
+       struct cfw_pfw *pfw;
+
+       if (pjt == NULL)
+               return -1;
+       if (ps->cur_mode < 0)
+               return -EINVAL;
+       pfw = pjt->pfw[pjt->mode[ps->cur_mode]->pfw];
+       if (pfw->pll) {
+               DBG("Configuring PLL for ASI%d using PFW%d", asi,
+                   pjt->mode[ps->cur_mode]->pfw);
+               aic3xxx_cfw_dlcmds(ps, pfw->pll);
+       }
+       return 0;
+}
+
+int aic3xxx_cfw_control(struct cfw_state *ps, char *cname, int param)
+{
+       int ret;
+
+       aic3xxx_cfw_lock(ps, 1);
+       ret = aic3xxx_cfw_control_u(ps, cname, param);
+       aic3xxx_cfw_lock(ps, 0);
+       return ret;
+}
+
+static int aic3xxx_cfw_control_u(struct cfw_state *ps, char *cname, int param)
+{
+       struct cfw_pfw *pfw;
+       int i;
+
+       if (ps->cur_pfw < 0 || ps->cur_pfw >= ps->pjt->npfw) {
+               warn("Not in MiniDSP mode");
+               return 0;
+       }
+       pfw = ps->pjt->pfw[ps->cur_pfw];
+       for (i = 0; i < pfw->nctrl; ++i) {
+               if (!strcasecmp(cname, pfw->ctrl[i]->name)) {
+                       struct cfw_control *pc = pfw->ctrl[i];
+                       if (param < 0 || param > pc->imax) {
+                               warn("Parameter out of range\n");
+                               return -EINVAL;
+                       }
+                       DBG("Sending control %s[%d]", cname, param);
+                       pc->icur = param;
+                       aic3xxx_cfw_dlctl(ps, pc->output[param],
+                                         pc->mute_flags);
+                       return 0;
+               }
+       }
+       warn("Control named %s nort found in pfw %s", cname, pfw->name);
+
+       return 0;
+}
+
+static void aic3xxx_cfw_dlcmds(struct cfw_state *ps, struct cfw_block *pb)
+{
+       int i = 0, lock = 0;
+
+       while (i < pb->ncmds) {
+               if (CFW_BLOCK_BURSTS(pb->type))
+                       ps->ops->bulk_write(ps->ops_obj,
+                                           pb->cmd[i].burst->reg.bpod,
+                                           pb->cmd[i].burst->length,
+                                           pb->cmd[i].burst->data);
+               else {
+                       struct cfw_meta_delay d = pb->cmd[i].reg.meta.delay;
+                       struct cfw_meta_bitop b = pb->cmd[i].reg.meta.bitop;
+                       switch (pb->cmd[i].reg.meta.mcmd) {
+                       case CFW_META_DELAY:
+                               mdelay(d.delay);
+                               break;
+                       case CFW_META_UPDTBITS:
+                               ps->ops->set_bits(ps->ops_obj,
+                                                 pb->cmd[i + 1].reg.bpod,
+                                                 b.mask,
+                                                 pb->cmd[i + 1].reg.data);
+                               i++;
+                               break;
+                       case CFW_META_WAITBITS:
+                               aic3xxx_wait(ps, pb->cmd[i + 1].reg.bpod,
+                                            b.mask, pb->cmd[i + 1].reg.data);
+                               i++;
+                               break;
+                       case CFW_META_LOCK:
+                               if (d.delay) {
+                                       ps->ops->lock(ps->ops_obj);
+                                       lock = 1;
+                               } else {
+                                       if (!lock)
+                                               error("already lock\n");
+                                       ps->ops->unlock(ps->ops_obj);
+                                       lock = 0;
+                               }
+                               break;
+                       default:
+                               ps->ops->reg_write(ps->ops_obj,
+                                                  pb->cmd[i].reg.bpod,
+                                                  pb->cmd[i].reg.data);
+                       }
+               }
+               ++i;
+       }
+       if (lock)
+               error("exiting blkcmds with lock ON");
+}
+
+static void aic3xxx_wait(struct cfw_state *ps, unsigned int reg, u8 mask,
+                       u8 data)
+{
+       while ((ps->ops->reg_read(ps->ops_obj, reg) & mask) != data)
+               mdelay(2);
+}
+
+static const struct {
+       u32 mdsp;
+       int buf_a, buf_b;
+       u32 swap;
+} csecs[] = {
+       {
+               .mdsp = AIC3XX_COPS_MDSP_A,
+               .swap = AIC3XX_ABUF_MDSP_A,
+               .buf_a = CFW_BLOCK_A_A_COEF,
+               .buf_b = CFW_BLOCK_A_B_COEF
+       },
+       {
+               .mdsp = AIC3XX_COPS_MDSP_D,
+               .swap = AIC3XX_ABUF_MDSP_D1,
+               .buf_a = CFW_BLOCK_D_A1_COEF,
+               .buf_b = CFW_BLOCK_D_B1_COEF
+       },
+       {
+               .mdsp = AIC3XX_COPS_MDSP_D,
+               .swap = AIC3XX_ABUF_MDSP_D2,
+               .buf_a = CFW_BLOCK_D_A2_COEF,
+               .buf_b = CFW_BLOCK_D_B2_COEF
+       },
+};
+
+static int aic3xxx_cfw_dlctl(struct cfw_state *ps, struct cfw_block *pb,
+                               u32 mute_flags)
+{
+       int i, btype = CFW_BLOCK_TYPE(pb->type);
+       int run_state = ps->ops->lock(ps->ops_obj);
+
+       DBG("Download CTL");
+       for (i = 0; i < sizeof(csecs) / sizeof(csecs[0]); ++i) {
+               if (csecs[i].buf_a == btype || csecs[i].buf_b == btype) {
+                       DBG("\tDownload once to %d", btype);
+                       aic3xxx_cfw_dlcmds(ps, pb);
+                       if (run_state & csecs[i].mdsp) {
+                               DBG("Download again %d", btype);
+                               aic3xxx_cfw_mute(ps, 1, run_state & mute_flags);
+                               ps->ops->bswap(ps->ops_obj, csecs[i].swap);
+                               aic3xxx_cfw_mute(ps, 0, run_state & mute_flags);
+                               aic3xxx_cfw_dlcmds(ps, pb);
+                       }
+                       break;
+               }
+       }
+       ps->ops->unlock(ps->ops_obj);
+       return 0;
+}
+
+static int aic3xxx_cfw_dlcfg(struct cfw_state *ps, struct cfw_image *pim)
+{
+       int i, run_state, swap;
+
+       DBG("Download CFG %s", pim->name);
+       run_state = ps->ops->lock(ps->ops_obj);
+       swap = 0;
+       for (i = 0; i < sizeof(csecs) / sizeof(csecs[0]); ++i) {
+               if (pim->block[csecs[i].buf_a]) {
+                       if (run_state & csecs[i].mdsp) {
+                               aic3xxx_cfw_dlcmds(ps,
+                                                  pim->block[csecs[i].buf_a]);
+                               swap |= csecs[i].swap;
+                       } else {
+                               aic3xxx_cfw_dlcmds(ps,
+                                                  pim->block[csecs[i].buf_a]);
+                               aic3xxx_cfw_dlcmds(ps,
+                                                  pim->block[csecs[i].buf_b]);
+                       }
+               }
+       }
+       if (swap) {
+               aic3xxx_cfw_mute(ps, 1, run_state & pim->mute_flags);
+               ps->ops->bswap(ps->ops_obj, swap);
+               aic3xxx_cfw_mute(ps, 0, run_state & pim->mute_flags);
+               for (i = 0; i < sizeof(csecs) / sizeof(csecs[0]); ++i) {
+                       if (pim->block[csecs[i].buf_a]) {
+                               if (run_state & csecs[i].mdsp)
+                                       aic3xxx_cfw_dlcmds(ps,
+                                                       pim->block[csecs[i].
+                                                       buf_a]);
+                       }
+               }
+       }
+       ps->ops->unlock(ps->ops_obj);
+       return 0;
+}
+
+static int aic3xxx_cfw_dlimage(struct cfw_state *ps, struct cfw_image *pim)
+{
+       int i;
+
+       DBG("Download IMAGE %s", pim->name);
+       for (i = 0; i < CFW_BLOCK_N; ++i)
+               if (pim->block[i])
+                       aic3xxx_cfw_dlcmds(ps, pim->block[i]);
+       return 0;
+}
+
+static int aic3xxx_cfw_mute(struct cfw_state *ps, int mute, u32 flags)
+{
+       if ((flags & AIC3XX_COPS_MDSP_D) && (flags & AIC3XX_COPS_MDSP_A))
+               aic3xxx_cfw_transition_u(ps, mute ? "AD_MUTE" : "AD_UNMUTE");
+       else if (flags & AIC3XX_COPS_MDSP_D)
+               aic3xxx_cfw_transition_u(ps, mute ? "D_MUTE" : "D_UNMUTE");
+       else if (flags & AIC3XX_COPS_MDSP_A)
+               aic3xxx_cfw_transition_u(ps, mute ? "A_MUTE" : "A_UNMUTE");
+       return 0;
+}
+
+#define FW_NDX2PTR(x, b) do {                        \
+x = (void *)((u8 *)(b) + ((int)(x)));           \
+} while (0)
+
+static void aic3xxx_cfw_unpickle_block(struct cfw_block *pb, void *p)
+{
+       int i;
+
+       if (CFW_BLOCK_BURSTS(pb->type))
+               for (i = 0; i < pb->ncmds; ++i)
+                       FW_NDX2PTR(pb->cmd[i].burst, p);
+}
+
+static void aic3xxx_cfw_unpickle_image(struct cfw_image *im, void *p)
+{
+       int i;
+       for (i = 0; i < CFW_BLOCK_N; ++i)
+               if (im->block[i]) {
+                       FW_NDX2PTR(im->block[i], p);
+                       aic3xxx_cfw_unpickle_block(im->block[i], p);
+               }
+}
+
+static void aic3xxx_cfw_unpickle_control(struct cfw_control *ct, void *p)
+{
+       int i;
+       FW_NDX2PTR(ct->output, p);
+       for (i = 0; i <= ct->imax; ++i) {
+               FW_NDX2PTR(ct->output[i], p);
+               aic3xxx_cfw_unpickle_block(ct->output[i], p);
+       }
+}
+#ifndef AIC3XXX_CFW_HOST_BLD
+static
+#endif
+unsigned int crc32(unsigned int *pdata, int n)
+{
+       u32 crc = 0, i, crc_poly = 0x04C11DB7;  /* CRC - 32 */
+       u32 msb;
+       u32 residue_value;
+       int bits;
+
+       for (i = 0; i < (n >> 2); i++) {
+               bits = 32;
+               while (--bits >= 0) {
+                       msb = crc & 0x80000000;
+                       crc = (crc << 1) ^ ((*pdata >> bits) & 1);
+                       if (msb)
+                               crc = crc ^ crc_poly;
+               }
+               pdata++;
+       }
+
+       switch (n & 3) {
+       case 0:
+               break;
+       case 1:
+               residue_value = (*pdata & 0xFF);
+               bits = 8;
+               break;
+       case 2:
+               residue_value = (*pdata & 0xFFFF);
+               bits = 16;
+               break;
+       case 3:
+               residue_value = (*pdata & 0xFFFFFF);
+               bits = 24;
+               break;
+       }
+
+       if (n & 3) {
+               while (--bits >= 0) {
+                       msb = crc & 0x80000000;
+                       crc = (crc << 1) ^ ((residue_value >> bits) & 1);
+                       if (msb)
+                               crc = crc ^ crc_poly;
+               }
+       }
+       return crc;
+}
+
+static int crc_chk(void *p, int n)
+{
+       struct cfw_project *pjt = (void *)p;
+       u32 crc = pjt->cksum, crc_comp;
+
+       pjt->cksum = 0;
+       DBG("Entering crc %d", n);
+       crc_comp = crc32(p, n);
+       if (crc_comp != crc) {
+               DBG("CRC mismatch 0x%08X != 0x%08X", crc, crc_comp);
+               return 0;
+       }
+       DBG("CRC pass");
+       pjt->cksum = crc;
+       return 1;
+}
+#ifndef AIC3XXX_CFW_HOST_BLD
+static
+#endif
+struct cfw_project *aic3xxx_cfw_unpickle(void *p, int n)
+{
+       struct cfw_project *pjt = p;
+       int i, j, k;
+
+       if (pjt->magic != CFW_FW_MAGIC ||
+               pjt->size != n || pjt->bmagic != CFW_FW_VERSION ||
+               !crc_chk(p, n)) {
+               error
+               ("magic:0x%08X!=0x%08X || size:%d!=%d ||version:0x%08X!=0x%08X",
+               pjt->magic, CFW_FW_MAGIC, pjt->size, n, pjt->cksum,
+               CFW_FW_VERSION);
+
+               return NULL;
+       }
+       DBG("Loaded firmware inside unpickle\n");
+
+       for (i = 0; i < CFW_MAX_TRANSITIONS; i++) {
+               if (pjt->transition[i]) {
+                       FW_NDX2PTR(pjt->transition[i], p);
+                       FW_NDX2PTR(pjt->transition[i]->block, p);
+                       aic3xxx_cfw_unpickle_block(pjt->transition[i]->block,
+                                                  p);
+               }
+       }
+
+       for (i = 0; i < pjt->npfw; i++) {
+               DBG("loading pfw %d\n", i);
+               FW_NDX2PTR(pjt->pfw[i], p);
+               if (pjt->pfw[i]->base) {
+                       FW_NDX2PTR(pjt->pfw[i]->base, p);
+                       aic3xxx_cfw_unpickle_image(pjt->pfw[i]->base, p);
+               }
+               if (pjt->pfw[i]->pll) {
+                       FW_NDX2PTR(pjt->pfw[i]->pll, p);
+                       aic3xxx_cfw_unpickle_block(pjt->pfw[i]->pll, p);
+               }
+               for (j = 0; j < pjt->pfw[i]->novly; ++j)
+                       for (k = 0; k < pjt->pfw[i]->ncfg; ++k) {
+                               FW_NDX2PTR(pjt->pfw[i]->ovly_cfg[j][k], p);
+                               aic3xxx_cfw_unpickle_image(pjt->pfw[i]->
+                                                          ovly_cfg[j][k], p);
+                       }
+               for (j = 0; j < pjt->pfw[i]->nctrl; ++j) {
+                       FW_NDX2PTR(pjt->pfw[i]->ctrl[j], p);
+                       aic3xxx_cfw_unpickle_control(pjt->pfw[i]->ctrl[j], p);
+               }
+       }
+
+       DBG("loaded pfw's\n");
+       for (i = 0; i < pjt->nmode; i++) {
+               FW_NDX2PTR(pjt->mode[i], p);
+               if (pjt->mode[i]->entry) {
+                       FW_NDX2PTR(pjt->mode[i]->entry, p);
+                       aic3xxx_cfw_unpickle_block(pjt->mode[i]->entry, p);
+               }
+               if (pjt->mode[i]->exit) {
+                       FW_NDX2PTR(pjt->mode[i]->exit, p);
+                       aic3xxx_cfw_unpickle_block(pjt->mode[i]->exit, p);
+               }
+       }
+       if (pjt->asoc_toc)
+               FW_NDX2PTR(pjt->asoc_toc, p);
+       else {
+               warn("asoc_toc not defined.  FW version mismatch?");
+               return NULL;
+       }
+       DBG("loaded modes");
+       return pjt;
+}
+
+#ifndef AIC3XXX_CFW_HOST_BLD
+static int aic3xxx_get_control(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct cfw_state *ps =
+               (struct cfw_state *) kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cfw_pfw *pfw;
+       int i;
+
+       if (ps->cur_pfw >= ps->pjt->npfw) {
+               DBG("Not in MiniDSP mode");
+               return 0;
+       }
+       pfw = ps->pjt->pfw[ps->cur_pfw];
+       for (i = 0; i < pfw->nctrl; ++i) {
+               if (!strcasecmp(kcontrol->id.name, pfw->ctrl[i]->name)) {
+                       struct cfw_control *pc = pfw->ctrl[i];
+                       ucontrol->value.integer.value[0] = pc->icur;
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+static int aic3xxx_put_control(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct cfw_state *ps =
+               (struct cfw_state *) kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+
+       aic3xxx_cfw_control(ps, kcontrol->id.name,
+                               ucontrol->value.integer.value[0]);
+       return 0;
+}
+
+static int aic3xxx_info_control(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_info *ucontrol)
+{
+       struct cfw_state *ps =
+               (struct cfw_state *) kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cfw_pfw *pfw;
+       int i;
+
+       if (ps->cur_pfw >= ps->pjt->npfw) {
+               DBG("Not in MiniDSP mode");
+               return 0;
+       }
+       pfw = ps->pjt->pfw[ps->cur_pfw];
+       for (i = 0; i < pfw->nctrl; ++i) {
+               if (!strcasecmp(kcontrol->id.name, pfw->ctrl[i]->name)) {
+                       struct cfw_control *pc = pfw->ctrl[i];
+                       ucontrol->value.integer.min = 0;
+                       ucontrol->value.integer.max = pc->imax;
+                       if (pc->imax == 1)
+                               ucontrol->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+                       else
+                               ucontrol->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+               }
+       }
+
+       ucontrol->count = 1;
+       return 0;
+}
+#endif
+int aic3xxx_cfw_add_controls(struct snd_soc_codec *codec, struct cfw_state *ps)
+{
+       int i, j;
+       struct cfw_pfw *pfw;
+
+       for (j = 0; j < ps->pjt->npfw; ++j) {
+               pfw = ps->pjt->pfw[j];
+
+               for (i = 0; i < pfw->nctrl; ++i) {
+                       struct cfw_control *pc = pfw->ctrl[i];
+#ifndef AIC3XXX_CFW_HOST_BLD
+                       struct snd_kcontrol_new *generic_control =
+                               kzalloc(sizeof(struct snd_kcontrol_new),
+                                       GFP_KERNEL);
+                       unsigned int *tlv_array =
+                               kzalloc(4 * sizeof(unsigned int), GFP_KERNEL);
+
+                       if (generic_control == NULL)
+                               return -ENOMEM;
+                       generic_control->access =
+                               SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+                               SNDRV_CTL_ELEM_ACCESS_READWRITE;
+                       tlv_array[0] = SNDRV_CTL_TLVT_DB_SCALE;
+                       tlv_array[1] = 2 * sizeof(unsigned int);
+                       tlv_array[2] = pc->min;
+                       tlv_array[3] = ((pc->step) & TLV_DB_SCALE_MASK);
+                       if (pc->step > 0)
+                               generic_control->tlv.p = tlv_array;
+                       generic_control->name = pc->name;
+                       generic_control->private_value = (unsigned long) ps;
+                       generic_control->get = aic3xxx_get_control;
+                       generic_control->put = aic3xxx_put_control;
+                       generic_control->info = aic3xxx_info_control;
+                       generic_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+#endif
+                       DBG("Adding control %s", pc->name);
+#ifndef AIC3XXX_CFW_HOST_BLD
+                       snd_soc_add_controls(codec, generic_control, 1);
+#endif
+               }
+       }
+       return 0;
+
+}
+
+static int aic3xxx_cfw_set_mode_id(struct cfw_state *ps)
+{
+       struct cfw_asoc_toc *toc = ps->pjt->asoc_toc;
+       int i;
+
+       for (i = 0; i < toc->nentries; ++i) {
+               if (toc->entry[i].cfg == ps->cur_cfg &&
+                   toc->entry[i].mode == ps->cur_mode) {
+                       ps->cur_mode_id = i;
+                       return 0;
+               }
+       }
+       DBG("Unknown mode, cfg combination [%d, %d]",
+               ps->cur_mode, ps->cur_cfg);
+       return -1;
+}
+#ifndef AIC3XXX_CFW_HOST_BLD
+static int aic3xxx_get_mode(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       struct cfw_state *ps = (struct cfw_state *)e->mask;
+
+       ucontrol->value.enumerated.item[0] = ps->cur_mode_id;
+
+       return 0;
+}
+#endif
+#ifndef AIC3XXX_CFW_HOST_BLD
+static int aic3xxx_put_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       struct cfw_state *ps = (struct cfw_state *)e->mask;
+       struct cfw_asoc_toc *toc;
+       int index, ret;
+
+       aic3xxx_cfw_lock(ps, 1);
+       toc = ps->pjt->asoc_toc;
+
+       index = ucontrol->value.enumerated.item[0];
+       if (index < 0 || index >= toc->nentries) {
+               aic3xxx_cfw_lock(ps, 0);
+               return -EINVAL;
+       }
+       ret =
+           aic3xxx_cfw_setmode_cfg_u(ps, toc->entry[index].mode,
+                                     toc->entry[index].cfg);
+       aic3xxx_cfw_lock(ps, 0);
+       return ret;
+}
+#endif
+
+int aic3xxx_cfw_add_modes(struct snd_soc_codec *codec, struct cfw_state *ps)
+{
+#ifndef AIC3XXX_CFW_HOST_BLD
+       int j;
+       struct cfw_asoc_toc *toc = ps->pjt->asoc_toc;
+       struct soc_enum *mode_cfg_enum =
+           kzalloc(sizeof(struct soc_enum), GFP_KERNEL);
+       struct snd_kcontrol_new *mode_cfg_control =
+           kzalloc(sizeof(struct snd_kcontrol_new), GFP_KERNEL);
+       char **enum_texts;
+
+       if (mode_cfg_enum == NULL)
+               goto mem_err;
+       if (mode_cfg_control == NULL)
+               goto mem_err;
+
+       mode_cfg_enum->texts =
+           kzalloc(toc->nentries * sizeof(char *), GFP_KERNEL);
+       if (mode_cfg_enum->texts == NULL)
+               goto mem_err;
+       /* Hack to overwrite the const * const pointer */
+       enum_texts = (char **)mode_cfg_enum->texts;
+
+       for (j = 0; j < toc->nentries; j++)
+               enum_texts[j] = toc->entry[j].etext;
+       mode_cfg_enum->reg = j;
+       mode_cfg_enum->max = toc->nentries;
+       mode_cfg_enum->mask = (unsigned int)ps;
+       mode_cfg_control->name = "Codec Firmware Setmode";
+       mode_cfg_control->get = aic3xxx_get_mode;
+       mode_cfg_control->put = aic3xxx_put_mode;
+       mode_cfg_control->info = snd_soc_info_enum_ext;
+       mode_cfg_control->private_value = (unsigned long)mode_cfg_enum;
+       mode_cfg_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       snd_soc_add_controls(codec, mode_cfg_control, 1);
+       return 0;
+mem_err:
+       kfree(mode_cfg_control);
+       kfree(mode_cfg_enum);
+       kfree(mode_cfg_enum->texts);
+       return -ENOMEM;
+#else
+       return 0;
+#endif
+
+}
diff --git a/sound/soc/codecs/aic3xxx_cfw_ops.h b/sound/soc/codecs/aic3xxx_cfw_ops.h
new file mode 100644 (file)
index 0000000..81f6bda
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef AIC3XXX_CFW_OPS_H_
+#define AIC3XXX_CFW_OPS_H_
+#define DEBUG
+#ifdef AIC3XXX_CFW_HOST_BLD
+struct mutex {
+       int lock;
+};
+#endif
+
+struct cfw_state {
+       struct cfw_project *pjt;
+       struct aic3xxx_codec_ops const *ops;
+       void *ops_obj;
+       struct mutex mutex;
+       int cur_mode_id;
+       int cur_mode;
+       int cur_pfw;
+       int cur_ovly;
+       int cur_cfg;
+};
+
+#ifdef AIC3XXX_CFW_HOST_BLD
+struct cfw_project *aic3xxx_cfw_unpickle(void *pcfw, int n);
+unsigned int crc32(unsigned int *pdata, int n);
+struct snd_soc_codec;
+#else
+#ifdef DEBUG
+#define DBG(fmt, ...) printk(KERN_DEBUG "CFW[%s:%d]: " fmt "\n",       \
+       __FILE__, __LINE__, ##__VA_ARGS__)
+#else
+       #define DBG(fmt, ...)
+#endif
+#endif
+int aic3xxx_cfw_init(struct cfw_state *ps, struct aic3xxx_codec_ops const *ops,
+               void *ops_obj);
+int aic3xxx_cfw_lock(struct cfw_state *ps, int lock);
+int aic3xxx_cfw_reload(struct cfw_state *ps, void *pcfw, int n);
+int aic3xxx_cfw_setmode(struct cfw_state *ps, int mode);
+int aic3xxx_cfw_setmode_cfg(struct cfw_state *ps, int mode, int cfg);
+int aic3xxx_cfw_setcfg(struct cfw_state *ps, int cfg);
+int aic3xxx_cfw_transition(struct cfw_state *ps, char *ttype);
+int aic3xxx_cfw_set_pll(struct cfw_state *ps, int asi);
+int aic3xxx_cfw_control(struct cfw_state *ps, char *cname, int param);
+int aic3xxx_cfw_add_controls(struct snd_soc_codec *codec, struct cfw_state *ps);
+int aic3xxx_cfw_add_modes(struct snd_soc_codec *codec, struct cfw_state *ps);
+
+
+#define AIC3XX_COPS_MDSP_D  (0x00000003u)
+#define AIC3XX_COPS_MDSP_A  (0x00000030u)
+#define AIC3XX_COPS_MDSP_ALL (AIC3XX_COPS_MDSP_D|AIC3XX_COPS_MDSP_A)
+
+#define AIC3XX_ABUF_MDSP_D1 (0x00000001u)
+#define AIC3XX_ABUF_MDSP_D2 (0x00000002u)
+#define AIC3XX_ABUF_MDSP_A  (0x00000010u)
+#define AIC3XX_ABUF_MDSP_ALL \
+       (AIC3XX_ABUF_MDSP_D1 | AIC3XX_ABUF_MDSP_D2 | AIC3XX_ABUF_MDSP_A)
+
+struct aic3xxx_codec_ops {
+       int (*reg_read)(void *p, unsigned int reg);
+       int (*reg_write)(void *p, unsigned int reg,
+                       unsigned int val);
+       int (*set_bits)(void *p, unsigned int reg,
+                       unsigned char mask, unsigned char val);
+       int (*bulk_read)(void *p, unsigned int reg,
+                       int count, u8 *buf);
+       int (*bulk_write)(void *p, unsigned int reg,
+                       int count, const u8 *buf);
+
+       int (*lock) (void *p);
+       int (*unlock) (void *p);
+       int (*stop) (void *p, int mask);
+       int (*restore) (void *p, int runstate);
+       int (*bswap) (void *p, int mask);
+};
+
+#endif
diff --git a/sound/soc/codecs/tlv320aic3262_default_fw.h b/sound/soc/codecs/tlv320aic3262_default_fw.h
new file mode 100644 (file)
index 0000000..55606d7
--- /dev/null
@@ -0,0 +1,330 @@
+unsigned char default_firmware[] = {
+       237, 241, 209, 192, 179, 0, 1, 0, 123, 20, 0, 0, 238, 201, 253, 6,
+       0, 0, 0, 0, 12, 220, 206, 79, 70, 105, 114, 109, 119, 97, 114, 101,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 2, 13, 0, 0, 8, 2, 0, 0,
+       168, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       1, 0, 1, 0, 16, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 151, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 231, 19, 0, 0, 105, 110, 105, 116, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 73, 110, 105, 116, 105, 97, 108, 105,
+       122, 97, 116, 105, 111, 110, 32, 115, 101, 113, 117, 101, 110,
+       99, 101, 32, 40, 97, 112, 112, 108, 105, 101, 100, 32, 111, 110,
+       108, 121, 32, 111, 110, 32, 115, 121, 115, 116, 101, 109, 32, 98,
+       111, 111, 116, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 236, 5, 0, 0, 0, 0, 0, 0,
+       7, 0, 0, 0, 100, 0, 128, 0, 0, 1, 1, 0, 0, 1, 122, 1,
+       0, 0, 4, 51, 0, 0, 82, 0, 0, 0, 67, 151, 0, 1, 119, 127,
+       100, 101, 102, 97, 117, 108, 116, 0, 98, 97, 115, 101, 95, 109, 97,
+       105, 110, 95, 82, 97, 116, 101, 52, 56, 46, 99, 102, 103, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0,
+       0, 0, 0, 0, 53, 12, 0, 0, 172, 9, 0, 0, 133, 12, 0, 0,
+       14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 101, 102, 97,
+       117, 108, 116, 47, 98, 97, 115, 101, 95, 109, 97, 105, 110, 95, 82, 97,
+       116, 101, 52, 56, 46, 99, 102, 103, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       32, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       128, 0, 0, 0, 1, 0, 0, 0, 44, 12, 0, 0, 2, 0, 0, 0,
+       0, 0, 60, 1, 1, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 129,
+       112, 0, 0, 6, 16, 0, 0, 129, 15, 0, 0, 6, 1, 0, 0, 7,
+       8, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 129, 127, 0, 0, 11,
+       2, 0, 0, 129, 127, 0, 0, 12, 8, 0, 0, 129, 127, 0, 0, 18,
+       2, 0, 0, 129, 127, 0, 0, 19, 16, 0, 0, 20, 64, 0, 0, 13,
+       0, 0, 0, 14, 128, 98, 97, 115, 101, 95, 109, 97, 105, 110, 0, 116,
+       99, 104, 95, 98, 97, 115, 101, 95, 109, 97, 105, 110, 95, 82, 97, 116,
+       101, 52, 56, 46, 99, 102, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 14, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 1, 0, 0,
+       0, 5, 15, 0, 0, 2, 0, 0, 0, 0, 0, 60, 1, 1, 98, 97,
+       115, 101, 95, 115, 112, 107, 0, 97, 116, 99, 104, 95, 98, 97, 115, 101,
+       95, 115, 112, 107, 95, 82, 97, 116, 101, 52, 56, 46, 99, 102, 103, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 130, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 128, 0, 0, 0, 1, 0, 0, 0, 142, 17, 0, 0, 2, 0,
+       0, 0, 0, 0, 60, 1, 1, 100, 101, 102, 97, 117, 108, 116, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 100, 101, 102, 97, 117,
+       108, 116, 32, 98, 97, 115, 101, 95, 109, 97, 105, 110, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 32, 98, 97, 115, 101, 95,
+       115, 112, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+};
index 5d6b929..06f813b 100644 (file)
 /*
-* linux/sound/soc/codecs/tlv320aic3262.c
-*
-* Copyright (C) 2012 Texas Instruments, Inc.
-*
-* Based on sound/soc/codecs/tlv320aic3262.c
-*
-* This package is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License version 2 as
-* published by the Free Software Foundation.
-*
-* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-*
-* The TLV320AIC3262 is a flexible, low-power, low-voltage stereo audio
-* codec with digital microphone inputs and programmable outputs.
-*
-* History:
-*
-* Rev 0.1   ASoC driver support       20-01-2011
-*
-*              The AIC325x ASoC driver is ported for the codec AIC3262.
-* Rev 0.2   ASoC driver support      21-03-2011
-*              The AIC326x ASoC driver is updated abe changes.
-*
-* Rev 0.3   ASoC driver support      12.09.2011
-*              fixed the compilation issues for Whistler support
-*
-* Rev 0.4   ASoC driver support     27.09.2011
-*              The AIC326x driver ported for Nvidia cardhu.
-*
-* Rev 0.5   Modified to support Multiple ASI Ports  08-Nov-2011
-*              Driver updated to support ASI Ports of AIC3262
-*
-* Modified by Nvidia 23-Nov-2011 for K39 ASoC changes.
-*/
+ * linux/sound/soc/codecs/tlv320aic326x.c
+ *
+ * Copyright (C) 2011 Texas Instruments Inc.,
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * The TLV320AIC3262 is a flexible, low-power, low-voltage stereo audio
+ * codec with digital microphone inputs and programmable outputs.
+ *
+ * History:
+ *
+ * Rev 0.1   ASoC driver support    TI 20-01-2011
+ *
+ *             The AIC325x ASoC driver is ported for the codec AIC3262.
+ * Rev 0.2   ASoC driver support    TI 21-03-2011
+ *             The AIC326x ASoC driver is updated for linux 2.6.32 Kernel.
+ * Rev 0.3   ASoC driver support    TI    20-04-2011
+ *             The AIC326x ASoC driver is ported to 2.6.35 omap4 kernel
+ */
 
 /*
  *****************************************************************************
  * INCLUDES
  *****************************************************************************
  */
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/platform_device.h>
+#include <linux/switch.h>
+#include <sound/jack.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
 #include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/input.h>
+
+#include <sound/tlv.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
-#include <sound/tlv.h>
-#include <asm/div64.h>
-#include <sound/tlv320aic326x.h>
-#include <sound/jack.h>
-#include <linux/spi/spi.h>
+#include <linux/mfd/tlv320aic3262-registers.h>
+#include <linux/mfd/tlv320aic3262-core.h>
+#include "aic3xxx_cfw.h"
+#include "aic3xxx_cfw_ops.h"
 
 #include "tlv320aic326x.h"
-#include <linux/gpio.h>
-/*
- *****************************************************************************
- * Global Variable
- *****************************************************************************
- */
-static u8 aic3262_reg_ctl;
-
-#ifdef AIC3262_TiLoad
-       extern int aic3262_driver_init(struct snd_soc_codec *codec);
-#endif
-
+#include "aic3262_codec_ops.h"
+#include "tlv320aic3262_default_fw.h"
 
 
-/* whenever aplay/arecord is run, aic3262_hw_params() function gets called.
- * This function reprograms the clock dividers etc. this flag can be used to
- * disable this when the clock dividers are programmed by pps config file
- */
-static struct snd_soc_codec *aic3262_codec;
-
-/*
- *****************************************************************************
- * Macros
- *****************************************************************************
- */
-
-/* ASoC Widget Control definition for a single Register based Control */
-#define SOC_SINGLE_AIC3262(xname) \
-{\
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-       .info = __new_control_info, .get = __new_control_get,\
-       .put = __new_control_put, \
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
-}
-#define SOC_SINGLE_N(xname, xreg, xshift, xmax, xinvert) \
-{\
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-       .info = n_control_info, .get = n_control_get,\
-       .put = n_control_put, \
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
-       .private_value =  ((unsigned long)&(struct soc_mixer_control)) \
-       {.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \
-       .invert = xinvert} }
-
-/* ASoC Widget Control definition for a Double Register based Control */
-
-#define SOC_DOUBLE_R_N(xname, reg_left, reg_right, xshift, xmax, xinvert) \
+#define SOC_DOUBLE_R_SX_TLV3262(xname, xreg_left, xreg_right, xshift,\
+                       xmin, xmax, tlv_array) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-       .info = snd_soc_info_volsw_2r_n, \
-       .get = snd_soc_get_volsw_2r_n, .put = snd_soc_put_volsw_2r_n, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-               .max = xmax, .invert = xinvert} }
-
-#define SND_SOC_DAPM_SWITCH_N(wname, wreg, wshift, winvert) \
-{      .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift,\
-       .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0}
-/*
- *****************************************************************************
- * Function Prototype
- *****************************************************************************
- */
-static int aic3262_set_bias_level(struct snd_soc_codec *codec,
-                                               enum snd_soc_bias_level level);
-
-static int __new_control_info(struct snd_kcontrol *kcontrol,
-                             struct snd_ctl_elem_info *uinfo);
-
-static int __new_control_get(struct snd_kcontrol *kcontrol,
-                            struct snd_ctl_elem_value *ucontrol);
-
-static int __new_control_put(struct snd_kcontrol *kcontrol,
-                            struct snd_ctl_elem_value *ucontrol);
-
-static inline int aic3262_get_divs(int mclk, int rate);
-
-static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params,
-                               struct snd_soc_dai *dai);
-
-static int aic3262_multi_i2s_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-               int clk_id, unsigned int freq, int dir);
-static int aic3262_multi_i2s_set_dai_pll(struct snd_soc_dai *codec_dai,
-               int pll_id, int source, unsigned int freq_in,
-               unsigned int freq_out);
-
-static int aic3262_multi_i2s_asi1_set_dai_fmt(struct snd_soc_dai *codec_dai,
-               unsigned int fmt);
-
-static int aic3262_multi_i2s_asi2_set_dai_fmt(struct snd_soc_dai *codec_dai,
-               unsigned int fmt);
-
-static int aic3262_multi_i2s_asi3_set_dai_fmt(struct snd_soc_dai *codec_dai,
-               unsigned int fmt);
-
-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"};
-static const char *dout1_pincontrol[] = {
-       "disabled", "ASI1 data output", "gpio", "clock out",
-       "INT1", "INT2", "SAR ADC interrupt"};
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+       SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+       .tlv.p = (tlv_array), \
+       .info = snd_soc_info_volsw_2r_sx, \
+       .get = snd_soc_get_volsw_2r_sx, \
+       .put = snd_soc_put_volsw_2r_sx_aic3262, \
+       .private_value = (unsigned long) &(struct soc_mixer_control) \
+                       {.reg = xreg_left, \
+       .rreg = xreg_right, .shift = xshift, \
+       .min = xmin, .max = xmax} }
 
-static const char *din1_pincontrol[] = {"disabled", "enabled"};
+/*****************************************************************************
+                        Macros
+******************************************************************************
 
-static const char *wclk2_pincontrol[] = {
-       "diabled", "ASI1 secondary wclk", "general purpose input",
-       "general purpose output", "clkout", "INT1 interrupt",
-       "IN2 interrupt", "output digital microphone",
-       "SAR ADC interrupt", "data output for ASI1"};
+******************************************************************************
+                 Function Prototype
+******************************************************************************/
 
-static const char *bclk2_pincontrol[] = {
-       "diabled", "ASI1 secondary wclk", "general purpose input",
-       "general purpose output", "clkout", "INT1 interrupt",
-       "IN2 interrupt", "output digital microphone",
-       "SAR ADC interrupt", "data output for ASI1"};
+static int aic3262_hw_params(struct snd_pcm_substream *substream,
+                            struct snd_pcm_hw_params *params,
+                            struct snd_soc_dai *dai);
 
-static const char *dout2_pincontrol[] = {
-       "disabled", "ASI2 Data Output", "General Purpose Output",
-       "INT1 Interrupt", "INT2 Interrupt", "SAR ADC interrupt",
-       "Output for digital microphone", "Data Output for ASI1"};
+static int aic3262_mute(struct snd_soc_dai *dai, int mute);
 
-static const char *din2_pincontrol[] = {"disabled", "enabled"};
+static int aic3262_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+                                 int clk_id, unsigned int freq, int dir);
 
-static const char *wclk3_pincontrol[] = {
-       "Disabled", "ASI3 WCLK", "General Purpose Input",
-       "General Purpose output", "Data Output for ASI1"};
+static int aic3262_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt);
 
-static const char *bclk3_pincontrol[] = {
-       "Disabled", "ASI3 BCLK", "General Purpose Input",
-       "General Purpose output", "Data Output for ASI1"};
+static int aic3262_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
+                               unsigned int Fin, unsigned int Fout);
 
-static const char *dout3_pincontrol[] = {
-       "disabled", "ASI3 data ooutput", "General Purpose Output",
-       "ASI1 Word Clock Output", "Data Output for ASI1"};
-
-static const char *din3_pincontrol[] = {"disabled", "enabled"};
-
-static const char *clkin[] = {
-       "mclk1", "bclk1", "gpio1", "pll_clk", "bclk2", "gpi1",
-       "hf_ref_clk", "hf_osc_clk", "mclk2", "gpio2", "gpi2"};
-
-#endif
-#ifdef DAC_INDEPENDENT_VOL
-/*
- *----------------------------------------------------------------------------
- * Function : n_control_info
- * Purpose  : This function is to initialize data for new control required to
- *            program the AIC3262 registers.
- *
- *----------------------------------------------------------------------------
- */
-static int n_control_info(struct snd_kcontrol *kcontrol,
-                             struct snd_ctl_elem_info *uinfo)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       int max = mc->max;
-       unsigned int shift = mc->shift;
-       unsigned int rshift = mc->rshift;
-
-       if (max == 1)
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       else
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-
-       uinfo->count = shift == rshift ? 1 : 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = max;
-       return 0;
-}
-
-/*
- *----------------------------------------------------------------------------
- * Function : n_control_get
- * Purpose  : This function is to read data of new control for
- *            program the AIC3262 registers.
- *
- *----------------------------------------------------------------------------
- */
-static int n_control_get(struct snd_kcontrol *kcontrol,
-                            struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       u32 val;
-       unsigned short mask, shift;
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       if (!strcmp(kcontrol->id.name, "Left DAC Volume")) {
-               mask = AIC3262_8BITS_MASK;
-               shift = 0;
-               val = snd_soc_read(codec, mc->reg);
-               ucontrol->value.integer.value[0] =
-                   (val <= 48) ? (val + 127) : (val - 129);
-       }
-       if (!strcmp(kcontrol->id.name, "Right DAC Volume")) {
-               mask = AIC3262_8BITS_MASK;
-               shift = 0;
-               val = snd_soc_read(codec, mc->reg);
-               ucontrol->value.integer.value[0] =
-                   (val <= 48) ? (val + 127) : (val - 129);
-       }
+static int aic3262_set_bias_level(struct snd_soc_codec *codec,
+                                 enum snd_soc_bias_level level);
 
-       return 0;
-}
+static int aic3262_set_mode_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol);
+static int aic3262_set_mode_put(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol);
 
-/*
- *----------------------------------------------------------------------------
- * Function : __new_control_put
- * Purpose  : new_control_put is called to pass data from user/application to
- *            the driver.
- *
- *----------------------------------------------------------------------------
- */
-static int n_control_put(struct snd_kcontrol *kcontrol,
-                            struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       u8 val, val_mask;
-       int reg, err;
-       unsigned int invert = mc->invert;
-       int max = mc->max;
-       DBG("n_control_put\n");
-       reg = mc->reg;
-       val = ucontrol->value.integer.value[0];
-       if (invert)
-               val = max - val;
-       if (!strcmp(kcontrol->id.name, "Left DAC Volume")) {
-               DBG("LDAC\n");
-               val = (val >= 127) ? (val - 127) : (val + 129);
-               val_mask = AIC3262_8BITS_MASK;
-       }
-       if (!strcmp(kcontrol->id.name, "Right DAC Volume")) {
-               DBG("RDAC\n");
-               val = (val >= 127) ? (val - 127) : (val + 129);
-               val_mask = AIC3262_8BITS_MASK;
-       }
+static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
+                                struct snd_kcontrol *kcontrol, int event);
 
-       err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
-       if (err < 0) {
-               printk(KERN_ERR "Error while updating bits\n");
-               return err;
-       }
+static long debug_level;
+module_param(debug_level, long, 0);
+MODULE_PARM_DESC(debug_level, "Debug level for printing");
 
-       return 0;
-}
-#endif /*#ifdef DAC_INDEPENDENT_VOL*/
-/*
- *------------------------------------------------------------------------------
- * snd_soc_info_volsw_2r_n - double mixer info callback
+/**
+ * snd_soc_put_volsw_2r_sx - double with tlv and variable data size
+ *             mixer put callback
  * @kcontrol: mixer control
  * @uinfo: control element information
  *
- * Callback to provide information about a double mixer control that
- * spans 2 codec registers.
- *
  * Returns 0 for success.
- *------------------------------------------------------------------------------
  */
-int snd_soc_info_volsw_2r_n(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_info *uinfo)
+int snd_soc_put_volsw_2r_sx_aic3262(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *ucontrol)
 {
        struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       int max = mc->max;
-
-       if (max == 1)
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       else
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = max;
-       return 0;
-}
-
-/*
- *------------------------------------------------------------------------------
- * snd_soc_get_volsw_2r_n - double mixer get callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to get the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- *------------------------------------------------------------------------------
- */
-int snd_soc_get_volsw_2r_n(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
+           (struct soc_mixer_control *)kcontrol->private_value;
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned int reg = mc->reg;
-       unsigned int reg2 = mc->rreg;
-       unsigned int shift = mc->shift;
-       int max = mc->max;
-       unsigned int mask;
-       unsigned int invert = mc->invert;
-       unsigned short val, val2;
-
-       if (!strcmp(kcontrol->id.name, "PCM Playback Volume")) {
-               mask = AIC3262_8BITS_MASK;
-               shift = 0;
-       } else if (!strcmp(kcontrol->id.name, "HP Driver Gain")) {
-               mask = 0x3F;
-               shift = 0;
-       } else if (!strcmp(kcontrol->id.name, "PGA Capture Volume")) {
-               mask = 0x7F;
-               shift = 0;
-       } else if (!strcmp(kcontrol->id.name, "REC Driver Volume")) {
-               mask = 0x3F;
-               shift = 0;
-       } else if (!strcmp(kcontrol->id.name, "LO to HP Volume")) {
-               mask = 0x7F;
-               shift = 0;
-       } else if (!strcmp(kcontrol->id.name, "MA Volume")) {
-               mask = 0x7F;
-               shift = 0;
-       } else {
-               printk(KERN_ERR "Invalid kcontrol name\n");
-               return -1;
-       }
-
-       /* Read, update the corresponding Registers */
-       val = (snd_soc_read(codec, reg) >> shift) & mask;
-       val2 = (snd_soc_read(codec, reg2) >> shift) & mask;
-
-       if (!strcmp(kcontrol->id.name, "PCM Playback Volume")) {
-               ucontrol->value.integer.value[0] =
-                   (val <= 48) ? (val + 127) : (val - 129);
-               ucontrol->value.integer.value[1] =
-                   (val2 <= 48) ? (val2 + 127) : (val2 - 129);
-       } else if (!strcmp(kcontrol->id.name, "HP Driver Gain")) {
-               ucontrol->value.integer.value[0] =
-                   (val >= 57) ? (val - 57) : (val + 7);
-               ucontrol->value.integer.value[1] =
-                   (val2 >= 57) ? (val2 - 57) : (val2 + 7);
-       } else if (!strcmp(kcontrol->id.name, "PGA Capture Volume")) {
-               ucontrol->value.integer.value[0] =
-                   (val <= 40) ? (val + 24) : (val - 104);
-               ucontrol->value.integer.value[1] =
-                   (val2 <= 40) ? (val2 + 24) : (val2 - 104);
-       } else if (!strcmp(kcontrol->id.name, "REC Driver Volume")) {
-               ucontrol->value.integer.value[0] = ((val >= 0) & (val <= 29)) ?
-                                                (val + 7) : (val - 57);
-               ucontrol->value.integer.value[1] = ((val2 >= 0) &
-                   (val2 <= 29)) ? (val2 + 7) : (val2 - 57);
-
-       } else if (!strcmp(kcontrol->id.name, "LO to HP Volume")) {
-               ucontrol->value.integer.value[0] = ((val >= 0) & (val <= 116)) ?
-                                (val + 1) : ((val == 127) ? (0) : (117));
-               ucontrol->value.integer.value[1] = ((val2 >= 0) & (val2 <= 116))
-                                ? (val2 + 1) : ((val2 == 127) ? (0) : (117));
-
-       } else if (!strcmp(kcontrol->id.name, "MA Volume")) {
-               ucontrol->value.integer.value[0] = (val <= 40) ?
-                                        (41 - val) : (val = 0);
-               ucontrol->value.integer.value[1] = (val2 <= 40) ?
-                                        (41 - val2) : (val2 = 0);
-       }
-
-       if (invert) {
-               ucontrol->value.integer.value[0] =
-                       max - ucontrol->value.integer.value[0];
-               ucontrol->value.integer.value[1] =
-                       max - ucontrol->value.integer.value[1];
-       }
-
-       return 0;
-}
-/*
-*-------------------------------------------------------------------------------
-* snd_soc_put_volsw_2r_n - double mixer set callback
-* @kcontrol: mixer control
-* @ucontrol: control element information
-*
-* Callback to set the value of a double mixer control that spans 2 registers.
-*
-* Returns 0 for success.
-*-------------------------------------------------------------------------------
-*/
-int snd_soc_put_volsw_2r_n(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned int reg = mc->reg;
-       unsigned int reg2 = mc->rreg;
-       unsigned int shift = mc->shift;
-       int max = mc->max;
-       unsigned int mask;
-       unsigned int invert = mc->invert;
-       int err;
-       unsigned short val, val2, val_mask;
-
-       mask = 0x00FF;
-
-       val = (ucontrol->value.integer.value[0] & mask);
-       val2 = (ucontrol->value.integer.value[1] & mask);
-       if (invert) {
-               val = max - val;
-               val2 = max - val2;
-       }
-
-       /* Check for the string name of the kcontrol */
-       if (!strcmp(kcontrol->id.name, "PCM Playback Volume")) {
-               val = (val >= 127) ? (val - 127) : (val + 129);
-               val2 = (val2 >= 127) ? (val2 - 127) : (val2 + 129);
-               val_mask = AIC3262_8BITS_MASK;  /* 8 bits */
-       } else if ((!strcmp(kcontrol->id.name, "HP Driver Gain")) ||
-                  (!strcmp(kcontrol->id.name, "LO Driver Gain"))) {
-               val = (val <= 6) ? (val + 57) : (val - 7);
-               val2 = (val2 <= 6) ? (val2 + 57) : (val2 - 7);
-               val_mask = 0x3F;        /* 6 bits */
-               DBG("val=%d, val2=%d", val, val2);
-       } else if (!strcmp(kcontrol->id.name, "PGA Capture Volume")) {
-               val = (val >= 24) ? ((val <= 64) ?
-                       (val-24) : (40)) : (val + 104);
-               val2 = (val2 >= 24) ?
-                       ((val2 <= 64) ? (val2 - 24) : (40)) : (val2 + 104);
-               val_mask = 0x7F;        /* 7 bits */
-       } else if (!strcmp(kcontrol->id.name, "LO to REC Volume")) {
-
-               val = (val <= 116) ?
-                        (val % 116) : ((val == 117) ? (127) : (117));
-               val2 = (val2 <= 116) ?
-                       (val2 % 116) : ((val2 == 117) ? (127) : (117));
-               val_mask = 0x7F;
-       } else if (!strcmp(kcontrol->id.name, "REC Driver Volume")) {
-
-               val = (val <= 7) ? (val + 57) : ((val < 36) ? (val - 7) : (29));
-               val2 = (val2 <= 7) ?
-                               (val2 + 57) : ((val2 < 36) ? (val2 - 7) : (29));
-               val_mask = 0x3F;
-       } else if (!strcmp(kcontrol->id.name, "LO to HP Volume")) {
-
-               val = ((val > 0) & (val <= 117)) ?
-                        (val - 1) : ((val == 0) ? (127) : (116));
-               val2 = ((val2 > 0) & (val2 <= 117)) ?
-                        (val2 - 1) : ((val2 == 0) ? (127) : (116));
-               val_mask = 0x7F;
-       } else if (!strcmp(kcontrol->id.name, "MA Volume")) {
-
-               val = ((val <= 41) & (val > 0)) ?
-                        (41 - val) : ((val > 41) ? (val = 41) : (63));
-               val2 = ((val2 <= 41) & (val2 > 0)) ?
-                        (41 - val2) : ((val2 > 41) ? (val2 = 41) : (63));
-               val_mask = 0x7F;
-       } else {
-               printk(KERN_ERR "Invalid control name\n");
-               return -1;
-       }
-
-       val = val << shift;
-       val2 = val2 << shift;
-
-       err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
-       if (err < 0)
-               return err;
+       unsigned int mask = (1 << mc->shift) - 1;
+       int min = mc->min;
+       int ret;
+       unsigned int val, valr;
 
-       err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
-       return err;
-}
-
-static int __new_control_info(struct snd_kcontrol *kcontrol,
-                             struct snd_ctl_elem_info *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 65535;
+       val = ((ucontrol->value.integer.value[0] + min) & 0xff);
+       val &= mask;
+       valr = ((ucontrol->value.integer.value[1] + min) & 0xff);
+       valr &= mask;
 
+       ret = 0;
+       ret = snd_soc_update_bits_locked(codec, mc->reg, mask, val);
+       if (ret < 0)
+               return ret;
+       ret = snd_soc_update_bits_locked(codec, mc->rreg, mask, valr);
+       if (ret < 0)
+               return ret;
        return 0;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : __new_control_get
- * Purpose  : This function is to read data of new control for
- *            program the AIC3262 registers.
- *
- *----------------------------------------------------------------------------
- */
-static int __new_control_get(struct snd_kcontrol *kcontrol,
-               struct snd_ctl_elem_value *ucontrol)
+static ssize_t debug_level_show(struct device *dev,
+               struct device_attribute *attr,
+               char *buf, size_t count)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       u32 val;
-       val = snd_soc_read(codec, aic3262_reg_ctl);
-       ucontrol->value.integer.value[0] = val;
-       return 0;
+       return sprintf(buf, "%ld\n", debug_level);
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : __new_control_put
- * Purpose  : new_control_put is called to pass data from user/application to
- *            the driver.
- *
- *----------------------------------------------------------------------------
- */
-static int __new_control_put(struct snd_kcontrol *kcontrol,
-               struct snd_ctl_elem_value *ucontrol)
+static ssize_t debug_level_set(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       u8 data[2];
-       int ret = 0;
-
-       u32 data_from_user = ucontrol->value.integer.value[0];
-
-       aic3262_change_book(codec, 0);
-       aic3262_reg_ctl = data[0] = (u8) ((data_from_user & 0xFF00) >> 8);
-       data[1] = (u8) ((data_from_user & 0x00FF));
-
-       if (!data[0])
-               aic3262->page_no = data[1];
+       int ret;
 
-       DBG("reg = %d val = %x\n", data[0], data[1]);
-#if defined(LOCAL_REG_ACCESS)
-       if (codec->hw_write(codec->control_data, data, 2) != 2)
-               ret = -EIO;
-#else
-       ret = snd_soc_write(codec, data[0], data[1]);
-#endif
+       ret = kstrtol(buf, 10, &debug_level);
        if (ret)
-               printk(KERN_ERR "Error in i2c write\n");
-
-       return ret;
+               return ret;
+       return count;
 }
 
+static DEVICE_ATTR(debug_level, 0644, debug_level_show, debug_level_set);
 
-/*
- *****************************************************************************
- * Structure Initialization
- *****************************************************************************
- */
 static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
 static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1200, 50, 0);
 static const DECLARE_TLV_DB_SCALE(spk_gain_tlv, 600, 600, 0);
-static const DECLARE_TLV_DB_SCALE(output_gain_tlv, -600, 100, 0);
+static const DECLARE_TLV_DB_SCALE(output_gain_tlv, -600, 100, 1);
 static const DECLARE_TLV_DB_SCALE(micpga_gain_tlv, 0, 50, 0);
 static const DECLARE_TLV_DB_SCALE(adc_fine_gain_tlv, -40, 10, 0);
 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" };
+static const char * const input_common_mode_text[] = {
+       "0.9v", "0.75v"
+};
 
-static const char *output_common_mode_text[] = {
-       "Input CM", "1.25v", "1.5v", "1.65v" };
+static const char * const output_common_mode_text[] = {
+       "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(AIC3262_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(AIC3262_CM_REG, 0, 4, output_common_mode_text);
 /*
  *****************************************************************************
  * Structure Initialization
@@ -641,2388 +203,874 @@ static const struct snd_kcontrol_new aic3262_snd_controls[] = {
 #ifndef DAC_INDEPENDENT_VOL
        /* sound new kcontrol for PCM Playback volume control */
 
-       SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
-                       DAC_LVOL, DAC_RVOL, 8,0xffffff81, 0x30, dac_vol_tlv),
+       SOC_DOUBLE_R_SX_TLV3262("PCM Playback Volume",
+                               AIC3262_DAC_LVOL, AIC3262_DAC_RVOL, 8,
+                               0xffffff81,
+                               0x30, dac_vol_tlv),
 #endif
-       /*HP Driver Gain Control*/
-       SOC_DOUBLE_R_SX_TLV("HeadPhone Driver Amplifier Volume",
-                       HPL_VOL, HPR_VOL, 6, 0xfffffffa, 0xe, output_gain_tlv),
-
-       /*LO Driver Gain Control*/
-       SOC_DOUBLE_TLV("Speaker Amplifier Volume",
-                               SPK_AMP_CNTL_R4, 4, 0, 5, 0, spk_gain_tlv),
+       /*HP Driver Gain Control */
+       SOC_DOUBLE_R_SX_TLV3262("HeadPhone Driver Amplifier Volume",
+                               AIC3262_HPL_VOL, AIC3262_HPR_VOL, 6, 0xffffffb9,
+                               0xffffffce, output_gain_tlv),
+       /*LO Driver Gain Control */
+       SOC_DOUBLE_TLV("Speaker Amplifier Volume", AIC3262_SPK_AMP_CNTL_R4, 4,
+                       0, 5, 0, spk_gain_tlv),
 
-       SOC_DOUBLE_R_SX_TLV("Receiver Amplifier Volume",
-       REC_AMP_CNTL_R5, RAMPR_VOL, 6, 0xfffffffa, 0x1d, output_gain_tlv),
+       SOC_DOUBLE_R_SX_TLV3262("Receiver Amplifier Volume",
+                               AIC3262_REC_AMP_CNTL_R5, AIC3262_RAMPR_VOL, 6,
+                               0xffffffb9, 0xffffffd6, output_gain_tlv),
 
-       SOC_DOUBLE_R_SX_TLV("PCM Capture Volume",
-               LADC_VOL, RADC_VOL, 7,0xffffff68, 0x24, adc_vol_tlv),
+       SOC_DOUBLE_R_SX_TLV3262("PCM Capture Volume", AIC3262_LADC_VOL,
+                               AIC3262_RADC_VOL, 7, 0xffffff68, 0xffffffa8,
+                               adc_vol_tlv),
 
+       SOC_DOUBLE_R_TLV("MicPGA Volume Control", AIC3262_MICL_PGA,
+                        AIC3262_MICR_PGA, 0, 0x5F, 0, micpga_gain_tlv),
 
-       SOC_DOUBLE_R_TLV ("MicPGA Volume Control",
-               MICL_PGA, MICR_PGA, 0, 0x5F, 0, micpga_gain_tlv),
-       SOC_DOUBLE_TLV("PCM Capture Fine Gain Volume",
-               ADC_FINE_GAIN, 4, 0, 5, 1, adc_fine_gain_tlv),
+       SOC_DOUBLE_TLV("PCM Capture Fine Gain Volume", AIC3262_ADC_FINE_GAIN,
+                       4, 0, 5, 1, adc_fine_gain_tlv),
 
-       SOC_DOUBLE("ADC channel mute", ADC_FINE_GAIN, 7, 3, 1, 0),
+       SOC_DOUBLE("ADC channel mute", AIC3262_ADC_FINE_GAIN, 7, 3, 1, 0),
 
-       SOC_DOUBLE("DAC MUTE", DAC_MVOL_CONF, 2, 3, 1, 1),
-
-       /* sound new kcontrol for Programming the registers from user space */
-       SOC_SINGLE_AIC3262("Program Registers"),
-
-       SOC_SINGLE("RESET", RESET_REG, 0,1,0),
-
-       SOC_SINGLE("DAC VOL SOFT STEPPING", DAC_MVOL_CONF, 0, 2, 0),
-
-#ifdef DAC_INDEPENDENT_VOL
-       /*SOC_SINGLE_N("Left DAC Volume", DAC_LVOL, 0, 0xAF, 0),
-       SOC_SINGLE_N("Right DAC Volume", DAC_RVOL, 0, 0xAF, 0),*/
-#endif
+       SOC_DOUBLE("DAC MUTE", AIC3262_DAC_MVOL_CONF, 2, 3, 1, 1),
 
-       SOC_SINGLE("DAC AUTO MUTE CONTROL", DAC_MVOL_CONF, 4, 7, 0),
-       SOC_SINGLE("RIGHT MODULATOR SETUP", DAC_MVOL_CONF, 7, 1, 0),
+       SOC_SINGLE("RESET", AIC3262_RESET_REG, 0, 1, 0),
 
-       SOC_SINGLE("ADC Volume soft stepping", ADC_CHANNEL_POW, 0, 3, 0),
+       SOC_SINGLE("DAC VOL SOFT STEPPING", AIC3262_DAC_MVOL_CONF, 0, 2, 0),
 
-       SOC_DOUBLE_R("MICPGA enable/disable",MICL_PGA,MICR_PGA,7, 1, 0),
+       SOC_SINGLE("DAC AUTO MUTE CONTROL", AIC3262_DAC_MVOL_CONF, 4, 7, 0),
 
-       SOC_SINGLE("Mic Bias ext independent enable", MIC_BIAS_CNTL, 7, 1, 0),
-       SOC_SINGLE("MICBIAS_EXT ON", MIC_BIAS_CNTL, 6, 1, 0),
-       SOC_SINGLE("MICBIAS EXT Power Level", MIC_BIAS_CNTL, 4, 3, 0),
+       SOC_SINGLE("RIGHT MODULATOR SETUP", AIC3262_DAC_MVOL_CONF, 7, 1, 0),
 
-       SOC_SINGLE("MICBIAS_INT ON", MIC_BIAS_CNTL, 2, 1, 0),
-       SOC_SINGLE("MICBIAS INT Power Level", MIC_BIAS_CNTL, 0, 3, 0),
+       SOC_SINGLE("ADC Volume soft stepping", AIC3262_ADC_CHANNEL_POW,
+                  0, 3, 0),
 
-       SOC_DOUBLE("DRC_EN_CTL", DRC_CNTL_R1, 6, 5, 1, 0),
-       SOC_SINGLE("DRC_THRESHOLD_LEVEL", DRC_CNTL_R1, 2, 7, 1),
-       SOC_SINGLE("DRC_HYSTERISIS_LEVEL", DRC_CNTL_R1, 0, 7, 0),
+       SOC_SINGLE("Mic Bias ext independent enable", AIC3262_MIC_BIAS_CNTL,
+                  7, 1, 0),
 
-       SOC_SINGLE("DRC_HOLD_LEVEL", DRC_CNTL_R2, 3, 0x0F, 0),
-       SOC_SINGLE("DRC_GAIN_RATE", DRC_CNTL_R2, 0, 4, 0),
-       SOC_SINGLE("DRC_ATTACK_RATE", DRC_CNTL_R3, 4, 0x0F, 1),
-       SOC_SINGLE("DRC_DECAY_RATE", DRC_CNTL_R3, 0, 0x0F, 1),
+       SOC_SINGLE("MICBIAS EXT Power Level", AIC3262_MIC_BIAS_CNTL, 4, 3, 0),
 
-       SOC_SINGLE("BEEP_GEN_EN", BEEP_CNTL_R1, 7, 1, 0),
-       SOC_DOUBLE_R("BEEP_VOL_CNTL", BEEP_CNTL_R1, BEEP_CNTL_R2, 0, 0x0F, 1),
-       SOC_SINGLE("BEEP_MAS_VOL", BEEP_CNTL_R2, 6, 3, 0),
+       SOC_SINGLE("MICBIAS INT Power Level", AIC3262_MIC_BIAS_CNTL, 0, 3, 0),
 
-       SOC_DOUBLE_R("AGC_EN", LAGC_CNTL, RAGC_CNTL, 7, 1, 0),
-       SOC_DOUBLE_R("AGC_TARGET_LEVEL", LAGC_CNTL, RAGC_CNTL, 4, 7, 1),
+       SOC_SINGLE("BEEP_GEN_EN", AIC3262_BEEP_CNTL_R1, 7, 1, 0),
 
-       SOC_DOUBLE_R("AGC_GAIN_HYSTERESIS", LAGC_CNTL, RAGC_CNTL, 0, 3, 0),
-       SOC_DOUBLE_R("AGC_HYSTERESIS", LAGC_CNTL_R2, RAGC_CNTL_R2, 6, 3, 0),
-       SOC_DOUBLE_R("AGC_NOISE_THRESHOLD", LAGC_CNTL_R2,
-                                               RAGC_CNTL_R2, 1, 31, 1),
+       SOC_DOUBLE_R("BEEP_VOL_CNTL", AIC3262_BEEP_CNTL_R1,
+                    AIC3262_BEEP_CNTL_R2, 0, 0x0F, 1),
 
-       SOC_DOUBLE_R("AGC_MAX_GAIN", LAGC_CNTL_R3, RAGC_CNTL_R3, 0, 116, 0),
-       SOC_DOUBLE_R("AGC_ATCK_TIME", LAGC_CNTL_R4, RAGC_CNTL_R4, 3, 31, 0),
-       SOC_DOUBLE_R("AGC_ATCK_SCALE_FACTOR",
-                               LAGC_CNTL_R4, RAGC_CNTL_R4, 0, 7, 0),
+       SOC_SINGLE("BEEP_MAS_VOL", AIC3262_BEEP_CNTL_R2, 6, 3, 0),
 
-       SOC_DOUBLE_R("AGC_DECAY_TIME", LAGC_CNTL_R5, RAGC_CNTL_R5, 3, 31, 0),
-       SOC_DOUBLE_R("AGC_DECAY_SCALE_FACTOR",
-                               LAGC_CNTL_R5, RAGC_CNTL_R5, 0, 7, 0),
-       SOC_DOUBLE_R("AGC_NOISE_DEB_TIME", LAGC_CNTL_R6,
-                                               RAGC_CNTL_R6, 0, 31, 0),
+       SOC_SINGLE("DAC PRB Selection", AIC3262_DAC_PRB, 0, 26, 0),
 
-       SOC_DOUBLE_R("AGC_SGL_DEB_TIME", LAGC_CNTL_R7,
-                                       RAGC_CNTL_R7, 0, 0x0F, 0),
+       SOC_SINGLE("ADC PRB Selection", AIC3262_ADC_PRB, 0, 18, 0),
 
-       SOC_SINGLE("DAC PRB Selection",DAC_PRB, 0, 25, 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),
-};
-
 
-/* the sturcture contains the different values for mclk */
-static const struct aic3262_rate_divs aic3262_divs[] = {
-/*
- * mclk, rate, p_val, pll_j, pll_d, dosr, ndac, mdac, aosr, nadc, madc, blck_N,
- * codec_speficic_initializations
- */
-       /* 8k rate */
-#ifdef CONFIG_MINI_DSP
-       {12000000, 8000, 1, 8, 1920, 768, 8, 2, 128, 8, 12, 4,
-               {{0, 60, 0}, {0, 61, 0} } },
-#else
-       {12000000, 8000, 1, 8, 1920, 128, 12, 8, 128, 8, 6, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {12288000, 8000, 1, 1, 3333, 128, 12, 8, 128, 8, 6, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {24000000, 8000, 1, 4, 96, 128, 12, 8, 128, 12, 8, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-#endif
-       /* 11.025k rate */
-       {12000000, 11025, 1, 1, 8816, 1024, 8, 2, 128, 8, 2, 48,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {12288000, 11025, 1, 1, 8375, 1024, 8, 2, 128, 8, 2, 48,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {24000000, 11025, 1, 3, 7632, 128, 8, 8, 128, 8, 8, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-
-       /* 16k rate */
-#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} } },
-       {12288000, 16000, 1, 2, 6667, 128, 8, 6, 128, 8, 6, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {24000000, 16000, 1, 4, 96, 128, 8, 6, 128, 8, 6, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-#endif
-       /* 22.05k rate */
-       {12000000, 22050, 1, 3, 7632, 128, 8, 2, 128, 8, 2, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {12288000, 22050, 1, 3, 675, 128, 8, 2, 128, 8, 2, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {24000000, 22050, 1, 3, 7632, 128, 8, 3, 128, 8, 3, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       /* 32k rate */
-       {12000000, 32000, 1, 5, 4613, 128, 8, 2, 128, 8, 2, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {12288000, 32000, 1, 5, 3333, 128, 8, 2, 128, 8, 2, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {24000000, 32000, 1, 4, 96, 128, 6, 4, 128, 6, 4, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-
-#ifdef CONFIG_MINI_DSP
-       {12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4,
-               {{0, 60, 0}, {0, 61, 0} } },
-       {12288000, 44100, 1, 7, 3548, 128, 2, 8, 128, 8, 2, 4,
-               {{0, 60, 0}, {0, 61, 0} } },
-#else
-       /* 44.1k rate */
-       {12000000, 44100, 1, 7, 5264, 128, 8, 2, 128, 8, 2, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {12288000, 44100, 1, 7, 3548, 128, 8, 2, 128, 8, 2, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {24000000, 44100, 1, 3, 7632, 128, 4, 4, 64, 4, 4, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-#endif
-
-#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,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {12288000, 48000, 1, 8, 52, 128, 8, 2, 128, 8, 2, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-       {24000000, 48000, 1, 4, 960, 128, 4, 4, 128, 4, 4, 4,
-               {{0, 60, 1}, {0, 61, 1} } },
-#endif
+       SOC_ENUM("Output CM mode", output_cm_mode),
 
-       /*96k rate */
-       {12000000, 96000, 1, 16, 3840, 128, 8, 2, 128, 8, 2 , 4,
-               {{0, 60, 7}, {0, 61, 7} } },
-       {24000000, 96000, 1, 4, 960, 128, 4, 2, 128, 4, 2, 2,
-               {{0, 60, 7}, {0, 61, 7} } },
-       /*192k */
-       {12000000, 192000, 1, 32, 7680, 128, 8, 2, 128, 8, 2, 4,
-               {{0, 60, 17}, {0, 61, 13} } },
-       {24000000, 192000, 1, 4, 960, 128, 2, 2, 128, 2, 2, 4,
-               {{0, 60, 17}, {0, 61, 13} } },
+       SOC_SINGLE_EXT("FIRMWARE SET MODE", SND_SOC_NOPM, 0, 0xffff, 0,
+                       aic3262_set_mode_get, aic3262_set_mode_put),
 };
 
-
-
-/*
-*----------------------------------------------------------------------------
-* Function : aic3262_multi_i2s_dump_regs
-* Purpose  : This function is to mute or unmute the left and right DAC
-*
-*----------------------------------------------------------------------------
-*/
-static void aic3262_multi_i2s_dump_regs(struct snd_soc_dai *dai)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       unsigned int counter;
-
-       DBG(KERN_INFO "#%s: Dai Active %d ASI%d REGS DUMP\n",
-               __func__, aic3262->active_count, dai->id);
-
-       aic3262_change_page(codec, 0);
-       aic3262_change_book(codec, 0);
-
-       DBG(KERN_INFO "#Page0 REGS..\n");
-       for (counter = 0; counter < 85; counter++) {
-               DBG(KERN_INFO "#%2d -> 0x%x\n", counter,
-                       snd_soc_read(codec, counter));
-       }
-
-       DBG(KERN_INFO "#Page1 REGS..\n");
-       for (counter = 128; counter < 176; counter++) {
-               DBG(KERN_INFO "#%2d -> 0x%x\n", (counter % 128),
-                       snd_soc_read(codec, counter));
-       }
-
-       DBG(KERN_INFO "#Page4 REGS..\n");
-       for (counter = 512; counter < 631; counter++) {
-               DBG(KERN_INFO "#%2d -> 0x%x\n",
-                       (counter % 128), snd_soc_read(codec, counter));
-       }
-
-       for (counter = 0; counter < MAX_ASI_COUNT; counter++) {
-               DBG(KERN_INFO "#ASI%d Frame %s @ %dHz Playback %d Record %d\n",
-               (counter + 1),
-               (aic3262->asiCtxt[counter].master == 1) ? "Master" : "Slave",
-               aic3262->asiCtxt[counter].sampling_rate,
-               aic3262->asiCtxt[counter].playback_mode,
-               aic3262->asiCtxt[counter].capture_mode);
-               DBG(KERN_INFO "#DAC Option [%d,%d] ADC Option %d WLEN %d\n\n",
-               aic3262->asiCtxt[counter].left_dac_output,
-               aic3262->asiCtxt[counter].right_dac_output,
-               aic3262->asiCtxt[counter].adc_input,
-               aic3262->asiCtxt[counter].word_len);
-       }
-       return;
-}
-
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_multi_i2s_mute
- * Purpose  : This function is to mute or unmute the left and right DAC
- *
- *----------------------------------------------------------------------------
- */
-static int aic3262_multi_i2s_mute(struct snd_soc_dai *dai, int mute)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "#%s : mute entered with %d\n", __func__, mute);
-
-       /* If we are doing both Recording and Playback on this DAI interface,
-       * do not MUTE the Codec.
-       */
-       if (mute && (aic3262->asiCtxt[dai->id - 1].asi_active > 1)) {
-               DBG("#%s Cannot Mute the ASI%d Now..\n",
-                       __func__, dai->id);
-       } else {
-               switch (dai->id) {
-               case 1:
-                       aic3262_multi_i2s_asi1_mute(dai, mute);
-               break;
-               case 2:
-                       aic3262_multi_i2s_asi2_mute(dai, mute);
-               break;
-               case 3:
-                       aic3262_multi_i2s_asi3_mute(dai, mute);
-               break;
-               default:
-                       printk(KERN_ERR "#%s: Invalid DAI id\n", __func__);
-                       return -EINVAL;
-               }
-       }
-       DBG(KERN_INFO "#%s : mute ended\n", __func__);
-       return 0;
-}
-
-
-/*
-*----------------------------------------------------------------------------
-* Function : aic3262_multi_i2s_asi1_mute
-* Purpose  : This function is to mute or unmute the left and right DAC
-*
-*----------------------------------------------------------------------------
-*/
-static int aic3262_multi_i2s_asi1_mute(struct snd_soc_dai *dai, int mute)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "#%s : mute %d started\n", __func__, mute);
-
-       if (mute && !aic3262->asiCtxt[0].port_muted ) {
-               DBG(KERN_INFO "Mute if part\n");
-
-
-       snd_soc_update_bits(codec, DAC_MVOL_CONF, DAC_LR_MUTE_MASK,DAC_LR_MUTE);
-
-               /* First check if both Playback and Recording is going on
-               * this interface.
-               */
-               if (aic3262->asiCtxt[0].asi_active > 1) {
-                       DBG("#%s Cannot Mute the ASI Now..\n", __func__);
-               } else if (!(aic3262->asiCtxt[1].playback_mode) &&
-                       !(aic3262->asiCtxt[2].playback_mode)) {
-                       /* Before Muting, please check if any other
-                       * ASI is active. if so, we cannot simply mute the
-                       * DAC and ADC Registers.
-                       */
-               DBG("#%s None of the ASI's are active now..\n", __func__);
-                       snd_soc_write(codec, DAC_MVOL_CONF,
-                               ((aic3262->dac_reg & 0xF3) | 0x0C));
-                       snd_soc_write(codec, ADC_FINE_GAIN,
-                               ((aic3262->adc_gain & 0x77) | 0x88));
-                       snd_soc_write(codec, HPL_VOL, 0xB9);
-                       snd_soc_write(codec, HPR_VOL, 0xB9);
-                       snd_soc_write(codec, REC_AMP_CNTL_R5, 0x39);
-                       snd_soc_write(codec, RAMPR_VOL, 0x39);
-                       snd_soc_write(codec, SPK_AMP_CNTL_R4, 0x00);
-                       aic3262->asiCtxt[0].port_muted = 1;
-               }
-       } else {
-               DBG(KERN_INFO "Mute else part\n");
-               snd_soc_update_bits(codec, DAC_MVOL_CONF,
-                                               DAC_LR_MUTE_MASK, 0x0);
-               snd_soc_write(codec, ADC_FINE_GAIN,(0X00 & 0x77) | 0x0);
-               aic3262_multi_i2s_dump_regs(dai);
-       }
-
-       DBG(KERN_INFO "#%s : mute %d ended\n", __func__, mute);
-
-       return 0;
-}
-
-/*
-*----------------------------------------------------------------------------
-* Function : aic3262_multi_i2s_asi2_maic3262_asi3_clk_configute
-* Purpose : This function is to mute or unmute the left and right DAC
-*
-*----------------------------------------------------------------------------
-*/
-static int aic3262_multi_i2s_asi2_mute(struct snd_soc_dai *dai, int mute)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "#%s : mute %d started\n", __func__, mute);
-
-       if (mute && !aic3262->asiCtxt[1].port_muted ) {
-               DBG(KERN_INFO "Mute if part\n");
-       snd_soc_update_bits(codec, DAC_MVOL_CONF, DAC_LR_MUTE_MASK,DAC_LR_MUTE);
-
-               /* First check if both Playback and Recording is going on
-               * this interface.
-               */
-               if (aic3262->asiCtxt[1].asi_active > 1) {
-                       DBG("#%s Cannot Mute the ASI Now..\n", __func__);
-               } else if (!(aic3262->asiCtxt[0].playback_mode) &&
-                       !(aic3262->asiCtxt[2].playback_mode)) {
-                       /* Before Muting, please check if any other
-                       * ASI is active. if so, we cannot simply mute the
-                       * DAC and ADC Registers.
-                       */
-                       snd_soc_write(codec, DAC_MVOL_CONF,
-                               ((aic3262->dac_reg & 0xF3) | 0x0C));
-                       snd_soc_write(codec, ADC_FINE_GAIN,
-                               ((aic3262->adc_gain & 0x77) | 0x88));
-                       snd_soc_write(codec, HPL_VOL, 0xB9);
-                       snd_soc_write(codec, HPR_VOL, 0xB9);
-                       snd_soc_write(codec, REC_AMP_CNTL_R5, 0x39);
-                       snd_soc_write(codec, RAMPR_VOL, 0x39);
-                       snd_soc_write(codec, SPK_AMP_CNTL_R4, 0x00);
-                       aic3262->asiCtxt[1].port_muted = 1;
-               }
-       } else {
-               DBG(KERN_INFO "Mute else part\n");
-               snd_soc_update_bits(codec, DAC_MVOL_CONF,
-                                               DAC_LR_MUTE_MASK, 0x0);
-
-               /*aic3262_multi_i2s_dump_regs(dai);*/
-       }
-
-       DBG(KERN_INFO "#%s : mute %d ended\n", __func__, mute);
-
-       return 0;
-}
-
-/*
-*----------------------------------------------------------------------------
-* Function : aic3262_multi_i2s_asi3_mute
-* Purpose : This function is to mute or unmute the left and right DAC
-*
-*----------------------------------------------------------------------------
-*/
-static int aic3262_multi_i2s_asi3_mute(struct snd_soc_dai *dai, int mute)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "#%s : mute %d started\n", __func__, mute);
-
-       if (mute && !aic3262->asiCtxt[2].port_muted) {
-               DBG("Mute if part\n");
-       snd_soc_update_bits(codec, DAC_MVOL_CONF, DAC_LR_MUTE_MASK,DAC_LR_MUTE);
-
-               /* First check if both Playback and Recording is going on
-               * this interface.
-               */
-               if (aic3262->asiCtxt[2].asi_active > 1) {
-                       DBG("#%s Cannot Mute the ASI Now..\n", __func__);
-               } else if (!(aic3262->asiCtxt[0].playback_mode) &&
-                       !(aic3262->asiCtxt[1].playback_mode)) {
-                       /* Before Muting, please check if any other
-                       * ASI is active. if so, we cannot simply mute the
-                       * DAC and ADC Registers.
-                       */
-                       snd_soc_write(codec, DAC_MVOL_CONF,
-                               ((aic3262->dac_reg & 0xF3) | 0x0C));
-                       snd_soc_write(codec, ADC_FINE_GAIN,
-                               ((aic3262->adc_gain & 0x77) | 0x88));
-                       snd_soc_write(codec, HPL_VOL, 0xB9);
-                       snd_soc_write(codec, HPR_VOL, 0xB9);
-                       snd_soc_write(codec, REC_AMP_CNTL_R5, 0x39);
-                       snd_soc_write(codec, RAMPR_VOL, 0x39);
-                       snd_soc_write(codec, SPK_AMP_CNTL_R4, 0x00);
-                       aic3262->asiCtxt[2].port_muted = 1;
-               }
-       } else {
-               DBG("Mute else part\n");
-               snd_soc_update_bits(codec, DAC_MVOL_CONF,
-                                               DAC_LR_MUTE_MASK, 0x0);
-
-               /*aic3262_multi_i2s_dump_regs(dai);*/
-
-       }
-
-       DBG(KERN_INFO "#%s : mute %d ended\n", __func__, mute);
-
-       return 0;
-}
-
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_multi_i2s_set_dai_fmt
- * Purpose  : This function is to set the DAI format
- *
- *----------------------------------------------------------------------------
- */
-static int aic3262_multi_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
-               unsigned int fmt)
-{
-       /* Check the DAI Id and based on that switch the configuration for
-       * the Individual ASI Port.
-       */
-       switch (codec_dai->id) {
-       case 1:
-               aic3262_multi_i2s_asi1_set_dai_fmt(codec_dai, fmt);
-       break;
-       case 2:
-               aic3262_multi_i2s_asi2_set_dai_fmt(codec_dai, fmt);
-       break;
-       case 3:
-               aic3262_multi_i2s_asi3_set_dai_fmt(codec_dai, fmt);
-       break;
-       default:
-               printk(KERN_ERR
-                       "#%s: Invalid DAI interface format\n", __func__);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-
-
-/*
-*----------------------------------------------------------------------------
-* Function : aic3262_multi_i2s_asi1_set_dai_fmt
-* Purpose  : This function is to set the DAI format for ASI1 Port
-*
-*----------------------------------------------------------------------------
-*/
-static int aic3262_multi_i2s_asi1_set_dai_fmt(struct snd_soc_dai *codec_dai,
-               unsigned int fmt)
-{
-       struct snd_soc_codec *codec = codec_dai->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       u8 iface_reg, clk_reg;
-       u8 regvalue;
-
-       DBG(KERN_INFO "%s: DAI_ID %d fmt %d\n",
-               __func__, codec_dai->id, fmt);
-
-       /* Read the B0_P4_R4 and B0_P4_R10 Registers to configure the
-       * ASI1 Bus and Clock Formats depending on the PCM Format.
-       */
-       iface_reg = snd_soc_read(codec, ASI1_BUS_FMT);
-       clk_reg   = snd_soc_read(codec, ASI1_BWCLK_CNTL_REG);
-
-       /* set master/slave audio interface */
-       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-       case SND_SOC_DAIFMT_CBM_CFM:
-               DBG(KERN_INFO "#%s: Configuring ASI%d as Frame Master..\n",
-                       __func__, codec_dai->id);
-               aic3262->asiCtxt[0].master = 1;
-               clk_reg |= (BIT5 | BIT2);       /* Codec Interface as Master */
-       break;
-       case SND_SOC_DAIFMT_CBS_CFS:
-               DBG(KERN_INFO "#%s: Configuring ASI%d as Frame Slave..\n",
-                       __func__, codec_dai->id);
-               clk_reg &= ~0xFC; /* Reset bits D[7:5] and D[4:2] to zero */
-               aic3262->asiCtxt[0].master = 0;
-       break;
-       case SND_SOC_DAIFMT_CBS_CFM:
-               /* new case..just for debugging */
-               DBG(KERN_INFO "%s: SND_SOC_DAIFMT_CBS_CFM\n", __func__);
-               aic3262->asiCtxt[0].master = 0;
-               clk_reg |= BIT5;        /* Only WCLK1 Output from Codec */
-               clk_reg &= ~0x1C;       /* BCLK1 Input to Codec */
-       break;
-       default:
-               printk(KERN_ERR "#%s: Invalid DAI master/slave interface\n",
-                       __func__);
-               return -EINVAL;
-       }
-       aic3262->asiCtxt[0].pcm_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
-       /* interface format */
-       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-       case SND_SOC_DAIFMT_I2S:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for I2s Mode..\n",
-                       __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f);
-       break;
-       case SND_SOC_DAIFMT_DSP_A:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for DSP_A Mode..\n",
-                       __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f) | 0x20;
-       break;
-       case SND_SOC_DAIFMT_RIGHT_J:
-               iface_reg = (iface_reg & 0x1f) | 0x40;
-       break;
-       case SND_SOC_DAIFMT_LEFT_J:
-               iface_reg = (iface_reg & 0x1f) | 0x60;
-       break;
-       case SND_SOC_DAIFMT_DSP_B:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for DSP_B Mode..\n",
-                       __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f) | 0x80;
-               /* voice call need data offset in 1 bitclock */
-               snd_soc_write(codec, ASI1_LCH_OFFSET, 1);
-       break;
-       default:
-               printk(KERN_ERR
-                       "#%s: Invalid DAI interface format\n", __func__);
-               return -EINVAL;
-       }
-       /* Also Configure the Pin Control Registers before writing into
-       * the ASI specific Clock Control and Format Registers
-       */
-
-       /* Configure B0_P4_R65_D[5:2] to 001 This configures the
-       * WCLK1 Pin to ASI1
-       */
-       regvalue = snd_soc_read(codec, WCLK1_PIN_CNTL_REG);
-       snd_soc_write(codec, WCLK1_PIN_CNTL_REG, (regvalue | BIT2));
-
-       /* Configure B0_P4_R68_d[6:5] = 01 and B0_P4_R67_D[4:1] to 0001
-       * to ensure that the DIN1 and DOUT1 Pins are configured
-       * correctly
-       */
-       regvalue = snd_soc_read(codec, DIN1_PIN_CNTL_REG);
-       snd_soc_write(codec, DIN1_PIN_CNTL_REG, (regvalue | BIT5));
-       regvalue = snd_soc_read(codec, DOUT1_PIN_CNTL_REG);
-       snd_soc_write(codec, DOUT1_PIN_CNTL_REG, (regvalue | BIT1));
-
-       snd_soc_write(codec, ASI1_BWCLK_CNTL_REG, clk_reg);
-
-       snd_soc_write(codec, ASI1_BUS_FMT, iface_reg);
-
-       return 0;
-}
-
-
-/*
-*----------------------------------------------------------------------------
-* Function : aic3262_multi_i2s_asi2_set_dai_fmt
-* Purpose  : This function is to set the DAI format for ASI2 Port
-*
-*----------------------------------------------------------------------------
-*/
-static int aic3262_multi_i2s_asi2_set_dai_fmt(struct snd_soc_dai *codec_dai,
-                       unsigned int fmt)
-{
-       struct snd_soc_codec *codec = codec_dai->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       u8 iface_reg, clk_reg;
-       u8 regvalue;
-
-       DBG(KERN_INFO "%s: DAI_ID %d fmt %d\n",
-               __func__, codec_dai->id, fmt);
-
-       /* Read the B0_P4_R17 and B0_P4_R26 Registers to configure the
-       * ASI1 Bus and Clock Formats depending on the PCM Format.
-       */
-       iface_reg = snd_soc_read(codec, ASI2_BUS_FMT);
-       clk_reg   = snd_soc_read(codec, ASI2_BWCLK_CNTL_REG);
-
-       /* set master/slave audio interface */
-       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-       case SND_SOC_DAIFMT_CBM_CFM:
-               DBG(KERN_INFO "#%s: Configuring ASI%d as Frame Master..\n",
-                       __func__, codec_dai->id);
-               aic3262->asiCtxt[1].master = 1;
-               clk_reg |= (BIT5 | BIT2);
-       break;
-       case SND_SOC_DAIFMT_CBS_CFS:
-               DBG(KERN_INFO "#%s: Configuring ASI%d as Frame Slave..\n",
-                       __func__, codec_dai->id);
-
-               clk_reg &= ~0xFC;
-               aic3262->asiCtxt[1].master = 0;
-       break;
-       case SND_SOC_DAIFMT_CBS_CFM:
-               /*new case..just for debugging */
-               DBG(KERN_INFO "%s: SND_SOC_DAIFMT_CBS_CFM\n", __func__);
-               aic3262->asiCtxt[1].master = 0;
-               clk_reg |= BIT5;
-               clk_reg &= ~0x1C;
-       break;
-       default:
-               printk(KERN_ERR "#%s:Invalid DAI master/slave interface\n",
-                       __func__);
-               return -EINVAL;
-       }
-       aic3262->asiCtxt[1].pcm_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
-       /* interface format */
-       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-       case SND_SOC_DAIFMT_I2S:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for I2S Mode..\n",
-                               __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f);
-       break;
-       case SND_SOC_DAIFMT_DSP_A:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for DSP_A Mode..\n",
-                       __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f) | 0x20;
-       break;
-       case SND_SOC_DAIFMT_RIGHT_J:
-               iface_reg = (iface_reg & 0x1f) | 0x40;
-       break;
-       case SND_SOC_DAIFMT_LEFT_J:
-               iface_reg = (iface_reg & 0x1f) | 0x60;
-       break;
-       case SND_SOC_DAIFMT_DSP_B:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for DSP Mode..\n",
-                       __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f) | 0x80;
-               /* voice call need data offset in 1 bitclock */
-               snd_soc_write(codec, ASI2_LCH_OFFSET, 1);
-       break;
-       default:
-               printk(KERN_ERR "#%s:Invalid DAI interface format\n", __func__);
-               return -EINVAL;
-       }
-
-       /* Also Configure the Pin Control Registers before writing into
-       * the ASI2 specific Clock Control and Format Registers
-       */
-
-       /* Configure B0_P4_R69_D[5:2] to 001 This configures the
-       * WCLK2 Pin to ASI2
-       */
-
-       regvalue = snd_soc_read(codec, WCLK2_PIN_CNTL_REG);
-       snd_soc_write(codec, WCLK2_PIN_CNTL_REG, (regvalue | BIT2));
-
-       regvalue = snd_soc_read(codec, BCLK2_PIN_CNTL_REG);
-       snd_soc_write(codec, BCLK2_PIN_CNTL_REG, (regvalue | BIT2));
-
-       /* Configure B0_P4_R72_d[6:5] = 01 and B0_P4_R71_D[4:1] to 0001
-        * to ensure that the DIN2 and DOUT2 Pins are configured
-        * correctly
-        */
-       regvalue = snd_soc_read(codec, DIN2_PIN_CNTL_REG);
-       snd_soc_write(codec, DIN2_PIN_CNTL_REG, (regvalue | BIT5));
-
-       regvalue = snd_soc_read(codec, DOUT2_PIN_CNTL_REG);
-       snd_soc_write(codec, DOUT2_PIN_CNTL_REG, (regvalue | BIT5 | BIT1));
-
-       snd_soc_write(codec, ASI2_BWCLK_CNTL_REG, clk_reg);
-
-       snd_soc_write(codec, ASI2_BUS_FMT, iface_reg);
-
-       return 0;
-}
-
-/*
-*----------------------------------------------------------------------------
-* Function : aic3262_multi_i2s_asi3_set_dai_fmt
-* Purpose  : This function is to set the DAI format for ASI3 Port
-*
-*----------------------------------------------------------------------------
-*/
-static int aic3262_multi_i2s_asi3_set_dai_fmt(struct snd_soc_dai *codec_dai,
-                       unsigned int fmt)
-{
-       struct snd_soc_codec *codec = codec_dai->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       u8 iface_reg, clk_reg;
-       u8 regvalue;
-
-       DBG(KERN_INFO "%s: DAI_ID %d fmt %d\n",
-               __func__, codec_dai->id, fmt);
-
-       /* Read the B0_P4_R33 and B0_P4_R42 Registers to configure the
-       * ASI1 Bus and Clock Formats depending on the PCM Format.
-       */
-       iface_reg = snd_soc_read(codec, ASI3_BUS_FMT);
-       clk_reg   = snd_soc_read(codec, ASI3_BWCLK_CNTL_REG);
-
-       /* set master/slave audio interface */
-       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-       case SND_SOC_DAIFMT_CBM_CFM:
-               DBG(KERN_INFO "#%s: Configuring ASI%d as Frame Master..\n",
-                       __func__, codec_dai->id);
-               aic3262->asiCtxt[2].master = 1;
-               clk_reg |= (BIT5 | BIT2);
-       break;
-       case SND_SOC_DAIFMT_CBS_CFS:
-               DBG(KERN_INFO "#%s: Configuring ASI%d as Frame Slave..\n",
-                       __func__, codec_dai->id);
-               clk_reg &= ~0xFC;
-               aic3262->asiCtxt[2].master = 0;
-       break;
-       case SND_SOC_DAIFMT_CBS_CFM:
-               /* new case..just for debugging */
-               DBG(KERN_INFO "%s: SND_SOC_DAIFMT_CBS_CFM\n", __func__);
-               aic3262->asiCtxt[2].master = 0;
-               clk_reg |= BIT5;
-               clk_reg &= ~0x1C;
-       break;
-       default:
-               printk(KERN_ERR "Invalid DAI master/slave interface\n");
-               return -EINVAL;
-       }
-       aic3262->asiCtxt[2].pcm_format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
-       /* interface format */
-       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-       case SND_SOC_DAIFMT_I2S:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for I2S Mode..\n",
-                       __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f);
-       break;
-       case SND_SOC_DAIFMT_DSP_A:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for DSP_A Mode..\n",
-                       __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f) | 0x20;
-       break;
-       case SND_SOC_DAIFMT_RIGHT_J:
-               iface_reg = (iface_reg & 0x1f) | 0x40;
-       break;
-       case SND_SOC_DAIFMT_LEFT_J:
-               iface_reg = (iface_reg & 0x1f) | 0x60;
-       break;
-       case SND_SOC_DAIFMT_DSP_B:
-               DBG(KERN_INFO "#%s: Configuring ASI%d for DSP Mode..\n",
-                       __func__, codec_dai->id);
-               iface_reg = (iface_reg & 0x1f) | 0x80;
-               /* voice call need data offset in 1 bitclock */
-               snd_soc_write(codec, ASI3_LCH_OFFSET, 1);
-       break;
-       default:
-               printk(KERN_ERR
-                       "#%s: Invalid DAI interface format\n", __func__);
-               return -EINVAL;
-       }
-
-       /* Also Configure the Pin Control Registers before writing into
-       * the ASI specific Clock Control and Format Registers
-       */
-       /* Configure B0_P4_R73_D[5:2] to 0001 This configures the
-       * WCLK1 Pin to ASI1
-       */
-       regvalue = snd_soc_read(codec, WCLK3_PIN_CNTL_REG);
-       snd_soc_write(codec, WCLK3_PIN_CNTL_REG, (regvalue | BIT2));
-
-       regvalue = snd_soc_read(codec, BCLK3_PIN_CNTL_REG);
-       snd_soc_write(codec, BCLK3_PIN_CNTL_REG, (regvalue | BIT2));
-
-       /* Configure B0_P4_R76_d[6:5] = 01 and B0_P4_R75_D[4:1] to 0001
-       * to ensure that the DIN1 and DOUT1 Pins are configured
-       * correctly
-       */
-       regvalue = snd_soc_read(codec, DIN3_PIN_CNTL_REG);
-       snd_soc_write(codec, DIN3_PIN_CNTL_REG, (regvalue | BIT5));
-       regvalue = snd_soc_read(codec, DOUT3_PIN_CNTL_REG);
-       snd_soc_write(codec, DOUT3_PIN_CNTL_REG, (regvalue | BIT1));
-
-       snd_soc_write(codec, ASI3_BWCLK_CNTL_REG, clk_reg);
-
-       snd_soc_write(codec, ASI3_BUS_FMT, iface_reg);
-
-       return 0;
-}
-
-/*
- * Clock after PLL and dividers
- */
-static int aic3262_multi_i2s_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-               int clk_id, unsigned int freq, int dir)
-{
-       struct snd_soc_codec *codec = codec_dai->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "#%s: DAI ID %d Freq %d Direction %d\n",
-                       __func__, codec_dai->id, freq, dir);
-       switch (freq) {
-       case AIC3262_FREQ_12000000:
-       case AIC3262_FREQ_12288000:
-       case AIC3262_FREQ_24000000:
-               aic3262->sysclk = freq;
-               return 0;
-               break;
-       }
-       printk(KERN_ERR "Invalid frequency to set DAI system clock\n");
-       return -EINVAL;
-}
-
-/*
-* aic3262_multi_i2s_set_pll
-*
-* This function is invoked as part of the PLL call-back
-* handler from the ALSA layer.
-*/
-static int aic3262_multi_i2s_set_dai_pll(struct snd_soc_dai *codec_dai,
-               int pll_id, int source, unsigned int freq_in,
-               unsigned int freq_out)
-{
-
-       printk(KERN_INFO "%s: DAI ID %d PLL_ID %d InFreq %d OutFreq %d\n",
-               __func__, pll_id, codec_dai->id, freq_in, freq_out);
-
-       return 0;
-}
-
-/*
-* aic3262_asi1_clk_config
-*
-* This function is used to configure the BCLK1, WCLK1 pins which
-* are specific to ASI1 Interface. This function just enables the
-* BCLk and WCLK  along with the miniDSP Port Control Registers.
-* However, depending on the user requirement, this function can also be
-* extended to configure the sourc for the BCLK and WCLK on a ASI basis.
-*/
-static int aic3262_asi1_clk_config(struct snd_soc_codec *codec,
-               struct snd_pcm_hw_params *params)
-{
-       u8 bclk_N_value, wclk_N_value;
-       u8 minidspD_data, minidspA_data;
-       u8 regval;
-
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "%s: Invoked\n",  __func__);
-
-       /* Configure the BCLK and WCLK Output Mux Options */
-       regval = snd_soc_read(codec, ASI1_BWCLK_OUT_CNTL);
-       regval &= ~(AIC3262_ASI_BCLK_MUX_MASK | AIC3262_ASI_WCLK_MUX_MASK);
-
-       regval |= (aic3262->asiCtxt[0].bclk_output <<
-                       AIC3262_ASI_BCLK_MUX_SHIFT);
-       regval |= aic3262->asiCtxt[0].wclk_output;
-       snd_soc_write(codec, ASI1_BWCLK_OUT_CNTL, regval);
-
-       /* Configure the corresponding miniDSP Data Ports */
-       minidspD_data = snd_soc_read(codec, MINIDSP_PORT_CNTL_REG);
-       minidspD_data &= ~(BIT5 | BIT4);
-       snd_soc_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data);
-
-       minidspA_data = snd_soc_read(codec, ASI1_ADC_INPUT_CNTL);
-       minidspA_data &= ~(BIT2 | BIT1 | BIT0);
-       minidspA_data |= aic3262->asiCtxt[0].adc_input;
-       snd_soc_write(codec, ASI1_ADC_INPUT_CNTL, minidspA_data);
-
-
-       if (aic3262->asiCtxt[0].master == 1) {
-               DBG(KERN_INFO
-               "#%s: Codec Master on ASI1 Port. Enabling BCLK WCLK Divider.\n",
-                       __func__);
-               bclk_N_value = aic3262->asiCtxt[0].bclk_div;
-               snd_soc_write(codec, ASI1_BCLK_N, (bclk_N_value | 0x80));
-
-               wclk_N_value = snd_soc_read(codec, ASI1_WCLK_N);
-               snd_soc_write(codec, ASI1_WCLK_N, (wclk_N_value | 0xA0));
-       }
-       return 0;
-
-}
-
-/*
-* aic3262_asi2_clk_config
-*
-* This function is used to configure the BCLK2, WCLK2 pins which
-* are specific to ASI2 Interface. This function just enables the
-* BCLk and WCLK  along with the miniDSP Port Control Registers.
-* However, depending on the user requirement, this function can also be
-* extended to configure the sourc for the BCLK and WCLK on a ASI basis.
-*/
-static int aic3262_asi2_clk_config(struct snd_soc_codec *codec,
-               struct snd_pcm_hw_params *params)
-{
-       u8 bclk_N_value, wclk_N_value, minidspD_data, minidspA_data;
-       u8 regval;
-
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "%s: Invoked\n",  __func__);
-
-
-       /* Configure the BCLK and WCLK Output Mux Options */
-       regval = snd_soc_read(codec, ASI2_BWCLK_OUT_CNTL);
-       regval &= ~(AIC3262_ASI_BCLK_MUX_MASK | AIC3262_ASI_WCLK_MUX_MASK);
-       regval |= (aic3262->asiCtxt[1].bclk_output <<
-                       AIC3262_ASI_BCLK_MUX_SHIFT);
-       regval |= aic3262->asiCtxt[1].wclk_output;
-
-       snd_soc_write(codec, ASI2_BWCLK_OUT_CNTL, regval);
-       /* Configure the corresponding miniDSP Data Ports */
-       minidspD_data = snd_soc_read(codec, MINIDSP_PORT_CNTL_REG);
-       minidspD_data |= (BIT2);
-       snd_soc_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data);
-
-       minidspA_data = snd_soc_read(codec, ASI2_ADC_INPUT_CNTL);
-       minidspA_data &= ~(BIT2 | BIT1 | BIT0);
-       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",
-                       __func__);
-               bclk_N_value = aic3262->asiCtxt[1].bclk_div;
-               snd_soc_write(codec, ASI2_BCLK_N, (bclk_N_value | 0x80));
-
-               wclk_N_value = snd_soc_read(codec, ASI2_WCLK_N);
-               snd_soc_write(codec, ASI2_WCLK_N, (wclk_N_value | 0xA0));
-       }
-
-       return 0;
-
-}
-
-/*
-* aic3262_asi3_clk_config
-*
-* This function is used to configure the BCLK3, WCLK3 pins which
-* are specific to ASI3 Interface. This function just enables the
-* BCLk and WCLK  along with the miniDSP Port Control Registers.
-* However, depending on the user requirement, this function can also be
-* extended to configure the sourc for the BCLK and WCLK on a ASI basis.
-*/
-static int aic3262_asi3_clk_config(struct snd_soc_codec *codec,
-               struct snd_pcm_hw_params *params)
-{
-       u8 bclk_N_value, wclk_N_value, minidspD_data, minidspA_data;
-       u8 regval;
-
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "%s:\n",  __func__);
-
-
-       /* Configure the BCLK and WCLK Output Mux Options */
-       regval = snd_soc_read(codec, ASI3_BWCLK_OUT_CNTL);
-       regval &= ~(AIC3262_ASI_BCLK_MUX_MASK | AIC3262_ASI_WCLK_MUX_MASK);
-       regval |= (aic3262->asiCtxt[2].bclk_output <<
-                       AIC3262_ASI_BCLK_MUX_SHIFT);
-       regval |= aic3262->asiCtxt[2].wclk_output;
-       snd_soc_write(codec, ASI3_BWCLK_OUT_CNTL, regval);
-
-       minidspD_data = snd_soc_read(codec, MINIDSP_PORT_CNTL_REG);
-       minidspD_data |= (BIT1);
-       snd_soc_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data);
-
-       minidspA_data = snd_soc_read(codec, ASI3_ADC_INPUT_CNTL);
-       minidspA_data &= ~(BIT2 | BIT1 | BIT0);
-       minidspA_data |= aic3262->asiCtxt[2].adc_input;
-       snd_soc_write(codec, ASI3_ADC_INPUT_CNTL, minidspA_data);
-
-               if (aic3262->asiCtxt[2].master == 1) {
-               DBG(KERN_INFO
-               "#%s: Codec Master on ASI3 Port. Enabling BCLK WCLK Divider.\n",
-                       __func__);
-               bclk_N_value = aic3262->asiCtxt[2].bclk_div;
-               snd_soc_write(codec, ASI2_BCLK_N, (bclk_N_value | 0x80));
-
-               wclk_N_value = snd_soc_read(codec, ASI3_WCLK_N);
-               snd_soc_write(codec, ASI3_WCLK_N, (wclk_N_value | 0xA0));
-       }
-       return 0;
-
-}
-
-/*
-* aic3262_multi_i2s_hw_params
-*
-* This function is used to configure the individual ASI port registers
-* depending on the configuration passed on by the snd_pcm_hw_params
-* structure.
-* This function internally configures the ASI specific pins and clock
-* Control Registers.
-*/
-static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream,
-                       struct snd_pcm_hw_params *params,
-                       struct snd_soc_dai *dai)
-{
-       int i, j;
-       u8 data;
-       u16 regoffset = 0;
-       u8 dacpath = 0;
-       u8 adcpath = 0;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       DBG(KERN_INFO "#%s: Invoked for ASI%d Port for %s Mode\n",
-               __func__, dai->id,
-               (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               ? "Playback" : "Record");
-
-       i = aic3262_get_divs(aic3262->sysclk, params_rate(params));
-
-       i2c_verify_book0(codec);
-
-       if (i < 0) {
-               printk(KERN_ERR "#%s: Sampling rate %d not supported\n",
-                       __func__, params_rate(params));
-               return i;
-       }
-
-       aic3262_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-       /* Configure the PLL J, R D values only if none of the ASI
-       * Interfaces are Active.
-       */
-
-       if (1) {
-               DBG(KERN_INFO "#%s: None of the ASIs active yet...\n",
-                       __func__);
-               /*We will fix R value to 1 and make P & J=K.D as variable */
-               /* Setting P & R values are set to 1 and 1 at init*/
-
-               /* J value */
-               snd_soc_write(codec, PLL_J_REG, aic3262_divs[i].pll_j);
-
-               /* MSB & LSB for D value */
-
-               snd_soc_write(codec, PLL_D_MSB, (aic3262_divs[i].pll_d >> 8));
-               snd_soc_write(codec, PLL_D_LSB,
-                             (aic3262_divs[i].pll_d & AIC3262_8BITS_MASK));
-
-               /* NDAC divider value */
-               data = snd_soc_read(codec, NDAC_DIV_POW_REG);
-               DBG(KERN_INFO "# reading NDAC = %d , NDAC_DIV_POW_REG = %x\n",
-                       aic3262_divs[i].ndac, data);
-               snd_soc_write(codec, NDAC_DIV_POW_REG,
-                        ((data & 0x80)|(aic3262_divs[i].ndac)));
-               DBG(KERN_INFO "# writing NDAC = %d , NDAC_DIV_POW_REG = %x\n",
-                       aic3262_divs[i].ndac,
-                       ((data & 0x80)|(aic3262_divs[i].ndac)));
-
-               /* MDAC divider value */
-               data = snd_soc_read(codec, MDAC_DIV_POW_REG);
-               DBG(KERN_INFO "# reading MDAC = %d , MDAC_DIV_POW_REG = %x\n",
-                       aic3262_divs[i].mdac, data);
-               snd_soc_write(codec, MDAC_DIV_POW_REG,
-                       ((data & 0x80)|(aic3262_divs[i].mdac)));
-               DBG(KERN_INFO "# writing MDAC = %d , MDAC_DIV_POW_REG = %x\n",
-               aic3262_divs[i].mdac, ((data & 0x80)|(aic3262_divs[i].mdac)));
-
-               /* DOSR MSB & LSB values */
-               snd_soc_write(codec, DOSR_MSB_REG, aic3262_divs[i].dosr >> 8);
-               DBG(KERN_INFO "# writing DOSR_MSB_REG = %d\n",
-                       (aic3262_divs[i].dosr >> 8));
-               snd_soc_write(codec, DOSR_LSB_REG,
-                       aic3262_divs[i].dosr & AIC3262_8BITS_MASK);
-               DBG(KERN_INFO "# writing DOSR_LSB_REG = %d\n",
-                       (aic3262_divs[i].dosr & AIC3262_8BITS_MASK));
-
-               /* NADC divider value */
-               data = snd_soc_read(codec, NADC_DIV_POW_REG);
-               snd_soc_write(codec, NADC_DIV_POW_REG,
-                       ((data & 0x80)|(aic3262_divs[i].nadc)));
-               DBG(KERN_INFO "# writing NADC_DIV_POW_REG = %d\n",
-                       aic3262_divs[i].nadc);
-
-               /* MADC divider value */
-               data = snd_soc_read(codec, MADC_DIV_POW_REG);
-               snd_soc_write(codec, MADC_DIV_POW_REG,
-                       ((data & 0x80)|(aic3262_divs[i].madc)));
-               DBG(KERN_INFO "# writing MADC_DIV_POW_REG = %d\n",
-                       aic3262_divs[i].madc);
-
-               /* AOSR value */
-               snd_soc_write(codec, AOSR_REG, aic3262_divs[i].aosr);
-               DBG(KERN_INFO "# writing AOSR = %d\n", aic3262_divs[i].aosr);
-       } else {
-               DBG(KERN_INFO "#Atleast 1 ASI Active. Cannot Program PLL..\n");
-       }
-       /* Check for the DAI ID to know which ASI needs
-       * Configuration.
-       */
-       switch (dai->id) {
-       case 1:
-               regoffset = ASI1_BUS_FMT;
-
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       DBG(KERN_INFO "#%s: ASI1 DAC Inputs enabled..\n",
-                                       __func__);
-                       /* Read the DAC Control Register and configure it
-                       * as per the ASIContext Structure Settings.
-                       */
-                       dacpath = snd_soc_read(codec, ASI1_DAC_OUT_CNTL);
-                       dacpath &= ~(AIC3262_ASI_LDAC_PATH_MASK |
-                               AIC3262_ASI_RDAC_PATH_MASK);
-                       dacpath |= (aic3262->asiCtxt[0].left_dac_output
-                               << AIC3262_ASI_LDAC_PATH_SHIFT);
-
-                       dacpath |= (aic3262->asiCtxt[0].right_dac_output
-                               << AIC3262_ASI_RDAC_PATH_SHIFT);
-                       snd_soc_write(codec, ASI1_DAC_OUT_CNTL, dacpath);
-
-                       aic3262->asiCtxt[0].playback_mode = 1;
-                       aic3262->asiCtxt[0].bclk_div =
-                               aic3262_divs[i].blck_N;
-               } else {
-                       /* For Recording, Configure the DOUT Pin as per
-                        * ASIContext Structure Settings.
-                        */
-                       adcpath = snd_soc_read(codec, ASI1_DATA_OUT);
-                       adcpath &= ~(AIC3262_ASI_DOUT_MASK);
-
-                       adcpath |= aic3262->asiCtxt[0].dout_option;
-                       snd_soc_write(codec, ASI1_DATA_OUT, adcpath);
-
-                       aic3262->asiCtxt[0].capture_mode = 1;
-               }
-       break;
-       case 2:
-               regoffset = ASI2_BUS_FMT;
-
-               /* Since we are configuring ASI2, please check if Playback
-                * is expected. If so, enable ASI2 Inputs to Left and
-                * Right DACs
-                */
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       DBG(KERN_INFO "#%s: ASI2 DAC Inputs enabled..\n",
-                                       __func__);
-                       /* Read the DAC Control Register and configure it
-                        * as per theASIContext Structure Settings.
-                        */
-                       dacpath = snd_soc_read(codec, ASI2_DAC_OUT_CNTL);
-                       dacpath &= ~(AIC3262_ASI_LDAC_PATH_MASK |
-                               AIC3262_ASI_RDAC_PATH_MASK);
-                       dacpath |= (aic3262->asiCtxt[1].left_dac_output
-                               << AIC3262_ASI_LDAC_PATH_SHIFT);
-
-                       dacpath |= (aic3262->asiCtxt[1].right_dac_output
-                               << AIC3262_ASI_RDAC_PATH_SHIFT);
-                       snd_soc_write(codec, ASI2_DAC_OUT_CNTL, dacpath);
-                       aic3262->asiCtxt[1].playback_mode = 1;
-
-                       aic3262->asiCtxt[1].bclk_div =
-                               aic3262_divs[i].blck_N;
-               } else {
-                       /* For Recording, Configure the DOUT Pin as per
-                        * ASIContext Structure Settings.
-                        */
-                       adcpath = snd_soc_read(codec, ASI2_DATA_OUT);
-                       adcpath &= ~(AIC3262_ASI_DOUT_MASK);
-                       adcpath |= aic3262->asiCtxt[1].dout_option;
-                       snd_soc_write(codec, ASI2_DATA_OUT, adcpath);
-
-                       aic3262->asiCtxt[1].capture_mode = 1;
-               }
-       break;
-       case 3:
-               regoffset = ASI3_BUS_FMT;
-               /* Since we are configuring ASI3, please check if Playback
-               * is expected. If so, enable ASI3 Inputs to Left and
-               * Right DACs
-               */
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       DBG(KERN_INFO "#%s:ASI3 DAC Inputs enabled.\n",
-                               __func__);
-                       /* Read the DAC Control Register and configure
-                       * it as per the ASIContext Structure Settings.
-                       */
-                       dacpath = snd_soc_read(codec, ASI3_DAC_OUT_CNTL);
-                       dacpath &= ~(AIC3262_ASI_LDAC_PATH_MASK |
-                                       AIC3262_ASI_RDAC_PATH_MASK);
-                       dacpath |= (aic3262->asiCtxt[2].left_dac_output
-                                       << AIC3262_ASI_LDAC_PATH_SHIFT);
-                       dacpath |= (aic3262->asiCtxt[2].right_dac_output
-                               << AIC3262_ASI_RDAC_PATH_SHIFT);
-                       snd_soc_write(codec,
-                               ASI3_DAC_OUT_CNTL, dacpath);
-
-                       aic3262->asiCtxt[2].playback_mode = 1;
-
-                       aic3262->asiCtxt[2].bclk_div =
-                               aic3262_divs[i].blck_N;
-               } else {
-                       /* For Recording, Configure the DOUT Pin as per
-                        * ASIContext Structure Settings.
-                        */
-                       adcpath &= ~(AIC3262_ASI_DOUT_MASK);
-                       adcpath |= aic3262->asiCtxt[2].dout_option;
-                       snd_soc_write(codec, ASI3_DATA_OUT, adcpath);
-
-                       aic3262->asiCtxt[2].capture_mode = 1;
-               }
-       break;
-       default:
-               printk(KERN_ERR "Invalid Dai ID %d in %s",
-                       dai->id, __func__);
-       break;
-       }
-       DBG(KERN_INFO "#%s: Reading Pg %d Reg %d for Bus Format Control.\n",
-               __func__, (regoffset/128),  (regoffset % 128));
-
-       /* Read the correspondig ASI DAI Interface Register */
-       data = snd_soc_read(codec, regoffset);
-
-       data = data & 0xe7;
-
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
-               DBG(KERN_INFO "#%s: Configuring ASI%d S16_LE Fmt..\n",
-                       __func__, dai->id);
-               data = data | 0x00;
-               aic3262->asiCtxt[dai->id - 1].word_len = 16;
-       break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
-               data |= (0x08);
-               aic3262->asiCtxt[dai->id - 1].word_len = 20;
-       break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-               DBG(KERN_INFO "#%s: Configuring ASI%d S24_LE Fmt..\n",
-                       __func__, dai->id);
-               data |= (0x10);
-               aic3262->asiCtxt[dai->id - 1].word_len = 24;
-       break;
-       case SNDRV_PCM_FORMAT_S32_LE:
-               DBG(KERN_INFO "#%s: Configuring ASI%d S32_LE Fmt..\n",
-                       __func__, dai->id);
-               data |= (0x18);
-               aic3262->asiCtxt[dai->id - 1].word_len = 32;
-       break;
-       }
-
-       /* configure the respective Registers for the above configuration */
-       snd_soc_write(codec, regoffset, data);
-
-       for (j = 0; j < NO_FEATURE_REGS; j++) {
-               snd_soc_write(codec,
-                       aic3262_divs[i].codec_specific_regs[j].reg_offset,
-                       aic3262_divs[i].codec_specific_regs[j].reg_val);
-       }
-
-       /* Enable the PLL, MDAC, NDAC, NADC, MADC and BCLK Dividers */
-       aic3262_set_bias_level(codec, SND_SOC_BIAS_ON);
-
-       /* Based on the DAI ID we enable the corresponding pins related to the
-       * ASI Port.
-       */
-       switch (dai->id) {
-       case 1:
-               aic3262_asi1_clk_config(codec, params);
-       break;
-       case 2:
-               aic3262_asi2_clk_config(codec, params);
-       break;
-       case 3:
-               aic3262_asi3_clk_config(codec, params);
-       break;
-       default:
-               printk(KERN_ERR "Invalid Dai ID %d in %s",
-                       dai->id, __func__);
-       break;
-       }
-       /* Depending on the DAI->ID update the local Flags */
-       aic3262->asiCtxt[dai->id - 1].asi_active++;
-       aic3262->asiCtxt[dai->id - 1].sampling_rate = params_rate(params);
-       /* Update the active_count flag */
-       aic3262->active_count++;
-
-       return 0;
-}
-
-/*
-*
-* aic3262_multi_i2s_hw_free
-*
-* This function is used to configure the Codec after the usage is completed.
-* We can use this function to disable the DAC and ADC specific inputs from the
-* individual ASI Ports of the Audio Codec.
-*/
-static void aic3262_multi_i2s_shutdown(struct snd_pcm_substream *substream,
-                       struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->codec;
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-
-       u8 value;
-       u8 dacpath;
-       u8 adcpath;
-       u16 dacregoffset = 0;
-       u16 adcregoffset = 0;
-
-       DBG(KERN_INFO "#%s: ASI%d Port for %s Mode\n",
-               __func__, dai->id,
-               (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-               "Playback" : "Record");
-
-       /* Check if this function was already executed earlier for the same
-       * ASI Port
-       */
-       if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
-               (aic3262->asiCtxt[dai->id - 1].playback_mode == 0)) {
-               DBG(KERN_INFO "#%s: Function Already Executed. Exiting..\n",
-                       __func__);
-               goto err;
-       } else if ((substream->stream != SNDRV_PCM_STREAM_PLAYBACK) &&
-               (aic3262->asiCtxt[dai->id - 1].capture_mode == 0)) {
-               DBG(KERN_INFO "#%s: Function Already Executed. Exiting..\n",
-                       __func__);
-               goto err;
-       }
-
-       switch (dai->id) {
-       case 1:
-               /* In case we are Frame Master on this Interface, Switch off
-               * the Bit Clock Divider and Word Clock Dividers
-               */
-               if (aic3262->asiCtxt[0].master == 1) {
-                       /* Also check if either Playback or Recording is still
-                       * going on this ASI Interface
-                       */
-
-                       value = snd_soc_read(codec, ASI1_BCLK_N);
-                       snd_soc_write(codec, ASI1_BCLK_N, (value & 0x7f));
-
-                       value = snd_soc_read(codec, ASI1_WCLK_N);
-                       snd_soc_write(codec, ASI1_WCLK_N, (value & 0x7f));
-               }
-
-               dacregoffset = ASI1_DAC_OUT_CNTL;
-               adcregoffset = ASI1_ADC_INPUT_CNTL;
-       break;
-       case 2:
-               /* In case we are Frame Master on this Interface, Switch off
-               * the Bit Clock Divider and Word Clock Dividers
-               */
-               if (aic3262->asiCtxt[1].master == 1) {
-                       value = snd_soc_read(codec, ASI2_BCLK_N);
-                       snd_soc_write(codec, ASI2_BCLK_N, (value & 0x7f));
-
-                       value = snd_soc_read(codec, ASI2_WCLK_N);
-                       snd_soc_write(codec, ASI2_WCLK_N, (value & 0x7f));
-               }
-               dacregoffset = ASI2_DAC_OUT_CNTL;
-               adcregoffset = ASI2_ADC_INPUT_CNTL;
-       break;
-       case 3:
-               /* In case we are Frame Master on this Interface, Switch off
-               * the Bit Clock Divider and Word Clock Dividers
-               */
-               if (aic3262->asiCtxt[2].master == 1) {
-                       value = snd_soc_read(codec, ASI3_BCLK_N);
-                       snd_soc_write(codec, ASI3_BCLK_N, (value & 0x7f));
-
-                       value = snd_soc_read(codec, ASI3_WCLK_N);
-                       snd_soc_write(codec, ASI3_WCLK_N, (value & 0x7f));
-               }
-               dacregoffset = ASI3_DAC_OUT_CNTL;
-               adcregoffset = ASI3_ADC_INPUT_CNTL;
-       break;
-       default:
-               printk(KERN_ERR "#%s: Invalid dai id\n", __func__);
-       }
-       /* If this was a Playback Stream Stop, then only
-       * switch off the DAC Inputs
-       */
-       if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
-               (dacregoffset != 0)) {
-               DBG(KERN_INFO "#%s: Disabling Pg %d Reg %d DAC Inputs ..\n",
-                       __func__, (dacregoffset/128), (dacregoffset % 128));
-
-               dacpath = snd_soc_read(codec, dacregoffset);
-               snd_soc_write(codec, dacregoffset, (dacpath & ~(BIT6 | BIT4)));
-
-               aic3262->asiCtxt[dai->id - 1].playback_mode = 0;
-       } else {
-               /* Switch off the ADC Input Control Registers here */
-               DBG(KERN_INFO "#%s: Disabling Pg %d Reg %d for ADC Inputs..\n",
-                       __func__, (adcregoffset/128), (adcregoffset % 128));
-
-               adcpath =  snd_soc_read(codec, adcregoffset);
-               snd_soc_write(codec, adcregoffset,
-                       (adcpath & ~(BIT2 | BIT1 | BIT0)));
-
-               aic3262->asiCtxt[dai->id - 1].capture_mode = 0;
-       }
-
-       /* If we were configured in mono PCM Mode earlier, then reset the
-       * Left Channel and Right Channel offset Registers here.
-       */
-       switch (dai->id) {
-       case 1:
-               if (aic3262->asiCtxt[0].pcm_format == SND_SOC_DAIFMT_DSP_B) {
-                       snd_soc_write(codec, ASI1_LCH_OFFSET, 0x00);
-                       snd_soc_write(codec, ASI1_RCH_OFFSET, 0x00);
-               }
-       break;
-       case 2:
-               if (aic3262->asiCtxt[1].pcm_format == SND_SOC_DAIFMT_DSP_B) {
-                       snd_soc_write(codec, ASI2_LCH_OFFSET, 0x00);
-                       snd_soc_write(codec, ASI2_RCH_OFFSET, 0x00);
-               }
-
-       break;
-       case 3:
-               if (aic3262->asiCtxt[2].pcm_format == SND_SOC_DAIFMT_DSP_B) {
-                       snd_soc_write(codec, ASI3_LCH_OFFSET, 0x00);
-                       snd_soc_write(codec, ASI3_RCH_OFFSET, 0x00);
-               }
-       break;
-       }
-       /* Depending on the DAI->ID update the asi_active Flags */
-       if (aic3262->asiCtxt[dai->id - 1].asi_active) {
-               aic3262->asiCtxt[dai->id - 1].asi_active--;
-
-               /* Update the active_count flag */
-               if (aic3262->active_count)
-                       aic3262->active_count--;
-       }
-err:
-       return;
-}
-
-
-/*
-*
-* 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 |
- *          It is SoC Codec DAI structure which has DAI capabilities viz.,
- *          playback and capture, DAI runtime information viz. state of 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 AIC3262 rates ranges from 8k to 192k
- *          The PCM bit format supported are 16, 20, 24 and 32 bits
+ *     The AIC3262 rates ranges from 8k to 192k
+ *     The PCM bit format supported are 16, 20, 24 and 32 bits
  *----------------------------------------------------------------------------
  */
-struct snd_soc_dai_ops aic3262_multi_i2s_dai_ops = {
-       .hw_params      = aic3262_multi_i2s_hw_params,
-       .digital_mute   = aic3262_multi_i2s_mute,
-       .set_fmt        = aic3262_multi_i2s_set_dai_fmt,
-       .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,
+struct snd_soc_dai_ops aic3262_asi1_dai_ops = {
+       .hw_params = aic3262_hw_params,
+       .digital_mute = aic3262_mute,
+       .set_sysclk = aic3262_set_dai_sysclk,
+       .set_fmt = aic3262_set_dai_fmt,
+       .set_pll = aic3262_dai_set_pll,
 };
 
-
-static struct snd_soc_dai_driver tlv320aic3262_dai[] = {
-/* AIC3262 ASI1 DAI */
-{
-       .name = "aic3262-asi1",
-       .id = 1,
-       .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 = "ASI1 Capture",
-               .channels_min = 1,
-               .channels_max = 2,
-               .rates = AIC3262_RATES,
-               .formats = AIC3262_FORMATS},
-       .ops = &aic3262_multi_i2s_dai_ops,
-},
-/* AIC3262 ASI2 DAI */
-{
-       .name = "aic3262-asi2",
-       .id = 2,
-       .playback = {
-               .stream_name = "ASI2 Playback",
-               .channels_min = 1,
-               .channels_max = 2,
-               .rates = AIC3262_RATES,
-               .formats = AIC3262_FORMATS,},
-       .capture = {
-               .stream_name = "ASI2 Capture",
-               .channels_min = 1,
-               .channels_max = 2,
-               .rates = AIC3262_RATES,
-               .formats = AIC3262_FORMATS,},
-       .ops = &aic3262_multi_i2s_dai_ops,
-
-},
-/* AIC3262 ASI3 DAI  */
-{
-       .name = "aic3262-asi3",
-       .id = 3,
-       .playback = {
-               .stream_name = "ASI3 Playback",
-               .channels_min = 1,
-               .channels_max = 2,
-               .rates = AIC3262_RATES,
-               .formats = AIC3262_FORMATS, },
-       .capture = {
-               .stream_name = "ASI3 Capture",
-               .channels_min = 1,
-               .channels_max = 2,
-               .rates = AIC3262_RATES,
-               .formats = AIC3262_FORMATS, },
-       .ops = &aic3262_multi_i2s_dai_ops,
-
-},
+struct snd_soc_dai_ops aic3262_asi2_dai_ops = {
+       .hw_params = aic3262_hw_params,
+       .digital_mute = aic3262_mute,
+       .set_sysclk = aic3262_set_dai_sysclk,
+       .set_fmt = aic3262_set_dai_fmt,
+       .set_pll = aic3262_dai_set_pll,
 };
 
-/*
- *****************************************************************************
- * Initializations
- *****************************************************************************
- */
-/*
- * AIC3262 register cache
- * We are caching the registers here.
- * There is no point in caching the reset register.
- *
- * NOTE: In AIC3262, there are 127 registers supported in both page0 and page1
- *       The following table contains the page0 and page 1 and page 3
- *       registers values.
- */
-static const u8 aic3262_reg[AIC3262_CACHEREGNUM] = {
-       0x00, 0x00, 0x10, 0x00, /* 0 */
-       0x03, 0x40, 0x11, 0x08, /* 4 */
-       0x00, 0x00, 0x00, 0x82, /* 8 */
-       0x88, 0x00, 0x80, 0x02, /* 12 */
-       0x00, 0x08, 0x01, 0x01, /* 16 */
-       0x80, 0x01, 0x00, 0x04, /* 20 */
-       0x00, 0x00, 0x01, 0x00, /* 24 */
-       0x00, 0x00, 0x01, 0x00, /* 28 */
-       0x00, 0x00, 0x00, 0x00, /* 32 */
-       0x00, 0x00, 0x00, 0x00, /* 36 */
-       0x00, 0x00, 0x00, 0x00, /* 40 */
-       0x00, 0x00, 0x00, 0x00, /* 44 */
-       0x00, 0x00, 0x00, 0x00, /* 48 */
-       0x00, 0x42, 0x02, 0x02, /* 52 */
-       0x42, 0x02, 0x02, 0x02, /* 56 */
-       0x00, 0x00, 0x00, 0x01, /* 60 */
-       0x01, 0x00, 0x14, 0x00, /* 64 */
-       0x0C, 0x00, 0x00, 0x00, /* 68 */
-       0x00, 0x00, 0x00, 0xEE, /* 72 */
-       0x10, 0xD8, 0x10, 0xD8, /* 76 */
-       0x00, 0x00, 0x88, 0x00, /* 80 */
-       0x00, 0x00, 0x00, 0x00, /* 84 */
-       0x7F, 0x00, 0x00, 0x00, /* 88 */
-       0x00, 0x00, 0x00, 0x00, /* 92 */
-       0x7F, 0x00, 0x00, 0x00, /* 96 */
-       0x00, 0x00, 0x00, 0x00, /* 100 */
-       0x00, 0x00, 0x00, 0x00, /* 104 */
-       0x00, 0x00, 0x00, 0x00, /* 108 */
-       0x00, 0x00, 0x00, 0x00, /* 112 */
-       0x00, 0x00, 0x00, 0x00, /* 116 */
-       0x00, 0x00, 0x00, 0x00, /* 120 */
-       0x00, 0x00, 0x00, 0x00, /* 124 - PAGE0 Registers(127) ends here */
-       0x01, 0x00, 0x08, 0x00, /* 128, PAGE1-0 */
-       0x00, 0x00, 0x00, 0x00, /* 132, PAGE1-4 */
-       0x00, 0x00, 0x00, 0x10, /* 136, PAGE1-8 */
-       0x00, 0x00, 0x00, 0x00, /* 140, PAGE1-12 */
-       0x40, 0x40, 0x40, 0x40, /* 144, PAGE1-16 */
-       0x00, 0x00, 0x00, 0x00, /* 148, PAGE1-20 */
-       0x00, 0x00, 0x00, 0x00, /* 152, PAGE1-24 */
-       0x00, 0x00, 0x00, 0x00, /* 156, PAGE1-28 */
-       0x00, 0x00, 0x00, 0x00, /* 160, PAGE1-32 */
-       0x00, 0x00, 0x00, 0x00, /* 164, PAGE1-36 */
-       0x00, 0x00, 0x00, 0x00, /* 168, PAGE1-40 */
-       0x00, 0x00, 0x00, 0x00, /* 172, PAGE1-44 */
-       0x00, 0x00, 0x00, 0x00, /* 176, PAGE1-48 */
-       0x00, 0x00, 0x00, 0x00, /* 180, PAGE1-52 */
-       0x00, 0x00, 0x00, 0x80, /* 184, PAGE1-56 */
-       0x80, 0x00, 0x00, 0x00, /* 188, PAGE1-60 */
-       0x00, 0x00, 0x00, 0x00, /* 192, PAGE1-64 */
-       0x00, 0x00, 0x00, 0x00, /* 196, PAGE1-68 */
-       0x00, 0x00, 0x00, 0x00, /* 200, PAGE1-72 */
-       0x00, 0x00, 0x00, 0x00, /* 204, PAGE1-76 */
-       0x00, 0x00, 0x00, 0x00, /* 208, PAGE1-80 */
-       0x00, 0x00, 0x00, 0x00, /* 212, PAGE1-84 */
-       0x00, 0x00, 0x00, 0x00, /* 216, PAGE1-88 */
-       0x00, 0x00, 0x00, 0x00, /* 220, PAGE1-92 */
-       0x00, 0x00, 0x00, 0x00, /* 224, PAGE1-96 */
-       0x00, 0x00, 0x00, 0x00, /* 228, PAGE1-100 */
-       0x00, 0x00, 0x00, 0x00, /* 232, PAGE1-104 */
-       0x00, 0x00, 0x00, 0x00, /* 236, PAGE1-108 */
-       0x00, 0x00, 0x00, 0x00, /* 240, PAGE1-112 */
-       0x00, 0x00, 0x00, 0x00, /* 244, PAGE1-116 */
-       0x00, 0x00, 0x00, 0x00, /* 248, PAGE1-120 */
-       0x00, 0x00, 0x00, 0x00, /* 252, PAGE1-124 Page 1 Registers Ends Here */
-       0x00, 0x00, 0x00, 0x00, /* 256, PAGE2-0  */
-       0x00, 0x00, 0x00, 0x00, /* 260, PAGE2-4  */
-       0x00, 0x00, 0x00, 0x00, /* 264, PAGE2-8  */
-       0x00, 0x00, 0x00, 0x00, /* 268, PAGE2-12 */
-       0x00, 0x00, 0x00, 0x00, /* 272, PAGE2-16 */
-       0x00, 0x00, 0x00, 0x00, /* 276, PAGE2-20 */
-       0x00, 0x00, 0x00, 0x00, /* 280, PAGE2-24 */
-       0x00, 0x00, 0x00, 0x00, /* 284, PAGE2-28 */
-       0x00, 0x00, 0x00, 0x00, /* 288, PAGE2-32 */
-       0x00, 0x00, 0x00, 0x00, /* 292, PAGE2-36 */
-       0x00, 0x00, 0x00, 0x00, /* 296, PAGE2-40 */
-       0x00, 0x00, 0x00, 0x00, /* 300, PAGE2-44 */
-       0x00, 0x00, 0x00, 0x00, /* 304, PAGE2-48 */
-       0x00, 0x00, 0x00, 0x00, /* 308, PAGE2-52 */
-       0x00, 0x00, 0x00, 0x00, /* 312, PAGE2-56 */
-       0x00, 0x00, 0x00, 0x00, /* 316, PAGE2-60 */
-       0x00, 0x00, 0x00, 0x00, /* 320, PAGE2-64 */
-       0x00, 0x00, 0x00, 0x00, /* 324, PAGE2-68 */
-       0x00, 0x00, 0x00, 0x00, /* 328, PAGE2-72 */
-       0x00, 0x00, 0x00, 0x00, /* 332, PAGE2-76 */
-       0x00, 0x00, 0x00, 0x00, /* 336, PAGE2-80 */
-       0x00, 0x00, 0x00, 0x00, /* 340, PAGE2-84 */
-       0x00, 0x00, 0x00, 0x00, /* 344, PAGE2-88 */
-       0x00, 0x00, 0x00, 0x00, /* 348, PAGE2-92 */
-       0x00, 0x00, 0x00, 0x00, /* 352, PAGE2-96 */
-       0x00, 0x00, 0x00, 0x00, /* 356, PAGE2-100 */
-       0x00, 0x00, 0x00, 0x00, /* 360, PAGE2-104 */
-       0x00, 0x00, 0x00, 0x00, /* 364, PAGE2-108 */
-       0x00, 0x00, 0x00, 0x00, /* 368, PAGE2-112*/
-       0x00, 0x00, 0x00, 0x00, /* 372, PAGE2-116*/
-       0x00, 0x00, 0x00, 0x00, /* 376, PAGE2-120*/
-       0x00, 0x00, 0x00, 0x00, /* 380, PAGE2-124 Page 2 Registers Ends Here */
-       0x00, 0x00, 0x00, 0x00, /* 384, PAGE3-0  */
-       0x00, 0x00, 0x00, 0x00, /* 388, PAGE3-4  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-8  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-12  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-16  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-20  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-24  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-28  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-32  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-36  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-40  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-44  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-48  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-52  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-56  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-60  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-64  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE3-68  */
-       0x00, 0x00, 0x00, 0x00, /* 328, PAGE3-72 */
-       0x00, 0x00, 0x00, 0x00, /* 332, PAGE3-76 */
-       0x00, 0x00, 0x00, 0x00, /* 336, PAGE3-80 */
-       0x00, 0x00, 0x00, 0x00, /* 340, PAGE3-84 */
-       0x00, 0x00, 0x00, 0x00, /* 344, PAGE3-88 */
-       0x00, 0x00, 0x00, 0x00, /* 348, PAGE3-92 */
-       0x00, 0x00, 0x00, 0x00, /* 352, PAGE3-96 */
-       0x00, 0x00, 0x00, 0x00, /* 356, PAGE3-100 */
-       0x00, 0x00, 0x00, 0x00, /* 360, PAGE3-104 */
-       0x00, 0x00, 0x00, 0x00, /* 364, PAGE3-108 */
-       0x00, 0x00, 0x00, 0x00, /* 368, PAGE3-112*/
-       0x00, 0x00, 0x00, 0x00, /* 372, PAGE3-116*/
-       0x00, 0x00, 0x00, 0x00, /* 376, PAGE3-120*/
-       0x00, 0x00, 0x00, 0x00, /* 380, PAGE3-124 Page 3 Registers Ends Here */
-       0x00, 0x00, 0x00, 0x00, /* 384, PAGE4-0  */
-       0x00, 0x00, 0x00, 0x00, /* 388, PAGE4-4  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-8  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-12  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-16  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-20  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-24  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-28  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-32  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-36  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-40  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-44  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-48  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-52  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-56  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-60  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-64  */
-       0x00, 0x00, 0x00, 0x00, /* 392, PAGE4-68  */
-       0x00, 0x00, 0x00, 0x00, /* 328, PAGE4-72 */
-       0x00, 0x00, 0x00, 0x00, /* 332, PAGE4-76 */
-       0x00, 0x00, 0x00, 0x00, /* 336, PAGE4-80 */
-       0x00, 0x00, 0x00, 0x00, /* 340, PAGE4-84 */
-       0x00, 0x00, 0x00, 0x00, /* 344, PAGE4-88 */
-       0x00, 0x00, 0x00, 0x00, /* 348, PAGE4-92 */
-       0x00, 0x00, 0x00, 0x00, /* 352, PAGE4-96 */
-       0x00, 0x00, 0x00, 0x00, /* 356, PAGE4-100 */
-       0x00, 0x00, 0x00, 0x00, /* 360, PAGE4-104 */
-       0x00, 0x00, 0x00, 0x00, /* 364, PAGE4-108 */
-       0x00, 0x00, 0x00, 0x00, /* 368, PAGE4-112*/
-       0x00, 0x00, 0x00, 0x00, /* 372, PAGE4-116*/
-       0x00, 0x00, 0x00, 0x00, /* 376, PAGE4-120*/
-       0x00, 0x00, 0x00, 0x00, /* 380, PAGE4-124 Page 2 Registers Ends Here */
-
+struct snd_soc_dai_ops aic3262_asi3_dai_ops = {
+       .hw_params = aic3262_hw_params,
+       .digital_mute = aic3262_mute,
+       .set_sysclk = aic3262_set_dai_sysclk,
+       .set_fmt = aic3262_set_dai_fmt,
+       .set_pll = aic3262_dai_set_pll,
 };
 
-/*
- *------------------------------------------------------------------------------
- * aic3262 initialization data
- * This structure initialization contains the initialization required for
- * AIC326x.
- * These registers values (reg_val) are written into the respective AIC3262
- * register offset (reg_offset) to  initialize AIC326x.
- * These values are used in aic3262_init() function only.
- *------------------------------------------------------------------------------
- */
-static const struct aic3262_configs aic3262_reg_init[] = {
-       /* CLOCKING */
-
-       {0, RESET_REG, 1},
-       {0, RESET_REG, 0},
-
-       {0, PASI_DAC_DP_SETUP,  0xc0},  /*DAC */
-       {0, DAC_MVOL_CONF,  0x00},      /*DAC un-muted*/
-       /* set default volumes */
-       {0, DAC_LVOL, 0x01},
-       {0, DAC_RVOL, 0x01},
-       {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},
-       {0, REC_AMP_CNTL_R5, 0x82},
-       {0, RAMPR_VOL, 20},
-       {0, RAMP_CNTL_R1, 70},
-       {0, RAMP_CNTL_R2, 70},
-
-       /* DRC Defaults */
-       {0, DRC_CNTL_R1, 0x6c},
-       {0, DRC_CNTL_R2, 16},
-
-       /* DEPOP SETTINGS */
-       {0, HP_DEPOP, 0x14},
-       {0, RECV_DEPOP, 0x14},
-
-       {0, POWER_CONF, 0x00},   /* Disconnecting AVDD-DVD weak link*/
-       {0, REF_PWR_DLY, 0x01},
-       {0, CM_REG, 0x00},      /*CM - default*/
-       {0, LDAC_PTM, 0},       /*LDAC_PTM - default*/
-       {0, RDAC_PTM, 0},       /*RDAC_PTM - default*/
-       {0, HP_CTL, 0x30},      /*HP output percentage - at 75%*/
-       {0, LADC_VOL, 0x01},    /*LADC volume*/
-       {0, RADC_VOL, 0x01},    /*RADC volume*/
-
-       {0, DAC_ADC_CLKIN_REG, 0x33},   /*DAC ADC CLKIN*/
-       {0, PLL_CLKIN_REG, 0x00},       /*PLL CLKIN*/
-       {0, PLL_PR_POW_REG, 0x11},      /*PLL Power=0-down, P=1, R=1 vals*/
-       {0, 0x3d, 1},
-
-       {0, LMIC_PGA_PIN, 0x0}, /*IN1_L select - - 10k -LMICPGA_P*/
-       {0, LMIC_PGA_MIN, 0x40},        /*CM to LMICPGA-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, 0x0}, /*ladc, radc ON , SOFT STEP disabled*/
-       {0, ADC_FINE_GAIN, 0x00},   /*ladc - unmute, radc - unmute*/
-       {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, 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, 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,HEADSET_TUNING1_REG,0x7f},
-       {0, INT1_CNTL, 0x40},
-       /*{0, TIMER_REG, 0x8c},*/
-       {0, INT_FMT, 0x40},
-       {0, GPIO1_IO_CNTL, 0x14},
-       {0, HP_DETECT, 0x96},
-
-#if defined(CONFIG_MINI_DSP)
-       {0, 60, 0},
-       {0, 61, 0},
-       /* Added the below set of values after consulting the miniDSP
-        * Program Section Array
-        */
-       {0, MINIDSP_ACCESS_CTRL, 0x00},
-#endif
-
+struct snd_soc_dai_driver aic326x_dai_driver[] = {
+       {
+        .name = "aic326x-asi1",
+        .playback = {
+                     .stream_name = "ASI1 Playback",
+                     .channels_min = 1,
+                     .channels_max = 2,
+                     .rates = AIC3262_RATES,
+                     .formats = AIC3262_FORMATS,
+                     },
+        .capture = {
+                    .stream_name = "ASI1 Capture",
+                    .channels_min = 1,
+                    .channels_max = 2,
+                    .rates = AIC3262_RATES,
+                    .formats = AIC3262_FORMATS,
+                    },
+        .ops = &aic3262_asi1_dai_ops,
+        },
+       {
+        .name = "aic326x-asi2",
+        .playback = {
+                     .stream_name = "ASI2 Playback",
+                     .channels_min = 1,
+                     .channels_max = 2,
+                     .rates = AIC3262_RATES,
+                     .formats = AIC3262_FORMATS,
+                     },
+        .capture = {
+                    .stream_name = "ASI2 Capture",
+                    .channels_min = 1,
+                    .channels_max = 2,
+                    .rates = AIC3262_RATES,
+                    .formats = AIC3262_FORMATS,
+                    },
+        .ops = &aic3262_asi2_dai_ops,
+        },
+       {
+        .name = "aic326x-asi3",
+        .playback = {
+                     .stream_name = "ASI3 Playback",
+                     .channels_min = 1,
+                     .channels_max = 2,
+                     .rates = AIC3262_RATES,
+                     .formats = AIC3262_FORMATS,
+                     },
+        .capture = {
+                    .stream_name = "ASI3 Capture",
+                    .channels_min = 1,
+                    .channels_max = 2,
+                    .rates = AIC3262_RATES,
+                    .formats = AIC3262_FORMATS,
+                    },
+        .ops = &aic3262_asi3_dai_ops,
+        },
 
 };
 
-static int reg_init_size =
-       sizeof(aic3262_reg_init) / sizeof(struct aic3262_configs);
 
 static const unsigned int adc_ma_tlv[] = {
-TLV_DB_RANGE_HEAD(4),
+       TLV_DB_RANGE_HEAD(4),
        0, 29, TLV_DB_SCALE_ITEM(-1450, 500, 0),
        30, 35, TLV_DB_SCALE_ITEM(-2060, 1000, 0),
        36, 38, TLV_DB_SCALE_ITEM(-2660, 2000, 0),
        39, 40, TLV_DB_SCALE_ITEM(-3610, 5000, 0),
 };
-static const DECLARE_TLV_DB_SCALE(lo_hp_tlv, -7830, 50, 0);
 
+static const DECLARE_TLV_DB_SCALE(lo_hp_tlv, -7830, 50, 0);
 static const struct snd_kcontrol_new mal_pga_mixer_controls[] = {
-       SOC_DAPM_SINGLE("IN1L Switch", MA_CNTL, 5, 1, 0),
-       SOC_DAPM_SINGLE_TLV("Left MicPGA Volume", LADC_PGA_MAL_VOL, 0,
-                                                       0x3f, 1, adc_ma_tlv),
-
+       SOC_DAPM_SINGLE("IN1L Switch", AIC3262_MA_CNTL, 5, 1, 0),
+       SOC_DAPM_SINGLE_TLV("Left MicPGA Volume", AIC3262_LADC_PGA_MAL_VOL,
+                               0, 0x3f, 1, adc_ma_tlv),
 };
 
 static const struct snd_kcontrol_new mar_pga_mixer_controls[] = {
-       SOC_DAPM_SINGLE("IN1R Switch", MA_CNTL, 4, 1, 0),
-       SOC_DAPM_SINGLE_TLV("Right MicPGA Volume", RADC_PGA_MAR_VOL, 0,
-                                                       0x3f, 1, adc_ma_tlv),
+       SOC_DAPM_SINGLE("IN1R Switch", AIC3262_MA_CNTL, 4, 1, 0),
+       SOC_DAPM_SINGLE_TLV("Right MicPGA Volume", AIC3262_RADC_PGA_MAR_VOL,
+                               0, 0x3f, 1, adc_ma_tlv),
 };
 
 /* Left HPL Mixer */
 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, 0, lo_hp_tlv),
+       SOC_DAPM_SINGLE("MAL Switch", AIC3262_HP_AMP_CNTL_R1, 7, 1,
+                       0),
+       SOC_DAPM_SINGLE("LDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+                       5, 1, 0),
+       SOC_DAPM_SINGLE_TLV("LOL-B1 Volume",
+                               AIC3262_HP_AMP_CNTL_R2, 0, 0x7f, 1, 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, 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),
+       SOC_DAPM_SINGLE_TLV("LOR-B1 Volume",
+                               AIC3262_HP_AMP_CNTL_R3, 0, 0x7f, 1, lo_hp_tlv),
+       SOC_DAPM_SINGLE("LDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+                       2, 1, 0),
+       SOC_DAPM_SINGLE("RDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+                       4, 1, 0),
+       SOC_DAPM_SINGLE("MAR Switch", AIC3262_HP_AMP_CNTL_R1,
+                       6, 1, 0),
 };
 
 /* Left LOL Mixer */
 static const struct snd_kcontrol_new lol_output_mixer_controls[] = {
-       SOC_DAPM_SINGLE("MAL Switch", LINE_AMP_CNTL_R2, 7, 1, 0),
-       SOC_DAPM_SINGLE("IN1L-B Switch", LINE_AMP_CNTL_R2, 3, 1,0),
-       SOC_DAPM_SINGLE("LDAC Switch", LINE_AMP_CNTL_R1, 7, 1, 0),
-       SOC_DAPM_SINGLE("RDAC Switch", LINE_AMP_CNTL_R1, 5, 1, 0),
+       SOC_DAPM_SINGLE("MAL Switch", AIC3262_LINE_AMP_CNTL_R2,
+                       7, 1, 0),
+       SOC_DAPM_SINGLE("IN1L-B Switch", AIC3262_LINE_AMP_CNTL_R2,
+                       3, 1, 0),
+       SOC_DAPM_SINGLE("LDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+                       7, 1, 0),
+       SOC_DAPM_SINGLE("RDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+                       5, 1, 0),
 };
 
 /* Right LOR Mixer */
 static const struct snd_kcontrol_new lor_output_mixer_controls[] = {
-       SOC_DAPM_SINGLE("LOL Switch", LINE_AMP_CNTL_R1, 2, 1, 0),
-       SOC_DAPM_SINGLE("RDAC Switch", LINE_AMP_CNTL_R1, 6, 1, 0),
-       SOC_DAPM_SINGLE("MAR Switch", LINE_AMP_CNTL_R2, 6, 1, 0),
-       SOC_DAPM_SINGLE("IN1R-B Switch", LINE_AMP_CNTL_R2, 0, 1,0),
+       SOC_DAPM_SINGLE("LOL Switch", AIC3262_LINE_AMP_CNTL_R1,
+                       2, 1, 0),
+       SOC_DAPM_SINGLE("RDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+                       6, 1, 0),
+       SOC_DAPM_SINGLE("MAR Switch", AIC3262_LINE_AMP_CNTL_R2,
+                       6, 1, 0),
+       SOC_DAPM_SINGLE("IN1R-B Switch", AIC3262_LINE_AMP_CNTL_R2,
+                       0, 1, 0),
 };
 
 /* Left SPKL Mixer */
 static const struct snd_kcontrol_new spkl_output_mixer_controls[] = {
-       SOC_DAPM_SINGLE("MAL Switch", SPK_AMP_CNTL_R1, 7, 1, 0),
-       SOC_DAPM_SINGLE_TLV("LOL Volume", SPK_AMP_CNTL_R2, 0, 0x7f,0,
-                                                               lo_hp_tlv),
-       SOC_DAPM_SINGLE("SPR_IN Switch", SPK_AMP_CNTL_R1, 2, 1, 0),
+       SOC_DAPM_SINGLE("MAL Switch", AIC3262_SPK_AMP_CNTL_R1,
+                       7, 1, 0),
+       SOC_DAPM_SINGLE_TLV("LOL Volume",
+                               AIC3262_SPK_AMP_CNTL_R2, 0, 0x7f, 1, lo_hp_tlv),
+       SOC_DAPM_SINGLE("SPR_IN Switch", AIC3262_SPK_AMP_CNTL_R1, 2, 1, 0),
 };
 
 /* Right SPKR Mixer */
 static const struct snd_kcontrol_new spkr_output_mixer_controls[] = {
-       SOC_DAPM_SINGLE_TLV("LOR Volume", SPK_AMP_CNTL_R3, 0, 0x7f, 0,
-                                                               lo_hp_tlv),
-       SOC_DAPM_SINGLE("MAR Switch", SPK_AMP_CNTL_R1, 6, 1, 0),
+       SOC_DAPM_SINGLE_TLV("LOR Volume",
+                               AIC3262_SPK_AMP_CNTL_R3, 0, 0x7f, 1, lo_hp_tlv),
+       SOC_DAPM_SINGLE("MAR Switch",
+                       AIC3262_SPK_AMP_CNTL_R1, 6, 1, 0),
 };
 
 /* REC Mixer */
 static const struct snd_kcontrol_new rec_output_mixer_controls[] = {
-       SOC_DAPM_SINGLE_TLV("LOL-B2 Volume", RAMP_CNTL_R1, 0, 0x7f,0,
-                                                       lo_hp_tlv),
-       SOC_DAPM_SINGLE_TLV("IN1L Volume", IN1L_SEL_RM, 0, 0x7f, 1, lo_hp_tlv),
-       SOC_DAPM_SINGLE_TLV("IN1R Volume", IN1R_SEL_RM, 0, 0x7f, 1, lo_hp_tlv),
-       SOC_DAPM_SINGLE_TLV("LOR-B2 Volume", RAMP_CNTL_R2, 0,0x7f, 0,lo_hp_tlv),
+       SOC_DAPM_SINGLE_TLV("LOL-B2 Volume",
+                               AIC3262_RAMP_CNTL_R1, 0, 0x7f, 1, lo_hp_tlv),
+       SOC_DAPM_SINGLE_TLV("IN1L Volume",
+                               AIC3262_IN1L_SEL_RM, 0, 0x7f, 1, lo_hp_tlv),
+       SOC_DAPM_SINGLE_TLV("IN1R Volume",
+                               AIC3262_IN1R_SEL_RM, 0, 0x7f, 1, lo_hp_tlv),
+       SOC_DAPM_SINGLE_TLV("LOR-B2 Volume",
+                               AIC3262_RAMP_CNTL_R2, 0, 0x7f, 1, lo_hp_tlv),
 };
 
 /* Left Input Mixer */
 static const struct snd_kcontrol_new left_input_mixer_controls[] = {
-       SOC_DAPM_SINGLE("IN1L Switch", LMIC_PGA_PIN, 6, 1, 0),
-       SOC_DAPM_SINGLE("IN2L Switch", LMIC_PGA_PIN, 4, 1, 0),
-       SOC_DAPM_SINGLE("IN3L Switch", LMIC_PGA_PIN, 2, 1, 0),
-       SOC_DAPM_SINGLE("IN4L Switch", LMIC_PGA_PM_IN4, 5, 1, 0),
-       SOC_DAPM_SINGLE("IN1R Switch", LMIC_PGA_PIN, 0, 1, 0),
-       SOC_DAPM_SINGLE("IN2R Switch", LMIC_PGA_MIN, 4, 1, 0),
-       SOC_DAPM_SINGLE("IN3R Switch", LMIC_PGA_MIN, 2, 1, 0),
-       SOC_DAPM_SINGLE("IN4R Switch", LMIC_PGA_PM_IN4, 4, 1, 0),
-       SOC_DAPM_SINGLE("CM2L Switch", LMIC_PGA_MIN, 0, 1, 0),
-       SOC_DAPM_SINGLE("CM1L Switch", LMIC_PGA_MIN, 6, 1, 0),
+       SOC_DAPM_SINGLE("IN1L Switch", AIC3262_LMIC_PGA_PIN,
+                       6, 3, 0),
+       SOC_DAPM_SINGLE("IN2L Switch", AIC3262_LMIC_PGA_PIN,
+                       4, 3, 0),
+       SOC_DAPM_SINGLE("IN3L Switch", AIC3262_LMIC_PGA_PIN,
+                       2, 3, 0),
+       SOC_DAPM_SINGLE("IN4L Switch", AIC3262_LMIC_PGA_PM_IN4,
+                       5, 1, 0),
+       SOC_DAPM_SINGLE("IN1R Switch", AIC3262_LMIC_PGA_PIN,
+                       0, 3, 0),
+       SOC_DAPM_SINGLE("IN2R Switch", AIC3262_LMIC_PGA_MIN,
+                       4, 3, 0),
+       SOC_DAPM_SINGLE("IN3R Switch", AIC3262_LMIC_PGA_MIN,
+                       2, 3, 0),
+       SOC_DAPM_SINGLE("IN4R Switch", AIC3262_LMIC_PGA_PM_IN4,
+                       4, 1, 0),
+       SOC_DAPM_SINGLE("CM2L Switch", AIC3262_LMIC_PGA_MIN,
+                       0, 3, 0),
+       SOC_DAPM_SINGLE("CM1L Switch", AIC3262_LMIC_PGA_MIN,
+                       6, 3, 0),
 };
 
 /* Right Input Mixer */
 static const struct snd_kcontrol_new right_input_mixer_controls[] = {
-       SOC_DAPM_SINGLE("IN1R Switch", RMIC_PGA_PIN, 6, 1, 0),
-       SOC_DAPM_SINGLE("IN2R Switch", RMIC_PGA_PIN, 4, 1, 0),
-       SOC_DAPM_SINGLE("IN3R Switch", RMIC_PGA_PIN, 2, 1, 0),
-       SOC_DAPM_SINGLE("IN4R Switch", RMIC_PGA_PM_IN4, 5, 1, 0),
-       SOC_DAPM_SINGLE("IN2L Switch", RMIC_PGA_PIN, 0, 1, 0),
-       SOC_DAPM_SINGLE("IN1L Switch", RMIC_PGA_MIN, 4, 1, 0),
-       SOC_DAPM_SINGLE("IN3L Switch", RMIC_PGA_MIN, 2, 1, 0),
-       SOC_DAPM_SINGLE("IN4L Switch", RMIC_PGA_PM_IN4, 4, 1, 0),
-       SOC_DAPM_SINGLE("CM1R Switch", RMIC_PGA_MIN, 6, 1, 0),
-       SOC_DAPM_SINGLE("CM2R Switch", RMIC_PGA_MIN, 0, 1, 0),
+       SOC_DAPM_SINGLE("IN1R Switch", AIC3262_RMIC_PGA_PIN,
+                       6, 3, 0),
+       SOC_DAPM_SINGLE("IN2R Switch", AIC3262_RMIC_PGA_PIN,
+                       4, 3, 0),
+       SOC_DAPM_SINGLE("IN3R Switch", AIC3262_RMIC_PGA_PIN,
+                       2, 3, 0),
+       SOC_DAPM_SINGLE("IN4R Switch", AIC3262_RMIC_PGA_PM_IN4,
+                       5, 1, 0),
+       SOC_DAPM_SINGLE("IN2L Switch", AIC3262_RMIC_PGA_PIN,
+                       0, 3, 0),
+       SOC_DAPM_SINGLE("IN1L Switch", AIC3262_RMIC_PGA_MIN,
+                       4, 3, 0),
+       SOC_DAPM_SINGLE("IN3L Switch", AIC3262_RMIC_PGA_MIN,
+                       2, 3, 0),
+       SOC_DAPM_SINGLE("IN4L Switch", AIC3262_RMIC_PGA_PM_IN4,
+                       4, 1, 0),
+       SOC_DAPM_SINGLE("CM1R Switch", AIC3262_RMIC_PGA_MIN,
+                       6, 3, 0),
+       SOC_DAPM_SINGLE("CM2R Switch", AIC3262_RMIC_PGA_MIN,
+                       0, 3, 0),
 };
 
-
-static const char *asi1lin_text[] = {
-       "Off", "ASI1 Left In","ASI1 Right In","ASI1 MonoMix In"
+static const char * const asi1lin_text[] = {
+       "Off", "ASI1 Left In", "ASI1 Right In", "ASI1 MonoMix In"
 };
 
-SOC_ENUM_SINGLE_DECL(asi1lin_enum, ASI1_DAC_OUT_CNTL, 6, asi1lin_text);
+SOC_ENUM_SINGLE_DECL(asi1lin_enum, AIC3262_ASI1_DAC_OUT_CNTL, 6, asi1lin_text);
 
 static const struct snd_kcontrol_new asi1lin_control =
-       SOC_DAPM_ENUM("ASI1LIN Route", asi1lin_enum);
-
+SOC_DAPM_ENUM("ASI1LIN Route", asi1lin_enum);
 
-static const char *asi1rin_text[] = {
-       "Off", "ASI1 Right In","ASI1 Left In","ASI1 MonoMix In"
+static const char * const asi1rin_text[] = {
+       "Off", "ASI1 Right In", "ASI1 Left In", "ASI1 MonoMix In"
 };
 
-SOC_ENUM_SINGLE_DECL(asi1rin_enum, ASI1_DAC_OUT_CNTL, 4, asi1rin_text);
+SOC_ENUM_SINGLE_DECL(asi1rin_enum, AIC3262_ASI1_DAC_OUT_CNTL, 4, asi1rin_text);
 
 static const struct snd_kcontrol_new asi1rin_control =
-       SOC_DAPM_ENUM("ASI1RIN Route", asi1rin_enum);
+SOC_DAPM_ENUM("ASI1RIN Route", asi1rin_enum);
 
-static const char *asi2lin_text[] = {
-       "Off", "ASI2 Left In","ASI2 Right In","ASI2 MonoMix In"
+static const char * const asi2lin_text[] = {
+       "Off", "ASI2 Left In", "ASI2 Right In", "ASI2 MonoMix In"
 };
 
-SOC_ENUM_SINGLE_DECL(asi2lin_enum, ASI2_DAC_OUT_CNTL, 6, asi2lin_text);
+SOC_ENUM_SINGLE_DECL(asi2lin_enum, AIC3262_ASI2_DAC_OUT_CNTL, 6, asi2lin_text);
+
 static const struct snd_kcontrol_new asi2lin_control =
-       SOC_DAPM_ENUM("ASI2LIN Route", asi2lin_enum);
+SOC_DAPM_ENUM("ASI2LIN Route", asi2lin_enum);
 
-static const char *asi2rin_text[] = {
-       "Off", "ASI2 Right In","ASI2 Left In","ASI2 MonoMix In"
+static const char * const asi2rin_text[] = {
+       "Off", "ASI2 Right In", "ASI2 Left In", "ASI2 MonoMix In"
 };
 
-
-SOC_ENUM_SINGLE_DECL(asi2rin_enum, ASI2_DAC_OUT_CNTL, 4, asi2rin_text);
+SOC_ENUM_SINGLE_DECL(asi2rin_enum, AIC3262_ASI2_DAC_OUT_CNTL, 4, asi2rin_text);
 
 static const struct snd_kcontrol_new asi2rin_control =
-       SOC_DAPM_ENUM("ASI2RIN Route", asi2rin_enum);
+SOC_DAPM_ENUM("ASI2RIN Route", asi2rin_enum);
 
-static const char *asi3lin_text[] = {
-       "Off", "ASI3 Left In","ASI3 Right In","ASI3 MonoMix In"
+static const char * const asi3lin_text[] = {
+       "Off", "ASI3 Left In", "ASI3 Right In", "ASI3 MonoMix In"
 };
 
+SOC_ENUM_SINGLE_DECL(asi3lin_enum, AIC3262_ASI3_DAC_OUT_CNTL, 6, asi3lin_text);
 
-SOC_ENUM_SINGLE_DECL(asi3lin_enum, ASI3_DAC_OUT_CNTL, 6, asi3lin_text);
 static const struct snd_kcontrol_new asi3lin_control =
-                       SOC_DAPM_ENUM("ASI3LIN Route", asi3lin_enum);
-
+SOC_DAPM_ENUM("ASI3LIN Route", asi3lin_enum);
 
-static const char *asi3rin_text[] = {
-       "Off", "ASI3 Right In","ASI3 Left In","ASI3 MonoMix In"
+static const char * const asi3rin_text[] = {
+       "Off", "ASI3 Right In", "ASI3 Left In", "ASI3 MonoMix In"
 };
 
+SOC_ENUM_SINGLE_DECL(asi3rin_enum, AIC3262_ASI3_DAC_OUT_CNTL, 4, asi3rin_text);
 
-SOC_ENUM_SINGLE_DECL(asi3rin_enum, ASI3_DAC_OUT_CNTL, 4, asi3rin_text);
 static const struct snd_kcontrol_new asi3rin_control =
-       SOC_DAPM_ENUM("ASI3RIN Route", asi3rin_enum);
+SOC_DAPM_ENUM("ASI3RIN Route", asi3rin_enum);
 
-
-static const char *dacminidspin1_text[] = {
-       "ASI1 In", "ASI2 In","ASI3 In","ADC MiniDSP Out"
+static const char * const dacminidspin1_text[] = {
+       "ASI1 In", "ASI2 In", "ASI3 In", "ADC MiniDSP Out"
 };
 
-SOC_ENUM_SINGLE_DECL(dacminidspin1_enum, MINIDSP_PORT_CNTL_REG, 4, dacminidspin1_text);
+SOC_ENUM_SINGLE_DECL(dacminidspin1_enum, AIC3262_MINIDSP_DATA_PORT_CNTL, 4,
+                    dacminidspin1_text);
+
 static const struct snd_kcontrol_new dacminidspin1_control =
-       SOC_DAPM_ENUM("DAC MiniDSP IN1 Route", dacminidspin1_enum);
+SOC_DAPM_ENUM("DAC MiniDSP IN1 Route", dacminidspin1_enum);
 
-static const char *dacminidspin2_text[] = {
-       "ASI1 In", "ASI2 In","ASI3 In"
+static const char * const 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);
+SOC_ENUM_SINGLE_DECL(dacminidspin2_enum, AIC3262_MINIDSP_DATA_PORT_CNTL, 2,
+                    dacminidspin2_text);
 
 static const struct snd_kcontrol_new dacminidspin2_control =
-       SOC_DAPM_ENUM("DAC MiniDSP IN2 Route", dacminidspin2_enum);
+SOC_DAPM_ENUM("DAC MiniDSP IN2 Route", dacminidspin2_enum);
 
-static const char *dacminidspin3_text[] = {
-       "ASI1 In", "ASI2 In","ASI3 In"
+static const char * const 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);
+SOC_ENUM_SINGLE_DECL(dacminidspin3_enum, AIC3262_MINIDSP_DATA_PORT_CNTL, 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[] = {
+static const char * const adcdac_route_text[] = {
        "Off",
+       "On",
+};
+
+SOC_ENUM_SINGLE_DECL(adcdac_enum, 0, 2, adcdac_route_text);
+
+static const struct snd_kcontrol_new adcdacroute_control =
+SOC_DAPM_ENUM_VIRT("ADC DAC Route", adcdac_enum);
+
+static const char * const dout1_text[] = {
        "ASI1 Out",
+       "DIN1 Bypass",
+       "DIN2 Bypass",
+       "DIN3 Bypass",
+};
+
+SOC_ENUM_SINGLE_DECL(dout1_enum, AIC3262_ASI1_DOUT_CNTL, 0, dout1_text);
+static const struct snd_kcontrol_new dout1_control =
+SOC_DAPM_ENUM("DOUT1 Route", dout1_enum);
+
+static const char * const dout2_text[] = {
+       "ASI2 Out",
+       "DIN1 Bypass",
+       "DIN2 Bypass",
+       "DIN3 Bypass",
+};
+
+SOC_ENUM_SINGLE_DECL(dout2_enum, AIC3262_ASI2_DOUT_CNTL, 0, dout2_text);
+static const struct snd_kcontrol_new dout2_control =
+SOC_DAPM_ENUM("DOUT2 Route", dout2_enum);
+
+static const char * const dout3_text[] = {
+       "ASI3 Out",
+       "DIN1 Bypass",
+       "DIN2 Bypass",
+       "DIN3 Bypass",
+};
+
+SOC_ENUM_SINGLE_DECL(dout3_enum, AIC3262_ASI3_DOUT_CNTL, 0, dout3_text);
+static const struct snd_kcontrol_new dout3_control =
+SOC_DAPM_ENUM("DOUT3 Route", dout3_enum);
+
+static const char * const asi1out_text[] = {
+       "Off",
+       "ADC MiniDSP Out1",
        "ASI1In Bypass",
        "ASI2In Bypass",
        "ASI3In Bypass",
 };
-SOC_ENUM_SINGLE_DECL(asi1out_enum, ASI1_ADC_INPUT_CNTL, 0, asi1out_text);
+
+SOC_ENUM_SINGLE_DECL(asi1out_enum, AIC3262_ASI1_ADC_INPUT_CNTL,
+                    0, asi1out_text);
 static const struct snd_kcontrol_new asi1out_control =
-       SOC_DAPM_ENUM("ASI1OUT Route", asi1out_enum);
+SOC_DAPM_ENUM("ASI1OUT Route", asi1out_enum);
 
-static const char *asi2out_text[] = {
+static const char * const asi2out_text[] = {
        "Off",
-       "ASI1 Out",
+       "ADC MiniDSP Out1",
        "ASI1In Bypass",
        "ASI2In Bypass",
        "ASI3In Bypass",
-       "ASI2 Out",
+       "ADC MiniDSP Out2",
 };
-SOC_ENUM_SINGLE_DECL(asi2out_enum, ASI2_ADC_INPUT_CNTL, 0, asi2out_text);
+
+SOC_ENUM_SINGLE_DECL(asi2out_enum, AIC3262_ASI2_ADC_INPUT_CNTL,
+                    0, asi2out_text);
 static const struct snd_kcontrol_new asi2out_control =
-       SOC_DAPM_ENUM("ASI2OUT Route", asi2out_enum);
-static const char *asi3out_text[] = {
+SOC_DAPM_ENUM("ASI2OUT Route", asi2out_enum);
+static const char * const asi3out_text[] = {
        "Off",
-       "ASI1 Out",
+       "ADC MiniDSP Out1",
        "ASI1In Bypass",
        "ASI2In Bypass",
        "ASI3In Bypass",
-       "ASI3 Out",
+       "Reserved",
+       "ADC MiniDSP Out3",
 };
-SOC_ENUM_SINGLE_DECL(asi3out_enum, ASI3_ADC_INPUT_CNTL, 0, asi3out_text);
-static const struct snd_kcontrol_new asi3out_control =
-       SOC_DAPM_ENUM("ASI3OUT Route", asi3out_enum);
 
-static const char *asi1bclk_text[] = {
+SOC_ENUM_SINGLE_DECL(asi3out_enum, AIC3262_ASI3_ADC_INPUT_CNTL,
+                    0, asi3out_text);
+static const struct snd_kcontrol_new asi3out_control =
+SOC_DAPM_ENUM("ASI3OUT Route", asi3out_enum);
+static const char * const asibclk_text[] = {
        "DAC_CLK",
        "DAC_MOD_CLK",
        "ADC_CLK",
        "ADC_MOD_CLK",
 };
 
-SOC_ENUM_SINGLE_DECL(asi1bclk_enum, ASI1_BCLK_N_CNTL, 0, asi1bclk_text);
+SOC_ENUM_SINGLE_DECL(asi1bclk_enum, AIC3262_ASI1_BCLK_N_CNTL, 0, asibclk_text);
 static const struct snd_kcontrol_new asi1bclk_control =
-       SOC_DAPM_ENUM("ASI1_BCLK Route", asi1bclk_enum);
+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);
+SOC_ENUM_SINGLE_DECL(asi2bclk_enum, AIC3262_ASI2_BCLK_N_CNTL, 0, asibclk_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);
+SOC_DAPM_ENUM("ASI2_BCLK Route", asi2bclk_enum);
+SOC_ENUM_SINGLE_DECL(asi3bclk_enum, AIC3262_ASI3_BCLK_N_CNTL, 0, asibclk_text);
 static const struct snd_kcontrol_new asi3bclk_control =
-       SOC_DAPM_ENUM("ASI3_BCLK Route", asi3bclk_enum);
+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)
-{
-       return 0;
-}
-static int pll_power_on_event(struct snd_soc_dapm_widget *w,
-       struct snd_kcontrol *kcontrol, int event)
-{
-       if (event == SND_SOC_DAPM_POST_PMU)
-       {
-               mdelay(10);
-       }
-       return 0;
-}
+static const char * const adc_mux_text[] = {
+       "Analog",
+       "Digital",
+};
 
-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;
-       }
+SOC_ENUM_SINGLE_DECL(adcl_enum, AIC3262_ADC_CHANNEL_POW, 4, adc_mux_text);
+SOC_ENUM_SINGLE_DECL(adcr_enum, AIC3262_ADC_CHANNEL_POW, 2, adc_mux_text);
 
-       printk("%s: exiting with count value %d \n", __func__, counter);
-       if(counter >= 500)
-               return -1;
-       return 0;
-}
+static const struct snd_kcontrol_new adcl_mux =
+SOC_DAPM_ENUM("Left ADC Route", adcl_enum);
 
-int poll_dac(struct snd_soc_codec *codec, int left_right, int on_off)
-{
-       int ret = 0;
+static const struct snd_kcontrol_new adcr_mux =
+SOC_DAPM_ENUM("Right ADC Route", adcr_enum);
 
-       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;
-                       }
+/**
+ * aic326x_hp_event: - To handle headphone related task before and after
+ *                     headphone powrup and power down
+ * @w: pointer variable to dapm_widget
+ * @kcontrol: mixer control
+ * @event: event element information
+ *
+ * Returns 0 for success.
+ */
+static int aic326x_hp_event(struct snd_soc_dapm_widget *w,
+                           struct snd_kcontrol *kcontrol, int event)
+{
+       int reg_mask = 0;
+       int ret_wbits = 0;
+
+       if (w->shift == 1)
+               reg_mask = AIC3262_HPL_POWER_MASK;
+       if (w->shift == 0)
+               reg_mask = AIC3262_HPR_POWER_MASK;
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+                                             AIC3262_HP_FLAG, reg_mask,
+                                             reg_mask, TIME_DELAY,
+                                             DELAY_COUNTER);
+               if (!ret_wbits) {
+                       dev_err(w->codec->dev, "HP POST_PMU timedout\n");
+                       return -1;
+               }
                break;
-               default:
-                       printk("%s:unknown arguement\n", __func__);
-                       break;
+       case SND_SOC_DAPM_POST_PMD:
+               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+                                             AIC3262_HP_FLAG, reg_mask, 0,
+                                             TIME_DELAY, DELAY_COUNTER);
+               if (!ret_wbits) {
+                       dev_err(w->codec->dev, "HP POST_PMD timedout\n");
+                       return -1;
                }
-       if(ret)
-               printk("%s: power %s %s failure", __func__, left_right?"right":"left", on_off?"on":"off");
-       return ret;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+       return 0;
 }
 
-int poll_adc(struct snd_soc_codec *codec, int left_right, int on_off)
-{
-       int ret = 0;
+/**
+ *aic326x_dac_event: Headset popup reduction and powering up dsps together
+ *                     when they are in sync mode
+ * @w: pointer variable to dapm_widget
+ * @kcontrol: pointer to sound control
+ * @event: event element information
+ *
+ * Returns 0 for success.
+ */
+static int aic326x_dac_event(struct snd_soc_dapm_widget *w,
+                            struct snd_kcontrol *kcontrol, int event)
+{
+       int reg_mask = 0;
+       int ret_wbits = 0;
+       int run_state_mask;
+       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(w->codec);
+       int sync_needed = 0, non_sync_state = 0;
+       int other_dsp = 0, run_state = 0;
+
+       if (w->shift == 7) {
+               reg_mask = AIC3262_LDAC_POWER_MASK;
+               run_state_mask = AIC3262_COPS_MDSP_D_L;
+       }
+       if (w->shift == 6) {
+               reg_mask = AIC3262_RDAC_POWER_MASK;
+               run_state_mask = AIC3262_COPS_MDSP_D_R;
+       }
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+
+               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+                                             AIC3262_DAC_FLAG, reg_mask,
+                                             reg_mask, TIME_DELAY,
+                                             DELAY_COUNTER);
+
+               sync_needed = SYNC_STATE(aic3262);
+               non_sync_state = DSP_NON_SYNC_MODE(aic3262->dsp_runstate);
+               other_dsp = aic3262->dsp_runstate & AIC3262_COPS_MDSP_A;
+
+               if (sync_needed && non_sync_state && other_dsp) {
+                       run_state = get_runstate(aic3262->codec->control_data);
+                       aic3262_dsp_pwrdwn_status(aic3262);
+                       aic3262_dsp_pwrup(aic3262, run_state);
+               }
+               aic3262->dsp_runstate |= run_state_mask;
 
-       aic3262_change_page(codec, 0);
-       aic3262_change_book(codec, 0);
+               if (!ret_wbits) {
+                       dev_err(w->codec->dev, "DAC POST_PMU timedout\n");
+                       return -1;
+               }
+               break;
+       case SND_SOC_DAPM_POST_PMD:
 
-       switch(on_off) {
+               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+                                             AIC3262_DAC_FLAG, reg_mask, 0,
+                                             TIME_DELAY, DELAY_COUNTER);
 
-               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;
+               aic3262->dsp_runstate = (aic3262->dsp_runstate &
+                                        ~run_state_mask);
+               if (!ret_wbits) {
+                       dev_err(w->codec->dev, "DAC POST_PMD timedout\n");
+                       return -1;
                }
-                       break;
-               default:
-                       printk("%s:unknown arguement\n", __func__);
-                       break;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
        }
+       return 0;
+}
 
-       if(ret)
-               printk("%s: power %s %s failure", __func__, left_right?"right":"left", on_off?"on":"off");
-       return ret;
+/**
+ * aic326x_spk_event: Speaker related task before and after
+ *                      headphone powrup and power down$
+ * @w: pointer variable to dapm_widget,
+ * @kcontrolr: pointer variable to sound control,
+ * @event:     integer to event,
+ *
+ * Return value: 0 for success
+ */
+static int aic326x_spk_event(struct snd_soc_dapm_widget *w,
+                            struct snd_kcontrol *kcontrol, int event)
+{
+       int reg_mask;
+
+       if (w->shift == 1)
+               reg_mask = AIC3262_SPKL_POWER_MASK;
+       if (w->shift == 0)
+               reg_mask = AIC3262_SPKR_POWER_MASK;
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               mdelay(1);
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               mdelay(1);
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+       return 0;
 }
 
-static int  slave_dac_event(struct snd_soc_dapm_widget *w,
-                              struct snd_kcontrol *kcontrol, int event)
+/**$
+ * pll_power_on_event: provide delay after widget  power up
+ * @w:  pointer variable to dapm_widget,
+ * @kcontrolr: pointer variable to sound control,
+ * @event:     integer to event,
+ *
+ * Return value: 0 for success
+ */
+static int pll_power_on_event(struct snd_soc_dapm_widget *w,
+                             struct snd_kcontrol *kcontrol, int event)
+{
+       if (event == SND_SOC_DAPM_POST_PMU)
+               mdelay(10);
+       return 0;
+}
 
+/**
+ * aic3262_set_mode_get: To get different mode of Firmware through tinymix
+ * @kcontrolr: pointer to sound control,
+ * ucontrol: pointer to control element value,
+ *
+ * Return value: 0 for success
+ */
+static int aic3262_set_mode_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = w->codec;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct aic3262_priv *priv_ds = snd_soc_codec_get_drvdata(codec);
 
-       if (event & SND_SOC_DAPM_POST_PMU) {
-               /* Poll for DAC Power-up first */
-               poll_dac(codec, 0, 1);
-               poll_dac(codec, 1, 1);
-       }
+       ucontrol->value.integer.value[0] = ((priv_ds->cfw_p->cur_mode << 8)
+                                           | priv_ds->cfw_p->cur_cfg);
 
-       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)
-
+/**
+ * aic3262_set_mode_put: To set different mode of Firmware through tinymix
+ * @kcontrolr: pointer to sound control,
+ * ucontrol: pointer to control element value,
+ *
+ * Return value: 0 for success
+ */
+static int aic3262_set_mode_put(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = w->codec;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct aic3262_priv *priv_ds = snd_soc_codec_get_drvdata(codec);
 
-       if (event & SND_SOC_DAPM_POST_PMU) {
+       int next_mode = 0, next_cfg = 0;
+       int ret = 0;
 
-               /* Poll for ADC Power-up first */
-               poll_adc(codec, 0, 1);
-               poll_adc(codec, 1, 1);
-       }
+       next_mode = (ucontrol->value.integer.value[0] >> 8);
+       next_cfg = (ucontrol->value.integer.value[0]) & 0xFF;
+       if (priv_ds == NULL)
+               dev_err(codec->dev, "failed to load firmware\n");
+       else
+               ret = aic3xxx_cfw_setmode_cfg(priv_ds->cfw_p,
+                                             next_mode, next_cfg);
 
+       return ret;
+}
 
-       if (event & SND_SOC_DAPM_POST_PMD) {
-               poll_adc(codec, 0, 0);
-               poll_adc(codec, 1, 0);
+/**
+ * aic326x_adc_dsp_event: To get DSP run state to perform synchronization
+ * @w: pointer variable to dapm_widget
+ * @kcontrol: pointer to sound control
+ * @event: event element information
+ *
+ * Returns 0 for success.
+ */
+static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
+                                struct snd_kcontrol *kcontrol, int event)
+{
+       int run_state = 0;
+       int non_sync_state = 0, sync_needed = 0;
+       int other_dsp = 0;
+       int run_state_mask = 0;
+       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(w->codec);
+       int reg_mask = 0;
+       int ret_wbits = 0;
+
+       if (w->shift == 7) {
+               reg_mask = AIC3262_LADC_POWER_MASK;
+               run_state_mask = AIC3262_COPS_MDSP_A_L;
+       }
+       if (w->shift == 6) {
+               reg_mask = AIC3262_RADC_POWER_MASK;
+               run_state_mask = AIC3262_COPS_MDSP_A_R;
+       }
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+                                             AIC3262_ADC_FLAG, reg_mask,
+                                             reg_mask, TIME_DELAY,
+                                             DELAY_COUNTER);
+               sync_needed = SYNC_STATE(aic3262);
+               non_sync_state = DSP_NON_SYNC_MODE(aic3262->dsp_runstate);
+               other_dsp = aic3262->dsp_runstate & AIC3262_COPS_MDSP_D;
+               if (sync_needed && non_sync_state && other_dsp) {
+                       run_state = get_runstate(aic3262->codec->control_data);
+                       aic3262_dsp_pwrdwn_status(aic3262);
+                       aic3262_dsp_pwrup(aic3262, run_state);
+               }
+               aic3262->dsp_runstate |= run_state_mask;
+               if (!ret_wbits) {
+                       dev_err(w->codec->dev, "ADC POST_PMU timedout\n");
+                       return -1;
+               }
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+                                             AIC3262_ADC_FLAG, reg_mask, 0,
+                                             TIME_DELAY, DELAY_COUNTER);
+               aic3262->dsp_runstate = (aic3262->dsp_runstate &
+                                        ~run_state_mask);
+               if (!ret_wbits) {
+                       dev_err(w->codec->dev, "ADC POST_PMD timedout\n");
+                       return -1;
+               }
+               break;
+       default:
+               BUG();
+               return -EINVAL;
        }
-
        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_AIF_IN("DIN1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_IN("DIN2", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_IN("DIN3", "ASI3 Playback", 0, SND_SOC_NOPM, 0, 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),
+       SND_SOC_DAPM_DAC_E("Left DAC", NULL, AIC3262_PASI_DAC_DP_SETUP, 7, 0,
+                          aic326x_dac_event, SND_SOC_DAPM_POST_PMU |
+                          SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_DAC_E("Right DAC", NULL, AIC3262_PASI_DAC_DP_SETUP, 6, 0,
+                          aic326x_dac_event, SND_SOC_DAPM_POST_PMU |
+                          SND_SOC_DAPM_POST_PMD),
 
        /* dapm widget (path domain) for HPL Output Mixer */
        SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0,
-                &hpl_output_mixer_controls[0],
-               ARRAY_SIZE(hpl_output_mixer_controls)),
+                               &hpl_output_mixer_controls[0],
+                               ARRAY_SIZE(hpl_output_mixer_controls)),
 
        /* dapm widget (path domain) for HPR Output Mixer */
        SND_SOC_DAPM_MIXER("HPR Output Mixer", SND_SOC_NOPM, 0, 0,
-                       &hpr_output_mixer_controls[0],
-                       ARRAY_SIZE(hpr_output_mixer_controls)),
+                               &hpr_output_mixer_controls[0],
+                               ARRAY_SIZE(hpr_output_mixer_controls)),
 
 
-       SND_SOC_DAPM_PGA_E("HPL Driver", HP_AMP_CNTL_R1, 1, 0, NULL, 0,
-                               aic326x_hp_event, SND_SOC_DAPM_POST_PMU),
-       SND_SOC_DAPM_PGA_E("HPR Driver", HP_AMP_CNTL_R1, 0, 0, NULL, 0,
-                               aic326x_hp_event, SND_SOC_DAPM_POST_PMU),
+       SND_SOC_DAPM_PGA_E("HPL Driver", AIC3262_HP_AMP_CNTL_R1,
+                               1, 0, NULL, 0, aic326x_hp_event,
+                               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_PGA_E("HPR Driver", AIC3262_HP_AMP_CNTL_R1,
+                               0, 0, NULL, 0, aic326x_hp_event,
+                               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 
        /* dapm widget (path domain) for LOL Output Mixer */
        SND_SOC_DAPM_MIXER("LOL Output Mixer", SND_SOC_NOPM, 0, 0,
-                       &lol_output_mixer_controls[0],
-                       ARRAY_SIZE(lol_output_mixer_controls)),
+                               &lol_output_mixer_controls[0],
+                               ARRAY_SIZE(lol_output_mixer_controls)),
 
        /* dapm widget (path domain) for LOR Output Mixer mixer */
        SND_SOC_DAPM_MIXER("LOR Output Mixer", SND_SOC_NOPM, 0, 0,
-                       &lor_output_mixer_controls[0],
-                       ARRAY_SIZE(lor_output_mixer_controls)),
+                               &lor_output_mixer_controls[0],
+                               ARRAY_SIZE(lor_output_mixer_controls)),
 
-       SND_SOC_DAPM_PGA("LOL Driver", LINE_AMP_CNTL_R1, 1, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("LOR Driver", LINE_AMP_CNTL_R1, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("LOL Driver", AIC3262_LINE_AMP_CNTL_R1,
+                               1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("LOR Driver", AIC3262_LINE_AMP_CNTL_R1,
+                               0, 0, NULL, 0),
 
 
        /* dapm widget (path domain) for SPKL Output Mixer */
        SND_SOC_DAPM_MIXER("SPKL Output Mixer", SND_SOC_NOPM, 0, 0,
-                       &spkl_output_mixer_controls[0],
-                       ARRAY_SIZE(spkl_output_mixer_controls)),
+                               &spkl_output_mixer_controls[0],
+                               ARRAY_SIZE(spkl_output_mixer_controls)),
 
        /* dapm widget (path domain) for SPKR Output Mixer */
        SND_SOC_DAPM_MIXER("SPKR Output Mixer", SND_SOC_NOPM, 0, 0,
-                       &spkr_output_mixer_controls[0],
-                       ARRAY_SIZE(spkr_output_mixer_controls)),
+                               &spkr_output_mixer_controls[0],
+                               ARRAY_SIZE(spkr_output_mixer_controls)),
 
-       SND_SOC_DAPM_PGA("SPKL Driver", SPK_AMP_CNTL_R1, 1, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("SPKR Driver", SPK_AMP_CNTL_R1, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_E("SPKL Driver", AIC3262_SPK_AMP_CNTL_R1,
+                               1, 0, NULL, 0, aic326x_spk_event,
+                               SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+       SND_SOC_DAPM_PGA_E("SPKR Driver", AIC3262_SPK_AMP_CNTL_R1,
+                               0, 0, NULL, 0, aic326x_spk_event,
+                               SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
 
 
        /* dapm widget (path domain) for SPKR Output Mixer */
        SND_SOC_DAPM_MIXER("REC Output Mixer", SND_SOC_NOPM, 0, 0,
-                       &rec_output_mixer_controls[0],
-                       ARRAY_SIZE(rec_output_mixer_controls)),
+                               &rec_output_mixer_controls[0],
+                               ARRAY_SIZE(rec_output_mixer_controls)),
 
-       SND_SOC_DAPM_PGA("RECP Driver", REC_AMP_CNTL_R5, 7, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("RECM Driver", REC_AMP_CNTL_R5, 6, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("RECP Driver", AIC3262_REC_AMP_CNTL_R5,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("RECM Driver", AIC3262_REC_AMP_CNTL_R5,
+                               6, 0, NULL, 0),
 
 
        SND_SOC_DAPM_MUX("ASI1LIN Route",
-               SND_SOC_NOPM, 0, 0, &asi1lin_control),
+                        SND_SOC_NOPM, 0, 0, &asi1lin_control),
        SND_SOC_DAPM_MUX("ASI1RIN Route",
-               SND_SOC_NOPM, 0, 0, &asi1rin_control),
+                        SND_SOC_NOPM, 0, 0, &asi1rin_control),
        SND_SOC_DAPM_MUX("ASI2LIN Route",
-               SND_SOC_NOPM, 0, 0, &asi2lin_control),
+                        SND_SOC_NOPM, 0, 0, &asi2lin_control),
        SND_SOC_DAPM_MUX("ASI2RIN Route",
-               SND_SOC_NOPM, 0, 0, &asi2rin_control),
+                        SND_SOC_NOPM, 0, 0, &asi2rin_control),
        SND_SOC_DAPM_MUX("ASI3LIN Route",
-               SND_SOC_NOPM, 0, 0, &asi3lin_control),
+                        SND_SOC_NOPM, 0, 0, &asi3lin_control),
        SND_SOC_DAPM_MUX("ASI3RIN Route",
-               SND_SOC_NOPM, 0, 0, &asi3rin_control),
+                        SND_SOC_NOPM, 0, 0, &asi3rin_control),
 
        SND_SOC_DAPM_PGA("ASI1LIN", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ASI1RIN", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -3030,14 +1078,6 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("ASI2RIN", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ASI3LIN", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ASI3RIN", SND_SOC_NOPM, 0, 0, NULL, 0),
-
-       SND_SOC_DAPM_PGA("ASI1LOUT", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("ASI1ROUT", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("ASI2LOUT", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("ASI2ROUT", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("ASI3LOUT", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("ASI3ROUT", SND_SOC_NOPM, 0, 0, NULL, 0),
-
        SND_SOC_DAPM_PGA("ASI1MonoMixIN", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ASI2MonoMixIN", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ASI3MonoMixIN", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -3046,13 +1086,15 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("ASI2IN Port", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ASI3IN Port", SND_SOC_NOPM, 0, 0, NULL, 0),
 
-
        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_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_NOPM, 0, 0, &dacminidspin3_control),
+
+       SND_SOC_DAPM_VIRT_MUX("ADC DAC Route",
+                             SND_SOC_NOPM, 0, 0, &adcdacroute_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),
@@ -3061,59 +1103,74 @@ SND_SOC_DAPM_MUX("DAC MiniDSP IN2 Route",
        SND_SOC_DAPM_PGA("CM2R", SND_SOC_NOPM, 0, 0, NULL, 0),
 
        /* TODO: Can we switch these off ? */
-       SND_SOC_DAPM_AIF_OUT("ASI1OUT","ASI1 Capture", 0, SND_SOC_NOPM, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("ASI2OUT", "ASI2 Capture",0, SND_SOC_NOPM, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("ASI3OUT", "ASI3 Capture",0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("DOUT1", "ASI1 Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("DOUT2", "ASI2 Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("DOUT3", "ASI3 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+       SND_SOC_DAPM_MUX("DOUT1 Route",
+                        SND_SOC_NOPM, 0, 0, &dout1_control),
+       SND_SOC_DAPM_MUX("DOUT2 Route",
+                        SND_SOC_NOPM, 0, 0, &dout2_control),
+       SND_SOC_DAPM_MUX("DOUT3 Route",
+                        SND_SOC_NOPM, 0, 0, &dout3_control),
+
+       SND_SOC_DAPM_PGA("ASI1OUT", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("ASI2OUT", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("ASI3OUT", SND_SOC_NOPM, 0, 0, NULL, 0),
 
        SND_SOC_DAPM_MUX("ASI1OUT Route",
-               SND_SOC_NOPM, 0, 0, &asi1out_control),
+                        SND_SOC_NOPM, 0, 0, &asi1out_control),
        SND_SOC_DAPM_MUX("ASI2OUT Route",
-               SND_SOC_NOPM, 0, 0, &asi2out_control),
+                        SND_SOC_NOPM, 0, 0, &asi2out_control),
        SND_SOC_DAPM_MUX("ASI3OUT Route",
-               SND_SOC_NOPM, 0, 0, &asi3out_control),
+                        SND_SOC_NOPM, 0, 0, &asi3out_control),
 
-       /* TODO: Will be used during MINIDSP programming */
+       /* TODO: Can we switch the ASI1 OUT1 off? */
        /* TODO: Can we switch them off? */
        SND_SOC_DAPM_PGA("ADC MiniDSP OUT1", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ADC MiniDSP OUT2", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ADC MiniDSP OUT3", SND_SOC_NOPM, 0, 0, NULL, 0),
 
+/*     SND_SOC_DAPM_MUX("DMICDAT Input Route",
+                       SND_SOC_NOPM, 0, 0, &dmicinput_control),*/
 
+       SND_SOC_DAPM_MUX("Left ADC Route", SND_SOC_NOPM, 0, 0, &adcl_mux),
+       SND_SOC_DAPM_MUX("Right ADC Route", SND_SOC_NOPM, 0, 0, &adcr_mux),
 
-       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_ADC_E("Left ADC", NULL, AIC3262_ADC_CHANNEL_POW, 7, 0,
+                          aic326x_adc_dsp_event, SND_SOC_DAPM_POST_PMU |
+                          SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_ADC_E("Right ADC", NULL, AIC3262_ADC_CHANNEL_POW, 6, 0,
+                          aic326x_adc_dsp_event, SND_SOC_DAPM_POST_PMU |
+                          SND_SOC_DAPM_POST_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),
+       SND_SOC_DAPM_PGA("Left MicPGA", AIC3262_MICL_PGA, 7, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Right MicPGA", AIC3262_MICR_PGA, 7, 1, NULL, 0),
 
-       SND_SOC_DAPM_PGA("MAL PGA", MA_CNTL, 3, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("MAR PGA", MA_CNTL, 2, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MAL PGA", AIC3262_MA_CNTL,
+                               3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MAR PGA", AIC3262_MA_CNTL,
+                               2, 0, NULL, 0),
 
-
-       /* dapm widget for MAL PGA Mixer*/
+       /* dapm widget for MAL PGA Mixer */
        SND_SOC_DAPM_MIXER("MAL PGA Mixer", SND_SOC_NOPM, 0, 0,
-                        &mal_pga_mixer_controls[0],
-                        ARRAY_SIZE(mal_pga_mixer_controls)),
+                               &mal_pga_mixer_controls[0],
+                               ARRAY_SIZE(mal_pga_mixer_controls)),
 
-       /* dapm widget for MAR PGA Mixer*/
+       /* dapm widget for MAR PGA Mixer */
        SND_SOC_DAPM_MIXER("MAR PGA Mixer", SND_SOC_NOPM, 0, 0,
-                       &mar_pga_mixer_controls[0],
-                       ARRAY_SIZE(mar_pga_mixer_controls)),
+                               &mar_pga_mixer_controls[0],
+                               ARRAY_SIZE(mar_pga_mixer_controls)),
 
-       /* dapm widget for Left Input Mixer*/
+       /* dapm widget for Left Input Mixer */
        SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0,
-                       &left_input_mixer_controls[0],
-                       ARRAY_SIZE(left_input_mixer_controls)),
+                               &left_input_mixer_controls[0],
+                               ARRAY_SIZE(left_input_mixer_controls)),
 
-       /* dapm widget for Right Input Mixer*/
+       /* dapm widget for Right Input Mixer */
        SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
-                       &right_input_mixer_controls[0],
-                       ARRAY_SIZE(right_input_mixer_controls)),
-
+                               &right_input_mixer_controls[0],
+                               ARRAY_SIZE(right_input_mixer_controls)),
 
        SND_SOC_DAPM_OUTPUT("HPL"),
        SND_SOC_DAPM_OUTPUT("HPR"),
@@ -3132,31 +1189,36 @@ SND_SOC_DAPM_MUX("DAC MiniDSP IN2 Route",
        SND_SOC_DAPM_INPUT("IN2R"),
        SND_SOC_DAPM_INPUT("IN3R"),
        SND_SOC_DAPM_INPUT("IN4R"),
-
-
-       SND_SOC_DAPM_MICBIAS("Mic Bias Ext", MIC_BIAS_CNTL, 6, 0),
-       SND_SOC_DAPM_MICBIAS("Mic Bias Int", MIC_BIAS_CNTL, 2, 0),
-
-       SND_SOC_DAPM_SUPPLY("PLLCLK",PLL_PR_POW_REG,7,0,pll_power_on_event,
-                                               SND_SOC_DAPM_POST_PMU),
-       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_INPUT("Left DMIC"),
+       SND_SOC_DAPM_INPUT("Right DMIC"),
+
+       SND_SOC_DAPM_MICBIAS("Mic Bias Ext", AIC3262_MIC_BIAS_CNTL, 6, 0),
+       SND_SOC_DAPM_MICBIAS("Mic Bias Int", AIC3262_MIC_BIAS_CNTL, 2, 0),
+
+       SND_SOC_DAPM_SUPPLY("PLLCLK", AIC3262_PLL_PR_POW_REG, 7, 0,
+                           pll_power_on_event, SND_SOC_DAPM_POST_PMU),
+       SND_SOC_DAPM_SUPPLY("DACCLK", AIC3262_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", AIC3262_MDAC_DIV_POW_REG,
+                           7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ADCCLK", AIC3262_NADC_DIV_POW_REG, 7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ADC_MOD_CLK", AIC3262_MADC_DIV_POW_REG,
+                           7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI1_BCLK", AIC3262_ASI1_BCLK_N, 7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI1_WCLK", AIC3262_ASI1_WCLK_N, 7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI2_BCLK", AIC3262_ASI2_BCLK_N, 7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI2_WCLK", AIC3262_ASI2_WCLK_N, 7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI3_BCLK", AIC3262_ASI3_BCLK_N, 7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ASI3_WCLK", AIC3262_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),
+                        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[] ={
+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 */
        {"CODEC_CLK_IN", NULL, "PLLCLK"},
@@ -3164,185 +1226,179 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
        {"ADCCLK", NULL, "CODEC_CLK_IN"},
        {"DAC_MOD_CLK", NULL, "DACCLK"},
 #ifdef AIC3262_SYNC_MODE
-       {"ADC_MOD_CLK", NULL,"DACCLK"},
+       {"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"},
+       {"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"},
+       {"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"},
+       {"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"},
+       {"DIN1", NULL, "PLLCLK"},
+       {"DIN1", NULL, "DACCLK"},
+       {"DIN1", NULL, "ADCCLK"},
+       {"DIN1", NULL, "DAC_MOD_CLK"},
+       {"DIN1", NULL, "ADC_MOD_CLK"},
+
+       {"DOUT1", NULL, "PLLCLK"},
+       {"DOUT1", NULL, "DACCLK"},
+       {"DOUT1", NULL, "ADCCLK"},
+       {"DOUT1", NULL, "DAC_MOD_CLK"},
+       {"DOUT1", NULL, "ADC_MOD_CLK"},
 #ifdef AIC3262_ASI1_MASTER
-       {"ASI1IN", NULL , "ASI1_BCLK"},
-       {"ASI1OUT", NULL , "ASI1_BCLK"},
-       {"ASI1IN", NULL , "ASI1_WCLK"},
-       {"ASI1OUT", NULL , "ASI1_WCLK"},
+       {"DIN1", NULL, "ASI1_BCLK"},
+       {"DOUT1", NULL, "ASI1_BCLK"},
+       {"DIN1", NULL, "ASI1_WCLK"},
+       {"DOUT1", NULL, "ASI1_WCLK"},
 #else
 
 #endif
-
-       {"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"},
+       {"DIN2", NULL, "PLLCLK"},
+       {"DIN2", NULL, "DACCLK"},
+       {"DIN2", NULL, "ADCCLK"},
+       {"DIN2", NULL, "DAC_MOD_CLK"},
+       {"DIN2", NULL, "ADC_MOD_CLK"},
+
+       {"DOUT2", NULL, "PLLCLK"},
+       {"DOUT2", NULL, "DACCLK"},
+       {"DOUT2", NULL, "ADCCLK"},
+       {"DOUT2", NULL, "DAC_MOD_CLK"},
+       {"DOUT2", NULL, "ADC_MOD_CLK"},
 
 #ifdef AIC3262_ASI2_MASTER
-       {"ASI2IN", NULL , "ASI2_BCLK"},
-       {"ASI2OUT", NULL , "ASI2_BCLK"},
-       {"ASI2IN", NULL , "ASI2_WCLK"},
-       {"ASI2OUT", NULL , "ASI2_WCLK"},
+       {"DIN2", NULL, "ASI2_BCLK"},
+       {"DOUT2", NULL, "ASI2_BCLK"},
+       {"DIN2", NULL, "ASI2_WCLK"},
+       {"DOUT2", NULL, "ASI2_WCLK"},
 #else
 
 #endif
-       {"ASI3IN", NULL , "PLLCLK"},
-       {"ASI3IN", NULL , "DACCLK"},
-       {"ASI3IN", NULL , "ADCCLK"},
-       {"ASI3IN", NULL , "DAC_MOD_CLK"},
-       {"ASI3IN", NULL , "ADC_MOD_CLK"},
-
-
-       {"ASI3OUT", NULL , "PLLCLK"},
-       {"ASI3OUT", NULL , "DACCLK"},
-       {"ASI3OUT", NULL , "ADCCLK"},
-       {"ASI3OUT", NULL , "DAC_MOD_CLK"},
-       {"ASI3OUT", NULL , "ADC_MOD_CLK"},
+       {"DIN3", NULL, "PLLCLK"},
+       {"DIN3", NULL, "DACCLK"},
+       {"DIN3", NULL, "ADCCLK"},
+       {"DIN3", NULL, "DAC_MOD_CLK"},
+       {"DIN3", NULL, "ADC_MOD_CLK"},
+
+       {"DOUT3", NULL, "PLLCLK"},
+       {"DOUT3", NULL, "DACCLK"},
+       {"DOUT3", NULL, "ADCCLK"},
+       {"DOUT3", NULL, "DAC_MOD_CLK"},
+       {"DOUT3", NULL, "ADC_MOD_CLK"},
 
 #ifdef AIC3262_ASI3_MASTER
-       {"ASI3IN", NULL , "ASI3_BCLK"},
-       {"ASI3OUT", NULL , "ASI3_BCLK"},
-       {"ASI3IN", NULL , "ASI3_WCLK"},
-       {"ASI3OUT", NULL , "ASI3_WCLK"},
+       {"DIN3", NULL, "ASI3_BCLK"},
+       {"DOUT3", NULL, "ASI3_BCLK"},
+       {"DIN3", NULL, "ASI3_WCLK"},
+       {"DOUT3", NULL, "ASI3_WCLK"},
 #else
-#endif
-
-/* Playback (DAC) Portion */
-       {"HPL Output Mixer","LDAC Switch","Left DAC"},
-       {"HPL Output Mixer","MAL Switch","MAL PGA"},
-       {"HPL Output Mixer","LOL-B1 Volume","LOL"},
 
-       {"HPR Output Mixer","LOR-B1 Volume","LOR"},
-       {"HPR Output Mixer","LDAC Switch","Left DAC"},
-       {"HPR Output Mixer","RDAC Switch","Right DAC"},
-       {"HPR Output Mixer","MAR Switch","MAR PGA"},
-
-       {"HPL Driver",NULL,"HPL Output Mixer"},
-       {"HPR Driver",NULL,"HPR Output Mixer"},
-
-       {"HPL",NULL,"HPL Driver"},
-       {"HPR",NULL,"HPR Driver"},
+#endif
+       /* Playback (DAC) Portion */
+       {"HPL Output Mixer", "LDAC Switch", "Left DAC"},
+       {"HPL Output Mixer", "MAL Switch", "MAL PGA"},
+       {"HPL Output Mixer", "LOL-B1 Volume", "LOL"},
 
-       {"LOL Output Mixer","MAL Switch","MAL PGA"},
-       {"LOL Output Mixer","IN1L-B Switch","IN1L"},
-       {"LOL Output Mixer","LDAC Switch","Left DAC"},
-       {"LOL Output Mixer","RDAC Switch","Right DAC"},
+       {"HPR Output Mixer", "LOR-B1 Volume", "LOR"},
+       {"HPR Output Mixer", "LDAC Switch", "Left DAC"},
+       {"HPR Output Mixer", "RDAC Switch", "Right DAC"},
+       {"HPR Output Mixer", "MAR Switch", "MAR PGA"},
 
-       {"LOR Output Mixer","LOL Switch","LOL"},
-       {"LOR Output Mixer","RDAC Switch","Right DAC"},
-       {"LOR Output Mixer","MAR Switch","MAR PGA"},
-       {"LOR Output Mixer","IN1R-B Switch","IN1R"},
+       {"HPL Driver", NULL, "HPL Output Mixer"},
+       {"HPR Driver", NULL, "HPR Output Mixer"},
 
-       {"LOL Driver",NULL,"LOL Output Mixer"},
-       {"LOR Driver",NULL,"LOR Output Mixer"},
+       {"HPL", NULL, "HPL Driver"},
+       {"HPR", NULL, "HPR Driver"},
 
-       {"LOL",NULL,"LOL Driver"},
-       {"LOR",NULL,"LOR Driver"},
+       {"LOL Output Mixer", "MAL Switch", "MAL PGA"},
+       {"LOL Output Mixer", "IN1L-B Switch", "IN1L"},
+       {"LOL Output Mixer", "LDAC Switch", "Left DAC"},
+       {"LOL Output Mixer", "RDAC Switch", "Right DAC"},
 
-       {"REC Output Mixer","LOL-B2 Volume","LOL"},
-       {"REC Output Mixer","IN1L Volume","IN1L"},
-       {"REC Output Mixer","IN1R Volume","IN1R"},
-       {"REC Output Mixer","LOR-B2 Volume","LOR"},
+       {"LOR Output Mixer", "LOL Switch", "LOL"},
+       {"LOR Output Mixer", "RDAC Switch", "Right DAC"},
+       {"LOR Output Mixer", "MAR Switch", "MAR PGA"},
+       {"LOR Output Mixer", "IN1R-B Switch", "IN1R"},
 
-       {"RECP Driver",NULL,"REC Output Mixer"},
-       {"RECM Driver",NULL,"REC Output Mixer"},
+       {"LOL Driver", NULL, "LOL Output Mixer"},
+       {"LOR Driver", NULL, "LOR Output Mixer"},
 
-       {"RECP",NULL,"RECP Driver"},
-       {"RECM",NULL,"RECM Driver"},
+       {"LOL", NULL, "LOL Driver"},
+       {"LOR", NULL, "LOR Driver"},
 
-       {"SPKL Output Mixer","MAL Switch","MAL PGA"},
-       {"SPKL Output Mixer","LOL Volume","LOL"},
-       {"SPKL Output Mixer","SPR_IN Switch","SPKR Output Mixer"},
+       {"REC Output Mixer", "LOL-B2 Volume", "LOL"},
+       {"REC Output Mixer", "IN1L Volume", "IN1L"},
+       {"REC Output Mixer", "IN1R Volume", "IN1R"},
+       {"REC Output Mixer", "LOR-B2 Volume", "LOR"},
 
-       {"SPKR Output Mixer", "LOR Volume","LOR"},
-       {"SPKR Output Mixer", "MAR Switch","MAR PGA"},
+       {"RECP Driver", NULL, "REC Output Mixer"},
+       {"RECM Driver", NULL, "REC Output Mixer"},
 
+       {"RECP", NULL, "RECP Driver"},
+       {"RECM", NULL, "RECM Driver"},
 
-       {"SPKL Driver",NULL,"SPKL Output Mixer"},
-       {"SPKR Driver",NULL,"SPKR Output Mixer"},
+       {"SPKL Output Mixer", "MAL Switch", "MAL PGA"},
+       {"SPKL Output Mixer", "LOL Volume", "LOL"},
+       {"SPKL Output Mixer", "SPR_IN Switch", "SPKR Output Mixer"},
 
-       {"SPKL",NULL,"SPKL Driver"},
-       {"SPKR",NULL,"SPKR Driver"},
-/* ASI Input routing */
-       {"ASI1LIN", NULL, "ASI1IN"},
-       {"ASI1RIN", NULL, "ASI1IN"},
-       {"ASI2LIN", NULL, "ASI2IN"},
-       {"ASI2RIN", NULL, "ASI2IN"},
-       {"ASI3LIN", NULL, "ASI3IN"},
-       {"ASI3RIN", NULL, "ASI3IN"},
+       {"SPKR Output Mixer", "LOR Volume", "LOR"},
+       {"SPKR Output Mixer", "MAR Switch", "MAR PGA"},
 
-       {"ASI1MonoMixIN", NULL, "ASI1IN"},
-       {"ASI2MonoMixIN", NULL, "ASI2IN"},
-       {"ASI3MonoMixIN", NULL, "ASI3IN"},
 
-       {"ASI1LIN Route","ASI1 Left In","ASI1LIN"},
-       {"ASI1LIN Route","ASI1 Right In","ASI1RIN"},
-       {"ASI1LIN Route","ASI1 MonoMix In","ASI1MonoMixIN"},
+       {"SPKL Driver", NULL, "SPKL Output Mixer"},
+       {"SPKR Driver", NULL, "SPKR Output Mixer"},
 
-       {"ASI1RIN Route", "ASI1 Right In","ASI1RIN"},
-       {"ASI1RIN Route","ASI1 Left In","ASI1LIN"},
-       {"ASI1RIN Route","ASI1 MonoMix In","ASI1MonoMixIN"},
+       {"SPKL", NULL, "SPKL Driver"},
+       {"SPKR", NULL, "SPKR Driver"},
+       /* ASI Input routing */
+       {"ASI1LIN", NULL, "DIN1"},
+       {"ASI1RIN", NULL, "DIN1"},
+       {"ASI1MonoMixIN", NULL, "DIN1"},
+       {"ASI2LIN", NULL, "DIN2"},
+       {"ASI2RIN", NULL, "DIN2"},
+       {"ASI2MonoMixIN", NULL, "DIN2"},
+       {"ASI3LIN", NULL, "DIN3"},
+       {"ASI3RIN", NULL, "DIN3"},
+       {"ASI3MonoMixIN", NULL, "DIN3"},
 
+       {"ASI1LIN Route", "ASI1 Left In", "ASI1LIN"},
+       {"ASI1LIN Route", "ASI1 Right In", "ASI1RIN"},
+       {"ASI1LIN Route", "ASI1 MonoMix In", "ASI1MonoMixIN"},
 
-       {"ASI2LIN Route","ASI2 Left In","ASI2LIN"},
-       {"ASI2LIN Route","ASI2 Right In","ASI2RIN"},
-       {"ASI2LIN Route","ASI2 MonoMix In","ASI2MonoMixIN"},
+       {"ASI1RIN Route", "ASI1 Right In", "ASI1RIN"},
+       {"ASI1RIN Route", "ASI1 Left In", "ASI1LIN"},
+       {"ASI1RIN Route", "ASI1 MonoMix In", "ASI1MonoMixIN"},
 
-       {"ASI2RIN Route","ASI2 Right In","ASI2RIN"},
-       {"ASI2RIN Route","ASI2 Left In","ASI2LIN"},
-       {"ASI2RIN Route","ASI2 MonoMix In","ASI2MonoMixIN"},
+       {"ASI2LIN Route", "ASI2 Left In", "ASI2LIN"},
+       {"ASI2LIN Route", "ASI2 Right In", "ASI2RIN"},
+       {"ASI2LIN Route", "ASI2 MonoMix In", "ASI2MonoMixIN"},
 
+       {"ASI2RIN Route", "ASI2 Right In", "ASI2RIN"},
+       {"ASI2RIN Route", "ASI2 Left In", "ASI2LIN"},
+       {"ASI2RIN Route", "ASI2 MonoMix In", "ASI2MonoMixIN"},
 
-       {"ASI3LIN Route","ASI3 Left In","ASI3LIN"},
-       {"ASI3LIN Route","ASI3 Right In","ASI3RIN"},
-       {"ASI3LIN Route","ASI3 MonoMix In","ASI3MonoMixIN"},
+       {"ASI3LIN Route", "ASI3 Left In", "ASI3LIN"},
+       {"ASI3LIN Route", "ASI3 Right In", "ASI3RIN"},
+       {"ASI3LIN Route", "ASI3 MonoMix In", "ASI3MonoMixIN"},
 
-       {"ASI3RIN Route","ASI3 Right In","ASI3RIN"},
-       {"ASI3RIN Route","ASI3 Left In","ASI3LIN"},
-       {"ASI3RIN Route","ASI3 MonoMix In","ASI3MonoMixIN"},
+       {"ASI3RIN Route", "ASI3 Right In", "ASI3RIN"},
+       {"ASI3RIN Route", "ASI3 Left In", "ASI3LIN"},
+       {"ASI3RIN Route", "ASI3 MonoMix In", "ASI3MonoMixIN"},
 
        {"ASI1IN Port", NULL, "ASI1LIN Route"},
        {"ASI1IN Port", NULL, "ASI1RIN Route"},
@@ -3351,83 +1407,94 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
        {"ASI3IN Port", NULL, "ASI3LIN Route"},
        {"ASI3IN Port", NULL, "ASI3RIN Route"},
 
-       {"DAC MiniDSP IN1 Route", "ASI1 In","ASI1IN Port"},
-       {"DAC MiniDSP IN1 Route","ASI2 In","ASI2IN Port"},
-       {"DAC MiniDSP IN1 Route","ASI3 In","ASI3IN Port"},
-       {"DAC MiniDSP IN1 Route","ADC MiniDSP Out","ADC MiniDSP OUT1"},
+       {"DAC MiniDSP IN1 Route", "ASI1 In", "ASI1IN Port"},
+       {"DAC MiniDSP IN1 Route", "ASI2 In", "ASI2IN Port"},
+       {"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 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"},
+       {"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"},
 
-       {"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 */
+       /* Mixer Amplifier */
 
-       {"MAL PGA Mixer", "IN1L Switch","IN1L"},
-       {"MAL PGA Mixer", "Left MicPGA Volume","Left MicPGA"},
+       {"MAL PGA Mixer", "IN1L Switch", "IN1L"},
+       {"MAL PGA Mixer", "Left MicPGA Volume", "Left MicPGA"},
 
        {"MAL PGA", NULL, "MAL PGA Mixer"},
 
 
-       {"MAR PGA Mixer", "IN1R Switch","IN1R"},
-       {"MAR PGA Mixer", "Right MicPGA Volume","Right MicPGA"},
+       {"MAR PGA Mixer", "IN1R Switch", "IN1R"},
+       {"MAR PGA Mixer", "Right MicPGA Volume", "Right MicPGA"},
 
        {"MAR PGA", NULL, "MAR PGA Mixer"},
 
 
-/* Capture (ADC) portions */
+       /* Virtual connection between DAC and ADC for miniDSP IPC */
+       {"ADC DAC Route", "On", "Left ADC"},
+       {"ADC DAC Route", "On", "Right ADC"},
+
+       {"Left DAC", NULL, "ADC DAC Route"},
+       {"Right DAC", NULL, "ADC DAC Route"},
+
+       /* Capture (ADC) portions */
        /* Left Positive PGA input */
-       {"Left Input Mixer","IN1L Switch","IN1L"},
-       {"Left Input Mixer","IN2L Switch","IN2L"},
-       {"Left Input Mixer","IN3L Switch","IN3L"},
-       {"Left Input Mixer","IN4L Switch","IN4L"},
-       {"Left Input Mixer","IN1R Switch","IN1R"},
+       {"Left Input Mixer", "IN1L Switch", "IN1L"},
+       {"Left Input Mixer", "IN2L Switch", "IN2L"},
+       {"Left Input Mixer", "IN3L Switch", "IN3L"},
+       {"Left Input Mixer", "IN4L Switch", "IN4L"},
+       {"Left Input Mixer", "IN1R Switch", "IN1R"},
        /* Left Negative PGA input */
-       {"Left Input Mixer","IN2R Switch","IN2R"},
-       {"Left Input Mixer","IN3R Switch","IN3R"},
-       {"Left Input Mixer","IN4R Switch","IN4R"},
-       {"Left Input Mixer","CM2L Switch","CM2L"},
-       {"Left Input Mixer","CM1L Switch","CM1L"},
+       {"Left Input Mixer", "IN2R Switch", "IN2R"},
+       {"Left Input Mixer", "IN3R Switch", "IN3R"},
+       {"Left Input Mixer", "IN4R Switch", "IN4R"},
+       {"Left Input Mixer", "CM2L Switch", "CM2L"},
+       {"Left Input Mixer", "CM1L Switch", "CM1L"},
 
-       /* Right Positive PGA Input */
-       {"Right Input Mixer","IN1R Switch","IN1R"},
-       {"Right Input Mixer","IN2R Switch","IN2R"},
-       {"Right Input Mixer","IN3R Switch","IN3R"},
-       {"Right Input Mixer","IN4R Switch","IN4R"},
-       {"Right Input Mixer","IN2L Switch","IN2L"},
 
+       /* Right Positive PGA Input */
+       {"Right Input Mixer", "IN1R Switch", "IN1R"},
+       {"Right Input Mixer", "IN2R Switch", "IN2R"},
+       {"Right Input Mixer", "IN3R Switch", "IN3R"},
+       {"Right Input Mixer", "IN4R Switch", "IN4R"},
+       {"Right Input Mixer", "IN2L Switch", "IN2L"},
        /* Right Negative PGA Input */
-       {"Right Input Mixer","IN1L Switch","IN1L"},
-       {"Right Input Mixer","IN3L Switch","IN3L"},
-       {"Right Input Mixer","IN4L Switch","IN4L"},
-       {"Right Input Mixer","CM1R Switch","CM1R"},
-       {"Right Input Mixer","CM2R Switch","CM2R"},
+       {"Right Input Mixer", "IN1L Switch", "IN1L"},
+       {"Right Input Mixer", "IN3L Switch", "IN3L"},
+       {"Right Input Mixer", "IN4L Switch", "IN4L"},
+       {"Right Input Mixer", "CM1R Switch", "CM1R"},
+       {"Right Input Mixer", "CM2R Switch", "CM2R"},
+
 
        {"CM1L", NULL, "CM"},
        {"CM2L", NULL, "CM"},
        {"CM1R", NULL, "CM"},
        {"CM2R", NULL, "CM"},
 
-       {"Left MicPGA",NULL,"Left Input Mixer"},
-       {"Right MicPGA",NULL,"Right Input Mixer"},
+       {"Left MicPGA", NULL, "Left Input Mixer"},
+       {"Right MicPGA", NULL, "Right Input Mixer"},
 
-       {"Left ADC", NULL, "Left MicPGA"},
-       {"Right ADC", NULL, "Right MicPGA"},
+       {"Left ADC Route", "Analog", "Left MicPGA"},
+       {"Left ADC Route", "Digital", "Left DMIC"},
 
-/* ASI Output Routing */
+       {"Right ADC Route", "Analog", "Right MicPGA"},
+       {"Right ADC Route", "Digital", "Right DMIC"},
+
+       {"Left ADC", NULL, "Left ADC Route"},
+       {"Right ADC", NULL, "Right ADC Route"},
+
+       /* ASI Output Routing */
        {"ADC MiniDSP OUT1", NULL, "Left ADC"},
        {"ADC MiniDSP OUT1", NULL, "Right ADC"},
        {"ADC MiniDSP OUT2", NULL, "Left ADC"},
@@ -3435,459 +1502,673 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={
        {"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"},
-       {"ASI1OUT Route", "ASI2In Bypass","ASI2IN Port"},
-       {"ASI1OUT Route", "ASI3In Bypass","ASI3IN Port"},
-
-       {"ASI2OUT Route", "ASI1 Out","ADC MiniDSP OUT1"},// Port 1
-       {"ASI2OUT Route", "ASI1In Bypass","ASI1IN Port"},
-       {"ASI2OUT Route", "ASI2In Bypass","ASI2IN Port"},
-       {"ASI2OUT Route", "ASI3In Bypass","ASI3IN Port"},
-       {"ASI2OUT Route", "ASI2 Out","ADC MiniDSP OUT2"},// Port 2
-
-       {"ASI3OUT Route", "ASI1 Out","ADC MiniDSP OUT1"},// Port 1
-       {"ASI3OUT Route", "ASI1In Bypass","ASI1IN Port"},
-       {"ASI3OUT Route", "ASI2In Bypass","ASI2IN Port"},
-       {"ASI3OUT Route", "ASI3In Bypass","ASI3IN Port"},
-       {"ASI3OUT Route", "ASI3 Out","ADC MiniDSP OUT3"},// Port 3
-
-       {"ASI1OUT",NULL,"ASI1OUT Route"},
-       {"ASI2OUT",NULL,"ASI2OUT Route"},
-       {"ASI3OUT",NULL,"ASI3OUT Route"},
-
+       {"ASI1OUT Route", "ADC MiniDSP Out1", "ADC MiniDSP OUT1"},
+       {"ASI1OUT Route", "ASI1In Bypass", "ASI1IN Port"},
+       {"ASI1OUT Route", "ASI2In Bypass", "ASI2IN Port"},
+       {"ASI1OUT Route", "ASI3In Bypass", "ASI3IN Port"},
+
+       {"ASI2OUT Route", "ADC MiniDSP Out1", "ADC MiniDSP OUT1"},
+       {"ASI2OUT Route", "ASI1In Bypass", "ASI1IN Port"},
+       {"ASI2OUT Route", "ASI2In Bypass", "ASI2IN Port"},
+       {"ASI2OUT Route", "ASI3In Bypass", "ASI3IN Port"},
+       {"ASI2OUT Route", "ADC MiniDSP Out2", "ADC MiniDSP OUT2"},
+
+       {"ASI3OUT Route", "ADC MiniDSP Out1", "ADC MiniDSP OUT1"},
+       {"ASI3OUT Route", "ASI1In Bypass", "ASI1IN Port"},
+       {"ASI3OUT Route", "ASI2In Bypass", "ASI2IN Port"},
+       {"ASI3OUT Route", "ASI3In Bypass", "ASI3IN Port"},
+       {"ASI3OUT Route", "ADC MiniDSP Out3", "ADC MiniDSP OUT3"},
+
+       {"ASI1OUT", NULL, "ASI1OUT Route"},
+       {"ASI2OUT", NULL, "ASI2OUT Route"},
+       {"ASI3OUT", NULL, "ASI3OUT Route"},
+
+       {"DOUT1 Route", "ASI1 Out", "ASI1OUT"},
+       {"DOUT1 Route", "DIN1 Bypass", "DIN1"},
+       {"DOUT1 Route", "DIN2 Bypass", "DIN2"},
+       {"DOUT1 Route", "DIN3 Bypass", "DIN3"},
+
+       {"DOUT2 Route", "ASI2 Out", "ASI2OUT"},
+       {"DOUT2 Route", "DIN1 Bypass", "DIN1"},
+       {"DOUT2 Route", "DIN2 Bypass", "DIN2"},
+       {"DOUT2 Route", "DIN3 Bypass", "DIN3"},
+
+       {"DOUT3 Route", "ASI3 Out", "ASI3OUT"},
+       {"DOUT3 Route", "DIN1 Bypass", "DIN1"},
+       {"DOUT3 Route", "DIN2 Bypass", "DIN2"},
+       {"DOUT3 Route", "DIN3 Bypass", "DIN3"},
+
+       {"DOUT1", NULL, "DOUT1 Route"},
+       {"DOUT2", NULL, "DOUT2 Route"},
+       {"DOUT3", NULL, "DOUT3 Route"},
 };
 
+#define AIC3262_DAPM_ROUTE_NUM (ARRAY_SIZE(aic3262_dapm_routes)/ \
+                                       sizeof(struct snd_soc_dapm_route))
+/* aic3262_firmware_load:   This function is called by the
+ *             request_firmware_nowait function as soon
+ *             as the firmware has been loaded from the file.
+ *             The firmware structure contains the data and$
+ *             the size of the firmware loaded.
+ * @fw: pointer to firmware file to be dowloaded
+ * @context: pointer variable to codec
+ *
+ * Returns 0 for success.
+ */
+void aic3262_firmware_load(const struct firmware *fw, void *context)
+{
+       struct snd_soc_codec *codec = context;
+       struct aic3262_priv *private_ds = snd_soc_codec_get_drvdata(codec);
+       int ret = 0;
 
-#define AIC3262_DAPM_ROUTE_NUM (sizeof(aic3262_dapm_routes)/sizeof(struct snd_soc_dapm_route))
+       aic3xxx_cfw_lock(private_ds->cfw_p, 1);
+       if (private_ds->cur_fw != NULL)
+               release_firmware(private_ds->cur_fw);
+       private_ds->cur_fw = NULL;
+
+       if (fw != NULL) {
+               dev_dbg(codec->dev, "Firmware binary load\n");
+               private_ds->cur_fw = (void *)fw;
+               ret = aic3xxx_cfw_reload(private_ds->cfw_p,
+                                        (void *)fw->data, fw->size);
+               if (ret < 0) {  /* reload failed */
+                       dev_err(codec->dev, "Firmware binary load failed\n");
+                       release_firmware(private_ds->cur_fw);
+                       private_ds->cur_fw = NULL;
+                       fw = NULL;
+               } else
+                       private_ds->isdefault_fw = 0;
+       }
+
+       if (fw == NULL) {
+               /* either request_firmware or reload failed */
+               dev_dbg(codec->dev, "Default firmware load\n");
+               ret = aic3xxx_cfw_reload(private_ds->cfw_p, default_firmware,
+                                        sizeof(default_firmware));
+               if (ret < 0)
+                       dev_err(codec->dev, "Default firmware load failed\n");
+               else
+                       private_ds->isdefault_fw = 1;
+       }
+       aic3xxx_cfw_lock(private_ds->cfw_p, 0);
+       if (ret >= 0) {
+               /* init function for transition */
+               aic3xxx_cfw_transition(private_ds->cfw_p, "INIT");
+               if (!private_ds->isdefault_fw) {
+                       aic3xxx_cfw_add_modes(codec, private_ds->cfw_p);
+                       aic3xxx_cfw_add_controls(codec, private_ds->cfw_p);
+               }
+               aic3xxx_cfw_setmode_cfg(private_ds->cfw_p, 0, 0);
+       }
+}
 
-/*
- *****************************************************************************
- * Function Definitions
- *****************************************************************************
- */
+/*=========================================================
 
+ headset work and headphone/headset jack interrupt handlers
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_change_page
- * Purpose  : This function is to switch between page 0 and page 1.
+ ========================================================*/
+
+/**
+ * aic3262_hs_jack_report: Report jack notication to upper layor
+ * @codec: pointer variable to codec having information related to codec
+ * @jack: Pointer variable to snd_soc_jack having information of codec
+ *              and pin number$
+ * @report: Provides informaton of whether it is headphone or microphone
  *
- *----------------------------------------------------------------------------
- */
-int aic3262_change_page(struct snd_soc_codec *codec, u8 new_page)
+*/
+static void aic3262_hs_jack_report(struct snd_soc_codec *codec,
+                                  struct snd_soc_jack *jack, int report)
 {
        struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       u8 data[2];
-       int ret = 0;
+       int status, state = 0;
 
-       data[0] = 0;
-       data[1] = new_page;
-       aic3262->page_no = new_page;
+       mutex_lock(&aic3262->mutex);
 
-#if defined(LOCAL_REG_ACCESS)
-       if (codec->hw_write(codec->control_data, data, 2) != 2)
-               ret = -EIO;
-#else
-       ret = snd_soc_write(codec, data[0], data[1]);
-#endif
-       if (ret)
-               printk(KERN_ERR "Error in changing page to %d\n", new_page);
+       /* Sync status */
+       status = snd_soc_read(codec, AIC3262_DAC_FLAG);
+       /* We will check only stereo MIC and headphone */
+       if (status & AIC3262_JACK_WITH_STEREO_HS)
+               state |= SND_JACK_HEADPHONE;
+       if (status & AIC3262_JACK_WITH_MIC)
+               state |= SND_JACK_MICROPHONE;
 
-       /*DBG("# Changing page to %d\r\n", new_page);*/
+       mutex_unlock(&aic3262->mutex);
+
+       snd_soc_jack_report(jack, state, report);
 
-       return ret;
 }
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_change_book
- * Purpose  : This function is to switch between books
+
+/**
+ * aic3262_hs_jack_detect: Detect headphone jack during boot time
+ * @codec: pointer variable to codec having information related to codec
+ * @jack: Pointer variable to snd_soc_jack having information of codec
+ *          and pin number$
+ * @report: Provides informaton of whether it is headphone or microphone
  *
- *----------------------------------------------------------------------------
- */
-int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book)
+*/
+void aic3262_hs_jack_detect(struct snd_soc_codec *codec,
+                           struct snd_soc_jack *jack, int report)
 {
        struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       u8 data[2];
-       int ret = 0;
+       struct aic3262_jack_data *hs_jack = &aic3262->hs_jack;
 
-       data[0] = 0x7F;
-       data[1] = new_book;
-       aic3262->book_no = new_book;
+       hs_jack->jack = jack;
+       hs_jack->report = report;
+       aic3262_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
+}
+EXPORT_SYMBOL_GPL(aic3262_hs_jack_detect);
+/**
+ * aic3262_accessory_work: Finished bottom half work from headphone jack
+ *             insertion interupt
+ * @work: pionter variable to work_struct which is maintaining work queqe
+ *
+*/
+static void aic3262_accessory_work(struct work_struct *work)
+{
+       struct aic3262_priv *aic3262 = container_of(work,
+                                                   struct aic3262_priv,
+                                                   delayed_work.work);
+       struct snd_soc_codec *codec = aic3262->codec;
+       struct aic3262_jack_data *hs_jack = &aic3262->hs_jack;
+       aic3262_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
+}
 
-       ret = aic3262_change_page(codec, 0);
-       if (ret)
-               return ret;
+/**
+ * aic3262_audio_handler: audio interrupt handler called
+ *             when interupt is generated
+ * @irq: provides interupt number which is assigned by aic3262_request_irq,
+ * @data having information of data passed by aic3262_request_irq last arg,
+ *
+ * Return IRQ_HANDLED(means interupt handeled successfully)
+*/
+static irqreturn_t aic3262_audio_handler(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
 
-#if defined(LOCAL_REG_ACCESS)
-       if (codec->hw_write(codec->control_data, data, 2) != 2)
-               ret = -EIO;
-#else
-       ret = snd_soc_write(codec, data[0], data[1]);
-#endif
-       if (ret)
-               printk(KERN_ERR "Error in changing Book\n");
+       queue_delayed_work(aic3262->workqueue, &aic3262->delayed_work,
+                          msecs_to_jiffies(200));
+       return IRQ_HANDLED;
+}
 
-       /*DBG("# Changing book to %d\r\n", new_book);*/
+static irqreturn_t aic3262_button_handler(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
+       input_report_key(aic3262->idev, KEY_MEDIA, 1);
+       mdelay(50);
+       input_report_key(aic3262->idev, KEY_MEDIA, 0);
+       input_sync(aic3262->idev);
 
-       return ret;
+       return IRQ_HANDLED;
 }
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_write_reg_cache
- * Purpose  : This function is to write aic3262 register cache
+
+/**
+ * aic3262_codec_read: provide read api to read aic3262 registe space
+ * @codec: pointer variable to codec having codec information,
+ * @reg: register address,
  *
- *----------------------------------------------------------------------------
+ * Return: Return value will be value read.
  */
-void aic3262_write_reg_cache(struct snd_soc_codec *codec,
-                                          u16 reg, u8 value)
+unsigned int aic3262_codec_read(struct snd_soc_codec *codec, unsigned int reg)
 {
-#if defined(EN_REG_CACHE)
-       u8 *cache = codec->reg_cache;
 
-       if (reg >= AIC3262_CACHEREGNUM)
-               return;
+       u8 value;
 
-       if (cache)
-               cache[reg] = value;
-#endif
+       union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
+       value = aic3262_reg_read(codec->control_data, reg);
+       dev_dbg(codec->dev, "p %d , r 30 %x %x\n",
+               aic_reg->aic326x_register.page,
+               aic_reg->aic326x_register.offset, value);
+       return value;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_read
- * Purpose  : This function is to read the aic3262 register space.
+/**
+ * aic3262_codec_write: provide write api to write at aic3262 registe space
+ * @codec: Pointer variable to codec having codec information,
+ * @reg: Register address,
+ * @value: Value to be written to address space
  *
- *----------------------------------------------------------------------------
+ * Return: Total no of byte written to address space.
  */
+int aic3262_codec_write(struct snd_soc_codec *codec, unsigned int reg,
+                       unsigned int value)
+{
+       union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
+       dev_dbg(codec->dev, "p %d, w 30 %x %x\n",
+               aic_reg->aic326x_register.page,
+               aic_reg->aic326x_register.offset, value);
+       return aic3262_reg_write(codec->control_data, reg, value);
+}
 
-unsigned int aic3262_read(struct snd_soc_codec *codec, unsigned int reg)
+/**
+ * aic3262_add_widget: This function is to add the dapm widgets
+ *       The following are the main widgets supported
+ *           # Left DAC to Left Outputs
+ *           # Right DAC to Right Outputs
+ *               # Left Inputs to Left ADC
+ *               # Right Inputs to Right ADC
+ * @codec: pointer variable to codec having informaton related to codec,
+ *
+ * Return: return 0 on success.
+ */
+static int aic3262_add_widgets(struct snd_soc_codec *codec)
 {
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       u8 value;
-       u8 page = reg / 128;
-       u16 *cache = codec->reg_cache;
-       u16 cmd;
-       u8 buffer[2];
-       int rc = 0;
-       reg = reg % 128;
-
-       if (reg >= AIC3262_CACHEREGNUM) {
-               return 0;
-       }
 
-       if (aic3262->control_type == SND_SOC_I2C) {
-               if (aic3262->page_no != page) {
-               aic3262_change_page(codec, page);
-               }
-               i2c_master_send(codec->control_data, (char *)&reg, 1);
-               i2c_master_recv(codec->control_data, &value, 1);
-               /*DBG("r %2x %02x\r\n", reg, value); */
-       } else if (aic3262->control_type == SND_SOC_SPI) {
-               u16 value;
-
-               /* Do SPI transfer; first 16bits are command; remaining is
-                * register contents */
-               cmd = AIC3262_READ_COMMAND_WORD(reg);
-               buffer[0] = (cmd >> 8) & 0xff;
-               buffer[1] = cmd & 0xff;
-               //rc = spi_write_then_read(aic3262->spi, buffer, 2, buffer, 2);
-
-               if (rc) {
-                       dev_err(&aic3262->spi->dev, "AIC26 reg read error\n");
-                       return -EIO;
-               }
-               value = (buffer[0] << 8) | buffer[1];
-       } else {
-               printk(KERN_ERR "Unknown Interface Type in aic3262_read\n");
-       }
+       snd_soc_dapm_new_controls(&codec->dapm, aic3262_dapm_widgets,
+                                 ARRAY_SIZE(aic3262_dapm_widgets));
+       /* set up audio path interconnects */
+       dev_dbg(codec->dev, "#Completed adding new dapm widget"
+                " controls size=%d\n", ARRAY_SIZE(aic3262_dapm_widgets));
 
-       /* Update the cache before returning with the value */
-       cache[reg] = value;
-       return value;
+       snd_soc_dapm_add_routes(&codec->dapm, aic3262_dapm_routes,
+                               ARRAY_SIZE(aic3262_dapm_routes));
+       dev_dbg(codec->dev, "#Completed adding DAPM routes\n");
+       snd_soc_dapm_new_widgets(&codec->dapm);
+       dev_dbg(codec->dev, "#Completed updating dapm\n");
 
+       return 0;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_write
- * Purpose  : This function is to write to the aic3262 register space.
+/**
+ * aic3262_set_interface_fmt: Setting interface ASI1/2/3 data format
+ * @dai: ponter to dai Holds runtime data for a DAI,
+ * @fmt: asi format info,
+ * @channel: number of channel,
  *
- *----------------------------------------------------------------------------
- */
-int aic3262_write(struct snd_soc_codec *codec, unsigned int reg,
-                                               unsigned int value)
+ * Return: On success return 0.
+*/
+static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
+                                    unsigned int channel)
 {
-       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       u8 data[2];
-       u8 page;
-       int ret = 0;
-
-       page = reg / 128;
-       data[AIC3262_REG_OFFSET_INDEX] = reg % 128;
-       if (aic3262->page_no != page)
-               aic3262_change_page(codec, page);
+       int aif_interface_reg;
+       int aif_bclk_offset_reg;
+       struct snd_soc_codec *codec = dai->codec;
+       u8 iface_val = 0;
+       u8 dsp_a_val = 0;
 
-       /* data is
-        *   D15..D8 aic3262 register offset
-        *   D7...D0 register data
-        */
-       data[AIC3262_REG_DATA_INDEX] = value & AIC3262_8BITS_MASK;
-#if defined(EN_REG_CACHE)
-       if ((page >= 0) & (page <= 4))
-               aic3262_write_reg_cache(codec, reg, value);
+       switch (dai->id) {
+       case 0:
+               aif_interface_reg = AIC3262_ASI1_BUS_FMT;
+               aif_bclk_offset_reg = AIC3262_ASI1_LCH_OFFSET;
+               break;
+       case 1:
+               aif_interface_reg = AIC3262_ASI2_BUS_FMT;
+               aif_bclk_offset_reg = AIC3262_ASI2_LCH_OFFSET;
+               break;
+       case 2:
+               aif_interface_reg = AIC3262_ASI3_BUS_FMT;
+               aif_bclk_offset_reg = AIC3262_ASI3_LCH_OFFSET;
+               break;
+       default:
+               return -EINVAL;
 
-#endif
-       if (!data[AIC3262_REG_OFFSET_INDEX]) {
-               /* if the write is to reg0 update aic3262->page_no */
-               aic3262->page_no = value;
        }
+       /* interface format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               iface_val = 0;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               dsp_a_val = 0x1;        /* Intentionally falling back
+                                          to following case */
+       case SND_SOC_DAIFMT_DSP_B:
+               switch (channel) {
+               case 1:
+                       iface_val = 0x80;       /* Choose mono PCM */
+                       break;
+               case 2:
+                       iface_val = 0x20;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               iface_val = 0x40;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface_val = 0x60;
+               break;
+       default:
+               dev_err(codec->dev, "Invalid DAI interface format\n");
+               return -EINVAL;
+       }
+       snd_soc_update_bits(codec, aif_interface_reg,
+                           AIC3262_ASI_INTERFACE_MASK, iface_val);
+       snd_soc_update_bits(codec, aif_bclk_offset_reg,
+                           AIC3262_BCLK_OFFSET_MASK, dsp_a_val);
+       return 0;
 
-       /*DBG("w %2x %02x\r\n",
-               data[AIC3262_REG_OFFSET_INDEX], data[AIC3262_REG_DATA_INDEX]);*/
-
-#if defined(LOCAL_REG_ACCESS)
-       if (codec->hw_write(codec->control_data, data, 2) != 2)
-               ret = -EIO;
-#else
-       ret = snd_soc_write(codec, data[AIC3262_REG_OFFSET_INDEX],
-                       data[AIC3262_REG_DATA_INDEX]);
-#endif
-       if (ret)
-               printk(KERN_ERR "Error in i2c write\n");
-
-       return ret;
 }
 
-/*
- *------------------------------------------------------------------------------
- * Function : aic3262_write__
- * Purpose  : This function is to write to the aic3262 register space.
- *            (low level).
- *------------------------------------------------------------------------------
+/**
+ * aic3262_hw_params: This function is to set the hardware parameters
+ *             for AIC3262.
+ *             The functions set the sample rate and audio serial data word
+ *             length.
+ * @substream: pointer variable to sn_pcm_substream,
+ * @params: pointer to snd_pcm_hw_params structure,
+ * @dai: ponter to dai Holds runtime data for a DAI,
+ *
+ * Return: Return 0 on success.
  */
-
-int aic3262_write__(struct i2c_client *client, const char *buf, int count)
+int aic3262_hw_params(struct snd_pcm_substream *substream,
+                     struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
-       u8 data[3];
-       int ret;
-       data[0] = *buf;
-       data[1] = *(buf+1);
-       data[2] = *(buf+2);
-       /*DBG("w %2x %02x\r\n",
-               data[AIC3262_REG_OFFSET_INDEX], data[AIC3262_REG_DATA_INDEX]);*/
-       ret = i2c_master_send(client, data, 2);
-       if (ret < 2) {
-               printk(
-               KERN_ERR "I2C write Error : bytes written = %d\n\n", ret);
-               return -EIO;
-       }
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
+       int asi_reg;
+       u8 data = 0;
 
-       return ret;
-}
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_reset_cache
- * Purpose  : This function is to reset the cache.
- *----------------------------------------------------------------------------
- */
-int aic3262_reset_cache(struct snd_soc_codec *codec)
-{
-#if defined(EN_REG_CACHE)
-       if (codec->reg_cache) {
-               memcpy(codec->reg_cache, aic3262_reg, sizeof(aic3262_reg));
-               return 0;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               aic3262->stream_status = 1;
+       else
+               aic3262->stream_status = 0;
+
+       switch (dai->id) {
+       case 0:
+               asi_reg = AIC3262_ASI1_BUS_FMT;
+               break;
+       case 1:
+               asi_reg = AIC3262_ASI2_BUS_FMT;
+               break;
+       case 2:
+               asi_reg = AIC3262_ASI3_BUS_FMT;
+               break;
+       default:
+               return -EINVAL;
        }
 
-       codec->reg_cache = kmemdup(aic3262_reg,
-                       sizeof(aic3262_reg), GFP_KERNEL);
-       if (!codec->reg_cache) {
-               printk(KERN_ERR "aic32x4: kmemdup failed\n");
-               return -ENOMEM;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               data = data | 0x00;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               data |= (0x08);
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               data |= (0x10);
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               data |= (0x18);
+               break;
        }
-#endif
-       return 0;
+
+       /* configure the respective Registers for the above configuration */
+       snd_soc_update_bits(codec, asi_reg,
+                           AIC3262_ASI_DATA_WORD_LENGTH_MASK, data);
+       return aic3262_set_interface_fmt(dai, aic3262->asi_fmt[dai->id],
+                                        params_channels(params));
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_get_divs
- * Purpose  : This function is to get required divisor from the "aic3262_divs"
- *            table.
+/**
+ * aic3262_mute: This function is to mute or unmute the left and right DAC
+ * @dai: ponter to dai Holds runtime data for a DAI,
+ * @mute: integer value one if we using mute else unmute,
  *
- *----------------------------------------------------------------------------
+ * Return: return 0 on success.
  */
-static inline int aic3262_get_divs(int mclk, int rate)
+static int aic3262_mute(struct snd_soc_dai *dai, int mute)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(aic3262_divs); i++) {
-               if ((aic3262_divs[i].rate == rate)
-                   && (aic3262_divs[i].mclk == mclk)) {
-                       DBG(KERN_INFO "#%s: Found Entry %d in Clock_Array\n",
-                               __func__, i);
-                       return i;
-               }
-       }
-       printk(KERN_ERR "Master clock and sample rate is not supported\n");
-       return -EINVAL;
+       struct snd_soc_codec *codec = dai->codec;
+       struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
+
+       dev_dbg(codec->dev, "codec : %s : started\n", __func__);
+       if (dai->id > 2)
+               return -EINVAL;
+       if (mute) {
+               aic3262->mute_asi &= ~((0x1) << dai->id);
+               if (aic3262->mute_asi == 0)
+                       /* Mute only when all asi's are muted */
+                       snd_soc_update_bits_locked(codec,
+                                                  AIC3262_DAC_MVOL_CONF,
+                                                  AIC3262_DAC_LR_MUTE_MASK,
+                                                  AIC3262_DAC_LR_MUTE);
+
+       } else {        /* Unmute */
+               if (aic3262->mute_asi == 0)
+                       /* Unmute for the first asi that need to unmute.
+                          rest unmute will pass */
+                       snd_soc_update_bits_locked(codec,
+                                                  AIC3262_DAC_MVOL_CONF,
+                                                  AIC3262_DAC_LR_MUTE_MASK,
+                                                  0x0);
+               aic3262->mute_asi |= ((0x1) << dai->id);
+       }
+       dev_dbg(codec->dev, "codec : %s : ended\n", __func__);
+       return 0;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_add_widgets
- * Purpose  : This function is to add the dapm widgets
- *            The following are the main widgets supported
- *                # Left DAC to Left Outputs
- *                # Right DAC to Right Outputs
- *               # Left Inputs to Left ADC
- *               # Right Inputs to Right ADC
+/**
+ * aic3262_set_dai_sysclk: This function is to set the DAI system clock
+ * @codec_dai: ponter to dai Holds runtime data for a DAI,
+ * @freq: system clock to be set,
+ * @dir: integer dir,
  *
- *----------------------------------------------------------------------------
+ * Return: return 0 on success.
  */
-static int aic3262_add_widgets(struct snd_soc_codec *codec)
+static int aic3262_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+                                 int clk_id, unsigned int freq, int dir)
 {
-       int ret;
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-#ifndef AIC3262_MULTI_I2S
-       int i;
-       for (i = 0; i < ARRAY_SIZE(aic3262_dapm_widgets); i++)
-               ret = snd_soc_dapm_new_control(dapm, &aic3262_dapm_widgets[i]);
-#else
-       ret = snd_soc_dapm_new_controls(dapm, aic3262_dapm_widgets,
-                       ARRAY_SIZE(aic3262_dapm_widgets));
-       if (ret != 0) {
-               printk(KERN_ERR "#%s: Unable to add DAPM Controls. Err %d\n",
-                                __func__, ret);
+       struct aic3262_priv *aic3262;
+       struct snd_soc_codec *codec;
+
+       codec = codec_dai->codec;
+       aic3262 = snd_soc_codec_get_drvdata(codec);
+       switch (freq) {
+       case AIC3262_FREQ_12000000:
+               aic3262->sysclk = freq;
+               return 0;
+       case AIC3262_FREQ_24000000:
+               aic3262->sysclk = freq;
+               return 0;
+               break;
+       case AIC3262_FREQ_19200000:
+               aic3262->sysclk = freq;
+               return 0;
+               break;
+       case AIC3262_FREQ_38400000:
+               aic3262->sysclk = freq;
+               dev_dbg(codec->dev, "codec: sysclk = %d\n", aic3262->sysclk);
+               return 0;
+               break;
+       case AIC3262_FREQ_12288000:
+               aic3262->sysclk = freq;
+               dev_dbg(codec->dev, "codec: sysclk = %d\n", aic3262->sysclk);
+               return 0;
+               break;
+
        }
-#endif
-       /* set up audio path interconnects */
-       DBG("#Completed adding new dapm widget controls size=%d\n",
-               ARRAY_SIZE(aic3262_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, aic3262_dapm_routes,
-                               ARRAY_SIZE(aic3262_dapm_routes));
-       DBG("#Completed adding DAPM routes\n");
-       snd_soc_dapm_new_widgets(dapm);
-       DBG("#Completed updating dapm\n");
-       return 0;
+       dev_err(codec->dev, "Invalid frequency to set DAI system clock\n");
+
+       return -EINVAL;
 }
-/*
- *----------------------------------------------------------------------------
- * Function : reg_def_conf
- * Purpose  : This function is to reset the codec book 0 registers
+
+/**
+ * aic3262_set_dai_fmt: This function is to set the DAI format
+ * @codec_dai: ponter to dai Holds runtime data for a DAI,
+ * @fmt: asi format info,
  *
- *----------------------------------------------------------------------------
+ * return: return 0 on success.
  */
-int reg_def_conf(struct snd_soc_codec *codec)
+static int aic3262_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
-       int i = 0, ret;
-       DBG(KERN_INFO "#%s: Invoked..\n", __func__);
+       struct aic3262_priv *aic3262;
+       struct snd_soc_codec *codec;
+       u8 iface_val, master;
+       int aif_bclk_wclk_reg;
 
-       ret = aic3262_change_page(codec, 0);
-       if (ret != 0)
-               return ret;
+       codec = codec_dai->codec;
+       aic3262 = snd_soc_codec_get_drvdata(codec);
+       iface_val = 0x00;
+       master = 0x0;
 
-       ret = aic3262_change_book(codec, 0);
-       if (ret != 0)
-               return ret;
+       switch (codec_dai->id) {
+       case 0:
+               aif_bclk_wclk_reg = AIC3262_ASI1_BWCLK_CNTL_REG;
+               break;
+       case 1:
+               aif_bclk_wclk_reg = AIC3262_ASI2_BWCLK_CNTL_REG;
+               break;
+       case 2:
+               aif_bclk_wclk_reg = AIC3262_ASI3_BWCLK_CNTL_REG;
+               break;
+       default:
+               return -EINVAL;
+
+       }
+       aic3262->asi_fmt[codec_dai->id] = fmt;
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               aic3262->master = 1;
+               master |= (AIC3262_WCLK_OUT_MASK | AIC3262_BCLK_OUT_MASK);
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               aic3262->master = 0;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:    /* new case..just for debugging */
+               master |= (AIC3262_WCLK_OUT_MASK);
+               aic3262->master = 0;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               master |= (AIC3262_BCLK_OUT_MASK);
+               aic3262->master = 0;
+               break;
 
-       /* Configure the Codec with the default Initialization Values */
-       for (i = 0; i < reg_init_size; i++) {
-               ret = snd_soc_write(codec, aic3262_reg_init[i].reg_offset,
-                       aic3262_reg_init[i].reg_val);
-               if (ret)
+       default:
+               dev_err(codec->dev, "Invalid DAI master/slave" " interface\n");
+
+               return -EINVAL;
+       }
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+             &nb