asoc: aic326x codec: Add TI codec support
Manoj Gangwal [Thu, 22 Nov 2012 06:12:15 +0000 (11:12 +0530)]
Added support for TI aic326x codec for K3.4

Bug 1179798

Change-Id: Ib9efcf67c7b99cc9c7cfc1d6150aa587b88bd3cd
Signed-off-by: Manoj Gangwal <mgangwal@nvidia.com>
Reviewed-on: http://git-master/r/165611
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Vijay Mali <vmali@nvidia.com>
Reviewed-by: Scott Peterson <speterson@nvidia.com>

sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/aic3xxx/aic3xxx_cfw.h [new file with mode: 0644]
sound/soc/codecs/aic3xxx/aic3xxx_cfw_ops.c [new file with mode: 0644]
sound/soc/codecs/aic3xxx/aic3xxx_cfw_ops.h [new file with mode: 0644]
sound/soc/codecs/aic3xxx_cfw.h [deleted file]
sound/soc/codecs/aic3xxx_cfw_ops.c [deleted file]
sound/soc/codecs/aic3xxx_cfw_ops.h [deleted file]
sound/soc/codecs/tlv320aic326x.c
sound/soc/codecs/tlv320aic326x.h

index a6d57cb..21ab9a3 100644 (file)
@@ -277,6 +277,7 @@ config SND_SOC_TLV320AIC32X4
 config SND_SOC_TLV320AIC3X
        tristate
 
+# TI TLV320AIC3262 codec
 config SND_SOC_TLV320AIC326X
        select AIC3262_CODEC
        tristate "TI AIC326x Codec"
index e2dcaad..da16bac 100644 (file)
@@ -43,8 +43,7 @@ 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 aic3xxx_cfw_ops.o
-snd-soc-tlv320aic326x-objs += aic3262_codec_ops.o aic326x_tiload.o
+snd-soc-tlv320aic326x-objs := tlv320aic326x.o aic3xxx/aic3xxx_cfw_ops.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/aic3xxx/aic3xxx_cfw.h b/sound/soc/codecs/aic3xxx/aic3xxx_cfw.h
new file mode 100644 (file)
index 0000000..2012d51
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ *  aic3xxx_cfw.h  --  SoC audio for TI OMAP44XX SDP
+ *                      Codec Firmware Declarations
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef CFW_FIRMWARE_H_
+#define CFW_FIRMWARE_H_
+
+
+#define CFW_FW_MAGIC 0xC0D1F1ED
+
+
+/** \defgroup pd Arbitrary Limitations */
+/* @{ */
+#ifndef CFW_MAX_ID
+#    define CFW_MAX_ID          (64)   /**<Max length of string identifies*/
+#    define CFW_MAX_VARS       (256)   /**<Number of "variables" alive at the*/
+                                       /**<same time in an acx file*/
+#endif
+
+/* @} */
+
+
+
+/** \defgroup st Enums, Flags, Macros and Supporting Types */
+/* @{ */
+
+
+/**
+ * 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,
+
+       CFW_DEV_AIC3266,
+       CFW_DEV_AIC3285,
+};
+
+/**
+ * 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
+};
+
+#ifndef __cplusplus
+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",
+};
+#endif
+
+/* @} */
+
+/** \defgroup ds Data Structures */
+/* @{ */
+
+
+/**
+* CFW Command
+* These commands do not appear in the register
+* set of the device.
+*/
+enum __attribute__ ((__packed__)) cfw_cmd_id {
+       CFW_CMD_NOP = 0x80,
+       CFW_CMD_DELAY,
+       CFW_CMD_UPDTBITS,
+       CFW_CMD_WAITBITS,
+       CFW_CMD_LOCK,
+       CFW_CMD_BURST,
+       CFW_CMD_RBURST,
+       CFW_CMD_LOAD_VAR_IM,
+       CFW_CMD_LOAD_VAR_ID,
+       CFW_CMD_STORE_VAR,
+       CFW_CMD_COND,
+       CFW_CMD_BRANCH,
+       CFW_CMD_BRANCH_IM,
+       CFW_CMD_BRANCH_ID,
+       CFW_CMD_PRINT,
+       CFW_CMD_OP_ADD = 0xC0,
+       CFW_CMD_OP_SUB,
+       CFW_CMD_OP_MUL,
+       CFW_CMD_OP_DIV,
+       CFW_CMD_OP_AND,
+       CFW_CMD_OP_OR,
+       CFW_CMD_OP_SHL,
+       CFW_CMD_OP_SHR,
+       CFW_CMD_OP_RR,
+       CFW_CMD_OP_XOR,
+       CFW_CMD_OP_NOT,
+       CFW_CMD_OP_LNOT,
+};
+
+/**
+* CFW Delay
+* Used for the cmd command delay
+* Has one parameter of delay time in ms
+*/
+struct cfw_cmd_delay {
+       u16 delay;
+       enum cfw_cmd_id cid;
+       u8 delay_fine;
+};
+
+/**
+* CFW Lock
+* Take codec mutex to avoid clashing with DAPM operations
+*/
+struct cfw_cmd_lock {
+       u16 lock;
+       enum cfw_cmd_id cid;
+       u8 unused;
+};
+
+
+/**
+ * CFW  UPDTBITS, WAITBITS, CHKBITS
+ * Both these cmd commands have same arguments
+ * cid will be used to specify which command it is
+ * has parameters of book, page, offset and mask
+ */
+struct cfw_cmd_bitop {
+       u16 unused1;
+       enum cfw_cmd_id cid;
+       u8 mask;
+};
+
+/**
+ * CFW  CMD Burst header
+ * Burst writes inside command array
+ * Followed by burst address, first byte
+ */
+struct cfw_cmd_bhdr {
+       u16 len;
+       enum cfw_cmd_id cid;
+       u8 unused;
+};
+
+/**
+ * CFW  CMD Burst
+ * Burst writes inside command array
+ * Followed by data to the extent indicated in previous len
+ * Can be safely cast to cfw_burst
+ */
+struct cfw_cmd_burst {
+       u8 book;
+       u8 page;
+       u8 offset;
+       u8 data[1];
+};
+#define CFW_CMD_BURST_LEN(n) (2 + ((n) - 1 + 3)/4)
+
+/**
+ * CFW  CMD Scratch register
+ * For load
+ *  if (svar != dvar)
+ *      dvar = setbits(svar, mask) // Ignore reg
+ *  else
+ *      dvar = setbits(reg, mask)
+ * For store
+ *  if (svar != dvar)
+ *      reg = setbits(svar,  dvar)
+ *  else
+ *      reg =  setbits(svar, mask)
+ *
+ */
+struct cfw_cmd_ldst {
+       u8 dvar;
+       u8 svar;
+       enum cfw_cmd_id cid;
+       u8 mask;
+};
+
+/**
+ * CFW  CMD Conditional
+ * May only precede branch. Followed by nmatch+1 jump
+ * instructions
+ *   cond = svar&mask
+ * At each of the following nmatch+1 branch command
+ *   if (cond == match)
+ *       take the branch
+ */
+struct cfw_cmd_cond {
+       u8 svar;
+       u8 nmatch;
+       enum cfw_cmd_id cid;
+       u8 mask;
+};
+#define CFW_CMD_COND_LEN(nm) (1 + ((nm)+1))
+
+/**
+ * CFW  CMD Goto
+ * For branch, break, continue and stop
+ */
+struct cfw_cmd_branch {
+       u16 address;
+       enum cfw_cmd_id cid;
+       u8 match;
+};
+
+/**
+ * CFW  Debug print
+ * For diagnostics
+ */
+struct cfw_cmd_print {
+       u8 fmtlen;
+       u8 nargs;
+       enum cfw_cmd_id cid;
+       char fmt[1];
+};
+
+#define CFW_CMD_PRINT_LEN(p) (1 + ((p).fmtlen/4) + (((p).nargs + 3)/4))
+#define CFW_CMD_PRINT_ARG(p) (1 + ((p).fmtlen/4))
+
+/**
+ * CFW  Arithmetic and logical operations
+ *  Bit 5 indicates if op1 is indirect
+ *  Bit 6 indicates if op2 is indirect
+ */
+struct cfw_cmd_op {
+       u8 op1;
+       u8 op2;
+       enum cfw_cmd_id cid;
+       u8 dst;
+};
+#define CFW_CMD_OP1_ID     (1u<<5)
+#define CFW_CMD_OP2_ID     (1u<<4)
+
+#define CFW_CMD_OP_START   CFW_CMD_OP_ADD
+#define CFW_CMD_OP_END     (CFW_CMD_OP_LNOT|CFW_CMD_OP1_ID|CFW_CMD_OP2_ID)
+#define CFW_CMD_OP_IS_UNARY(x) \
+                       (((x) == CFW_CMD_OP_NOT) || ((x) == CFW_CMD_OP_LNOT))
+
+
+/**
+ * CFW Register
+ *
+ * A single reg write
+ *
+ */
+union cfw_register {
+       struct {
+               u8 book;
+               u8 page;
+               u8 offset;
+               u8 data;
+       };
+       u32 bpod;
+};
+
+
+
+/**
+ * CFW Command
+ *
+ * Can be a either a
+ *      -# single register write, or
+ *      -# command
+ *
+ */
+union cfw_cmd {
+       struct {
+               u16 unused1;
+               enum cfw_cmd_id cid;
+               u8 unused2;
+       };
+       union cfw_register reg;
+       struct cfw_cmd_delay delay;
+       struct cfw_cmd_lock lock;
+       struct cfw_cmd_bitop bitop;
+       struct cfw_cmd_bhdr bhdr;
+       struct cfw_cmd_burst burst;
+       struct cfw_cmd_ldst ldst;
+       struct cfw_cmd_cond cond;
+       struct cfw_cmd_branch branch;
+       struct cfw_cmd_print print;
+       u8     print_arg[4];
+       struct cfw_cmd_op op;
+};
+
+#define CFW_REG_IS_CMD(x) ((x).cid >= CFW_CMD_DELAY)
+
+/**
+ * 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,
+};
+#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/cmd-commands
+ *
+ */
+struct cfw_block {
+       enum cfw_block_t type;
+       int ncmds;
+       union cfw_cmd cmd[];
+};
+#define CFW_BLOCK_SIZE(ncmds) (sizeof(struct cfw_block) + \
+                               ((ncmds)*sizeof(union cfw_cmd)))
+
+/**
+ * CFW Image
+ *
+ * A downloadable image
+ */
+struct cfw_image {
+       char name[CFW_MAX_ID];  /**< Name of the pfw/overlay/configuration*/
+       char *desc;             /**< User string*/
+       int mute_flags;
+       struct cfw_block *block[CFW_BLOCK_N];
+};
+
+
+
+/**
+ * CFW PLL
+ *
+ * PLL configuration sequence and match critirea
+ */
+struct cfw_pll {
+       char name[CFW_MAX_ID];  /**< Name of the PLL sequence*/
+       char *desc;             /**< User string*/
+       struct cfw_block *seq;
+};
+
+/**
+ * CFW Control
+ *
+ * Run-time control for a process flow
+ */
+struct cfw_control {
+       char name[CFW_MAX_ID];  /**< Control identifier*/
+       char *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;             /**< 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_image *base; /**< Base sequence*/
+       struct cfw_image **ovly_cfg;    /**< Overlay and cfg*/
+                                       /**< patches (if any)*/
+       struct cfw_control **ctrl;      /**< Array of run-time controls*/
+};
+
+#define CFW_OCFG_NDX(p, o, c) (((o)*(p)->ncfg)+(c))
+/**
+ * Process transition
+ *
+ * Sequence for specific state transisitions within the driver
+ *
+ */
+struct cfw_transition {
+       char name[CFW_MAX_ID];  /**< Name of the transition*/
+       char *desc;             /**< User string*/
+       struct cfw_block *block;
+};
+
+/**
+ * Device audio mode
+ *
+ * Link operating modes to process flows,
+ * configurations and sequences
+ *
+ */
+struct cfw_mode {
+       char name[CFW_MAX_ID];
+       char *desc;             /**< User string*/
+       u32 flags;
+       u8 pfw;
+       u8 ovly;
+       u8 cfg;
+       u8 pll;
+       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;              /**< magic number for identifying F/W file*/
+       u32 if_id;              /**< Interface match code */
+       u32 size;               /**< Total size of the firmware (including this header)*/
+       u32 cksum;              /**< CRC32 of the pickled firmware */
+       u32 version;            /**< Firmware version (from CFD file)*/
+       u32 tstamp;             /**< Time stamp of firmware build (epoch seconds)*/
+       char name[CFW_MAX_ID];  /**< Project name*/
+       char *desc;             /**< User string*/
+       enum cfw_dfamily dfamily;       /**< Device family*/
+       enum cfw_device device; /**< Device identifier*/
+       u32 flags;              /**< CFW flags*/
+
+       struct cfw_transition **transition;     /**< Transition sequences*/
+
+       u16 npll;               /**< Number of PLL settings*/
+       struct cfw_pll **pll;   /**< PLL settings*/
+
+       u16 npfw;               /**< Number of process flows*/
+       struct cfw_pfw **pfw;   /**< Process flows*/
+
+       u16 nmode;              /**< Number of operating modes*/
+       struct cfw_mode **mode; /**< Modes*/
+
+       struct cfw_asoc_toc *asoc_toc;  /**< list of amixer controls*/
+};
+
+
+/* @} */
+
+/* **CFW_INTERFACE_ID=0x3FA6D547** */
+
+#endif                         /* CFW_FIRMWARE_H_ */
diff --git a/sound/soc/codecs/aic3xxx/aic3xxx_cfw_ops.c b/sound/soc/codecs/aic3xxx/aic3xxx_cfw_ops.c
new file mode 100644 (file)
index 0000000..83c6b48
--- /dev/null
@@ -0,0 +1,1133 @@
+/*
+ * linux/sound/soc/codecs/aic3xxx/aic3xxx_cfw_ops.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.
+ *
+ */
+
+#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>
+
+/* FIXME to be removed/replaced */
+#define warn(fmt, ...) printk(fmt "\n", ##__VA_ARGS__)
+#define error(fmt, ...)        printk(fmt "\n", ##__VA_ARGS__)
+#define DBG printk
+
+#include "aic3xxx_cfw.h"
+#include "aic3xxx_cfw_ops.h"
+
+
+/* **Code beyond this point is compilable on host** */
+
+/*
+ * 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.
+ */
+#undef CFW_FW_IF_ID
+#define CFW_FW_IF_ID 0x3FA6D547
+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 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);
+static struct cfw_project *aic3xxx_cfw_unpickle(void *pcfw, int n);
+
+static void aic3xxx_wait(struct cfw_state *ps, unsigned int reg, u8 mask,
+                        u8 data);
+static void aic3xxx_set_bits(u8 *data, u8 mask, u8 val);
+static int aic3xxx_driver_init(struct cfw_state *ps);
+
+int aic3xxx_cfw_init(struct cfw_state *ps, const struct aic3xxx_codec_ops *ops,
+                    struct snd_soc_codec *codec)
+{
+       ps->ops = ops;
+       ps->codec = codec;
+       ps->pjt = NULL;
+       mutex_init(&ps->mutex);
+
+       /* FIXME Need a special CONFIG flag to disable debug driver */
+       aic3xxx_driver_init(ps);
+       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_pll = 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;
+       struct cfw_image *patch;
+
+       if (pjt == NULL)
+               return -1;
+       if (ps->cur_pfw < 0 || ps->cur_pfw >= pjt->npfw)
+               return -1;      /* Non miniDSP */
+       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);
+       patch =
+           pfw->ovly_cfg[CFW_OCFG_NDX(pfw, ps->cur_ovly, ps->cur_cfg)];
+       if (pfw->ncfg != 0)
+               return aic3xxx_cfw_dlcfg(ps, patch);
+       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;
+       struct cfw_mode *pmode;
+       int which = 0, ocndx;
+
+       if (pjt == NULL)
+               goto err;
+       if ((mode < 0) || (mode >= pjt->nmode))
+               goto err;
+       if (cfg < 0)
+               goto err;
+       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)
+               aic3xxx_cfw_dlcmds(ps, pjt->mode[ps->cur_mode]->exit);
+       pmode = pjt->mode[mode];
+       if (pjt->mode[mode]->pfw < pjt->npfw) { /* New mode uses miniDSP */
+               struct cfw_image *im;
+               struct cfw_pfw *pfw = pjt->pfw[pmode->pfw];
+
+               /* Make sure cfg is valid and supported in this mode */
+               if (pfw->ncfg == 0 && cfg != 0)
+                       goto err;
+               if (cfg > 0 && cfg >= pfw->ncfg)
+                       goto err;
+
+               /*
+                * 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 |= AIC3XXX_COPS_MDSP_A;
+               if (im->block[CFW_BLOCK_D_INST])
+                       which |= AIC3XXX_COPS_MDSP_D;
+
+               if (pmode->pfw != ps->cur_pfw) {
+
+                       /* New mode requires different PFW */
+                       ps->cur_pfw = pmode->pfw;
+                       ps->cur_ovly = 0;
+                       ps->cur_cfg = 0;
+
+                       which = ps->ops->stop(ps->codec, which);
+                       aic3xxx_cfw_dlimage(ps, im);
+                       if (pmode->ovly && pmode->ovly < pfw->novly) {
+
+                               /* New mode uses ovly */
+                               ocndx = CFW_OCFG_NDX(pfw, pmode->ovly, cfg);
+                               aic3xxx_cfw_dlimage(ps,
+                                                   pfw->ovly_cfg[ocndx]);
+                       } else if (pfw->ncfg > 0) {
+
+                               /* new mode needs only a cfg change */
+                               ocndx = CFW_OCFG_NDX(pfw, 0, cfg);
+                               aic3xxx_cfw_dlimage(ps,
+                                                   pfw->ovly_cfg[ocndx]);
+                       }
+                       ps->ops->restore(ps->codec, which);
+
+               } else if (pmode->ovly != ps->cur_ovly) {
+
+                       /* New mode requires only an ovly change */
+                       ocndx = CFW_OCFG_NDX(pfw, pmode->ovly, cfg);
+                       which = ps->ops->stop(ps->codec, which);
+                       aic3xxx_cfw_dlimage(ps, pfw->ovly_cfg[ocndx]);
+                       ps->ops->restore(ps->codec, which);
+               } else if (pfw->ncfg > 0 && cfg != ps->cur_cfg) {
+
+                       /* New mode requires only a cfg change */
+                       ocndx = CFW_OCFG_NDX(pfw, pmode->ovly, cfg);
+                       aic3xxx_cfw_dlcfg(ps, pfw->ovly_cfg[ocndx]);
+               }
+               ps->cur_ovly = pmode->ovly;
+               ps->cur_cfg = cfg;
+
+               ps->cur_mode = mode;
+               aic3xxx_cfw_set_pll_u(ps, 0);
+
+       } else if (pjt->mode[mode]->pfw != 0xFF) {
+
+               /* Not bypass mode */
+               warn("Bad pfw setting detected (%d).  Max pfw=%d",
+                    pmode->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 */
+       aic3xxx_cfw_dlcmds(ps, pmode->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;
+
+err:
+       DBG("Failed to set firmware mode");
+       return -EINVAL;
+}
+
+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 -EINVAL;
+       for (i = 0; i < CFW_TRN_N; ++i) {
+               if (!strcasecmp(ttype, cfw_transition_id[i])) {
+                       struct cfw_transition *pt = ps->pjt->transition[i];
+                       DBG("Sending transition %s[%d]", ttype, i);
+                       if (pt)
+                               aic3xxx_cfw_dlcmds(ps, pt->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;
+       int pll_id;
+
+       if (pjt == NULL)
+               return -EINVAL;
+       if (ps->cur_mode < 0)
+               return -EINVAL;
+       pll_id = pjt->mode[ps->cur_mode]->pll;
+       if (ps->cur_pll != pll_id) {
+               DBG("Re-configuring PLL: %s==>%d", pjt->pll[pll_id]->name,
+                   pll_id);
+               aic3xxx_cfw_dlcmds(ps, pjt->pll[pll_id]->seq);
+               ps->cur_pll = pll_id;
+       }
+       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) {
+               struct cfw_control *pc = pfw->ctrl[i];
+               if (strcasecmp(cname, pfw->ctrl[i]->name))
+                       continue;
+               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 not found in pfw %s", cname, pfw->name);
+
+       return -EINVAL;
+}
+
+static void aic3xxx_cfw_op(struct cfw_state *ps, unsigned char *var,
+                          struct cfw_cmd_op cmd)
+{
+       u32 op1, op2;
+       u32 cid = cmd.cid;
+
+       op1 = cmd.op1;
+       op2 = cmd.op2;
+       if (cid & CFW_CMD_OP1_ID)
+               op1 = var[op1];
+       if (cid & CFW_CMD_OP2_ID)
+               op2 = var[op2];
+       cid &= ~(CFW_CMD_OP1_ID | CFW_CMD_OP2_ID);
+
+       switch (cid) {
+       case CFW_CMD_OP_ADD:
+               var[cmd.dst] = op1 + op2;
+               break;
+       case CFW_CMD_OP_SUB:
+               var[cmd.dst] = op1 - op2;
+               break;
+       case CFW_CMD_OP_MUL:
+               var[cmd.dst] = op1 * op2;
+               break;
+       case CFW_CMD_OP_DIV:
+               var[cmd.dst] = op1 / op2;
+               break;
+       case CFW_CMD_OP_AND:
+               var[cmd.dst] = op1 & op2;
+               break;
+       case CFW_CMD_OP_OR:
+               var[cmd.dst] = op1 | op2;
+               break;
+       case CFW_CMD_OP_SHL:
+               var[cmd.dst] = (op1 << op2);
+               break;
+       case CFW_CMD_OP_SHR:
+               var[cmd.dst] = (op1 >> op2);
+               break;
+       case CFW_CMD_OP_RR:
+               while (op2--)
+                       var[cmd.dst] = (op1 >> 1) | ((op1 & 1) << 7);
+               break;
+       case CFW_CMD_OP_XOR:
+               var[cmd.dst] = op1 ^ op2;
+               break;
+       case CFW_CMD_OP_NOT:
+               var[cmd.dst] = ~op1;
+               break;
+       case CFW_CMD_OP_LNOT:
+               var[cmd.dst] = !op1;
+               break;
+       default:
+               break;
+       }
+}
+
+static void aic3xxx_cfw_dlcmds(struct cfw_state *ps, struct cfw_block *pb)
+{
+       int pc = 0, cond = 0;
+       unsigned char var[256];
+
+       if (!pb)
+               return;
+       while (pc < pb->ncmds) {
+               union cfw_cmd *c = &(pb->cmd[pc]);
+               if (c->cid != CFW_CMD_BRANCH_IM &&
+                   c->cid != CFW_CMD_BRANCH_ID && c->cid != CFW_CMD_NOP)
+                       cond = 0;
+               switch (c->cid) {
+               case 0 ... (CFW_CMD_NOP - 1):
+                       ps->ops->reg_write(ps->codec, c->reg.bpod,
+                                          c->reg.data);
+                       pc += 1;
+                       break;
+               case CFW_CMD_NOP:
+                       pc += 1;
+                       break;
+               case CFW_CMD_DELAY:
+                       mdelay(c->delay.delay);
+                       pc += 1;
+                       break;
+               case CFW_CMD_UPDTBITS:
+                       ps->ops->set_bits(ps->codec, c[1].reg.bpod,
+                                         c->bitop.mask, c[1].reg.data);
+                       pc += 2;
+                       break;
+               case CFW_CMD_WAITBITS:
+                       aic3xxx_wait(ps, c[1].reg.bpod, c->bitop.mask,
+                                    c[1].reg.data);
+                       pc += 2;
+                       break;
+               case CFW_CMD_LOCK:
+                       if (c->delay.delay)
+                               ps->ops->lock(ps->codec);
+                       else
+                               ps->ops->unlock(ps->codec);
+                       pc += 1;
+                       break;
+               case CFW_CMD_BURST:
+                       ps->ops->bulk_write(ps->codec, c[1].reg.bpod,
+                                           c->bhdr.len, c[1].burst.data);
+                       pc += CFW_CMD_BURST_LEN(c->bhdr.len);
+                       break;
+               case CFW_CMD_RBURST:
+                       ps->ops->bulk_read(ps->codec, c[1].reg.bpod,
+                                           c->bhdr.len, c[1].burst.data);
+                       pc += CFW_CMD_BURST_LEN(c->bhdr.len);
+                       break;
+               case CFW_CMD_LOAD_VAR_IM:
+                       aic3xxx_set_bits(&var[c->ldst.dvar],
+                                        c->ldst.mask, c->ldst.svar);
+                       pc += 1;
+                       break;
+               case CFW_CMD_LOAD_VAR_ID:
+                       if (c->ldst.svar != c->ldst.dvar) {
+                               aic3xxx_set_bits(&var[c->ldst.dvar],
+                                                c->ldst.mask,
+                                                var[c->ldst.svar]);
+                               pc += 1;
+                       } else {
+                               u8 data;
+                               data = ps->ops->reg_read(ps->codec,
+                                                       c[1].reg.bpod);
+                               aic3xxx_set_bits(&var[c->ldst.dvar],
+                                                c->ldst.mask, data);
+                               pc += 2;
+                       }
+                       break;
+               case CFW_CMD_STORE_VAR:
+                       if (c->ldst.svar != c->ldst.dvar)
+                               ps->ops->set_bits(ps->codec,
+                                                 c[1].reg.bpod,
+                                                 var[c->ldst.dvar],
+                                                 var[c->ldst.svar]);
+                       else
+                               ps->ops->set_bits(ps->codec,
+                                                 c[1].reg.bpod,
+                                                 c->ldst.mask,
+                                                 var[c->ldst.svar]);
+                       pc += 2;
+                       break;
+               case CFW_CMD_COND:
+                       cond = var[c->cond.svar] & c->cond.mask;
+                       pc += 1;
+                       break;
+               case CFW_CMD_BRANCH:
+                       pc = c->branch.address;
+                       break;
+               case CFW_CMD_BRANCH_IM:
+                       if (c->branch.match == cond)
+                               pc = c->branch.address;
+                       else
+                               pc += 1;
+                       break;
+               case CFW_CMD_BRANCH_ID:
+                       if (var[c->branch.match] == cond)
+                               pc = c->branch.address;
+                       else
+                               pc += 1;
+                       break;
+               case CFW_CMD_PRINT:
+                       {
+                               union cfw_cmd *parglist =
+                                   c + CFW_CMD_PRINT_ARG(c->print);
+                               printk(c->print.fmt,
+                                    var[parglist->print_arg[0]],
+                                    var[parglist->print_arg[1]],
+                                    var[parglist->print_arg[2]],
+                                    var[parglist->print_arg[3]]);
+                               pc += CFW_CMD_PRINT_LEN(c->print);
+                       }
+                       break;
+               case CFW_CMD_OP_START ... CFW_CMD_OP_END:
+                       aic3xxx_cfw_op(ps, var, c->op);
+                       pc += 1;
+                       break;
+               default:
+                       warn("Unknown cmd command %x. Skipped", c->cid);
+                       pc += 1;
+                       break;
+               }
+       }
+}
+
+static void aic3xxx_wait(struct cfw_state *ps, unsigned int reg, u8 mask,
+                        u8 data)
+{
+       while ((ps->ops->reg_read(ps->codec, reg) & mask) != data)
+               mdelay(2);
+}
+
+static void aic3xxx_set_bits(u8 *data, u8 mask, u8 val)
+{
+       *data = (*data & (~mask)) | (val & mask);
+}
+
+static const struct {
+       u32 mdsp;
+       int buf_a, buf_b;
+       u32 swap;
+} csecs[] = {
+       {
+               .mdsp = AIC3XXX_COPS_MDSP_A,
+               .swap = AIC3XXX_ABUF_MDSP_A,
+               .buf_a = CFW_BLOCK_A_A_COEF,
+               .buf_b = CFW_BLOCK_A_B_COEF
+       },
+       {
+               .mdsp = AIC3XXX_COPS_MDSP_D,
+               .swap = AIC3XXX_ABUF_MDSP_D1,
+               .buf_a = CFW_BLOCK_D_A1_COEF,
+               .buf_b = CFW_BLOCK_D_B1_COEF
+       },
+       {
+               .mdsp = AIC3XXX_COPS_MDSP_D,
+               .swap = AIC3XXX_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 = pb->type;
+       int run_state = ps->ops->lock(ps->codec);
+
+       DBG("Download CTL");
+       for (i = 0; i < sizeof(csecs) / sizeof(csecs[0]); ++i) {
+               if (csecs[i].buf_a != btype && csecs[i].buf_b != btype)
+                       continue;
+               DBG("\tDownload once to %d", btype);
+               aic3xxx_cfw_dlcmds(ps, pb);
+               if (run_state & csecs[i].mdsp) {
+                       DBG("\tDownload again to make sure it reaches B");
+                       aic3xxx_cfw_mute(ps, 1, run_state & mute_flags);
+                       ps->ops->bswap(ps->codec, csecs[i].swap);
+                       aic3xxx_cfw_mute(ps, 0, run_state & mute_flags);
+                       aic3xxx_cfw_dlcmds(ps, pb);
+               }
+               break;
+       }
+       ps->ops->unlock(ps->codec);
+       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->codec);
+       swap = 0;
+       for (i = 0; i < sizeof(csecs) / sizeof(csecs[0]); ++i) {
+               if (!pim->block[csecs[i].buf_a])
+                       continue;
+               aic3xxx_cfw_dlcmds(ps, pim->block[csecs[i].buf_a]);
+               aic3xxx_cfw_dlcmds(ps, pim->block[csecs[i].buf_b]);
+               if (run_state & csecs[i].mdsp)
+                       swap |= csecs[i].swap;
+       }
+       if (swap) {
+               aic3xxx_cfw_mute(ps, 1, run_state & pim->mute_flags);
+               ps->ops->bswap(ps->codec, 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])
+                               continue;
+                       if (!(run_state & csecs[i].mdsp))
+                               continue;
+                       aic3xxx_cfw_dlcmds(ps, pim->block[csecs[i].buf_a]);
+                       aic3xxx_cfw_dlcmds(ps, pim->block[csecs[i].buf_b]);
+               }
+       }
+       ps->ops->unlock(ps->codec);
+       return 0;
+}
+
+static int aic3xxx_cfw_dlimage(struct cfw_state *ps, struct cfw_image *pim)
+{
+       int i;
+
+       if (!pim)
+               return 0;
+       DBG("Download IMAGE %s", pim->name);
+       for (i = 0; i < CFW_BLOCK_N; ++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 & AIC3XXX_COPS_MDSP_D) && (flags & AIC3XXX_COPS_MDSP_A))
+               aic3xxx_cfw_transition_u(ps,
+                                        mute ? "AD_MUTE" : "AD_UNMUTE");
+       else if (flags & AIC3XXX_COPS_MDSP_D)
+               aic3xxx_cfw_transition_u(ps, mute ? "D_MUTE" : "D_UNMUTE");
+       else if (flags & AIC3XXX_COPS_MDSP_A)
+               aic3xxx_cfw_transition_u(ps, mute ? "A_MUTE" : "A_UNMUTE");
+       return 0;
+}
+
+static inline void *aic3xxx_cfw_ndx2ptr(void *p, u8 *base)
+{
+       return &base[(int)p];
+}
+static inline char *aic3xxx_cfw_desc(void *p, u8 *base)
+{
+       if (p)
+               return aic3xxx_cfw_ndx2ptr(p, base);
+       return NULL;
+}
+
+static void aic3xxx_cfw_unpickle_image(struct cfw_image *im, void *p)
+{
+       int i;
+
+       im->desc = aic3xxx_cfw_desc(im->desc, p);
+       for (i = 0; i < CFW_BLOCK_N; ++i)
+               if (im->block[i])
+                       im->block[i] = aic3xxx_cfw_ndx2ptr(im->block[i], p);
+}
+
+static void aic3xxx_cfw_unpickle_control(struct cfw_control *ct, void *p)
+{
+       int i;
+
+       ct->output = aic3xxx_cfw_ndx2ptr(ct->output, p);
+       ct->desc = aic3xxx_cfw_desc(ct->desc, p);
+       for (i = 0; i <= ct->imax; ++i)
+               ct->output[i] = aic3xxx_cfw_ndx2ptr(ct->output[i], p);
+}
+
+static unsigned int crc32(unsigned int *pdata, int n)
+{
+       u32 crc = 0, i, crc_poly = 0x04C11DB7;  /* CRC - 32 */
+       u32 msb;
+       u32 residue_value = 0;
+       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;
+}
+
+static struct cfw_project *aic3xxx_cfw_unpickle(void *p, int n)
+{
+       struct cfw_project *pjt = p;
+       int i, j;
+
+       if (pjt->magic != CFW_FW_MAGIC || pjt->size != n ||
+           pjt->if_id != CFW_FW_IF_ID || !crc_chk(p, n)) {
+               error("Version mismatch: unable to load firmware\n");
+               return NULL;
+       }
+       DBG("Loaded firmware inside unpickle\n");
+
+       pjt->desc = aic3xxx_cfw_desc(pjt->desc, p);
+       pjt->transition = aic3xxx_cfw_ndx2ptr(pjt->transition, p);
+       for (i = 0; i < CFW_TRN_N; i++) {
+               if (!pjt->transition[i])
+                       continue;
+               pjt->transition[i] = aic3xxx_cfw_ndx2ptr(pjt->transition[i], p);
+               pjt->transition[i]->desc = aic3xxx_cfw_desc(
+                                               pjt->transition[i]->desc, p);
+               pjt->transition[i]->block = aic3xxx_cfw_ndx2ptr(
+                                               pjt->transition[i]->block, p);
+       }
+       pjt->pll = aic3xxx_cfw_ndx2ptr(pjt->pll, p);
+       for (i = 0; i < pjt->npll; i++) {
+               pjt->pll[i] = aic3xxx_cfw_ndx2ptr(pjt->pll[i], p);
+               pjt->pll[i]->desc = aic3xxx_cfw_desc(pjt->pll[i]->desc, p);
+               pjt->pll[i]->seq = aic3xxx_cfw_ndx2ptr(pjt->pll[i]->seq, p);
+       }
+
+       pjt->pfw = aic3xxx_cfw_ndx2ptr(pjt->pfw, p);
+       for (i = 0; i < pjt->npfw; i++) {
+               DBG("loading pfw %d\n", i);
+               pjt->pfw[i] = aic3xxx_cfw_ndx2ptr(pjt->pfw[i], p);
+               pjt->pfw[i]->desc = aic3xxx_cfw_desc(pjt->pfw[i]->desc, p);
+               if (pjt->pfw[i]->base) {
+                       pjt->pfw[i]->base = aic3xxx_cfw_ndx2ptr(
+                                                       pjt->pfw[i]->base, p);
+                       aic3xxx_cfw_unpickle_image(pjt->pfw[i]->base, p);
+               }
+               pjt->pfw[i]->ovly_cfg = aic3xxx_cfw_ndx2ptr(
+                                               pjt->pfw[i]->ovly_cfg, p);
+               for (j = 0; j < pjt->pfw[i]->novly * pjt->pfw[i]->ncfg; ++j) {
+                       pjt->pfw[i]->ovly_cfg[j] = aic3xxx_cfw_ndx2ptr(
+                                               pjt->pfw[i]->ovly_cfg[j], p);
+                       aic3xxx_cfw_unpickle_image(pjt->pfw[i]->ovly_cfg[j], p);
+               }
+               if (pjt->pfw[i]->nctrl)
+                       pjt->pfw[i]->ctrl = aic3xxx_cfw_ndx2ptr(
+                                                       pjt->pfw[i]->ctrl, p);
+               for (j = 0; j < pjt->pfw[i]->nctrl; ++j) {
+                       pjt->pfw[i]->ctrl[j] = aic3xxx_cfw_ndx2ptr(
+                                               pjt->pfw[i]->ctrl[j], p);
+                       aic3xxx_cfw_unpickle_control(pjt->pfw[i]->ctrl[j], p);
+               }
+       }
+
+       DBG("loaded pfw's\n");
+       pjt->mode = aic3xxx_cfw_ndx2ptr(pjt->mode, p);
+       for (i = 0; i < pjt->nmode; i++) {
+               pjt->mode[i] = aic3xxx_cfw_ndx2ptr(pjt->mode[i], p);
+               pjt->mode[i]->desc = aic3xxx_cfw_desc(pjt->mode[i]->desc, p);
+               if (pjt->mode[i]->entry)
+                       pjt->mode[i]->entry = aic3xxx_cfw_ndx2ptr(
+                                               pjt->mode[i]->entry, p);
+               if (pjt->mode[i]->exit)
+                       pjt->mode[i]->exit = aic3xxx_cfw_ndx2ptr(
+                                               pjt->mode[i]->exit, p);
+       }
+       if (pjt->asoc_toc)
+               pjt->asoc_toc = aic3xxx_cfw_ndx2ptr(pjt->asoc_toc, p);
+       else {
+               warn("asoc_toc not defined.  FW version mismatch?");
+               return NULL;
+       }
+       DBG("loaded modes");
+       return pjt;
+}
+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;
+}
+
+/* **Code beyond this point is not compilable on host** */
+
+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 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;
+
+       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 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;
+}
+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];
+                       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;
+                       snd_soc_add_codec_controls(codec, generic_control, 1);
+                       DBG("Added control %s", pc->name);
+               }
+       }
+       return 0;
+
+}
+
+
+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;
+}
+
+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;
+}
+
+int aic3xxx_cfw_add_modes(struct snd_soc_codec *codec, struct cfw_state *ps)
+{
+       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_codec_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;
+
+}
+
+#if defined(CONFIG_AIC3111_CODEC) || defined(CONFIG_AIC3111_CORE)
+
+#      define AIC3XXX_CFW_DEVICE "aic3111_cfw"
+#elif defined(CONFIG_AIC3256_CODEC) || defined(CONFIG_AIC3256_CORE)
+
+#      define AIC3XXX_CFW_DEVICE "aic3256_cfw"
+#elif defined(CONFIG_AIC3262_CODEC) || defined(CONFIG_AIC3262_CORE)
+#      define AIC3XXX_CFW_DEVICE "aic3262_cfw"
+#else
+#      define AIC3XXX_CFW_DEVICE "aic3xxx_cfw"
+#endif
+
+static int aic3xxx_cfw_open(struct inode *in, struct file *filp)
+{
+       struct cfw_state *ps = container_of(in->i_cdev, struct cfw_state, cdev);
+       if (ps->is_open) {
+               warn("driver_open: device is already open");
+               return -1;
+       }
+       ps->is_open++;
+       filp->private_data = ps;
+       return 0;
+}
+static int aic3xxx_cfw_release(struct inode *in, struct file *filp)
+{
+       struct cfw_state *ps = filp->private_data;
+       ps->is_open--;
+       return ps->is_open;
+}
+static long aic3xxx_cfw_ioctl(struct file *filp,
+                       unsigned int cmd, unsigned long arg)
+{
+       return 0;
+}
+static ssize_t aic3xxx_cfw_rw(struct file *filp, char __user *buf,
+                          size_t count, loff_t *offset)
+{
+       struct cfw_state *ps = filp->private_data;
+       struct cfw_block *kbuf = kmalloc(count, GFP_KERNEL);
+       if (!kbuf || copy_from_user(kbuf, buf, count)) {
+               warn("dev_rw: Allocation or copy failure");
+               goto err;
+       }
+       if (count != CFW_BLOCK_SIZE(kbuf->ncmds)) {
+               warn("dev_rw: Bad packet received\n");
+               goto err;
+       }
+       aic3xxx_cfw_dlcmds(ps, kbuf);
+       if (copy_to_user(buf, kbuf, count)) {
+               warn("dev_rw: copy failure");
+               goto err;
+       }
+       kfree(kbuf);
+       return count;
+err:
+       kfree(kbuf);
+       return -EINVAL;
+}
+
+static const struct file_operations aic3xxx_cfw_fops = {
+       .owner = THIS_MODULE,
+       .open = aic3xxx_cfw_open,
+       .release = aic3xxx_cfw_release,
+       .read = aic3xxx_cfw_rw,
+       .write = (ssize_t (*)(struct file *filp, const char __user *buf,
+                       size_t count, loff_t *offset))aic3xxx_cfw_rw,
+       .unlocked_ioctl = aic3xxx_cfw_ioctl,
+};
+static int aic3xxx_driver_init(struct cfw_state *ps)
+{
+       int err;
+
+       dev_t dev = MKDEV(0, 0);
+
+       err = alloc_chrdev_region(&dev, 0, 1, AIC3XXX_CFW_DEVICE);
+       if (err < 0) {
+               warn("driver_init: Error allocating device number");
+               return err;
+       }
+       warn("driver_init: Allocated Major Number: %d\n", MAJOR(dev));
+
+       cdev_init(&(ps->cdev), &aic3xxx_cfw_fops);
+       ps->cdev.owner = THIS_MODULE;
+       ps->cdev.ops = &aic3xxx_cfw_fops;
+       ps->is_open = 0;
+
+       err = cdev_add(&(ps->cdev), dev, 1);
+       if (err < 0) {
+               warn("driver_init: cdev_add failed");
+               unregister_chrdev_region(dev, 1);
+               return err;
+       }
+       warn("driver_init: Registered cfw driver");
+       return 0;
+}
+
+MODULE_DESCRIPTION("ASoC tlv320aic3xxx codec driver firmware functions");
+MODULE_AUTHOR("Hari Rajagopala <harik@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/aic3xxx/aic3xxx_cfw_ops.h b/sound/soc/codecs/aic3xxx/aic3xxx_cfw_ops.h
new file mode 100644 (file)
index 0000000..fe5b63c
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * aic3xxx_cfw_ops.h  --  SoC audio for TI OMAP44XX SDP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef AIC3XXX_CFW_OPS_H_
+#define AIC3XXX_CFW_OPS_H_
+
+#include <linux/mutex.h>
+#include <sound/soc.h>
+#include <linux/cdev.h>
+
+struct cfw_project;
+struct aic3xxx_codec_ops;
+
+struct cfw_state {
+       struct cfw_project *pjt;
+       const struct aic3xxx_codec_ops  *ops;
+       struct snd_soc_codec *codec;
+       struct mutex mutex;
+       int cur_mode_id;
+       int cur_pll;
+       int cur_mode;
+       int cur_pfw;
+       int cur_ovly;
+       int cur_cfg;
+       struct cdev cdev;
+       int is_open;
+};
+
+int aic3xxx_cfw_init(struct cfw_state *ps, const struct aic3xxx_codec_ops *ops,
+                    struct snd_soc_codec *codec);
+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 AIC3XXX_COPS_MDSP_D_L    (0x00000002u)
+#define AIC3XXX_COPS_MDSP_D_R    (0x00000001u)
+#define AIC3XXX_COPS_MDSP_D      (AIC3XXX_COPS_MDSP_D_L|AIC3XXX_COPS_MDSP_D_R)
+
+#define AIC3XXX_COPS_MDSP_A_L    (0x00000020u)
+#define AIC3XXX_COPS_MDSP_A_R    (0x00000010u)
+#define AIC3XXX_COPS_MDSP_A      (AIC3XXX_COPS_MDSP_A_L|AIC3XXX_COPS_MDSP_A_R)
+
+#define AIC3XXX_COPS_MDSP_ALL    (AIC3XXX_COPS_MDSP_D|AIC3XXX_COPS_MDSP_A)
+
+#define AIC3XXX_ABUF_MDSP_D1 (0x00000001u)
+#define AIC3XXX_ABUF_MDSP_D2 (0x00000002u)
+#define AIC3XXX_ABUF_MDSP_A  (0x00000010u)
+#define AIC3XXX_ABUF_MDSP_ALL \
+               (AIC3XXX_ABUF_MDSP_D1|AIC3XXX_ABUF_MDSP_D2|AIC3XXX_ABUF_MDSP_A)
+
+
+struct aic3xxx_codec_ops {
+       int (*reg_read) (struct snd_soc_codec *codec, unsigned int reg);
+       int (*reg_write) (struct snd_soc_codec *codec, unsigned int reg,
+                                       unsigned char val);
+       int (*set_bits) (struct snd_soc_codec *codec, unsigned int reg,
+                                       unsigned char mask, unsigned char val);
+       int (*bulk_read) (struct snd_soc_codec *codec, unsigned int reg,
+                                       int count, u8 *buf);
+       int (*bulk_write) (struct snd_soc_codec *codec, unsigned int reg,
+                                       int count, const u8 *buf);
+       int (*lock) (struct snd_soc_codec *codec);
+       int (*unlock) (struct snd_soc_codec *codec);
+       int (*stop) (struct snd_soc_codec *codec, int mask);
+       int (*restore) (struct snd_soc_codec *codec, int runstate);
+       int (*bswap) (struct snd_soc_codec *codec, int mask);
+};
+
+MODULE_LICENSE("GPL");
+
+#endif
diff --git a/sound/soc/codecs/aic3xxx_cfw.h b/sound/soc/codecs/aic3xxx_cfw.h
deleted file mode 100644 (file)
index 12bc855..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-/**
- * \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
deleted file mode 100644 (file)
index 4f8e3a5..0000000
+++ /dev/null
@@ -1,918 +0,0 @@
-#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 = 0;
-       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 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;
-
-       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 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_codec_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_codec_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
deleted file mode 100644 (file)
index 81f6bda..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#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
index 65e92c6..d985311 100644 (file)
@@ -37,9 +37,9 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/pm_runtime.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 <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <linux/mfd/tlv320aic3262-registers.h>
-#include <linux/mfd/tlv320aic3262-core.h>
-#include "aic3xxx_cfw.h"
-#include "aic3xxx_cfw_ops.h"
+#include <linux/mfd/tlv320aic3xxx-core.h>
+#include "aic3xxx/aic3xxx_cfw.h"
+#include "aic3xxx/aic3xxx_cfw_ops.h"
 
 #include "tlv320aic326x.h"
-#include "aic3262_codec_ops.h"
-#include "tlv320aic3262_default_fw.h"
 
 
-#define SOC_DOUBLE_R_SX_TLV3262(xname, xreg_left, xreg_right, xshift,\
-                       xmin, xmax, tlv_array) \
+
+#define SOC_DOUBLE_R_SX_TLV3262(xname, xreg_left, xreg_right, xshift, \
+               xmin, xmax, tlv_array) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
-       SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+                 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} }
+       .private_value = (unsigned long)&(struct soc_mixer_control) \
+               {.reg = xreg_left, \
+                .rreg = xreg_right, .shift = xshift, \
+                .min = xmin, .max = xmax} }
 
-/*****************************************************************************
+/******************************************************************************
                         Macros
 ******************************************************************************
 
@@ -93,9 +92,6 @@ static int aic3262_hw_params(struct snd_pcm_substream *substream,
 
 static int aic3262_mute(struct snd_soc_dai *dai, int mute);
 
-static int aic3262_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-                                 int clk_id, unsigned int freq, int dir);
-
 static int aic3262_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt);
 
 static int aic3262_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
@@ -111,33 +107,37 @@ static int aic3262_set_mode_put(struct snd_kcontrol *kcontrol,
 
 static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
                                 struct snd_kcontrol *kcontrol, int event);
+static int aic3262_get_runstate(struct snd_soc_codec *codec);
+static int aic3262_dsp_pwrdwn_status(struct snd_soc_codec *codec);
+static int aic3262_dsp_pwrup(struct snd_soc_codec *codec, int state);
+static int aic3262_restart_dsps_sync(struct snd_soc_codec *codec, int rs);
 
-static long debug_level;
-module_param(debug_level, long, 0);
-MODULE_PARM_DESC(debug_level, "Debug level for printing");
+static inline unsigned int dsp_non_sync_mode(unsigned int state)
+                       { return (!((state & 0x03) && (state & 0x30))); }
 
 /**
  * snd_soc_put_volsw_2r_sx - double with tlv and variable data size
- *             mixer put callback
+ *  mixer put callback
  * @kcontrol: mixer control
  * @uinfo: control element information
  *
  * Returns 0 for success.
  */
 int snd_soc_put_volsw_2r_sx_aic3262(struct snd_kcontrol *kcontrol,
-                                   struct snd_ctl_elem_value *ucontrol)
+                       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 mask = (1 << mc->shift) - 1;
+       unsigned int mask = (1<<mc->shift)-1;
        int min = mc->min;
        int ret;
        unsigned int val, valr;
 
-       val = ((ucontrol->value.integer.value[0] + min) & 0xff);
+
+       val = ((ucontrol->value.integer.value[0]+min) & 0xff);
        val &= mask;
-       valr = ((ucontrol->value.integer.value[1] + min) & 0xff);
+       valr = ((ucontrol->value.integer.value[1]+min) & 0xff);
        valr &= mask;
 
        ret = 0;
@@ -150,27 +150,6 @@ int snd_soc_put_volsw_2r_sx_aic3262(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static ssize_t debug_level_show(struct device *dev,
-               struct device_attribute *attr,
-               char *buf, size_t count)
-{
-       return sprintf(buf, "%ld\n", debug_level);
-}
-
-static ssize_t debug_level_set(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       int ret;
-
-       ret = kstrtol(buf, 10, &debug_level);
-       if (ret)
-               return ret;
-       return count;
-}
-
-static DEVICE_ATTR(debug_level, 0644, debug_level_show, debug_level_set);
-
 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);
@@ -284,7 +263,6 @@ static const struct snd_kcontrol_new aic3262_snd_controls[] = {
 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,
 };
@@ -292,7 +270,6 @@ struct snd_soc_dai_ops aic3262_asi1_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,
 };
@@ -300,7 +277,6 @@ struct snd_soc_dai_ops aic3262_asi2_dai_ops = {
 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,
 };
@@ -311,14 +287,14 @@ struct snd_soc_dai_driver aic326x_dai_driver[] = {
         .playback = {
                      .stream_name = "ASI1 Playback",
                      .channels_min = 1,
-                     .channels_max = 2,
+                     .channels_max = 8,
                      .rates = AIC3262_RATES,
                      .formats = AIC3262_FORMATS,
                      },
         .capture = {
                     .stream_name = "ASI1 Capture",
                     .channels_min = 1,
-                    .channels_max = 2,
+                    .channels_max = 8,
                     .rates = AIC3262_RATES,
                     .formats = AIC3262_FORMATS,
                     },
@@ -363,148 +339,150 @@ struct snd_soc_dai_driver aic326x_dai_driver[] = {
 
 };
 
-
 static const unsigned int adc_ma_tlv[] = {
-       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),
+       TLV_DB_RANGE_HEAD(7),
+       1, 1, TLV_DB_SCALE_ITEM(-3610, 0, 0),
+       2, 2, TLV_DB_SCALE_ITEM(-3010, 0, 0),
+       3, 3, TLV_DB_SCALE_ITEM(-2660, 0, 0),
+       4, 4, TLV_DB_SCALE_ITEM(-2410, 0, 0),
+       5, 7, TLV_DB_SCALE_ITEM(-2210, 1500, 0),
+       8, 11, TLV_DB_SCALE_ITEM(-1810, 1000, 0),
+       12, 41 , TLV_DB_SCALE_ITEM(-1450, 500, 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", AIC3262_MA_CNTL, 5, 1, 0),
+       SOC_DAPM_SINGLE("IN1 Left Capture 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", AIC3262_MA_CNTL, 4, 1, 0),
+       SOC_DAPM_SINGLE("IN1 Right Capture 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", AIC3262_HP_AMP_CNTL_R1, 7, 1,
+       SOC_DAPM_SINGLE("MA Left Playback Switch", AIC3262_HP_AMP_CNTL_R1, 7, 1,
                        0),
-       SOC_DAPM_SINGLE("LDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("Left DAC Playback Switch", AIC3262_HP_AMP_CNTL_R1,
                        5, 1, 0),
-       SOC_DAPM_SINGLE_TLV("LOL-B1 Volume",
+       SOC_DAPM_SINGLE_TLV("LO Left-B1 Playback 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",
+       SOC_DAPM_SINGLE_TLV("LO Right-B1 Playback Volume",
                                AIC3262_HP_AMP_CNTL_R3, 0, 0x7f, 1, lo_hp_tlv),
-       SOC_DAPM_SINGLE("LDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("Left DAC Playback Switch", AIC3262_HP_AMP_CNTL_R1,
                        2, 1, 0),
-       SOC_DAPM_SINGLE("RDAC Switch", AIC3262_HP_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("Right DAC Playback Switch", AIC3262_HP_AMP_CNTL_R1,
                        4, 1, 0),
-       SOC_DAPM_SINGLE("MAR Switch", AIC3262_HP_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("MA Right Playback 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", AIC3262_LINE_AMP_CNTL_R2,
+       SOC_DAPM_SINGLE("MA Left Playback Switch", AIC3262_LINE_AMP_CNTL_R2,
                        7, 1, 0),
-       SOC_DAPM_SINGLE("IN1L-B Switch", AIC3262_LINE_AMP_CNTL_R2,
+       SOC_DAPM_SINGLE("IN1 Left-B Capture Switch", AIC3262_LINE_AMP_CNTL_R2,
                        3, 1, 0),
-       SOC_DAPM_SINGLE("LDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("Left DAC Playback Switch", AIC3262_LINE_AMP_CNTL_R1,
                        7, 1, 0),
-       SOC_DAPM_SINGLE("RDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("Right DAC Playback 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", AIC3262_LINE_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("LO Left Playback Switch", AIC3262_LINE_AMP_CNTL_R1,
                        2, 1, 0),
-       SOC_DAPM_SINGLE("RDAC Switch", AIC3262_LINE_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("Right DAC Playback Switch", AIC3262_LINE_AMP_CNTL_R1,
                        6, 1, 0),
-       SOC_DAPM_SINGLE("MAR Switch", AIC3262_LINE_AMP_CNTL_R2,
+       SOC_DAPM_SINGLE("MA Right Playback Switch", AIC3262_LINE_AMP_CNTL_R2,
                        6, 1, 0),
-       SOC_DAPM_SINGLE("IN1R-B Switch", AIC3262_LINE_AMP_CNTL_R2,
+       SOC_DAPM_SINGLE("IN1 Right-B Capture 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", AIC3262_SPK_AMP_CNTL_R1,
+       SOC_DAPM_SINGLE("MA Left Playback Switch", AIC3262_SPK_AMP_CNTL_R1,
                        7, 1, 0),
-       SOC_DAPM_SINGLE_TLV("LOL Volume",
+       SOC_DAPM_SINGLE_TLV("LO Left Playback 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",
+       SOC_DAPM_SINGLE_TLV("LO Right Playback Volume",
                                AIC3262_SPK_AMP_CNTL_R3, 0, 0x7f, 1, lo_hp_tlv),
-       SOC_DAPM_SINGLE("MAR Switch",
+       SOC_DAPM_SINGLE("MA Right Playback 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",
+       SOC_DAPM_SINGLE_TLV("LO Left-B2 Playback Volume",
                                AIC3262_RAMP_CNTL_R1, 0, 0x7f, 1, lo_hp_tlv),
-       SOC_DAPM_SINGLE_TLV("IN1L Volume",
+       SOC_DAPM_SINGLE_TLV("IN1 Left Capture Volume",
                                AIC3262_IN1L_SEL_RM, 0, 0x7f, 1, lo_hp_tlv),
-       SOC_DAPM_SINGLE_TLV("IN1R Volume",
+       SOC_DAPM_SINGLE_TLV("IN1 Right Capture Volume",
                                AIC3262_IN1R_SEL_RM, 0, 0x7f, 1, lo_hp_tlv),
-       SOC_DAPM_SINGLE_TLV("LOR-B2 Volume",
+       SOC_DAPM_SINGLE_TLV("LO Right-B2 Playback 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", AIC3262_LMIC_PGA_PIN,
+       SOC_DAPM_SINGLE("IN1 Left Capture Switch", AIC3262_LMIC_PGA_PIN,
                        6, 3, 0),
-       SOC_DAPM_SINGLE("IN2L Switch", AIC3262_LMIC_PGA_PIN,
+       SOC_DAPM_SINGLE("IN2 Left Capture Switch", AIC3262_LMIC_PGA_PIN,
                        4, 3, 0),
-       SOC_DAPM_SINGLE("IN3L Switch", AIC3262_LMIC_PGA_PIN,
+       SOC_DAPM_SINGLE("IN3 Left Capture Switch", AIC3262_LMIC_PGA_PIN,
                        2, 3, 0),
-       SOC_DAPM_SINGLE("IN4L Switch", AIC3262_LMIC_PGA_PM_IN4,
+       SOC_DAPM_SINGLE("IN4 Left Capture Switch", AIC3262_LMIC_PGA_PM_IN4,
                        5, 1, 0),
-       SOC_DAPM_SINGLE("IN1R Switch", AIC3262_LMIC_PGA_PIN,
+       SOC_DAPM_SINGLE("IN1 Right Capture Switch", AIC3262_LMIC_PGA_PIN,
                        0, 3, 0),
-       SOC_DAPM_SINGLE("IN2R Switch", AIC3262_LMIC_PGA_MIN,
+       SOC_DAPM_SINGLE("IN2 Right Capture Switch", AIC3262_LMIC_PGA_MIN,
                        4, 3, 0),
-       SOC_DAPM_SINGLE("IN3R Switch", AIC3262_LMIC_PGA_MIN,
+       SOC_DAPM_SINGLE("IN3 Right Capture Switch", AIC3262_LMIC_PGA_MIN,
                        2, 3, 0),
-       SOC_DAPM_SINGLE("IN4R Switch", AIC3262_LMIC_PGA_PM_IN4,
+       SOC_DAPM_SINGLE("IN4 Right Capture Switch", AIC3262_LMIC_PGA_PM_IN4,
                        4, 1, 0),
-       SOC_DAPM_SINGLE("CM2L Switch", AIC3262_LMIC_PGA_MIN,
+       SOC_DAPM_SINGLE("CM2 Left Capture Switch", AIC3262_LMIC_PGA_MIN,
                        0, 3, 0),
-       SOC_DAPM_SINGLE("CM1L Switch", AIC3262_LMIC_PGA_MIN,
+       SOC_DAPM_SINGLE("CM1 Left Capture 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", AIC3262_RMIC_PGA_PIN,
+       SOC_DAPM_SINGLE("IN1 Right Capture Switch", AIC3262_RMIC_PGA_PIN,
                        6, 3, 0),
-       SOC_DAPM_SINGLE("IN2R Switch", AIC3262_RMIC_PGA_PIN,
+       SOC_DAPM_SINGLE("IN2 Right Capture Switch", AIC3262_RMIC_PGA_PIN,
                        4, 3, 0),
-       SOC_DAPM_SINGLE("IN3R Switch", AIC3262_RMIC_PGA_PIN,
+       SOC_DAPM_SINGLE("IN3 Right Capture Switch", AIC3262_RMIC_PGA_PIN,
                        2, 3, 0),
-       SOC_DAPM_SINGLE("IN4R Switch", AIC3262_RMIC_PGA_PM_IN4,
+       SOC_DAPM_SINGLE("IN4 Right Capture Switch", AIC3262_RMIC_PGA_PM_IN4,
                        5, 1, 0),
-       SOC_DAPM_SINGLE("IN2L Switch", AIC3262_RMIC_PGA_PIN,
+       SOC_DAPM_SINGLE("IN2 Left Capture Switch", AIC3262_RMIC_PGA_PIN,
                        0, 3, 0),
-       SOC_DAPM_SINGLE("IN1L Switch", AIC3262_RMIC_PGA_MIN,
+       SOC_DAPM_SINGLE("IN1 Left Capture Switch", AIC3262_RMIC_PGA_MIN,
                        4, 3, 0),
-       SOC_DAPM_SINGLE("IN3L Switch", AIC3262_RMIC_PGA_MIN,
+       SOC_DAPM_SINGLE("IN3 Left Capture Switch", AIC3262_RMIC_PGA_MIN,
                        2, 3, 0),
-       SOC_DAPM_SINGLE("IN4L Switch", AIC3262_RMIC_PGA_PM_IN4,
+       SOC_DAPM_SINGLE("IN4 Left Capture Switch", AIC3262_RMIC_PGA_PM_IN4,
                        4, 1, 0),
-       SOC_DAPM_SINGLE("CM1R Switch", AIC3262_RMIC_PGA_MIN,
+       SOC_DAPM_SINGLE("CM1 Right Capture Switch", AIC3262_RMIC_PGA_MIN,
                        6, 3, 0),
-       SOC_DAPM_SINGLE("CM2R Switch", AIC3262_RMIC_PGA_MIN,
+       SOC_DAPM_SINGLE("CM2 Right Capture Switch", AIC3262_RMIC_PGA_MIN,
                        0, 3, 0),
 };
 
@@ -720,31 +698,69 @@ static int aic326x_hp_event(struct snd_soc_dapm_widget *w,
                            struct snd_kcontrol *kcontrol, int event)
 {
        int reg_mask = 0;
+       int mute_reg = 0;
        int ret_wbits = 0;
+       u8 hpl_hpr;
 
-       if (w->shift == 1)
-               reg_mask = AIC3262_HPL_POWER_MASK;
-       if (w->shift == 0)
-               reg_mask = AIC3262_HPR_POWER_MASK;
+       if (w->shift == 1) {
+               reg_mask = AIC3262_HPL_POWER_STATUS_MASK;
+               mute_reg = AIC3262_HPL_VOL;
+       }
+       if (w->shift == 0) {
+               reg_mask = AIC3262_HPR_POWER_STATUS_MASK;
+               mute_reg = AIC3262_HPR_VOL;
+       }
        switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+                       snd_soc_update_bits(w->codec, AIC3262_CHARGE_PUMP_CNTL,
+                       AIC3262_DYNAMIC_OFFSET_CALIB_MASK,
+                       AIC3262_DYNAMIC_OFFSET_CALIB);
+                       snd_soc_write(w->codec, mute_reg, 0x80);
+                       snd_soc_update_bits(w->codec, AIC3262_HP_CTL,
+                       AIC3262_HP_STAGE_MASK ,
+                       AIC3262_HP_STAGE_25 << AIC3262_HP_STAGE_SHIFT);
+               break;
+
        case SND_SOC_DAPM_POST_PMU:
-               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+               ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
                                              AIC3262_HP_FLAG, reg_mask,
-                                             reg_mask, TIME_DELAY,
-                                             DELAY_COUNTER);
+                                             reg_mask, AIC326X_TIME_DELAY,
+                                             AIC326X_DELAY_COUNTER);
                if (!ret_wbits) {
                        dev_err(w->codec->dev, "HP POST_PMU timedout\n");
                        return -1;
                }
+               snd_soc_update_bits(w->codec, AIC3262_HP_CTL,
+                       AIC3262_HP_STAGE_MASK ,
+                       AIC3262_HP_STAGE_100 << AIC3262_HP_STAGE_SHIFT);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               snd_soc_update_bits(w->codec, AIC3262_HP_CTL,
+                               AIC3262_HP_STAGE_MASK ,
+                               AIC3262_HP_STAGE_25 << AIC3262_HP_STAGE_SHIFT);
+               hpl_hpr = snd_soc_read(w->codec, AIC3262_HP_AMP_CNTL_R1);
+               if ((hpl_hpr & 0x3) == 0x3) {
+                       snd_soc_update_bits(w->codec, AIC3262_HP_AMP_CNTL_R1,
+                                               AIC3262_HPL_POWER_MASK, 0x0);
+                       mdelay(1);
+                       snd_soc_update_bits(w->codec, AIC3262_HP_AMP_CNTL_R1,
+                                               AIC3262_HPR_POWER_MASK, 0x0);
+               }
                break;
+
        case SND_SOC_DAPM_POST_PMD:
-               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+               ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
                                              AIC3262_HP_FLAG, reg_mask, 0,
-                                             TIME_DELAY, DELAY_COUNTER);
+                                             AIC326X_TIME_DELAY,
+                                               AIC326X_DELAY_COUNTER);
                if (!ret_wbits) {
                        dev_err(w->codec->dev, "HP POST_PMD timedout\n");
                        return -1;
                }
+               snd_soc_write(w->codec, mute_reg, 0xb9);
+               snd_soc_write(w->codec, AIC3262_POWER_CONF,
+                               snd_soc_read(w->codec, AIC3262_POWER_CONF));
                break;
        default:
                BUG();
@@ -773,29 +789,31 @@ static int aic326x_dac_event(struct snd_soc_dapm_widget *w,
        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;
+               reg_mask = AIC3262_LDAC_POWER_STATUS_MASK;
+               run_state_mask = AIC3XXX_COPS_MDSP_D_L;
        }
        if (w->shift == 6) {
-               reg_mask = AIC3262_RDAC_POWER_MASK;
-               run_state_mask = AIC3262_COPS_MDSP_D_R;
+               reg_mask = AIC3262_RDAC_POWER_STATUS_MASK;
+               run_state_mask = AIC3XXX_COPS_MDSP_D_R;
        }
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
 
-               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+               ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
                                              AIC3262_DAC_FLAG, reg_mask,
-                                             reg_mask, TIME_DELAY,
-                                             DELAY_COUNTER);
+                                             reg_mask, AIC326X_TIME_DELAY,
+                                             AIC326X_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;
+               sync_needed = aic3xxx_reg_read(w->codec->control_data,
+                                                       AIC3262_DAC_PRB);
+               non_sync_state = dsp_non_sync_mode(aic3262->dsp_runstate);
+               other_dsp = aic3262->dsp_runstate & AIC3XXX_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);
+                       run_state = aic3262_get_runstate(
+                                               aic3262->codec);
+                       aic3262_dsp_pwrdwn_status(aic3262->codec);
+                       aic3262_dsp_pwrup(aic3262->codec, run_state);
                }
                aic3262->dsp_runstate |= run_state_mask;
 
@@ -806,9 +824,10 @@ static int aic326x_dac_event(struct snd_soc_dapm_widget *w,
                break;
        case SND_SOC_DAPM_POST_PMD:
 
-               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+               ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
                                              AIC3262_DAC_FLAG, reg_mask, 0,
-                                             TIME_DELAY, DELAY_COUNTER);
+                                             AIC326X_TIME_DELAY,
+                                               AIC326X_DELAY_COUNTER);
 
                aic3262->dsp_runstate = (aic3262->dsp_runstate &
                                         ~run_state_mask);
@@ -839,9 +858,9 @@ static int aic326x_spk_event(struct snd_soc_dapm_widget *w,
        int reg_mask;
 
        if (w->shift == 1)
-               reg_mask = AIC3262_SPKL_POWER_MASK;
+               reg_mask = AIC3262_SPKL_POWER_STATUS_MASK;
        if (w->shift == 0)
-               reg_mask = AIC3262_SPKR_POWER_MASK;
+               reg_mask = AIC3262_SPKR_POWER_STATUS_MASK;
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
                mdelay(1);
@@ -914,7 +933,6 @@ static int aic3262_set_mode_put(struct snd_kcontrol *kcontrol,
        else
                ret = aic3xxx_cfw_setmode_cfg(priv_ds->cfw_p,
                                              next_mode, next_cfg);
-
        return ret;
 }
 
@@ -939,25 +957,27 @@ static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
 
        if (w->shift == 7) {
                reg_mask = AIC3262_LADC_POWER_MASK;
-               run_state_mask = AIC3262_COPS_MDSP_A_L;
+               run_state_mask = AIC3XXX_COPS_MDSP_A_L;
        }
        if (w->shift == 6) {
                reg_mask = AIC3262_RADC_POWER_MASK;
-               run_state_mask = AIC3262_COPS_MDSP_A_R;
+               run_state_mask = AIC3XXX_COPS_MDSP_A_R;
        }
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
-               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+               ret_wbits = aic3xxx_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;
+                                             reg_mask, AIC326X_TIME_DELAY,
+                                             AIC326X_DELAY_COUNTER);
+               sync_needed =  aic3xxx_reg_read(w->codec->control_data,
+                                                       AIC3262_DAC_PRB);
+               non_sync_state = dsp_non_sync_mode(aic3262->dsp_runstate);
+               other_dsp = aic3262->dsp_runstate & AIC3XXX_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);
+                       run_state = aic3262_get_runstate(
+                                               aic3262->codec);
+                       aic3262_dsp_pwrdwn_status(aic3262->codec);
+                       aic3262_dsp_pwrup(aic3262->codec, run_state);
                }
                aic3262->dsp_runstate |= run_state_mask;
                if (!ret_wbits) {
@@ -966,9 +986,10 @@ static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
                }
                break;
        case SND_SOC_DAPM_POST_PMD:
-               ret_wbits = aic3262_wait_bits(w->codec->control_data,
+               ret_wbits = aic3xxx_wait_bits(w->codec->control_data,
                                              AIC3262_ADC_FLAG, reg_mask, 0,
-                                             TIME_DELAY, DELAY_COUNTER);
+                                             AIC326X_TIME_DELAY,
+                                               AIC326X_DELAY_COUNTER);
                aic3262->dsp_runstate = (aic3262->dsp_runstate &
                                         ~run_state_mask);
                if (!ret_wbits) {
@@ -984,6 +1005,7 @@ static int aic326x_adc_dsp_event(struct snd_soc_dapm_widget *w,
 }
 
 static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
+       /* TODO: Can we switch these off ? */
        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),
@@ -996,68 +1018,65 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
                           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)),
+       SND_SOC_DAPM_MIXER("HP Left Mixer", SND_SOC_NOPM, 0, 0,
+                          &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)),
-
-
-       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),
-
+       SND_SOC_DAPM_MIXER("HP Right Mixer", SND_SOC_NOPM, 0, 0,
+                          &hpr_output_mixer_controls[0],
+                          ARRAY_SIZE(hpr_output_mixer_controls)),
+
+       SND_SOC_DAPM_PGA_S("HP Left Playback Driver", 3,
+               AIC3262_HP_AMP_CNTL_R1, 1, 0, aic326x_hp_event,
+               SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+               SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_PGA_S("HP Right Playback Driver", 3,
+               AIC3262_HP_AMP_CNTL_R1, 0, 0, aic326x_hp_event,
+               SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+               SND_SOC_DAPM_PRE_PMD | 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)),
+       SND_SOC_DAPM_MIXER("LO Left Mixer", SND_SOC_NOPM, 0, 0,
+                          &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)),
-
-       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),
+       SND_SOC_DAPM_MIXER("LO Right Mixer", SND_SOC_NOPM, 0, 0,
+                          &lor_output_mixer_controls[0],
+                          ARRAY_SIZE(lor_output_mixer_controls)),
 
+       SND_SOC_DAPM_PGA_S("LO Left Playback Driver", 2,
+                       AIC3262_LINE_AMP_CNTL_R1, 1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("LO Right Playback Driver", 2,
+                       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)),
+       SND_SOC_DAPM_MIXER("SPK Left Mixer", SND_SOC_NOPM, 0, 0,
+                          &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)),
-
-       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),
+       SND_SOC_DAPM_MIXER("SPK Right Mixer", SND_SOC_NOPM, 0, 0,
+                          &spkr_output_mixer_controls[0],
+                          ARRAY_SIZE(spkr_output_mixer_controls)),
 
+       SND_SOC_DAPM_PGA_S("SPK Left Playback Driver", 3,
+                       AIC3262_SPK_AMP_CNTL_R1, 1, 0, aic326x_spk_event,
+                       SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+       SND_SOC_DAPM_PGA_S("SPK Right Playback Driver", 3,
+                       AIC3262_SPK_AMP_CNTL_R1, 0, 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)),
-
-       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_MIXER("REC Mixer", SND_SOC_NOPM, 0, 0,
+                          &rec_output_mixer_controls[0],
+                          ARRAY_SIZE(rec_output_mixer_controls)),
 
+       SND_SOC_DAPM_PGA_S("RECP Playback Driver", 3, AIC3262_REC_AMP_CNTL_R5,
+                        7, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("RECM Playback Driver", 3, AIC3262_REC_AMP_CNTL_R5,
+                        6, 0, NULL, 0),
 
        SND_SOC_DAPM_MUX("ASI1LIN Route",
                         SND_SOC_NOPM, 0, 0, &asi1lin_control),
@@ -1097,10 +1116,10 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
                              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),
-       SND_SOC_DAPM_PGA("CM2L", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("CM1R", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("CM2R", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("CM1 Left Capture", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("CM2 Left Capture", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("CM1 Right Capture", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("CM2 Right Capture", SND_SOC_NOPM, 0, 0, NULL, 0),
 
        /* TODO: Can we switch these off ? */
        SND_SOC_DAPM_AIF_OUT("DOUT1", "ASI1 Capture", 0, SND_SOC_NOPM, 0, 0),
@@ -1131,9 +1150,6 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
        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),
 
@@ -1144,72 +1160,80 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = {
                           aic326x_adc_dsp_event, SND_SOC_DAPM_POST_PMU |
                           SND_SOC_DAPM_POST_PMD),
 
-       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_S("Left MicPGA", 0, AIC3262_MICL_PGA, 7, 1, NULL, 0),
+       SND_SOC_DAPM_PGA_S("Right MicPGA", 0, AIC3262_MICR_PGA, 7, 1, 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),
+       SND_SOC_DAPM_PGA_S("MA Left Playback PGA", 1, AIC3262_MA_CNTL,
+                        3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("MA Right Playback PGA", 1, AIC3262_MA_CNTL,
+                        2, 0, NULL, 0),
 
        /* 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)),
+       SND_SOC_DAPM_MIXER("MA Left PGA Mixer", SND_SOC_NOPM, 0, 0,
+                          &mal_pga_mixer_controls[0],
+                          ARRAY_SIZE(mal_pga_mixer_controls)),
 
        /* 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)),
+       SND_SOC_DAPM_MIXER("MA Right PGA Mixer", SND_SOC_NOPM, 0, 0,
+                          &mar_pga_mixer_controls[0],
+                          ARRAY_SIZE(mar_pga_mixer_controls)),
 
        /* 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 */
        SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
-                               &right_input_mixer_controls[0],
-                               ARRAY_SIZE(right_input_mixer_controls)),
-
-       SND_SOC_DAPM_OUTPUT("HPL"),
-       SND_SOC_DAPM_OUTPUT("HPR"),
-       SND_SOC_DAPM_OUTPUT("LOL"),
-       SND_SOC_DAPM_OUTPUT("LOR"),
-       SND_SOC_DAPM_OUTPUT("SPKL"),
-       SND_SOC_DAPM_OUTPUT("SPKR"),
-       SND_SOC_DAPM_OUTPUT("RECP"),
-       SND_SOC_DAPM_OUTPUT("RECM"),
-
-       SND_SOC_DAPM_INPUT("IN1L"),
-       SND_SOC_DAPM_INPUT("IN2L"),
-       SND_SOC_DAPM_INPUT("IN3L"),
-       SND_SOC_DAPM_INPUT("IN4L"),
-       SND_SOC_DAPM_INPUT("IN1R"),
-       SND_SOC_DAPM_INPUT("IN2R"),
-       SND_SOC_DAPM_INPUT("IN3R"),
-       SND_SOC_DAPM_INPUT("IN4R"),
-       SND_SOC_DAPM_INPUT("Left DMIC"),
-       SND_SOC_DAPM_INPUT("Right DMIC"),
+                          &right_input_mixer_controls[0],
+                          ARRAY_SIZE(right_input_mixer_controls)),
+
+       SND_SOC_DAPM_OUTPUT("HP Left Playback"),
+       SND_SOC_DAPM_OUTPUT("HP Right Playback"),
+       SND_SOC_DAPM_OUTPUT("LO Left Playback"),
+       SND_SOC_DAPM_OUTPUT("LO Right Playback"),
+       SND_SOC_DAPM_OUTPUT("SPK Left Playback"),
+       SND_SOC_DAPM_OUTPUT("SPK Right Playback"),
+       SND_SOC_DAPM_OUTPUT("RECP Playback"),
+       SND_SOC_DAPM_OUTPUT("RECM Playback"),
+
+       SND_SOC_DAPM_INPUT("IN1 Left Capture"),
+       SND_SOC_DAPM_INPUT("IN2 Left Capture"),
+       SND_SOC_DAPM_INPUT("IN3 Left Capture"),
+       SND_SOC_DAPM_INPUT("IN4 Left Capture"),
+       SND_SOC_DAPM_INPUT("IN1 Right Capture"),
+       SND_SOC_DAPM_INPUT("IN2 Right Capture"),
+       SND_SOC_DAPM_INPUT("IN3 Right Capture"),
+       SND_SOC_DAPM_INPUT("IN4 Right Capture"),
+       SND_SOC_DAPM_INPUT("Left DMIC Capture"),
+       SND_SOC_DAPM_INPUT("Right DMIC Capture"),
 
        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,
+       SND_SOC_DAPM_SUPPLY_S("PLLCLK", 0, 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_SUPPLY_S("DACCLK", 2, AIC3262_NDAC_DIV_POW_REG, 7, 0,
+                               NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("CODEC_CLK_IN", 1, SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("DAC_MOD_CLK", 3, AIC3262_MDAC_DIV_POW_REG,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("ADCCLK", 2, AIC3262_NADC_DIV_POW_REG,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("ADC_MOD_CLK", 3, AIC3262_MADC_DIV_POW_REG,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("ASI1_BCLK", 4, AIC3262_ASI1_BCLK_N,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("ASI1_WCLK", 4, AIC3262_ASI1_WCLK_N,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("ASI2_BCLK", 4, AIC3262_ASI2_BCLK_N,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("ASI2_WCLK", 4, AIC3262_ASI2_WCLK_N,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("ASI3_BCLK", 4, AIC3262_ASI3_BCLK_N,
+                               7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("ASI3_WCLK", 4, 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",
@@ -1249,122 +1273,89 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] = {
        {"ASI1_BCLK", NULL, "ASI1_BCLK Route"},
        {"ASI2_BCLK", NULL, "ASI2_BCLK Route"},
        {"ASI3_BCLK", NULL, "ASI3_BCLK Route"},
-
-       {"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
        {"DIN1", NULL, "ASI1_BCLK"},
        {"DOUT1", NULL, "ASI1_BCLK"},
        {"DIN1", NULL, "ASI1_WCLK"},
        {"DOUT1", NULL, "ASI1_WCLK"},
-#else
-
 #endif
-       {"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
        {"DIN2", NULL, "ASI2_BCLK"},
        {"DOUT2", NULL, "ASI2_BCLK"},
        {"DIN2", NULL, "ASI2_WCLK"},
        {"DOUT2", NULL, "ASI2_WCLK"},
-#else
-
 #endif
-       {"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
        {"DIN3", NULL, "ASI3_BCLK"},
        {"DOUT3", NULL, "ASI3_BCLK"},
        {"DIN3", NULL, "ASI3_WCLK"},
        {"DOUT3", NULL, "ASI3_WCLK"},
-#else
-
 #endif
+       {"Left DAC", NULL, "DAC_MOD_CLK"},
+       {"Right DAC", NULL, "DAC_MOD_CLK"},
+       /* When we are master, ASI bclk and wclk are generated by
+        * DAC_MOD_CLK, so we put them as dependency for ADC too.
+        */
+       {"Left ADC", NULL, "DAC_MOD_CLK"},
+       {"Right ADC", NULL, "DAC_MOD_CLK"},
+       {"Left ADC", NULL, "ADC_MOD_CLK"},
+       {"Right ADC", NULL, "ADC_MOD_CLK"},
        /* 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"},
+       {"HP Left Mixer", "Left DAC Playback Switch", "Left DAC"},
+       {"HP Left Mixer", "MA Left Playback Switch", "MA Left Playback PGA"},
+       {"HP Left Mixer", "LO Left-B1 Playback Volume", "LO Left Playback"},
 
-       {"HPL Driver", NULL, "HPL Output Mixer"},
-       {"HPR Driver", NULL, "HPR Output Mixer"},
+       {"HP Right Mixer", "LO Right-B1 Playback Volume", "LO Right Playback"},
+       {"HP Right Mixer", "Left DAC Playback Switch", "Left DAC"},
+       {"HP Right Mixer", "Right DAC Playback Switch", "Right DAC"},
+       {"HP Right Mixer", "MA Right Playback Switch", "MA Right Playback PGA"},
 
-       {"HPL", NULL, "HPL Driver"},
-       {"HPR", NULL, "HPR Driver"},
+       {"HP Left Playback Driver", NULL, "HP Left Mixer"},
+       {"HP Right Playback Driver", NULL, "HP Right Mixer"},
 
-       {"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"},
+       {"HP Left Playback", NULL, "HP Left Playback Driver"},
+       {"HP Right Playback", NULL, "HP Right Playback Driver"},
 
-       {"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"},
+       {"LO Left Mixer", "MA Left Playback Switch", "MA Left Playback PGA"},
+       {"LO Left Mixer", "IN1 Left-B Capture Switch", "IN1 Left Capture"},
+       {"LO Left Mixer", "Left DAC Playback Switch", "Left DAC"},
+       {"LO Left Mixer", "Right DAC Playback Switch", "Right DAC"},
 
-       {"LOL Driver", NULL, "LOL Output Mixer"},
-       {"LOR Driver", NULL, "LOR Output Mixer"},
+       {"LO Right Mixer", "LO Left Playback Switch", "LO Left Playback"},
+       {"LO Right Mixer", "Right DAC Playback Switch", "Right DAC"},
+       {"LO Right Mixer", "MA Right Playback Switch", "MA Right Playback PGA"},
+       {"LO Right Mixer", "IN1 Right-B Capture Switch", "IN1 Right Capture"},
 
-       {"LOL", NULL, "LOL Driver"},
-       {"LOR", NULL, "LOR Driver"},
+       {"LO Left Playback Driver", NULL, "LO Left Mixer"},
+       {"LO Right Playback Driver", NULL, "LO Right 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"},
+       {"LO Left Playback", NULL, "LO Left Playback Driver"},
+       {"LO Right Playback", NULL, "LO Right Playback Driver"},
 
-       {"RECP Driver", NULL, "REC Output Mixer"},
-       {"RECM Driver", NULL, "REC Output Mixer"},
+       {"REC Mixer", "LO Left-B2 Playback Volume", "LO Left Playback"},
+       {"REC Mixer", "IN1 Left Capture Volume", "IN1 Left Capture"},
+       {"REC Mixer", "IN1 Right Capture Volume", "IN1 Right Capture"},
+       {"REC Mixer", "LO Right-B2 Playback Volume", "LO Right Playback"},
 
-       {"RECP", NULL, "RECP Driver"},
-       {"RECM", NULL, "RECM Driver"},
+       {"RECP Playback Driver", NULL, "REC Mixer"},
+       {"RECM Playback Driver", NULL, "REC Mixer"},
 
-       {"SPKL Output Mixer", "MAL Switch", "MAL PGA"},
-       {"SPKL Output Mixer", "LOL Volume", "LOL"},
-       {"SPKL Output Mixer", "SPR_IN Switch", "SPKR Output Mixer"},
+       {"RECP Playback", NULL, "RECP Playback Driver"},
+       {"RECM Playback", NULL, "RECM Playback Driver"},
 
-       {"SPKR Output Mixer", "LOR Volume", "LOR"},
-       {"SPKR Output Mixer", "MAR Switch", "MAR PGA"},
+       {"SPK Left Mixer", "MA Left Playback Switch", "MA Left Playback PGA"},
+       {"SPK Left Mixer", "LO Left Playback Volume", "LO Left Playback"},
+       {"SPK Left Mixer", "SPR_IN Switch", "SPK Right Mixer"},
 
+       {"SPK Right Mixer", "LO Right Playback Volume", "LO Right Playback"},
+       {"SPK Right Mixer", "MA Right Playback Switch",
+        "MA Right Playback PGA"},
 
-       {"SPKL Driver", NULL, "SPKL Output Mixer"},
-       {"SPKR Driver", NULL, "SPKR Output Mixer"},
+       {"SPK Left Playback Driver", NULL, "SPK Left Mixer"},
+       {"SPK Right Playback Driver", NULL, "SPK Right Mixer"},
 
-       {"SPKL", NULL, "SPKL Driver"},
-       {"SPKR", NULL, "SPKR Driver"},
+       {"SPK Left Playback", NULL, "SPK Left Playback Driver"},
+       {"SPK Right Playback", NULL, "SPK Right Playback Driver"},
        /* ASI Input routing */
        {"ASI1LIN", NULL, "DIN1"},
        {"ASI1RIN", NULL, "DIN1"},
@@ -1428,18 +1419,15 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] = {
        {"Right DAC", "NULL", "DAC MiniDSP IN3 Route"},
 
        /* Mixer Amplifier */
+       {"MA Left PGA Mixer", "IN1 Left Capture Switch", "IN1 Left Capture"},
+       {"MA Left 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"},
-
+       {"MA Left Playback PGA", NULL, "MA Left PGA Mixer"},
 
-       {"MAR PGA Mixer", "IN1R Switch", "IN1R"},
-       {"MAR PGA Mixer", "Right MicPGA Volume", "Right MicPGA"},
-
-       {"MAR PGA", NULL, "MAR PGA Mixer"},
+       {"MA Right PGA Mixer", "IN1 Right Capture Switch", "IN1 Right Capture"},
+       {"MA Right PGA Mixer", "Right MicPGA Volume", "Right MicPGA"},
 
+       {"MA Right Playback PGA", NULL, "MA Right PGA Mixer"},
 
        /* Virtual connection between DAC and ADC for miniDSP IPC */
        {"ADC DAC Route", "On", "Left ADC"},
@@ -1450,46 +1438,44 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] = {
 
        /* 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", "IN1 Left Capture Switch", "IN1 Left Capture"},
+       {"Left Input Mixer", "IN2 Left Capture Switch", "IN2 Left Capture"},
+       {"Left Input Mixer", "IN3 Left Capture Switch", "IN3 Left Capture"},
+       {"Left Input Mixer", "IN4 Left Capture Switch", "IN4 Left Capture"},
+       {"Left Input Mixer", "IN1 Right Capture Switch", "IN1 Right Capture"},
        /* 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", "IN2 Right Capture Switch", "IN2 Right Capture"},
+       {"Left Input Mixer", "IN3 Right Capture Switch", "IN3 Right Capture"},
+       {"Left Input Mixer", "IN4 Right Capture Switch", "IN4 Right Capture"},
+       {"Left Input Mixer", "CM2 Left Capture Switch", "CM2 Left Capture"},
+       {"Left Input Mixer", "CM1 Left Capture Switch", "CM1 Left Capture"},
 
        /* 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 Input Mixer", "IN1 Right Capture Switch", "IN1 Right Capture"},
+       {"Right Input Mixer", "IN2 Right Capture Switch", "IN2 Right Capture"},
+       {"Right Input Mixer", "IN3 Right Capture Switch", "IN3 Right Capture"},
+       {"Right Input Mixer", "IN4 Right Capture Switch", "IN4 Right Capture"},
+       {"Right Input Mixer", "IN2 Left Capture Switch", "IN2 Left Capture"},
        /* 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", "IN1 Left Capture Switch", "IN1 Left Capture"},
+       {"Right Input Mixer", "IN3 Left Capture Switch", "IN3 Left Capture"},
+       {"Right Input Mixer", "IN4 Left Capture Switch", "IN4 Left Capture"},
+       {"Right Input Mixer", "CM1 Right Capture Switch", "CM1 Right Capture"},
+       {"Right Input Mixer", "CM2 Right Capture Switch", "CM2 Right Capture"},
 
-       {"CM1L", NULL, "CM"},
-       {"CM2L", NULL, "CM"},
-       {"CM1R", NULL, "CM"},
-       {"CM2R", NULL, "CM"},
+       {"CM1 Left Capture", NULL, "CM"},
+       {"CM2 Left Capture", NULL, "CM"},
+       {"CM1 Right Capture", NULL, "CM"},
+       {"CM2 Right Capture", NULL, "CM"},
 
        {"Left MicPGA", NULL, "Left Input Mixer"},
        {"Right MicPGA", NULL, "Right Input Mixer"},
 
        {"Left ADC Route", "Analog", "Left MicPGA"},
-       {"Left ADC Route", "Digital", "Left DMIC"},
+       {"Left ADC Route", "Digital", "Left DMIC Capture"},
 
        {"Right ADC Route", "Analog", "Right MicPGA"},
-       {"Right ADC Route", "Digital", "Right DMIC"},
+       {"Right ADC Route", "Digital", "Right DMIC Capture"},
 
        {"Left ADC", NULL, "Left ADC Route"},
        {"Right ADC", NULL, "Right ADC Route"},
@@ -1555,7 +1541,7 @@ static const struct snd_soc_dapm_route aic3262_dapm_routes[] = {
  *
  * Returns 0 for success.
  */
-void aic3262_firmware_load(const struct firmware *fw, void *context)
+static 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);
@@ -1569,37 +1555,35 @@ void aic3262_firmware_load(const struct firmware *fw, void *context)
        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 */
+               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;
+               }
+       } else {
+               /* request_firmware failed*/
+               /* could not locate file tlv320aic3262_fw_v1.bin
+                       under /vendor/firmare
+               */
+               dev_err(codec->dev, "request_firmware failed\n");
+               ret = -1;
        }
 
-       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 */
+               /*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);
-               }
+               /* add firmware modes */
+               aic3xxx_cfw_add_modes(codec, private_ds->cfw_p);
+               /* add runtime controls */
+               aic3xxx_cfw_add_controls(codec, private_ds->cfw_p);
+               /* set the default firmware mode */
                aic3xxx_cfw_setmode_cfg(private_ds->cfw_p, 0, 0);
        }
+
 }
 
 /*=========================================================
@@ -1608,6 +1592,12 @@ void aic3262_firmware_load(const struct firmware *fw, void *context)
 
  ========================================================*/
 
+enum headset_accessory_state {
+       BIT_NO_ACCESSORY = 0,
+       BIT_HEADSET = (1 << 0),
+       BIT_HEADPHONE = (1 << 1),
+};
+
 /**
  * aic3262_hs_jack_report: Report jack notication to upper layor
  * @codec: pointer variable to codec having information related to codec
@@ -1620,28 +1610,30 @@ 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);
-       int status, state = 0;
+       int status, state = 0, switch_state = BIT_NO_ACCESSORY;
 
        mutex_lock(&aic3262->mutex);
 
        /* Sync status */
        status = snd_soc_read(codec, AIC3262_DAC_FLAG);
-
+       /* We will check only stereo MIC and headphone */
        switch (status & AIC3262_JACK_TYPE_MASK) {
        case AIC3262_JACK_WITH_MIC:
                state |= SND_JACK_HEADSET;
                break;
        case AIC3262_JACK_WITHOUT_MIC:
                state |= SND_JACK_HEADPHONE;
-               break;
-       default:
-               break;
        }
 
        mutex_unlock(&aic3262->mutex);
 
        snd_soc_jack_report(jack, state, report);
 
+       if ((state & SND_JACK_HEADSET) == SND_JACK_HEADSET)
+               switch_state |= BIT_HEADSET;
+       else if (state & SND_JACK_HEADPHONE)
+               switch_state |= BIT_HEADPHONE;
+
 }
 
 /**
@@ -1697,19 +1689,337 @@ static irqreturn_t aic3262_audio_handler(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t aic3262_button_handler(int irq, void *data)
+/**
+ * Methods for CFW Operations
+ *
+ * Due to incompatibilites between structures used by MFD and CFW
+ * we need to transform the register format before linking to
+ * CFW operations.
+ */
+static inline unsigned int aic3262_ops_cfw2reg(unsigned int reg)
+{
+       union cfw_register *c = (union cfw_register *) &reg;
+       union aic3xxx_reg_union mreg;
+
+       mreg.aic3xxx_register.offset = c->offset;
+       mreg.aic3xxx_register.page = c->page;
+       mreg.aic3xxx_register.book = c->book;
+       mreg.aic3xxx_register.reserved = 0;
+
+       return mreg.aic3xxx_register_int;
+}
+static int aic3262_ops_reg_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+       return aic3xxx_reg_read(codec->control_data, aic3262_ops_cfw2reg(reg));
+}
+
+static int aic3262_ops_reg_write(struct snd_soc_codec *codec, unsigned int reg,
+                         unsigned char val)
 {
-       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 aic3xxx_reg_write(codec->control_data,
+                                       aic3262_ops_cfw2reg(reg), val);
+}
 
-       return IRQ_HANDLED;
+static int aic3262_ops_set_bits(struct snd_soc_codec *codec, unsigned int reg,
+                               unsigned char mask, unsigned char val)
+{
+       return aic3xxx_set_bits(codec->control_data,
+                                       aic3262_ops_cfw2reg(reg), mask, val);
+
+}
+
+static int aic3262_ops_bulk_read(struct snd_soc_codec *codec, unsigned int reg,
+                                int count, u8 *buf)
+{
+       return aic3xxx_bulk_read(codec->control_data,
+                                       aic3262_ops_cfw2reg(reg), count, buf);
+}
+
+static int aic3262_ops_bulk_write(struct snd_soc_codec *codec, unsigned int reg,
+                          int count, const u8 *buf)
+{
+       return aic3xxx_bulk_write(codec->control_data,
+                                       aic3262_ops_cfw2reg(reg), count, buf);
 }
 
 /**
+ * aic3262_ops_dlock_lock: To Read the run state of the DAC and ADC
+ *                     by reading the codec and returning the run state
+ * @pv: pointer argument to the codec
+ *
+ * Run state Bit format
+ *
+ * ------------------------------------------------------
+ * D31|..........| D7 | D6|  D5  |  D4  | D3 | D2 | D1  |   D0  |
+ * R               R    R   LADC   RADC    R    R   LDAC   RDAC
+ * ------------------------------------------------------
+ *
+ * R- Reserved
+ * LDAC- Left DAC
+ * RDAC- Right DAC
+ *
+ * Return value  : Integer
+ */
+static int aic3262_ops_lock(struct snd_soc_codec *codec)
+{
+       mutex_lock(&codec->mutex);
+
+       /* Reading the run state of adc and dac */
+       return aic3262_get_runstate(codec);
+
+}
+
+/**
+ * aic3262_ops_dlock_unlock: To unlock the mutex acqiured for reading
+ *                     run state of the codec
+ * @pv: pointer argument to the codec
+ *
+ * Return Value: integer returning 0
+ */
+static int aic3262_ops_unlock(struct snd_soc_codec *codec)
+{
+       /*Releasing the lock of mutex */
+       mutex_unlock(&codec->mutex);
+       return 0;
+}
+
+/**
+ * aic3262_ops_dlock_stop:
+ * @pv: 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
+ *
+ * Return: return run state
+ */
+static int aic3262_ops_stop(struct snd_soc_codec *codec, int mask)
+{
+       int run_state = 0;
+
+       run_state = aic3262_get_runstate(codec);
+
+       if (mask & AIC3XXX_COPS_MDSP_A)
+               aic3xxx_set_bits(codec->control_data,
+                                AIC3262_ADC_DATAPATH_SETUP, 0xC0, 0);
+
+       if (mask & AIC3XXX_COPS_MDSP_D)
+               aic3xxx_set_bits(codec->control_data,
+                                AIC3262_DAC_DATAPATH_SETUP, 0xC0, 0);
+
+       if ((mask & AIC3XXX_COPS_MDSP_A) &&
+               !aic3xxx_wait_bits(codec->control_data,
+                                     AIC3262_ADC_FLAG, AIC3262_ADC_POWER_MASK,
+                                     0, AIC326X_TIME_DELAY,
+                                       AIC326X_DELAY_COUNTER))
+               goto err;
+
+       if ((mask & AIC3XXX_COPS_MDSP_D) &&
+               !aic3xxx_wait_bits(codec->control_data,
+                                     AIC3262_DAC_FLAG, AIC3262_DAC_POWER_MASK,
+                                     0, AIC326X_TIME_DELAY,
+                                       AIC326X_DELAY_COUNTER))
+               goto err;
+
+       return run_state;
+err:
+       dev_err(codec->dev, "Unable to turn off ADCs or DACs at [%s:%d]",
+                               __FILE__, __LINE__);
+       return -EINVAL;
+}
+
+/**
+ * aic3262_ops_dlock_restore: To unlock the mutex acqiured for reading
+ * @pv: pointer argument to the codec,run_state
+ * @run_state:  run state of the codec and to restore the states of the dsp
+ *
+ * Return Value        : integer returning 0
+ */
+
+static int aic3262_ops_restore(struct snd_soc_codec *codec, int run_state)
+{
+       int sync_state;
+
+       /* This is for read the sync mode register state  */
+       sync_state = aic3xxx_reg_read(codec->control_data, AIC3262_DAC_PRB);
+
+       /*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(codec, run_state);
+       else
+               aic3262_dsp_pwrup(codec, run_state);
+
+       return 0;
+}
+
+/**
+ * aic3262_ops_adaptivebuffer_swap: To swap the coefficient buffers
+ *                              of minidsp according to mask
+ * @pv: pointer argument to the codec,
+ * @mask: tells us which dsp has to be chosen for swapping
+ *
+ * Return Value    : returning 0 on success
+ */
+int aic3262_ops_adaptivebuffer_swap(struct snd_soc_codec *codec, int mask)
+{
+       const int sbuf[][2] = {
+               { AIC3XXX_ABUF_MDSP_A, AIC3262_ADC_ADAPTIVE_CRAM_REG },
+               { AIC3XXX_ABUF_MDSP_D1, AIC3262_DAC_ADAPTIVE_BANK1_REG },
+               { AIC3XXX_ABUF_MDSP_D2, AIC3262_DAC_ADAPTIVE_BANK2_REG },
+       };
+       int i;
+
+       for (i = 0; i < sizeof(sbuf)/sizeof(sbuf[0]); ++i) {
+               if (!(mask & sbuf[i][0]))
+                       continue;
+               aic3xxx_set_bits(codec->control_data, sbuf[i][1], 0x1, 0x1);
+               if (!aic3xxx_wait_bits(codec->control_data,
+                                               sbuf[i][1], 0x1, 0, 15, 1))
+                       goto err;
+       }
+       return 0;
+err:
+       dev_err(codec->dev, "miniDSP buffer swap failure at [%s:%d]",
+                               __FILE__, __LINE__);
+       return -EINVAL;
+}
+
+/**
+ * get_runstate: To read the current state of the dac's and adc's
+ * @ps: pointer argument to the codec
+ *
+ * Return Value        : returning the runstate
+ */
+static int aic3262_get_runstate(struct snd_soc_codec *codec)
+{
+       unsigned int dac, adc;
+       /* Read the run state */
+       dac = aic3xxx_reg_read(codec->control_data, AIC3262_DAC_FLAG);
+       adc = aic3xxx_reg_read(codec->control_data, AIC3262_ADC_FLAG);
+
+       return (((adc>>6)&1)<<5)  |
+               (((adc>>2)&1)<<4) |
+               (((dac>>7)&1)<<1) |
+               (((dac>>3)&1)<<0);
+}
+
+/**
+ * aic3262_dsp_pwrdwn_status: To read the status of dsp's
+ * @pv: pointer argument to the codec , cur_state of dac's and adc's
+ *
+ * Return Value        : integer returning 0
+ */
+static int aic3262_dsp_pwrdwn_status(struct snd_soc_codec *codec)
+{
+
+       aic3xxx_set_bits(codec->control_data,
+                       AIC3262_ADC_DATAPATH_SETUP, 0XC0, 0);
+       aic3xxx_set_bits(codec->control_data,
+                       AIC3262_DAC_DATAPATH_SETUP, 0XC0, 0);
+
+       if (!aic3xxx_wait_bits(codec->control_data, AIC3262_ADC_FLAG,
+                             AIC3262_ADC_POWER_MASK, 0, AIC326X_TIME_DELAY,
+                             AIC326X_DELAY_COUNTER))
+               goto err;
+       if (!aic3xxx_wait_bits(codec->control_data, AIC3262_DAC_FLAG,
+                       AIC3262_DAC_POWER_MASK, 0, AIC326X_TIME_DELAY,
+                       AIC326X_DELAY_COUNTER))
+               goto err;
+
+       return 0;
+err:
+       dev_err(codec->dev, "DAC/ADC Power down timedout at [%s:%d]",
+                               __FILE__, __LINE__);
+       return -EINVAL;
+}
+static int aic3262_dsp_pwrup(struct snd_soc_codec *codec, int state)
+{
+       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 & AIC3XXX_COPS_MDSP_A_L) {
+               adc_reg_mask |= 0x80;
+               adc_power_mask |= AIC3262_LADC_POWER_MASK;
+       }
+       if (state & AIC3XXX_COPS_MDSP_A_R) {
+               adc_reg_mask |= 0x40;
+               adc_power_mask |= AIC3262_RADC_POWER_MASK;
+       }
+
+       if (state & AIC3XXX_COPS_MDSP_A)
+               aic3xxx_set_bits(codec->control_data,
+                                       AIC3262_ADC_DATAPATH_SETUP, 0XC0,
+                                       adc_reg_mask);
+
+       if (state & AIC3XXX_COPS_MDSP_D_L) {
+               dac_reg_mask |= 0x80;
+               dac_power_mask |= AIC3262_LDAC_POWER_STATUS_MASK;
+       }
+       if (state & AIC3XXX_COPS_MDSP_D_R) {
+               dac_reg_mask |= 0x40;
+               dac_power_mask |= AIC3262_RDAC_POWER_STATUS_MASK;
+       }
+
+       if (state & AIC3XXX_COPS_MDSP_D)
+               aic3xxx_set_bits(codec->control_data,
+                                       AIC3262_DAC_DATAPATH_SETUP, 0XC0,
+                                       dac_reg_mask);
+
+       if (state & AIC3XXX_COPS_MDSP_A) {
+               ret_wbits = aic3xxx_wait_bits(codec->control_data,
+                               AIC3262_ADC_FLAG, AIC3262_ADC_POWER_MASK,
+                               adc_power_mask, AIC326X_TIME_DELAY,
+                               AIC326X_DELAY_COUNTER);
+               if (!ret_wbits)
+                       dev_err(codec->dev, "ADC Power down timedout\n");
+       }
+
+       if (state & AIC3XXX_COPS_MDSP_D) {
+               ret_wbits = aic3xxx_wait_bits(codec->control_data,
+                               AIC3262_DAC_FLAG, AIC3262_DAC_POWER_MASK,
+                               dac_power_mask, AIC326X_TIME_DELAY,
+                               AIC326X_DELAY_COUNTER);
+               if (!ret_wbits)
+                       dev_err(codec->dev, "ADC Power down timedout\n");
+       }
+
+       return 0;
+}
+
+static int aic3262_restart_dsps_sync(struct snd_soc_codec *codec, int run_state)
+{
+
+       aic3262_dsp_pwrdwn_status(codec);
+       aic3262_dsp_pwrup(codec, run_state);
+
+       return 0;
+}
+
+static 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,
+};
+
+
+/**
  * aic3262_codec_read: provide read api to read aic3262 registe space
  * @codec: pointer variable to codec having codec information,
  * @reg: register address,
@@ -1721,11 +2031,11 @@ unsigned int aic3262_codec_read(struct snd_soc_codec *codec, unsigned int reg)
 
        u8 value;
 
-       union aic326x_reg_union *aic_reg = (union aic326x_reg_union *) &reg;
-       value = aic3262_reg_read(codec->control_data, reg);
+       union aic3xxx_reg_union *aic_reg = (union aic3xxx_reg_union *) &reg;
+       value = aic3xxx_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);
+               aic_reg->aic3xxx_register.page,
+               aic_reg->aic3xxx_register.offset, value);
        return value;
 }
 
@@ -1740,40 +2050,11 @@ unsigned int aic3262_codec_read(struct snd_soc_codec *codec, unsigned int reg)
 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;
+       union aic3xxx_reg_union *aic_reg = (union aic3xxx_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);
-}
-
-/**
- * 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)
-{
-
-       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));
-
-       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;
+               aic_reg->aic3xxx_register.page,
+               aic_reg->aic3xxx_register.offset, value);
+       return aic3xxx_reg_write(codec->control_data, reg, value);
 }
 
 /**
@@ -1785,7 +2066,7 @@ static int aic3262_add_widgets(struct snd_soc_codec *codec)
  * Return: On success return 0.
 */
 static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
-                                    unsigned int channel)
+                                       unsigned int channel)
 {
        int aif_interface_reg;
        int aif_bclk_offset_reg;
@@ -1816,19 +2097,14 @@ static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
                iface_val = 0;
                break;
        case SND_SOC_DAIFMT_DSP_A:
-               dsp_a_val = 0x1;        /* Intentionally falling back
-                                          to following case */
+               dsp_a_val = 0x1;        /* Intentionally falling through */
        case SND_SOC_DAIFMT_DSP_B:
-               switch (channel) {
-               case 1:
+               if (channel == 1)
                        iface_val = 0x80;       /* Choose mono PCM */
-                       break;
-               case 2:
-                       iface_val = 0x20;
-                       break;
-               default:
+               else if (channel <= 8)
+                       iface_val = 0x20;       /* choose multichannel PCM */
+               else
                        return -EINVAL;
-               }
                break;
        case SND_SOC_DAIFMT_RIGHT_J:
                iface_val = 0x40;
@@ -1841,9 +2117,9 @@ static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
                return -EINVAL;
        }
        snd_soc_update_bits(codec, aif_interface_reg,
-                           AIC3262_ASI_INTERFACE_MASK, iface_val);
+                                       AIC3262_ASI_INTERFACE_MASK, iface_val);
        snd_soc_update_bits(codec, aif_bclk_offset_reg,
-                           AIC3262_BCLK_OFFSET_MASK, dsp_a_val);
+                                       AIC3262_BCLK_OFFSET_MASK, dsp_a_val);
        return 0;
 
 }
@@ -1860,13 +2136,15 @@ static int aic3262_set_interface_fmt(struct snd_soc_dai *dai, unsigned int fmt,
  * Return: Return 0 on success.
  */
 int aic3262_hw_params(struct snd_pcm_substream *substream,
-                     struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+                       struct snd_pcm_hw_params *params,
+                       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);
-       int asi_reg;
-       u8 data = 0;
+       int asi_reg, ret = 0;
+       u8 data = 0, value = 0, val = 0, wclk_div = 0, bclk_div = 0;
+       unsigned int channels = params_channels(params);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                aic3262->stream_status = 1;
@@ -1902,11 +2180,52 @@ int aic3262_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
+       /* Configure TDM for multi chennels */
+       switch (channels) {
+       case 4:
+               value = value | 0x40;
+               bclk_div = 0x03;
+               wclk_div = 0x40;
+               break;
+       case 6:
+               bclk_div = 0x02;
+               wclk_div = 0x60;
+               value = value | 0x80;
+               break;
+       case 8:
+               bclk_div = 0x01;
+               wclk_div = 0x00;
+               value = value | 0xC0;
+               break;
+       default:
+               bclk_div = 0x04;
+               wclk_div = 0x20;
+       }
+
+       snd_soc_update_bits(codec, AIC3262_ASI1_CHNL_SETUP,
+                               AIC3262_ASI1_CHNL_MASK, value);
+
+       snd_soc_update_bits(codec, AIC3262_ASI1_BCLK_N,
+                               AIC3262_ASI1_BCLK_N_MASK, bclk_div);
+
+       snd_soc_update_bits(codec, AIC3262_ASI1_WCLK_N,
+                               AIC3262_ASI1_WCLK_N_MASK, wclk_div);
+
+
+       val = snd_soc_read(codec, AIC3262_ASI1_BUS_FMT);
+       val = snd_soc_read(codec, AIC3262_ASI1_CHNL_SETUP);
+
        /* 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));
+       ret = aic3262_set_interface_fmt(dai, aic3262->asi_fmt[dai->id],
+                                        channels);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to set hardware params for AIC3262\n");
+               return ret;
+       }
+
+       return 0;
 }
 
 /**
@@ -1947,50 +2266,6 @@ static int aic3262_mute(struct snd_soc_dai *dai, int mute)
        return 0;
 }
 
-/**
- * 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_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-                                 int clk_id, unsigned int freq, int dir)
-{
-       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;
-
-       }
-       dev_err(codec->dev, "Invalid frequency to set DAI system clock\n");
-
-       return -EINVAL;
-}
 
 /**
  * aic3262_set_dai_fmt: This function is to set the DAI format
@@ -2035,7 +2310,7 @@ static int aic3262_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_CBS_CFS:
                aic3262->master = 0;
                break;
-       case SND_SOC_DAIFMT_CBS_CFM:    /* new case..just for debugging */
+       case SND_SOC_DAIFMT_CBS_CFM:    /* new case..for debug purpose */
                master |= (AIC3262_WCLK_OUT_MASK);
                aic3262->master = 0;
                break;
@@ -2108,6 +2383,7 @@ static int aic3262_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
        /* TODO: How to select low/high clock range? */
 
        aic3xxx_cfw_set_pll(aic3262->cfw_p, dai->id);
+
        return 0;
 }
 
@@ -2144,6 +2420,7 @@ static int aic3262_set_bias_level(struct snd_soc_codec *codec,
                 */
                dev_dbg(codec->dev, "set_bias_stby\n");
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       pm_runtime_get_sync(codec->dev);
                        snd_soc_update_bits(codec, AIC3262_POWER_CONF,
                                            (AIC3262_AVDD_TO_DVDD_MASK |
                                             AIC3262_EXT_ANALOG_SUPPLY_MASK),
@@ -2152,21 +2429,26 @@ static int aic3262_set_bias_level(struct snd_soc_codec *codec,
                                            AIC3262_CHIP_REF_PWR_ON_MASK,
                                            AIC3262_CHIP_REF_PWR_ON);
                        mdelay(40);
-               }
 
+                       snd_soc_update_bits(codec, AIC3262_CHARGE_PUMP_CNTL,
+                               AIC3262_DYNAMIC_OFFSET_CALIB_MASK,
+                               AIC3262_DYNAMIC_OFFSET_CALIB);
+               }
                break;
 
                /* Off, without power */
        case SND_SOC_BIAS_OFF:
                dev_dbg(codec->dev, "set_bias_off\n");
+               /* force all power off */
                if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
                        snd_soc_update_bits(codec, AIC3262_REF_PWR_DLY,
-                               AIC3262_CHIP_REF_PWR_ON_MASK, 0x0);
+                                           AIC3262_CHIP_REF_PWR_ON_MASK, 0x0);
                        snd_soc_update_bits(codec, AIC3262_POWER_CONF,
-                                               (AIC3262_AVDD_TO_DVDD_MASK |
-                                               AIC3262_EXT_ANALOG_SUPPLY_MASK),
-                                               (AIC3262_AVDD_TO_DVDD |
-                                               AIC3262_EXT_ANALOG_SUPPLY_OFF));
+                                           (AIC3262_AVDD_TO_DVDD_MASK |
+                                            AIC3262_EXT_ANALOG_SUPPLY_MASK),
+                                           (AIC3262_AVDD_TO_DVDD |
+                                            AIC3262_EXT_ANALOG_SUPPLY_OFF));
+                       pm_runtime_put(codec->dev);
                }
                break;
        }
@@ -2175,25 +2457,25 @@ static int aic3262_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_suspend
- * Purpose  : This function is to suspend the AIC3262 driver.
+/**
  *
- *----------------------------------------------------------------------------
+ * aic3262_suspend; This function is to suspend the AIC3262 driver.
+ * @codec: pointer variable to codec having informaton related to codec,
+ *
+ * Return: Return 0 on success.
  */
-static int aic3262_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int aic3262_suspend(struct snd_soc_codec *codec)
 {
        aic3262_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_resume
- * Purpose  : This function is to resume the AIC3262 driver
+/**
+ * aic3262_resume: This function is to resume the AIC3262 driver
+ *              from off state to standby
+ * @codec: pointer variable to codec having informaton related to codec,
  *
- *----------------------------------------------------------------------------
+ * Return: Return 0 on success.
  */
 static int aic3262_resume(struct snd_soc_codec *codec)
 {
@@ -2202,20 +2484,17 @@ static int aic3262_resume(struct snd_soc_codec *codec)
        return 0;
 }
 
-/*
- *----------------------------------------------------------------------------
- * Function : aic3262_probe
- * Purpose  : This is first driver function called by the SoC core driver.
+/**
+ * aic3262_probe: This is first driver function called by the SoC core driver.
+ * @codec: pointer variable to codec having informaton related to codec,
  *
- *----------------------------------------------------------------------------
+ * Return: Return 0 on success.
  */
 static int aic3262_codec_probe(struct snd_soc_codec *codec)
 {
        int ret = 0;
-       int ret_btn = 0;
-       struct aic3262 *control;
+       struct aic3xxx *control;
        struct aic3262_priv *aic3262;
-       struct aic3262_jack_data *jack;
 
        if (codec == NULL)
                dev_err(codec->dev, "codec pointer is NULL.\n");
@@ -2230,56 +2509,37 @@ static int aic3262_codec_probe(struct snd_soc_codec *codec)
        aic3262->pdata = dev_get_platdata(codec->dev->parent);
        aic3262->codec = codec;
        aic3262->cur_fw = NULL;
-       aic3262->isdefault_fw = 0;
        aic3262->cfw_p = &(aic3262->cfw_ps);
-       aic3xxx_cfw_init(aic3262->cfw_p, &aic3262_cfw_codec_ops, aic3262);
+       aic3xxx_cfw_init(aic3262->cfw_p, &aic3262_cfw_codec_ops,
+                                                       aic3262->codec);
        aic3262->workqueue = create_singlethread_workqueue("aic3262-codec");
        if (!aic3262->workqueue) {
                ret = -ENOMEM;
                goto work_err;
        }
-       ret = device_create_file(codec->dev, &dev_attr_debug_level);
-       if (ret)
-               dev_info(codec->dev, "Failed to add debug_level sysfs\n");
        INIT_DELAYED_WORK(&aic3262->delayed_work, aic3262_accessory_work);
        mutex_init(&aic3262->mutex);
        mutex_init(&codec->mutex);
        mutex_init(&aic3262->cfw_mutex);
-       aic3262->dsp_runstate = 0;
-       /* use switch-class based headset reporting if platform requires it */
-       jack = &aic3262->hs_jack;
-       aic3262->idev = input_allocate_device();
-       if (aic3262->idev <= 0)
-               printk(KERN_ERR, "Allocate failed\n");
-
-       input_set_capability(aic3262->idev, EV_KEY, KEY_MEDIA);
-       ret = input_register_device(aic3262->idev);
-       if (ret < 0) {
-               dev_err(codec->dev, "register input dev fail\n");
-               goto input_dev_err;
-       }
+       pm_runtime_enable(codec->dev);
+       pm_runtime_resume(codec->dev);
+               aic3262->dsp_runstate = 0;
 
        if (control->irq) {
-               ret = aic3262_request_irq(codec->control_data,
-                       AIC3262_IRQ_HEADSET_DETECT,
-                       aic3262_audio_handler, 0,
-                       "aic3262_irq_headset", codec);
+               ret = aic3xxx_request_irq(codec->control_data,
+                                         AIC3262_IRQ_HEADSET_DETECT,
+                                         aic3262_audio_handler,
+                                         IRQF_NO_SUSPEND,
+                                         "aic3262_irq_headset", codec);
 
-               if (ret) {
+       if (ret) {
                        dev_err(codec->dev, "HEADSET detect irq request"
                        "failed: %d\n", ret);
                        goto irq_err;
-               }
-
-               ret = aic3262_request_irq(codec->control_data,
-                       AIC3262_IRQ_BUTTON_PRESS,
-                       aic3262_button_handler, 0, "aic3262_irq_button",
-                       codec);
-
-               if (ret) {
-                       dev_err(codec->dev, "button press irq request"
-                       "failed: %d\n", ret);
-                       goto irq_err;
+               } else {
+                       /*  Dynamic Headset Detection Enabled */
+                       snd_soc_update_bits(codec, AIC3262_HP_DETECT,
+                       AIC3262_HEADSET_IN_MASK, AIC3262_HEADSET_IN_MASK);
                }
        }
        /* Keep the reference voltage ON while in$
@@ -2289,74 +2549,63 @@ static int aic3262_codec_probe(struct snd_soc_codec *codec)
                            AIC3262_CHIP_REF_PWR_ON_MASK,
                            AIC3262_CHIP_REF_PWR_ON);
        mdelay(40);
-       aic3262_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       ret = snd_soc_add_codec_controls(codec, aic3262_snd_controls,
-                                       ARRAY_SIZE(aic3262_snd_controls));
-       if(ret)
-       {
-               printk(KERN_INFO "%s failed\n", __func__);
-       }
+       snd_soc_update_bits(codec, AIC3262_CHARGE_PUMP_CNTL,
+                               AIC3262_DYNAMIC_OFFSET_CALIB_MASK,
+                               AIC3262_DYNAMIC_OFFSET_CALIB);
 
-       aic3262->mute_asi = 0;
+       aic3262_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       aic3262_add_widgets(codec);
+       aic3262->mute_asi = 0;
 
-#ifdef AIC3262_TiLoad
-       ret = aic3262_driver_init(codec);
-       if (ret < 0)
-               dev_err(codec->dev, "\nTiLoad Initialization failed\n");
-#endif
-       /* force loading the default firmware */
-       aic3262_firmware_load(NULL, codec);
-       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+       ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
                                "tlv320aic3262_fw_v1.bin", codec->dev,
                                GFP_KERNEL, codec, aic3262_firmware_load);
+       if (ret < 0) {
+               dev_err(codec->dev, "Firmware request failed\n");
+               goto firm_err;
+       }
 
        return 0;
+firm_err:
+       aic3xxx_free_irq(control,
+                        AIC3262_IRQ_HEADSET_DETECT, codec);
 irq_err:
-       input_unregister_device(aic3262->idev);
-       input_free_device(aic3262->idev);
-input_dev_err:
-reg_err:
+       destroy_workqueue(aic3262->workqueue);
 work_err:
        kfree(aic3262);
        return 0;
 }
 
 /*
-* aic3262_remove: Cleans up and Remove aic3262 soc device
-* @codec: pointer variable to codec having informaton related to codec,
-*
-* Return: Return 0 on success.
-*/
+ * aic3262_remove: Cleans up and Remove aic3262 soc device
+ * @codec: pointer variable to codec having informaton related to codec,
+ *
+ * Return: Return 0 on success.
+ */
 static int aic3262_codec_remove(struct snd_soc_codec *codec)
 {
        /* power down chip */
        struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec);
-       struct aic3262 *control = codec->control_data;
-       struct aic3262_jack_data *jack = &aic3262->hs_jack;
+       struct aic3xxx *control = codec->control_data;
 
        aic3262_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        /* free_irq if any */
        switch (control->type) {
        case TLV320AIC3262:
-               if (control->irq) {
-                       aic3262_free_irq(control, AIC3262_IRQ_HEADSET_DETECT,
-                               codec);
-                       aic3262_free_irq(control, AIC3262_IRQ_BUTTON_PRESS,
-                               codec);
-               }
+               if (control->irq)
+                       aic3xxx_free_irq(control,
+                                        AIC3262_IRQ_HEADSET_DETECT, codec);
                break;
+       default:
+               dev_info(codec->dev, "Coded is not TLV320AIC3262\n");
        }
        /* release firmware if any */
        if (aic3262->cur_fw != NULL)
                release_firmware(aic3262->cur_fw);
        /* destroy workqueue for jac dev */
        destroy_workqueue(aic3262->workqueue);
-       input_unregister_device(aic3262->idev);
-       input_free_device(aic3262->idev);
 
        kfree(aic3262);
 
@@ -2370,6 +2619,12 @@ static struct snd_soc_codec_driver soc_codec_driver_aic326x = {
        .resume = aic3262_resume,
        .read = aic3262_codec_read,
        .write = aic3262_codec_write,
+       .controls = aic3262_snd_controls,
+       .num_controls = ARRAY_SIZE(aic3262_snd_controls),
+       .dapm_widgets = aic3262_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(aic3262_dapm_widgets),
+       .dapm_routes = aic3262_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(aic3262_dapm_routes),
        .set_bias_level = aic3262_set_bias_level,
        .reg_cache_size = 0,
        .reg_word_size = sizeof(u8),
@@ -2390,42 +2645,31 @@ static int aic326x_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id aic3262_of_match[] = {
+               { .compatible = "ti,aic3262", },
+               { },
+};
+MODULE_DEVICE_TABLE(of, aic3262_of_match);
+
+static const struct platform_device_id aic3262_i2c_id[] = {
+               { "tlv320aic3262-codec", 0 },
+               { }
+};
+MODULE_DEVICE_TABLE(i2c, aic3262_i2c_id);
+
 static struct platform_driver aic326x_codec_driver = {
        .driver = {
-                  .name = "tlv320aic3262-codec",
-                  .owner = THIS_MODULE,
-                  },
+               .name = "tlv320aic3262-codec",
+               .owner = THIS_MODULE,
+               .of_match_table = aic3262_of_match,
+       },
        .probe = aic326x_probe,
        .remove = __devexit_p(aic326x_remove),
+       .id_table = aic3262_i2c_id,
 };
-/*
-*----------------------------------------------------------------------------
-* Function : tlv320aic3262_modinit
-* Purpose  : module init function. First function to run.
-*
-*----------------------------------------------------------------------------
-*/
-static int __init tlv320aic3262_modinit(void)
-{
-       return platform_driver_register(&aic326x_codec_driver);
-}
 
-module_init(tlv320aic3262_modinit);
-
-/*
-*----------------------------------------------------------------------------
-* Function : tlv320aic3262_exit
-* Purpose  : module init function. First function to run.
-*
-*----------------------------------------------------------------------------
-*/
-static void __exit tlv320aic3262_exit(void)
-{
-       platform_driver_unregister(&aic326x_codec_driver);
-
-}
+module_platform_driver(aic326x_codec_driver);
 
-module_exit(tlv320aic3262_exit);
 MODULE_ALIAS("platform:tlv320aic3262-codec");
 MODULE_DESCRIPTION("ASoC TLV320AIC3262 codec driver");
 MODULE_AUTHOR("Y Preetam Sashank Reddy ");
index 4a7d909..de56bd9 100644 (file)
 
 #ifndef _TLV320AIC3262_H
 #define _TLV320AIC3262_H
-#include "aic3xxx_cfw.h"
-#include "aic3xxx_cfw_ops.h"
-#include <linux/switch.h>
+#include "aic3xxx/aic3xxx_cfw.h"
+#include "aic3xxx/aic3xxx_cfw_ops.h"
 
 #define AUDIO_NAME "aic3262"
 #define AIC3262_VERSION "1.1"
 /* Macro to enable the inclusion of tiload kernel driver */
 #define AIC3262_TiLoad
 #undef AIC3262_SYNC_MODE
-
-/* #define AIC3262_ASI1_MASTER */
 #undef AIC3262_ASI1_MASTER
-/* #define AIC3262_ASI2_MASTER */
 #undef AIC3262_ASI2_MASTER
-/* #define AIC3262_ASI3_MASTER */
 #undef AIC3262_ASI3_MASTER
 /* Macro for McBsp master / slave configuration */
 #define AIC3262_MCBSP_SLAVE    /*3262 master */
@@ -63,7 +58,6 @@
 #define AIC3262_FREQ_19200000 19200000
 #define AIC3262_FREQ_24000000 24000000
 #define AIC3262_FREQ_38400000 38400000
-#define AIC3262_FREQ_12288000 12288000
 /* Audio data word length = 16-bits (default setting) */
 #define AIC3262_WORD_LEN_16BITS                0x00
 #define AIC3262_WORD_LEN_20BITS                0x01
 /* Updated from 256 to support Page 3 registers */
 #define        AIC3262_CACHEREGNUM                             1024
 
-#define DSP_NON_SYNC_MODE(state) (!((state & 0x03) && (state & 0x30)))
-
-#define TIME_DELAY                                     5
-#define DELAY_COUNTER                                  100
-
-#ifdef AIC3262_TiLoad
-int aic3262_driver_init(struct snd_soc_codec *codec);
-#endif
+#define AIC326X_TIME_DELAY                                     5
+#define AIC326X_DELAY_COUNTER                                  100
 
 struct aic3262_jack_data {
        struct snd_soc_jack *jack;
        int report;
-       struct switch_dev sdev;
 };
 
 struct aic3262_priv {
@@ -139,60 +126,10 @@ struct aic3262_priv {
        int isdefault_fw;
 };
 
-/*
- *----------------------------------------------------------------------------
- * @struct  aic3262_rate_divs |
- *          Setting up the values to get different freqencies
- *
- * @field   u32 | mclk |
- *          Master clock
- * @field   u32 | rate |
- *          sample rate
- * @field   u8 | p_val |
- *          value of p in PLL
- * @field   u32 | pll_j |
- *          value for pll_j
- * @field   u32 | pll_d |
- *          value for pll_d
- * @field   u32 | dosr |
- *          value to store dosr
- * @field   u32 | ndac |
- *          value for ndac
- * @field   u32 | mdac |
- *          value for mdac
- * @field   u32 | aosr |
- *          value for aosr
- * @field   u32 | nadc |
- *          value for nadc
- * @field   u32 | madc |
- *          value for madc
- * @field   u32 | blck_N |
- *          value for block N
- *----------------------------------------------------------------------------
- */
-struct aic3262_rate_divs {
-       u32 mclk;
-       u32 rate;
-       u8 p_val;
-       u8 pll_j;
-       u16 pll_d;
-       u16 dosr;
-       u8 ndac;
-       u8 mdac;
-       u8 aosr;
-       u8 nadc;
-       u8 madc;
-       u8 blck_N;
-};
-
 extern struct snd_soc_dai tlv320aic3262_dai;
-extern struct snd_soc_codec_device soc_codec_dev_aic3262;
-extern const struct aic3xxx_codec_ops aic3262_cfw_codec_ops;
 void aic3262_hs_jack_detect(struct snd_soc_codec *codec,
                                struct snd_soc_jack *jack, int report);
 
-unsigned int aic3262_read(struct snd_soc_codec *codec, unsigned int reg);
-int aic3262_write(struct snd_soc_codec *codec, unsigned int reg,
-                               unsigned int value);
+
 #endif                         /* _TLV320AIC3262_H */