summary refs log tree commit diff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/Kconfig31
-rw-r--r--sound/soc/codecs/Makefile19
-rw-r--r--sound/soc/codecs/ab8500-codec.c2522
-rw-r--r--sound/soc/codecs/ab8500-codec.h590
-rw-r--r--sound/soc/codecs/ac97.c6
-rw-r--r--sound/soc/codecs/arizona.c937
-rw-r--r--sound/soc/codecs/arizona.h159
-rw-r--r--sound/soc/codecs/cs42l52.c19
-rw-r--r--sound/soc/codecs/cs42l73.c20
-rw-r--r--sound/soc/codecs/da732x.c1627
-rw-r--r--sound/soc/codecs/da732x.h133
-rw-r--r--sound/soc/codecs/da732x_reg.h654
-rw-r--r--sound/soc/codecs/isabelle.c1176
-rw-r--r--sound/soc/codecs/isabelle.h143
-rw-r--r--sound/soc/codecs/lm49453.c3
-rw-r--r--sound/soc/codecs/max98095.c5
-rw-r--r--sound/soc/codecs/ml26124.c5
-rw-r--r--sound/soc/codecs/spdif_receiver.c67
-rw-r--r--sound/soc/codecs/sta529.c442
-rw-r--r--sound/soc/codecs/tlv320aic3x.c40
-rw-r--r--sound/soc/codecs/tlv320aic3x.h27
-rw-r--r--sound/soc/codecs/twl6040.c2
-rw-r--r--sound/soc/codecs/wm1250-ev1.c7
-rw-r--r--sound/soc/codecs/wm2000.c32
-rw-r--r--sound/soc/codecs/wm5100-tables.c2
-rw-r--r--sound/soc/codecs/wm5100.c11
-rw-r--r--sound/soc/codecs/wm5102.c903
-rw-r--r--sound/soc/codecs/wm5102.h21
-rw-r--r--sound/soc/codecs/wm5110.c950
-rw-r--r--sound/soc/codecs/wm5110.h21
-rw-r--r--sound/soc/codecs/wm8350.c22
-rw-r--r--sound/soc/codecs/wm8400.c2
-rw-r--r--sound/soc/codecs/wm8580.c2
-rw-r--r--sound/soc/codecs/wm8731.c1
-rw-r--r--sound/soc/codecs/wm8741.c2
-rw-r--r--sound/soc/codecs/wm8753.c2
-rw-r--r--sound/soc/codecs/wm8776.c2
-rw-r--r--sound/soc/codecs/wm8804.c2
-rw-r--r--sound/soc/codecs/wm8903.c316
-rw-r--r--sound/soc/codecs/wm8904.c272
-rw-r--r--sound/soc/codecs/wm8960.c2
-rw-r--r--sound/soc/codecs/wm8961.c2
-rw-r--r--sound/soc/codecs/wm8962.c8
-rw-r--r--sound/soc/codecs/wm8993.c2
-rw-r--r--sound/soc/codecs/wm8994.c46
-rw-r--r--sound/soc/codecs/wm8996.c587
-rw-r--r--sound/soc/codecs/wm9081.c2
-rw-r--r--sound/soc/codecs/wm9090.c2
-rw-r--r--sound/soc/codecs/wm9712.c2
-rw-r--r--sound/soc/codecs/wm9713.c2
-rw-r--r--sound/soc/codecs/wm_hubs.c2
51 files changed, 11029 insertions, 825 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 1e1613a438dd..9f8e8594aeb9 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -12,6 +12,7 @@ config SND_SOC_ALL_CODECS
 	tristate "Build all ASoC CODEC drivers"
 	select SND_SOC_88PM860X if MFD_88PM860X
 	select SND_SOC_L3
+	select SND_SOC_AB8500_CODEC if ABX500_CORE
 	select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
 	select SND_SOC_AD1836 if SPI_MASTER
 	select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
@@ -35,7 +36,9 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_CX20442
 	select SND_SOC_DA7210 if I2C
+	select SND_SOC_DA732X if I2C
 	select SND_SOC_DFBMCS320
+	select SND_SOC_ISABELLE if I2C
 	select SND_SOC_JZ4740_CODEC
 	select SND_SOC_LM4857 if I2C
 	select SND_SOC_LM49453 if I2C
@@ -54,6 +57,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_SPDIF
 	select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_STA32X if I2C
+	select SND_SOC_STA529 if I2C
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
 	select SND_SOC_TLV320AIC23 if I2C
 	select SND_SOC_TLV320AIC26 if SPI_MASTER
@@ -70,6 +74,8 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_WM2000 if I2C
 	select SND_SOC_WM2200 if I2C
 	select SND_SOC_WM5100 if I2C
+	select SND_SOC_WM5102 if MFD_WM5102
+	select SND_SOC_WM5110 if MFD_WM5110
 	select SND_SOC_WM8350 if MFD_WM8350
 	select SND_SOC_WM8400 if MFD_WM8400
 	select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
@@ -126,11 +132,21 @@ config SND_SOC_ALL_CODECS
 config SND_SOC_88PM860X
 	tristate
 
+config SND_SOC_ARIZONA
+	tristate
+	default y if SND_SOC_WM5102=y
+	default y if SND_SOC_WM5110=y
+	default m if SND_SOC_WM5102=m
+	default m if SND_SOC_WM5110=m
+
 config SND_SOC_WM_HUBS
 	tristate
 	default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
 	default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m
 
+config SND_SOC_AB8500_CODEC
+	tristate
+
 config SND_SOC_AC97_CODEC
 	tristate
 	select SND_AC97_CODEC
@@ -219,12 +235,18 @@ config SND_SOC_L3
 config SND_SOC_DA7210
         tristate
 
+config SND_SOC_DA732X
+        tristate
+
 config SND_SOC_DFBMCS320
 	tristate
 
 config SND_SOC_DMIC
 	tristate
 
+config SND_SOC_ISABELLE
+        tristate
+
 config SND_SOC_LM49453
 	tristate
 
@@ -266,6 +288,9 @@ config SND_SOC_SSM2602
 config SND_SOC_STA32X
 	tristate
 
+config SND_SOC_STA529
+	tristate
+
 config SND_SOC_STAC9766
 	tristate
 
@@ -313,6 +338,12 @@ config SND_SOC_WM2200
 config SND_SOC_WM5100
 	tristate
 
+config SND_SOC_WM5102
+	tristate
+
+config SND_SOC_WM5110
+	tristate
+
 config SND_SOC_WM8350
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fc27fec39487..34148bb59c68 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,4 +1,5 @@
 snd-soc-88pm860x-objs := 88pm860x-codec.o
+snd-soc-ab8500-codec-objs := ab8500-codec.o
 snd-soc-ac97-objs := ac97.o
 snd-soc-ad1836-objs := ad1836.o
 snd-soc-ad193x-objs := ad193x.o
@@ -13,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o
 snd-soc-ak4641-objs := ak4641.o
 snd-soc-ak4642-objs := ak4642.o
 snd-soc-ak4671-objs := ak4671.o
+snd-soc-arizona-objs := arizona.o
 snd-soc-cq93vc-objs := cq93vc.o
 snd-soc-cs42l51-objs := cs42l51.o
 snd-soc-cs42l52-objs := cs42l52.o
@@ -21,8 +23,10 @@ snd-soc-cs4270-objs := cs4270.o
 snd-soc-cs4271-objs := cs4271.o
 snd-soc-cx20442-objs := cx20442.o
 snd-soc-da7210-objs := da7210.o
+snd-soc-da732x-objs := da732x.o
 snd-soc-dfbmcs320-objs := dfbmcs320.o
 snd-soc-dmic-objs := dmic.o
+snd-soc-isabelle-objs := isabelle.o
 snd-soc-jz4740-codec-objs := jz4740.o
 snd-soc-l3-objs := l3.o
 snd-soc-lm4857-objs := lm4857.o
@@ -41,9 +45,11 @@ snd-soc-alc5623-objs := alc5623.o
 snd-soc-alc5632-objs := alc5632.o
 snd-soc-sigmadsp-objs := sigmadsp.o
 snd-soc-sn95031-objs := sn95031.o
-snd-soc-spdif-objs := spdif_transciever.o
+snd-soc-spdif-tx-objs := spdif_transciever.o
+snd-soc-spdif-rx-objs := spdif_receiver.o
 snd-soc-ssm2602-objs := ssm2602.o
 snd-soc-sta32x-objs := sta32x.o
+snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
@@ -59,6 +65,8 @@ snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm2000-objs := wm2000.o
 snd-soc-wm2200-objs := wm2200.o
 snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
+snd-soc-wm5102-objs := wm5102.o
+snd-soc-wm5110-objs := wm5110.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
 snd-soc-wm8510-objs := wm8510.o
@@ -108,6 +116,7 @@ snd-soc-max9877-objs := max9877.o
 snd-soc-tpa6130a2-objs := tpa6130a2.o
 
 obj-$(CONFIG_SND_SOC_88PM860X)	+= snd-soc-88pm860x.o
+obj-$(CONFIG_SND_SOC_AB8500_CODEC)	+= snd-soc-ab8500-codec.o
 obj-$(CONFIG_SND_SOC_AC97_CODEC)	+= snd-soc-ac97.o
 obj-$(CONFIG_SND_SOC_AD1836)	+= snd-soc-ad1836.o
 obj-$(CONFIG_SND_SOC_AD193X)	+= snd-soc-ad193x.o
@@ -124,6 +133,7 @@ obj-$(CONFIG_SND_SOC_AK4642)	+= snd-soc-ak4642.o
 obj-$(CONFIG_SND_SOC_AK4671)	+= snd-soc-ak4671.o
 obj-$(CONFIG_SND_SOC_ALC5623)    += snd-soc-alc5623.o
 obj-$(CONFIG_SND_SOC_ALC5632)	+= snd-soc-alc5632.o
+obj-$(CONFIG_SND_SOC_ARIZONA)	+= snd-soc-arizona.o
 obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
 obj-$(CONFIG_SND_SOC_CS42L51)	+= snd-soc-cs42l51.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
@@ -132,8 +142,10 @@ obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_CS4271)	+= snd-soc-cs4271.o
 obj-$(CONFIG_SND_SOC_CX20442)	+= snd-soc-cx20442.o
 obj-$(CONFIG_SND_SOC_DA7210)	+= snd-soc-da7210.o
+obj-$(CONFIG_SND_SOC_DA732X)	+= snd-soc-da732x.o
 obj-$(CONFIG_SND_SOC_DFBMCS320)	+= snd-soc-dfbmcs320.o
 obj-$(CONFIG_SND_SOC_DMIC)	+= snd-soc-dmic.o
+obj-$(CONFIG_SND_SOC_ISABELLE)	+= snd-soc-isabelle.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
 obj-$(CONFIG_SND_SOC_L3)	+= snd-soc-l3.o
 obj-$(CONFIG_SND_SOC_LM4857)	+= snd-soc-lm4857.o
@@ -150,9 +162,10 @@ obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SIGMADSP)	+= snd-soc-sigmadsp.o
 obj-$(CONFIG_SND_SOC_SN95031)	+=snd-soc-sn95031.o
-obj-$(CONFIG_SND_SOC_SPDIF)	+= snd-soc-spdif.o
+obj-$(CONFIG_SND_SOC_SPDIF)	+= snd-soc-spdif-rx.o snd-soc-spdif-tx.o
 obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
 obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
+obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
@@ -168,6 +181,8 @@ obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
 obj-$(CONFIG_SND_SOC_WM2000)	+= snd-soc-wm2000.o
 obj-$(CONFIG_SND_SOC_WM2200)	+= snd-soc-wm2200.o
 obj-$(CONFIG_SND_SOC_WM5100)	+= snd-soc-wm5100.o
+obj-$(CONFIG_SND_SOC_WM5102)	+= snd-soc-wm5102.o
+obj-$(CONFIG_SND_SOC_WM5110)	+= snd-soc-wm5110.o
 obj-$(CONFIG_SND_SOC_WM8350)	+= snd-soc-wm8350.o
 obj-$(CONFIG_SND_SOC_WM8400)	+= snd-soc-wm8400.o
 obj-$(CONFIG_SND_SOC_WM8510)	+= snd-soc-wm8510.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
new file mode 100644
index 000000000000..3c795921c5f6
--- /dev/null
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -0,0 +1,2522 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ *         Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>,
+ *         Roger Nilsson <roger.xr.nilsson@stericsson.com>,
+ *         for ST-Ericsson.
+ *
+ *         Based on the early work done by:
+ *         Mikko J. Lehto <mikko.lehto@symbio.com>,
+ *         Mikko Sarmanne <mikko.sarmanne@symbio.com>,
+ *         Jarmo K. Kuronen <jarmo.kuronen@symbio.com>,
+ *         for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500-sysctrl.h>
+#include <linux/mfd/abx500/ab8500-codec.h>
+#include <linux/regulator/consumer.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#include "ab8500-codec.h"
+
+/* Macrocell value definitions */
+#define CLK_32K_OUT2_DISABLE			0x01
+#define INACTIVE_RESET_AUDIO			0x02
+#define ENABLE_AUDIO_CLK_TO_AUDIO_BLK		0x10
+#define ENABLE_VINTCORE12_SUPPLY		0x04
+#define GPIO27_DIR_OUTPUT			0x04
+#define GPIO29_DIR_OUTPUT			0x10
+#define GPIO31_DIR_OUTPUT			0x40
+
+/* Macrocell register definitions */
+#define AB8500_CTRL3_REG			0x0200
+#define AB8500_GPIO_DIR4_REG			0x1013
+
+/* Nr of FIR/IIR-coeff banks in ANC-block */
+#define AB8500_NR_OF_ANC_COEFF_BANKS		2
+
+/* Minimum duration to keep ANC IIR Init bit high or
+low before proceeding with the configuration sequence */
+#define AB8500_ANC_SM_DELAY			2000
+
+#define AB8500_FILTER_CONTROL(xname, xcount, xmin, xmax) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.info = filter_control_info, \
+	.get = filter_control_get, .put = filter_control_put, \
+	.private_value = (unsigned long)&(struct filter_control) \
+		{.count = xcount, .min = xmin, .max = xmax} }
+
+struct filter_control {
+	long min, max;
+	unsigned int count;
+	long value[128];
+};
+
+/* Sidetone states */
+static const char * const enum_sid_state[] = {
+	"Unconfigured",
+	"Apply FIR",
+	"FIR is configured",
+};
+enum sid_state {
+	SID_UNCONFIGURED = 0,
+	SID_APPLY_FIR = 1,
+	SID_FIR_CONFIGURED = 2,
+};
+
+static const char * const enum_anc_state[] = {
+	"Unconfigured",
+	"Apply FIR and IIR",
+	"FIR and IIR are configured",
+	"Apply FIR",
+	"FIR is configured",
+	"Apply IIR",
+	"IIR is configured"
+};
+enum anc_state {
+	ANC_UNCONFIGURED = 0,
+	ANC_APPLY_FIR_IIR = 1,
+	ANC_FIR_IIR_CONFIGURED = 2,
+	ANC_APPLY_FIR = 3,
+	ANC_FIR_CONFIGURED = 4,
+	ANC_APPLY_IIR = 5,
+	ANC_IIR_CONFIGURED = 6
+};
+
+/* Analog microphones */
+enum amic_idx {
+	AMIC_IDX_1A,
+	AMIC_IDX_1B,
+	AMIC_IDX_2
+};
+
+struct ab8500_codec_drvdata_dbg {
+	struct regulator *vaud;
+	struct regulator *vamic1;
+	struct regulator *vamic2;
+	struct regulator *vdmic;
+};
+
+/* Private data for AB8500 device-driver */
+struct ab8500_codec_drvdata {
+	/* Sidetone */
+	long *sid_fir_values;
+	enum sid_state sid_status;
+
+	/* ANC */
+	struct mutex anc_lock;
+	long *anc_fir_values;
+	long *anc_iir_values;
+	enum anc_state anc_status;
+};
+
+static inline const char *amic_micbias_str(enum amic_micbias micbias)
+{
+	switch (micbias) {
+	case AMIC_MICBIAS_VAMIC1:
+		return "VAMIC1";
+	case AMIC_MICBIAS_VAMIC2:
+		return "VAMIC2";
+	default:
+		return "Unknown";
+	}
+}
+
+static inline const char *amic_type_str(enum amic_type type)
+{
+	switch (type) {
+	case AMIC_TYPE_DIFFERENTIAL:
+		return "DIFFERENTIAL";
+	case AMIC_TYPE_SINGLE_ENDED:
+		return "SINGLE ENDED";
+	default:
+		return "Unknown";
+	}
+}
+
+/*
+ * Read'n'write functions
+ */
+
+/* Read a register from the audio-bank of AB8500 */
+static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec,
+					unsigned int reg)
+{
+	int status;
+	unsigned int value = 0;
+
+	u8 value8;
+	status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO,
+						reg, &value8);
+	if (status < 0) {
+		dev_err(codec->dev,
+			"%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n",
+			__func__, (u8)AB8500_AUDIO, (u8)reg, status);
+	} else {
+		dev_dbg(codec->dev,
+			"%s: Read 0x%02x from register 0x%02x:0x%02x\n",
+			__func__, value8, (u8)AB8500_AUDIO, (u8)reg);
+		value = (unsigned int)value8;
+	}
+
+	return value;
+}
+
+/* Write to a register in the audio-bank of AB8500 */
+static int ab8500_codec_write_reg(struct snd_soc_codec *codec,
+				unsigned int reg, unsigned int value)
+{
+	int status;
+
+	status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO,
+						reg, value);
+	if (status < 0)
+		dev_err(codec->dev,
+			"%s: ERROR: Register (%02x:%02x) write failed (%d).\n",
+			__func__, (u8)AB8500_AUDIO, (u8)reg, status);
+	else
+		dev_dbg(codec->dev,
+			"%s: Wrote 0x%02x into register %02x:%02x\n",
+			__func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg);
+
+	return status;
+}
+
+/*
+ * Controls - DAPM
+ */
+
+/* Earpiece */
+
+/* Earpiece source selector */
+static const char * const enum_ear_lineout_source[] = {"Headset Left",
+						"Speaker Left"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_ear_lineout_source, AB8500_DMICFILTCONF,
+			AB8500_DMICFILTCONF_DA3TOEAR, enum_ear_lineout_source);
+static const struct snd_kcontrol_new dapm_ear_lineout_source =
+	SOC_DAPM_ENUM("Earpiece or LineOut Mono Source",
+		dapm_enum_ear_lineout_source);
+
+/* LineOut */
+
+/* LineOut source selector */
+static const char * const enum_lineout_source[] = {"Mono Path", "Stereo Path"};
+static SOC_ENUM_DOUBLE_DECL(dapm_enum_lineout_source, AB8500_ANACONF5,
+			AB8500_ANACONF5_HSLDACTOLOL,
+			AB8500_ANACONF5_HSRDACTOLOR, enum_lineout_source);
+static const struct snd_kcontrol_new dapm_lineout_source[] = {
+	SOC_DAPM_ENUM("LineOut Source", dapm_enum_lineout_source),
+};
+
+/* Handsfree */
+
+/* Speaker Left - ANC selector */
+static const char * const enum_HFx_sel[] = {"Audio Path", "ANC"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_HFl_sel, AB8500_DIGMULTCONF2,
+			AB8500_DIGMULTCONF2_HFLSEL, enum_HFx_sel);
+static const struct snd_kcontrol_new dapm_HFl_select[] = {
+	SOC_DAPM_ENUM("Speaker Left Source", dapm_enum_HFl_sel),
+};
+
+/* Speaker Right - ANC selector */
+static SOC_ENUM_SINGLE_DECL(dapm_enum_HFr_sel, AB8500_DIGMULTCONF2,
+			AB8500_DIGMULTCONF2_HFRSEL, enum_HFx_sel);
+static const struct snd_kcontrol_new dapm_HFr_select[] = {
+	SOC_DAPM_ENUM("Speaker Right Source", dapm_enum_HFr_sel),
+};
+
+/* Mic 1 */
+
+/* Mic 1 - Mic 1a or 1b selector */
+static const char * const enum_mic1ab_sel[] = {"Mic 1b", "Mic 1a"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_mic1ab_sel, AB8500_ANACONF3,
+			AB8500_ANACONF3_MIC1SEL, enum_mic1ab_sel);
+static const struct snd_kcontrol_new dapm_mic1ab_mux[] = {
+	SOC_DAPM_ENUM("Mic 1a or 1b Select", dapm_enum_mic1ab_sel),
+};
+
+/* Mic 1 - AD3 - Mic 1 or DMic 3 selector */
+static const char * const enum_ad3_sel[] = {"Mic 1", "DMic 3"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_ad3_sel, AB8500_DIGMULTCONF1,
+			AB8500_DIGMULTCONF1_AD3SEL, enum_ad3_sel);
+static const struct snd_kcontrol_new dapm_ad3_select[] = {
+	SOC_DAPM_ENUM("AD3 Source Select", dapm_enum_ad3_sel),
+};
+
+/* Mic 1 - AD6 - Mic 1 or DMic 6 selector */
+static const char * const enum_ad6_sel[] = {"Mic 1", "DMic 6"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_ad6_sel, AB8500_DIGMULTCONF1,
+			AB8500_DIGMULTCONF1_AD6SEL, enum_ad6_sel);
+static const struct snd_kcontrol_new dapm_ad6_select[] = {
+	SOC_DAPM_ENUM("AD6 Source Select", dapm_enum_ad6_sel),
+};
+
+/* Mic 2 */
+
+/* Mic 2 - AD5 - Mic 2 or DMic 5 selector */
+static const char * const enum_ad5_sel[] = {"Mic 2", "DMic 5"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_ad5_sel, AB8500_DIGMULTCONF1,
+			AB8500_DIGMULTCONF1_AD5SEL, enum_ad5_sel);
+static const struct snd_kcontrol_new dapm_ad5_select[] = {
+	SOC_DAPM_ENUM("AD5 Source Select", dapm_enum_ad5_sel),
+};
+
+/* LineIn */
+
+/* LineIn left - AD1 - LineIn Left or DMic 1 selector */
+static const char * const enum_ad1_sel[] = {"LineIn Left", "DMic 1"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_ad1_sel, AB8500_DIGMULTCONF1,
+			AB8500_DIGMULTCONF1_AD1SEL, enum_ad1_sel);
+static const struct snd_kcontrol_new dapm_ad1_select[] = {
+	SOC_DAPM_ENUM("AD1 Source Select", dapm_enum_ad1_sel),
+};
+
+/* LineIn right - Mic 2 or LineIn Right selector */
+static const char * const enum_mic2lr_sel[] = {"Mic 2", "LineIn Right"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_mic2lr_sel, AB8500_ANACONF3,
+			AB8500_ANACONF3_LINRSEL, enum_mic2lr_sel);
+static const struct snd_kcontrol_new dapm_mic2lr_select[] = {
+	SOC_DAPM_ENUM("Mic 2 or LINR Select", dapm_enum_mic2lr_sel),
+};
+
+/* LineIn right - AD2 - LineIn Right or DMic2 selector */
+static const char * const enum_ad2_sel[] = {"LineIn Right", "DMic 2"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_ad2_sel, AB8500_DIGMULTCONF1,
+			AB8500_DIGMULTCONF1_AD2SEL, enum_ad2_sel);
+static const struct snd_kcontrol_new dapm_ad2_select[] = {
+	SOC_DAPM_ENUM("AD2 Source Select", dapm_enum_ad2_sel),
+};
+
+
+/* ANC */
+
+static const char * const enum_anc_in_sel[] = {"Mic 1 / DMic 6",
+					"Mic 2 / DMic 5"};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_anc_in_sel, AB8500_DMICFILTCONF,
+			AB8500_DMICFILTCONF_ANCINSEL, enum_anc_in_sel);
+static const struct snd_kcontrol_new dapm_anc_in_select[] = {
+	SOC_DAPM_ENUM("ANC Source", dapm_enum_anc_in_sel),
+};
+
+/* ANC - Enable/Disable */
+static const struct snd_kcontrol_new dapm_anc_enable[] = {
+	SOC_DAPM_SINGLE("Switch", AB8500_ANCCONF1,
+			AB8500_ANCCONF1_ENANC, 0, 0),
+};
+
+/* ANC to Earpiece - Mute */
+static const struct snd_kcontrol_new dapm_anc_ear_mute[] = {
+	SOC_DAPM_SINGLE("Switch", AB8500_DIGMULTCONF1,
+			AB8500_DIGMULTCONF1_ANCSEL, 1, 0),
+};
+
+
+
+/* Sidetone left */
+
+/* Sidetone left - Input selector */
+static const char * const enum_stfir1_in_sel[] = {
+	"LineIn Left", "LineIn Right", "Mic 1", "Headset Left"
+};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir1_in_sel, AB8500_DIGMULTCONF2,
+			AB8500_DIGMULTCONF2_FIRSID1SEL, enum_stfir1_in_sel);
+static const struct snd_kcontrol_new dapm_stfir1_in_select[] = {
+	SOC_DAPM_ENUM("Sidetone Left Source", dapm_enum_stfir1_in_sel),
+};
+
+/* Sidetone right path */
+
+/* Sidetone right - Input selector */
+static const char * const enum_stfir2_in_sel[] = {
+	"LineIn Right", "Mic 1", "DMic 4", "Headset Right"
+};
+static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir2_in_sel, AB8500_DIGMULTCONF2,
+			AB8500_DIGMULTCONF2_FIRSID2SEL, enum_stfir2_in_sel);
+static const struct snd_kcontrol_new dapm_stfir2_in_select[] = {
+	SOC_DAPM_ENUM("Sidetone Right Source", dapm_enum_stfir2_in_sel),
+};
+
+/* Vibra */
+
+static const char * const enum_pwm2vibx[] = {"Audio Path", "PWM Generator"};
+
+static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib1, AB8500_PWMGENCONF1,
+			AB8500_PWMGENCONF1_PWMTOVIB1, enum_pwm2vibx);
+
+static const struct snd_kcontrol_new dapm_pwm2vib1[] = {
+	SOC_DAPM_ENUM("Vibra 1 Controller", dapm_enum_pwm2vib1),
+};
+
+static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib2, AB8500_PWMGENCONF1,
+			AB8500_PWMGENCONF1_PWMTOVIB2, enum_pwm2vibx);
+
+static const struct snd_kcontrol_new dapm_pwm2vib2[] = {
+	SOC_DAPM_ENUM("Vibra 2 Controller", dapm_enum_pwm2vib2),
+};
+
+/*
+ * DAPM-widgets
+ */
+
+static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = {
+
+	/* Clocks */
+	SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"),
+
+	/* Regulators */
+	SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0),
+	SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0),
+	SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0),
+	SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0),
+
+	/* Power */
+	SND_SOC_DAPM_SUPPLY("Audio Power",
+			AB8500_POWERUP, AB8500_POWERUP_POWERUP, 0,
+			NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("Audio Analog Power",
+			AB8500_POWERUP, AB8500_POWERUP_ENANA, 0,
+			NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Main supply node */
+	SND_SOC_DAPM_SUPPLY("Main Supply", SND_SOC_NOPM, 0, 0,
+			NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* DA/AD */
+
+	SND_SOC_DAPM_INPUT("ADC Input"),
+	SND_SOC_DAPM_ADC("ADC", "ab8500_0c", SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_OUTPUT("DAC Output"),
+
+	SND_SOC_DAPM_AIF_IN("DA_IN1", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("DA_IN2", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("DA_IN3", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("DA_IN4", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("DA_IN5", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("DA_IN6", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AD_OUT1", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AD_OUT2", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AD_OUT3", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AD_OUT4", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AD_OUT57", NULL, 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AD_OUT68", NULL, 0, SND_SOC_NOPM, 0, 0),
+
+	/* Headset path */
+
+	SND_SOC_DAPM_SUPPLY("Charge Pump", AB8500_ANACONF5,
+			AB8500_ANACONF5_ENCPHS, 0, NULL, 0),
+
+	SND_SOC_DAPM_DAC("DA1 Enable", "ab8500_0p",
+			AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA1, 0),
+	SND_SOC_DAPM_DAC("DA2 Enable", "ab8500_0p",
+			AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA2, 0),
+
+	SND_SOC_DAPM_PGA("HSL Digital Volume", SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_PGA("HSR Digital Volume", SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+
+	SND_SOC_DAPM_DAC("HSL DAC", "ab8500_0p",
+			AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSL, 0),
+	SND_SOC_DAPM_DAC("HSR DAC", "ab8500_0p",
+			AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSR, 0),
+	SND_SOC_DAPM_MIXER("HSL DAC Mute", AB8500_MUTECONF,
+			AB8500_MUTECONF_MUTDACHSL, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("HSR DAC Mute", AB8500_MUTECONF,
+			AB8500_MUTECONF_MUTDACHSR, 1,
+			NULL, 0),
+	SND_SOC_DAPM_DAC("HSL DAC Driver", "ab8500_0p",
+			AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSL, 0),
+	SND_SOC_DAPM_DAC("HSR DAC Driver", "ab8500_0p",
+			AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSR, 0),
+
+	SND_SOC_DAPM_MIXER("HSL Mute",
+			AB8500_MUTECONF, AB8500_MUTECONF_MUTHSL, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("HSR Mute",
+			AB8500_MUTECONF, AB8500_MUTECONF_MUTHSR, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("HSL Enable",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENHSL, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("HSR Enable",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENHSR, 0,
+			NULL, 0),
+	SND_SOC_DAPM_PGA("HSL Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_PGA("HSR Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+
+	SND_SOC_DAPM_OUTPUT("Headset Left"),
+	SND_SOC_DAPM_OUTPUT("Headset Right"),
+
+	/* LineOut path */
+
+	SND_SOC_DAPM_MUX("LineOut Source",
+			SND_SOC_NOPM, 0, 0, dapm_lineout_source),
+
+	SND_SOC_DAPM_MIXER("LOL Disable HFL",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("LOR Disable HFR",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 1,
+			NULL, 0),
+
+	SND_SOC_DAPM_MIXER("LOL Enable",
+			AB8500_ANACONF5, AB8500_ANACONF5_ENLOL, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("LOR Enable",
+			AB8500_ANACONF5, AB8500_ANACONF5_ENLOR, 0,
+			NULL, 0),
+
+	SND_SOC_DAPM_OUTPUT("LineOut Left"),
+	SND_SOC_DAPM_OUTPUT("LineOut Right"),
+
+	/* Earpiece path */
+
+	SND_SOC_DAPM_MUX("Earpiece or LineOut Mono Source",
+			SND_SOC_NOPM, 0, 0, &dapm_ear_lineout_source),
+	SND_SOC_DAPM_MIXER("EAR DAC",
+			AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACEAR, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("EAR Mute",
+			AB8500_MUTECONF, AB8500_MUTECONF_MUTEAR, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("EAR Enable",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENEAR, 0,
+			NULL, 0),
+
+	SND_SOC_DAPM_OUTPUT("Earpiece"),
+
+	/* Handsfree path */
+
+	SND_SOC_DAPM_MIXER("DA3 Channel Volume",
+			AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA3, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DA4 Channel Volume",
+			AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA4, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MUX("Speaker Left Source",
+			SND_SOC_NOPM, 0, 0, dapm_HFl_select),
+	SND_SOC_DAPM_MUX("Speaker Right Source",
+			SND_SOC_NOPM, 0, 0, dapm_HFr_select),
+	SND_SOC_DAPM_MIXER("HFL DAC", AB8500_DAPATHCONF,
+			AB8500_DAPATHCONF_ENDACHFL, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("HFR DAC",
+			AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHFR, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DA4 or ANC path to HfR",
+			AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFREN, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DA3 or ANC path to HfL",
+			AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFLEN, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("HFL Enable",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("HFR Enable",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 0,
+			NULL, 0),
+
+	SND_SOC_DAPM_OUTPUT("Speaker Left"),
+	SND_SOC_DAPM_OUTPUT("Speaker Right"),
+
+	/* Vibrator path */
+
+	SND_SOC_DAPM_INPUT("PWMGEN1"),
+	SND_SOC_DAPM_INPUT("PWMGEN2"),
+
+	SND_SOC_DAPM_MIXER("DA5 Channel Volume",
+			AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA5, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DA6 Channel Volume",
+			AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA6, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("VIB1 DAC",
+			AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB1, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("VIB2 DAC",
+			AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB2, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MUX("Vibra 1 Controller",
+			SND_SOC_NOPM, 0, 0, dapm_pwm2vib1),
+	SND_SOC_DAPM_MUX("Vibra 2 Controller",
+			SND_SOC_NOPM, 0, 0, dapm_pwm2vib2),
+	SND_SOC_DAPM_MIXER("VIB1 Enable",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENVIB1, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("VIB2 Enable",
+			AB8500_ANACONF4, AB8500_ANACONF4_ENVIB2, 0,
+			NULL, 0),
+
+	SND_SOC_DAPM_OUTPUT("Vibra 1"),
+	SND_SOC_DAPM_OUTPUT("Vibra 2"),
+
+	/* Mic 1 */
+
+	SND_SOC_DAPM_INPUT("Mic 1"),
+
+	SND_SOC_DAPM_MUX("Mic 1a or 1b Select",
+			SND_SOC_NOPM, 0, 0, dapm_mic1ab_mux),
+	SND_SOC_DAPM_MIXER("MIC1 Mute",
+			AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC1, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("MIC1A V-AMICx Enable",
+			AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("MIC1B V-AMICx Enable",
+			AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("MIC1 ADC",
+			AB8500_ANACONF3, AB8500_ANACONF3_ENADCMIC, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MUX("AD3 Source Select",
+			SND_SOC_NOPM, 0, 0, dapm_ad3_select),
+	SND_SOC_DAPM_MIXER("AD3 Channel Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("AD3 Enable",
+			AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34, 0,
+			NULL, 0),
+
+	/* Mic 2 */
+
+	SND_SOC_DAPM_INPUT("Mic 2"),
+
+	SND_SOC_DAPM_MIXER("MIC2 Mute",
+			AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC2, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("MIC2 V-AMICx Enable", AB8500_ANACONF2,
+			AB8500_ANACONF2_ENMIC2, 0,
+			NULL, 0),
+
+	/* LineIn */
+
+	SND_SOC_DAPM_INPUT("LineIn Left"),
+	SND_SOC_DAPM_INPUT("LineIn Right"),
+
+	SND_SOC_DAPM_MIXER("LINL Mute",
+			AB8500_ANACONF2, AB8500_ANACONF2_MUTLINL, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("LINR Mute",
+			AB8500_ANACONF2, AB8500_ANACONF2_MUTLINR, 1,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("LINL Enable", AB8500_ANACONF2,
+			AB8500_ANACONF2_ENLINL, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("LINR Enable", AB8500_ANACONF2,
+			AB8500_ANACONF2_ENLINR, 0,
+			NULL, 0),
+
+	/* LineIn Bypass path */
+	SND_SOC_DAPM_MIXER("LINL to HSL Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("LINR to HSR Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+
+	/* LineIn, Mic 2 */
+	SND_SOC_DAPM_MUX("Mic 2 or LINR Select",
+			SND_SOC_NOPM, 0, 0, dapm_mic2lr_select),
+	SND_SOC_DAPM_MIXER("LINL ADC", AB8500_ANACONF3,
+			AB8500_ANACONF3_ENADCLINL, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("LINR ADC", AB8500_ANACONF3,
+			AB8500_ANACONF3_ENADCLINR, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MUX("AD1 Source Select",
+			SND_SOC_NOPM, 0, 0, dapm_ad1_select),
+	SND_SOC_DAPM_MUX("AD2 Source Select",
+			SND_SOC_NOPM, 0, 0, dapm_ad2_select),
+	SND_SOC_DAPM_MIXER("AD1 Channel Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("AD2 Channel Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+
+	SND_SOC_DAPM_MIXER("AD12 Enable",
+			AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD12, 0,
+			NULL, 0),
+
+	/* HD Capture path */
+
+	SND_SOC_DAPM_MUX("AD5 Source Select",
+			SND_SOC_NOPM, 0, 0, dapm_ad5_select),
+	SND_SOC_DAPM_MUX("AD6 Source Select",
+			SND_SOC_NOPM, 0, 0, dapm_ad6_select),
+	SND_SOC_DAPM_MIXER("AD5 Channel Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("AD6 Channel Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("AD57 Enable",
+			AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("AD68 Enable",
+			AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0,
+			NULL, 0),
+
+	/* Digital Microphone path */
+
+	SND_SOC_DAPM_INPUT("DMic 1"),
+	SND_SOC_DAPM_INPUT("DMic 2"),
+	SND_SOC_DAPM_INPUT("DMic 3"),
+	SND_SOC_DAPM_INPUT("DMic 4"),
+	SND_SOC_DAPM_INPUT("DMic 5"),
+	SND_SOC_DAPM_INPUT("DMic 6"),
+
+	SND_SOC_DAPM_MIXER("DMIC1",
+			AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC1, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DMIC2",
+			AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC2, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DMIC3",
+			AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC3, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DMIC4",
+			AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC4, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DMIC5",
+			AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC5, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("DMIC6",
+			AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC6, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("AD4 Channel Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("AD4 Enable",
+			AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34,
+			0, NULL, 0),
+
+	/* Acoustical Noise Cancellation path */
+
+	SND_SOC_DAPM_INPUT("ANC Configure Input"),
+	SND_SOC_DAPM_OUTPUT("ANC Configure Output"),
+
+	SND_SOC_DAPM_MUX("ANC Source",
+			SND_SOC_NOPM, 0, 0,
+			dapm_anc_in_select),
+	SND_SOC_DAPM_SWITCH("ANC",
+			SND_SOC_NOPM, 0, 0,
+			dapm_anc_enable),
+	SND_SOC_DAPM_SWITCH("ANC to Earpiece",
+			SND_SOC_NOPM, 0, 0,
+			dapm_anc_ear_mute),
+
+	/* Sidetone Filter path */
+
+	SND_SOC_DAPM_MUX("Sidetone Left Source",
+			SND_SOC_NOPM, 0, 0,
+			dapm_stfir1_in_select),
+	SND_SOC_DAPM_MUX("Sidetone Right Source",
+			SND_SOC_NOPM, 0, 0,
+			dapm_stfir2_in_select),
+	SND_SOC_DAPM_MIXER("STFIR1 Control",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("STFIR2 Control",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("STFIR1 Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+	SND_SOC_DAPM_MIXER("STFIR2 Volume",
+			SND_SOC_NOPM, 0, 0,
+			NULL, 0),
+};
+
+/*
+ * DAPM-routes
+ */
+static const struct snd_soc_dapm_route ab8500_dapm_routes[] = {
+	/* Power AB8500 audio-block when AD/DA is active */
+	{"Main Supply", NULL, "V-AUD"},
+	{"Main Supply", NULL, "audioclk"},
+	{"Main Supply", NULL, "Audio Power"},
+	{"Main Supply", NULL, "Audio Analog Power"},
+
+	{"DAC", NULL, "ab8500_0p"},
+	{"DAC", NULL, "Main Supply"},
+	{"ADC", NULL, "ab8500_0c"},
+	{"ADC", NULL, "Main Supply"},
+
+	/* ANC Configure */
+	{"ANC Configure Input", NULL, "Main Supply"},
+	{"ANC Configure Output", NULL, "ANC Configure Input"},
+
+	/* AD/DA */
+	{"ADC", NULL, "ADC Input"},
+	{"DAC Output", NULL, "DAC"},
+
+	/* Powerup charge pump if DA1/2 is in use */
+
+	{"DA_IN1", NULL, "ab8500_0p"},
+	{"DA_IN1", NULL, "Charge Pump"},
+	{"DA_IN2", NULL, "ab8500_0p"},
+	{"DA_IN2", NULL, "Charge Pump"},
+
+	/* Headset path */
+
+	{"DA1 Enable", NULL, "DA_IN1"},
+	{"DA2 Enable", NULL, "DA_IN2"},
+
+	{"HSL Digital Volume", NULL, "DA1 Enable"},
+	{"HSR Digital Volume", NULL, "DA2 Enable"},
+
+	{"HSL DAC", NULL, "HSL Digital Volume"},
+	{"HSR DAC", NULL, "HSR Digital Volume"},
+
+	{"HSL DAC Mute", NULL, "HSL DAC"},
+	{"HSR DAC Mute", NULL, "HSR DAC"},
+
+	{"HSL DAC Driver", NULL, "HSL DAC Mute"},
+	{"HSR DAC Driver", NULL, "HSR DAC Mute"},
+
+	{"HSL Mute", NULL, "HSL DAC Driver"},
+	{"HSR Mute", NULL, "HSR DAC Driver"},
+
+	{"HSL Enable", NULL, "HSL Mute"},
+	{"HSR Enable", NULL, "HSR Mute"},
+
+	{"HSL Volume", NULL, "HSL Enable"},
+	{"HSR Volume", NULL, "HSR Enable"},
+
+	{"Headset Left", NULL, "HSL Volume"},
+	{"Headset Right", NULL, "HSR Volume"},
+
+	/* HF or LineOut path */
+
+	{"DA_IN3", NULL, "ab8500_0p"},
+	{"DA3 Channel Volume", NULL, "DA_IN3"},
+	{"DA_IN4", NULL, "ab8500_0p"},
+	{"DA4 Channel Volume", NULL, "DA_IN4"},
+
+	{"Speaker Left Source", "Audio Path", "DA3 Channel Volume"},
+	{"Speaker Right Source", "Audio Path", "DA4 Channel Volume"},
+
+	{"DA3 or ANC path to HfL", NULL, "Speaker Left Source"},
+	{"DA4 or ANC path to HfR", NULL, "Speaker Right Source"},
+
+	/* HF path */
+
+	{"HFL DAC", NULL, "DA3 or ANC path to HfL"},
+	{"HFR DAC", NULL, "DA4 or ANC path to HfR"},
+
+	{"HFL Enable", NULL, "HFL DAC"},
+	{"HFR Enable", NULL, "HFR DAC"},
+
+	{"Speaker Left", NULL, "HFL Enable"},
+	{"Speaker Right", NULL, "HFR Enable"},
+
+	/* Earpiece path */
+
+	{"Earpiece or LineOut Mono Source", "Headset Left",
+		"HSL Digital Volume"},
+	{"Earpiece or LineOut Mono Source", "Speaker Left",
+		"DA3 or ANC path to HfL"},
+
+	{"EAR DAC", NULL, "Earpiece or LineOut Mono Source"},
+
+	{"EAR Mute", NULL, "EAR DAC"},
+
+	{"EAR Enable", NULL, "EAR Mute"},
+
+	{"Earpiece", NULL, "EAR Enable"},
+
+	/* LineOut path stereo */
+
+	{"LineOut Source", "Stereo Path", "HSL DAC Driver"},
+	{"LineOut Source", "Stereo Path", "HSR DAC Driver"},
+
+	/* LineOut path mono */
+
+	{"LineOut Source", "Mono Path", "EAR DAC"},
+
+	/* LineOut path */
+
+	{"LOL Disable HFL", NULL, "LineOut Source"},
+	{"LOR Disable HFR", NULL, "LineOut Source"},
+
+	{"LOL Enable", NULL, "LOL Disable HFL"},
+	{"LOR Enable", NULL, "LOR Disable HFR"},
+
+	{"LineOut Left", NULL, "LOL Enable"},
+	{"LineOut Right", NULL, "LOR Enable"},
+
+	/* Vibrator path */
+
+	{"DA_IN5", NULL, "ab8500_0p"},
+	{"DA5 Channel Volume", NULL, "DA_IN5"},
+	{"DA_IN6", NULL, "ab8500_0p"},
+	{"DA6 Channel Volume", NULL, "DA_IN6"},
+
+	{"VIB1 DAC", NULL, "DA5 Channel Volume"},
+	{"VIB2 DAC", NULL, "DA6 Channel Volume"},
+
+	{"Vibra 1 Controller", "Audio Path", "VIB1 DAC"},
+	{"Vibra 2 Controller", "Audio Path", "VIB2 DAC"},
+	{"Vibra 1 Controller", "PWM Generator", "PWMGEN1"},
+	{"Vibra 2 Controller", "PWM Generator", "PWMGEN2"},
+
+	{"VIB1 Enable", NULL, "Vibra 1 Controller"},
+	{"VIB2 Enable", NULL, "Vibra 2 Controller"},
+
+	{"Vibra 1", NULL, "VIB1 Enable"},
+	{"Vibra 2", NULL, "VIB2 Enable"},
+
+
+	/* Mic 2 */
+
+	{"MIC2 V-AMICx Enable", NULL, "Mic 2"},
+
+	/* LineIn */
+	{"LINL Mute", NULL, "LineIn Left"},
+	{"LINR Mute", NULL, "LineIn Right"},
+
+	{"LINL Enable", NULL, "LINL Mute"},
+	{"LINR Enable", NULL, "LINR Mute"},
+
+	/* LineIn, Mic 2 */
+	{"Mic 2 or LINR Select", "LineIn Right", "LINR Enable"},
+	{"Mic 2 or LINR Select", "Mic 2", "MIC2 V-AMICx Enable"},
+
+	{"LINL ADC", NULL, "LINL Enable"},
+	{"LINR ADC", NULL, "Mic 2 or LINR Select"},
+
+	{"AD1 Source Select", "LineIn Left", "LINL ADC"},
+	{"AD2 Source Select", "LineIn Right", "LINR ADC"},
+
+	{"AD1 Channel Volume", NULL, "AD1 Source Select"},
+	{"AD2 Channel Volume", NULL, "AD2 Source Select"},
+
+	{"AD12 Enable", NULL, "AD1 Channel Volume"},
+	{"AD12 Enable", NULL, "AD2 Channel Volume"},
+
+	{"AD_OUT1", NULL, "ab8500_0c"},
+	{"AD_OUT1", NULL, "AD12 Enable"},
+	{"AD_OUT2", NULL, "ab8500_0c"},
+	{"AD_OUT2", NULL, "AD12 Enable"},
+
+	/* Mic 1 */
+
+	{"MIC1 Mute", NULL, "Mic 1"},
+
+	{"MIC1A V-AMICx Enable", NULL, "MIC1 Mute"},
+	{"MIC1B V-AMICx Enable", NULL, "MIC1 Mute"},
+
+	{"Mic 1a or 1b Select", "Mic 1a", "MIC1A V-AMICx Enable"},
+	{"Mic 1a or 1b Select", "Mic 1b", "MIC1B V-AMICx Enable"},
+
+	{"MIC1 ADC", NULL, "Mic 1a or 1b Select"},
+
+	{"AD3 Source Select", "Mic 1", "MIC1 ADC"},
+
+	{"AD3 Channel Volume", NULL, "AD3 Source Select"},
+
+	{"AD3 Enable", NULL, "AD3 Channel Volume"},
+
+	{"AD_OUT3", NULL, "ab8500_0c"},
+	{"AD_OUT3", NULL, "AD3 Enable"},
+
+	/* HD Capture path */
+
+	{"AD5 Source Select", "Mic 2", "LINR ADC"},
+	{"AD6 Source Select", "Mic 1", "MIC1 ADC"},
+
+	{"AD5 Channel Volume", NULL, "AD5 Source Select"},
+	{"AD6 Channel Volume", NULL, "AD6 Source Select"},
+
+	{"AD57 Enable", NULL, "AD5 Channel Volume"},
+	{"AD68 Enable", NULL, "AD6 Channel Volume"},
+
+	{"AD_OUT57", NULL, "ab8500_0c"},
+	{"AD_OUT57", NULL, "AD57 Enable"},
+	{"AD_OUT68", NULL, "ab8500_0c"},
+	{"AD_OUT68", NULL, "AD68 Enable"},
+
+	/* Digital Microphone path */
+
+	{"DMic 1", NULL, "V-DMIC"},
+	{"DMic 2", NULL, "V-DMIC"},
+	{"DMic 3", NULL, "V-DMIC"},
+	{"DMic 4", NULL, "V-DMIC"},
+	{"DMic 5", NULL, "V-DMIC"},
+	{"DMic 6", NULL, "V-DMIC"},
+
+	{"AD1 Source Select", NULL, "DMic 1"},
+	{"AD2 Source Select", NULL, "DMic 2"},
+	{"AD3 Source Select", NULL, "DMic 3"},
+	{"AD5 Source Select", NULL, "DMic 5"},
+	{"AD6 Source Select", NULL, "DMic 6"},
+
+	{"AD4 Channel Volume", NULL, "DMic 4"},
+	{"AD4 Enable", NULL, "AD4 Channel Volume"},
+
+	{"AD_OUT4", NULL, "ab8500_0c"},
+	{"AD_OUT4", NULL, "AD4 Enable"},
+
+	/* LineIn Bypass path */
+
+	{"LINL to HSL Volume", NULL, "LINL Enable"},
+	{"LINR to HSR Volume", NULL, "LINR Enable"},
+
+	{"HSL DAC Driver", NULL, "LINL to HSL Volume"},
+	{"HSR DAC Driver", NULL, "LINR to HSR Volume"},
+
+	/* ANC path (Acoustic Noise Cancellation) */
+
+	{"ANC Source", "Mic 2 / DMic 5", "AD5 Channel Volume"},
+	{"ANC Source", "Mic 1 / DMic 6", "AD6 Channel Volume"},
+
+	{"ANC", "Switch", "ANC Source"},
+
+	{"Speaker Left Source", "ANC", "ANC"},
+	{"Speaker Right Source", "ANC", "ANC"},
+	{"ANC to Earpiece", "Switch", "ANC"},
+
+	{"HSL Digital Volume", NULL, "ANC to Earpiece"},
+
+	/* Sidetone Filter path */
+
+	{"Sidetone Left Source", "LineIn Left", "AD12 Enable"},
+	{"Sidetone Left Source", "LineIn Right", "AD12 Enable"},
+	{"Sidetone Left Source", "Mic 1", "AD3 Enable"},
+	{"Sidetone Left Source", "Headset Left", "DA_IN1"},
+	{"Sidetone Right Source", "LineIn Right", "AD12 Enable"},
+	{"Sidetone Right Source", "Mic 1", "AD3 Enable"},
+	{"Sidetone Right Source", "DMic 4", "AD4 Enable"},
+	{"Sidetone Right Source", "Headset Right", "DA_IN2"},
+
+	{"STFIR1 Control", NULL, "Sidetone Left Source"},
+	{"STFIR2 Control", NULL, "Sidetone Right Source"},
+
+	{"STFIR1 Volume", NULL, "STFIR1 Control"},
+	{"STFIR2 Volume", NULL, "STFIR2 Control"},
+
+	{"DA1 Enable", NULL, "STFIR1 Volume"},
+	{"DA2 Enable", NULL, "STFIR2 Volume"},
+};
+
+static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1a_vamicx[] = {
+	{"MIC1A V-AMICx Enable", NULL, "V-AMIC1"},
+	{"MIC1A V-AMICx Enable", NULL, "V-AMIC2"},
+};
+
+static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1b_vamicx[] = {
+	{"MIC1B V-AMICx Enable", NULL, "V-AMIC1"},
+	{"MIC1B V-AMICx Enable", NULL, "V-AMIC2"},
+};
+
+static const struct snd_soc_dapm_route ab8500_dapm_routes_mic2_vamicx[] = {
+	{"MIC2 V-AMICx Enable", NULL, "V-AMIC1"},
+	{"MIC2 V-AMICx Enable", NULL, "V-AMIC2"},
+};
+
+/* ANC FIR-coefficients configuration sequence */
+static void anc_fir(struct snd_soc_codec *codec,
+		unsigned int bnk, unsigned int par, unsigned int val)
+{
+	if (par == 0 && bnk == 0)
+		snd_soc_update_bits(codec, AB8500_ANCCONF1,
+			BIT(AB8500_ANCCONF1_ANCFIRUPDATE),
+			BIT(AB8500_ANCCONF1_ANCFIRUPDATE));
+
+	snd_soc_write(codec, AB8500_ANCCONF5, val >> 8 & 0xff);
+	snd_soc_write(codec, AB8500_ANCCONF6, val &  0xff);
+
+	if (par == AB8500_ANC_FIR_COEFFS - 1 && bnk == 1)
+		snd_soc_update_bits(codec, AB8500_ANCCONF1,
+			BIT(AB8500_ANCCONF1_ANCFIRUPDATE), 0);
+}
+
+/* ANC IIR-coefficients configuration sequence */
+static void anc_iir(struct snd_soc_codec *codec, unsigned int bnk,
+		unsigned int par, unsigned int val)
+{
+	if (par == 0) {
+		if (bnk == 0) {
+			snd_soc_update_bits(codec, AB8500_ANCCONF1,
+					BIT(AB8500_ANCCONF1_ANCIIRINIT),
+					BIT(AB8500_ANCCONF1_ANCIIRINIT));
+			usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY);
+			snd_soc_update_bits(codec, AB8500_ANCCONF1,
+					BIT(AB8500_ANCCONF1_ANCIIRINIT), 0);
+			usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY);
+		} else {
+			snd_soc_update_bits(codec, AB8500_ANCCONF1,
+					BIT(AB8500_ANCCONF1_ANCIIRUPDATE),
+					BIT(AB8500_ANCCONF1_ANCIIRUPDATE));
+		}
+	} else if (par > 3) {
+		snd_soc_write(codec, AB8500_ANCCONF7, 0);
+		snd_soc_write(codec, AB8500_ANCCONF8, val >> 16 & 0xff);
+	}
+
+	snd_soc_write(codec, AB8500_ANCCONF7, val >> 8 & 0xff);
+	snd_soc_write(codec, AB8500_ANCCONF8, val & 0xff);
+
+	if (par == AB8500_ANC_IIR_COEFFS - 1 && bnk == 1)
+		snd_soc_update_bits(codec, AB8500_ANCCONF1,
+			BIT(AB8500_ANCCONF1_ANCIIRUPDATE), 0);
+}
+
+/* ANC IIR-/FIR-coefficients configuration sequence */
+static void anc_configure(struct snd_soc_codec *codec,
+			bool apply_fir, bool apply_iir)
+{
+	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
+	unsigned int bnk, par, val;
+
+	dev_dbg(codec->dev, "%s: Enter.\n", __func__);
+
+	if (apply_fir)
+		snd_soc_update_bits(codec, AB8500_ANCCONF1,
+			BIT(AB8500_ANCCONF1_ENANC), 0);
+
+	snd_soc_update_bits(codec, AB8500_ANCCONF1,
+		BIT(AB8500_ANCCONF1_ENANC), BIT(AB8500_ANCCONF1_ENANC));
+
+	if (apply_fir)
+		for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++)
+			for (par = 0; par < AB8500_ANC_FIR_COEFFS; par++) {
+				val = snd_soc_read(codec,
+						drvdata->anc_fir_values[par]);
+				anc_fir(codec, bnk, par, val);
+			}
+
+	if (apply_iir)
+		for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++)
+			for (par = 0; par < AB8500_ANC_IIR_COEFFS; par++) {
+				val = snd_soc_read(codec,
+						drvdata->anc_iir_values[par]);
+				anc_iir(codec, bnk, par, val);
+			}
+
+	dev_dbg(codec->dev, "%s: Exit.\n", __func__);
+}
+
+/*
+ * Control-events
+ */
+
+static int sid_status_control_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
+
+	mutex_lock(&codec->mutex);
+	ucontrol->value.integer.value[0] = drvdata->sid_status;
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
+/* Write sidetone FIR-coefficients configuration sequence */
+static int sid_status_control_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
+	unsigned int param, sidconf, val;
+	int status = 1;
+
+	dev_dbg(codec->dev, "%s: Enter\n", __func__);
+
+	if (ucontrol->value.integer.value[0] != SID_APPLY_FIR) {
+		dev_err(codec->dev,
+			"%s: ERROR: This control supports '%s' only!\n",
+			__func__, enum_sid_state[SID_APPLY_FIR]);
+		return -EIO;
+	}
+
+	mutex_lock(&codec->mutex);
+
+	sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF);
+	if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) {
+		if ((sidconf & BIT(AB8500_SIDFIRCONF_ENFIRSIDS)) == 0) {
+			dev_err(codec->dev, "%s: Sidetone busy while off!\n",
+				__func__);
+			status = -EPERM;
+		} else {
+			status = -EBUSY;
+		}
+		goto out;
+	}
+
+	snd_soc_write(codec, AB8500_SIDFIRADR, 0);
+
+	for (param = 0; param < AB8500_SID_FIR_COEFFS; param++) {
+		val = snd_soc_read(codec, drvdata->sid_fir_values[param]);
+		snd_soc_write(codec, AB8500_SIDFIRCOEF1, val >> 8 & 0xff);
+		snd_soc_write(codec, AB8500_SIDFIRCOEF2, val & 0xff);
+	}
+
+	snd_soc_update_bits(codec, AB8500_SIDFIRADR,
+		BIT(AB8500_SIDFIRADR_FIRSIDSET),
+		BIT(AB8500_SIDFIRADR_FIRSIDSET));
+	snd_soc_update_bits(codec, AB8500_SIDFIRADR,
+		BIT(AB8500_SIDFIRADR_FIRSIDSET), 0);
+
+	drvdata->sid_status = SID_FIR_CONFIGURED;
+
+out:
+	mutex_unlock(&codec->mutex);
+
+	dev_dbg(codec->dev, "%s: Exit\n", __func__);
+
+	return status;
+}
+
+static int anc_status_control_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
+
+	mutex_lock(&codec->mutex);
+	ucontrol->value.integer.value[0] = drvdata->anc_status;
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
+static int anc_status_control_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
+	struct device *dev = codec->dev;
+	bool apply_fir, apply_iir;
+	int req, status;
+
+	dev_dbg(dev, "%s: Enter.\n", __func__);
+
+	mutex_lock(&drvdata->anc_lock);
+
+	req = ucontrol->value.integer.value[0];
+	if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR &&
+		req != ANC_APPLY_IIR) {
+		dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n",
+			__func__, enum_anc_state[req]);
+		status = -EINVAL;
+		goto cleanup;
+	}
+	apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR;
+	apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR;
+
+	status = snd_soc_dapm_force_enable_pin(&codec->dapm,
+					"ANC Configure Input");
+	if (status < 0) {
+		dev_err(dev,
+			"%s: ERROR: Failed to enable power (status = %d)!\n",
+			__func__, status);
+		goto cleanup;
+	}
+	snd_soc_dapm_sync(&codec->dapm);
+
+	mutex_lock(&codec->mutex);
+	anc_configure(codec, apply_fir, apply_iir);
+	mutex_unlock(&codec->mutex);
+
+	if (apply_fir) {
+		if (drvdata->anc_status == ANC_IIR_CONFIGURED)
+			drvdata->anc_status = ANC_FIR_IIR_CONFIGURED;
+		else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED)
+			drvdata->anc_status =  ANC_FIR_CONFIGURED;
+	}
+	if (apply_iir) {
+		if (drvdata->anc_status == ANC_FIR_CONFIGURED)
+			drvdata->anc_status = ANC_FIR_IIR_CONFIGURED;
+		else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED)
+			drvdata->anc_status =  ANC_IIR_CONFIGURED;
+	}
+
+	status = snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input");
+	snd_soc_dapm_sync(&codec->dapm);
+
+cleanup:
+	mutex_unlock(&drvdata->anc_lock);
+
+	if (status < 0)
+		dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n",
+			__func__, status);
+
+	dev_dbg(dev, "%s: Exit.\n", __func__);
+
+	return (status < 0) ? status : 1;
+}
+
+static int filter_control_info(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *uinfo)
+{
+	struct filter_control *fc =
+			(struct filter_control *)kcontrol->private_value;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = fc->count;
+	uinfo->value.integer.min = fc->min;
+	uinfo->value.integer.max = fc->max;
+
+	return 0;
+}
+
+static int filter_control_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct filter_control *fc =
+			(struct filter_control *)kcontrol->private_value;
+	unsigned int i;
+
+	mutex_lock(&codec->mutex);
+	for (i = 0; i < fc->count; i++)
+		ucontrol->value.integer.value[i] = fc->value[i];
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
+static int filter_control_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct filter_control *fc =
+			(struct filter_control *)kcontrol->private_value;
+	unsigned int i;
+
+	mutex_lock(&codec->mutex);
+	for (i = 0; i < fc->count; i++)
+		fc->value[i] = ucontrol->value.integer.value[i];
+	mutex_unlock(&codec->mutex);
+
+	return 0;
+}
+
+/*
+ * Controls - Non-DAPM ASoC
+ */
+
+static DECLARE_TLV_DB_SCALE(adx_dig_gain_tlv, -3200, 100, 1);
+/* -32dB = Mute */
+
+static DECLARE_TLV_DB_SCALE(dax_dig_gain_tlv, -6300, 100, 1);
+/* -63dB = Mute */
+
+static DECLARE_TLV_DB_SCALE(hs_ear_dig_gain_tlv, -100, 100, 1);
+/* -1dB = Mute */
+
+static const unsigned int hs_gain_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 3, TLV_DB_SCALE_ITEM(-3200, 400, 0),
+	4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0),
+};
+
+static DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0);
+
+static DECLARE_TLV_DB_SCALE(lin_gain_tlv, -1000, 200, 0);
+
+static DECLARE_TLV_DB_SCALE(lin2hs_gain_tlv, -3800, 200, 1);
+/* -38dB = Mute */
+
+static const char * const enum_hsfadspeed[] = {"2ms", "0.5ms", "10.6ms",
+					"5ms"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_hsfadspeed,
+	AB8500_DIGMICCONF, AB8500_DIGMICCONF_HSFADSPEED, enum_hsfadspeed);
+
+static const char * const enum_envdetthre[] = {
+	"250mV", "300mV", "350mV", "400mV",
+	"450mV", "500mV", "550mV", "600mV",
+	"650mV", "700mV", "750mV", "800mV",
+	"850mV", "900mV", "950mV", "1.00V" };
+static SOC_ENUM_SINGLE_DECL(soc_enum_envdeththre,
+	AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETHTHRE, enum_envdetthre);
+static SOC_ENUM_SINGLE_DECL(soc_enum_envdetlthre,
+	AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETLTHRE, enum_envdetthre);
+static const char * const enum_envdettime[] = {
+	"26.6us", "53.2us", "106us",  "213us",
+	"426us",  "851us",  "1.70ms", "3.40ms",
+	"6.81ms", "13.6ms", "27.2ms", "54.5ms",
+	"109ms",  "218ms",  "436ms",  "872ms" };
+static SOC_ENUM_SINGLE_DECL(soc_enum_envdettime,
+	AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETTIME, enum_envdettime);
+
+static const char * const enum_sinc31[] = {"Sinc 3", "Sinc 1"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_hsesinc, AB8500_HSLEARDIGGAIN,
+			AB8500_HSLEARDIGGAIN_HSSINC1, enum_sinc31);
+
+static const char * const enum_fadespeed[] = {"1ms", "4ms", "8ms", "16ms"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_fadespeed, AB8500_HSRDIGGAIN,
+			AB8500_HSRDIGGAIN_FADESPEED, enum_fadespeed);
+
+/* Earpiece */
+
+static const char * const enum_lowpow[] = {"Normal", "Low Power"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_eardaclowpow, AB8500_ANACONF1,
+			AB8500_ANACONF1_EARDACLOWPOW, enum_lowpow);
+static SOC_ENUM_SINGLE_DECL(soc_enum_eardrvlowpow, AB8500_ANACONF1,
+			AB8500_ANACONF1_EARDRVLOWPOW, enum_lowpow);
+
+static const char * const enum_av_mode[] = {"Audio", "Voice"};
+static SOC_ENUM_DOUBLE_DECL(soc_enum_ad12voice, AB8500_ADFILTCONF,
+	AB8500_ADFILTCONF_AD1VOICE, AB8500_ADFILTCONF_AD2VOICE, enum_av_mode);
+static SOC_ENUM_DOUBLE_DECL(soc_enum_ad34voice, AB8500_ADFILTCONF,
+	AB8500_ADFILTCONF_AD3VOICE, AB8500_ADFILTCONF_AD4VOICE, enum_av_mode);
+
+/* DA */
+
+static SOC_ENUM_SINGLE_DECL(soc_enum_da12voice,
+			AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DA12VOICE,
+			enum_av_mode);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da34voice,
+			AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DA34VOICE,
+			enum_av_mode);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da56voice,
+			AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DA56VOICE,
+			enum_av_mode);
+
+static const char * const enum_da2hslr[] = {"Sidetone", "Audio Path"};
+static SOC_ENUM_DOUBLE_DECL(soc_enum_da2hslr, AB8500_DIGMULTCONF1,
+			AB8500_DIGMULTCONF1_DATOHSLEN,
+			AB8500_DIGMULTCONF1_DATOHSREN, enum_da2hslr);
+
+static const char * const enum_sinc53[] = {"Sinc 5", "Sinc 3"};
+static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic12sinc, AB8500_DMICFILTCONF,
+			AB8500_DMICFILTCONF_DMIC1SINC3,
+			AB8500_DMICFILTCONF_DMIC2SINC3, enum_sinc53);
+static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic34sinc, AB8500_DMICFILTCONF,
+			AB8500_DMICFILTCONF_DMIC3SINC3,
+			AB8500_DMICFILTCONF_DMIC4SINC3, enum_sinc53);
+static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic56sinc, AB8500_DMICFILTCONF,
+			AB8500_DMICFILTCONF_DMIC5SINC3,
+			AB8500_DMICFILTCONF_DMIC6SINC3, enum_sinc53);
+
+/* Digital interface - DA from slot mapping */
+static const char * const enum_da_from_slot_map[] = {"SLOT0",
+					"SLOT1",
+					"SLOT2",
+					"SLOT3",
+					"SLOT4",
+					"SLOT5",
+					"SLOT6",
+					"SLOT7",
+					"SLOT8",
+					"SLOT9",
+					"SLOT10",
+					"SLOT11",
+					"SLOT12",
+					"SLOT13",
+					"SLOT14",
+					"SLOT15",
+					"SLOT16",
+					"SLOT17",
+					"SLOT18",
+					"SLOT19",
+					"SLOT20",
+					"SLOT21",
+					"SLOT22",
+					"SLOT23",
+					"SLOT24",
+					"SLOT25",
+					"SLOT26",
+					"SLOT27",
+					"SLOT28",
+					"SLOT29",
+					"SLOT30",
+					"SLOT31"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_da1slotmap,
+			AB8500_DASLOTCONF1, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
+			enum_da_from_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da2slotmap,
+			AB8500_DASLOTCONF2, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
+			enum_da_from_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da3slotmap,
+			AB8500_DASLOTCONF3, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
+			enum_da_from_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da4slotmap,
+			AB8500_DASLOTCONF4, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
+			enum_da_from_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da5slotmap,
+			AB8500_DASLOTCONF5, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
+			enum_da_from_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da6slotmap,
+			AB8500_DASLOTCONF6, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
+			enum_da_from_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da7slotmap,
+			AB8500_DASLOTCONF7, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
+			enum_da_from_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_da8slotmap,
+			AB8500_DASLOTCONF8, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
+			enum_da_from_slot_map);
+
+/* Digital interface - AD to slot mapping */
+static const char * const enum_ad_to_slot_map[] = {"AD_OUT1",
+					"AD_OUT2",
+					"AD_OUT3",
+					"AD_OUT4",
+					"AD_OUT5",
+					"AD_OUT6",
+					"AD_OUT7",
+					"AD_OUT8",
+					"zeroes",
+					"tristate"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map,
+			AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot1map,
+			AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot2map,
+			AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot3map,
+			AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot4map,
+			AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot5map,
+			AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot6map,
+			AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot7map,
+			AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot8map,
+			AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot9map,
+			AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot10map,
+			AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot11map,
+			AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot12map,
+			AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot13map,
+			AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot14map,
+			AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot15map,
+			AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot16map,
+			AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot17map,
+			AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot18map,
+			AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot19map,
+			AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot20map,
+			AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot21map,
+			AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot22map,
+			AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot23map,
+			AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot24map,
+			AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot25map,
+			AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot26map,
+			AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot27map,
+			AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot28map,
+			AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot29map,
+			AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot30map,
+			AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_EVEN_SHIFT,
+			enum_ad_to_slot_map);
+static SOC_ENUM_SINGLE_DECL(soc_enum_adslot31map,
+			AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_ODD_SHIFT,
+			enum_ad_to_slot_map);
+
+/* Digital interface - Burst mode */
+static const char * const enum_mask[] = {"Unmasked", "Masked"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomask,
+			AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOMASK,
+			enum_mask);
+static const char * const enum_bitclk0[] = {"19_2_MHz", "38_4_MHz"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_bfifo19m2,
+			AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFO19M2,
+			enum_bitclk0);
+static const char * const enum_slavemaster[] = {"Slave", "Master"};
+static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomast,
+			AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOMAST_SHIFT,
+			enum_slavemaster);
+
+/* Sidetone */
+static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_sidstate, enum_sid_state);
+
+/* ANC */
+static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_ancstate, enum_anc_state);
+
+static struct snd_kcontrol_new ab8500_ctrls[] = {
+	/* Charge pump */
+	SOC_ENUM("Charge Pump High Threshold For Low Voltage",
+		soc_enum_envdeththre),
+	SOC_ENUM("Charge Pump Low Threshold For Low Voltage",
+		soc_enum_envdetlthre),
+	SOC_SINGLE("Charge Pump Envelope Detection Switch",
+		AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETCPEN,
+		1, 0),
+	SOC_ENUM("Charge Pump Envelope Detection Decay Time",
+		soc_enum_envdettime),
+
+	/* Headset */
+	SOC_ENUM("Headset Mode", soc_enum_da12voice),
+	SOC_SINGLE("Headset High Pass Switch",
+		AB8500_ANACONF1, AB8500_ANACONF1_HSHPEN,
+		1, 0),
+	SOC_SINGLE("Headset Low Power Switch",
+		AB8500_ANACONF1, AB8500_ANACONF1_HSLOWPOW,
+		1, 0),
+	SOC_SINGLE("Headset DAC Low Power Switch",
+		AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW1,
+		1, 0),
+	SOC_SINGLE("Headset DAC Drv Low Power Switch",
+		AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW0,
+		1, 0),
+	SOC_ENUM("Headset Fade Speed", soc_enum_hsfadspeed),
+	SOC_ENUM("Headset Source", soc_enum_da2hslr),
+	SOC_ENUM("Headset Filter", soc_enum_hsesinc),
+	SOC_DOUBLE_R_TLV("Headset Master Volume",
+		AB8500_DADIGGAIN1, AB8500_DADIGGAIN2,
+		0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv),
+	SOC_DOUBLE_R_TLV("Headset Digital Volume",
+		AB8500_HSLEARDIGGAIN, AB8500_HSRDIGGAIN,
+		0, AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX, 1, hs_ear_dig_gain_tlv),
+	SOC_DOUBLE_TLV("Headset Volume",
+		AB8500_ANAGAIN3,
+		AB8500_ANAGAIN3_HSLGAIN, AB8500_ANAGAIN3_HSRGAIN,
+		AB8500_ANAGAIN3_HSXGAIN_MAX, 1, hs_gain_tlv),
+
+	/* Earpiece */
+	SOC_ENUM("Earpiece DAC Mode",
+		soc_enum_eardaclowpow),
+	SOC_ENUM("Earpiece DAC Drv Mode",
+		soc_enum_eardrvlowpow),
+
+	/* HandsFree */
+	SOC_ENUM("HF Mode", soc_enum_da34voice),
+	SOC_SINGLE("HF and Headset Swap Switch",
+		AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_SWAPDA12_34,
+		1, 0),
+	SOC_DOUBLE("HF Low EMI Mode Switch",
+		AB8500_CLASSDCONF1,
+		AB8500_CLASSDCONF1_HFLSWAPEN, AB8500_CLASSDCONF1_HFRSWAPEN,
+		1, 0),
+	SOC_DOUBLE("HF FIR Bypass Switch",
+		AB8500_CLASSDCONF2,
+		AB8500_CLASSDCONF2_FIRBYP0, AB8500_CLASSDCONF2_FIRBYP1,
+		1, 0),
+	SOC_DOUBLE("HF High Volume Switch",
+		AB8500_CLASSDCONF2,
+		AB8500_CLASSDCONF2_HIGHVOLEN0, AB8500_CLASSDCONF2_HIGHVOLEN1,
+		1, 0),
+	SOC_SINGLE("HF L and R Bridge Switch",
+		AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLHF,
+		1, 0),
+	SOC_DOUBLE_R_TLV("HF Master Volume",
+		AB8500_DADIGGAIN3, AB8500_DADIGGAIN4,
+		0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv),
+
+	/* Vibra */
+	SOC_DOUBLE("Vibra High Volume Switch",
+		AB8500_CLASSDCONF2,
+		AB8500_CLASSDCONF2_HIGHVOLEN2, AB8500_CLASSDCONF2_HIGHVOLEN3,
+		1, 0),
+	SOC_DOUBLE("Vibra Low EMI Mode Switch",
+		AB8500_CLASSDCONF1,
+		AB8500_CLASSDCONF1_VIB1SWAPEN, AB8500_CLASSDCONF1_VIB2SWAPEN,
+		1, 0),
+	SOC_DOUBLE("Vibra FIR Bypass Switch",
+		AB8500_CLASSDCONF2,
+		AB8500_CLASSDCONF2_FIRBYP2, AB8500_CLASSDCONF2_FIRBYP3,
+		1, 0),
+	SOC_ENUM("Vibra Mode", soc_enum_da56voice),
+	SOC_DOUBLE_R("Vibra PWM Duty Cycle N",
+		AB8500_PWMGENCONF3, AB8500_PWMGENCONF5,
+		AB8500_PWMGENCONFX_PWMVIBXDUTCYC,
+		AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0),
+	SOC_DOUBLE_R("Vibra PWM Duty Cycle P",
+		AB8500_PWMGENCONF2, AB8500_PWMGENCONF4,
+		AB8500_PWMGENCONFX_PWMVIBXDUTCYC,
+		AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0),
+	SOC_SINGLE("Vibra 1 and 2 Bridge Switch",
+		AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLVIB,
+		1, 0),
+	SOC_DOUBLE_R_TLV("Vibra Master Volume",
+		AB8500_DADIGGAIN5, AB8500_DADIGGAIN6,
+		0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv),
+
+	/* HandsFree, Vibra */
+	SOC_SINGLE("ClassD High Pass Volume",
+		AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHHPGAIN,
+		AB8500_CLASSDCONF3_DITHHPGAIN_MAX, 0),
+	SOC_SINGLE("ClassD White Volume",
+		AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHWGAIN,
+		AB8500_CLASSDCONF3_DITHWGAIN_MAX, 0),
+
+	/* Mic 1, Mic 2, LineIn */
+	SOC_DOUBLE_R_TLV("Mic Master Volume",
+		AB8500_ADDIGGAIN3, AB8500_ADDIGGAIN4,
+		0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv),
+
+	/* Mic 1 */
+	SOC_SINGLE_TLV("Mic 1",
+		AB8500_ANAGAIN1,
+		AB8500_ANAGAINX_MICXGAIN,
+		AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv),
+	SOC_SINGLE("Mic 1 Low Power Switch",
+		AB8500_ANAGAIN1, AB8500_ANAGAINX_LOWPOWMICX,
+		1, 0),
+
+	/* Mic 2 */
+	SOC_DOUBLE("Mic High Pass Switch",
+		AB8500_ADFILTCONF,
+		AB8500_ADFILTCONF_AD3NH, AB8500_ADFILTCONF_AD4NH,
+		1, 1),
+	SOC_ENUM("Mic Mode", soc_enum_ad34voice),
+	SOC_ENUM("Mic Filter", soc_enum_dmic34sinc),
+	SOC_SINGLE_TLV("Mic 2",
+		AB8500_ANAGAIN2,
+		AB8500_ANAGAINX_MICXGAIN,
+		AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv),
+	SOC_SINGLE("Mic 2 Low Power Switch",
+		AB8500_ANAGAIN2, AB8500_ANAGAINX_LOWPOWMICX,
+		1, 0),
+
+	/* LineIn */
+	SOC_DOUBLE("LineIn High Pass Switch",
+		AB8500_ADFILTCONF,
+		AB8500_ADFILTCONF_AD1NH, AB8500_ADFILTCONF_AD2NH,
+		1, 1),
+	SOC_ENUM("LineIn Filter", soc_enum_dmic12sinc),
+	SOC_ENUM("LineIn Mode", soc_enum_ad12voice),
+	SOC_DOUBLE_R_TLV("LineIn Master Volume",
+		AB8500_ADDIGGAIN1, AB8500_ADDIGGAIN2,
+		0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv),
+	SOC_DOUBLE_TLV("LineIn",
+		AB8500_ANAGAIN4,
+		AB8500_ANAGAIN4_LINLGAIN, AB8500_ANAGAIN4_LINRGAIN,
+		AB8500_ANAGAIN4_LINXGAIN_MAX, 0, lin_gain_tlv),
+	SOC_DOUBLE_R_TLV("LineIn to Headset Volume",
+		AB8500_DIGLINHSLGAIN, AB8500_DIGLINHSRGAIN,
+		AB8500_DIGLINHSXGAIN_LINTOHSXGAIN,
+		AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX,
+		1, lin2hs_gain_tlv),
+
+	/* DMic */
+	SOC_ENUM("DMic Filter", soc_enum_dmic56sinc),
+	SOC_DOUBLE_R_TLV("DMic Master Volume",
+		AB8500_ADDIGGAIN5, AB8500_ADDIGGAIN6,
+		0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv),
+
+	/* Digital gains */
+	SOC_ENUM("Digital Gain Fade Speed", soc_enum_fadespeed),
+
+	/* Analog loopback */
+	SOC_DOUBLE_R_TLV("Analog Loopback Volume",
+		AB8500_ADDIGLOOPGAIN1, AB8500_ADDIGLOOPGAIN2,
+		0, AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX, 1, dax_dig_gain_tlv),
+
+	/* Digital interface - DA from slot mapping */
+	SOC_ENUM("Digital Interface DA 1 From Slot Map", soc_enum_da1slotmap),
+	SOC_ENUM("Digital Interface DA 2 From Slot Map", soc_enum_da2slotmap),
+	SOC_ENUM("Digital Interface DA 3 From Slot Map", soc_enum_da3slotmap),
+	SOC_ENUM("Digital Interface DA 4 From Slot Map", soc_enum_da4slotmap),
+	SOC_ENUM("Digital Interface DA 5 From Slot Map", soc_enum_da5slotmap),
+	SOC_ENUM("Digital Interface DA 6 From Slot Map", soc_enum_da6slotmap),
+	SOC_ENUM("Digital Interface DA 7 From Slot Map", soc_enum_da7slotmap),
+	SOC_ENUM("Digital Interface DA 8 From Slot Map", soc_enum_da8slotmap),
+
+	/* Digital interface - AD to slot mapping */
+	SOC_ENUM("Digital Interface AD To Slot 0 Map", soc_enum_adslot0map),
+	SOC_ENUM("Digital Interface AD To Slot 1 Map", soc_enum_adslot1map),
+	SOC_ENUM("Digital Interface AD To Slot 2 Map", soc_enum_adslot2map),
+	SOC_ENUM("Digital Interface AD To Slot 3 Map", soc_enum_adslot3map),
+	SOC_ENUM("Digital Interface AD To Slot 4 Map", soc_enum_adslot4map),
+	SOC_ENUM("Digital Interface AD To Slot 5 Map", soc_enum_adslot5map),
+	SOC_ENUM("Digital Interface AD To Slot 6 Map", soc_enum_adslot6map),
+	SOC_ENUM("Digital Interface AD To Slot 7 Map", soc_enum_adslot7map),
+	SOC_ENUM("Digital Interface AD To Slot 8 Map", soc_enum_adslot8map),
+	SOC_ENUM("Digital Interface AD To Slot 9 Map", soc_enum_adslot9map),
+	SOC_ENUM("Digital Interface AD To Slot 10 Map", soc_enum_adslot10map),
+	SOC_ENUM("Digital Interface AD To Slot 11 Map", soc_enum_adslot11map),
+	SOC_ENUM("Digital Interface AD To Slot 12 Map", soc_enum_adslot12map),
+	SOC_ENUM("Digital Interface AD To Slot 13 Map", soc_enum_adslot13map),
+	SOC_ENUM("Digital Interface AD To Slot 14 Map", soc_enum_adslot14map),
+	SOC_ENUM("Digital Interface AD To Slot 15 Map", soc_enum_adslot15map),
+	SOC_ENUM("Digital Interface AD To Slot 16 Map", soc_enum_adslot16map),
+	SOC_ENUM("Digital Interface AD To Slot 17 Map", soc_enum_adslot17map),
+	SOC_ENUM("Digital Interface AD To Slot 18 Map", soc_enum_adslot18map),
+	SOC_ENUM("Digital Interface AD To Slot 19 Map", soc_enum_adslot19map),
+	SOC_ENUM("Digital Interface AD To Slot 20 Map", soc_enum_adslot20map),
+	SOC_ENUM("Digital Interface AD To Slot 21 Map", soc_enum_adslot21map),
+	SOC_ENUM("Digital Interface AD To Slot 22 Map", soc_enum_adslot22map),
+	SOC_ENUM("Digital Interface AD To Slot 23 Map", soc_enum_adslot23map),
+	SOC_ENUM("Digital Interface AD To Slot 24 Map", soc_enum_adslot24map),
+	SOC_ENUM("Digital Interface AD To Slot 25 Map", soc_enum_adslot25map),
+	SOC_ENUM("Digital Interface AD To Slot 26 Map", soc_enum_adslot26map),
+	SOC_ENUM("Digital Interface AD To Slot 27 Map", soc_enum_adslot27map),
+	SOC_ENUM("Digital Interface AD To Slot 28 Map", soc_enum_adslot28map),
+	SOC_ENUM("Digital Interface AD To Slot 29 Map", soc_enum_adslot29map),
+	SOC_ENUM("Digital Interface AD To Slot 30 Map", soc_enum_adslot30map),
+	SOC_ENUM("Digital Interface AD To Slot 31 Map", soc_enum_adslot31map),
+
+	/* Digital interface - Loopback */
+	SOC_SINGLE("Digital Interface AD 1 Loopback Switch",
+		AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DAI7TOADO1,
+		1, 0),
+	SOC_SINGLE("Digital Interface AD 2 Loopback Switch",
+		AB8500_DASLOTCONF2, AB8500_DASLOTCONF2_DAI8TOADO2,
+		1, 0),
+	SOC_SINGLE("Digital Interface AD 3 Loopback Switch",
+		AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DAI7TOADO3,
+		1, 0),
+	SOC_SINGLE("Digital Interface AD 4 Loopback Switch",
+		AB8500_DASLOTCONF4, AB8500_DASLOTCONF4_DAI8TOADO4,
+		1, 0),
+	SOC_SINGLE("Digital Interface AD 5 Loopback Switch",
+		AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DAI7TOADO5,
+		1, 0),
+	SOC_SINGLE("Digital Interface AD 6 Loopback Switch",
+		AB8500_DASLOTCONF6, AB8500_DASLOTCONF6_DAI8TOADO6,
+		1, 0),
+	SOC_SINGLE("Digital Interface AD 7 Loopback Switch",
+		AB8500_DASLOTCONF7, AB8500_DASLOTCONF7_DAI8TOADO7,
+		1, 0),
+	SOC_SINGLE("Digital Interface AD 8 Loopback Switch",
+		AB8500_DASLOTCONF8, AB8500_DASLOTCONF8_DAI7TOADO8,
+		1, 0),
+
+	/* Digital interface - Burst FIFO */
+	SOC_SINGLE("Digital Interface 0 FIFO Enable Switch",
+		AB8500_DIGIFCONF3, AB8500_DIGIFCONF3_IF0BFIFOEN,
+		1, 0),
+	SOC_ENUM("Burst FIFO Mask", soc_enum_bfifomask),
+	SOC_ENUM("Burst FIFO Bit-clock Frequency", soc_enum_bfifo19m2),
+	SOC_SINGLE("Burst FIFO Threshold",
+		AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOINT_SHIFT,
+		AB8500_FIFOCONF1_BFIFOINT_MAX, 0),
+	SOC_SINGLE("Burst FIFO Length",
+		AB8500_FIFOCONF2, AB8500_FIFOCONF2_BFIFOTX_SHIFT,
+		AB8500_FIFOCONF2_BFIFOTX_MAX, 0),
+	SOC_SINGLE("Burst FIFO EOS Extra Slots",
+		AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOEXSL_SHIFT,
+		AB8500_FIFOCONF3_BFIFOEXSL_MAX, 0),
+	SOC_SINGLE("Burst FIFO FS Extra Bit-clocks",
+		AB8500_FIFOCONF3, AB8500_FIFOCONF3_PREBITCLK0_SHIFT,
+		AB8500_FIFOCONF3_PREBITCLK0_MAX, 0),
+	SOC_ENUM("Burst FIFO Interface Mode", soc_enum_bfifomast),
+
+	SOC_SINGLE("Burst FIFO Interface Switch",
+		AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFORUN_SHIFT,
+		1, 0),
+	SOC_SINGLE("Burst FIFO Switch Frame Number",
+		AB8500_FIFOCONF4, AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT,
+		AB8500_FIFOCONF4_BFIFOFRAMSW_MAX, 0),
+	SOC_SINGLE("Burst FIFO Wake Up Delay",
+		AB8500_FIFOCONF5, AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT,
+		AB8500_FIFOCONF5_BFIFOWAKEUP_MAX, 0),
+	SOC_SINGLE("Burst FIFO Samples In FIFO",
+		AB8500_FIFOCONF6, AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT,
+		AB8500_FIFOCONF6_BFIFOSAMPLE_MAX, 0),
+
+	/* ANC */
+	SOC_ENUM_EXT("ANC Status", soc_enum_ancstate,
+		anc_status_control_get, anc_status_control_put),
+	SOC_SINGLE_XR_SX("ANC Warp Delay Shift",
+		AB8500_ANCCONF2, 1, AB8500_ANCCONF2_SHIFT,
+		AB8500_ANCCONF2_MIN, AB8500_ANCCONF2_MAX, 0),
+	SOC_SINGLE_XR_SX("ANC FIR Output Shift",
+		AB8500_ANCCONF3, 1, AB8500_ANCCONF3_SHIFT,
+		AB8500_ANCCONF3_MIN, AB8500_ANCCONF3_MAX, 0),
+	SOC_SINGLE_XR_SX("ANC IIR Output Shift",
+		AB8500_ANCCONF4, 1, AB8500_ANCCONF4_SHIFT,
+		AB8500_ANCCONF4_MIN, AB8500_ANCCONF4_MAX, 0),
+	SOC_SINGLE_XR_SX("ANC Warp Delay",
+		AB8500_ANCCONF9, 2, AB8500_ANC_WARP_DELAY_SHIFT,
+		AB8500_ANC_WARP_DELAY_MIN, AB8500_ANC_WARP_DELAY_MAX, 0),
+
+	/* Sidetone */
+	SOC_ENUM_EXT("Sidetone Status", soc_enum_sidstate,
+		sid_status_control_get, sid_status_control_put),
+	SOC_SINGLE_STROBE("Sidetone Reset",
+		AB8500_SIDFIRADR, AB8500_SIDFIRADR_FIRSIDSET, 0),
+};
+
+static struct snd_kcontrol_new ab8500_filter_controls[] = {
+	AB8500_FILTER_CONTROL("ANC FIR Coefficients", AB8500_ANC_FIR_COEFFS,
+		AB8500_ANC_FIR_COEFF_MIN, AB8500_ANC_FIR_COEFF_MAX),
+	AB8500_FILTER_CONTROL("ANC IIR Coefficients", AB8500_ANC_IIR_COEFFS,
+		AB8500_ANC_IIR_COEFF_MIN, AB8500_ANC_IIR_COEFF_MAX),
+	AB8500_FILTER_CONTROL("Sidetone FIR Coefficients",
+			AB8500_SID_FIR_COEFFS, AB8500_SID_FIR_COEFF_MIN,
+			AB8500_SID_FIR_COEFF_MAX)
+};
+enum ab8500_filter {
+	AB8500_FILTER_ANC_FIR = 0,
+	AB8500_FILTER_ANC_IIR = 1,
+	AB8500_FILTER_SID_FIR = 2,
+};
+
+/*
+ * Extended interface for codec-driver
+ */
+
+static int ab8500_audio_init_audioblock(struct snd_soc_codec *codec)
+{
+	int status;
+
+	dev_dbg(codec->dev, "%s: Enter.\n", __func__);
+
+	/* Reset audio-registers and disable 32kHz-clock output 2 */
+	status = ab8500_sysctrl_write(AB8500_STW4500CTRL3,
+				AB8500_STW4500CTRL3_CLK32KOUT2DIS |
+					AB8500_STW4500CTRL3_RESETAUDN,
+				AB8500_STW4500CTRL3_RESETAUDN);
+	if (status < 0)
+		return status;
+
+	return 0;
+}
+
+static int ab8500_audio_setup_mics(struct snd_soc_codec *codec,
+			struct amic_settings *amics)
+{
+	u8 value8;
+	unsigned int value;
+	int status;
+	const struct snd_soc_dapm_route *route;
+
+	dev_dbg(codec->dev, "%s: Enter.\n", __func__);
+
+	/* Set DMic-clocks to outputs */
+	status = abx500_get_register_interruptible(codec->dev, (u8)AB8500_MISC,
+						(u8)AB8500_GPIO_DIR4_REG,
+						&value8);
+	if (status < 0)
+		return status;
+	value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT |
+		GPIO31_DIR_OUTPUT;
+	status = abx500_set_register_interruptible(codec->dev,
+						(u8)AB8500_MISC,
+						(u8)AB8500_GPIO_DIR4_REG,
+						value);
+	if (status < 0)
+		return status;
+
+	/* Attach regulators to AMic DAPM-paths */
+	dev_dbg(codec->dev, "%s: Mic 1a regulator: %s\n", __func__,
+		amic_micbias_str(amics->mic1a_micbias));
+	route = &ab8500_dapm_routes_mic1a_vamicx[amics->mic1a_micbias];
+	status = snd_soc_dapm_add_routes(&codec->dapm, route, 1);
+	dev_dbg(codec->dev, "%s: Mic 1b regulator: %s\n", __func__,
+		amic_micbias_str(amics->mic1b_micbias));
+	route = &ab8500_dapm_routes_mic1b_vamicx[amics->mic1b_micbias];
+	status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1);
+	dev_dbg(codec->dev, "%s: Mic 2 regulator: %s\n", __func__,
+		amic_micbias_str(amics->mic2_micbias));
+	route = &ab8500_dapm_routes_mic2_vamicx[amics->mic2_micbias];
+	status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1);
+	if (status < 0) {
+		dev_err(codec->dev,
+			"%s: Failed to add AMic-regulator DAPM-routes (%d).\n",
+			__func__, status);
+		return status;
+	}
+
+	/* Set AMic-configuration */
+	dev_dbg(codec->dev, "%s: Mic 1 mic-type: %s\n", __func__,
+		amic_type_str(amics->mic1_type));
+	snd_soc_update_bits(codec, AB8500_ANAGAIN1, AB8500_ANAGAINX_ENSEMICX,
+			amics->mic1_type == AMIC_TYPE_DIFFERENTIAL ?
+				0 : AB8500_ANAGAINX_ENSEMICX);
+	dev_dbg(codec->dev, "%s: Mic 2 mic-type: %s\n", __func__,
+		amic_type_str(amics->mic2_type));
+	snd_soc_update_bits(codec, AB8500_ANAGAIN2, AB8500_ANAGAINX_ENSEMICX,
+			amics->mic2_type == AMIC_TYPE_DIFFERENTIAL ?
+				0 : AB8500_ANAGAINX_ENSEMICX);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ab8500_audio_setup_mics);
+
+static int ab8500_audio_set_ear_cmv(struct snd_soc_codec *codec,
+				enum ear_cm_voltage ear_cmv)
+{
+	char *cmv_str;
+
+	switch (ear_cmv) {
+	case EAR_CMV_0_95V:
+		cmv_str = "0.95V";
+		break;
+	case EAR_CMV_1_10V:
+		cmv_str = "1.10V";
+		break;
+	case EAR_CMV_1_27V:
+		cmv_str = "1.27V";
+		break;
+	case EAR_CMV_1_58V:
+		cmv_str = "1.58V";
+		break;
+	default:
+		dev_err(codec->dev,
+			"%s: Unknown earpiece CM-voltage (%d)!\n",
+			__func__, (int)ear_cmv);
+		return -EINVAL;
+	}
+	dev_dbg(codec->dev, "%s: Earpiece CM-voltage: %s\n", __func__,
+		cmv_str);
+	snd_soc_update_bits(codec, AB8500_ANACONF1, AB8500_ANACONF1_EARSELCM,
+			ear_cmv);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ab8500_audio_set_ear_cmv);
+
+static int ab8500_audio_set_bit_delay(struct snd_soc_dai *dai,
+				unsigned int delay)
+{
+	unsigned int mask, val;
+	struct snd_soc_codec *codec = dai->codec;
+
+	mask = BIT(AB8500_DIGIFCONF2_IF0DEL);
+	val = 0;
+
+	switch (delay) {
+	case 0:
+		break;
+	case 1:
+		val |= BIT(AB8500_DIGIFCONF2_IF0DEL);
+		break;
+	default:
+		dev_err(dai->codec->dev,
+			"%s: ERROR: Unsupported bit-delay (0x%x)!\n",
+			__func__, delay);
+		return -EINVAL;
+	}
+
+	dev_dbg(dai->codec->dev, "%s: IF0 Bit-delay: %d bits.\n",
+		__func__, delay);
+	snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val);
+
+	return 0;
+}
+
+/* Gates clocking according format mask */
+static int ab8500_codec_set_dai_clock_gate(struct snd_soc_codec *codec,
+					unsigned int fmt)
+{
+	unsigned int mask;
+	unsigned int val;
+
+	mask = BIT(AB8500_DIGIFCONF1_ENMASTGEN) |
+			BIT(AB8500_DIGIFCONF1_ENFSBITCLK0);
+
+	val = BIT(AB8500_DIGIFCONF1_ENMASTGEN);
+
+	switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
+	case SND_SOC_DAIFMT_CONT: /* continuous clock */
+		dev_dbg(codec->dev, "%s: IF0 Clock is continuous.\n",
+			__func__);
+		val |= BIT(AB8500_DIGIFCONF1_ENFSBITCLK0);
+		break;
+	case SND_SOC_DAIFMT_GATED: /* clock is gated */
+		dev_dbg(codec->dev, "%s: IF0 Clock is gated.\n",
+			__func__);
+		break;
+	default:
+		dev_err(codec->dev,
+			"%s: ERROR: Unsupported clock mask (0x%x)!\n",
+			__func__, fmt & SND_SOC_DAIFMT_CLOCK_MASK);
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val);
+
+	return 0;
+}
+
+static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	unsigned int mask;
+	unsigned int val;
+	struct snd_soc_codec *codec = dai->codec;
+	int status;
+
+	dev_dbg(codec->dev, "%s: Enter (fmt = 0x%x)\n", __func__, fmt);
+
+	mask = BIT(AB8500_DIGIFCONF3_IF1DATOIF0AD) |
+			BIT(AB8500_DIGIFCONF3_IF1CLKTOIF0CLK) |
+			BIT(AB8500_DIGIFCONF3_IF0BFIFOEN) |
+			BIT(AB8500_DIGIFCONF3_IF0MASTER);
+	val = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & FRM master */
+		dev_dbg(dai->codec->dev,
+			"%s: IF0 Master-mode: AB8500 master.\n", __func__);
+		val |= BIT(AB8500_DIGIFCONF3_IF0MASTER);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & FRM slave */
+		dev_dbg(dai->codec->dev,
+			"%s: IF0 Master-mode: AB8500 slave.\n", __func__);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & FRM master */
+	case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
+		dev_err(dai->codec->dev,
+			"%s: ERROR: The device is either a master or a slave.\n",
+			__func__);
+	default:
+		dev_err(dai->codec->dev,
+			"%s: ERROR: Unsupporter master mask 0x%x\n",
+			__func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
+		return -EINVAL;
+		break;
+	}
+
+	snd_soc_update_bits(codec, AB8500_DIGIFCONF3, mask, val);
+
+	/* Set clock gating */
+	status = ab8500_codec_set_dai_clock_gate(codec, fmt);
+	if (status) {
+		dev_err(dai->codec->dev,
+			"%s: ERRROR: Failed to set clock gate (%d).\n",
+			__func__, status);
+		return status;
+	}
+
+	/* Setting data transfer format */
+
+	mask = BIT(AB8500_DIGIFCONF2_IF0FORMAT0) |
+		BIT(AB8500_DIGIFCONF2_IF0FORMAT1) |
+		BIT(AB8500_DIGIFCONF2_FSYNC0P) |
+		BIT(AB8500_DIGIFCONF2_BITCLK0P);
+	val = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S: /* I2S mode */
+		dev_dbg(dai->codec->dev, "%s: IF0 Protocol: I2S\n", __func__);
+		val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT1);
+		ab8500_audio_set_bit_delay(dai, 0);
+		break;
+
+	case SND_SOC_DAIFMT_DSP_A: /* L data MSB after FRM LRC */
+		dev_dbg(dai->codec->dev,
+			"%s: IF0 Protocol: DSP A (TDM)\n", __func__);
+		val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0);
+		ab8500_audio_set_bit_delay(dai, 1);
+		break;
+
+	case SND_SOC_DAIFMT_DSP_B: /* L data MSB during FRM LRC */
+		dev_dbg(dai->codec->dev,
+			"%s: IF0 Protocol: DSP B (TDM)\n", __func__);
+		val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0);
+		ab8500_audio_set_bit_delay(dai, 0);
+		break;
+
+	default:
+		dev_err(dai->codec->dev,
+			"%s: ERROR: Unsupported format (0x%x)!\n",
+			__func__, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
+		dev_dbg(dai->codec->dev,
+			"%s: IF0: Normal bit clock, normal frame\n",
+			__func__);
+		break;
+	case SND_SOC_DAIFMT_NB_IF: /* normal BCLK + inv FRM */
+		dev_dbg(dai->codec->dev,
+			"%s: IF0: Normal bit clock, inverted frame\n",
+			__func__);
+		val |= BIT(AB8500_DIGIFCONF2_FSYNC0P);
+		break;
+	case SND_SOC_DAIFMT_IB_NF: /* invert BCLK + nor FRM */
+		dev_dbg(dai->codec->dev,
+			"%s: IF0: Inverted bit clock, normal frame\n",
+			__func__);
+		val |= BIT(AB8500_DIGIFCONF2_BITCLK0P);
+		break;
+	case SND_SOC_DAIFMT_IB_IF: /* invert BCLK + FRM */
+		dev_dbg(dai->codec->dev,
+			"%s: IF0: Inverted bit clock, inverted frame\n",
+			__func__);
+		val |= BIT(AB8500_DIGIFCONF2_FSYNC0P);
+		val |= BIT(AB8500_DIGIFCONF2_BITCLK0P);
+		break;
+	default:
+		dev_err(dai->codec->dev,
+			"%s: ERROR: Unsupported INV mask 0x%x\n",
+			__func__, fmt & SND_SOC_DAIFMT_INV_MASK);
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val);
+
+	return 0;
+}
+
+static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
+		unsigned int tx_mask, unsigned int rx_mask,
+		int slots, int slot_width)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	unsigned int val, mask, slots_active;
+
+	mask = BIT(AB8500_DIGIFCONF2_IF0WL0) |
+		BIT(AB8500_DIGIFCONF2_IF0WL1);
+	val = 0;
+
+	switch (slot_width) {
+	case 16:
+		break;
+	case 20:
+		val |= BIT(AB8500_DIGIFCONF2_IF0WL0);
+		break;
+	case 24:
+		val |= BIT(AB8500_DIGIFCONF2_IF0WL1);
+		break;
+	case 32:
+		val |= BIT(AB8500_DIGIFCONF2_IF0WL1) |
+			BIT(AB8500_DIGIFCONF2_IF0WL0);
+		break;
+	default:
+		dev_err(dai->codec->dev, "%s: Unsupported slot-width 0x%x\n",
+			__func__, slot_width);
+		return -EINVAL;
+	}
+
+	dev_dbg(dai->codec->dev, "%s: IF0 slot-width: %d bits.\n",
+		__func__, slot_width);
+	snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val);
+
+	/* Setup TDM clocking according to slot count */
+	dev_dbg(dai->codec->dev, "%s: Slots, total: %d\n", __func__, slots);
+	mask = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) |
+			BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1);
+	switch (slots) {
+	case 2:
+		val = AB8500_MASK_NONE;
+		break;
+	case 4:
+		val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0);
+		break;
+	case 8:
+		val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1);
+		break;
+	case 16:
+		val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) |
+			BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1);
+		break;
+	default:
+		dev_err(dai->codec->dev,
+			"%s: ERROR: Unsupported number of slots (%d)!\n",
+			__func__, slots);
+		return -EINVAL;
+	}
+	snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val);
+
+	/* Setup TDM DA according to active tx slots */
+	mask = AB8500_DASLOTCONFX_SLTODAX_MASK;
+	slots_active = hweight32(tx_mask);
+	dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__,
+		slots_active);
+	switch (slots_active) {
+	case 0:
+		break;
+	case 1:
+		/* Slot 9 -> DA_IN1 & DA_IN3 */
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11);
+		break;
+	case 2:
+		/* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11);
+		snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11);
+
+		break;
+	case 8:
+		dev_dbg(dai->codec->dev,
+			"%s: In 8-channel mode DA-from-slot mapping is set manually.",
+			__func__);
+		break;
+	default:
+		dev_err(dai->codec->dev,
+			"%s: Unsupported number of active TX-slots (%d)!\n",
+			__func__, slots_active);
+		return -EINVAL;
+	}
+
+	/* Setup TDM AD according to active RX-slots */
+	slots_active = hweight32(rx_mask);
+	dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__,
+		slots_active);
+	switch (slots_active) {
+	case 0:
+		break;
+	case 1:
+		/* AD_OUT3 -> slot 0 & 1 */
+		snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL,
+				AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN |
+				AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD);
+		break;
+	case 2:
+		/* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */
+		snd_soc_update_bits(codec,
+				AB8500_ADSLOTSEL1,
+				AB8500_MASK_ALL,
+				AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN |
+				AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD);
+		break;
+	case 8:
+		dev_dbg(dai->codec->dev,
+			"%s: In 8-channel mode AD-to-slot mapping is set manually.",
+			__func__);
+		break;
+	default:
+		dev_err(dai->codec->dev,
+			"%s: Unsupported number of active RX-slots (%d)!\n",
+			__func__, slots_active);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+struct snd_soc_dai_driver ab8500_codec_dai[] = {
+	{
+		.name = "ab8500-codec-dai.0",
+		.id = 0,
+		.playback = {
+			.stream_name = "ab8500_0p",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = AB8500_SUPPORTED_RATE,
+			.formats = AB8500_SUPPORTED_FMT,
+		},
+		.ops = (struct snd_soc_dai_ops[]) {
+			{
+				.set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
+				.set_fmt = ab8500_codec_set_dai_fmt,
+			}
+		},
+		.symmetric_rates = 1
+	},
+	{
+		.name = "ab8500-codec-dai.1",
+		.id = 1,
+		.capture = {
+			.stream_name = "ab8500_0c",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = AB8500_SUPPORTED_RATE,
+			.formats = AB8500_SUPPORTED_FMT,
+		},
+		.ops = (struct snd_soc_dai_ops[]) {
+			{
+				.set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
+				.set_fmt = ab8500_codec_set_dai_fmt,
+			}
+		},
+		.symmetric_rates = 1
+	}
+};
+
+static int ab8500_codec_probe(struct snd_soc_codec *codec)
+{
+	struct device *dev = codec->dev;
+	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
+	struct ab8500_platform_data *pdata;
+	struct filter_control *fc;
+	int status;
+
+	dev_dbg(dev, "%s: Enter.\n", __func__);
+
+	/* Setup AB8500 according to board-settings */
+	pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent);
+	status = ab8500_audio_setup_mics(codec, &pdata->codec->amics);
+	if (status < 0) {
+		pr_err("%s: Failed to setup mics (%d)!\n", __func__, status);
+		return status;
+	}
+	status = ab8500_audio_set_ear_cmv(codec, pdata->codec->ear_cmv);
+	if (status < 0) {
+		pr_err("%s: Failed to set earpiece CM-voltage (%d)!\n",
+			__func__, status);
+		return status;
+	}
+
+	status = ab8500_audio_init_audioblock(codec);
+	if (status < 0) {
+		dev_err(dev, "%s: failed to init audio-block (%d)!\n",
+			__func__, status);
+		return status;
+	}
+
+	/* Override HW-defaults */
+	ab8500_codec_write_reg(codec,
+				AB8500_ANACONF5,
+				BIT(AB8500_ANACONF5_HSAUTOEN));
+	ab8500_codec_write_reg(codec,
+				AB8500_SHORTCIRCONF,
+				BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
+
+	/* Add filter controls */
+	status = snd_soc_add_codec_controls(codec, ab8500_filter_controls,
+				ARRAY_SIZE(ab8500_filter_controls));
+	if (status < 0) {
+		dev_err(dev,
+			"%s: failed to add ab8500 filter controls (%d).\n",
+			__func__, status);
+		return status;
+	}
+	fc = (struct filter_control *)
+		&ab8500_filter_controls[AB8500_FILTER_ANC_FIR].private_value;
+	drvdata->anc_fir_values = (long *)fc->value;
+	fc = (struct filter_control *)
+		&ab8500_filter_controls[AB8500_FILTER_ANC_IIR].private_value;
+	drvdata->anc_iir_values = (long *)fc->value;
+	fc = (struct filter_control *)
+		&ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value;
+	drvdata->sid_fir_values = (long *)fc->value;
+
+	(void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input");
+
+	mutex_init(&drvdata->anc_lock);
+
+	return status;
+}
+
+static struct snd_soc_codec_driver ab8500_codec_driver = {
+	.probe =		ab8500_codec_probe,
+	.read =			ab8500_codec_read_reg,
+	.write =		ab8500_codec_write_reg,
+	.reg_word_size =	sizeof(u8),
+	.controls =		ab8500_ctrls,
+	.num_controls =		ARRAY_SIZE(ab8500_ctrls),
+	.dapm_widgets =		ab8500_dapm_widgets,
+	.num_dapm_widgets =	ARRAY_SIZE(ab8500_dapm_widgets),
+	.dapm_routes =		ab8500_dapm_routes,
+	.num_dapm_routes =	ARRAY_SIZE(ab8500_dapm_routes),
+};
+
+static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
+{
+	int status;
+	struct ab8500_codec_drvdata *drvdata;
+
+	dev_dbg(&pdev->dev, "%s: Enter.\n", __func__);
+
+	/* Create driver private-data struct */
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_codec_drvdata),
+			GFP_KERNEL);
+	drvdata->sid_status = SID_UNCONFIGURED;
+	drvdata->anc_status = ANC_UNCONFIGURED;
+	dev_set_drvdata(&pdev->dev, drvdata);
+
+	dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__);
+	status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver,
+				ab8500_codec_dai,
+				ARRAY_SIZE(ab8500_codec_dai));
+	if (status < 0)
+		dev_err(&pdev->dev,
+			"%s: Error: Failed to register codec (%d).\n",
+			__func__, status);
+
+	return status;
+}
+
+static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev)
+{
+	dev_info(&pdev->dev, "%s Enter.\n", __func__);
+
+	snd_soc_unregister_codec(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver ab8500_codec_platform_driver = {
+	.driver	= {
+		.name	= "ab8500-codec",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ab8500_codec_driver_probe,
+	.remove		= __devexit_p(ab8500_codec_driver_remove),
+	.suspend	= NULL,
+	.resume		= NULL,
+};
+module_platform_driver(ab8500_codec_platform_driver);
+
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/ab8500-codec.h b/sound/soc/codecs/ab8500-codec.h
new file mode 100644
index 000000000000..114f69a0c629
--- /dev/null
+++ b/sound/soc/codecs/ab8500-codec.h
@@ -0,0 +1,590 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
+ *         Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>,
+ *         Roger Nilsson <roger.xr.nilsson@stericsson.com>,
+ *         for ST-Ericsson.
+ *
+ *         Based on the early work done by:
+ *         Mikko J. Lehto <mikko.lehto@symbio.com>,
+ *         Mikko Sarmanne <mikko.sarmanne@symbio.com>,
+ *         for ST-Ericsson.
+ *
+ * License terms:
+ *
+ * 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.
+ */
+
+#ifndef AB8500_CODEC_REGISTERS_H
+#define AB8500_CODEC_REGISTERS_H
+
+#define AB8500_SUPPORTED_RATE			(SNDRV_PCM_RATE_48000)
+#define AB8500_SUPPORTED_FMT			(SNDRV_PCM_FMTBIT_S16_LE)
+
+/* AB8500 audio bank (0x0d) register definitions */
+
+#define AB8500_POWERUP				0x00
+#define AB8500_AUDSWRESET			0x01
+#define AB8500_ADPATHENA			0x02
+#define AB8500_DAPATHENA			0x03
+#define AB8500_ANACONF1				0x04
+#define AB8500_ANACONF2				0x05
+#define AB8500_DIGMICCONF			0x06
+#define AB8500_ANACONF3				0x07
+#define AB8500_ANACONF4				0x08
+#define AB8500_DAPATHCONF			0x09
+#define AB8500_MUTECONF				0x0A
+#define AB8500_SHORTCIRCONF			0x0B
+#define AB8500_ANACONF5				0x0C
+#define AB8500_ENVCPCONF			0x0D
+#define AB8500_SIGENVCONF			0x0E
+#define AB8500_PWMGENCONF1			0x0F
+#define AB8500_PWMGENCONF2			0x10
+#define AB8500_PWMGENCONF3			0x11
+#define AB8500_PWMGENCONF4			0x12
+#define AB8500_PWMGENCONF5			0x13
+#define AB8500_ANAGAIN1				0x14
+#define AB8500_ANAGAIN2				0x15
+#define AB8500_ANAGAIN3				0x16
+#define AB8500_ANAGAIN4				0x17
+#define AB8500_DIGLINHSLGAIN			0x18
+#define AB8500_DIGLINHSRGAIN			0x19
+#define AB8500_ADFILTCONF			0x1A
+#define AB8500_DIGIFCONF1			0x1B
+#define AB8500_DIGIFCONF2			0x1C
+#define AB8500_DIGIFCONF3			0x1D
+#define AB8500_DIGIFCONF4			0x1E
+#define AB8500_ADSLOTSEL1			0x1F
+#define AB8500_ADSLOTSEL2			0x20
+#define AB8500_ADSLOTSEL3			0x21
+#define AB8500_ADSLOTSEL4			0x22
+#define AB8500_ADSLOTSEL5			0x23
+#define AB8500_ADSLOTSEL6			0x24
+#define AB8500_ADSLOTSEL7			0x25
+#define AB8500_ADSLOTSEL8			0x26
+#define AB8500_ADSLOTSEL9			0x27
+#define AB8500_ADSLOTSEL10			0x28
+#define AB8500_ADSLOTSEL11			0x29
+#define AB8500_ADSLOTSEL12			0x2A
+#define AB8500_ADSLOTSEL13			0x2B
+#define AB8500_ADSLOTSEL14			0x2C
+#define AB8500_ADSLOTSEL15			0x2D
+#define AB8500_ADSLOTSEL16			0x2E
+#define AB8500_ADSLOTHIZCTRL1			0x2F
+#define AB8500_ADSLOTHIZCTRL2			0x30
+#define AB8500_ADSLOTHIZCTRL3			0x31
+#define AB8500_ADSLOTHIZCTRL4			0x32
+#define AB8500_DASLOTCONF1			0x33
+#define AB8500_DASLOTCONF2			0x34
+#define AB8500_DASLOTCONF3			0x35
+#define AB8500_DASLOTCONF4			0x36
+#define AB8500_DASLOTCONF5			0x37
+#define AB8500_DASLOTCONF6			0x38
+#define AB8500_DASLOTCONF7			0x39
+#define AB8500_DASLOTCONF8			0x3A
+#define AB8500_CLASSDCONF1			0x3B
+#define AB8500_CLASSDCONF2			0x3C
+#define AB8500_CLASSDCONF3			0x3D
+#define AB8500_DMICFILTCONF			0x3E
+#define AB8500_DIGMULTCONF1			0x3F
+#define AB8500_DIGMULTCONF2			0x40
+#define AB8500_ADDIGGAIN1			0x41
+#define AB8500_ADDIGGAIN2			0x42
+#define AB8500_ADDIGGAIN3			0x43
+#define AB8500_ADDIGGAIN4			0x44
+#define AB8500_ADDIGGAIN5			0x45
+#define AB8500_ADDIGGAIN6			0x46
+#define AB8500_DADIGGAIN1			0x47
+#define AB8500_DADIGGAIN2			0x48
+#define AB8500_DADIGGAIN3			0x49
+#define AB8500_DADIGGAIN4			0x4A
+#define AB8500_DADIGGAIN5			0x4B
+#define AB8500_DADIGGAIN6			0x4C
+#define AB8500_ADDIGLOOPGAIN1			0x4D
+#define AB8500_ADDIGLOOPGAIN2			0x4E
+#define AB8500_HSLEARDIGGAIN			0x4F
+#define AB8500_HSRDIGGAIN			0x50
+#define AB8500_SIDFIRGAIN1			0x51
+#define AB8500_SIDFIRGAIN2			0x52
+#define AB8500_ANCCONF1				0x53
+#define AB8500_ANCCONF2				0x54
+#define AB8500_ANCCONF3				0x55
+#define AB8500_ANCCONF4				0x56
+#define AB8500_ANCCONF5				0x57
+#define AB8500_ANCCONF6				0x58
+#define AB8500_ANCCONF7				0x59
+#define AB8500_ANCCONF8				0x5A
+#define AB8500_ANCCONF9				0x5B
+#define AB8500_ANCCONF10			0x5C
+#define AB8500_ANCCONF11			0x5D
+#define AB8500_ANCCONF12			0x5E
+#define AB8500_ANCCONF13			0x5F
+#define AB8500_ANCCONF14			0x60
+#define AB8500_SIDFIRADR			0x61
+#define AB8500_SIDFIRCOEF1			0x62
+#define AB8500_SIDFIRCOEF2			0x63
+#define AB8500_SIDFIRCONF			0x64
+#define AB8500_AUDINTMASK1			0x65
+#define AB8500_AUDINTSOURCE1			0x66
+#define AB8500_AUDINTMASK2			0x67
+#define AB8500_AUDINTSOURCE2			0x68
+#define AB8500_FIFOCONF1			0x69
+#define AB8500_FIFOCONF2			0x6A
+#define AB8500_FIFOCONF3			0x6B
+#define AB8500_FIFOCONF4			0x6C
+#define AB8500_FIFOCONF5			0x6D
+#define AB8500_FIFOCONF6			0x6E
+#define AB8500_AUDREV				0x6F
+
+#define AB8500_FIRST_REG			AB8500_POWERUP
+#define AB8500_LAST_REG				AB8500_AUDREV
+#define AB8500_CACHEREGNUM			(AB8500_LAST_REG + 1)
+
+#define AB8500_MASK_ALL				0xFF
+#define AB8500_MASK_NONE			0x00
+
+/* AB8500_POWERUP */
+#define AB8500_POWERUP_POWERUP			7
+#define AB8500_POWERUP_ENANA			3
+
+/* AB8500_AUDSWRESET */
+#define AB8500_AUDSWRESET_SWRESET		7
+
+/* AB8500_ADPATHENA */
+#define AB8500_ADPATHENA_ENAD12			7
+#define AB8500_ADPATHENA_ENAD34			5
+#define AB8500_ADPATHENA_ENAD5768		3
+
+/* AB8500_DAPATHENA */
+#define AB8500_DAPATHENA_ENDA1			7
+#define AB8500_DAPATHENA_ENDA2			6
+#define AB8500_DAPATHENA_ENDA3			5
+#define AB8500_DAPATHENA_ENDA4			4
+#define AB8500_DAPATHENA_ENDA5			3
+#define AB8500_DAPATHENA_ENDA6			2
+
+/* AB8500_ANACONF1 */
+#define AB8500_ANACONF1_HSLOWPOW		7
+#define AB8500_ANACONF1_DACLOWPOW1		6
+#define AB8500_ANACONF1_DACLOWPOW0		5
+#define AB8500_ANACONF1_EARDACLOWPOW		4
+#define AB8500_ANACONF1_EARSELCM		2
+#define AB8500_ANACONF1_HSHPEN			1
+#define AB8500_ANACONF1_EARDRVLOWPOW		0
+
+/* AB8500_ANACONF2 */
+#define AB8500_ANACONF2_ENMIC1			7
+#define AB8500_ANACONF2_ENMIC2			6
+#define AB8500_ANACONF2_ENLINL			5
+#define AB8500_ANACONF2_ENLINR			4
+#define AB8500_ANACONF2_MUTMIC1			3
+#define AB8500_ANACONF2_MUTMIC2			2
+#define AB8500_ANACONF2_MUTLINL			1
+#define AB8500_ANACONF2_MUTLINR			0
+
+/* AB8500_DIGMICCONF */
+#define AB8500_DIGMICCONF_ENDMIC1		7
+#define AB8500_DIGMICCONF_ENDMIC2		6
+#define AB8500_DIGMICCONF_ENDMIC3		5
+#define AB8500_DIGMICCONF_ENDMIC4		4
+#define AB8500_DIGMICCONF_ENDMIC5		3
+#define AB8500_DIGMICCONF_ENDMIC6		2
+#define AB8500_DIGMICCONF_HSFADSPEED		0
+
+/* AB8500_ANACONF3 */
+#define AB8500_ANACONF3_MIC1SEL			7
+#define AB8500_ANACONF3_LINRSEL			6
+#define AB8500_ANACONF3_ENDRVHSL		5
+#define AB8500_ANACONF3_ENDRVHSR		4
+#define AB8500_ANACONF3_ENADCMIC		2
+#define AB8500_ANACONF3_ENADCLINL		1
+#define AB8500_ANACONF3_ENADCLINR		0
+
+/* AB8500_ANACONF4 */
+#define AB8500_ANACONF4_DISPDVSS		7
+#define AB8500_ANACONF4_ENEAR			6
+#define AB8500_ANACONF4_ENHSL			5
+#define AB8500_ANACONF4_ENHSR			4
+#define AB8500_ANACONF4_ENHFL			3
+#define AB8500_ANACONF4_ENHFR			2
+#define AB8500_ANACONF4_ENVIB1			1
+#define AB8500_ANACONF4_ENVIB2			0
+
+/* AB8500_DAPATHCONF */
+#define AB8500_DAPATHCONF_ENDACEAR		6
+#define AB8500_DAPATHCONF_ENDACHSL		5
+#define AB8500_DAPATHCONF_ENDACHSR		4
+#define AB8500_DAPATHCONF_ENDACHFL		3
+#define AB8500_DAPATHCONF_ENDACHFR		2
+#define AB8500_DAPATHCONF_ENDACVIB1		1
+#define AB8500_DAPATHCONF_ENDACVIB2		0
+
+/* AB8500_MUTECONF */
+#define AB8500_MUTECONF_MUTEAR			6
+#define AB8500_MUTECONF_MUTHSL			5
+#define AB8500_MUTECONF_MUTHSR			4
+#define AB8500_MUTECONF_MUTDACEAR		2
+#define AB8500_MUTECONF_MUTDACHSL		1
+#define AB8500_MUTECONF_MUTDACHSR		0
+
+/* AB8500_SHORTCIRCONF */
+#define AB8500_SHORTCIRCONF_ENSHORTPWD		7
+#define AB8500_SHORTCIRCONF_EARSHORTDIS		6
+#define AB8500_SHORTCIRCONF_HSSHORTDIS		5
+#define AB8500_SHORTCIRCONF_HSPULLDEN		4
+#define AB8500_SHORTCIRCONF_HSOSCEN		2
+#define AB8500_SHORTCIRCONF_HSFADDIS		1
+#define AB8500_SHORTCIRCONF_HSZCDDIS		0
+/* Zero cross should be disabled */
+
+/* AB8500_ANACONF5 */
+#define AB8500_ANACONF5_ENCPHS			7
+#define AB8500_ANACONF5_HSLDACTOLOL		5
+#define AB8500_ANACONF5_HSRDACTOLOR		4
+#define AB8500_ANACONF5_ENLOL			3
+#define AB8500_ANACONF5_ENLOR			2
+#define AB8500_ANACONF5_HSAUTOEN		0
+
+/* AB8500_ENVCPCONF */
+#define AB8500_ENVCPCONF_ENVDETHTHRE		4
+#define AB8500_ENVCPCONF_ENVDETLTHRE		0
+#define AB8500_ENVCPCONF_ENVDETHTHRE_MAX	0x0F
+#define AB8500_ENVCPCONF_ENVDETLTHRE_MAX	0x0F
+
+/* AB8500_SIGENVCONF */
+#define AB8500_SIGENVCONF_CPLVEN		5
+#define AB8500_SIGENVCONF_ENVDETCPEN		4
+#define AB8500_SIGENVCONF_ENVDETTIME		0
+#define AB8500_SIGENVCONF_ENVDETTIME_MAX	0x0F
+
+/* AB8500_PWMGENCONF1 */
+#define AB8500_PWMGENCONF1_PWMTOVIB1		7
+#define AB8500_PWMGENCONF1_PWMTOVIB2		6
+#define AB8500_PWMGENCONF1_PWM1CTRL		5
+#define AB8500_PWMGENCONF1_PWM2CTRL		4
+#define AB8500_PWMGENCONF1_PWM1NCTRL		3
+#define AB8500_PWMGENCONF1_PWM1PCTRL		2
+#define AB8500_PWMGENCONF1_PWM2NCTRL		1
+#define AB8500_PWMGENCONF1_PWM2PCTRL		0
+
+/* AB8500_PWMGENCONF2 */
+/* AB8500_PWMGENCONF3 */
+/* AB8500_PWMGENCONF4 */
+/* AB8500_PWMGENCONF5 */
+#define AB8500_PWMGENCONFX_PWMVIBXPOL		7
+#define AB8500_PWMGENCONFX_PWMVIBXDUTCYC	0
+#define AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX	0x64
+
+/* AB8500_ANAGAIN1 */
+/* AB8500_ANAGAIN2 */
+#define AB8500_ANAGAINX_ENSEMICX		7
+#define AB8500_ANAGAINX_LOWPOWMICX		6
+#define AB8500_ANAGAINX_MICXGAIN		0
+#define AB8500_ANAGAINX_MICXGAIN_MAX		0x1F
+
+/* AB8500_ANAGAIN3 */
+#define AB8500_ANAGAIN3_HSLGAIN			4
+#define AB8500_ANAGAIN3_HSRGAIN			0
+#define AB8500_ANAGAIN3_HSXGAIN_MAX		0x0F
+
+/* AB8500_ANAGAIN4 */
+#define AB8500_ANAGAIN4_LINLGAIN		4
+#define AB8500_ANAGAIN4_LINRGAIN		0
+#define AB8500_ANAGAIN4_LINXGAIN_MAX		0x0F
+
+/* AB8500_DIGLINHSLGAIN */
+/* AB8500_DIGLINHSRGAIN */
+#define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN	0
+#define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX	0x13
+
+/* AB8500_ADFILTCONF */
+#define AB8500_ADFILTCONF_AD1NH			7
+#define AB8500_ADFILTCONF_AD2NH			6
+#define AB8500_ADFILTCONF_AD3NH			5
+#define AB8500_ADFILTCONF_AD4NH			4
+#define AB8500_ADFILTCONF_AD1VOICE		3
+#define AB8500_ADFILTCONF_AD2VOICE		2
+#define AB8500_ADFILTCONF_AD3VOICE		1
+#define AB8500_ADFILTCONF_AD4VOICE		0
+
+/* AB8500_DIGIFCONF1 */
+#define AB8500_DIGIFCONF1_ENMASTGEN		7
+#define AB8500_DIGIFCONF1_IF1BITCLKOS1		6
+#define AB8500_DIGIFCONF1_IF1BITCLKOS0		5
+#define AB8500_DIGIFCONF1_ENFSBITCLK1		4
+#define AB8500_DIGIFCONF1_IF0BITCLKOS1		2
+#define AB8500_DIGIFCONF1_IF0BITCLKOS0		1
+#define AB8500_DIGIFCONF1_ENFSBITCLK0		0
+
+/* AB8500_DIGIFCONF2 */
+#define AB8500_DIGIFCONF2_FSYNC0P		6
+#define AB8500_DIGIFCONF2_BITCLK0P		5
+#define AB8500_DIGIFCONF2_IF0DEL		4
+#define AB8500_DIGIFCONF2_IF0FORMAT1		3
+#define AB8500_DIGIFCONF2_IF0FORMAT0		2
+#define AB8500_DIGIFCONF2_IF0WL1		1
+#define AB8500_DIGIFCONF2_IF0WL0		0
+
+/* AB8500_DIGIFCONF3 */
+#define AB8500_DIGIFCONF3_IF0DATOIF1AD		7
+#define AB8500_DIGIFCONF3_IF0CLKTOIF1CLK	6
+#define AB8500_DIGIFCONF3_IF1MASTER		5
+#define AB8500_DIGIFCONF3_IF1DATOIF0AD		3
+#define AB8500_DIGIFCONF3_IF1CLKTOIF0CLK	2
+#define AB8500_DIGIFCONF3_IF0MASTER		1
+#define AB8500_DIGIFCONF3_IF0BFIFOEN		0
+
+/* AB8500_DIGIFCONF4 */
+#define AB8500_DIGIFCONF4_FSYNC1P		6
+#define AB8500_DIGIFCONF4_BITCLK1P		5
+#define AB8500_DIGIFCONF4_IF1DEL		4
+#define AB8500_DIGIFCONF4_IF1FORMAT1		3
+#define AB8500_DIGIFCONF4_IF1FORMAT0		2
+#define AB8500_DIGIFCONF4_IF1WL1		1
+#define AB8500_DIGIFCONF4_IF1WL0		0
+
+/* AB8500_ADSLOTSELX */
+#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD	0x00
+#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD	0x01
+#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD	0x02
+#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD	0x03
+#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD	0x04
+#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD	0x05
+#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD	0x06
+#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD	0x07
+#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD	0x08
+#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD	0x0F
+#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN	0x00
+#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN	0x10
+#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN	0x20
+#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN	0x30
+#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN	0x40
+#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN	0x50
+#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN	0x60
+#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN	0x70
+#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN	0x80
+#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN	0xF0
+#define AB8500_ADSLOTSELX_EVEN_SHIFT		0
+#define AB8500_ADSLOTSELX_ODD_SHIFT		4
+
+/* AB8500_ADSLOTHIZCTRL1 */
+/* AB8500_ADSLOTHIZCTRL2 */
+/* AB8500_ADSLOTHIZCTRL3 */
+/* AB8500_ADSLOTHIZCTRL4 */
+/* AB8500_DASLOTCONF1 */
+#define AB8500_DASLOTCONF1_DA12VOICE		7
+#define AB8500_DASLOTCONF1_SWAPDA12_34		6
+#define AB8500_DASLOTCONF1_DAI7TOADO1		5
+
+/* AB8500_DASLOTCONF2 */
+#define AB8500_DASLOTCONF2_DAI8TOADO2		5
+
+/* AB8500_DASLOTCONF3 */
+#define AB8500_DASLOTCONF3_DA34VOICE		7
+#define AB8500_DASLOTCONF3_DAI7TOADO3		5
+
+/* AB8500_DASLOTCONF4 */
+#define AB8500_DASLOTCONF4_DAI8TOADO4		5
+
+/* AB8500_DASLOTCONF5 */
+#define AB8500_DASLOTCONF5_DA56VOICE		7
+#define AB8500_DASLOTCONF5_DAI7TOADO5		5
+
+/* AB8500_DASLOTCONF6 */
+#define AB8500_DASLOTCONF6_DAI8TOADO6		5
+
+/* AB8500_DASLOTCONF7 */
+#define AB8500_DASLOTCONF7_DAI8TOADO7		5
+
+/* AB8500_DASLOTCONF8 */
+#define AB8500_DASLOTCONF8_DAI7TOADO8		5
+
+#define AB8500_DASLOTCONFX_SLTODAX_SHIFT	0
+#define AB8500_DASLOTCONFX_SLTODAX_MASK		0x1F
+
+/* AB8500_CLASSDCONF1 */
+#define AB8500_CLASSDCONF1_PARLHF		7
+#define AB8500_CLASSDCONF1_PARLVIB		6
+#define AB8500_CLASSDCONF1_VIB1SWAPEN		3
+#define AB8500_CLASSDCONF1_VIB2SWAPEN		2
+#define AB8500_CLASSDCONF1_HFLSWAPEN		1
+#define AB8500_CLASSDCONF1_HFRSWAPEN		0
+
+/* AB8500_CLASSDCONF2 */
+#define AB8500_CLASSDCONF2_FIRBYP3		7
+#define AB8500_CLASSDCONF2_FIRBYP2		6
+#define AB8500_CLASSDCONF2_FIRBYP1		5
+#define AB8500_CLASSDCONF2_FIRBYP0		4
+#define AB8500_CLASSDCONF2_HIGHVOLEN3		3
+#define AB8500_CLASSDCONF2_HIGHVOLEN2		2
+#define AB8500_CLASSDCONF2_HIGHVOLEN1		1
+#define AB8500_CLASSDCONF2_HIGHVOLEN0		0
+
+/* AB8500_CLASSDCONF3 */
+#define AB8500_CLASSDCONF3_DITHHPGAIN		4
+#define AB8500_CLASSDCONF3_DITHHPGAIN_MAX	0x0A
+#define AB8500_CLASSDCONF3_DITHWGAIN		0
+#define AB8500_CLASSDCONF3_DITHWGAIN_MAX	0x0A
+
+/* AB8500_DMICFILTCONF */
+#define AB8500_DMICFILTCONF_ANCINSEL		7
+#define AB8500_DMICFILTCONF_DA3TOEAR		6
+#define AB8500_DMICFILTCONF_DMIC1SINC3		5
+#define AB8500_DMICFILTCONF_DMIC2SINC3		4
+#define AB8500_DMICFILTCONF_DMIC3SINC3		3
+#define AB8500_DMICFILTCONF_DMIC4SINC3		2
+#define AB8500_DMICFILTCONF_DMIC5SINC3		1
+#define AB8500_DMICFILTCONF_DMIC6SINC3		0
+
+/* AB8500_DIGMULTCONF1 */
+#define AB8500_DIGMULTCONF1_DATOHSLEN		7
+#define AB8500_DIGMULTCONF1_DATOHSREN		6
+#define AB8500_DIGMULTCONF1_AD1SEL		5
+#define AB8500_DIGMULTCONF1_AD2SEL		4
+#define AB8500_DIGMULTCONF1_AD3SEL		3
+#define AB8500_DIGMULTCONF1_AD5SEL		2
+#define AB8500_DIGMULTCONF1_AD6SEL		1
+#define AB8500_DIGMULTCONF1_ANCSEL		0
+
+/* AB8500_DIGMULTCONF2 */
+#define AB8500_DIGMULTCONF2_DATOHFREN		7
+#define AB8500_DIGMULTCONF2_DATOHFLEN		6
+#define AB8500_DIGMULTCONF2_HFRSEL		5
+#define AB8500_DIGMULTCONF2_HFLSEL		4
+#define AB8500_DIGMULTCONF2_FIRSID1SEL		2
+#define AB8500_DIGMULTCONF2_FIRSID2SEL		0
+
+/* AB8500_ADDIGGAIN1 */
+/* AB8500_ADDIGGAIN2 */
+/* AB8500_ADDIGGAIN3 */
+/* AB8500_ADDIGGAIN4 */
+/* AB8500_ADDIGGAIN5 */
+/* AB8500_ADDIGGAIN6 */
+#define AB8500_ADDIGGAINX_FADEDISADX		6
+#define AB8500_ADDIGGAINX_ADXGAIN_MAX		0x3F
+
+/* AB8500_DADIGGAIN1 */
+/* AB8500_DADIGGAIN2 */
+/* AB8500_DADIGGAIN3 */
+/* AB8500_DADIGGAIN4 */
+/* AB8500_DADIGGAIN5 */
+/* AB8500_DADIGGAIN6 */
+#define AB8500_DADIGGAINX_FADEDISDAX		6
+#define AB8500_DADIGGAINX_DAXGAIN_MAX		0x3F
+
+/* AB8500_ADDIGLOOPGAIN1 */
+/* AB8500_ADDIGLOOPGAIN2 */
+#define AB8500_ADDIGLOOPGAINX_FADEDISADXL	6
+#define AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX	0x3F
+
+/* AB8500_HSLEARDIGGAIN */
+#define AB8500_HSLEARDIGGAIN_HSSINC1		7
+#define AB8500_HSLEARDIGGAIN_FADEDISHSL		4
+#define AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX	0x09
+
+/* AB8500_HSRDIGGAIN */
+#define AB8500_HSRDIGGAIN_FADESPEED		6
+#define AB8500_HSRDIGGAIN_FADEDISHSR		4
+#define AB8500_HSRDIGGAIN_HSRDGAIN_MAX		0x09
+
+/* AB8500_SIDFIRGAIN1 */
+/* AB8500_SIDFIRGAIN2 */
+#define AB8500_SIDFIRGAINX_FIRSIDXGAIN_MAX	0x1F
+
+/* AB8500_ANCCONF1 */
+#define AB8500_ANCCONF1_ANCIIRUPDATE		3
+#define AB8500_ANCCONF1_ENANC			2
+#define AB8500_ANCCONF1_ANCIIRINIT		1
+#define AB8500_ANCCONF1_ANCFIRUPDATE		0
+
+/* AB8500_ANCCONF2 */
+#define AB8500_ANCCONF2_SHIFT			5
+#define AB8500_ANCCONF2_MIN			-0x10
+#define AB8500_ANCCONF2_MAX			0xF
+
+/* AB8500_ANCCONF3 */
+#define AB8500_ANCCONF3_SHIFT			5
+#define AB8500_ANCCONF3_MIN			-0x10
+#define AB8500_ANCCONF3_MAX			0xF
+
+/* AB8500_ANCCONF4 */
+#define AB8500_ANCCONF4_SHIFT			5
+#define AB8500_ANCCONF4_MIN			-0x10
+#define AB8500_ANCCONF4_MAX			0xF
+
+/* AB8500_ANC_FIR_COEFFS */
+#define AB8500_ANC_FIR_COEFF_MIN		-0x8000
+#define AB8500_ANC_FIR_COEFF_MAX		0x7FFF
+#define AB8500_ANC_FIR_COEFFS			15
+
+/* AB8500_ANC_IIR_COEFFS */
+#define AB8500_ANC_IIR_COEFF_MIN		-0x800000
+#define AB8500_ANC_IIR_COEFF_MAX		0x7FFFFF
+#define AB8500_ANC_IIR_COEFFS			24
+/* AB8500_ANC_WARP_DELAY */
+#define AB8500_ANC_WARP_DELAY_SHIFT		16
+#define AB8500_ANC_WARP_DELAY_MIN		0x0000
+#define AB8500_ANC_WARP_DELAY_MAX		0xFFFF
+
+/* AB8500_ANCCONF11 */
+/* AB8500_ANCCONF12 */
+/* AB8500_ANCCONF13 */
+/* AB8500_ANCCONF14 */
+
+/* AB8500_SIDFIRADR */
+#define AB8500_SIDFIRADR_FIRSIDSET		7
+#define AB8500_SIDFIRADR_ADDRESS_SHIFT		0
+#define AB8500_SIDFIRADR_ADDRESS_MAX		0x7F
+
+/* AB8500_SIDFIRCOEF1 */
+/* AB8500_SIDFIRCOEF2 */
+#define AB8500_SID_FIR_COEFF_MIN		0
+#define AB8500_SID_FIR_COEFF_MAX		0xFFFF
+#define AB8500_SID_FIR_COEFFS			128
+
+/* AB8500_SIDFIRCONF */
+#define AB8500_SIDFIRCONF_ENFIRSIDS		2
+#define AB8500_SIDFIRCONF_FIRSIDSTOIF1		1
+#define AB8500_SIDFIRCONF_FIRSIDBUSY		0
+
+/* AB8500_AUDINTMASK1 */
+/* AB8500_AUDINTSOURCE1 */
+/* AB8500_AUDINTMASK2 */
+/* AB8500_AUDINTSOURCE2 */
+
+/* AB8500_FIFOCONF1 */
+#define AB8500_FIFOCONF1_BFIFOMASK		0x80
+#define AB8500_FIFOCONF1_BFIFO19M2		0x40
+#define AB8500_FIFOCONF1_BFIFOINT_SHIFT		0
+#define AB8500_FIFOCONF1_BFIFOINT_MAX		0x3F
+
+/* AB8500_FIFOCONF2 */
+#define AB8500_FIFOCONF2_BFIFOTX_SHIFT		0
+#define AB8500_FIFOCONF2_BFIFOTX_MAX		0xFF
+
+/* AB8500_FIFOCONF3 */
+#define AB8500_FIFOCONF3_BFIFOEXSL_SHIFT	5
+#define AB8500_FIFOCONF3_BFIFOEXSL_MAX		0x5
+#define AB8500_FIFOCONF3_PREBITCLK0_SHIFT	2
+#define AB8500_FIFOCONF3_PREBITCLK0_MAX		0x7
+#define AB8500_FIFOCONF3_BFIFOMAST_SHIFT	1
+#define AB8500_FIFOCONF3_BFIFORUN_SHIFT		0
+
+/* AB8500_FIFOCONF4 */
+#define AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT	0
+#define AB8500_FIFOCONF4_BFIFOFRAMSW_MAX	0xFF
+
+/* AB8500_FIFOCONF5 */
+#define AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT	0
+#define AB8500_FIFOCONF5_BFIFOWAKEUP_MAX	0xFF
+
+/* AB8500_FIFOCONF6 */
+#define AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT	0
+#define AB8500_FIFOCONF6_BFIFOSAMPLE_MAX	0xFF
+
+/* AB8500_AUDREV */
+
+#endif
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 2023c749f232..ea06b834a7de 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -91,11 +91,6 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
 	return 0;
 }
 
-static int ac97_soc_remove(struct snd_soc_codec *codec)
-{
-	return 0;
-}
-
 #ifdef CONFIG_PM
 static int ac97_soc_suspend(struct snd_soc_codec *codec)
 {
@@ -119,7 +114,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
 	.write =	ac97_write,
 	.read =		ac97_read,
 	.probe = 	ac97_soc_probe,
-	.remove = 	ac97_soc_remove,
 	.suspend =	ac97_soc_suspend,
 	.resume =	ac97_soc_resume,
 };
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
new file mode 100644
index 000000000000..5c9cacaf2d52
--- /dev/null
+++ b/sound/soc/codecs/arizona.c
@@ -0,0 +1,937 @@
+/*
+ * arizona.c - Wolfson Arizona class device shared support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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.
+ */
+
+#include <linux/gcd.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/registers.h>
+
+#include "arizona.h"
+
+#define ARIZONA_AIF_BCLK_CTRL                   0x00
+#define ARIZONA_AIF_TX_PIN_CTRL                 0x01
+#define ARIZONA_AIF_RX_PIN_CTRL                 0x02
+#define ARIZONA_AIF_RATE_CTRL                   0x03
+#define ARIZONA_AIF_FORMAT                      0x04
+#define ARIZONA_AIF_TX_BCLK_RATE                0x05
+#define ARIZONA_AIF_RX_BCLK_RATE                0x06
+#define ARIZONA_AIF_FRAME_CTRL_1                0x07
+#define ARIZONA_AIF_FRAME_CTRL_2                0x08
+#define ARIZONA_AIF_FRAME_CTRL_3                0x09
+#define ARIZONA_AIF_FRAME_CTRL_4                0x0A
+#define ARIZONA_AIF_FRAME_CTRL_5                0x0B
+#define ARIZONA_AIF_FRAME_CTRL_6                0x0C
+#define ARIZONA_AIF_FRAME_CTRL_7                0x0D
+#define ARIZONA_AIF_FRAME_CTRL_8                0x0E
+#define ARIZONA_AIF_FRAME_CTRL_9                0x0F
+#define ARIZONA_AIF_FRAME_CTRL_10               0x10
+#define ARIZONA_AIF_FRAME_CTRL_11               0x11
+#define ARIZONA_AIF_FRAME_CTRL_12               0x12
+#define ARIZONA_AIF_FRAME_CTRL_13               0x13
+#define ARIZONA_AIF_FRAME_CTRL_14               0x14
+#define ARIZONA_AIF_FRAME_CTRL_15               0x15
+#define ARIZONA_AIF_FRAME_CTRL_16               0x16
+#define ARIZONA_AIF_FRAME_CTRL_17               0x17
+#define ARIZONA_AIF_FRAME_CTRL_18               0x18
+#define ARIZONA_AIF_TX_ENABLES                  0x19
+#define ARIZONA_AIF_RX_ENABLES                  0x1A
+#define ARIZONA_AIF_FORCE_WRITE                 0x1B
+
+#define arizona_fll_err(_fll, fmt, ...) \
+	dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
+#define arizona_fll_warn(_fll, fmt, ...) \
+	dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
+#define arizona_fll_dbg(_fll, fmt, ...) \
+	dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
+
+#define arizona_aif_err(_dai, fmt, ...) \
+	dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
+#define arizona_aif_warn(_dai, fmt, ...) \
+	dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
+#define arizona_aif_dbg(_dai, fmt, ...) \
+	dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
+
+const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
+	"None",
+	"Tone Generator 1",
+	"Tone Generator 2",
+	"Haptics",
+	"AEC",
+	"Mic Mute Mixer",
+	"Noise Generator",
+	"IN1L",
+	"IN1R",
+	"IN2L",
+	"IN2R",
+	"IN3L",
+	"IN3R",
+	"IN4L",
+	"IN4R",
+	"AIF1RX1",
+	"AIF1RX2",
+	"AIF1RX3",
+	"AIF1RX4",
+	"AIF1RX5",
+	"AIF1RX6",
+	"AIF1RX7",
+	"AIF1RX8",
+	"AIF2RX1",
+	"AIF2RX2",
+	"AIF3RX1",
+	"AIF3RX2",
+	"SLIMRX1",
+	"SLIMRX2",
+	"SLIMRX3",
+	"SLIMRX4",
+	"SLIMRX5",
+	"SLIMRX6",
+	"SLIMRX7",
+	"SLIMRX8",
+	"EQ1",
+	"EQ2",
+	"EQ3",
+	"EQ4",
+	"DRC1L",
+	"DRC1R",
+	"DRC2L",
+	"DRC2R",
+	"LHPF1",
+	"LHPF2",
+	"LHPF3",
+	"LHPF4",
+	"DSP1.1",
+	"DSP1.2",
+	"DSP1.3",
+	"DSP1.4",
+	"DSP1.5",
+	"DSP1.6",
+	"ASRC1L",
+	"ASRC1R",
+	"ASRC2L",
+	"ASRC2R",
+};
+EXPORT_SYMBOL_GPL(arizona_mixer_texts);
+
+int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
+	0x00,  /* None */
+	0x04,  /* Tone */
+	0x05,
+	0x06,  /* Haptics */
+	0x08,  /* AEC */
+	0x0c,  /* Noise mixer */
+	0x0d,  /* Comfort noise */
+	0x10,  /* IN1L */
+	0x11,
+	0x12,
+	0x13,
+	0x14,
+	0x15,
+	0x16,
+	0x17,
+	0x20,  /* AIF1RX1 */
+	0x21,
+	0x22,
+	0x23,
+	0x24,
+	0x25,
+	0x26,
+	0x27,
+	0x28,  /* AIF2RX1 */
+	0x29,
+	0x30,  /* AIF3RX1 */
+	0x31,
+	0x38,  /* SLIMRX1 */
+	0x39,
+	0x3a,
+	0x3b,
+	0x3c,
+	0x3d,
+	0x3e,
+	0x3f,
+	0x50,  /* EQ1 */
+	0x51,
+	0x52,
+	0x53,
+	0x58,  /* DRC1L */
+	0x59,
+	0x5a,
+	0x5b,
+	0x60,  /* LHPF1 */
+	0x61,
+	0x62,
+	0x63,
+	0x68,  /* DSP1.1 */
+	0x69,
+	0x6a,
+	0x6b,
+	0x6c,
+	0x6d,
+	0x90,  /* ASRC1L */
+	0x91,
+	0x92,
+	0x93,
+};
+EXPORT_SYMBOL_GPL(arizona_mixer_values);
+
+const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
+EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
+
+static const char *arizona_lhpf_mode_text[] = {
+	"Low-pass", "High-pass"
+};
+
+const struct soc_enum arizona_lhpf1_mode =
+	SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
+			arizona_lhpf_mode_text);
+EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
+
+const struct soc_enum arizona_lhpf2_mode =
+	SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
+			arizona_lhpf_mode_text);
+EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
+
+const struct soc_enum arizona_lhpf3_mode =
+	SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
+			arizona_lhpf_mode_text);
+EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
+
+const struct soc_enum arizona_lhpf4_mode =
+	SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
+			arizona_lhpf_mode_text);
+EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
+
+int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
+		  int event)
+{
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_in_ev);
+
+int arizona_out_ev(struct snd_soc_dapm_widget *w,
+		   struct snd_kcontrol *kcontrol,
+		   int event)
+{
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_out_ev);
+
+int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+		       int source, unsigned int freq, int dir)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	char *name;
+	unsigned int reg;
+	unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
+	unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
+	unsigned int *clk;
+
+	switch (clk_id) {
+	case ARIZONA_CLK_SYSCLK:
+		name = "SYSCLK";
+		reg = ARIZONA_SYSTEM_CLOCK_1;
+		clk = &priv->sysclk;
+		mask |= ARIZONA_SYSCLK_FRAC;
+		break;
+	case ARIZONA_CLK_ASYNCCLK:
+		name = "ASYNCCLK";
+		reg = ARIZONA_ASYNC_CLOCK_1;
+		clk = &priv->asyncclk;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (freq) {
+	case  5644800:
+	case  6144000:
+		break;
+	case 11289600:
+	case 12288000:
+		val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		break;
+	case 22579200:
+	case 24576000:
+		val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		break;
+	case 45158400:
+	case 49152000:
+		val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*clk = freq;
+
+	if (freq % 6144000)
+		val |= ARIZONA_SYSCLK_FRAC;
+
+	dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
+
+	return regmap_update_bits(arizona->regmap, reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(arizona_set_sysclk);
+
+static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	int lrclk, bclk, mode, base;
+
+	base = dai->driver->base;
+
+	lrclk = 0;
+	bclk = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+		mode = 0;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		mode = 1;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		mode = 2;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		mode = 3;
+		break;
+	default:
+		arizona_aif_err(dai, "Unsupported DAI format %d\n",
+				fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+		lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		bclk |= ARIZONA_AIF1_BCLK_MSTR;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		bclk |= ARIZONA_AIF1_BCLK_MSTR;
+		lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
+		break;
+	default:
+		arizona_aif_err(dai, "Unsupported master mode %d\n",
+				fmt & SND_SOC_DAIFMT_MASTER_MASK);
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		bclk |= ARIZONA_AIF1_BCLK_INV;
+		lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		bclk |= ARIZONA_AIF1_BCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
+			    ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
+			    bclk);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
+			    ARIZONA_AIF1TX_LRCLK_INV |
+			    ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
+			    ARIZONA_AIF1RX_LRCLK_INV |
+			    ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
+			    ARIZONA_AIF1_FMT_MASK, mode);
+
+	return 0;
+}
+
+static const int arizona_48k_bclk_rates[] = {
+	-1,
+	48000,
+	64000,
+	96000,
+	128000,
+	192000,
+	256000,
+	384000,
+	512000,
+	768000,
+	1024000,
+	1536000,
+	2048000,
+	3072000,
+	4096000,
+	6144000,
+	8192000,
+	12288000,
+	24576000,
+};
+
+static const unsigned int arizona_48k_rates[] = {
+	12000,
+	24000,
+	48000,
+	96000,
+	192000,
+	384000,
+	768000,
+	4000,
+	8000,
+	16000,
+	32000,
+	64000,
+	128000,
+	256000,
+	512000,
+};
+
+static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
+	.count	= ARRAY_SIZE(arizona_48k_rates),
+	.list	= arizona_48k_rates,
+};
+
+static const int arizona_44k1_bclk_rates[] = {
+	-1,
+	44100,
+	58800,
+	88200,
+	117600,
+	177640,
+	235200,
+	352800,
+	470400,
+	705600,
+	940800,
+	1411200,
+	1881600,
+	2882400,
+	3763200,
+	5644800,
+	7526400,
+	11289600,
+	22579200,
+};
+
+static const unsigned int arizona_44k1_rates[] = {
+	11025,
+	22050,
+	44100,
+	88200,
+	176400,
+	352800,
+	705600,
+};
+
+static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
+	.count	= ARRAY_SIZE(arizona_44k1_rates),
+	.list	= arizona_44k1_rates,
+};
+
+static int arizona_sr_vals[] = {
+	0,
+	12000,
+	24000,
+	48000,
+	96000,
+	192000,
+	384000,
+	768000,
+	0,
+	11025,
+	22050,
+	44100,
+	88200,
+	176400,
+	352800,
+	705600,
+	4000,
+	8000,
+	16000,
+	32000,
+	64000,
+	128000,
+	256000,
+	512000,
+};
+
+static int arizona_startup(struct snd_pcm_substream *substream,
+			   struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
+	const struct snd_pcm_hw_constraint_list *constraint;
+	unsigned int base_rate;
+
+	switch (dai_priv->clk) {
+	case ARIZONA_CLK_SYSCLK:
+		base_rate = priv->sysclk;
+		break;
+	case ARIZONA_CLK_ASYNCCLK:
+		base_rate = priv->asyncclk;
+		break;
+	default:
+		return 0;
+	}
+
+	if (base_rate % 8000)
+		constraint = &arizona_44k1_constraint;
+	else
+		constraint = &arizona_48k_constraint;
+
+	return snd_pcm_hw_constraint_list(substream->runtime, 0,
+					  SNDRV_PCM_HW_PARAM_RATE,
+					  constraint);
+}
+
+static int arizona_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params,
+			     struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
+	int base = dai->driver->base;
+	const int *rates;
+	int i;
+	int bclk, lrclk, wl, frame, sr_val;
+
+	if (params_rate(params) % 8000)
+		rates = &arizona_44k1_bclk_rates[0];
+	else
+		rates = &arizona_48k_bclk_rates[0];
+
+	for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
+		if (rates[i] >= snd_soc_params_to_bclk(params) &&
+		    rates[i] % params_rate(params) == 0) {
+			bclk = i;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
+		arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
+				params_rate(params));
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
+		if (arizona_sr_vals[i] == params_rate(params))
+			break;
+	if (i == ARRAY_SIZE(arizona_sr_vals)) {
+		arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
+				params_rate(params));
+		return -EINVAL;
+	}
+	sr_val = i;
+
+	lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
+
+	arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
+			rates[bclk], rates[bclk] / lrclk);
+
+	wl = snd_pcm_format_width(params_format(params));
+	frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
+
+	/*
+	 * We will need to be more flexible than this in future,
+	 * currently we use a single sample rate for SYSCLK.
+	 */
+	switch (dai_priv->clk) {
+	case ARIZONA_CLK_SYSCLK:
+		snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
+				    ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
+		snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
+				    ARIZONA_AIF1_RATE_MASK, 0);
+		break;
+	case ARIZONA_CLK_ASYNCCLK:
+		snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
+				    ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
+		snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
+				    ARIZONA_AIF1_RATE_MASK, 8);
+		break;
+	default:
+		arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
+			    ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
+			    ARIZONA_AIF1TX_BCPF_MASK, lrclk);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
+			    ARIZONA_AIF1RX_BCPF_MASK, lrclk);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
+			    ARIZONA_AIF1TX_WL_MASK |
+			    ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
+	snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
+			    ARIZONA_AIF1RX_WL_MASK |
+			    ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
+
+	return 0;
+}
+
+static const char *arizona_dai_clk_str(int clk_id)
+{
+	switch (clk_id) {
+	case ARIZONA_CLK_SYSCLK:
+		return "SYSCLK";
+	case ARIZONA_CLK_ASYNCCLK:
+		return "ASYNCCLK";
+	default:
+		return "Unknown clock";
+	}
+}
+
+static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
+				  int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
+	struct snd_soc_dapm_route routes[2];
+
+	switch (clk_id) {
+	case ARIZONA_CLK_SYSCLK:
+	case ARIZONA_CLK_ASYNCCLK:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (clk_id == dai_priv->clk)
+		return 0;
+
+	if (dai->active) {
+		dev_err(codec->dev, "Can't change clock on active DAI %d\n",
+			dai->id);
+		return -EBUSY;
+	}
+
+	memset(&routes, 0, sizeof(routes));
+	routes[0].sink = dai->driver->capture.stream_name;
+	routes[1].sink = dai->driver->playback.stream_name;
+
+	routes[0].source = arizona_dai_clk_str(dai_priv->clk);
+	routes[1].source = arizona_dai_clk_str(dai_priv->clk);
+	snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
+
+	routes[0].source = arizona_dai_clk_str(clk_id);
+	routes[1].source = arizona_dai_clk_str(clk_id);
+	snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
+
+	return snd_soc_dapm_sync(&codec->dapm);
+}
+
+const struct snd_soc_dai_ops arizona_dai_ops = {
+	.startup = arizona_startup,
+	.set_fmt = arizona_set_fmt,
+	.hw_params = arizona_hw_params,
+	.set_sysclk = arizona_dai_set_sysclk,
+};
+EXPORT_SYMBOL_GPL(arizona_dai_ops);
+
+int arizona_init_dai(struct arizona_priv *priv, int id)
+{
+	struct arizona_dai_priv *dai_priv = &priv->dai[id];
+
+	dai_priv->clk = ARIZONA_CLK_SYSCLK;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_init_dai);
+
+static irqreturn_t arizona_fll_lock(int irq, void *data)
+{
+	struct arizona_fll *fll = data;
+
+	arizona_fll_dbg(fll, "Locked\n");
+
+	complete(&fll->lock);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
+{
+	struct arizona_fll *fll = data;
+
+	arizona_fll_dbg(fll, "clock OK\n");
+
+	complete(&fll->ok);
+
+	return IRQ_HANDLED;
+}
+
+static struct {
+	unsigned int min;
+	unsigned int max;
+	u16 fratio;
+	int ratio;
+} fll_fratios[] = {
+	{       0,    64000, 4, 16 },
+	{   64000,   128000, 3,  8 },
+	{  128000,   256000, 2,  4 },
+	{  256000,  1000000, 1,  2 },
+	{ 1000000, 13500000, 0,  1 },
+};
+
+struct arizona_fll_cfg {
+	int n;
+	int theta;
+	int lambda;
+	int refdiv;
+	int outdiv;
+	int fratio;
+};
+
+static int arizona_calc_fll(struct arizona_fll *fll,
+			    struct arizona_fll_cfg *cfg,
+			    unsigned int Fref,
+			    unsigned int Fout)
+{
+	unsigned int target, div, gcd_fll;
+	int i, ratio;
+
+	arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
+
+	/* Fref must be <=13.5MHz */
+	div = 1;
+	cfg->refdiv = 0;
+	while ((Fref / div) > 13500000) {
+		div *= 2;
+		cfg->refdiv++;
+
+		if (div > 8) {
+			arizona_fll_err(fll,
+					"Can't scale %dMHz in to <=13.5MHz\n",
+					Fref);
+			return -EINVAL;
+		}
+	}
+
+	/* Apply the division for our remaining calculations */
+	Fref /= div;
+
+	/* Fvco should be over the targt; don't check the upper bound */
+	div = 1;
+	while (Fout * div < 90000000 * fll->vco_mult) {
+		div++;
+		if (div > 7) {
+			arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
+					Fout);
+			return -EINVAL;
+		}
+	}
+	target = Fout * div / fll->vco_mult;
+	cfg->outdiv = div;
+
+	arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
+
+	/* Find an appropraite FLL_FRATIO and factor it out of the target */
+	for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+		if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+			cfg->fratio = fll_fratios[i].fratio;
+			ratio = fll_fratios[i].ratio;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(fll_fratios)) {
+		arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
+				Fref);
+		return -EINVAL;
+	}
+
+	cfg->n = target / (ratio * Fref);
+
+	if (target % Fref) {
+		gcd_fll = gcd(target, ratio * Fref);
+		arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
+
+		cfg->theta = (target - (cfg->n * ratio * Fref))
+			/ gcd_fll;
+		cfg->lambda = (ratio * Fref) / gcd_fll;
+	} else {
+		cfg->theta = 0;
+		cfg->lambda = 0;
+	}
+
+	arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
+			cfg->n, cfg->theta, cfg->lambda);
+	arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
+			cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
+
+	return 0;
+
+}
+
+static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
+			      struct arizona_fll_cfg *cfg, int source)
+{
+	regmap_update_bits(arizona->regmap, base + 3,
+			   ARIZONA_FLL1_THETA_MASK, cfg->theta);
+	regmap_update_bits(arizona->regmap, base + 4,
+			   ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
+	regmap_update_bits(arizona->regmap, base + 5,
+			   ARIZONA_FLL1_FRATIO_MASK,
+			   cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
+	regmap_update_bits(arizona->regmap, base + 6,
+			   ARIZONA_FLL1_CLK_REF_DIV_MASK |
+			   ARIZONA_FLL1_CLK_REF_SRC_MASK,
+			   cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
+			   source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
+
+	regmap_update_bits(arizona->regmap, base + 2,
+			   ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
+			   ARIZONA_FLL1_CTRL_UPD | cfg->n);
+}
+
+int arizona_set_fll(struct arizona_fll *fll, int source,
+		    unsigned int Fref, unsigned int Fout)
+{
+	struct arizona *arizona = fll->arizona;
+	struct arizona_fll_cfg cfg, sync;
+	unsigned int reg, val;
+	int syncsrc;
+	bool ena;
+	int ret;
+
+	ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
+	if (ret != 0) {
+		arizona_fll_err(fll, "Failed to read current state: %d\n",
+				ret);
+		return ret;
+	}
+	ena = reg & ARIZONA_FLL1_ENA;
+
+	if (Fout) {
+		/* Do we have a 32kHz reference? */
+		regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
+		switch (val & ARIZONA_CLK_32K_SRC_MASK) {
+		case ARIZONA_CLK_SRC_MCLK1:
+		case ARIZONA_CLK_SRC_MCLK2:
+			syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
+			break;
+		default:
+			syncsrc = -1;
+		}
+
+		if (source == syncsrc)
+			syncsrc = -1;
+
+		if (syncsrc >= 0) {
+			ret = arizona_calc_fll(fll, &sync, Fref, Fout);
+			if (ret != 0)
+				return ret;
+
+			ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
+			if (ret != 0)
+				return ret;
+		} else {
+			ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
+			if (ret != 0)
+				return ret;
+		}
+	} else {
+		regmap_update_bits(arizona->regmap, fll->base + 1,
+				   ARIZONA_FLL1_ENA, 0);
+		regmap_update_bits(arizona->regmap, fll->base + 0x11,
+				   ARIZONA_FLL1_SYNC_ENA, 0);
+
+		if (ena)
+			pm_runtime_put_autosuspend(arizona->dev);
+
+		return 0;
+	}
+
+	regmap_update_bits(arizona->regmap, fll->base + 5,
+			   ARIZONA_FLL1_OUTDIV_MASK,
+			   cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
+
+	if (syncsrc >= 0) {
+		arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
+		arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
+	} else {
+		arizona_apply_fll(arizona, fll->base, &cfg, source);
+	}
+
+	if (!ena)
+		pm_runtime_get(arizona->dev);
+
+	/* Clear any pending completions */
+	try_wait_for_completion(&fll->ok);
+
+	regmap_update_bits(arizona->regmap, fll->base + 1,
+			   ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
+	if (syncsrc >= 0)
+		regmap_update_bits(arizona->regmap, fll->base + 0x11,
+				   ARIZONA_FLL1_SYNC_ENA,
+				   ARIZONA_FLL1_SYNC_ENA);
+
+	ret = wait_for_completion_timeout(&fll->ok,
+					  msecs_to_jiffies(25));
+	if (ret == 0)
+		arizona_fll_warn(fll, "Timed out waiting for lock\n");
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_set_fll);
+
+int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
+		     int ok_irq, struct arizona_fll *fll)
+{
+	int ret;
+
+	init_completion(&fll->lock);
+	init_completion(&fll->ok);
+
+	fll->id = id;
+	fll->base = base;
+	fll->arizona = arizona;
+
+	snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
+	snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
+		 "FLL%d clock OK", id);
+
+	ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
+				  arizona_fll_lock, fll);
+	if (ret != 0) {
+		dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
+			id, ret);
+	}
+
+	ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
+				  arizona_fll_clock_ok, fll);
+	if (ret != 0) {
+		dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
+			id, ret);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_init_fll);
+
+MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
new file mode 100644
index 000000000000..59caca8865e8
--- /dev/null
+++ b/sound/soc/codecs/arizona.h
@@ -0,0 +1,159 @@
+/*
+ * arizona.h - Wolfson Arizona class device shared support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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.
+ */
+
+#ifndef _ASOC_ARIZONA_H
+#define _ASOC_ARIZONA_H
+
+#include <linux/completion.h>
+
+#include <sound/soc.h>
+
+#define ARIZONA_CLK_SYSCLK   1
+#define ARIZONA_CLK_ASYNCCLK 2
+
+#define ARIZONA_CLK_SRC_MCLK1    0x0
+#define ARIZONA_CLK_SRC_MCLK2    0x1
+#define ARIZONA_CLK_SRC_FLL1     0x4
+#define ARIZONA_CLK_SRC_FLL2     0x5
+#define ARIZONA_CLK_SRC_AIF1BCLK 0x8
+#define ARIZONA_CLK_SRC_AIF2BCLK 0x9
+#define ARIZONA_CLK_SRC_AIF3BCLK 0xa
+
+#define ARIZONA_FLL_SRC_MCLK1      0
+#define ARIZONA_FLL_SRC_MCLK2      1
+#define ARIZONA_FLL_SRC_SLIMCLK    2
+#define ARIZONA_FLL_SRC_FLL1       3
+#define ARIZONA_FLL_SRC_FLL2       4
+#define ARIZONA_FLL_SRC_AIF1BCLK   5
+#define ARIZONA_FLL_SRC_AIF2BCLK   6
+#define ARIZONA_FLL_SRC_AIF3BCLK   7
+#define ARIZONA_FLL_SRC_AIF1LRCLK  8
+#define ARIZONA_FLL_SRC_AIF2LRCLK  9
+#define ARIZONA_FLL_SRC_AIF3LRCLK 10
+
+#define ARIZONA_MIXER_VOL_MASK             0x00FE
+#define ARIZONA_MIXER_VOL_SHIFT                 1
+#define ARIZONA_MIXER_VOL_WIDTH                 7
+
+#define ARIZONA_MAX_DAI 3
+
+struct arizona;
+
+struct arizona_dai_priv {
+	int clk;
+};
+
+struct arizona_priv {
+	struct arizona *arizona;
+	int sysclk;
+	int asyncclk;
+	struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
+};
+
+#define ARIZONA_NUM_MIXER_INPUTS 57
+
+extern const unsigned int arizona_mixer_tlv[];
+extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS];
+extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
+
+#define ARIZONA_MIXER_CONTROLS(name, base) \
+	SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base + 1,		\
+			     ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0,	\
+			     arizona_mixer_tlv),			\
+	SOC_SINGLE_RANGE_TLV(name " Input 2 Volume", base + 3,		\
+			     ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0,	\
+			     arizona_mixer_tlv),			\
+	SOC_SINGLE_RANGE_TLV(name " Input 3 Volume", base + 5,		\
+			     ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0,	\
+			     arizona_mixer_tlv),			\
+	SOC_SINGLE_RANGE_TLV(name " Input 4 Volume", base + 7,		\
+			     ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0,	\
+			     arizona_mixer_tlv)
+
+#define ARIZONA_MUX_ENUM_DECL(name, reg) \
+	SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff,			\
+				   arizona_mixer_texts, arizona_mixer_values)
+
+#define ARIZONA_MUX_CTL_DECL(name) \
+	const struct snd_kcontrol_new name##_mux =	\
+		SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define ARIZONA_MIXER_ENUMS(name, base_reg) \
+	static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg);      \
+	static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
+	static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
+	static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
+	static ARIZONA_MUX_CTL_DECL(name##_in1); \
+	static ARIZONA_MUX_CTL_DECL(name##_in2); \
+	static ARIZONA_MUX_CTL_DECL(name##_in3); \
+	static ARIZONA_MUX_CTL_DECL(name##_in4)
+
+#define ARIZONA_MUX(name, ctrl) \
+	SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define ARIZONA_MIXER_WIDGETS(name, name_str)	\
+	ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \
+	ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \
+	ARIZONA_MUX(name_str " Input 3", &name##_in3_mux), \
+	ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
+	SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define ARIZONA_MIXER_ROUTES(widget, name) \
+	{ widget, NULL, name " Mixer" },         \
+	{ name " Mixer", NULL, name " Input 1" }, \
+	{ name " Mixer", NULL, name " Input 2" }, \
+	{ name " Mixer", NULL, name " Input 3" }, \
+	{ name " Mixer", NULL, name " Input 4" }, \
+	ARIZONA_MIXER_INPUT_ROUTES(name " Input 1"), \
+	ARIZONA_MIXER_INPUT_ROUTES(name " Input 2"), \
+	ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
+	ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
+
+extern const struct soc_enum arizona_lhpf1_mode;
+extern const struct soc_enum arizona_lhpf2_mode;
+extern const struct soc_enum arizona_lhpf3_mode;
+extern const struct soc_enum arizona_lhpf4_mode;
+
+extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol,
+			 int event);
+extern int arizona_out_ev(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol,
+			  int event);
+
+extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+			      int source, unsigned int freq, int dir);
+
+extern const struct snd_soc_dai_ops arizona_dai_ops;
+
+#define ARIZONA_FLL_NAME_LEN 20
+
+struct arizona_fll {
+	struct arizona *arizona;
+	int id;
+	unsigned int base;
+	unsigned int vco_mult;
+	struct completion lock;
+	struct completion ok;
+
+	char lock_name[ARIZONA_FLL_NAME_LEN];
+	char clock_ok_name[ARIZONA_FLL_NAME_LEN];
+};
+
+extern int arizona_init_fll(struct arizona *arizona, int id, int base,
+			    int lock_irq, int ok_irq, struct arizona_fll *fll);
+extern int arizona_set_fll(struct arizona_fll *fll, int source,
+			   unsigned int Fref, unsigned int Fout);
+
+extern int arizona_init_dai(struct arizona_priv *priv, int dai);
+
+#endif
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index a7109413aef1..628daf6a1d97 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -14,7 +14,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -1217,11 +1216,11 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
 		return -ENOMEM;
 	cs42l52->dev = &i2c_client->dev;
 
-	cs42l52->regmap = regmap_init_i2c(i2c_client, &cs42l52_regmap);
+	cs42l52->regmap = devm_regmap_init_i2c(i2c_client, &cs42l52_regmap);
 	if (IS_ERR(cs42l52->regmap)) {
 		ret = PTR_ERR(cs42l52->regmap);
 		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
-		goto err;
+		return ret;
 	}
 
 	i2c_set_clientdata(i2c_client, cs42l52);
@@ -1243,7 +1242,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
 		dev_err(&i2c_client->dev,
 			"CS42L52 Device ID (%X). Expected %X\n",
 			devid, CS42L52_CHIP_ID);
-		goto err_regmap;
+		return ret;
 	}
 
 	regcache_cache_only(cs42l52->regmap, true);
@@ -1251,23 +1250,13 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
 	ret =  snd_soc_register_codec(&i2c_client->dev,
 			&soc_codec_dev_cs42l52, &cs42l52_dai, 1);
 	if (ret < 0)
-		goto err_regmap;
+		return ret;
 	return 0;
-
-err_regmap:
-	regmap_exit(cs42l52->regmap);
-
-err:
-	return ret;
 }
 
 static int cs42l52_i2c_remove(struct i2c_client *client)
 {
-	struct cs42l52_private *cs42l52 = i2c_get_clientdata(client);
-
 	snd_soc_unregister_codec(&client->dev);
-	regmap_exit(cs42l52->regmap);
-
 	return 0;
 }
 
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index e0d45fdaa750..2c08c4cb465a 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1362,11 +1362,11 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
 
 	i2c_set_clientdata(i2c_client, cs42l73);
 
-	cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap);
+	cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
 	if (IS_ERR(cs42l73->regmap)) {
 		ret = PTR_ERR(cs42l73->regmap);
 		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
-		goto err;
+		return ret;
 	}
 	/* initialize codec */
 	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
@@ -1384,13 +1384,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
 		dev_err(&i2c_client->dev,
 			"CS42L73 Device ID (%X). Expected %X\n",
 			devid, CS42L73_DEVID);
-		goto err_regmap;
+		return ret;
 	}
 
 	ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
 	if (ret < 0) {
 		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
-		goto err_regmap;
+		return ret;;
 	}
 
 	dev_info(&i2c_client->dev,
@@ -1402,23 +1402,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
 			&soc_codec_dev_cs42l73, cs42l73_dai,
 			ARRAY_SIZE(cs42l73_dai));
 	if (ret < 0)
-		goto err_regmap;
+		return ret;
 	return 0;
-
-err_regmap:
-	regmap_exit(cs42l73->regmap);
-
-err:
-	return ret;
 }
 
 static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
 {
-	struct cs42l73_private *cs42l73 = i2c_get_clientdata(client);
-
 	snd_soc_unregister_codec(&client->dev);
-	regmap_exit(cs42l73->regmap);
-
 	return 0;
 }
 
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
new file mode 100644
index 000000000000..01be2a320e21
--- /dev/null
+++ b/sound/soc/codecs/da732x.c
@@ -0,0 +1,1627 @@
+/*
+ * da732x.c --- Dialog DA732X ALSA SoC Audio Driver
+ *
+ * Copyright (C) 2012 Dialog Semiconductor GmbH
+ *
+ * Author: Michal Hajduk <Michal.Hajduk@diasemi.com>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <asm/div64.h>
+
+#include "da732x.h"
+#include "da732x_reg.h"
+
+
+struct da732x_priv {
+	struct regmap *regmap;
+	struct snd_soc_codec *codec;
+
+	unsigned int sysclk;
+	bool pll_en;
+};
+
+/*
+ * da732x register cache - default settings
+ */
+static struct reg_default da732x_reg_cache[] = {
+	{ DA732X_REG_REF1		, 0x02 },
+	{ DA732X_REG_BIAS_EN		, 0x80 },
+	{ DA732X_REG_BIAS1		, 0x00 },
+	{ DA732X_REG_BIAS2		, 0x00 },
+	{ DA732X_REG_BIAS3		, 0x00 },
+	{ DA732X_REG_BIAS4		, 0x00 },
+	{ DA732X_REG_MICBIAS2		, 0x00 },
+	{ DA732X_REG_MICBIAS1		, 0x00 },
+	{ DA732X_REG_MICDET		, 0x00 },
+	{ DA732X_REG_MIC1_PRE		, 0x01 },
+	{ DA732X_REG_MIC1		, 0x40 },
+	{ DA732X_REG_MIC2_PRE		, 0x01 },
+	{ DA732X_REG_MIC2		, 0x40 },
+	{ DA732X_REG_AUX1L		, 0x75 },
+	{ DA732X_REG_AUX1R		, 0x75 },
+	{ DA732X_REG_MIC3_PRE		, 0x01 },
+	{ DA732X_REG_MIC3		, 0x40 },
+	{ DA732X_REG_INP_PINBIAS	, 0x00 },
+	{ DA732X_REG_INP_ZC_EN		, 0x00 },
+	{ DA732X_REG_INP_MUX		, 0x50 },
+	{ DA732X_REG_HP_DET		, 0x00 },
+	{ DA732X_REG_HPL_DAC_OFFSET	, 0x00 },
+	{ DA732X_REG_HPL_DAC_OFF_CNTL	, 0x00 },
+	{ DA732X_REG_HPL_OUT_OFFSET	, 0x00 },
+	{ DA732X_REG_HPL		, 0x40 },
+	{ DA732X_REG_HPL_VOL		, 0x0F },
+	{ DA732X_REG_HPR_DAC_OFFSET	, 0x00 },
+	{ DA732X_REG_HPR_DAC_OFF_CNTL	, 0x00 },
+	{ DA732X_REG_HPR_OUT_OFFSET	, 0x00 },
+	{ DA732X_REG_HPR		, 0x40 },
+	{ DA732X_REG_HPR_VOL		, 0x0F },
+	{ DA732X_REG_LIN2		, 0x4F },
+	{ DA732X_REG_LIN3		, 0x4F },
+	{ DA732X_REG_LIN4		, 0x4F },
+	{ DA732X_REG_OUT_ZC_EN		, 0x00 },
+	{ DA732X_REG_HP_LIN1_GNDSEL	, 0x00 },
+	{ DA732X_REG_CP_HP1		, 0x0C },
+	{ DA732X_REG_CP_HP2		, 0x03 },
+	{ DA732X_REG_CP_CTRL1		, 0x00 },
+	{ DA732X_REG_CP_CTRL2		, 0x99 },
+	{ DA732X_REG_CP_CTRL3		, 0x25 },
+	{ DA732X_REG_CP_LEVEL_MASK	, 0x3F },
+	{ DA732X_REG_CP_DET		, 0x00 },
+	{ DA732X_REG_CP_STATUS		, 0x00 },
+	{ DA732X_REG_CP_THRESH1		, 0x00 },
+	{ DA732X_REG_CP_THRESH2		, 0x00 },
+	{ DA732X_REG_CP_THRESH3		, 0x00 },
+	{ DA732X_REG_CP_THRESH4		, 0x00 },
+	{ DA732X_REG_CP_THRESH5		, 0x00 },
+	{ DA732X_REG_CP_THRESH6		, 0x00 },
+	{ DA732X_REG_CP_THRESH7		, 0x00 },
+	{ DA732X_REG_CP_THRESH8		, 0x00 },
+	{ DA732X_REG_PLL_DIV_LO		, 0x00 },
+	{ DA732X_REG_PLL_DIV_MID	, 0x00 },
+	{ DA732X_REG_PLL_DIV_HI		, 0x00 },
+	{ DA732X_REG_PLL_CTRL		, 0x02 },
+	{ DA732X_REG_CLK_CTRL		, 0xaa },
+	{ DA732X_REG_CLK_DSP		, 0x07 },
+	{ DA732X_REG_CLK_EN1		, 0x00 },
+	{ DA732X_REG_CLK_EN2		, 0x00 },
+	{ DA732X_REG_CLK_EN3		, 0x00 },
+	{ DA732X_REG_CLK_EN4		, 0x00 },
+	{ DA732X_REG_CLK_EN5		, 0x00 },
+	{ DA732X_REG_AIF_MCLK		, 0x00 },
+	{ DA732X_REG_AIFA1		, 0x02 },
+	{ DA732X_REG_AIFA2		, 0x00 },
+	{ DA732X_REG_AIFA3		, 0x08 },
+	{ DA732X_REG_AIFB1		, 0x02 },
+	{ DA732X_REG_AIFB2		, 0x00 },
+	{ DA732X_REG_AIFB3		, 0x08 },
+	{ DA732X_REG_PC_CTRL		, 0xC0 },
+	{ DA732X_REG_DATA_ROUTE		, 0x00 },
+	{ DA732X_REG_DSP_CTRL		, 0x00 },
+	{ DA732X_REG_CIF_CTRL2		, 0x00 },
+	{ DA732X_REG_HANDSHAKE		, 0x00 },
+	{ DA732X_REG_SPARE1_OUT		, 0x00 },
+	{ DA732X_REG_SPARE2_OUT		, 0x00 },
+	{ DA732X_REG_SPARE1_IN		, 0x00 },
+	{ DA732X_REG_ADC1_PD		, 0x00 },
+	{ DA732X_REG_ADC1_HPF		, 0x00 },
+	{ DA732X_REG_ADC1_SEL		, 0x00 },
+	{ DA732X_REG_ADC1_EQ12		, 0x00 },
+	{ DA732X_REG_ADC1_EQ34		, 0x00 },
+	{ DA732X_REG_ADC1_EQ5		, 0x00 },
+	{ DA732X_REG_ADC2_PD		, 0x00 },
+	{ DA732X_REG_ADC2_HPF		, 0x00 },
+	{ DA732X_REG_ADC2_SEL		, 0x00 },
+	{ DA732X_REG_ADC2_EQ12		, 0x00 },
+	{ DA732X_REG_ADC2_EQ34		, 0x00 },
+	{ DA732X_REG_ADC2_EQ5		, 0x00 },
+	{ DA732X_REG_DAC1_HPF		, 0x00 },
+	{ DA732X_REG_DAC1_L_VOL		, 0x00 },
+	{ DA732X_REG_DAC1_R_VOL		, 0x00 },
+	{ DA732X_REG_DAC1_SEL		, 0x00 },
+	{ DA732X_REG_DAC1_SOFTMUTE	, 0x00 },
+	{ DA732X_REG_DAC1_EQ12		, 0x00 },
+	{ DA732X_REG_DAC1_EQ34		, 0x00 },
+	{ DA732X_REG_DAC1_EQ5		, 0x00 },
+	{ DA732X_REG_DAC2_HPF		, 0x00 },
+	{ DA732X_REG_DAC2_L_VOL		, 0x00 },
+	{ DA732X_REG_DAC2_R_VOL		, 0x00 },
+	{ DA732X_REG_DAC2_SEL		, 0x00 },
+	{ DA732X_REG_DAC2_SOFTMUTE	, 0x00 },
+	{ DA732X_REG_DAC2_EQ12		, 0x00 },
+	{ DA732X_REG_DAC2_EQ34		, 0x00 },
+	{ DA732X_REG_DAC2_EQ5		, 0x00 },
+	{ DA732X_REG_DAC3_HPF		, 0x00 },
+	{ DA732X_REG_DAC3_VOL		, 0x00 },
+	{ DA732X_REG_DAC3_SEL		, 0x00 },
+	{ DA732X_REG_DAC3_SOFTMUTE	, 0x00 },
+	{ DA732X_REG_DAC3_EQ12		, 0x00 },
+	{ DA732X_REG_DAC3_EQ34		, 0x00 },
+	{ DA732X_REG_DAC3_EQ5		, 0x00 },
+	{ DA732X_REG_BIQ_BYP		, 0x00 },
+	{ DA732X_REG_DMA_CMD		, 0x00 },
+	{ DA732X_REG_DMA_ADDR0		, 0x00 },
+	{ DA732X_REG_DMA_ADDR1		, 0x00 },
+	{ DA732X_REG_DMA_DATA0		, 0x00 },
+	{ DA732X_REG_DMA_DATA1		, 0x00 },
+	{ DA732X_REG_DMA_DATA2		, 0x00 },
+	{ DA732X_REG_DMA_DATA3		, 0x00 },
+	{ DA732X_REG_UNLOCK		, 0x00 },
+};
+
+static inline int da732x_get_input_div(struct snd_soc_codec *codec, int sysclk)
+{
+	int val;
+	int ret;
+
+	if (sysclk < DA732X_MCLK_10MHZ) {
+		val = DA732X_MCLK_RET_0_10MHZ;
+		ret = DA732X_MCLK_VAL_0_10MHZ;
+	} else if ((sysclk >= DA732X_MCLK_10MHZ) &&
+	    (sysclk < DA732X_MCLK_20MHZ)) {
+		val = DA732X_MCLK_RET_10_20MHZ;
+		ret = DA732X_MCLK_VAL_10_20MHZ;
+	} else if ((sysclk >= DA732X_MCLK_20MHZ) &&
+	    (sysclk < DA732X_MCLK_40MHZ)) {
+		val = DA732X_MCLK_RET_20_40MHZ;
+		ret = DA732X_MCLK_VAL_20_40MHZ;
+	} else if ((sysclk >= DA732X_MCLK_40MHZ) &&
+	    (sysclk <= DA732X_MCLK_54MHZ)) {
+		val = DA732X_MCLK_RET_40_54MHZ;
+		ret = DA732X_MCLK_VAL_40_54MHZ;
+	} else {
+		return -EINVAL;
+	}
+
+	snd_soc_write(codec, DA732X_REG_PLL_CTRL, val);
+
+	return ret;
+}
+
+static void da732x_set_charge_pump(struct snd_soc_codec *codec, int state)
+{
+	switch (state) {
+	case DA732X_ENABLE_CP:
+		snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_EN);
+		snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_EN |
+			      DA732X_HP_CP_REG | DA732X_HP_CP_PULSESKIP);
+		snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA732X_CP_EN |
+			      DA732X_CP_CTRL_CPVDD1);
+		snd_soc_write(codec, DA732X_REG_CP_CTRL2,
+			      DA732X_CP_MANAGE_MAGNITUDE | DA732X_CP_BOOST);
+		snd_soc_write(codec, DA732X_REG_CP_CTRL3, DA732X_CP_1MHZ);
+		break;
+	case DA732X_DISABLE_CP:
+		snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_DIS);
+		snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_DIS);
+		snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA723X_CP_DIS);
+		break;
+	default:
+		pr_err(KERN_ERR "Wrong charge pump state\n");
+		break;
+	}
+}
+
+static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, DA732X_MIC_PRE_VOL_DB_MIN,
+				  DA732X_MIC_PRE_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, DA732X_MIC_VOL_DB_MIN,
+				  DA732X_MIC_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(aux_pga_tlv, DA732X_AUX_VOL_DB_MIN,
+				  DA732X_AUX_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(hp_pga_tlv, DA732X_HP_VOL_DB_MIN,
+				  DA732X_AUX_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(lin2_pga_tlv, DA732X_LIN2_VOL_DB_MIN,
+				  DA732X_LIN2_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(lin3_pga_tlv, DA732X_LIN3_VOL_DB_MIN,
+				  DA732X_LIN3_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(lin4_pga_tlv, DA732X_LIN4_VOL_DB_MIN,
+				  DA732X_LIN4_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(adc_pga_tlv, DA732X_ADC_VOL_DB_MIN,
+				  DA732X_ADC_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(dac_pga_tlv, DA732X_DAC_VOL_DB_MIN,
+				  DA732X_DAC_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(eq_band_pga_tlv, DA732X_EQ_BAND_VOL_DB_MIN,
+				  DA732X_EQ_BAND_VOL_DB_INC, 0);
+
+static const DECLARE_TLV_DB_SCALE(eq_overall_tlv, DA732X_EQ_OVERALL_VOL_DB_MIN,
+				  DA732X_EQ_OVERALL_VOL_DB_INC, 0);
+
+/* High Pass Filter */
+static const char *da732x_hpf_mode[] = {
+	"Disable", "Music", "Voice",
+};
+
+static const char *da732x_hpf_music[] = {
+	"1.8Hz", "3.75Hz", "7.5Hz", "15Hz",
+};
+
+static const char *da732x_hpf_voice[] = {
+	"2.5Hz", "25Hz", "50Hz", "100Hz",
+	"150Hz", "200Hz", "300Hz", "400Hz"
+};
+
+static const struct soc_enum da732x_dac1_hpf_mode_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT,
+			DA732X_HPF_MODE_MAX, da732x_hpf_mode)
+};
+
+static const struct soc_enum da732x_dac2_hpf_mode_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT,
+			DA732X_HPF_MODE_MAX, da732x_hpf_mode)
+};
+
+static const struct soc_enum da732x_dac3_hpf_mode_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT,
+			DA732X_HPF_MODE_MAX, da732x_hpf_mode)
+};
+
+static const struct soc_enum da732x_adc1_hpf_mode_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT,
+			DA732X_HPF_MODE_MAX, da732x_hpf_mode)
+};
+
+static const struct soc_enum da732x_adc2_hpf_mode_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT,
+			DA732X_HPF_MODE_MAX, da732x_hpf_mode)
+};
+
+static const struct soc_enum da732x_dac1_hp_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT,
+			DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
+};
+
+static const struct soc_enum da732x_dac2_hp_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT,
+			DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
+};
+
+static const struct soc_enum da732x_dac3_hp_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT,
+			DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
+};
+
+static const struct soc_enum da732x_adc1_hp_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT,
+			DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
+};
+
+static const struct soc_enum da732x_adc2_hp_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT,
+			DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
+};
+
+static const struct soc_enum da732x_dac1_voice_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT,
+			DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
+};
+
+static const struct soc_enum da732x_dac2_voice_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT,
+			DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
+};
+
+static const struct soc_enum da732x_dac3_voice_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT,
+			DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
+};
+
+static const struct soc_enum da732x_adc1_voice_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT,
+			DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
+};
+
+static const struct soc_enum da732x_adc2_voice_filter_enum[] = {
+	SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT,
+			DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
+};
+
+
+static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
+	unsigned int reg = enum_ctrl->reg;
+	unsigned int sel = ucontrol->value.integer.value[0];
+	unsigned int bits;
+
+	switch (sel) {
+	case DA732X_HPF_DISABLED:
+		bits = DA732X_HPF_DIS;
+		break;
+	case DA732X_HPF_VOICE:
+		bits = DA732X_HPF_VOICE_EN;
+		break;
+	case DA732X_HPF_MUSIC:
+		bits = DA732X_HPF_MUSIC_EN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, reg, DA732X_HPF_MASK, bits);
+
+	return 0;
+}
+
+static int da732x_hpf_get(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
+	unsigned int reg = enum_ctrl->reg;
+	int val;
+
+	val = snd_soc_read(codec, reg) & DA732X_HPF_MASK;
+
+	switch (val) {
+	case DA732X_HPF_VOICE_EN:
+		ucontrol->value.integer.value[0] = DA732X_HPF_VOICE;
+		break;
+	case DA732X_HPF_MUSIC_EN:
+		ucontrol->value.integer.value[0] = DA732X_HPF_MUSIC;
+		break;
+	default:
+		ucontrol->value.integer.value[0] = DA732X_HPF_DISABLED;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new da732x_snd_controls[] = {
+	/* Input PGAs */
+	SOC_SINGLE_RANGE_TLV("MIC1 Boost Volume", DA732X_REG_MIC1_PRE,
+			     DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN,
+			     DA732X_MICBOOST_MAX, 0, mic_boost_tlv),
+	SOC_SINGLE_RANGE_TLV("MIC2 Boost Volume", DA732X_REG_MIC2_PRE,
+			     DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN,
+			     DA732X_MICBOOST_MAX, 0, mic_boost_tlv),
+	SOC_SINGLE_RANGE_TLV("MIC3 Boost Volume", DA732X_REG_MIC3_PRE,
+			     DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN,
+			     DA732X_MICBOOST_MAX, 0, mic_boost_tlv),
+
+	/* MICs */
+	SOC_SINGLE("MIC1 Switch", DA732X_REG_MIC1, DA732X_MIC_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_RANGE_TLV("MIC1 Volume", DA732X_REG_MIC1,
+			     DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN,
+			     DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv),
+	SOC_SINGLE("MIC2 Switch", DA732X_REG_MIC2, DA732X_MIC_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_RANGE_TLV("MIC2 Volume", DA732X_REG_MIC2,
+			     DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN,
+			     DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv),
+	SOC_SINGLE("MIC3 Switch", DA732X_REG_MIC3, DA732X_MIC_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_RANGE_TLV("MIC3 Volume", DA732X_REG_MIC3,
+			     DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN,
+			     DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv),
+
+	/* AUXs */
+	SOC_SINGLE("AUX1L Switch", DA732X_REG_AUX1L, DA732X_AUX_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_TLV("AUX1L Volume", DA732X_REG_AUX1L,
+		       DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX,
+		       DA732X_NO_INVERT, aux_pga_tlv),
+	SOC_SINGLE("AUX1R Switch", DA732X_REG_AUX1R, DA732X_AUX_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_TLV("AUX1R Volume", DA732X_REG_AUX1R,
+		       DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX,
+		       DA732X_NO_INVERT, aux_pga_tlv),
+
+	/* ADCs */
+	SOC_DOUBLE_TLV("ADC1 Volume", DA732X_REG_ADC1_SEL,
+		       DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT,
+		       DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv),
+
+	SOC_DOUBLE_TLV("ADC2 Volume", DA732X_REG_ADC2_SEL,
+		       DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT,
+		       DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv),
+
+	/* DACs */
+	SOC_DOUBLE("Digital Playback DAC12 Switch", DA732X_REG_DAC1_SEL,
+		   DA732X_DACL_MUTE_SHIFT, DA732X_DACR_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_DOUBLE_R_TLV("Digital Playback DAC12 Volume", DA732X_REG_DAC1_L_VOL,
+			 DA732X_REG_DAC1_R_VOL, DA732X_DAC_VOL_SHIFT,
+			 DA732X_DAC_VOL_VAL_MAX, DA732X_INVERT, dac_pga_tlv),
+	SOC_SINGLE("Digital Playback DAC3 Switch", DA732X_REG_DAC2_SEL,
+		   DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_TLV("Digital Playback DAC3 Volume", DA732X_REG_DAC2_L_VOL,
+			DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX,
+			DA732X_INVERT, dac_pga_tlv),
+	SOC_SINGLE("Digital Playback DAC4 Switch", DA732X_REG_DAC2_SEL,
+		   DA732X_DACR_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_TLV("Digital Playback DAC4 Volume", DA732X_REG_DAC2_R_VOL,
+		       DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX,
+		       DA732X_INVERT, dac_pga_tlv),
+	SOC_SINGLE("Digital Playback DAC5 Switch", DA732X_REG_DAC3_SEL,
+		   DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_TLV("Digital Playback DAC5 Volume", DA732X_REG_DAC3_VOL,
+		       DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX,
+		       DA732X_INVERT, dac_pga_tlv),
+
+	/* High Pass Filters */
+	SOC_ENUM_EXT("DAC1 High Pass Filter Mode",
+		     da732x_dac1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
+	SOC_ENUM("DAC1 High Pass Filter", da732x_dac1_hp_filter_enum),
+	SOC_ENUM("DAC1 Voice Filter", da732x_dac1_voice_filter_enum),
+
+	SOC_ENUM_EXT("DAC2 High Pass Filter Mode",
+		     da732x_dac2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
+	SOC_ENUM("DAC2 High Pass Filter", da732x_dac2_hp_filter_enum),
+	SOC_ENUM("DAC2 Voice Filter", da732x_dac2_voice_filter_enum),
+
+	SOC_ENUM_EXT("DAC3 High Pass Filter Mode",
+		     da732x_dac3_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
+	SOC_ENUM("DAC3 High Pass Filter", da732x_dac3_hp_filter_enum),
+	SOC_ENUM("DAC3 Filter Mode", da732x_dac3_voice_filter_enum),
+
+	SOC_ENUM_EXT("ADC1 High Pass Filter Mode",
+		     da732x_adc1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
+	SOC_ENUM("ADC1 High Pass Filter", da732x_adc1_hp_filter_enum),
+	SOC_ENUM("ADC1 Voice Filter", da732x_adc1_voice_filter_enum),
+
+	SOC_ENUM_EXT("ADC2 High Pass Filter Mode",
+		     da732x_adc2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
+	SOC_ENUM("ADC2 High Pass Filter", da732x_adc2_hp_filter_enum),
+	SOC_ENUM("ADC2 Voice Filter", da732x_adc2_voice_filter_enum),
+
+	/* Equalizers */
+	SOC_SINGLE("ADC1 EQ Switch", DA732X_REG_ADC1_EQ5,
+		   DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
+	SOC_SINGLE_TLV("ADC1 EQ Band 1 Volume", DA732X_REG_ADC1_EQ12,
+		       DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ADC1 EQ Band 2 Volume", DA732X_REG_ADC1_EQ12,
+		       DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ADC1 EQ Band 3 Volume", DA732X_REG_ADC1_EQ34,
+		       DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ADC1 EQ Band 4 Volume", DA732X_REG_ADC1_EQ34,
+		       DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ADC1 EQ Band 5 Volume", DA732X_REG_ADC1_EQ5,
+		       DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ADC1 EQ Overall Volume", DA732X_REG_ADC1_EQ5,
+		       DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_overall_tlv),
+
+	SOC_SINGLE("ADC2 EQ Switch", DA732X_REG_ADC2_EQ5,
+		   DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
+	SOC_SINGLE_TLV("ADC2 EQ Band 1 Volume", DA732X_REG_ADC2_EQ12,
+		       DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ADC2 EQ Band 2 Volume", DA732X_REG_ADC2_EQ12,
+		       DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ADC2 EQ Band 3 Volume", DA732X_REG_ADC2_EQ34,
+		       DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ACD2 EQ Band 4 Volume", DA732X_REG_ADC2_EQ34,
+		       DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ACD2 EQ Band 5 Volume", DA732X_REG_ADC2_EQ5,
+		       DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("ADC2 EQ Overall Volume", DA732X_REG_ADC1_EQ5,
+		       DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_overall_tlv),
+
+	SOC_SINGLE("DAC1 EQ Switch", DA732X_REG_DAC1_EQ5,
+		   DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
+	SOC_SINGLE_TLV("DAC1 EQ Band 1 Volume", DA732X_REG_DAC1_EQ12,
+		       DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC1 EQ Band 2 Volume", DA732X_REG_DAC1_EQ12,
+		       DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC1 EQ Band 3 Volume", DA732X_REG_DAC1_EQ34,
+		       DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC1 EQ Band 4 Volume", DA732X_REG_DAC1_EQ34,
+		       DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC1 EQ Band 5 Volume", DA732X_REG_DAC1_EQ5,
+		       DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+
+	SOC_SINGLE("DAC2 EQ Switch", DA732X_REG_DAC2_EQ5,
+		   DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
+	SOC_SINGLE_TLV("DAC2 EQ Band 1 Volume", DA732X_REG_DAC2_EQ12,
+		       DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC2 EQ Band 2 Volume", DA732X_REG_DAC2_EQ12,
+		       DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC2 EQ Band 3 Volume", DA732X_REG_DAC2_EQ34,
+		       DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC2 EQ Band 4 Volume", DA732X_REG_DAC2_EQ34,
+		       DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC2 EQ Band 5 Volume", DA732X_REG_DAC2_EQ5,
+		       DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+
+	SOC_SINGLE("DAC3 EQ Switch", DA732X_REG_DAC3_EQ5,
+		   DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
+	SOC_SINGLE_TLV("DAC3 EQ Band 1 Volume", DA732X_REG_DAC3_EQ12,
+		       DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC3 EQ Band 2 Volume", DA732X_REG_DAC3_EQ12,
+		       DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC3 EQ Band 3 Volume", DA732X_REG_DAC3_EQ34,
+		       DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC3 EQ Band 4 Volume", DA732X_REG_DAC3_EQ34,
+		       DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+	SOC_SINGLE_TLV("DAC3 EQ Band 5 Volume", DA732X_REG_DAC3_EQ5,
+		       DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
+		       DA732X_INVERT, eq_band_pga_tlv),
+
+	/* Lineout 2 Reciever*/
+	SOC_SINGLE("Lineout 2 Switch", DA732X_REG_LIN2, DA732X_LOUT_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_TLV("Lineout 2 Volume", DA732X_REG_LIN2,
+		       DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX,
+		       DA732X_NO_INVERT, lin2_pga_tlv),
+
+	/* Lineout 3 SPEAKER*/
+	SOC_SINGLE("Lineout 3 Switch", DA732X_REG_LIN3, DA732X_LOUT_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_TLV("Lineout 3 Volume", DA732X_REG_LIN3,
+		       DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX,
+		       DA732X_NO_INVERT, lin3_pga_tlv),
+
+	/* Lineout 4 */
+	SOC_SINGLE("Lineout 4 Switch", DA732X_REG_LIN4, DA732X_LOUT_MUTE_SHIFT,
+		   DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_SINGLE_TLV("Lineout 4 Volume", DA732X_REG_LIN4,
+		       DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX,
+		       DA732X_NO_INVERT, lin4_pga_tlv),
+
+	/* Headphones */
+	SOC_DOUBLE_R("Headphone Switch", DA732X_REG_HPR, DA732X_REG_HPL,
+		     DA732X_HP_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT),
+	SOC_DOUBLE_R_TLV("Headphone Volume", DA732X_REG_HPL_VOL,
+			 DA732X_REG_HPR_VOL, DA732X_HP_VOL_SHIFT,
+			 DA732X_HP_VOL_VAL_MAX, DA732X_NO_INVERT, hp_pga_tlv),
+};
+
+static int da732x_adc_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		switch (w->reg) {
+		case DA732X_REG_ADC1_PD:
+			snd_soc_update_bits(codec, DA732X_REG_CLK_EN3,
+					    DA732X_ADCA_BB_CLK_EN,
+					    DA732X_ADCA_BB_CLK_EN);
+			break;
+		case DA732X_REG_ADC2_PD:
+			snd_soc_update_bits(codec, DA732X_REG_CLK_EN3,
+					    DA732X_ADCC_BB_CLK_EN,
+					    DA732X_ADCC_BB_CLK_EN);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK,
+				    DA732X_ADC_SET_ACT);
+		snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK,
+				    DA732X_ADC_ON);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK,
+				    DA732X_ADC_OFF);
+		snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK,
+				    DA732X_ADC_SET_RST);
+
+		switch (w->reg) {
+		case DA732X_REG_ADC1_PD:
+			snd_soc_update_bits(codec, DA732X_REG_CLK_EN3,
+					    DA732X_ADCA_BB_CLK_EN, 0);
+			break;
+		case DA732X_REG_ADC2_PD:
+			snd_soc_update_bits(codec, DA732X_REG_CLK_EN3,
+					    DA732X_ADCC_BB_CLK_EN, 0);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int da732x_out_pga_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, w->reg,
+				    (1 << w->shift) | DA732X_OUT_HIZ_EN,
+				    (1 << w->shift) | DA732X_OUT_HIZ_EN);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, w->reg,
+				    (1 << w->shift) | DA732X_OUT_HIZ_EN,
+				    (1 << w->shift) | DA732X_OUT_HIZ_DIS);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const char *adcl_text[] = {
+	"AUX1L", "MIC1"
+};
+
+static const char *adcr_text[] = {
+	"AUX1R", "MIC2", "MIC3"
+};
+
+static const char *enable_text[] = {
+	"Disabled",
+	"Enabled"
+};
+
+/* ADC1LMUX */
+static const struct soc_enum adc1l_enum =
+	SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT,
+			DA732X_ADCL_MUX_MAX, adcl_text);
+static const struct snd_kcontrol_new adc1l_mux =
+	SOC_DAPM_ENUM("ADC Route", adc1l_enum);
+
+/* ADC1RMUX */
+static const struct soc_enum adc1r_enum =
+	SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT,
+			DA732X_ADCR_MUX_MAX, adcr_text);
+static const struct snd_kcontrol_new adc1r_mux =
+	SOC_DAPM_ENUM("ADC Route", adc1r_enum);
+
+/* ADC2LMUX */
+static const struct soc_enum adc2l_enum =
+	SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT,
+			DA732X_ADCL_MUX_MAX, adcl_text);
+static const struct snd_kcontrol_new adc2l_mux =
+	SOC_DAPM_ENUM("ADC Route", adc2l_enum);
+
+/* ADC2RMUX */
+static const struct soc_enum adc2r_enum =
+	SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT,
+			DA732X_ADCR_MUX_MAX, adcr_text);
+
+static const struct snd_kcontrol_new adc2r_mux =
+	SOC_DAPM_ENUM("ADC Route", adc2r_enum);
+
+static const struct soc_enum da732x_hp_left_output =
+	SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT,
+			DA732X_DAC_EN_MAX, enable_text);
+
+static const struct snd_kcontrol_new hpl_mux =
+	SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output);
+
+static const struct soc_enum da732x_hp_right_output =
+	SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT,
+			DA732X_DAC_EN_MAX, enable_text);
+
+static const struct snd_kcontrol_new hpr_mux =
+	SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output);
+
+static const struct soc_enum da732x_speaker_output =
+	SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT,
+			DA732X_DAC_EN_MAX, enable_text);
+
+static const struct snd_kcontrol_new spk_mux =
+	SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output);
+
+static const struct soc_enum da732x_lout4_output =
+	SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT,
+			DA732X_DAC_EN_MAX, enable_text);
+
+static const struct snd_kcontrol_new lout4_mux =
+	SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output);
+
+static const struct soc_enum da732x_lout2_output =
+	SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT,
+			DA732X_DAC_EN_MAX, enable_text);
+
+static const struct snd_kcontrol_new lout2_mux =
+	SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output);
+
+static const struct snd_soc_dapm_widget da732x_dapm_widgets[] = {
+	/* Supplies */
+	SND_SOC_DAPM_SUPPLY("ADC1 Supply", DA732X_REG_ADC1_PD, 0,
+			    DA732X_NO_INVERT, da732x_adc_event,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("ADC2 Supply", DA732X_REG_ADC2_PD, 0,
+			    DA732X_NO_INVERT, da732x_adc_event,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("DAC1 CLK", DA732X_REG_CLK_EN4,
+			    DA732X_DACA_BB_CLK_SHIFT, DA732X_NO_INVERT,
+			    NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC2 CLK", DA732X_REG_CLK_EN4,
+			    DA732X_DACC_BB_CLK_SHIFT, DA732X_NO_INVERT,
+			    NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC3 CLK", DA732X_REG_CLK_EN5,
+			    DA732X_DACE_BB_CLK_SHIFT, DA732X_NO_INVERT,
+			    NULL, 0),
+
+	/* Micbias */
+	SND_SOC_DAPM_SUPPLY("MICBIAS1", DA732X_REG_MICBIAS1,
+			    DA732X_MICBIAS_EN_SHIFT,
+			    DA732X_NO_INVERT, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("MICBIAS2", DA732X_REG_MICBIAS2,
+			    DA732X_MICBIAS_EN_SHIFT,
+			    DA732X_NO_INVERT, NULL, 0),
+
+	/* Inputs */
+	SND_SOC_DAPM_INPUT("MIC1"),
+	SND_SOC_DAPM_INPUT("MIC2"),
+	SND_SOC_DAPM_INPUT("MIC3"),
+	SND_SOC_DAPM_INPUT("AUX1L"),
+	SND_SOC_DAPM_INPUT("AUX1R"),
+
+	/* Outputs */
+	SND_SOC_DAPM_OUTPUT("HPL"),
+	SND_SOC_DAPM_OUTPUT("HPR"),
+	SND_SOC_DAPM_OUTPUT("LOUTL"),
+	SND_SOC_DAPM_OUTPUT("LOUTR"),
+	SND_SOC_DAPM_OUTPUT("ClassD"),
+
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC1L", NULL, DA732X_REG_ADC1_SEL,
+			 DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT),
+	SND_SOC_DAPM_ADC("ADC1R", NULL, DA732X_REG_ADC1_SEL,
+			 DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT),
+	SND_SOC_DAPM_ADC("ADC2L", NULL, DA732X_REG_ADC2_SEL,
+			 DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT),
+	SND_SOC_DAPM_ADC("ADC2R", NULL, DA732X_REG_ADC2_SEL,
+			 DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT),
+
+	/* DACs */
+	SND_SOC_DAPM_DAC("DAC1L", NULL, DA732X_REG_DAC1_SEL,
+			 DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT),
+	SND_SOC_DAPM_DAC("DAC1R", NULL, DA732X_REG_DAC1_SEL,
+			 DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT),
+	SND_SOC_DAPM_DAC("DAC2L", NULL, DA732X_REG_DAC2_SEL,
+			 DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT),
+	SND_SOC_DAPM_DAC("DAC2R", NULL, DA732X_REG_DAC2_SEL,
+			 DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT),
+	SND_SOC_DAPM_DAC("DAC3", NULL, DA732X_REG_DAC3_SEL,
+			 DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT),
+
+	/* Input Pgas */
+	SND_SOC_DAPM_PGA("MIC1 PGA", DA732X_REG_MIC1, DA732X_MIC_EN_SHIFT,
+			 0, NULL, 0),
+	SND_SOC_DAPM_PGA("MIC2 PGA", DA732X_REG_MIC2, DA732X_MIC_EN_SHIFT,
+			 0, NULL, 0),
+	SND_SOC_DAPM_PGA("MIC3 PGA", DA732X_REG_MIC3, DA732X_MIC_EN_SHIFT,
+			 0, NULL, 0),
+	SND_SOC_DAPM_PGA("AUX1L PGA", DA732X_REG_AUX1L, DA732X_AUX_EN_SHIFT,
+			 0, NULL, 0),
+	SND_SOC_DAPM_PGA("AUX1R PGA", DA732X_REG_AUX1R, DA732X_AUX_EN_SHIFT,
+			 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA_E("HP Left", DA732X_REG_HPL, DA732X_HP_OUT_EN_SHIFT,
+			   0, NULL, 0, da732x_out_pga_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("HP Right", DA732X_REG_HPR, DA732X_HP_OUT_EN_SHIFT,
+			   0, NULL, 0, da732x_out_pga_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LIN2", DA732X_REG_LIN2, DA732X_LIN_OUT_EN_SHIFT,
+			   0, NULL, 0, da732x_out_pga_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LIN3", DA732X_REG_LIN3, DA732X_LIN_OUT_EN_SHIFT,
+			   0, NULL, 0, da732x_out_pga_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LIN4", DA732X_REG_LIN4, DA732X_LIN_OUT_EN_SHIFT,
+			   0, NULL, 0, da732x_out_pga_event,
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* MUXs */
+	SND_SOC_DAPM_MUX("ADC1 Left MUX", SND_SOC_NOPM, 0, 0, &adc1l_mux),
+	SND_SOC_DAPM_MUX("ADC1 Right MUX", SND_SOC_NOPM, 0, 0, &adc1r_mux),
+	SND_SOC_DAPM_MUX("ADC2 Left MUX", SND_SOC_NOPM, 0, 0, &adc2l_mux),
+	SND_SOC_DAPM_MUX("ADC2 Right MUX", SND_SOC_NOPM, 0, 0, &adc2r_mux),
+
+	SND_SOC_DAPM_MUX("HP Left MUX", SND_SOC_NOPM, 0, 0, &hpl_mux),
+	SND_SOC_DAPM_MUX("HP Right MUX", SND_SOC_NOPM, 0, 0, &hpr_mux),
+	SND_SOC_DAPM_MUX("Speaker MUX", SND_SOC_NOPM, 0, 0, &spk_mux),
+	SND_SOC_DAPM_MUX("LOUT2 MUX", SND_SOC_NOPM, 0, 0, &lout2_mux),
+	SND_SOC_DAPM_MUX("LOUT4 MUX", SND_SOC_NOPM, 0, 0, &lout4_mux),
+
+	/* AIF interfaces */
+	SND_SOC_DAPM_AIF_OUT("AIFA Output", "AIFA Capture", 0, DA732X_REG_AIFA3,
+			     DA732X_AIF_EN_SHIFT, 0),
+	SND_SOC_DAPM_AIF_IN("AIFA Input", "AIFA Playback", 0, DA732X_REG_AIFA3,
+			    DA732X_AIF_EN_SHIFT, 0),
+
+	SND_SOC_DAPM_AIF_OUT("AIFB Output", "AIFB Capture", 0, DA732X_REG_AIFB3,
+			     DA732X_AIF_EN_SHIFT, 0),
+	SND_SOC_DAPM_AIF_IN("AIFB Input", "AIFB Playback", 0, DA732X_REG_AIFB3,
+			    DA732X_AIF_EN_SHIFT, 0),
+};
+
+static const struct snd_soc_dapm_route da732x_dapm_routes[] = {
+	/* Inputs */
+	{"AUX1L PGA", "NULL", "AUX1L"},
+	{"AUX1R PGA", "NULL", "AUX1R"},
+	{"MIC1 PGA", NULL, "MIC1"},
+	{"MIC2 PGA", "NULL", "MIC2"},
+	{"MIC3 PGA", "NULL", "MIC3"},
+
+	/* Capture Path */
+	{"ADC1 Left MUX", "MIC1", "MIC1 PGA"},
+	{"ADC1 Left MUX", "AUX1L", "AUX1L PGA"},
+
+	{"ADC1 Right MUX", "AUX1R", "AUX1R PGA"},
+	{"ADC1 Right MUX", "MIC2", "MIC2 PGA"},
+	{"ADC1 Right MUX", "MIC3", "MIC3 PGA"},
+
+	{"ADC2 Left MUX", "AUX1L", "AUX1L PGA"},
+	{"ADC2 Left MUX", "MIC1", "MIC1 PGA"},
+
+	{"ADC2 Right MUX", "AUX1R", "AUX1R PGA"},
+	{"ADC2 Right MUX", "MIC2", "MIC2 PGA"},
+	{"ADC2 Right MUX", "MIC3", "MIC3 PGA"},
+
+	{"ADC1L", NULL, "ADC1 Supply"},
+	{"ADC1R", NULL, "ADC1 Supply"},
+	{"ADC2L", NULL, "ADC2 Supply"},
+	{"ADC2R", NULL, "ADC2 Supply"},
+
+	{"ADC1L", NULL, "ADC1 Left MUX"},
+	{"ADC1R", NULL, "ADC1 Right MUX"},
+	{"ADC2L", NULL, "ADC2 Left MUX"},
+	{"ADC2R", NULL, "ADC2 Right MUX"},
+
+	{"AIFA Output", NULL, "ADC1L"},
+	{"AIFA Output", NULL, "ADC1R"},
+	{"AIFB Output", NULL, "ADC2L"},
+	{"AIFB Output", NULL, "ADC2R"},
+
+	{"HP Left MUX", "Enabled", "AIFA Input"},
+	{"HP Right MUX", "Enabled", "AIFA Input"},
+	{"Speaker MUX", "Enabled", "AIFB Input"},
+	{"LOUT2 MUX", "Enabled", "AIFB Input"},
+	{"LOUT4 MUX", "Enabled", "AIFB Input"},
+
+	{"DAC1L", NULL, "DAC1 CLK"},
+	{"DAC1R", NULL, "DAC1 CLK"},
+	{"DAC2L", NULL, "DAC2 CLK"},
+	{"DAC2R", NULL, "DAC2 CLK"},
+	{"DAC3", NULL, "DAC3 CLK"},
+
+	{"DAC1L", NULL, "HP Left MUX"},
+	{"DAC1R", NULL, "HP Right MUX"},
+	{"DAC2L", NULL, "Speaker MUX"},
+	{"DAC2R", NULL, "LOUT4 MUX"},
+	{"DAC3", NULL, "LOUT2 MUX"},
+
+	/* Output Pgas */
+	{"HP Left", NULL, "DAC1L"},
+	{"HP Right", NULL, "DAC1R"},
+	{"LIN3", NULL, "DAC2L"},
+	{"LIN4", NULL, "DAC2R"},
+	{"LIN2", NULL, "DAC3"},
+
+	/* Outputs */
+	{"ClassD", NULL, "LIN3"},
+	{"LOUTL", NULL, "LIN2"},
+	{"LOUTR", NULL, "LIN4"},
+	{"HPL", NULL, "HP Left"},
+	{"HPR", NULL, "HP Right"},
+};
+
+static int da732x_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u32 aif = 0;
+	u32 reg_aif;
+	u32 fs;
+
+	reg_aif = dai->driver->base;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		aif |= DA732X_AIF_WORD_16;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		aif |= DA732X_AIF_WORD_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		aif |= DA732X_AIF_WORD_24;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		aif |= DA732X_AIF_WORD_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (params_rate(params)) {
+	case 8000:
+		fs = DA732X_SR_8KHZ;
+		break;
+	case 11025:
+		fs = DA732X_SR_11_025KHZ;
+		break;
+	case 12000:
+		fs = DA732X_SR_12KHZ;
+		break;
+	case 16000:
+		fs = DA732X_SR_16KHZ;
+		break;
+	case 22050:
+		fs = DA732X_SR_22_05KHZ;
+		break;
+	case 24000:
+		fs = DA732X_SR_24KHZ;
+		break;
+	case 32000:
+		fs = DA732X_SR_32KHZ;
+		break;
+	case 44100:
+		fs = DA732X_SR_44_1KHZ;
+		break;
+	case 48000:
+		fs = DA732X_SR_48KHZ;
+		break;
+	case 88100:
+		fs = DA732X_SR_88_1KHZ;
+		break;
+	case 96000:
+		fs = DA732X_SR_96KHZ;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, reg_aif, DA732X_AIF_WORD_MASK, aif);
+	snd_soc_update_bits(codec, DA732X_REG_CLK_CTRL, DA732X_SR1_MASK, fs);
+
+	return 0;
+}
+
+static int da732x_set_dai_fmt(struct snd_soc_dai *dai, u32 fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u32 aif_mclk, pc_count;
+	u32 reg_aif1, aif1;
+	u32 reg_aif3, aif3;
+
+	switch (dai->id) {
+	case DA732X_DAI_ID1:
+		reg_aif1 = DA732X_REG_AIFA1;
+		reg_aif3 = DA732X_REG_AIFA3;
+		pc_count = DA732X_PC_PULSE_AIFA | DA732X_PC_RESYNC_NOT_AUT |
+			   DA732X_PC_SAME;
+		break;
+	case DA732X_DAI_ID2:
+		reg_aif1 = DA732X_REG_AIFB1;
+		reg_aif3 = DA732X_REG_AIFB3;
+		pc_count = DA732X_PC_PULSE_AIFB | DA732X_PC_RESYNC_NOT_AUT |
+			   DA732X_PC_SAME;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		aif1 = DA732X_AIF_SLAVE;
+		aif_mclk = DA732X_AIFM_FRAME_64 | DA732X_AIFM_SRC_SEL_AIFA;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		aif1 = DA732X_AIF_CLK_FROM_SRC;
+		aif_mclk = DA732X_CLK_GENERATION_AIF_A;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		aif3 = DA732X_AIF_I2S_MODE;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		aif3 = DA732X_AIF_RIGHT_J_MODE;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		aif3 = DA732X_AIF_LEFT_J_MODE;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		aif3 = DA732X_AIF_DSP_MODE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_B:
+		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+		case SND_SOC_DAIFMT_NB_NF:
+			break;
+		case SND_SOC_DAIFMT_IB_NF:
+			aif3 |= DA732X_AIF_BCLK_INV;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case SND_SOC_DAIFMT_I2S:
+	case SND_SOC_DAIFMT_RIGHT_J:
+	case SND_SOC_DAIFMT_LEFT_J:
+		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+		case SND_SOC_DAIFMT_NB_NF:
+			break;
+		case SND_SOC_DAIFMT_IB_IF:
+			aif3 |= DA732X_AIF_BCLK_INV | DA732X_AIF_WCLK_INV;
+			break;
+		case SND_SOC_DAIFMT_IB_NF:
+			aif3 |= DA732X_AIF_BCLK_INV;
+			break;
+		case SND_SOC_DAIFMT_NB_IF:
+			aif3 |= DA732X_AIF_WCLK_INV;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_write(codec, DA732X_REG_AIF_MCLK, aif_mclk);
+	snd_soc_update_bits(codec, reg_aif1, DA732X_AIF1_CLK_MASK, aif1);
+	snd_soc_update_bits(codec, reg_aif3, DA732X_AIF_BCLK_INV |
+			    DA732X_AIF_WCLK_INV | DA732X_AIF_MODE_MASK, aif3);
+	snd_soc_write(codec, DA732X_REG_PC_CTRL, pc_count);
+
+	return 0;
+}
+
+
+
+static int da732x_set_dai_pll(struct snd_soc_codec *codec, int pll_id,
+			      int source, unsigned int freq_in,
+			      unsigned int freq_out)
+{
+	struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
+	int fref, indiv;
+	u8 div_lo, div_mid, div_hi;
+	u64 frac_div;
+
+	/* Disable PLL */
+	if (freq_out == 0) {
+		snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL,
+				    DA732X_PLL_EN, 0);
+		da732x->pll_en = false;
+		return 0;
+	}
+
+	if (da732x->pll_en)
+		return -EBUSY;
+
+	if (source == DA732X_SRCCLK_MCLK) {
+		/* Validate Sysclk rate */
+		switch (da732x->sysclk) {
+		case 11290000:
+		case 12288000:
+		case 22580000:
+		case 24576000:
+		case 45160000:
+		case 49152000:
+			snd_soc_write(codec, DA732X_REG_PLL_CTRL,
+				      DA732X_PLL_BYPASS);
+			return 0;
+		default:
+			dev_err(codec->dev,
+				"Cannot use PLL Bypass, invalid SYSCLK rate\n");
+			return -EINVAL;
+		}
+	}
+
+	indiv = da732x_get_input_div(codec, da732x->sysclk);
+	if (indiv < 0)
+		return indiv;
+
+	fref = (da732x->sysclk / indiv);
+	div_hi = freq_out / fref;
+	frac_div = (u64)(freq_out % fref) * 8192ULL;
+	do_div(frac_div, fref);
+	div_mid = (frac_div >> DA732X_1BYTE_SHIFT) & DA732X_U8_MASK;
+	div_lo = (frac_div) & DA732X_U8_MASK;
+
+	snd_soc_write(codec, DA732X_REG_PLL_DIV_LO, div_lo);
+	snd_soc_write(codec, DA732X_REG_PLL_DIV_MID, div_mid);
+	snd_soc_write(codec, DA732X_REG_PLL_DIV_HI, div_hi);
+
+	snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, DA732X_PLL_EN,
+			    DA732X_PLL_EN);
+
+	da732x->pll_en = true;
+
+	return 0;
+}
+
+static int da732x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+				 unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
+
+	da732x->sysclk = freq;
+
+	return 0;
+}
+
+#define DA732X_RATES	SNDRV_PCM_RATE_8000_96000
+
+#define	DA732X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops da732x_dai1_ops = {
+	.hw_params	= da732x_hw_params,
+	.set_fmt	= da732x_set_dai_fmt,
+	.set_sysclk	= da732x_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_ops da732x_dai2_ops = {
+	.hw_params	= da732x_hw_params,
+	.set_fmt	= da732x_set_dai_fmt,
+	.set_sysclk	= da732x_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver da732x_dai[] = {
+	{
+		.name	= "DA732X_AIFA",
+		.id	= DA732X_DAI_ID1,
+		.base	= DA732X_REG_AIFA1,
+		.playback = {
+			.stream_name = "AIFA Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = DA732X_RATES,
+			.formats = DA732X_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIFA Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = DA732X_RATES,
+			.formats = DA732X_FORMATS,
+		},
+		.ops = &da732x_dai1_ops,
+	},
+	{
+		.name	= "DA732X_AIFB",
+		.id	= DA732X_DAI_ID2,
+		.base	= DA732X_REG_AIFB1,
+		.playback = {
+			.stream_name = "AIFB Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = DA732X_RATES,
+			.formats = DA732X_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIFB Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = DA732X_RATES,
+			.formats = DA732X_FORMATS,
+		},
+		.ops = &da732x_dai2_ops,
+	},
+};
+
+static const struct regmap_config da732x_regmap = {
+	.reg_bits		= 8,
+	.val_bits		= 8,
+
+	.max_register		= DA732X_MAX_REG,
+	.reg_defaults		= da732x_reg_cache,
+	.num_reg_defaults	= ARRAY_SIZE(da732x_reg_cache),
+	.cache_type		= REGCACHE_RBTREE,
+};
+
+
+static void da732x_dac_offset_adjust(struct snd_soc_codec *codec)
+{
+	u8 offset[DA732X_HP_DACS];
+	u8 sign[DA732X_HP_DACS];
+	u8 step = DA732X_DAC_OFFSET_STEP;
+
+	/* Initialize DAC offset calibration circuits and registers */
+	snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET,
+		      DA732X_HP_DAC_OFFSET_TRIM_VAL);
+	snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET,
+		      DA732X_HP_DAC_OFFSET_TRIM_VAL);
+	snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL,
+		      DA732X_HP_DAC_OFF_CALIBRATION |
+		      DA732X_HP_DAC_OFF_SCALE_STEPS);
+	snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL,
+		      DA732X_HP_DAC_OFF_CALIBRATION |
+		      DA732X_HP_DAC_OFF_SCALE_STEPS);
+
+	/* Wait for voltage stabilization */
+	msleep(DA732X_WAIT_FOR_STABILIZATION);
+
+	/* Check DAC offset sign */
+	sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
+				DA732X_HP_DAC_OFF_CNTL_COMPO);
+	sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
+				DA732X_HP_DAC_OFF_CNTL_COMPO);
+
+	/* Binary search DAC offset values (both channels at once) */
+	offset[DA732X_HPL_DAC] = sign[DA732X_HPL_DAC] << DA732X_HP_DAC_COMPO_SHIFT;
+	offset[DA732X_HPR_DAC] = sign[DA732X_HPR_DAC] << DA732X_HP_DAC_COMPO_SHIFT;
+
+	do {
+		offset[DA732X_HPL_DAC] |= step;
+		offset[DA732X_HPR_DAC] |= step;
+		snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET,
+			      ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK);
+		snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET,
+			      ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK);
+
+		msleep(DA732X_WAIT_FOR_STABILIZATION);
+
+		if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
+		     DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC])
+			offset[DA732X_HPL_DAC] &= ~step;
+		if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
+		     DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC])
+			offset[DA732X_HPR_DAC] &= ~step;
+
+		step >>= 1;
+	} while (step);
+
+	/* Write final DAC offsets to registers */
+	snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET,
+		      ~offset[DA732X_HPL_DAC] &	DA732X_HP_DAC_OFF_MASK);
+	snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET,
+		      ~offset[DA732X_HPR_DAC] &	DA732X_HP_DAC_OFF_MASK);
+
+	/* End DAC calibration mode */
+	snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL,
+		DA732X_HP_DAC_OFF_SCALE_STEPS);
+	snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL,
+		DA732X_HP_DAC_OFF_SCALE_STEPS);
+}
+
+static void da732x_output_offset_adjust(struct snd_soc_codec *codec)
+{
+	u8 offset[DA732X_HP_AMPS];
+	u8 sign[DA732X_HP_AMPS];
+	u8 step = DA732X_OUTPUT_OFFSET_STEP;
+
+	offset[DA732X_HPL_AMP] = DA732X_HP_OUT_TRIM_VAL;
+	offset[DA732X_HPR_AMP] = DA732X_HP_OUT_TRIM_VAL;
+
+	/* Initialize output offset calibration circuits and registers  */
+	snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL);
+	snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL);
+	snd_soc_write(codec, DA732X_REG_HPL,
+		      DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN);
+	snd_soc_write(codec, DA732X_REG_HPR,
+		      DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN);
+
+	/* Wait for voltage stabilization */
+	msleep(DA732X_WAIT_FOR_STABILIZATION);
+
+	/* Check output offset sign */
+	sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) &
+			       DA732X_HP_OUT_COMPO;
+	sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) &
+			       DA732X_HP_OUT_COMPO;
+
+	snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP |
+		      (sign[DA732X_HPL_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) |
+		      DA732X_HP_OUT_EN);
+	snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_COMP |
+		      (sign[DA732X_HPR_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) |
+		      DA732X_HP_OUT_EN);
+
+	/* Binary search output offset values (both channels at once) */
+	do {
+		offset[DA732X_HPL_AMP] |= step;
+		offset[DA732X_HPR_AMP] |= step;
+		snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET,
+			      offset[DA732X_HPL_AMP]);
+		snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET,
+			      offset[DA732X_HPR_AMP]);
+
+		msleep(DA732X_WAIT_FOR_STABILIZATION);
+
+		if ((codec->hw_read(codec, DA732X_REG_HPL) &
+		     DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP])
+			offset[DA732X_HPL_AMP] &= ~step;
+		if ((codec->hw_read(codec, DA732X_REG_HPR) &
+		     DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP])
+			offset[DA732X_HPR_AMP] &= ~step;
+
+		step >>= 1;
+	} while (step);
+
+	/* Write final DAC offsets to registers */
+	snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, offset[DA732X_HPL_AMP]);
+	snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, offset[DA732X_HPR_AMP]);
+}
+
+static void da732x_hp_dc_offset_cancellation(struct snd_soc_codec *codec)
+{
+	/* Make sure that we have Soft Mute enabled */
+	snd_soc_write(codec, DA732X_REG_DAC1_SOFTMUTE, DA732X_SOFTMUTE_EN |
+		      DA732X_GAIN_RAMPED | DA732X_16_SAMPLES);
+	snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACL_EN |
+		      DA732X_DACR_EN | DA732X_DACL_SDM | DA732X_DACR_SDM |
+		      DA732X_DACL_MUTE | DA732X_DACR_MUTE);
+	snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN |
+		      DA732X_HP_OUT_MUTE | DA732X_HP_OUT_EN);
+	snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_EN |
+		      DA732X_HP_OUT_MUTE | DA732X_HP_OUT_DAC_EN);
+
+	da732x_dac_offset_adjust(codec);
+	da732x_output_offset_adjust(codec);
+
+	snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACS_DIS);
+	snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_DIS);
+	snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_DIS);
+}
+
+static int da732x_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		snd_soc_update_bits(codec, DA732X_REG_BIAS_EN,
+				    DA732X_BIAS_BOOST_MASK,
+				    DA732X_BIAS_BOOST_100PC);
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			/* Init Codec */
+			snd_soc_write(codec, DA732X_REG_REF1,
+				      DA732X_VMID_FASTCHG);
+			snd_soc_write(codec, DA732X_REG_BIAS_EN,
+				      DA732X_BIAS_EN);
+
+			mdelay(DA732X_STARTUP_DELAY);
+
+			/* Disable Fast Charge and enable DAC ref voltage */
+			snd_soc_write(codec, DA732X_REG_REF1,
+				      DA732X_REFBUFX2_EN);
+
+			/* Enable bypass DSP routing */
+			snd_soc_write(codec, DA732X_REG_DATA_ROUTE,
+				      DA732X_BYPASS_DSP);
+
+			/* Enable Digital subsystem */
+			snd_soc_write(codec, DA732X_REG_DSP_CTRL,
+				      DA732X_DIGITAL_EN);
+
+			snd_soc_write(codec, DA732X_REG_SPARE1_OUT,
+				      DA732X_HP_DRIVER_EN |
+				      DA732X_HP_GATE_LOW |
+				      DA732X_HP_LOOP_GAIN_CTRL);
+			snd_soc_write(codec, DA732X_REG_HP_LIN1_GNDSEL,
+				      DA732X_HP_OUT_GNDSEL);
+
+			da732x_set_charge_pump(codec, DA732X_ENABLE_CP);
+
+			snd_soc_write(codec, DA732X_REG_CLK_EN1,
+			      DA732X_SYS3_CLK_EN | DA732X_PC_CLK_EN);
+
+			/* Enable Zero Crossing */
+			snd_soc_write(codec, DA732X_REG_INP_ZC_EN,
+				      DA732X_MIC1_PRE_ZC_EN |
+				      DA732X_MIC1_ZC_EN |
+				      DA732X_MIC2_PRE_ZC_EN |
+				      DA732X_MIC2_ZC_EN |
+				      DA732X_AUXL_ZC_EN |
+				      DA732X_AUXR_ZC_EN |
+				      DA732X_MIC3_PRE_ZC_EN |
+				      DA732X_MIC3_ZC_EN);
+			snd_soc_write(codec, DA732X_REG_OUT_ZC_EN,
+				      DA732X_HPL_ZC_EN | DA732X_HPR_ZC_EN |
+				      DA732X_LIN2_ZC_EN | DA732X_LIN3_ZC_EN |
+				      DA732X_LIN4_ZC_EN);
+
+			da732x_hp_dc_offset_cancellation(codec);
+
+			regcache_cache_only(codec->control_data, false);
+			regcache_sync(codec->control_data);
+		} else {
+			snd_soc_update_bits(codec, DA732X_REG_BIAS_EN,
+					    DA732X_BIAS_BOOST_MASK,
+					    DA732X_BIAS_BOOST_50PC);
+			snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL,
+					    DA732X_PLL_EN, 0);
+			da732x->pll_en = false;
+		}
+		break;
+	case SND_SOC_BIAS_OFF:
+		regcache_cache_only(codec->control_data, true);
+		da732x_set_charge_pump(codec, DA732X_DISABLE_CP);
+		snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN,
+				    DA732X_BIAS_DIS);
+		da732x->pll_en = false;
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static int da732x_probe(struct snd_soc_codec *codec)
+{
+	struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret = 0;
+
+	da732x->codec = codec;
+
+	dapm->idle_bias_off = false;
+
+	codec->control_data = da732x->regmap;
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to register codec.\n");
+		goto err;
+	}
+
+	da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+err:
+	return ret;
+}
+
+static int da732x_remove(struct snd_soc_codec *codec)
+{
+
+	da732x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_da732x = {
+	.probe			= da732x_probe,
+	.remove			= da732x_remove,
+	.set_bias_level		= da732x_set_bias_level,
+	.controls		= da732x_snd_controls,
+	.num_controls		= ARRAY_SIZE(da732x_snd_controls),
+	.dapm_widgets		= da732x_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(da732x_dapm_widgets),
+	.dapm_routes		= da732x_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(da732x_dapm_routes),
+	.set_pll		= da732x_set_dai_pll,
+	.reg_cache_size		= ARRAY_SIZE(da732x_reg_cache),
+};
+
+static __devinit int da732x_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct da732x_priv *da732x;
+	unsigned int reg;
+	int ret;
+
+	da732x = devm_kzalloc(&i2c->dev, sizeof(struct da732x_priv),
+			      GFP_KERNEL);
+	if (!da732x)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, da732x);
+
+	da732x->regmap = devm_regmap_init_i2c(i2c, &da732x_regmap);
+	if (IS_ERR(da732x->regmap)) {
+		ret = PTR_ERR(da732x->regmap);
+		dev_err(&i2c->dev, "Failed to initialize regmap\n");
+		goto err;
+	}
+
+	ret = regmap_read(da732x->regmap, DA732X_REG_ID, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+		goto err;
+	}
+
+	dev_info(&i2c->dev, "Revision: %d.%d\n",
+		 (reg & DA732X_ID_MAJOR_MASK), (reg & DA732X_ID_MINOR_MASK));
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da732x,
+				     da732x_dai, ARRAY_SIZE(da732x_dai));
+	if (ret != 0)
+		dev_err(&i2c->dev, "Failed to register codec.\n");
+
+err:
+	return ret;
+}
+
+static __devexit int da732x_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id da732x_i2c_id[] = {
+	{ "da7320", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, da732x_i2c_id);
+
+static struct i2c_driver da732x_i2c_driver = {
+	.driver		= {
+		.name	= "da7320",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= da732x_i2c_probe,
+	.remove		= __devexit_p(da732x_i2c_remove),
+	.id_table	= da732x_i2c_id,
+};
+
+module_i2c_driver(da732x_i2c_driver);
+
+
+MODULE_DESCRIPTION("ASoC DA732X driver");
+MODULE_AUTHOR("Michal Hajduk <michal.hajduk@diasemi.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h
new file mode 100644
index 000000000000..c8ce5475de22
--- /dev/null
+++ b/sound/soc/codecs/da732x.h
@@ -0,0 +1,133 @@
+/*
+ * da732x.h -- Dialog DA732X ALSA SoC Audio Driver Header File
+ *
+ * Copyright (C) 2012 Dialog Semiconductor GmbH
+ *
+ * Author: Michal Hajduk <Michal.Hajduk@diasemi.com>
+ *
+ * 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.
+ */
+
+#ifndef __DA732X_H_
+#define __DA732X_H
+
+#include <sound/soc.h>
+
+/* General */
+#define	DA732X_U8_MASK			0xFF
+#define	DA732X_4BYTES			4
+#define	DA732X_3BYTES			3
+#define	DA732X_2BYTES			2
+#define	DA732X_1BYTE			1
+#define	DA732X_1BYTE_SHIFT		8
+#define	DA732X_2BYTES_SHIFT		16
+#define	DA732X_3BYTES_SHIFT		24
+#define	DA732X_4BYTES_SHIFT		32
+
+#define	DA732X_DACS_DIS			0x0
+#define	DA732X_HP_DIS			0x0
+#define	DA732X_CLEAR_REG		0x0
+
+/* Calibration */
+#define	DA732X_DAC_OFFSET_STEP		0x20
+#define	DA732X_OUTPUT_OFFSET_STEP	0x80
+#define	DA732X_HP_OUT_TRIM_VAL		0x0
+#define	DA732X_WAIT_FOR_STABILIZATION	1
+#define	DA732X_HPL_DAC			0
+#define	DA732X_HPR_DAC			1
+#define	DA732X_HP_DACS			2
+#define	DA732X_HPL_AMP			0
+#define	DA732X_HPR_AMP			1
+#define	DA732X_HP_AMPS			2
+
+/* Clock settings */
+#define DA732X_STARTUP_DELAY		100
+#define	DA732X_PLL_OUT_196608		196608000
+#define	DA732X_PLL_OUT_180634		180633600
+#define	DA732X_PLL_OUT_SRM		188620800
+#define	DA732X_MCLK_10MHZ		10000000
+#define	DA732X_MCLK_20MHZ		20000000
+#define	DA732X_MCLK_40MHZ		40000000
+#define	DA732X_MCLK_54MHZ		54000000
+#define	DA732X_MCLK_RET_0_10MHZ		0
+#define	DA732X_MCLK_VAL_0_10MHZ		1
+#define	DA732X_MCLK_RET_10_20MHZ	1
+#define	DA732X_MCLK_VAL_10_20MHZ	2
+#define	DA732X_MCLK_RET_20_40MHZ	2
+#define	DA732X_MCLK_VAL_20_40MHZ	4
+#define	DA732X_MCLK_RET_40_54MHZ	3
+#define	DA732X_MCLK_VAL_40_54MHZ	8
+#define	DA732X_DAI_ID1			0
+#define	DA732X_DAI_ID2			1
+#define	DA732X_SRCCLK_PLL		0
+#define	DA732X_SRCCLK_MCLK		1
+
+#define	DA732X_LIN_LP_VOL		0x4F
+#define	DA732X_LP_VOL			0x40
+
+/* Kcontrols */
+#define	DA732X_DAC_EN_MAX		2
+#define	DA732X_ADCL_MUX_MAX		2
+#define	DA732X_ADCR_MUX_MAX		3
+#define	DA732X_HPF_MODE_MAX		3
+#define	DA732X_HPF_MODE_SHIFT		4
+#define	DA732X_HPF_MUSIC_SHIFT		0
+#define	DA732X_HPF_MUSIC_MAX		4
+#define	DA732X_HPF_VOICE_SHIFT		4
+#define	DA732X_HPF_VOICE_MAX		8
+#define	DA732X_EQ_EN_MAX		1
+#define	DA732X_HPF_VOICE		1
+#define	DA732X_HPF_MUSIC		2
+#define	DA732X_HPF_DISABLED		0
+#define	DA732X_NO_INVERT		0
+#define	DA732X_INVERT			1
+#define	DA732X_SWITCH_MAX		1
+#define	DA732X_ENABLE_CP		1
+#define	DA732X_DISABLE_CP		0
+#define	DA732X_DISABLE_ALL_CLKS		0
+#define	DA732X_RESET_ADCS		0
+
+/* dB values */
+#define DA732X_MIC_VOL_DB_MIN		0
+#define DA732X_MIC_VOL_DB_INC		50
+#define DA732X_MIC_PRE_VOL_DB_MIN	0
+#define DA732X_MIC_PRE_VOL_DB_INC	600
+#define DA732X_AUX_VOL_DB_MIN		-6000
+#define DA732X_AUX_VOL_DB_INC		150
+#define DA732X_HP_VOL_DB_MIN		-2250
+#define DA732X_HP_VOL_DB_INC		150
+#define	DA732X_LIN2_VOL_DB_MIN		-1650
+#define	DA732X_LIN2_VOL_DB_INC		150
+#define	DA732X_LIN3_VOL_DB_MIN		-1650
+#define DA732X_LIN3_VOL_DB_INC		150
+#define	DA732X_LIN4_VOL_DB_MIN		-2250
+#define DA732X_LIN4_VOL_DB_INC		150
+#define	DA732X_EQ_BAND_VOL_DB_MIN	-1050
+#define	DA732X_EQ_BAND_VOL_DB_INC	150
+#define DA732X_DAC_VOL_DB_MIN		-7725
+#define DA732X_DAC_VOL_DB_INC		75
+#define DA732X_ADC_VOL_DB_MIN		0
+#define DA732X_ADC_VOL_DB_INC		-1
+#define	DA732X_EQ_OVERALL_VOL_DB_MIN	-1800
+#define	DA732X_EQ_OVERALL_VOL_DB_INC	600
+
+#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \
+	{.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext}
+
+enum da732x_sysctl {
+	DA732X_SR_8KHZ		= 0x1,
+	DA732X_SR_11_025KHZ	= 0x2,
+	DA732X_SR_12KHZ		= 0x3,
+	DA732X_SR_16KHZ		= 0x5,
+	DA732X_SR_22_05KHZ	= 0x6,
+	DA732X_SR_24KHZ		= 0x7,
+	DA732X_SR_32KHZ		= 0x9,
+	DA732X_SR_44_1KHZ	= 0xA,
+	DA732X_SR_48KHZ		= 0xB,
+	DA732X_SR_88_1KHZ	= 0xE,
+	DA732X_SR_96KHZ		= 0xF,
+};
+
+#endif /* __DA732X_H_ */
diff --git a/sound/soc/codecs/da732x_reg.h b/sound/soc/codecs/da732x_reg.h
new file mode 100644
index 000000000000..bdd03ca4b2de
--- /dev/null
+++ b/sound/soc/codecs/da732x_reg.h
@@ -0,0 +1,654 @@
+/*
+ * da732x_reg.h --- Dialog DA732X ALSA SoC Audio Registers Header File
+ *
+ * Copyright (C) 2012 Dialog Semiconductor GmbH
+ *
+ * Author: Michal Hajduk <Michal.Hajduk@diasemi.com>
+ *
+ * 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.
+ */
+
+#ifndef __DA732X_REG_H_
+#define __DA732X_REG_H_
+
+/* DA732X registers */
+#define	DA732X_REG_STATUS_EXT		0x00
+#define DA732X_REG_STATUS		0x01
+#define DA732X_REG_REF1			0x02
+#define DA732X_REG_BIAS_EN		0x03
+#define DA732X_REG_BIAS1		0x04
+#define DA732X_REG_BIAS2		0x05
+#define DA732X_REG_BIAS3		0x06
+#define DA732X_REG_BIAS4		0x07
+#define DA732X_REG_MICBIAS2		0x0F
+#define DA732X_REG_MICBIAS1		0x10
+#define DA732X_REG_MICDET		0x11
+#define DA732X_REG_MIC1_PRE		0x12
+#define DA732X_REG_MIC1			0x13
+#define DA732X_REG_MIC2_PRE		0x14
+#define DA732X_REG_MIC2			0x15
+#define DA732X_REG_AUX1L		0x16
+#define DA732X_REG_AUX1R		0x17
+#define DA732X_REG_MIC3_PRE		0x18
+#define DA732X_REG_MIC3			0x19
+#define DA732X_REG_INP_PINBIAS		0x1A
+#define DA732X_REG_INP_ZC_EN		0x1B
+#define DA732X_REG_INP_MUX		0x1D
+#define DA732X_REG_HP_DET		0x20
+#define DA732X_REG_HPL_DAC_OFFSET	0x21
+#define DA732X_REG_HPL_DAC_OFF_CNTL	0x22
+#define DA732X_REG_HPL_OUT_OFFSET	0x23
+#define DA732X_REG_HPL			0x24
+#define DA732X_REG_HPL_VOL		0x25
+#define DA732X_REG_HPR_DAC_OFFSET	0x26
+#define DA732X_REG_HPR_DAC_OFF_CNTL	0x27
+#define DA732X_REG_HPR_OUT_OFFSET	0x28
+#define DA732X_REG_HPR			0x29
+#define DA732X_REG_HPR_VOL		0x2A
+#define DA732X_REG_LIN2			0x2B
+#define DA732X_REG_LIN3			0x2C
+#define DA732X_REG_LIN4			0x2D
+#define DA732X_REG_OUT_ZC_EN		0x2E
+#define DA732X_REG_HP_LIN1_GNDSEL	0x37
+#define DA732X_REG_CP_HP1		0x3A
+#define DA732X_REG_CP_HP2		0x3B
+#define DA732X_REG_CP_CTRL1		0x40
+#define DA732X_REG_CP_CTRL2		0x41
+#define DA732X_REG_CP_CTRL3		0x42
+#define DA732X_REG_CP_LEVEL_MASK	0x43
+#define DA732X_REG_CP_DET		0x44
+#define DA732X_REG_CP_STATUS		0x45
+#define DA732X_REG_CP_THRESH1		0x46
+#define DA732X_REG_CP_THRESH2		0x47
+#define DA732X_REG_CP_THRESH3		0x48
+#define DA732X_REG_CP_THRESH4		0x49
+#define DA732X_REG_CP_THRESH5		0x4A
+#define DA732X_REG_CP_THRESH6		0x4B
+#define DA732X_REG_CP_THRESH7		0x4C
+#define DA732X_REG_CP_THRESH8		0x4D
+#define DA732X_REG_PLL_DIV_LO		0x50
+#define DA732X_REG_PLL_DIV_MID		0x51
+#define DA732X_REG_PLL_DIV_HI		0x52
+#define DA732X_REG_PLL_CTRL		0x53
+#define DA732X_REG_CLK_CTRL		0x54
+#define DA732X_REG_CLK_DSP		0x5A
+#define DA732X_REG_CLK_EN1		0x5B
+#define DA732X_REG_CLK_EN2		0x5C
+#define DA732X_REG_CLK_EN3		0x5D
+#define DA732X_REG_CLK_EN4		0x5E
+#define DA732X_REG_CLK_EN5		0x5F
+#define DA732X_REG_AIF_MCLK		0x60
+#define DA732X_REG_AIFA1		0x61
+#define DA732X_REG_AIFA2		0x62
+#define DA732X_REG_AIFA3		0x63
+#define DA732X_REG_AIFB1		0x64
+#define DA732X_REG_AIFB2		0x65
+#define DA732X_REG_AIFB3		0x66
+#define DA732X_REG_PC_CTRL		0x6A
+#define DA732X_REG_DATA_ROUTE		0x70
+#define DA732X_REG_DSP_CTRL		0x71
+#define DA732X_REG_CIF_CTRL2		0x74
+#define DA732X_REG_HANDSHAKE		0x75
+#define DA732X_REG_MBOX0		0x76
+#define DA732X_REG_MBOX1		0x77
+#define DA732X_REG_MBOX2		0x78
+#define DA732X_REG_MBOX_STATUS		0x79
+#define DA732X_REG_SPARE1_OUT		0x7D
+#define DA732X_REG_SPARE2_OUT		0x7E
+#define DA732X_REG_SPARE1_IN		0x7F
+#define DA732X_REG_ID			0x81
+#define DA732X_REG_ADC1_PD		0x90
+#define DA732X_REG_ADC1_HPF		0x93
+#define DA732X_REG_ADC1_SEL		0x94
+#define DA732X_REG_ADC1_EQ12		0x95
+#define DA732X_REG_ADC1_EQ34		0x96
+#define DA732X_REG_ADC1_EQ5		0x97
+#define DA732X_REG_ADC2_PD		0x98
+#define DA732X_REG_ADC2_HPF		0x9B
+#define DA732X_REG_ADC2_SEL		0x9C
+#define DA732X_REG_ADC2_EQ12		0x9D
+#define DA732X_REG_ADC2_EQ34		0x9E
+#define DA732X_REG_ADC2_EQ5		0x9F
+#define DA732X_REG_DAC1_HPF		0xA0
+#define DA732X_REG_DAC1_L_VOL		0xA1
+#define DA732X_REG_DAC1_R_VOL		0xA2
+#define DA732X_REG_DAC1_SEL		0xA3
+#define DA732X_REG_DAC1_SOFTMUTE	0xA4
+#define DA732X_REG_DAC1_EQ12		0xA5
+#define DA732X_REG_DAC1_EQ34		0xA6
+#define DA732X_REG_DAC1_EQ5		0xA7
+#define DA732X_REG_DAC2_HPF		0xB0
+#define DA732X_REG_DAC2_L_VOL		0xB1
+#define DA732X_REG_DAC2_R_VOL		0xB2
+#define DA732X_REG_DAC2_SEL		0xB3
+#define DA732X_REG_DAC2_SOFTMUTE	0xB4
+#define DA732X_REG_DAC2_EQ12		0xB5
+#define DA732X_REG_DAC2_EQ34		0xB6
+#define DA732X_REG_DAC2_EQ5		0xB7
+#define DA732X_REG_DAC3_HPF		0xC0
+#define DA732X_REG_DAC3_VOL		0xC1
+#define DA732X_REG_DAC3_SEL		0xC3
+#define DA732X_REG_DAC3_SOFTMUTE	0xC4
+#define DA732X_REG_DAC3_EQ12		0xC5
+#define DA732X_REG_DAC3_EQ34		0xC6
+#define DA732X_REG_DAC3_EQ5		0xC7
+#define DA732X_REG_BIQ_BYP		0xD2
+#define DA732X_REG_DMA_CMD		0xD3
+#define DA732X_REG_DMA_ADDR0		0xD4
+#define DA732X_REG_DMA_ADDR1		0xD5
+#define DA732X_REG_DMA_DATA0		0xD6
+#define DA732X_REG_DMA_DATA1		0xD7
+#define DA732X_REG_DMA_DATA2		0xD8
+#define DA732X_REG_DMA_DATA3		0xD9
+#define DA732X_REG_DMA_STATUS		0xDA
+#define DA732X_REG_BROWNOUT		0xDF
+#define DA732X_REG_UNLOCK		0xE0
+
+#define	DA732X_MAX_REG			DA732X_REG_UNLOCK
+/*
+ * Bits
+ */
+
+/* DA732X_REG_STATUS_EXT (addr=0x00) */
+#define	DA732X_STATUS_EXT_DSP			(1 << 4)
+#define	DA732X_STATUS_EXT_CLEAR			(0 << 0)
+
+/* DA732X_REG_STATUS	(addr=0x01) */
+#define DA732X_STATUS_PLL_LOCK			(1 << 0)
+#define DA732X_STATUS_PLL_MCLK_DET		(1 << 1)
+#define DA732X_STATUS_HPDET_OUT			(1 << 2)
+#define DA732X_STATUS_INP_MIXDET_1		(1 << 3)
+#define DA732X_STATUS_INP_MIXDET_2		(1 << 4)
+#define DA732X_STATUS_BO_STATUS			(1 << 5)
+
+/* DA732X_REG_REF1	(addr=0x02) */
+#define DA732X_VMID_FASTCHG			(1 << 1)
+#define DA732X_VMID_FASTDISCHG			(1 << 2)
+#define DA732X_REFBUFX2_EN			(1 << 6)
+#define DA732X_REFBUFX2_DIS			(0 << 6)
+
+/* DA732X_REG_BIAS_EN	(addr=0x03) */
+#define DA732X_BIAS_BOOST_MASK			(3 << 0)
+#define DA732X_BIAS_BOOST_100PC			(0 << 0)
+#define DA732X_BIAS_BOOST_133PC			(1 << 0)
+#define DA732X_BIAS_BOOST_88PC			(2 << 0)
+#define DA732X_BIAS_BOOST_50PC			(3 << 0)
+#define DA732X_BIAS_EN				(1 << 7)
+#define DA732X_BIAS_DIS				(0 << 7)
+
+/* DA732X_REG_BIAS1	(addr=0x04) */
+#define DA732X_BIAS1_HP_DAC_BIAS_MASK		(3 << 0)
+#define DA732X_BIAS1_HP_DAC_BIAS_100PC		(0 << 0)
+#define DA732X_BIAS1_HP_DAC_BIAS_150PC		(1 << 0)
+#define DA732X_BIAS1_HP_DAC_BIAS_50PC		(2 << 0)
+#define DA732X_BIAS1_HP_DAC_BIAS_75PC		(3 << 0)
+#define DA732X_BIAS1_HP_OUT_BIAS_MASK		(7 << 4)
+#define DA732X_BIAS1_HP_OUT_BIAS_100PC		(0 << 4)
+#define DA732X_BIAS1_HP_OUT_BIAS_125PC		(1 << 4)
+#define DA732X_BIAS1_HP_OUT_BIAS_150PC		(2 << 4)
+#define DA732X_BIAS1_HP_OUT_BIAS_175PC		(3 << 4)
+#define DA732X_BIAS1_HP_OUT_BIAS_200PC		(4 << 4)
+#define DA732X_BIAS1_HP_OUT_BIAS_250PC		(5 << 4)
+#define DA732X_BIAS1_HP_OUT_BIAS_300PC		(6 << 4)
+#define DA732X_BIAS1_HP_OUT_BIAS_350PC		(7 << 4)
+
+/* DA732X_REG_BIAS2	(addr=0x05) */
+#define DA732X_BIAS2_LINE2_DAC_BIAS_MASK	(3 << 0)
+#define DA732X_BIAS2_LINE2_DAC_BIAS_100PC	(0 << 0)
+#define DA732X_BIAS2_LINE2_DAC_BIAS_150PC	(1 << 0)
+#define DA732X_BIAS2_LINE2_DAC_BIAS_50PC	(2 << 0)
+#define DA732X_BIAS2_LINE2_DAC_BIAS_75PC	(3 << 0)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_MASK	(7 << 4)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_100PC	(0 << 4)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_125PC	(1 << 4)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_150PC	(2 << 4)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_175PC	(3 << 4)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_200PC	(4 << 4)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_250PC	(5 << 4)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_300PC	(6 << 4)
+#define DA732X_BIAS2_LINE2_OUT_BIAS_350PC	(7 << 4)
+
+/* DA732X_REG_BIAS3	(addr=0x06) */
+#define DA732X_BIAS3_LINE3_DAC_BIAS_MASK	(3 << 0)
+#define DA732X_BIAS3_LINE3_DAC_BIAS_100PC	(0 << 0)
+#define DA732X_BIAS3_LINE3_DAC_BIAS_150PC	(1 << 0)
+#define DA732X_BIAS3_LINE3_DAC_BIAS_50PC	(2 << 0)
+#define DA732X_BIAS3_LINE3_DAC_BIAS_75PC	(3 << 0)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_MASK	(7 << 4)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_100PC	(0 << 4)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_125PC	(1 << 4)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_150PC	(2 << 4)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_175PC	(3 << 4)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_200PC	(4 << 4)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_250PC	(5 << 4)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_300PC	(6 << 4)
+#define DA732X_BIAS3_LINE3_OUT_BIAS_350PC	(7 << 4)
+
+/* DA732X_REG_BIAS4	(addr=0x07) */
+#define DA732X_BIAS4_LINE4_DAC_BIAS_MASK	(3 << 0)
+#define DA732X_BIAS4_LINE4_DAC_BIAS_100PC	(0 << 0)
+#define DA732X_BIAS4_LINE4_DAC_BIAS_150PC	(1 << 0)
+#define DA732X_BIAS4_LINE4_DAC_BIAS_50PC	(2 << 0)
+#define DA732X_BIAS4_LINE4_DAC_BIAS_75PC	(3 << 0)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_MASK	(7 << 4)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_100PC	(0 << 4)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_125PC	(1 << 4)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_150PC	(2 << 4)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_175PC	(3 << 4)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_200PC	(4 << 4)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_250PC	(5 << 4)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_300PC	(6 << 4)
+#define DA732X_BIAS4_LINE4_OUT_BIAS_350PC	(7 << 4)
+
+/* DA732X_REG_SIF_VDD_SEL	(addr=0x08) */
+#define DA732X_SIF_VDD_SEL_AIFA_VDD2		(1 << 0)
+#define DA732X_SIF_VDD_SEL_AIFB_VDD2		(1 << 1)
+#define DA732X_SIF_VDD_SEL_CIFA_VDD2		(1 << 4)
+
+/* DA732X_REG_MICBIAS2/1	(addr=0x0F/0x10) */
+#define DA732X_MICBIAS_VOLTAGE_MASK		(0x0F << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V		(0x00 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V05		(0x01 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V1		(0x02 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V15		(0x03 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V2		(0x04 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V25		(0x05 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V3		(0x06 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V35		(0x07 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V4		(0x08 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V45		(0x09 << 0)
+#define DA732X_MICBIAS_VOLTAGE_2V5		(0x0A << 0)
+#define DA732X_MICBIAS_EN			(1 << 7)
+#define DA732X_MICBIAS_EN_SHIFT			7
+#define DA732X_MICBIAS_VOLTAGE_SHIFT		0
+#define	DA732X_MICBIAS_VOLTAGE_MAX		0x0B
+
+/* DA732X_REG_MICDET	(addr=0x11) */
+#define DA732X_MICDET_INP_MICRES		(1 << 0)
+#define DA732X_MICDET_INP_MICHOOK		(1 << 1)
+#define DA732X_MICDET_INP_DEBOUNCE_PRD_8MS	(0 << 0)
+#define DA732X_MICDET_INP_DEBOUNCE_PRD_16MS	(1 << 0)
+#define DA732X_MICDET_INP_DEBOUNCE_PRD_32MS	(2 << 0)
+#define DA732X_MICDET_INP_DEBOUNCE_PRD_64MS	(3 << 0)
+#define DA732X_MICDET_INP_MICDET_EN		(1 << 7)
+
+/* DA732X_REG_MIC1/2/3_PRE (addr=0x11/0x14/0x18) */
+#define	DA732X_MICBOOST_MASK			0x7
+#define	DA732X_MICBOOST_SHIFT			0
+#define	DA732X_MICBOOST_MIN			0x1
+#define	DA732X_MICBOOST_MAX			DA732X_MICBOOST_MASK
+
+/* DA732X_REG_MIC1/2/3	(addr=0x13/0x15/0x19) */
+#define	DA732X_MIC_VOL_SHIFT			0
+#define	DA732X_MIC_VOL_VAL_MASK			0x1F
+#define DA732X_MIC_MUTE_SHIFT			6
+#define DA732X_MIC_EN_SHIFT			7
+#define DA732X_MIC_VOL_VAL_MIN			0x7
+#define	DA732X_MIC_VOL_VAL_MAX			DA732X_MIC_VOL_VAL_MASK
+
+/* DA732X_REG_AUX1L/R	(addr=0x16/0x17) */
+#define	DA732X_AUX_VOL_SHIFT			0
+#define	DA732X_AUX_VOL_MASK			0x7
+#define DA732X_AUX_MUTE_SHIFT			6
+#define DA732X_AUX_EN_SHIFT			7
+#define	DA732X_AUX_VOL_VAL_MAX			DA732X_AUX_VOL_MASK
+
+/* DA732X_REG_INP_PINBIAS	(addr=0x1A) */
+#define DA732X_INP_MICL_PINBIAS_EN		(1 << 0)
+#define DA732X_INP_MICR_PINBIAS_EN		(1 << 1)
+#define DA732X_INP_AUX1L_PINBIAS_EN		(1 << 2)
+#define DA732X_INP_AUX1R_PINBIAS_EN		(1 << 3)
+#define DA732X_INP_AUX2_PINBIAS_EN		(1 << 4)
+
+/* DA732X_REG_INP_ZC_EN	(addr=0x1B) */
+#define	DA732X_MIC1_PRE_ZC_EN			(1 << 0)
+#define	DA732X_MIC1_ZC_EN			(1 << 1)
+#define	DA732X_MIC2_PRE_ZC_EN			(1 << 2)
+#define	DA732X_MIC2_ZC_EN			(1 << 3)
+#define	DA732X_AUXL_ZC_EN			(1 << 4)
+#define	DA732X_AUXR_ZC_EN			(1 << 5)
+#define	DA732X_MIC3_PRE_ZC_EN			(1 << 6)
+#define	DA732X_MIC3_ZC_EN			(1 << 7)
+
+/* DA732X_REG_INP_MUX	(addr=0x1D) */
+#define DA732X_INP_ADC1L_MUX_SEL_AUX1L		(0 << 0)
+#define DA732X_INP_ADC1L_MUX_SEL_MIC1		(1 << 0)
+#define DA732X_INP_ADC1R_MUX_SEL_MASK		(3 << 2)
+#define DA732X_INP_ADC1R_MUX_SEL_AUX1R		(0 << 2)
+#define DA732X_INP_ADC1R_MUX_SEL_MIC2		(1 << 2)
+#define DA732X_INP_ADC1R_MUX_SEL_MIC3		(2 << 2)
+#define DA732X_INP_ADC2L_MUX_SEL_AUX1L		(0 << 4)
+#define DA732X_INP_ADC2L_MUX_SEL_MICL		(1 << 4)
+#define DA732X_INP_ADC2R_MUX_SEL_MASK		(3 << 6)
+#define DA732X_INP_ADC2R_MUX_SEL_AUX1R		(0 << 6)
+#define DA732X_INP_ADC2R_MUX_SEL_MICR		(1 << 6)
+#define DA732X_INP_ADC2R_MUX_SEL_AUX2		(2 << 6)
+#define	DA732X_ADC1L_MUX_SEL_SHIFT		0
+#define	DA732X_ADC1R_MUX_SEL_SHIFT		2
+#define	DA732X_ADC2L_MUX_SEL_SHIFT		4
+#define	DA732X_ADC2R_MUX_SEL_SHIFT		6
+
+/* DA732X_REG_HP_DET		(addr=0x20) */
+#define DA732X_HP_DET_AZ			(1 << 0)
+#define DA732X_HP_DET_SEL1			(1 << 1)
+#define DA732X_HP_DET_IS_MASK			(3 << 2)
+#define DA732X_HP_DET_IS_0_5UA			(0 << 2)
+#define DA732X_HP_DET_IS_1UA			(1 << 2)
+#define DA732X_HP_DET_IS_2UA			(2 << 2)
+#define DA732X_HP_DET_IS_4UA			(3 << 2)
+#define DA732X_HP_DET_RS_MASK			(3 << 4)
+#define DA732X_HP_DET_RS_INFINITE		(0 << 4)
+#define DA732X_HP_DET_RS_100KOHM		(1 << 4)
+#define DA732X_HP_DET_RS_10KOHM			(2 << 4)
+#define DA732X_HP_DET_RS_1KOHM			(3 << 4)
+#define DA732X_HP_DET_EN			(1 << 7)
+
+/* DA732X_REG_HPL_DAC_OFFSET	(addr=0x21/0x26) */
+#define DA732X_HP_DAC_OFFSET_TRIM_MASK		(0x3F << 0)
+#define DA732X_HP_DAC_OFFSET_DAC_SIGN		(1 << 6)
+
+/* DA732X_REG_HPL_DAC_OFF_CNTL	(addr=0x22/0x27) */
+#define DA732X_HP_DAC_OFF_CNTL_CONT_MASK	(7 << 0)
+#define DA732X_HP_DAC_OFF_CNTL_COMPO		(1 << 3)
+#define	DA732X_HP_DAC_OFF_CALIBRATION		(1 << 0)
+#define	DA732X_HP_DAC_OFF_SCALE_STEPS		(1 << 1)
+#define	DA732X_HP_DAC_OFF_MASK			0x7F
+#define DA732X_HP_DAC_COMPO_SHIFT		3
+
+/* DA732X_REG_HPL_OUT_OFFSET	(addr=0x23/0x28) */
+#define DA732X_HP_OUT_OFFSET_MASK		(0xFF << 0)
+#define	DA732X_HP_DAC_OFFSET_TRIM_VAL		0x7F
+
+/* DA732X_REG_HPL/R	(addr=0x24/0x29) */
+#define DA732X_HP_OUT_SIGN			(1 << 0)
+#define DA732X_HP_OUT_COMP			(1 << 1)
+#define DA732X_HP_OUT_RESERVED			(1 << 2)
+#define DA732X_HP_OUT_COMPO			(1 << 3)
+#define DA732X_HP_OUT_DAC_EN			(1 << 4)
+#define DA732X_HP_OUT_HIZ_EN			(1 << 5)
+#define	DA732X_HP_OUT_HIZ_DIS			(0 << 5)
+#define DA732X_HP_OUT_MUTE			(1 << 6)
+#define DA732X_HP_OUT_EN			(1 << 7)
+#define	DA732X_HP_OUT_COMPO_SHIFT		3
+#define	DA732X_HP_OUT_DAC_EN_SHIFT		4
+#define	DA732X_HP_HIZ_SHIFT			5
+#define	DA732X_HP_MUTE_SHIFT			6
+#define DA732X_HP_OUT_EN_SHIFT			7
+
+#define DA732X_OUT_HIZ_EN			(1 << 5)
+#define	DA732X_OUT_HIZ_DIS			(0 << 5)
+
+/* DA732X_REG_HPL/R_VOL	(addr=0x25/0x2A) */
+#define	DA732X_HP_VOL_VAL_MASK			0xF
+#define	DA732X_HP_VOL_SHIFT			0
+#define	DA732X_HP_VOL_VAL_MAX			DA732X_HP_VOL_VAL_MASK
+
+/* DA732X_REG_LIN2/3/4	(addr=0x2B/0x2C/0x2D) */
+#define DA732X_LOUT_VOL_SHIFT			0
+#define DA732X_LOUT_VOL_MASK			0x0F
+#define DA732X_LOUT_DAC_OFF			(0 << 4)
+#define DA732X_LOUT_DAC_EN			(1 << 4)
+#define DA732X_LOUT_HIZ_N_DIS			(0 << 5)
+#define DA732X_LOUT_HIZ_N_EN			(1 << 5)
+#define DA732X_LOUT_UNMUTED			(0 << 6)
+#define DA732X_LOUT_MUTED			(1 << 6)
+#define DA732X_LOUT_EN				(0 << 7)
+#define DA732X_LOUT_DIS				(1 << 7)
+#define DA732X_LOUT_DAC_EN_SHIFT		4
+#define	DA732X_LOUT_MUTE_SHIFT			6
+#define DA732X_LIN_OUT_EN_SHIFT			7
+#define DA732X_LOUT_VOL_VAL_MAX			DA732X_LOUT_VOL_MASK
+
+/* DA732X_REG_OUT_ZC_EN		(addr=0x2E) */
+#define	DA732X_HPL_ZC_EN_SHIFT			0
+#define DA732X_HPR_ZC_EN_SHIFT			1
+#define DA732X_HPL_ZC_EN			(1 << 0)
+#define DA732X_HPL_ZC_DIS			(0 << 0)
+#define DA732X_HPR_ZC_EN			(1 << 1)
+#define DA732X_HPR_ZC_DIS			(0 << 1)
+#define DA732X_LIN2_ZC_EN			(1 << 2)
+#define DA732X_LIN2_ZC_DIS			(0 << 2)
+#define DA732X_LIN3_ZC_EN			(1 << 3)
+#define DA732X_LIN3_ZC_DIS			(0 << 3)
+#define DA732X_LIN4_ZC_EN			(1 << 4)
+#define DA732X_LIN4_ZC_DIS			(0 << 4)
+
+/* DA732X_REG_HP_LIN1_GNDSEL (addr=0x37) */
+#define	DA732X_HP_OUT_GNDSEL			(1 << 0)
+
+/* DA732X_REG_CP_HP2 (addr=0x3a) */
+#define	DA732X_HP_CP_PULSESKIP			(1 << 0)
+#define	DA732X_HP_CP_REG			(1 << 1)
+#define DA732X_HP_CP_EN				(1 << 3)
+#define DA732X_HP_CP_DIS			(0 << 3)
+
+/* DA732X_REG_CP_CTRL1 (addr=0x40) */
+#define	DA732X_CP_MODE_MASK			(7 << 1)
+#define	DA732X_CP_CTRL_STANDBY			(0 << 1)
+#define	DA732X_CP_CTRL_CPVDD6			(2 << 1)
+#define	DA732X_CP_CTRL_CPVDD5			(3 << 1)
+#define	DA732X_CP_CTRL_CPVDD4			(4 << 1)
+#define	DA732X_CP_CTRL_CPVDD3			(5 << 1)
+#define	DA732X_CP_CTRL_CPVDD2			(6 << 1)
+#define	DA732X_CP_CTRL_CPVDD1			(7 << 1)
+#define	DA723X_CP_DIS				(0 << 7)
+#define	DA732X_CP_EN				(1 << 7)
+
+/* DA732X_REG_CP_CTRL2 (addr=0x41) */
+#define	DA732X_CP_BOOST				(1 << 0)
+#define	DA732X_CP_MANAGE_MAGNITUDE		(2 << 2)
+
+/* DA732X_REG_CP_CTRL3 (addr=0x42) */
+#define	DA732X_CP_1MHZ				(0 << 0)
+#define	DA732X_CP_500KHZ			(1 << 0)
+#define	DA732X_CP_250KHZ			(2 << 0)
+#define	DA732X_CP_125KHZ			(3 << 0)
+#define	DA732X_CP_63KHZ				(4 << 0)
+#define	DA732X_CP_0KHZ				(5 << 0)
+
+/* DA732X_REG_PLL_CTRL (addr=0x53) */
+#define	DA732X_PLL_INDIV_MASK			(3 << 0)
+#define	DA732X_PLL_SRM_EN			(1 << 2)
+#define	DA732X_PLL_EN				(1 << 7)
+#define	DA732X_PLL_BYPASS			(0 << 0)
+
+/* DA732X_REG_CLK_CTRL (addr=0x54) */
+#define	DA732X_SR1_MASK				(0xF)
+#define	DA732X_SR2_MASK				(0xF0)
+
+/* DA732X_REG_CLK_DSP (addr=0x5A) */
+#define	DA732X_DSP_FREQ_MASK			(7 << 0)
+#define	DA732X_DSP_FREQ_12MHZ			(0 << 0)
+#define	DA732X_DSP_FREQ_24MHZ			(1 << 0)
+#define	DA732X_DSP_FREQ_36MHZ			(2 << 0)
+#define	DA732X_DSP_FREQ_48MHZ			(3 << 0)
+#define	DA732X_DSP_FREQ_60MHZ			(4 << 0)
+#define	DA732X_DSP_FREQ_72MHZ			(5 << 0)
+#define	DA732X_DSP_FREQ_84MHZ			(6 << 0)
+#define	DA732X_DSP_FREQ_96MHZ			(7 << 0)
+
+/* DA732X_REG_CLK_EN1 (addr=0x5B) */
+#define	DA732X_DSP_CLK_EN			(1 << 0)
+#define	DA732X_SYS3_CLK_EN			(1 << 1)
+#define	DA732X_DSP12_CLK_EN			(1 << 2)
+#define	DA732X_PC_CLK_EN			(1 << 3)
+#define	DA732X_MCLK_SQR_EN			(1 << 7)
+
+/* DA732X_REG_CLK_EN2 (addr=0x5C) */
+#define	DA732X_UART_CLK_EN			(1 << 1)
+#define	DA732X_CP_CLK_EN			(1 << 2)
+#define	DA732X_CP_CLK_DIS			(0 << 2)
+
+/* DA732X_REG_CLK_EN3 (addr=0x5D) */
+#define	DA732X_ADCA_BB_CLK_EN			(1 << 0)
+#define	DA732X_ADCC_BB_CLK_EN			(1 << 4)
+
+/* DA732X_REG_CLK_EN4 (addr=0x5E) */
+#define	DA732X_DACA_BB_CLK_EN			(1 << 0)
+#define	DA732X_DACC_BB_CLK_EN			(1 << 4)
+#define DA732X_DACA_BB_CLK_SHIFT		0
+#define DA732X_DACC_BB_CLK_SHIFT		4
+
+/* DA732X_REG_CLK_EN5 (addr=0x5F) */
+#define	DA732X_DACE_BB_CLK_EN			(1 << 0)
+#define DA732X_DACE_BB_CLK_SHIFT		0
+
+/* DA732X_REG_AIF_MCLK (addr=0x60) */
+#define DA732X_AIFM_FRAME_64			(1 << 2)
+#define	DA732X_AIFM_SRC_SEL_AIFA		(1 << 6)
+#define	DA732X_CLK_GENERATION_AIF_A		(1 << 4)
+#define	DA732X_NO_CLK_GENERATION		0x0
+
+/* DA732X_REG_AIFA1 (addr=0x61) */
+#define	DA732X_AIF_WORD_MASK			(0x3 << 0)
+#define	DA732X_AIF_WORD_16			(0 << 0)
+#define	DA732X_AIF_WORD_20			(1 << 0)
+#define	DA732X_AIF_WORD_24			(2 << 0)
+#define	DA732X_AIF_WORD_32			(3 << 0)
+#define	DA732X_AIF_TDM_MONO_SHIFT		(1 << 6)
+#define	DA732X_AIF1_CLK_MASK			(1 << 7)
+#define	DA732X_AIF_SLAVE			(0 << 7)
+#define DA732X_AIF_CLK_FROM_SRC			(1 << 7)
+
+/* DA732X_REG_AIFA3 (addr=0x63) */
+#define	DA732X_AIF_MODE_SHIFT			0
+#define	DA732X_AIF_MODE_MASK			0x3
+#define	DA732X_AIF_I2S_MODE			(0 << 0)
+#define	DA732X_AIF_LEFT_J_MODE			(1 << 0)
+#define	DA732X_AIF_RIGHT_J_MODE			(2 << 0)
+#define	DA732X_AIF_DSP_MODE			(3 << 0)
+#define DA732X_AIF_WCLK_INV			(1 << 4)
+#define DA732X_AIF_BCLK_INV			(1 << 5)
+#define	DA732X_AIF_EN				(1 << 7)
+#define	DA732X_AIF_EN_SHIFT			7
+
+/* DA732X_REG_PC_CTRL (addr=0x6a) */
+#define	DA732X_PC_PULSE_AIFA			(0 << 0)
+#define	DA732X_PC_PULSE_AIFB			(1 << 0)
+#define	DA732X_PC_RESYNC_AUT			(1 << 6)
+#define	DA732X_PC_RESYNC_NOT_AUT		(0 << 6)
+#define	DA732X_PC_SAME				(1 << 7)
+
+/* DA732X_REG_DATA_ROUTE (addr=0x70) */
+#define DA732X_ADC1_TO_AIFA			(0 << 0)
+#define DA732X_DSP_TO_AIFA			(1 << 0)
+#define DA732X_ADC2_TO_AIFB			(0 << 1)
+#define DA732X_DSP_TO_AIFB			(1 << 1)
+#define DA732X_AIFA_TO_DAC1L			(0 << 2)
+#define DA732X_DSP_TO_DAC1L			(1 << 2)
+#define DA732X_AIFA_TO_DAC1R			(0 << 3)
+#define DA732X_DSP_TO_DAC1R			(1 << 3)
+#define DA732X_AIFB_TO_DAC2L			(0 << 4)
+#define DA732X_DSP_TO_DAC2L			(1 << 4)
+#define DA732X_AIFB_TO_DAC2R			(0 << 5)
+#define DA732X_DSP_TO_DAC2R			(1 << 5)
+#define DA732X_AIFB_TO_DAC3			(0 << 6)
+#define DA732X_DSP_TO_DAC3			(1 << 6)
+#define	DA732X_BYPASS_DSP			(0 << 0)
+#define	DA732X_ALL_TO_DSP			(0x7F << 0)
+
+/* DA732X_REG_DSP_CTRL (addr=0x71) */
+#define	DA732X_DIGITAL_EN			(1 << 0)
+#define	DA732X_DIGITAL_RESET			(0 << 0)
+#define	DA732X_DSP_CORE_EN			(1 << 1)
+#define	DA732X_DSP_CORE_RESET			(0 << 1)
+
+/* DA732X_REG_SPARE1_OUT (addr=0x7D)*/
+#define	DA732X_HP_DRIVER_EN			(1 << 0)
+#define	DA732X_HP_GATE_LOW			(1 << 2)
+#define DA732X_HP_LOOP_GAIN_CTRL		(1 << 3)
+
+/* DA732X_REG_ID (addr=0x81)*/
+#define DA732X_ID_MINOR_MASK			(0xF << 0)
+#define DA732X_ID_MAJOR_MASK			(0xF << 4)
+
+/* DA732X_REG_ADC1/2_PD (addr=0x90/0x98) */
+#define	DA732X_ADC_RST_MASK			(0x3 << 0)
+#define	DA732X_ADC_PD_MASK			(0x3 << 2)
+#define	DA732X_ADC_SET_ACT			(0x3 << 0)
+#define	DA732X_ADC_SET_RST			(0x0 << 0)
+#define	DA732X_ADC_ON				(0x3 << 2)
+#define	DA732X_ADC_OFF				(0x0 << 2)
+
+/* DA732X_REG_ADC1/2_SEL (addr=0x94/0x9C) */
+#define	DA732X_ADC_VOL_VAL_MASK			0x7
+#define	DA732X_ADCL_VOL_SHIFT			0
+#define	DA732X_ADCR_VOL_SHIFT			4
+#define DA732X_ADCL_EN_SHIFT			2
+#define DA732X_ADCR_EN_SHIFT			3
+#define	DA732X_ADCL_EN				(1 << 2)
+#define	DA732X_ADCR_EN				(1 << 3)
+#define	DA732X_ADC_VOL_VAL_MAX			DA732X_ADC_VOL_VAL_MASK
+
+/*
+ * DA732X_REG_ADC1/2_HPF (addr=0x93/0x9b)
+ * DA732x_REG_DAC1/2/3_HPG	(addr=0xA5/0xB5/0xC5)
+ */
+#define	DA732X_HPF_MUSIC_EN			(1 << 3)
+#define	DA732X_HPF_VOICE_EN			((1 << 3) | (1 << 7))
+#define	DA732X_HPF_MASK				((1 << 3) | (1 << 7))
+#define DA732X_HPF_DIS				((0 << 3) | (0 << 7))
+
+/* DA732X_REG_DAC1/2/3_VOL */
+#define DA732X_DAC_VOL_VAL_MASK			0x7F
+#define DA732X_DAC_VOL_SHIFT			0
+#define DA732X_DAC_VOL_VAL_MAX			DA732X_DAC_VOL_VAL_MASK
+
+/* DA732X_REG_DAC1/2/3_SEL (addr=0xA3/0xB3/0xC3) */
+#define DA732X_DACL_EN_SHIFT			3
+#define	DA732X_DACR_EN_SHIFT			7
+#define DA732X_DACL_MUTE_SHIFT			2
+#define	DA732X_DACR_MUTE_SHIFT			6
+#define DA732X_DACL_EN				(1 << 3)
+#define	DA732X_DACR_EN				(1 << 7)
+#define	DA732X_DACL_SDM				(1 << 0)
+#define	DA732X_DACR_SDM				(1 << 4)
+#define	DA732X_DACL_MUTE			(1 << 2)
+#define	DA732X_DACR_MUTE			(1 << 6)
+
+/* DA732X_REG_DAC_SOFTMUTE (addr=0xA4/0xB4/0xC4) */
+#define	DA732X_SOFTMUTE_EN			(1 << 7)
+#define	DA732X_GAIN_RAMPED			(1 << 6)
+#define	DA732X_16_SAMPLES			(4 << 0)
+#define	DA732X_SOFTMUTE_MASK			(1 << 7)
+#define	DA732X_SOFTMUTE_SHIFT			7
+
+/*
+ * DA732x_REG_ADC1/2_EQ12	(addr=0x95/0x9D)
+ * DA732x_REG_ADC1/2_EQ34	(addr=0x96/0x9E)
+ * DA732x_REG_ADC1/2_EQ5	(addr=0x97/0x9F)
+ * DA732x_REG_DAC1/2/3_EQ12	(addr=0xA5/0xB5/0xC5)
+ * DA732x_REG_DAC1/2/3_EQ34	(addr=0xA6/0xB6/0xC6)
+ * DA732x_REG_DAC1/2/3_EQ5	(addr=0xA7/0xB7/0xB7)
+ */
+#define	DA732X_EQ_VOL_VAL_MASK			0xF
+#define	DA732X_EQ_BAND1_SHIFT			0
+#define	DA732X_EQ_BAND2_SHIFT			4
+#define	DA732X_EQ_BAND3_SHIFT			0
+#define	DA732X_EQ_BAND4_SHIFT			4
+#define	DA732X_EQ_BAND5_SHIFT			0
+#define	DA732X_EQ_OVERALL_SHIFT			4
+#define	DA732X_EQ_OVERALL_VOL_VAL_MASK		0x3
+#define	DA732X_EQ_DIS				(0 << 7)
+#define	DA732X_EQ_EN				(1 << 7)
+#define	DA732X_EQ_EN_SHIFT			7
+#define	DA732X_EQ_VOL_VAL_MAX			DA732X_EQ_VOL_VAL_MASK
+#define	DA732X_EQ_OVERALL_VOL_VAL_MAX		DA732X_EQ_OVERALL_VOL_VAL_MASK
+
+/* DA732X_REG_DMA_CMD (addr=0xD3) */
+#define	DA732X_SEL_DSP_DMA_MASK			(3 << 0)
+#define	DA732X_SEL_DSP_DMA_DIS			(0 << 0)
+#define	DA732X_SEL_DSP_DMA_PMEM			(1 << 0)
+#define	DA732X_SEL_DSP_DMA_XMEM			(2 << 0)
+#define	DA732X_SEL_DSP_DMA_YMEM			(3 << 0)
+#define	DA732X_DSP_RW_MASK			(1 << 4)
+#define	DA732X_DSP_DMA_WRITE			(0 << 4)
+#define	DA732X_DSP_DMA_READ			(1 << 4)
+
+/* DA732X_REG_DMA_STATUS (addr=0xDA) */
+#define	DA732X_DSP_DMA_FREE			(0 << 0)
+#define	DA732X_DSP_DMA_BUSY			(1 << 0)
+
+#endif /* __DA732X_REG_H_ */
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
new file mode 100644
index 000000000000..5d8f39e32978
--- /dev/null
+++ b/sound/soc/codecs/isabelle.c
@@ -0,0 +1,1176 @@
+/*
+ * isabelle.c - Low power high fidelity audio codec driver
+ *
+ * Copyright (c) 2012 Texas Instruments, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ *
+ * Initially based on sound/soc/codecs/twl6040.c
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <asm/div64.h>
+#include "isabelle.h"
+
+
+/* Register default values for ISABELLE driver. */
+static struct reg_default isabelle_reg_defs[] = {
+	{ 0, 0x00 },
+	{ 1, 0x00 },
+	{ 2, 0x00 },
+	{ 3, 0x00 },
+	{ 4, 0x00 },
+	{ 5, 0x00 },
+	{ 6, 0x00 },
+	{ 7, 0x00 },
+	{ 8, 0x00 },
+	{ 9, 0x00 },
+	{ 10, 0x00 },
+	{ 11, 0x00 },
+	{ 12, 0x00 },
+	{ 13, 0x00 },
+	{ 14, 0x00 },
+	{ 15, 0x00 },
+	{ 16, 0x00 },
+	{ 17, 0x00 },
+	{ 18, 0x00 },
+	{ 19, 0x00 },
+	{ 20, 0x00 },
+	{ 21, 0x02 },
+	{ 22, 0x02 },
+	{ 23, 0x02 },
+	{ 24, 0x02 },
+	{ 25, 0x0F },
+	{ 26, 0x8F },
+	{ 27, 0x0F },
+	{ 28, 0x8F },
+	{ 29, 0x00 },
+	{ 30, 0x00 },
+	{ 31, 0x00 },
+	{ 32, 0x00 },
+	{ 33, 0x00 },
+	{ 34, 0x00 },
+	{ 35, 0x00 },
+	{ 36, 0x00 },
+	{ 37, 0x00 },
+	{ 38, 0x00 },
+	{ 39, 0x00 },
+	{ 40, 0x00 },
+	{ 41, 0x00 },
+	{ 42, 0x00 },
+	{ 43, 0x00 },
+	{ 44, 0x00 },
+	{ 45, 0x00 },
+	{ 46, 0x00 },
+	{ 47, 0x00 },
+	{ 48, 0x00 },
+	{ 49, 0x00 },
+	{ 50, 0x00 },
+	{ 51, 0x00 },
+	{ 52, 0x00 },
+	{ 53, 0x00 },
+	{ 54, 0x00 },
+	{ 55, 0x00 },
+	{ 56, 0x00 },
+	{ 57, 0x00 },
+	{ 58, 0x00 },
+	{ 59, 0x00 },
+	{ 60, 0x00 },
+	{ 61, 0x00 },
+	{ 62, 0x00 },
+	{ 63, 0x00 },
+	{ 64, 0x00 },
+	{ 65, 0x00 },
+	{ 66, 0x00 },
+	{ 67, 0x00 },
+	{ 68, 0x00 },
+	{ 69, 0x90 },
+	{ 70, 0x90 },
+	{ 71, 0x90 },
+	{ 72, 0x00 },
+	{ 73, 0x00 },
+	{ 74, 0x00 },
+	{ 75, 0x00 },
+	{ 76, 0x00 },
+	{ 77, 0x00 },
+	{ 78, 0x00 },
+	{ 79, 0x00 },
+	{ 80, 0x00 },
+	{ 81, 0x00 },
+	{ 82, 0x00 },
+	{ 83, 0x00 },
+	{ 84, 0x00 },
+	{ 85, 0x07 },
+	{ 86, 0x00 },
+	{ 87, 0x00 },
+	{ 88, 0x00 },
+	{ 89, 0x07 },
+	{ 90, 0x80 },
+	{ 91, 0x07 },
+	{ 92, 0x07 },
+	{ 93, 0x00 },
+	{ 94, 0x00 },
+	{ 95, 0x00 },
+	{ 96, 0x00 },
+	{ 97, 0x00 },
+	{ 98, 0x00 },
+	{ 99, 0x00 },
+};
+
+static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"};
+static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"};
+
+static const struct soc_enum isabelle_rx1_enum[] = {
+	SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts),
+	SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts),
+};
+
+static const struct soc_enum isabelle_rx2_enum[] = {
+	SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts),
+	SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts),
+};
+
+/* Headset DAC playback switches */
+static const struct snd_kcontrol_new rx1_mux_controls =
+	SOC_DAPM_ENUM("Route", isabelle_rx1_enum);
+
+static const struct snd_kcontrol_new rx2_mux_controls =
+	SOC_DAPM_ENUM("Route", isabelle_rx2_enum);
+
+/* TX input selection */
+static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"};
+static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"};
+
+static const struct soc_enum isabelle_atx_enum[] = {
+	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts),
+	SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts),
+};
+
+static const struct soc_enum isabelle_vtx_enum[] = {
+	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts),
+	SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts),
+};
+
+static const struct snd_kcontrol_new atx_mux_controls =
+	SOC_DAPM_ENUM("Route", isabelle_atx_enum);
+
+static const struct snd_kcontrol_new vtx_mux_controls =
+	SOC_DAPM_ENUM("Route", isabelle_vtx_enum);
+
+/* Left analog microphone selection */
+static const char *isabelle_amic1_texts[] = {
+	"Main Mic", "Headset Mic", "Aux/FM Left"};
+
+/* Left analog microphone selection */
+static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"};
+
+static const struct soc_enum isabelle_amic1_enum[] = {
+	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5,
+			ARRAY_SIZE(isabelle_amic1_texts),
+			isabelle_amic1_texts),
+};
+
+static const struct soc_enum isabelle_amic2_enum[] = {
+	SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4,
+			ARRAY_SIZE(isabelle_amic2_texts),
+			isabelle_amic2_texts),
+};
+
+static const struct snd_kcontrol_new amic1_control =
+	SOC_DAPM_ENUM("Route", isabelle_amic1_enum);
+
+static const struct snd_kcontrol_new amic2_control =
+	SOC_DAPM_ENUM("Route", isabelle_amic2_enum);
+
+static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"};
+
+static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"};
+
+static const struct soc_enum isabelle_st_audio_enum[] = {
+	SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1,
+			isabelle_st_audio_texts),
+	SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1,
+			isabelle_st_audio_texts),
+};
+
+static const struct soc_enum isabelle_st_voice_enum[] = {
+	SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1,
+			isabelle_st_voice_texts),
+	SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1,
+			isabelle_st_voice_texts),
+};
+
+static const struct snd_kcontrol_new st_audio_control =
+	SOC_DAPM_ENUM("Route", isabelle_st_audio_enum);
+
+static const struct snd_kcontrol_new st_voice_control =
+	SOC_DAPM_ENUM("Route", isabelle_st_voice_enum);
+
+/* Mixer controls */
+static const struct snd_kcontrol_new isabelle_hs_left_mixer_controls[] = {
+SOC_DAPM_SINGLE("DAC1L Playback Switch", ISABELLE_HSDRV_CFG1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_hs_right_mixer_controls[] = {
+SOC_DAPM_SINGLE("DAC1R Playback Switch", ISABELLE_HSDRV_CFG1_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_hf_left_mixer_controls[] = {
+SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_HFLPGA_CFG_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HFLPGA_CFG_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_hf_right_mixer_controls[] = {
+SOC_DAPM_SINGLE("DAC2R Playback Switch", ISABELLE_HFRPGA_CFG_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HFRPGA_CFG_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_ep_mixer_controls[] = {
+SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_EARDRV_CFG1_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_EARDRV_CFG1_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_aux_left_mixer_controls[] = {
+SOC_DAPM_SINGLE("DAC3L Playback Switch", ISABELLE_LINEAMP_CFG_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_aux_right_mixer_controls[] = {
+SOC_DAPM_SINGLE("DAC3R Playback Switch", ISABELLE_LINEAMP_CFG_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_dpga1_left_mixer_controls[] = {
+SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_dpga1_right_mixer_controls[] = {
+SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_dpga2_left_mixer_controls[] = {
+SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 4, 1, 0),
+SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_dpga2_right_mixer_controls[] = {
+SOC_DAPM_SINGLE("USNC Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_dpga3_left_mixer_controls[] = {
+SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 6, 1, 0),
+SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_dpga3_right_mixer_controls[] = {
+SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 2, 1, 0),
+SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_rx1_mixer_controls[] = {
+SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DL1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_rx2_mixer_controls[] = {
+SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("DL2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_rx3_mixer_controls[] = {
+SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 3, 1, 0),
+SOC_DAPM_SINGLE("DL3 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_rx4_mixer_controls[] = {
+SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 1, 1, 0),
+SOC_DAPM_SINGLE("DL4 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_rx5_mixer_controls[] = {
+SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 7, 1, 0),
+SOC_DAPM_SINGLE("DL5 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new isabelle_rx6_mixer_controls[] = {
+SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 5, 1, 0),
+SOC_DAPM_SINGLE("DL6 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new ep_path_enable_control =
+	SOC_DAPM_SINGLE("Switch", ISABELLE_EARDRV_CFG2_REG, 0, 1, 0);
+
+/* TLV Declarations */
+static const DECLARE_TLV_DB_SCALE(mic_amp_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_SCALE(afm_amp_tlv, -3300, 300, 0);
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -1200, 200, 0);
+static const DECLARE_TLV_DB_SCALE(hf_tlv, -5000, 200, 0);
+
+/* from -63 to 0 dB in 1 dB steps */
+static const DECLARE_TLV_DB_SCALE(dpga_tlv, -6300, 100, 1);
+
+/* from -63 to 9 dB in 1 dB steps */
+static const DECLARE_TLV_DB_SCALE(rx_tlv, -6300, 100, 1);
+
+static const DECLARE_TLV_DB_SCALE(st_tlv, -2700, 300, 1);
+static const DECLARE_TLV_DB_SCALE(tx_tlv, -600, 100, 0);
+
+static const struct snd_kcontrol_new isabelle_snd_controls[] = {
+	SOC_DOUBLE_TLV("Headset Playback Volume", ISABELLE_HSDRV_GAIN_REG,
+			4, 0, 0xF, 0, dac_tlv),
+	SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
+			ISABELLE_HFLPGA_CFG_REG, ISABELLE_HFRPGA_CFG_REG,
+			0, 0x1F, 0, hf_tlv),
+	SOC_DOUBLE_TLV("Aux Playback Volume", ISABELLE_LINEAMP_GAIN_REG,
+			4, 0, 0xF, 0, dac_tlv),
+	SOC_SINGLE_TLV("Earpiece Playback Volume", ISABELLE_EARDRV_CFG1_REG,
+			0, 0xF, 0, dac_tlv),
+
+	SOC_DOUBLE_TLV("Aux FM Volume", ISABELLE_APGA_GAIN_REG, 4, 0, 0xF, 0,
+			afm_amp_tlv),
+	SOC_SINGLE_TLV("Mic1 Capture Volume", ISABELLE_MIC1_GAIN_REG, 3, 0x1F,
+			0, mic_amp_tlv),
+	SOC_SINGLE_TLV("Mic2 Capture Volume", ISABELLE_MIC2_GAIN_REG, 3, 0x1F,
+			0, mic_amp_tlv),
+
+	SOC_DOUBLE_R_TLV("DPGA1 Volume", ISABELLE_DPGA1L_GAIN_REG,
+			ISABELLE_DPGA1R_GAIN_REG, 0, 0x3F, 0, dpga_tlv),
+	SOC_DOUBLE_R_TLV("DPGA2 Volume", ISABELLE_DPGA2L_GAIN_REG,
+			ISABELLE_DPGA2R_GAIN_REG, 0, 0x3F, 0, dpga_tlv),
+	SOC_DOUBLE_R_TLV("DPGA3 Volume", ISABELLE_DPGA3L_GAIN_REG,
+			ISABELLE_DPGA3R_GAIN_REG, 0, 0x3F, 0, dpga_tlv),
+
+	SOC_SINGLE_TLV("Sidetone Audio TX1 Volume",
+			ISABELLE_ATX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv),
+	SOC_SINGLE_TLV("Sidetone Audio TX2 Volume",
+			ISABELLE_ATX_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv),
+	SOC_SINGLE_TLV("Sidetone Voice TX1 Volume",
+			ISABELLE_VTX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv),
+	SOC_SINGLE_TLV("Sidetone Voice TX2 Volume",
+			ISABELLE_VTX2_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv),
+
+	SOC_SINGLE_TLV("Audio TX1 Volume", ISABELLE_ATX1_DPGA_REG, 4, 0xF, 0,
+			tx_tlv),
+	SOC_SINGLE_TLV("Audio TX2 Volume", ISABELLE_ATX2_DPGA_REG, 4, 0xF, 0,
+			tx_tlv),
+	SOC_SINGLE_TLV("Voice TX1 Volume", ISABELLE_VTX1_DPGA_REG, 4, 0xF, 0,
+			tx_tlv),
+	SOC_SINGLE_TLV("Voice TX2 Volume", ISABELLE_VTX2_DPGA_REG, 4, 0xF, 0,
+			tx_tlv),
+
+	SOC_SINGLE_TLV("RX1 DPGA Volume", ISABELLE_RX1_DPGA_REG, 0, 0x3F, 0,
+			rx_tlv),
+	SOC_SINGLE_TLV("RX2 DPGA Volume", ISABELLE_RX2_DPGA_REG, 0, 0x3F, 0,
+			rx_tlv),
+	SOC_SINGLE_TLV("RX3 DPGA Volume", ISABELLE_RX3_DPGA_REG, 0, 0x3F, 0,
+			rx_tlv),
+	SOC_SINGLE_TLV("RX4 DPGA Volume", ISABELLE_RX4_DPGA_REG, 0, 0x3F, 0,
+			rx_tlv),
+	SOC_SINGLE_TLV("RX5 DPGA Volume", ISABELLE_RX5_DPGA_REG, 0, 0x3F, 0,
+			rx_tlv),
+	SOC_SINGLE_TLV("RX6 DPGA Volume", ISABELLE_RX6_DPGA_REG, 0, 0x3F, 0,
+			rx_tlv),
+
+	SOC_SINGLE("Headset Noise Gate", ISABELLE_HS_NG_CFG1_REG, 7, 1, 0),
+	SOC_SINGLE("Handsfree Noise Gate", ISABELLE_HF_NG_CFG1_REG, 7, 1, 0),
+
+	SOC_SINGLE("ATX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		7, 1, 0),
+	SOC_SINGLE("ATX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		6, 1, 0),
+	SOC_SINGLE("ARX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		5, 1, 0),
+	SOC_SINGLE("ARX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		4, 1, 0),
+	SOC_SINGLE("ARX3 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		3, 1, 0),
+	SOC_SINGLE("ARX4 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		2, 1, 0),
+	SOC_SINGLE("ARX5 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		1, 1, 0),
+	SOC_SINGLE("ARX6 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		0, 1, 0),
+	SOC_SINGLE("VRX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		3, 1, 0),
+	SOC_SINGLE("VRX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
+		2, 1, 0),
+
+	SOC_SINGLE("ATX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG,
+		7, 1, 0),
+	SOC_SINGLE("ATX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG,
+		6, 1, 0),
+	SOC_SINGLE("VTX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG,
+		5, 1, 0),
+	SOC_SINGLE("VTX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG,
+		4, 1, 0),
+	SOC_SINGLE("RX1 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
+		5, 1, 0),
+	SOC_SINGLE("RX2 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
+		4, 1, 0),
+	SOC_SINGLE("RX3 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
+		3, 1, 0),
+	SOC_SINGLE("RX4 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
+		2, 1, 0),
+	SOC_SINGLE("RX5 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
+		1, 1, 0),
+	SOC_SINGLE("RX6 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
+		0, 1, 0),
+
+	SOC_SINGLE("ULATX12 Capture Switch", ISABELLE_ULATX12_INTF_CFG_REG,
+		7, 1, 0),
+
+	SOC_SINGLE("DL12 Playback Switch", ISABELLE_DL12_INTF_CFG_REG,
+		7, 1, 0),
+	SOC_SINGLE("DL34 Playback Switch", ISABELLE_DL34_INTF_CFG_REG,
+		7, 1, 0),
+	SOC_SINGLE("DL56 Playback Switch", ISABELLE_DL56_INTF_CFG_REG,
+		7, 1, 0),
+
+	/* DMIC Switch */
+	SOC_SINGLE("DMIC Switch", ISABELLE_DMIC_CFG_REG, 0, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget isabelle_dapm_widgets[] = {
+	/* Inputs */
+	SND_SOC_DAPM_INPUT("MAINMIC"),
+	SND_SOC_DAPM_INPUT("HSMIC"),
+	SND_SOC_DAPM_INPUT("SUBMIC"),
+	SND_SOC_DAPM_INPUT("LINEIN1"),
+	SND_SOC_DAPM_INPUT("LINEIN2"),
+	SND_SOC_DAPM_INPUT("DMICDAT"),
+
+	/* Outputs */
+	SND_SOC_DAPM_OUTPUT("HSOL"),
+	SND_SOC_DAPM_OUTPUT("HSOR"),
+	SND_SOC_DAPM_OUTPUT("HFL"),
+	SND_SOC_DAPM_OUTPUT("HFR"),
+	SND_SOC_DAPM_OUTPUT("EP"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+
+	SND_SOC_DAPM_PGA("DL1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DL2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DL3", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DL4", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DL5", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DL6", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Analog input muxes for the capture amplifiers */
+	SND_SOC_DAPM_MUX("Analog Left Capture Route",
+			SND_SOC_NOPM, 0, 0, &amic1_control),
+	SND_SOC_DAPM_MUX("Analog Right Capture Route",
+			SND_SOC_NOPM, 0, 0, &amic2_control),
+
+	SND_SOC_DAPM_MUX("Sidetone Audio Playback", SND_SOC_NOPM, 0, 0,
+			&st_audio_control),
+	SND_SOC_DAPM_MUX("Sidetone Voice Playback", SND_SOC_NOPM, 0, 0,
+			&st_voice_control),
+
+	/* AIF */
+	SND_SOC_DAPM_AIF_IN("INTF1_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 7, 0),
+	SND_SOC_DAPM_AIF_IN("INTF2_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 6, 0),
+
+	SND_SOC_DAPM_AIF_OUT("INTF1_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 5, 0),
+	SND_SOC_DAPM_AIF_OUT("INTF2_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 4, 0),
+
+	SND_SOC_DAPM_OUT_DRV("ULATX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("ULATX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("ULVTX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("ULVTX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Analog Capture PGAs */
+	SND_SOC_DAPM_PGA("MicAmp1", ISABELLE_AMIC_CFG_REG, 5, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("MicAmp2", ISABELLE_AMIC_CFG_REG, 4, 0, NULL, 0),
+
+	/* Auxiliary FM PGAs */
+	SND_SOC_DAPM_PGA("APGA1", ISABELLE_APGA_CFG_REG, 7, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("APGA2", ISABELLE_APGA_CFG_REG, 6, 0, NULL, 0),
+
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC1", "Left Front Capture",
+			ISABELLE_AMIC_CFG_REG, 7, 0),
+	SND_SOC_DAPM_ADC("ADC2", "Right Front Capture",
+			ISABELLE_AMIC_CFG_REG, 6, 0),
+
+	/* Microphone Bias */
+	SND_SOC_DAPM_SUPPLY("Headset Mic Bias", ISABELLE_ABIAS_CFG_REG,
+			3, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Main Mic Bias", ISABELLE_ABIAS_CFG_REG,
+			2, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias",
+			ISABELLE_DBIAS_CFG_REG, 3, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias",
+			ISABELLE_DBIAS_CFG_REG, 2, 0, NULL, 0),
+
+	/* Mixers */
+	SND_SOC_DAPM_MIXER("Headset Left Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_hs_left_mixer_controls,
+			ARRAY_SIZE(isabelle_hs_left_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Headset Right Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_hs_right_mixer_controls,
+			ARRAY_SIZE(isabelle_hs_right_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Handsfree Left Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_hf_left_mixer_controls,
+			ARRAY_SIZE(isabelle_hf_left_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Handsfree Right Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_hf_right_mixer_controls,
+			ARRAY_SIZE(isabelle_hf_right_mixer_controls)),
+	SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_aux_left_mixer_controls,
+			ARRAY_SIZE(isabelle_aux_left_mixer_controls)),
+	SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_aux_right_mixer_controls,
+			ARRAY_SIZE(isabelle_aux_right_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Earphone Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_ep_mixer_controls,
+			ARRAY_SIZE(isabelle_ep_mixer_controls)),
+
+	SND_SOC_DAPM_MIXER("DPGA1L Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_dpga1_left_mixer_controls,
+			ARRAY_SIZE(isabelle_dpga1_left_mixer_controls)),
+	SND_SOC_DAPM_MIXER("DPGA1R Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_dpga1_right_mixer_controls,
+			ARRAY_SIZE(isabelle_dpga1_right_mixer_controls)),
+	SND_SOC_DAPM_MIXER("DPGA2L Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_dpga2_left_mixer_controls,
+			ARRAY_SIZE(isabelle_dpga2_left_mixer_controls)),
+	SND_SOC_DAPM_MIXER("DPGA2R Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_dpga2_right_mixer_controls,
+			ARRAY_SIZE(isabelle_dpga2_right_mixer_controls)),
+	SND_SOC_DAPM_MIXER("DPGA3L Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_dpga3_left_mixer_controls,
+			ARRAY_SIZE(isabelle_dpga3_left_mixer_controls)),
+	SND_SOC_DAPM_MIXER("DPGA3R Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_dpga3_right_mixer_controls,
+			ARRAY_SIZE(isabelle_dpga3_right_mixer_controls)),
+
+	SND_SOC_DAPM_MIXER("RX1 Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_rx1_mixer_controls,
+			ARRAY_SIZE(isabelle_rx1_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX2 Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_rx2_mixer_controls,
+			ARRAY_SIZE(isabelle_rx2_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX3 Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_rx3_mixer_controls,
+			ARRAY_SIZE(isabelle_rx3_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX4 Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_rx4_mixer_controls,
+			ARRAY_SIZE(isabelle_rx4_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX5 Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_rx5_mixer_controls,
+			ARRAY_SIZE(isabelle_rx5_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RX6 Mixer", SND_SOC_NOPM, 0, 0,
+			isabelle_rx6_mixer_controls,
+			ARRAY_SIZE(isabelle_rx6_mixer_controls)),
+
+	/* DACs */
+	SND_SOC_DAPM_DAC("DAC1L", "Headset Playback", ISABELLE_DAC_CFG_REG,
+			5, 0),
+	SND_SOC_DAPM_DAC("DAC1R", "Headset Playback", ISABELLE_DAC_CFG_REG,
+			4, 0),
+	SND_SOC_DAPM_DAC("DAC2L", "Handsfree Playback", ISABELLE_DAC_CFG_REG,
+			3, 0),
+	SND_SOC_DAPM_DAC("DAC2R", "Handsfree Playback", ISABELLE_DAC_CFG_REG,
+			2, 0),
+	SND_SOC_DAPM_DAC("DAC3L", "Lineout Playback", ISABELLE_DAC_CFG_REG,
+			1, 0),
+	SND_SOC_DAPM_DAC("DAC3R", "Lineout Playback", ISABELLE_DAC_CFG_REG,
+			0, 0),
+
+	/* Analog Playback PGAs */
+	SND_SOC_DAPM_PGA("Sidetone Audio PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Sidetone Voice PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("HF Left PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("HF Right PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DPGA1L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DPGA1R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DPGA2L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DPGA2R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DPGA3L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DPGA3R", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Analog Playback Mux */
+	SND_SOC_DAPM_MUX("RX1 Playback", ISABELLE_ALU_RX_EN_REG, 5, 0,
+			&rx1_mux_controls),
+	SND_SOC_DAPM_MUX("RX2 Playback", ISABELLE_ALU_RX_EN_REG, 4, 0,
+			&rx2_mux_controls),
+
+	/* TX Select */
+	SND_SOC_DAPM_MUX("ATX Select", ISABELLE_TX_INPUT_CFG_REG,
+			7, 0, &atx_mux_controls),
+	SND_SOC_DAPM_MUX("VTX Select", ISABELLE_TX_INPUT_CFG_REG,
+			6, 0, &vtx_mux_controls),
+
+	SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
+			&ep_path_enable_control),
+
+	/* Output Drivers */
+	SND_SOC_DAPM_OUT_DRV("HS Left Driver", ISABELLE_HSDRV_CFG2_REG,
+			1, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("HS Right Driver", ISABELLE_HSDRV_CFG2_REG,
+			0, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("LINEOUT1 Left Driver", ISABELLE_LINEAMP_CFG_REG,
+			1, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("LINEOUT2 Right Driver", ISABELLE_LINEAMP_CFG_REG,
+			0, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("Earphone Driver", ISABELLE_EARDRV_CFG2_REG,
+			1, 0, NULL, 0),
+
+	SND_SOC_DAPM_OUT_DRV("HF Left Driver", ISABELLE_HFDRV_CFG_REG,
+			1, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("HF Right Driver", ISABELLE_HFDRV_CFG_REG,
+			0, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_route isabelle_intercon[] = {
+	/* Interface mapping */
+	{ "DL1", "DL12 Playback Switch", "INTF1_SDI" },
+	{ "DL2", "DL12 Playback Switch", "INTF1_SDI" },
+	{ "DL3", "DL34 Playback Switch", "INTF1_SDI" },
+	{ "DL4", "DL34 Playback Switch", "INTF1_SDI" },
+	{ "DL5", "DL56 Playback Switch", "INTF1_SDI" },
+	{ "DL6", "DL56 Playback Switch", "INTF1_SDI" },
+
+	{ "DL1", "DL12 Playback Switch", "INTF2_SDI" },
+	{ "DL2", "DL12 Playback Switch", "INTF2_SDI" },
+	{ "DL3", "DL34 Playback Switch", "INTF2_SDI" },
+	{ "DL4", "DL34 Playback Switch", "INTF2_SDI" },
+	{ "DL5", "DL56 Playback Switch", "INTF2_SDI" },
+	{ "DL6", "DL56 Playback Switch", "INTF2_SDI" },
+
+	/* Input side mapping */
+	{ "Sidetone Audio PGA", NULL, "Sidetone Audio Playback" },
+	{ "Sidetone Voice PGA", NULL, "Sidetone Voice Playback" },
+
+	{ "RX1 Mixer", "ST1 Playback Switch", "Sidetone Audio PGA" },
+
+	{ "RX1 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" },
+	{ "RX1 Mixer", "DL1 Playback Switch", "DL1" },
+
+	{ "RX2 Mixer", "ST2 Playback Switch", "Sidetone Audio PGA" },
+
+	{ "RX2 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" },
+	{ "RX2 Mixer", "DL2 Playback Switch", "DL2" },
+
+	{ "RX3 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" },
+	{ "RX3 Mixer", "DL3 Playback Switch", "DL3" },
+
+	{ "RX4 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" },
+	{ "RX4 Mixer", "DL4 Playback Switch", "DL4" },
+
+	{ "RX5 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" },
+	{ "RX5 Mixer", "DL5 Playback Switch", "DL5" },
+
+	{ "RX6 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" },
+	{ "RX6 Mixer", "DL6 Playback Switch", "DL6" },
+
+	/* Capture path */
+	{ "Analog Left Capture Route", "Headset Mic", "HSMIC" },
+	{ "Analog Left Capture Route", "Main Mic", "MAINMIC" },
+	{ "Analog Left Capture Route", "Aux/FM Left", "LINEIN1" },
+
+	{ "Analog Right Capture Route", "Sub Mic", "SUBMIC" },
+	{ "Analog Right Capture Route", "Aux/FM Right", "LINEIN2" },
+
+	{ "MicAmp1", NULL, "Analog Left Capture Route" },
+	{ "MicAmp2", NULL, "Analog Right Capture Route" },
+
+	{ "ADC1", NULL, "MicAmp1" },
+	{ "ADC2", NULL, "MicAmp2" },
+
+	{ "ATX Select", "AMIC1", "ADC1" },
+	{ "ATX Select", "DMIC", "DMICDAT" },
+	{ "ATX Select", "AMIC2", "ADC2" },
+
+	{ "VTX Select", "AMIC1", "ADC1" },
+	{ "VTX Select", "DMIC", "DMICDAT" },
+	{ "VTX Select", "AMIC2", "ADC2" },
+
+	{ "ULATX1", "ATX1 Filter Enable Switch", "ATX Select" },
+	{ "ULATX1", "ATX1 Filter Bypass Switch", "ATX Select" },
+	{ "ULATX2", "ATX2 Filter Enable Switch", "ATX Select" },
+	{ "ULATX2", "ATX2 Filter Bypass Switch", "ATX Select" },
+
+	{ "ULVTX1", "VTX1 Filter Enable Switch", "VTX Select" },
+	{ "ULVTX1", "VTX1 Filter Bypass Switch", "VTX Select" },
+	{ "ULVTX2", "VTX2 Filter Enable Switch", "VTX Select" },
+	{ "ULVTX2", "VTX2 Filter Bypass Switch", "VTX Select" },
+
+	{ "INTF1_SDO", "ULATX12 Capture Switch", "ULATX1" },
+	{ "INTF1_SDO", "ULATX12 Capture Switch", "ULATX2" },
+	{ "INTF2_SDO", "ULATX12 Capture Switch", "ULATX1" },
+	{ "INTF2_SDO", "ULATX12 Capture Switch", "ULATX2" },
+
+	{ "INTF1_SDO", NULL, "ULVTX1" },
+	{ "INTF1_SDO", NULL, "ULVTX2" },
+	{ "INTF2_SDO", NULL, "ULVTX1" },
+	{ "INTF2_SDO", NULL, "ULVTX2" },
+
+	/* AFM Path */
+	{ "APGA1", NULL, "LINEIN1" },
+	{ "APGA2", NULL, "LINEIN2" },
+
+	{ "RX1 Playback", "VRX1 Filter Bypass Switch", "RX1 Mixer" },
+	{ "RX1 Playback", "ARX1 Filter Bypass Switch", "RX1 Mixer" },
+	{ "RX1 Playback", "RX1 Filter Enable Switch", "RX1 Mixer" },
+
+	{ "RX2 Playback", "VRX2 Filter Bypass Switch", "RX2 Mixer" },
+	{ "RX2 Playback", "ARX2 Filter Bypass Switch", "RX2 Mixer" },
+	{ "RX2 Playback", "RX2 Filter Enable Switch", "RX2 Mixer" },
+
+	{ "RX3 Playback", "ARX3 Filter Bypass Switch", "RX3 Mixer" },
+	{ "RX3 Playback", "RX3 Filter Enable Switch", "RX3 Mixer" },
+
+	{ "RX4 Playback", "ARX4 Filter Bypass Switch", "RX4 Mixer" },
+	{ "RX4 Playback", "RX4 Filter Enable Switch", "RX4 Mixer" },
+
+	{ "RX5 Playback", "ARX5 Filter Bypass Switch", "RX5 Mixer" },
+	{ "RX5 Playback", "RX5 Filter Enable Switch", "RX5 Mixer" },
+
+	{ "RX6 Playback", "ARX6 Filter Bypass Switch", "RX6 Mixer" },
+	{ "RX6 Playback", "RX6 Filter Enable Switch", "RX6 Mixer" },
+
+	{ "DPGA1L Mixer", "RX1 Playback Switch", "RX1 Playback" },
+	{ "DPGA1L Mixer", "RX3 Playback Switch", "RX3 Playback" },
+	{ "DPGA1L Mixer", "RX5 Playback Switch", "RX5 Playback" },
+
+	{ "DPGA1R Mixer", "RX2 Playback Switch", "RX2 Playback" },
+	{ "DPGA1R Mixer", "RX4 Playback Switch", "RX4 Playback" },
+	{ "DPGA1R Mixer", "RX6 Playback Switch", "RX6 Playback" },
+
+	{ "DPGA1L", NULL, "DPGA1L Mixer" },
+	{ "DPGA1R", NULL, "DPGA1R Mixer" },
+
+	{ "DAC1L", NULL, "DPGA1L" },
+	{ "DAC1R", NULL, "DPGA1R" },
+
+	{ "DPGA2L Mixer", "RX1 Playback Switch", "RX1 Playback" },
+	{ "DPGA2L Mixer", "RX2 Playback Switch", "RX2 Playback" },
+	{ "DPGA2L Mixer", "RX3 Playback Switch", "RX3 Playback" },
+	{ "DPGA2L Mixer", "RX4 Playback Switch", "RX4 Playback" },
+	{ "DPGA2L Mixer", "RX5 Playback Switch", "RX5 Playback" },
+	{ "DPGA2L Mixer", "RX6 Playback Switch", "RX6 Playback" },
+
+	{ "DPGA2R Mixer", "RX2 Playback Switch", "RX2 Playback" },
+	{ "DPGA2R Mixer", "RX4 Playback Switch", "RX4 Playback" },
+	{ "DPGA2R Mixer", "RX6 Playback Switch", "RX6 Playback" },
+
+	{ "DPGA2L", NULL, "DPGA2L Mixer" },
+	{ "DPGA2R", NULL, "DPGA2R Mixer" },
+
+	{ "DAC2L", NULL, "DPGA2L" },
+	{ "DAC2R", NULL, "DPGA2R" },
+
+	{ "DPGA3L Mixer", "RX1 Playback Switch", "RX1 Playback" },
+	{ "DPGA3L Mixer", "RX3 Playback Switch", "RX3 Playback" },
+	{ "DPGA3L Mixer", "RX5 Playback Switch", "RX5 Playback" },
+
+	{ "DPGA3R Mixer", "RX2 Playback Switch", "RX2 Playback" },
+	{ "DPGA3R Mixer", "RX4 Playback Switch", "RX4 Playback" },
+	{ "DPGA3R Mixer", "RX6 Playback Switch", "RX6 Playback" },
+
+	{ "DPGA3L", NULL, "DPGA3L Mixer" },
+	{ "DPGA3R", NULL, "DPGA3R Mixer" },
+
+	{ "DAC3L", NULL, "DPGA3L" },
+	{ "DAC3R", NULL, "DPGA3R" },
+
+	{ "Headset Left Mixer", "DAC1L Playback Switch", "DAC1L" },
+	{ "Headset Left Mixer", "APGA1 Playback Switch", "APGA1" },
+
+	{ "Headset Right Mixer", "DAC1R Playback Switch", "DAC1R" },
+	{ "Headset Right Mixer", "APGA2 Playback Switch", "APGA2" },
+
+	{ "HS Left Driver", NULL, "Headset Left Mixer" },
+	{ "HS Right Driver", NULL, "Headset Right Mixer" },
+
+	{ "HSOL", NULL, "HS Left Driver" },
+	{ "HSOR", NULL, "HS Right Driver" },
+
+	/* Earphone playback path */
+	{ "Earphone Mixer", "DAC2L Playback Switch", "DAC2L" },
+	{ "Earphone Mixer", "APGA1 Playback Switch", "APGA1" },
+
+	{ "Earphone Playback", "Switch", "Earphone Mixer" },
+	{ "Earphone Driver", NULL, "Earphone Playback" },
+	{ "EP", NULL, "Earphone Driver" },
+
+	{ "Handsfree Left Mixer", "DAC2L Playback Switch", "DAC2L" },
+	{ "Handsfree Left Mixer", "APGA1 Playback Switch", "APGA1" },
+
+	{ "Handsfree Right Mixer", "DAC2R Playback Switch", "DAC2R" },
+	{ "Handsfree Right Mixer", "APGA2 Playback Switch", "APGA2" },
+
+	{ "HF Left PGA", NULL, "Handsfree Left Mixer" },
+	{ "HF Right PGA", NULL, "Handsfree Right Mixer" },
+
+	{ "HF Left Driver", NULL, "HF Left PGA" },
+	{ "HF Right Driver", NULL, "HF Right PGA" },
+
+	{ "HFL", NULL, "HF Left Driver" },
+	{ "HFR", NULL, "HF Right Driver" },
+
+	{ "LINEOUT1 Mixer", "DAC3L Playback Switch", "DAC3L" },
+	{ "LINEOUT1 Mixer", "APGA1 Playback Switch", "APGA1" },
+
+	{ "LINEOUT2 Mixer", "DAC3R Playback Switch", "DAC3R" },
+	{ "LINEOUT2 Mixer", "APGA2 Playback Switch", "APGA2" },
+
+	{ "LINEOUT1 Driver", NULL, "LINEOUT1 Mixer" },
+	{ "LINEOUT2 Driver", NULL, "LINEOUT2 Mixer" },
+
+	{ "LINEOUT1", NULL, "LINEOUT1 Driver" },
+	{ "LINEOUT2", NULL, "LINEOUT2 Driver" },
+};
+
+static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute)
+{
+	snd_soc_update_bits(dai->codec, ISABELLE_DAC1_SOFTRAMP_REG,
+			BIT(4), (mute ? BIT(4) : 0));
+
+	return 0;
+}
+
+static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute)
+{
+	snd_soc_update_bits(dai->codec, ISABELLE_DAC2_SOFTRAMP_REG,
+			BIT(4), (mute ? BIT(4) : 0));
+
+	return 0;
+}
+
+static int isabelle_line_mute(struct snd_soc_dai *dai, int mute)
+{
+	snd_soc_update_bits(dai->codec, ISABELLE_DAC3_SOFTRAMP_REG,
+			BIT(4), (mute ? BIT(4) : 0));
+
+	return 0;
+}
+
+static int isabelle_set_bias_level(struct snd_soc_codec *codec,
+				enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG,
+				ISABELLE_CHIP_EN, BIT(0));
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG,
+				ISABELLE_CHIP_EN, 0);
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static int isabelle_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *params,
+			      struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	u16 aif = 0;
+	unsigned int fs_val = 0;
+
+	switch (params_rate(params)) {
+	case 8000:
+		fs_val = ISABELLE_FS_RATE_8;
+		break;
+	case 11025:
+		fs_val = ISABELLE_FS_RATE_11;
+		break;
+	case 12000:
+		fs_val = ISABELLE_FS_RATE_12;
+		break;
+	case 16000:
+		fs_val = ISABELLE_FS_RATE_16;
+		break;
+	case 22050:
+		fs_val = ISABELLE_FS_RATE_22;
+		break;
+	case 24000:
+		fs_val = ISABELLE_FS_RATE_24;
+		break;
+	case 32000:
+		fs_val = ISABELLE_FS_RATE_32;
+		break;
+	case 44100:
+		fs_val = ISABELLE_FS_RATE_44;
+		break;
+	case 48000:
+		fs_val = ISABELLE_FS_RATE_48;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, ISABELLE_FS_RATE_CFG_REG,
+			ISABELLE_FS_RATE_MASK, fs_val);
+
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		aif |= ISABELLE_AIF_LENGTH_20;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		aif |= ISABELLE_AIF_LENGTH_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG,
+			ISABELLE_AIF_LENGTH_MASK, aif);
+
+	return 0;
+}
+
+static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	unsigned int aif_val = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		aif_val &= ~ISABELLE_AIF_MS;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		aif_val |= ISABELLE_AIF_MS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		aif_val |= ISABELLE_I2S_MODE;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		aif_val |= ISABELLE_LEFT_J_MODE;
+		break;
+	case SND_SOC_DAIFMT_PDM:
+		aif_val |= ISABELLE_PDM_MODE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG,
+			(ISABELLE_AIF_MS | ISABELLE_AIF_FMT_MASK), aif_val);
+
+	return 0;
+}
+
+/* Rates supported by Isabelle driver */
+#define ISABELLE_RATES		SNDRV_PCM_RATE_8000_48000
+
+/* Formates supported by Isabelle driver. */
+#define ISABELLE_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE |\
+			SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops isabelle_hs_dai_ops = {
+	.hw_params	= isabelle_hw_params,
+	.set_fmt	= isabelle_set_dai_fmt,
+	.digital_mute	= isabelle_hs_mute,
+};
+
+static struct snd_soc_dai_ops isabelle_hf_dai_ops = {
+	.hw_params	= isabelle_hw_params,
+	.set_fmt	= isabelle_set_dai_fmt,
+	.digital_mute	= isabelle_hf_mute,
+};
+
+static struct snd_soc_dai_ops isabelle_line_dai_ops = {
+	.hw_params	= isabelle_hw_params,
+	.set_fmt	= isabelle_set_dai_fmt,
+	.digital_mute	= isabelle_line_mute,
+};
+
+static struct snd_soc_dai_ops isabelle_ul_dai_ops = {
+	.hw_params	= isabelle_hw_params,
+	.set_fmt	= isabelle_set_dai_fmt,
+};
+
+/* ISABELLE dai structure */
+static struct snd_soc_dai_driver isabelle_dai[] = {
+	{
+		.name = "isabelle-dl1",
+		.playback = {
+			.stream_name = "Headset Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = ISABELLE_RATES,
+			.formats = ISABELLE_FORMATS,
+		},
+		.ops = &isabelle_hs_dai_ops,
+	},
+	{
+		.name = "isabelle-dl2",
+		.playback = {
+			.stream_name = "Handsfree Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = ISABELLE_RATES,
+			.formats = ISABELLE_FORMATS,
+		},
+		.ops = &isabelle_hf_dai_ops,
+	},
+	{
+		.name = "isabelle-lineout",
+		.playback = {
+			.stream_name = "Lineout Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = ISABELLE_RATES,
+			.formats = ISABELLE_FORMATS,
+		},
+		.ops = &isabelle_line_dai_ops,
+	},
+	{
+		.name = "isabelle-ul",
+		.capture = {
+			.stream_name = "Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = ISABELLE_RATES,
+			.formats = ISABELLE_FORMATS,
+		},
+		.ops = &isabelle_ul_dai_ops,
+	},
+};
+
+static int isabelle_probe(struct snd_soc_codec *codec)
+{
+	int ret = 0;
+
+	codec->control_data = dev_get_regmap(codec->dev, NULL);
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_isabelle = {
+	.probe = isabelle_probe,
+	.set_bias_level = isabelle_set_bias_level,
+	.controls = isabelle_snd_controls,
+	.num_controls = ARRAY_SIZE(isabelle_snd_controls),
+	.dapm_widgets = isabelle_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets),
+	.dapm_routes = isabelle_intercon,
+	.num_dapm_routes = ARRAY_SIZE(isabelle_intercon),
+	.idle_bias_off = true,
+};
+
+static const struct regmap_config isabelle_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = ISABELLE_MAX_REGISTER,
+	.reg_defaults = isabelle_reg_defs,
+	.num_reg_defaults = ARRAY_SIZE(isabelle_reg_defs),
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
+					const struct i2c_device_id *id)
+{
+	struct regmap *isabelle_regmap;
+	int ret = 0;
+
+	isabelle_regmap = devm_regmap_init_i2c(i2c, &isabelle_regmap_config);
+	if (IS_ERR(isabelle_regmap)) {
+		ret = PTR_ERR(isabelle_regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+	i2c_set_clientdata(i2c, isabelle_regmap);
+
+	ret =  snd_soc_register_codec(&i2c->dev,
+				&soc_codec_dev_isabelle, isabelle_dai,
+				ARRAY_SIZE(isabelle_dai));
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int __devexit isabelle_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static const struct i2c_device_id isabelle_i2c_id[] = {
+	{ "isabelle", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id);
+
+static struct i2c_driver isabelle_i2c_driver = {
+	.driver = {
+		.name = "isabelle",
+		.owner = THIS_MODULE,
+	},
+	.probe = isabelle_i2c_probe,
+	.remove = __devexit_p(isabelle_i2c_remove),
+	.id_table = isabelle_i2c_id,
+};
+
+module_i2c_driver(isabelle_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC ISABELLE driver");
+MODULE_AUTHOR("Vishwas A Deshpande <vishwas.a.deshpande@ti.com>");
+MODULE_AUTHOR("M R Swami Reddy <MR.Swami.Reddy@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/isabelle.h b/sound/soc/codecs/isabelle.h
new file mode 100644
index 000000000000..96d839a8c956
--- /dev/null
+++ b/sound/soc/codecs/isabelle.h
@@ -0,0 +1,143 @@
+/*
+ * isabelle.h - Low power high fidelity audio codec driver header file
+ *
+ * Copyright (c) 2012 Texas Instruments, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ */
+
+#ifndef _ISABELLE_H
+#define _ISABELLE_H
+
+#include <linux/bitops.h>
+
+/* ISABELLE REGISTERS */
+
+#define ISABELLE_PWR_CFG_REG		0x01
+#define ISABELLE_PWR_EN_REG		0x02
+#define ISABELLE_PS_EN1_REG		0x03
+#define ISABELLE_INT1_STATUS_REG	0x04
+#define ISABELLE_INT1_MASK_REG		0x05
+#define ISABELLE_INT2_STATUS_REG	0x06
+#define ISABELLE_INT2_MASK_REG		0x07
+#define ISABELLE_HKCTL1_REG		0x08
+#define ISABELLE_HKCTL2_REG		0x09
+#define ISABELLE_HKCTL3_REG		0x0A
+#define ISABELLE_ACCDET_STATUS_REG	0x0B
+#define ISABELLE_BUTTON_ID_REG		0x0C
+#define ISABELLE_PLL_CFG_REG		0x10
+#define ISABELLE_PLL_EN_REG		0x11
+#define ISABELLE_FS_RATE_CFG_REG	0x12
+#define ISABELLE_INTF_CFG_REG		0x13
+#define ISABELLE_INTF_EN_REG		0x14
+#define ISABELLE_ULATX12_INTF_CFG_REG	0x15
+#define ISABELLE_DL12_INTF_CFG_REG	0x16
+#define ISABELLE_DL34_INTF_CFG_REG	0x17
+#define ISABELLE_DL56_INTF_CFG_REG	0x18
+#define ISABELLE_ATX_STPGA1_CFG_REG	0x19
+#define ISABELLE_ATX_STPGA2_CFG_REG	0x1A
+#define ISABELLE_VTX_STPGA1_CFG_REG	0x1B
+#define ISABELLE_VTX2_STPGA2_CFG_REG	0x1C
+#define ISABELLE_ATX1_DPGA_REG		0x1D
+#define ISABELLE_ATX2_DPGA_REG		0x1E
+#define ISABELLE_VTX1_DPGA_REG		0x1F
+#define ISABELLE_VTX2_DPGA_REG		0x20
+#define ISABELLE_TX_INPUT_CFG_REG	0x21
+#define ISABELLE_RX_INPUT_CFG_REG	0x22
+#define ISABELLE_RX_INPUT_CFG2_REG	0x23
+#define ISABELLE_VOICE_HPF_CFG_REG	0x24
+#define ISABELLE_AUDIO_HPF_CFG_REG	0x25
+#define ISABELLE_RX1_DPGA_REG		0x26
+#define ISABELLE_RX2_DPGA_REG		0x27
+#define ISABELLE_RX3_DPGA_REG		0x28
+#define ISABELLE_RX4_DPGA_REG		0x29
+#define ISABELLE_RX5_DPGA_REG		0x2A
+#define ISABELLE_RX6_DPGA_REG		0x2B
+#define ISABELLE_ALU_TX_EN_REG		0x2C
+#define ISABELLE_ALU_RX_EN_REG		0x2D
+#define ISABELLE_IIR_RESYNC_REG		0x2E
+#define ISABELLE_ABIAS_CFG_REG		0x30
+#define ISABELLE_DBIAS_CFG_REG		0x31
+#define ISABELLE_MIC1_GAIN_REG		0x32
+#define ISABELLE_MIC2_GAIN_REG		0x33
+#define ISABELLE_AMIC_CFG_REG		0x34
+#define ISABELLE_DMIC_CFG_REG		0x35
+#define ISABELLE_APGA_GAIN_REG		0x36
+#define ISABELLE_APGA_CFG_REG		0x37
+#define ISABELLE_TX_GAIN_DLY_REG	0x38
+#define ISABELLE_RX_GAIN_DLY_REG	0x39
+#define ISABELLE_RX_PWR_CTRL_REG	0x3A
+#define ISABELLE_DPGA1LR_IN_SEL_REG	0x3B
+#define ISABELLE_DPGA1L_GAIN_REG	0x3C
+#define ISABELLE_DPGA1R_GAIN_REG	0x3D
+#define ISABELLE_DPGA2L_IN_SEL_REG	0x3E
+#define ISABELLE_DPGA2R_IN_SEL_REG	0x3F
+#define ISABELLE_DPGA2L_GAIN_REG	0x40
+#define ISABELLE_DPGA2R_GAIN_REG	0x41
+#define ISABELLE_DPGA3LR_IN_SEL_REG	0x42
+#define ISABELLE_DPGA3L_GAIN_REG	0x43
+#define ISABELLE_DPGA3R_GAIN_REG	0x44
+#define ISABELLE_DAC1_SOFTRAMP_REG	0x45
+#define ISABELLE_DAC2_SOFTRAMP_REG	0x46
+#define ISABELLE_DAC3_SOFTRAMP_REG	0x47
+#define ISABELLE_DAC_CFG_REG		0x48
+#define ISABELLE_EARDRV_CFG1_REG	0x49
+#define ISABELLE_EARDRV_CFG2_REG	0x4A
+#define ISABELLE_HSDRV_GAIN_REG		0x4B
+#define ISABELLE_HSDRV_CFG1_REG		0x4C
+#define ISABELLE_HSDRV_CFG2_REG		0x4D
+#define ISABELLE_HS_NG_CFG1_REG		0x4E
+#define ISABELLE_HS_NG_CFG2_REG		0x4F
+#define ISABELLE_LINEAMP_GAIN_REG	0x50
+#define ISABELLE_LINEAMP_CFG_REG	0x51
+#define ISABELLE_HFL_VOL_CTRL_REG	0x52
+#define ISABELLE_HFL_SFTVOL_CTRL_REG	0x53
+#define ISABELLE_HFL_LIM_CTRL_1_REG	0x54
+#define ISABELLE_HFL_LIM_CTRL_2_REG	0x55
+#define ISABELLE_HFR_VOL_CTRL_REG	0x56
+#define ISABELLE_HFR_SFTVOL_CTRL_REG	0x57
+#define ISABELLE_HFR_LIM_CTRL_1_REG	0x58
+#define ISABELLE_HFR_LIM_CTRL_2_REG	0x59
+#define ISABELLE_HF_MODE_REG		0x5A
+#define ISABELLE_HFLPGA_CFG_REG		0x5B
+#define ISABELLE_HFRPGA_CFG_REG		0x5C
+#define ISABELLE_HFDRV_CFG_REG		0x5D
+#define ISABELLE_PDMOUT_CFG1_REG	0x5E
+#define ISABELLE_PDMOUT_CFG2_REG	0x5F
+#define ISABELLE_PDMOUT_L_WM_REG	0x60
+#define ISABELLE_PDMOUT_R_WM_REG	0x61
+#define ISABELLE_HF_NG_CFG1_REG		0x62
+#define ISABELLE_HF_NG_CFG2_REG		0x63
+
+/* ISABELLE_PWR_EN_REG (0x02h) */
+#define ISABELLE_CHIP_EN		BIT(0)
+
+/* ISABELLE DAI FORMATS */
+#define ISABELLE_AIF_FMT_MASK		0x70
+#define ISABELLE_I2S_MODE		0x0
+#define ISABELLE_LEFT_J_MODE		0x1
+#define ISABELLE_PDM_MODE		0x2
+
+#define ISABELLE_AIF_LENGTH_MASK	0x30
+#define ISABELLE_AIF_LENGTH_20		0x00
+#define ISABELLE_AIF_LENGTH_32		0x10
+
+#define ISABELLE_AIF_MS			0x80
+
+#define ISABELLE_FS_RATE_MASK		0xF
+#define ISABELLE_FS_RATE_8		0x0
+#define ISABELLE_FS_RATE_11		0x1
+#define ISABELLE_FS_RATE_12		0x2
+#define ISABELLE_FS_RATE_16		0x4
+#define ISABELLE_FS_RATE_22		0x5
+#define ISABELLE_FS_RATE_24		0x6
+#define ISABELLE_FS_RATE_32		0x8
+#define ISABELLE_FS_RATE_44		0x9
+#define ISABELLE_FS_RATE_48		0xA
+
+#define ISABELLE_MAX_REGISTER		0xFF
+
+#endif
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 802b9f176b16..99b0a9dcff34 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -1358,7 +1357,7 @@ static struct snd_soc_dai_ops lm49453_lineout_dai_ops = {
 };
 
 /* LM49453 dai structure. */
-static const struct snd_soc_dai_driver lm49453_dai[] = {
+static struct snd_soc_dai_driver lm49453_dai[] = {
 	{
 		.name = "LM49453 Headset",
 		.playback = {
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 35179e2c23c9..7cd508e16a5c 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -2216,7 +2216,7 @@ static irqreturn_t max98095_report_jack(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-int max98095_jack_detect_enable(struct snd_soc_codec *codec)
+static int max98095_jack_detect_enable(struct snd_soc_codec *codec)
 {
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	int ret = 0;
@@ -2245,7 +2245,7 @@ int max98095_jack_detect_enable(struct snd_soc_codec *codec)
 	return ret;
 }
 
-int max98095_jack_detect_disable(struct snd_soc_codec *codec)
+static int max98095_jack_detect_disable(struct snd_soc_codec *codec)
 {
 	int ret = 0;
 
@@ -2286,6 +2286,7 @@ int max98095_jack_detect(struct snd_soc_codec *codec,
 	max98095_report_jack(client->irq, codec);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(max98095_jack_detect);
 
 #ifdef CONFIG_PM
 static int max98095_suspend(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 22cb5bf59273..96aa5fa05160 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -638,7 +638,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
 
 	i2c_set_clientdata(i2c, priv);
 
-	priv->regmap = regmap_init_i2c(i2c, &ml26124_i2c_regmap);
+	priv->regmap = devm_regmap_init_i2c(i2c, &ml26124_i2c_regmap);
 	if (IS_ERR(priv->regmap)) {
 		ret = PTR_ERR(priv->regmap);
 		dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret);
@@ -651,10 +651,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
 
 static __devexit int ml26124_i2c_remove(struct i2c_client *client)
 {
-	struct ml26124_priv *priv = i2c_get_clientdata(client);
-
 	snd_soc_unregister_codec(&client->dev);
-	regmap_exit(priv->regmap);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c
new file mode 100644
index 000000000000..dd8d856053fc
--- /dev/null
+++ b/sound/soc/codecs/spdif_receiver.c
@@ -0,0 +1,67 @@
+/*
+ * ALSA SoC SPDIF DIR (Digital Interface Reciever) driver
+ *
+ * Based on ALSA SoC SPDIF DIT driver
+ *
+ *  This driver is used by controllers which can operate in DIR (SPDI/F) where
+ *  no codec is needed.  This file provides stub codec that can be used
+ *  in these configurations. SPEAr SPDIF IN Audio controller uses this driver.
+ *
+ * Author:      Vipin Kumar,  <vipin.kumar@st.com>
+ * Copyright:   (C) 2012  ST Microelectronics
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+
+#define STUB_RATES	SNDRV_PCM_RATE_8000_192000
+#define STUB_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
+
+static struct snd_soc_codec_driver soc_codec_spdif_dir;
+
+static struct snd_soc_dai_driver dir_stub_dai = {
+	.name		= "dir-hifi",
+	.capture	= {
+		.stream_name	= "Capture",
+		.channels_min	= 1,
+		.channels_max	= 384,
+		.rates		= STUB_RATES,
+		.formats	= STUB_FORMATS,
+	},
+};
+
+static int spdif_dir_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dir,
+			&dir_stub_dai, 1);
+}
+
+static int spdif_dir_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver spdif_dir_driver = {
+	.probe		= spdif_dir_probe,
+	.remove		= spdif_dir_remove,
+	.driver		= {
+		.name	= "spdif-dir",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(spdif_dir_driver);
+
+MODULE_DESCRIPTION("ASoC SPDIF DIR driver");
+MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
new file mode 100644
index 000000000000..0c225cd569d2
--- /dev/null
+++ b/sound/soc/codecs/sta529.c
@@ -0,0 +1,442 @@
+/*
+ * ASoC codec driver for spear platform
+ *
+ * sound/soc/codecs/sta529.c -- spear ALSA Soc codec driver
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Rajeev Kumar <rajeev-dlh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+/* STA529 Register offsets */
+#define	 STA529_FFXCFG0		0x00
+#define	 STA529_FFXCFG1		0x01
+#define	 STA529_MVOL		0x02
+#define	 STA529_LVOL		0x03
+#define	 STA529_RVOL		0x04
+#define	 STA529_TTF0		0x05
+#define	 STA529_TTF1		0x06
+#define	 STA529_TTP0		0x07
+#define	 STA529_TTP1		0x08
+#define	 STA529_S2PCFG0		0x0A
+#define	 STA529_S2PCFG1		0x0B
+#define	 STA529_P2SCFG0		0x0C
+#define	 STA529_P2SCFG1		0x0D
+#define	 STA529_PLLCFG0		0x14
+#define	 STA529_PLLCFG1		0x15
+#define	 STA529_PLLCFG2		0x16
+#define	 STA529_PLLCFG3		0x17
+#define	 STA529_PLLPFE		0x18
+#define	 STA529_PLLST		0x19
+#define	 STA529_ADCCFG		0x1E /*mic_select*/
+#define	 STA529_CKOCFG		0x1F
+#define	 STA529_MISC		0x20
+#define	 STA529_PADST0		0x21
+#define	 STA529_PADST1		0x22
+#define	 STA529_FFXST		0x23
+#define	 STA529_PWMIN1		0x2D
+#define	 STA529_PWMIN2		0x2E
+#define	 STA529_POWST		0x32
+
+#define STA529_MAX_REGISTER	0x32
+
+#define STA529_RATES		(SNDRV_PCM_RATE_8000 | \
+				SNDRV_PCM_RATE_11025 | \
+				SNDRV_PCM_RATE_16000 | \
+				SNDRV_PCM_RATE_22050 | \
+				SNDRV_PCM_RATE_32000 | \
+				SNDRV_PCM_RATE_44100 | \
+				SNDRV_PCM_RATE_48000)
+
+#define STA529_FORMAT		(SNDRV_PCM_FMTBIT_S16_LE | \
+				SNDRV_PCM_FMTBIT_S24_LE | \
+				SNDRV_PCM_FMTBIT_S32_LE)
+#define	S2PC_VALUE		0x98
+#define CLOCK_OUT		0x60
+#define LEFT_J_DATA_FORMAT	0x10
+#define I2S_DATA_FORMAT		0x12
+#define RIGHT_J_DATA_FORMAT	0x14
+#define CODEC_MUTE_VAL		0x80
+
+#define POWER_CNTLMSAK		0x40
+#define POWER_STDBY		0x40
+#define FFX_MASK		0x80
+#define FFX_OFF			0x80
+#define POWER_UP		0x00
+#define FFX_CLK_ENB		0x01
+#define FFX_CLK_DIS		0x00
+#define FFX_CLK_MSK		0x01
+#define PLAY_FREQ_RANGE_MSK	0x70
+#define CAP_FREQ_RANGE_MSK	0x0C
+#define PDATA_LEN_MSK		0xC0
+#define BCLK_TO_FS_MSK		0x30
+#define AUDIO_MUTE_MSK		0x80
+
+static const struct reg_default sta529_reg_defaults[] = {
+	{ 0,  0x35 },     /* R0   - FFX Configuration reg 0 */
+	{ 1,  0xc8 },     /* R1   - FFX Configuration reg 1 */
+	{ 2,  0x50 },     /* R2   - Master Volume */
+	{ 3,  0x00 },     /* R3   - Left Volume */
+	{ 4,  0x00 },     /* R4  -  Right Volume */
+	{ 10, 0xb2 },     /* R10  - S2P Config Reg 0 */
+	{ 11, 0x41 },     /* R11  - S2P Config Reg 1 */
+	{ 12, 0x92 },     /* R12  - P2S Config Reg 0 */
+	{ 13, 0x41 },     /* R13  - P2S Config Reg 1 */
+	{ 30, 0xd2 },     /* R30  - ADC Config Reg */
+	{ 31, 0x40 },     /* R31  - clock Out Reg */
+	{ 32, 0x21 },     /* R32  - Misc Register */
+};
+
+struct sta529 {
+	struct regmap *regmap;
+};
+
+static bool sta529_readable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+
+	case STA529_FFXCFG0:
+	case STA529_FFXCFG1:
+	case STA529_MVOL:
+	case STA529_LVOL:
+	case STA529_RVOL:
+	case STA529_S2PCFG0:
+	case STA529_S2PCFG1:
+	case STA529_P2SCFG0:
+	case STA529_P2SCFG1:
+	case STA529_ADCCFG:
+	case STA529_CKOCFG:
+	case STA529_MISC:
+		return true;
+	default:
+		return false;
+	}
+}
+
+
+static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary",
+	"Phase-shift"};
+
+static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0);
+static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0);
+static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
+
+static const struct snd_kcontrol_new sta529_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0,
+			127, 0, out_gain_tlv),
+	SOC_SINGLE_TLV("Master Playback Volume", STA529_MVOL, 0, 127, 1,
+			master_vol_tlv),
+	SOC_ENUM("PWM Select", pwm_src),
+};
+
+static int sta529_set_bias_level(struct snd_soc_codec *codec, enum
+		snd_soc_bias_level level)
+{
+	struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec);
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+	case SND_SOC_BIAS_PREPARE:
+		snd_soc_update_bits(codec, STA529_FFXCFG0, POWER_CNTLMSAK,
+				POWER_UP);
+		snd_soc_update_bits(codec, STA529_MISC,	FFX_CLK_MSK,
+				FFX_CLK_ENB);
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+			regcache_sync(sta529->regmap);
+		snd_soc_update_bits(codec, STA529_FFXCFG0,
+					POWER_CNTLMSAK, POWER_STDBY);
+		/* Making FFX output to zero */
+		snd_soc_update_bits(codec, STA529_FFXCFG0, FFX_MASK,
+				FFX_OFF);
+		snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK,
+				FFX_CLK_DIS);
+		break;
+	case SND_SOC_BIAS_OFF:
+		break;
+	}
+
+	/*
+	 * store the label for powers down audio subsystem for suspend.This is
+	 * used by soc core layer
+	 */
+	codec->dapm.bias_level = level;
+
+	return 0;
+
+}
+
+static int sta529_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params,
+		struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	int pdata, play_freq_val, record_freq_val;
+	int bclk_to_fs_ratio;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		pdata = 1;
+		bclk_to_fs_ratio = 0;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		pdata = 2;
+		bclk_to_fs_ratio = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		pdata = 3;
+		bclk_to_fs_ratio = 2;
+		break;
+	default:
+		dev_err(codec->dev, "Unsupported format\n");
+		return -EINVAL;
+	}
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 11025:
+		play_freq_val = 0;
+		record_freq_val = 2;
+		break;
+	case 16000:
+	case 22050:
+		play_freq_val = 1;
+		record_freq_val = 0;
+		break;
+
+	case 32000:
+	case 44100:
+	case 48000:
+		play_freq_val = 2;
+		record_freq_val = 0;
+		break;
+	default:
+		dev_err(codec->dev, "Unsupported rate\n");
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		snd_soc_update_bits(codec, STA529_S2PCFG1, PDATA_LEN_MSK,
+				pdata << 6);
+		snd_soc_update_bits(codec, STA529_S2PCFG1, BCLK_TO_FS_MSK,
+				bclk_to_fs_ratio << 4);
+		snd_soc_update_bits(codec, STA529_MISC, PLAY_FREQ_RANGE_MSK,
+				play_freq_val << 4);
+	} else {
+		snd_soc_update_bits(codec, STA529_P2SCFG1, PDATA_LEN_MSK,
+				pdata << 6);
+		snd_soc_update_bits(codec, STA529_P2SCFG1, BCLK_TO_FS_MSK,
+				bclk_to_fs_ratio << 4);
+		snd_soc_update_bits(codec, STA529_MISC, CAP_FREQ_RANGE_MSK,
+				record_freq_val << 2);
+	}
+
+	return 0;
+}
+
+static int sta529_mute(struct snd_soc_dai *dai, int mute)
+{
+	u8 val = 0;
+
+	if (mute)
+		val |= CODEC_MUTE_VAL;
+
+	snd_soc_update_bits(dai->codec, STA529_FFXCFG0, AUDIO_MUTE_MSK, val);
+
+	return 0;
+}
+
+static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u8 mode = 0;
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_LEFT_J:
+		mode = LEFT_J_DATA_FORMAT;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		mode = I2S_DATA_FORMAT;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		mode = RIGHT_J_DATA_FORMAT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops sta529_dai_ops = {
+	.hw_params	=	sta529_hw_params,
+	.set_fmt	=	sta529_set_dai_fmt,
+	.digital_mute	=	sta529_mute,
+};
+
+static struct snd_soc_dai_driver sta529_dai = {
+	.name = "sta529-audio",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = STA529_RATES,
+		.formats = STA529_FORMAT,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = STA529_RATES,
+		.formats = STA529_FORMAT,
+	},
+	.ops	= &sta529_dai_ops,
+};
+
+static int sta529_probe(struct snd_soc_codec *codec)
+{
+	struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	codec->control_data = sta529->regmap;
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+	sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	return 0;
+}
+
+/* power down chip */
+static int sta529_remove(struct snd_soc_codec *codec)
+{
+	sta529_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+static int sta529_suspend(struct snd_soc_codec *codec)
+{
+	sta529_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+static int sta529_resume(struct snd_soc_codec *codec)
+{
+	sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	return 0;
+}
+
+struct snd_soc_codec_driver sta529_codec_driver = {
+	.probe = sta529_probe,
+	.remove = sta529_remove,
+	.set_bias_level = sta529_set_bias_level,
+	.suspend = sta529_suspend,
+	.resume = sta529_resume,
+	.controls = sta529_snd_controls,
+	.num_controls = ARRAY_SIZE(sta529_snd_controls),
+};
+
+static const struct regmap_config sta529_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = STA529_MAX_REGISTER,
+	.readable_reg = sta529_readable,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = sta529_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
+};
+
+static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
+		const struct i2c_device_id *id)
+{
+	struct sta529 *sta529;
+	int ret;
+
+	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EINVAL;
+
+	sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL);
+	if (sta529 == NULL) {
+		dev_err(&i2c->dev, "Can not allocate memory\n");
+		return -ENOMEM;
+	}
+
+	sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap);
+	if (IS_ERR(sta529->regmap)) {
+		ret = PTR_ERR(sta529->regmap);
+		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+		return ret;
+	}
+
+	i2c_set_clientdata(i2c, sta529);
+
+	ret = snd_soc_register_codec(&i2c->dev,
+			&sta529_codec_driver, &sta529_dai, 1);
+	if (ret != 0)
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+
+	return ret;
+}
+
+static int __devexit sta529_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id sta529_i2c_id[] = {
+	{ "sta529", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sta529_i2c_id);
+
+static struct i2c_driver sta529_i2c_driver = {
+	.driver = {
+		.name = "sta529",
+		.owner = THIS_MODULE,
+	},
+	.probe		= sta529_i2c_probe,
+	.remove		= __devexit_p(sta529_i2c_remove),
+	.id_table	= sta529_i2c_id,
+};
+
+module_i2c_driver(sta529_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC STA529 codec driver");
+MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index e9b62b5ea637..dc78f5a4bcbf 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -118,7 +118,9 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
 	0x00, 0x00, 0x00, 0x00,	/* 88 */
 	0x00, 0x00, 0x00, 0x00,	/* 92 */
 	0x00, 0x00, 0x00, 0x00,	/* 96 */
-	0x00, 0x00, 0x02,	/* 100 */
+	0x00, 0x00, 0x02, 0x00,	/* 100 */
+	0x00, 0x00, 0x00, 0x00,	/* 104 */
+	0x00, 0x00,            	/* 108 */
 };
 
 #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
@@ -229,6 +231,25 @@ static const struct soc_enum aic3x_enum[] = {
 	SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf),
 };
 
+static const char *aic3x_agc_level[] =
+	{ "-5.5dB", "-8dB", "-10dB", "-12dB", "-14dB", "-17dB", "-20dB", "-24dB" };
+static const struct soc_enum aic3x_agc_level_enum[] = {
+	SOC_ENUM_SINGLE(LAGC_CTRL_A, 4, 8, aic3x_agc_level),
+	SOC_ENUM_SINGLE(RAGC_CTRL_A, 4, 8, aic3x_agc_level),
+};
+
+static const char *aic3x_agc_attack[] = { "8ms", "11ms", "16ms", "20ms" };
+static const struct soc_enum aic3x_agc_attack_enum[] = {
+	SOC_ENUM_SINGLE(LAGC_CTRL_A, 2, 4, aic3x_agc_attack),
+	SOC_ENUM_SINGLE(RAGC_CTRL_A, 2, 4, aic3x_agc_attack),
+};
+
+static const char *aic3x_agc_decay[] = { "100ms", "200ms", "400ms", "500ms" };
+static const struct soc_enum aic3x_agc_decay_enum[] = {
+	SOC_ENUM_SINGLE(LAGC_CTRL_A, 0, 4, aic3x_agc_decay),
+	SOC_ENUM_SINGLE(RAGC_CTRL_A, 0, 4, aic3x_agc_decay),
+};
+
 /*
  * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps
  */
@@ -353,6 +374,15 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
 	 * adjust PGA to max value when ADC is on and will never go back.
 	*/
 	SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0),
+	SOC_ENUM("Left AGC Target level", aic3x_agc_level_enum[0]),
+	SOC_ENUM("Right AGC Target level", aic3x_agc_level_enum[1]),
+	SOC_ENUM("Left AGC Attack time", aic3x_agc_attack_enum[0]),
+	SOC_ENUM("Right AGC Attack time", aic3x_agc_attack_enum[1]),
+	SOC_ENUM("Left AGC Decay time", aic3x_agc_decay_enum[0]),
+	SOC_ENUM("Right AGC Decay time", aic3x_agc_decay_enum[1]),
+
+	/* De-emphasis */
+	SOC_DOUBLE("De-emphasis Switch", AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0),
 
 	/* Input */
 	SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL,
@@ -368,7 +398,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
 static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0);
 
 static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl =
-	SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv);
+	SOC_DOUBLE_TLV("Class-D Playback Volume", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv);
 
 /* Left DAC Mux */
 static const struct snd_kcontrol_new aic3x_left_dac_mux_controls =
@@ -970,6 +1000,12 @@ static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	struct snd_soc_codec *codec = codec_dai->codec;
 	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
 
+	/* set clock on MCLK or GPIO2 or BCLK */
+	snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, PLLCLK_IN_MASK,
+				clk_id << PLLCLK_IN_SHIFT);
+	snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, CLKDIV_IN_MASK,
+				clk_id << CLKDIV_IN_SHIFT);
+
 	aic3x->sysclk = freq;
 	return 0;
 }
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 08c7f6685ff0..6db3c41b0163 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -13,7 +13,7 @@
 #define _AIC3X_H
 
 /* AIC3X register space */
-#define AIC3X_CACHEREGNUM		103
+#define AIC3X_CACHEREGNUM		110
 
 /* Page select register */
 #define AIC3X_PAGE_SELECT		0
@@ -74,6 +74,8 @@
 #define HPLCOM_CFG			37
 /* Right High Power Output control registers */
 #define HPRCOM_CFG			38
+/* High Power Output Stage Control Register */
+#define HPOUT_SC			40
 /* DAC Output Switching control registers */
 #define DAC_LINE_MUX			41
 /* High Power Output Driver Pop Reduction registers */
@@ -148,6 +150,17 @@
 #define AIC3X_GPIOB_REG			101
 /* Clock generation control register */
 #define AIC3X_CLKGEN_CTRL_REG		102
+/* New AGC registers */
+#define LAGCN_ATTACK			103
+#define LAGCN_DECAY			104
+#define RAGCN_ATTACK			105
+#define RAGCN_DECAY			106
+/* New Programmable ADC Digital Path and I2C Bus Condition Register */
+#define NEW_ADC_DIGITALPATH		107
+/* Passive Analog Signal Bypass Selection During Powerdown Register */
+#define PASSIVE_BYPASS			108
+/* DAC Quiescent Current Adjustment Register */
+#define DAC_ICC_ADJ			109
 
 /* Page select register bits */
 #define PAGE0_SELECT		0
@@ -163,6 +176,10 @@
 #define DUAL_RATE_MODE		((1 << 5) | (1 << 6))
 #define LDAC2LCH		(0x1 << 3)
 #define RDAC2RCH		(0x1 << 1)
+#define LDAC2RCH		(0x2 << 3)
+#define RDAC2LCH		(0x2 << 1)
+#define LDAC2MONOMIX		(0x3 << 3)
+#define RDAC2MONOMIX		(0x3 << 1)
 
 /* PLL registers bitfields */
 #define PLLP_SHIFT		0
@@ -179,6 +196,14 @@
 #define PLL_CLKIN_SHIFT		4
 #define MCLK_SOURCE		0x0
 #define PLL_CLKDIV_SHIFT	0
+#define PLLCLK_IN_MASK		0x30
+#define PLLCLK_IN_SHIFT		4
+#define CLKDIV_IN_MASK		0xc0
+#define CLKDIV_IN_SHIFT		6
+/* clock in source */
+#define CLKIN_MCLK		0
+#define CLKIN_GPIO2		1
+#define CLKIN_BCLK		2
 
 /* Software reset register bits */
 #define SOFT_RESET		0x80
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index a36e9fcdf184..0ff1e70b7770 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -553,7 +553,7 @@ static const struct snd_kcontrol_new vibrar_mux_controls =
 
 /* Headset power mode */
 static const char *twl6040_power_mode_texts[] = {
-	"Low-Power", "High-Perfomance",
+	"Low-Power", "High-Performance",
 };
 
 static const struct soc_enum twl6040_power_mode_enum =
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index e0b51e9f8b12..951d7b49476a 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -121,20 +121,23 @@ static const struct snd_soc_dai_ops wm1250_ev1_ops = {
 	.hw_params = wm1250_ev1_hw_params,
 };
 
+#define WM1250_EV1_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			  SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_64000)
+
 static struct snd_soc_dai_driver wm1250_ev1_dai = {
 	.name = "wm1250-ev1",
 	.playback = {
 		.stream_name = "Playback",
 		.channels_min = 1,
 		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_8000,
+		.rates = WM1250_EV1_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
 	.capture = {
 		.stream_name = "Capture",
 		.channels_min = 1,
 		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_8000,
+		.rates = WM1250_EV1_RATES,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
 	.ops = &wm1250_ev1_ops,
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 0418fa11e6bd..3fd5b29dc933 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -1,7 +1,7 @@
 /*
  * wm2000.c  --  WM2000 ALSA Soc Audio driver
  *
- * Copyright 2008-2010 Wolfson Microelectronics PLC.
+ * Copyright 2008-2011 Wolfson Microelectronics PLC.
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
@@ -674,9 +674,39 @@ static int wm2000_resume(struct snd_soc_codec *codec)
 #define wm2000_resume NULL
 #endif
 
+static bool wm2000_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM2000_REG_SYS_START:
+	case WM2000_REG_SPEECH_CLARITY:
+	case WM2000_REG_SYS_WATCHDOG:
+	case WM2000_REG_ANA_VMID_PD_TIME:
+	case WM2000_REG_ANA_VMID_PU_TIME:
+	case WM2000_REG_CAT_FLTR_INDX:
+	case WM2000_REG_CAT_GAIN_0:
+	case WM2000_REG_SYS_STATUS:
+	case WM2000_REG_SYS_MODE_CNTRL:
+	case WM2000_REG_SYS_START0:
+	case WM2000_REG_SYS_START1:
+	case WM2000_REG_ID1:
+	case WM2000_REG_ID2:
+	case WM2000_REG_REVISON:
+	case WM2000_REG_SYS_CTL1:
+	case WM2000_REG_SYS_CTL2:
+	case WM2000_REG_ANC_STAT:
+	case WM2000_REG_IF_CTL:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static const struct regmap_config wm2000_regmap = {
 	.reg_bits = 8,
 	.val_bits = 8,
+
+	.max_register = WM2000_REG_IF_CTL,
+	.readable_reg = wm2000_readable_reg,
 };
 
 static int wm2000_probe(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c
index e167207a19cc..e239f4bf2460 100644
--- a/sound/soc/codecs/wm5100-tables.c
+++ b/sound/soc/codecs/wm5100-tables.c
@@ -1,7 +1,7 @@
 /*
  * wm5100-tables.c  --  WM5100 ALSA SoC Audio driver data
  *
- * Copyright 2011 Wolfson Microelectronics plc
+ * Copyright 2011-2 Wolfson Microelectronics plc
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index cb6d5372103a..f4817292ef45 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1,7 +1,7 @@
 /*
  * wm5100.c  --  WM5100 ALSA SoC Audio driver
  *
- * Copyright 2011 Wolfson Microelectronics plc
+ * Copyright 2011-2 Wolfson Microelectronics plc
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
@@ -2378,13 +2378,6 @@ static int wm5100_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
-static int wm5100_soc_volatile(struct snd_soc_codec *codec,
-			       unsigned int reg)
-{
-	return true;
-}
-
-
 static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
 	.probe =	wm5100_probe,
 	.remove =	wm5100_remove,
@@ -2392,8 +2385,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
 	.set_sysclk = wm5100_set_sysclk,
 	.set_pll = wm5100_set_fll,
 	.idle_bias_off = 1,
-	.reg_cache_size = WM5100_MAX_REGISTER,
-	.volatile_register = wm5100_soc_volatile,
 
 	.seq_notifier = wm5100_seq_notifier,
 	.controls = wm5100_snd_controls,
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
new file mode 100644
index 000000000000..6537f16d383e
--- /dev/null
+++ b/sound/soc/codecs/wm5102.c
@@ -0,0 +1,903 @@
+/*
+ * wm5102.c  --  WM5102 ALSA SoC Audio driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/registers.h>
+
+#include "arizona.h"
+#include "wm5102.h"
+
+struct wm5102_priv {
+	struct arizona_priv core;
+	struct arizona_fll fll[2];
+};
+
+static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
+static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
+
+static const struct snd_kcontrol_new wm5102_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
+	   ARIZONA_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL,
+	   ARIZONA_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL,
+	   ARIZONA_IN3_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL,
+		       ARIZONA_IN1R_CONTROL,
+		       ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
+SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL,
+		       ARIZONA_IN2R_CONTROL,
+		       ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
+SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL,
+		       ARIZONA_IN3R_CONTROL,
+		       ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
+
+SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L,
+	     ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L,
+	     ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L,
+	     ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L,
+		 ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L,
+		 ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
+		 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+
+ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
+
+SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE),
+
+SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5,
+		   ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA),
+SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5,
+		   ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA),
+
+ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
+
+SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
+SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
+SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
+SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
+
+ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
+
+SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR,
+	       ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv),
+
+ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
+
+SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
+	   ARIZONA_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
+	   ARIZONA_OUT2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
+	   ARIZONA_OUT3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
+	   ARIZONA_OUT4_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
+	   ARIZONA_OUT5_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
+	   ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
+	       ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+
+SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
+		       ARIZONA_OUTPUT_PATH_CONFIG_1R,
+		       ARIZONA_OUT1L_PGA_VOL_SHIFT,
+		       0x34, 0x40, 0, ana_tlv),
+SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
+		       ARIZONA_OUTPUT_PATH_CONFIG_2R,
+		       ARIZONA_OUT2L_PGA_VOL_SHIFT,
+		       0x34, 0x40, 0, ana_tlv),
+SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
+		     ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
+
+SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
+	   ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
+
+ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE),
+
+ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
+
+ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
+};
+
+ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+
+static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
+		    0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
+		    ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0),
+
+SND_SOC_DAPM_SIGGEN("TONE"),
+SND_SOC_DAPM_SIGGEN("NOISE"),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+
+SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
+		    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
+		    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
+		    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
+		 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1,
+		 ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1,
+		 ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1,
+		 ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT,
+		 0, NULL, 0),
+SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT,
+		 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
+		     ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
+		     ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
+		    ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
+		    ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
+		     ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
+		     ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
+		    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
+		    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"),
+ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"),
+ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"),
+ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"),
+
+ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"),
+ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"),
+ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"),
+ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"),
+
+ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"),
+ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"),
+ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"),
+ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"),
+
+ARIZONA_MIXER_WIDGETS(Mic, "Mic"),
+ARIZONA_MIXER_WIDGETS(Noise, "Noise"),
+
+ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"),
+ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"),
+
+ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"),
+ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"),
+ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"),
+ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"),
+ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"),
+ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
+ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
+ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
+ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
+
+ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
+ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
+
+ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
+ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+
+ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
+ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
+
+ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("HPOUT2L"),
+SND_SOC_DAPM_OUTPUT("HPOUT2R"),
+SND_SOC_DAPM_OUTPUT("EPOUTN"),
+SND_SOC_DAPM_OUTPUT("EPOUTP"),
+SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
+SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
+SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
+SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
+SND_SOC_DAPM_OUTPUT("SPKDAT1L"),
+SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
+};
+
+#define ARIZONA_MIXER_INPUT_ROUTES(name)	\
+	{ name, "Noise Generator", "Noise Generator" }, \
+	{ name, "Tone Generator 1", "Tone Generator 1" }, \
+	{ name, "Tone Generator 2", "Tone Generator 2" }, \
+	{ name, "IN1L", "IN1L PGA" }, \
+	{ name, "IN1R", "IN1R PGA" }, \
+	{ name, "IN2L", "IN2L PGA" }, \
+	{ name, "IN2R", "IN2R PGA" }, \
+	{ name, "IN3L", "IN3L PGA" }, \
+	{ name, "IN3R", "IN3R PGA" }, \
+	{ name, "Mic Mute Mixer", "Mic Mute Mixer" }, \
+	{ name, "AIF1RX1", "AIF1RX1" }, \
+	{ name, "AIF1RX2", "AIF1RX2" }, \
+	{ name, "AIF1RX3", "AIF1RX3" }, \
+	{ name, "AIF1RX4", "AIF1RX4" }, \
+	{ name, "AIF1RX5", "AIF1RX5" }, \
+	{ name, "AIF1RX6", "AIF1RX6" }, \
+	{ name, "AIF1RX7", "AIF1RX7" }, \
+	{ name, "AIF1RX8", "AIF1RX8" }, \
+	{ name, "AIF2RX1", "AIF2RX1" }, \
+	{ name, "AIF2RX2", "AIF2RX2" }, \
+	{ name, "AIF3RX1", "AIF3RX1" }, \
+	{ name, "AIF3RX2", "AIF3RX2" }, \
+	{ name, "EQ1", "EQ1" }, \
+	{ name, "EQ2", "EQ2" }, \
+	{ name, "EQ3", "EQ3" }, \
+	{ name, "EQ4", "EQ4" }, \
+	{ name, "DRC1L", "DRC1L" }, \
+	{ name, "DRC1R", "DRC1R" }, \
+	{ name, "DRC2L", "DRC2L" }, \
+	{ name, "DRC2R", "DRC2R" }, \
+	{ name, "LHPF1", "LHPF1" }, \
+	{ name, "LHPF2", "LHPF2" }, \
+	{ name, "LHPF3", "LHPF3" }, \
+	{ name, "LHPF4", "LHPF4" }, \
+	{ name, "ASRC1L", "ASRC1L" }, \
+	{ name, "ASRC1R", "ASRC1R" }, \
+	{ name, "ASRC2L", "ASRC2L" }, \
+	{ name, "ASRC2R", "ASRC2R" }
+
+static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
+	{ "AIF2 Capture", NULL, "DBVDD2" },
+	{ "AIF2 Playback", NULL, "DBVDD2" },
+
+	{ "AIF3 Capture", NULL, "DBVDD3" },
+	{ "AIF3 Playback", NULL, "DBVDD3" },
+
+	{ "OUT1L", NULL, "CPVDD" },
+	{ "OUT1R", NULL, "CPVDD" },
+	{ "OUT2L", NULL, "CPVDD" },
+	{ "OUT2R", NULL, "CPVDD" },
+	{ "OUT3L", NULL, "CPVDD" },
+
+	{ "OUT4L", NULL, "SPKVDDL" },
+	{ "OUT4R", NULL, "SPKVDDR" },
+
+	{ "OUT1L", NULL, "SYSCLK" },
+	{ "OUT1R", NULL, "SYSCLK" },
+	{ "OUT2L", NULL, "SYSCLK" },
+	{ "OUT2R", NULL, "SYSCLK" },
+	{ "OUT3L", NULL, "SYSCLK" },
+	{ "OUT4L", NULL, "SYSCLK" },
+	{ "OUT4R", NULL, "SYSCLK" },
+	{ "OUT5L", NULL, "SYSCLK" },
+	{ "OUT5R", NULL, "SYSCLK" },
+
+	{ "MICBIAS1", NULL, "MICVDD" },
+	{ "MICBIAS2", NULL, "MICVDD" },
+	{ "MICBIAS3", NULL, "MICVDD" },
+
+	{ "Noise Generator", NULL, "NOISE" },
+	{ "Tone Generator 1", NULL, "TONE" },
+	{ "Tone Generator 2", NULL, "TONE" },
+
+	{ "Mic Mute Mixer", NULL, "Noise Mixer" },
+	{ "Mic Mute Mixer", NULL, "Mic Mixer" },
+
+	{ "AIF1 Capture", NULL, "AIF1TX1" },
+	{ "AIF1 Capture", NULL, "AIF1TX2" },
+	{ "AIF1 Capture", NULL, "AIF1TX3" },
+	{ "AIF1 Capture", NULL, "AIF1TX4" },
+	{ "AIF1 Capture", NULL, "AIF1TX5" },
+	{ "AIF1 Capture", NULL, "AIF1TX6" },
+	{ "AIF1 Capture", NULL, "AIF1TX7" },
+	{ "AIF1 Capture", NULL, "AIF1TX8" },
+
+	{ "AIF1RX1", NULL, "AIF1 Playback" },
+	{ "AIF1RX2", NULL, "AIF1 Playback" },
+	{ "AIF1RX3", NULL, "AIF1 Playback" },
+	{ "AIF1RX4", NULL, "AIF1 Playback" },
+	{ "AIF1RX5", NULL, "AIF1 Playback" },
+	{ "AIF1RX6", NULL, "AIF1 Playback" },
+	{ "AIF1RX7", NULL, "AIF1 Playback" },
+	{ "AIF1RX8", NULL, "AIF1 Playback" },
+
+	{ "AIF2 Capture", NULL, "AIF2TX1" },
+	{ "AIF2 Capture", NULL, "AIF2TX2" },
+
+	{ "AIF2RX1", NULL, "AIF2 Playback" },
+	{ "AIF2RX2", NULL, "AIF2 Playback" },
+
+	{ "AIF3 Capture", NULL, "AIF3TX1" },
+	{ "AIF3 Capture", NULL, "AIF3TX2" },
+
+	{ "AIF3RX1", NULL, "AIF3 Playback" },
+	{ "AIF3RX2", NULL, "AIF3 Playback" },
+
+	{ "AIF1 Playback", NULL, "SYSCLK" },
+	{ "AIF2 Playback", NULL, "SYSCLK" },
+	{ "AIF3 Playback", NULL, "SYSCLK" },
+
+	{ "AIF1 Capture", NULL, "SYSCLK" },
+	{ "AIF2 Capture", NULL, "SYSCLK" },
+	{ "AIF3 Capture", NULL, "SYSCLK" },
+
+	ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
+	ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
+	ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
+	ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"),
+	ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"),
+
+	ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"),
+	ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"),
+	ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
+	ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
+
+	ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"),
+	ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"),
+
+	ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+	ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+	ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+	ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+	ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+	ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+	ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
+	ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
+
+	ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
+	ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+
+	ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
+	ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
+
+	ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
+	ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
+	ARIZONA_MIXER_ROUTES("EQ3", "EQ3"),
+	ARIZONA_MIXER_ROUTES("EQ4", "EQ4"),
+
+	ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"),
+	ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"),
+	ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"),
+	ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"),
+
+	ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"),
+	ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"),
+	ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
+	ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
+
+	ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
+	ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
+	ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
+	ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+
+	{ "HPOUT1L", NULL, "OUT1L" },
+	{ "HPOUT1R", NULL, "OUT1R" },
+
+	{ "HPOUT2L", NULL, "OUT2L" },
+	{ "HPOUT2R", NULL, "OUT2R" },
+
+	{ "EPOUTN", NULL, "OUT3L" },
+	{ "EPOUTP", NULL, "OUT3L" },
+
+	{ "SPKOUTLN", NULL, "OUT4L" },
+	{ "SPKOUTLP", NULL, "OUT4L" },
+
+	{ "SPKOUTRN", NULL, "OUT4R" },
+	{ "SPKOUTRP", NULL, "OUT4R" },
+
+	{ "SPKDAT1L", NULL, "OUT5L" },
+	{ "SPKDAT1R", NULL, "OUT5R" },
+};
+
+static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+			  unsigned int Fref, unsigned int Fout)
+{
+	struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec);
+
+	switch (fll_id) {
+	case WM5102_FLL1:
+		return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout);
+	case WM5102_FLL2:
+		return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout);
+	default:
+		return -EINVAL;
+	}
+}
+
+#define WM5102_RATES SNDRV_PCM_RATE_8000_192000
+
+#define WM5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm5102_dai[] = {
+	{
+		.name = "wm5102-aif1",
+		.id = 1,
+		.base = ARIZONA_AIF1_BCLK_CTRL,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = WM5102_RATES,
+			.formats = WM5102_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF1 Capture",
+			 .channels_min = 1,
+			 .channels_max = 8,
+			 .rates = WM5102_RATES,
+			 .formats = WM5102_FORMATS,
+		 },
+		.ops = &arizona_dai_ops,
+		.symmetric_rates = 1,
+	},
+	{
+		.name = "wm5102-aif2",
+		.id = 2,
+		.base = ARIZONA_AIF2_BCLK_CTRL,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = WM5102_RATES,
+			.formats = WM5102_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF2 Capture",
+			 .channels_min = 1,
+			 .channels_max = 2,
+			 .rates = WM5102_RATES,
+			 .formats = WM5102_FORMATS,
+		 },
+		.ops = &arizona_dai_ops,
+		.symmetric_rates = 1,
+	},
+	{
+		.name = "wm5102-aif3",
+		.id = 3,
+		.base = ARIZONA_AIF3_BCLK_CTRL,
+		.playback = {
+			.stream_name = "AIF3 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = WM5102_RATES,
+			.formats = WM5102_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF3 Capture",
+			 .channels_min = 1,
+			 .channels_max = 2,
+			 .rates = WM5102_RATES,
+			 .formats = WM5102_FORMATS,
+		 },
+		.ops = &arizona_dai_ops,
+		.symmetric_rates = 1,
+	},
+};
+
+static int wm5102_codec_probe(struct snd_soc_codec *codec)
+{
+	struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+	codec->control_data = priv->core.arizona->regmap;
+	return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+}
+
+#define WM5102_DIG_VU 0x0200
+
+static unsigned int wm5102_digital_vu[] = {
+	ARIZONA_ADC_DIGITAL_VOLUME_1L,
+	ARIZONA_ADC_DIGITAL_VOLUME_1R,
+	ARIZONA_ADC_DIGITAL_VOLUME_2L,
+	ARIZONA_ADC_DIGITAL_VOLUME_2R,
+	ARIZONA_ADC_DIGITAL_VOLUME_3L,
+	ARIZONA_ADC_DIGITAL_VOLUME_3R,
+
+	ARIZONA_DAC_DIGITAL_VOLUME_1L,
+	ARIZONA_DAC_DIGITAL_VOLUME_1R,
+	ARIZONA_DAC_DIGITAL_VOLUME_2L,
+	ARIZONA_DAC_DIGITAL_VOLUME_2R,
+	ARIZONA_DAC_DIGITAL_VOLUME_3L,
+	ARIZONA_DAC_DIGITAL_VOLUME_3R,
+	ARIZONA_DAC_DIGITAL_VOLUME_4L,
+	ARIZONA_DAC_DIGITAL_VOLUME_4R,
+	ARIZONA_DAC_DIGITAL_VOLUME_5L,
+	ARIZONA_DAC_DIGITAL_VOLUME_5R,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
+	.probe = wm5102_codec_probe,
+
+	.idle_bias_off = true,
+
+	.set_sysclk = arizona_set_sysclk,
+	.set_pll = wm5102_set_fll,
+
+	.controls = wm5102_snd_controls,
+	.num_controls = ARRAY_SIZE(wm5102_snd_controls),
+	.dapm_widgets = wm5102_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets),
+	.dapm_routes = wm5102_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes),
+};
+
+static int __devinit wm5102_probe(struct platform_device *pdev)
+{
+	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+	struct wm5102_priv *wm5102;
+	int i;
+
+	wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv),
+			      GFP_KERNEL);
+	if (wm5102 == NULL)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, wm5102);
+
+	wm5102->core.arizona = arizona;
+
+	for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
+		wm5102->fll[i].vco_mult = 1;
+
+	arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1,
+			 ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK,
+			 &wm5102->fll[0]);
+	arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1,
+			 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
+			 &wm5102->fll[1]);
+
+	for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++)
+		arizona_init_dai(&wm5102->core, i);
+
+	/* Latch volume update bits */
+	for (i = 0; i < ARRAY_SIZE(wm5102_digital_vu); i++)
+		regmap_update_bits(arizona->regmap, wm5102_digital_vu[i],
+				   WM5102_DIG_VU, WM5102_DIG_VU);
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_idle(&pdev->dev);
+
+	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102,
+				      wm5102_dai, ARRAY_SIZE(wm5102_dai));
+}
+
+static int __devexit wm5102_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver wm5102_codec_driver = {
+	.driver = {
+		.name = "wm5102-codec",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm5102_probe,
+	.remove = __devexit_p(wm5102_remove),
+};
+
+module_platform_driver(wm5102_codec_driver);
+
+MODULE_DESCRIPTION("ASoC WM5102 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm5102-codec");
diff --git a/sound/soc/codecs/wm5102.h b/sound/soc/codecs/wm5102.h
new file mode 100644
index 000000000000..d30477f3070c
--- /dev/null
+++ b/sound/soc/codecs/wm5102.h
@@ -0,0 +1,21 @@
+/*
+ * wm5102.h  --  WM5102 ALSA SoC Audio driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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.
+ */
+
+#ifndef _WM5102_H
+#define _WM5102_H
+
+#include "arizona.h"
+
+#define WM5102_FLL1 1
+#define WM5102_FLL2 2
+
+#endif
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
new file mode 100644
index 000000000000..8033f7065189
--- /dev/null
+++ b/sound/soc/codecs/wm5110.c
@@ -0,0 +1,950 @@
+/*
+ * wm5110.c  --  WM5110 ALSA SoC Audio driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/registers.h>
+
+#include "arizona.h"
+#include "wm5110.h"
+
+struct wm5110_priv {
+	struct arizona_priv core;
+	struct arizona_fll fll[2];
+};
+
+static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
+static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
+
+static const struct snd_kcontrol_new wm5110_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
+	   ARIZONA_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL,
+	   ARIZONA_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL,
+	   ARIZONA_IN3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL,
+	   ARIZONA_IN4_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL,
+		       ARIZONA_IN1R_CONTROL,
+		       ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
+SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL,
+		       ARIZONA_IN2R_CONTROL,
+		       ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
+SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL,
+		       ARIZONA_IN3R_CONTROL,
+		       ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
+
+SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L,
+	     ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L,
+	     ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L,
+	     ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN4 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_4L,
+	     ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L,
+		 ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L,
+		 ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
+		 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L,
+		 ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+
+ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
+
+SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE),
+
+SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5,
+		   ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA),
+SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5,
+		   ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA),
+
+ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
+
+SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
+SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
+SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
+SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
+
+ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
+
+SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR,
+	       ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv),
+
+ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE),
+
+SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
+	   ARIZONA_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
+	   ARIZONA_OUT2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
+	   ARIZONA_OUT3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
+	   ARIZONA_OUT4_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
+	   ARIZONA_OUT5_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
+	   ARIZONA_OUT6_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
+	   ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_6L,
+	     ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
+	       ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L,
+		 ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+
+SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
+		       ARIZONA_OUTPUT_PATH_CONFIG_1R,
+		       ARIZONA_OUT1L_PGA_VOL_SHIFT,
+		       0x34, 0x40, 0, ana_tlv),
+SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
+		       ARIZONA_OUTPUT_PATH_CONFIG_2R,
+		       ARIZONA_OUT2L_PGA_VOL_SHIFT,
+		       0x34, 0x40, 0, ana_tlv),
+SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
+		     ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
+
+SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
+	   ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
+	   ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
+
+ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE),
+
+ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
+
+ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
+};
+
+ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKDAT2L, ARIZONA_OUT6LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKDAT2R, ARIZONA_OUT6RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+
+static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
+		    0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
+		    ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0),
+
+SND_SOC_DAPM_SIGGEN("TONE"),
+SND_SOC_DAPM_SIGGEN("NOISE"),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+SND_SOC_DAPM_INPUT("IN4L"),
+SND_SOC_DAPM_INPUT("IN4R"),
+
+SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT,
+		   0, NULL, 0, arizona_in_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
+		    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
+		    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
+		    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
+		 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1,
+		 ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1,
+		 ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1,
+		 ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT,
+		 0, NULL, 0),
+SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT,
+		 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
+		     ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
+		    ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
+		     ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
+		     ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
+		    ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
+		    ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
+		     ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
+		     ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
+		    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
+		    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT6L", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT6L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT6R", ARIZONA_OUTPUT_ENABLES_1,
+		   ARIZONA_OUT6R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"),
+ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"),
+ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"),
+ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"),
+
+ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"),
+ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"),
+ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"),
+ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"),
+
+ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"),
+ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"),
+ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"),
+ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"),
+
+ARIZONA_MIXER_WIDGETS(Mic, "Mic"),
+ARIZONA_MIXER_WIDGETS(Noise, "Noise"),
+
+ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"),
+ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"),
+
+ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"),
+ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"),
+ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"),
+ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"),
+ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"),
+ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
+ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
+ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
+ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
+ARIZONA_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"),
+ARIZONA_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"),
+
+ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
+ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
+
+ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
+ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+
+ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
+ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
+
+ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("HPOUT2L"),
+SND_SOC_DAPM_OUTPUT("HPOUT2R"),
+SND_SOC_DAPM_OUTPUT("EPOUTN"),
+SND_SOC_DAPM_OUTPUT("EPOUTP"),
+SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
+SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
+SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
+SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
+SND_SOC_DAPM_OUTPUT("SPKDAT1L"),
+SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
+SND_SOC_DAPM_OUTPUT("SPKDAT2L"),
+SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
+};
+
+#define ARIZONA_MIXER_INPUT_ROUTES(name)	\
+	{ name, "Noise Generator", "Noise Generator" }, \
+	{ name, "Tone Generator 1", "Tone Generator 1" }, \
+	{ name, "Tone Generator 2", "Tone Generator 2" }, \
+	{ name, "IN1L", "IN1L PGA" }, \
+	{ name, "IN1R", "IN1R PGA" }, \
+	{ name, "IN2L", "IN2L PGA" }, \
+	{ name, "IN2R", "IN2R PGA" }, \
+	{ name, "IN3L", "IN3L PGA" }, \
+	{ name, "IN3R", "IN3R PGA" }, \
+	{ name, "IN4L", "IN4L PGA" }, \
+	{ name, "IN4R", "IN4R PGA" }, \
+	{ name, "Mic Mute Mixer", "Mic Mute Mixer" }, \
+	{ name, "AIF1RX1", "AIF1RX1" }, \
+	{ name, "AIF1RX2", "AIF1RX2" }, \
+	{ name, "AIF1RX3", "AIF1RX3" }, \
+	{ name, "AIF1RX4", "AIF1RX4" }, \
+	{ name, "AIF1RX5", "AIF1RX5" }, \
+	{ name, "AIF1RX6", "AIF1RX6" }, \
+	{ name, "AIF1RX7", "AIF1RX7" }, \
+	{ name, "AIF1RX8", "AIF1RX8" }, \
+	{ name, "AIF2RX1", "AIF2RX1" }, \
+	{ name, "AIF2RX2", "AIF2RX2" }, \
+	{ name, "AIF3RX1", "AIF3RX1" }, \
+	{ name, "AIF3RX2", "AIF3RX2" }, \
+	{ name, "EQ1", "EQ1" }, \
+	{ name, "EQ2", "EQ2" }, \
+	{ name, "EQ3", "EQ3" }, \
+	{ name, "EQ4", "EQ4" }, \
+	{ name, "DRC1L", "DRC1L" }, \
+	{ name, "DRC1R", "DRC1R" }, \
+	{ name, "DRC2L", "DRC2L" }, \
+	{ name, "DRC2R", "DRC2R" }, \
+	{ name, "LHPF1", "LHPF1" }, \
+	{ name, "LHPF2", "LHPF2" }, \
+	{ name, "LHPF3", "LHPF3" }, \
+	{ name, "LHPF4", "LHPF4" }, \
+	{ name, "ASRC1L", "ASRC1L" }, \
+	{ name, "ASRC1R", "ASRC1R" }, \
+	{ name, "ASRC2L", "ASRC2L" }, \
+	{ name, "ASRC2R", "ASRC2R" }
+
+static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
+	{ "AIF2 Capture", NULL, "DBVDD2" },
+	{ "AIF2 Playback", NULL, "DBVDD2" },
+
+	{ "AIF3 Capture", NULL, "DBVDD3" },
+	{ "AIF3 Playback", NULL, "DBVDD3" },
+
+	{ "OUT1L", NULL, "CPVDD" },
+	{ "OUT1R", NULL, "CPVDD" },
+	{ "OUT2L", NULL, "CPVDD" },
+	{ "OUT2R", NULL, "CPVDD" },
+	{ "OUT3L", NULL, "CPVDD" },
+
+	{ "OUT4L", NULL, "SPKVDDL" },
+	{ "OUT4R", NULL, "SPKVDDR" },
+
+	{ "OUT1L", NULL, "SYSCLK" },
+	{ "OUT1R", NULL, "SYSCLK" },
+	{ "OUT2L", NULL, "SYSCLK" },
+	{ "OUT2R", NULL, "SYSCLK" },
+	{ "OUT3L", NULL, "SYSCLK" },
+	{ "OUT4L", NULL, "SYSCLK" },
+	{ "OUT4R", NULL, "SYSCLK" },
+	{ "OUT5L", NULL, "SYSCLK" },
+	{ "OUT5R", NULL, "SYSCLK" },
+	{ "OUT6L", NULL, "SYSCLK" },
+	{ "OUT6R", NULL, "SYSCLK" },
+
+	{ "MICBIAS1", NULL, "MICVDD" },
+	{ "MICBIAS2", NULL, "MICVDD" },
+	{ "MICBIAS3", NULL, "MICVDD" },
+
+	{ "Noise Generator", NULL, "NOISE" },
+	{ "Tone Generator 1", NULL, "TONE" },
+	{ "Tone Generator 2", NULL, "TONE" },
+
+	{ "Mic Mute Mixer", NULL, "Noise Mixer" },
+	{ "Mic Mute Mixer", NULL, "Mic Mixer" },
+
+	{ "AIF1 Capture", NULL, "AIF1TX1" },
+	{ "AIF1 Capture", NULL, "AIF1TX2" },
+	{ "AIF1 Capture", NULL, "AIF1TX3" },
+	{ "AIF1 Capture", NULL, "AIF1TX4" },
+	{ "AIF1 Capture", NULL, "AIF1TX5" },
+	{ "AIF1 Capture", NULL, "AIF1TX6" },
+	{ "AIF1 Capture", NULL, "AIF1TX7" },
+	{ "AIF1 Capture", NULL, "AIF1TX8" },
+
+	{ "AIF1RX1", NULL, "AIF1 Playback" },
+	{ "AIF1RX2", NULL, "AIF1 Playback" },
+	{ "AIF1RX3", NULL, "AIF1 Playback" },
+	{ "AIF1RX4", NULL, "AIF1 Playback" },
+	{ "AIF1RX5", NULL, "AIF1 Playback" },
+	{ "AIF1RX6", NULL, "AIF1 Playback" },
+	{ "AIF1RX7", NULL, "AIF1 Playback" },
+	{ "AIF1RX8", NULL, "AIF1 Playback" },
+
+	{ "AIF2 Capture", NULL, "AIF2TX1" },
+	{ "AIF2 Capture", NULL, "AIF2TX2" },
+
+	{ "AIF2RX1", NULL, "AIF2 Playback" },
+	{ "AIF2RX2", NULL, "AIF2 Playback" },
+
+	{ "AIF3 Capture", NULL, "AIF3TX1" },
+	{ "AIF3 Capture", NULL, "AIF3TX2" },
+
+	{ "AIF3RX1", NULL, "AIF3 Playback" },
+	{ "AIF3RX2", NULL, "AIF3 Playback" },
+
+	{ "AIF1 Playback", NULL, "SYSCLK" },
+	{ "AIF2 Playback", NULL, "SYSCLK" },
+	{ "AIF3 Playback", NULL, "SYSCLK" },
+
+	{ "AIF1 Capture", NULL, "SYSCLK" },
+	{ "AIF2 Capture", NULL, "SYSCLK" },
+	{ "AIF3 Capture", NULL, "SYSCLK" },
+
+	ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
+	ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
+	ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
+	ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"),
+	ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"),
+
+	ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"),
+	ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"),
+	ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
+	ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
+	ARIZONA_MIXER_ROUTES("OUT6L", "SPKDAT2L"),
+	ARIZONA_MIXER_ROUTES("OUT6R", "SPKDAT2R"),
+
+	ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"),
+	ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"),
+
+	ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+	ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+	ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+	ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+	ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+	ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+	ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
+	ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
+
+	ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
+	ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+
+	ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
+	ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
+
+	ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
+	ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
+	ARIZONA_MIXER_ROUTES("EQ3", "EQ3"),
+	ARIZONA_MIXER_ROUTES("EQ4", "EQ4"),
+
+	ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"),
+	ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"),
+	ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"),
+	ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"),
+
+	ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"),
+	ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"),
+	ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
+	ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
+
+	ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
+	ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
+	ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
+	ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+
+	{ "HPOUT1L", NULL, "OUT1L" },
+	{ "HPOUT1R", NULL, "OUT1R" },
+
+	{ "HPOUT2L", NULL, "OUT2L" },
+	{ "HPOUT2R", NULL, "OUT2R" },
+
+	{ "EPOUTN", NULL, "OUT3L" },
+	{ "EPOUTP", NULL, "OUT3L" },
+
+	{ "SPKOUTLN", NULL, "OUT4L" },
+	{ "SPKOUTLP", NULL, "OUT4L" },
+
+	{ "SPKOUTRN", NULL, "OUT4R" },
+	{ "SPKOUTRP", NULL, "OUT4R" },
+
+	{ "SPKDAT1L", NULL, "OUT5L" },
+	{ "SPKDAT1R", NULL, "OUT5R" },
+
+	{ "SPKDAT2L", NULL, "OUT6L" },
+	{ "SPKDAT2R", NULL, "OUT6R" },
+};
+
+static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+			  unsigned int Fref, unsigned int Fout)
+{
+	struct wm5110_priv *wm5110 = snd_soc_codec_get_drvdata(codec);
+
+	switch (fll_id) {
+	case WM5110_FLL1:
+		return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout);
+	case WM5110_FLL2:
+		return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout);
+	default:
+		return -EINVAL;
+	}
+}
+
+#define WM5110_RATES SNDRV_PCM_RATE_8000_192000
+
+#define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm5110_dai[] = {
+	{
+		.name = "wm5110-aif1",
+		.id = 1,
+		.base = ARIZONA_AIF1_BCLK_CTRL,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = WM5110_RATES,
+			.formats = WM5110_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF1 Capture",
+			 .channels_min = 1,
+			 .channels_max = 8,
+			 .rates = WM5110_RATES,
+			 .formats = WM5110_FORMATS,
+		 },
+		.ops = &arizona_dai_ops,
+		.symmetric_rates = 1,
+	},
+	{
+		.name = "wm5110-aif2",
+		.id = 2,
+		.base = ARIZONA_AIF2_BCLK_CTRL,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = WM5110_RATES,
+			.formats = WM5110_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF2 Capture",
+			 .channels_min = 1,
+			 .channels_max = 2,
+			 .rates = WM5110_RATES,
+			 .formats = WM5110_FORMATS,
+		 },
+		.ops = &arizona_dai_ops,
+		.symmetric_rates = 1,
+	},
+	{
+		.name = "wm5110-aif3",
+		.id = 3,
+		.base = ARIZONA_AIF3_BCLK_CTRL,
+		.playback = {
+			.stream_name = "AIF3 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = WM5110_RATES,
+			.formats = WM5110_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF3 Capture",
+			 .channels_min = 1,
+			 .channels_max = 2,
+			 .rates = WM5110_RATES,
+			 .formats = WM5110_FORMATS,
+		 },
+		.ops = &arizona_dai_ops,
+		.symmetric_rates = 1,
+	},
+};
+
+static int wm5110_codec_probe(struct snd_soc_codec *codec)
+{
+	struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+	codec->control_data = priv->core.arizona->regmap;
+	return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+}
+
+#define WM5110_DIG_VU 0x0200
+
+static unsigned int wm5110_digital_vu[] = {
+	ARIZONA_ADC_DIGITAL_VOLUME_1L,
+	ARIZONA_ADC_DIGITAL_VOLUME_1R,
+	ARIZONA_ADC_DIGITAL_VOLUME_2L,
+	ARIZONA_ADC_DIGITAL_VOLUME_2R,
+	ARIZONA_ADC_DIGITAL_VOLUME_3L,
+	ARIZONA_ADC_DIGITAL_VOLUME_3R,
+
+	ARIZONA_DAC_DIGITAL_VOLUME_1L,
+	ARIZONA_DAC_DIGITAL_VOLUME_1R,
+	ARIZONA_DAC_DIGITAL_VOLUME_2L,
+	ARIZONA_DAC_DIGITAL_VOLUME_2R,
+	ARIZONA_DAC_DIGITAL_VOLUME_3L,
+	ARIZONA_DAC_DIGITAL_VOLUME_3R,
+	ARIZONA_DAC_DIGITAL_VOLUME_4L,
+	ARIZONA_DAC_DIGITAL_VOLUME_4R,
+	ARIZONA_DAC_DIGITAL_VOLUME_5L,
+	ARIZONA_DAC_DIGITAL_VOLUME_5R,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
+	.probe = wm5110_codec_probe,
+
+	.idle_bias_off = true,
+
+	.set_sysclk = arizona_set_sysclk,
+	.set_pll = wm5110_set_fll,
+
+	.controls = wm5110_snd_controls,
+	.num_controls = ARRAY_SIZE(wm5110_snd_controls),
+	.dapm_widgets = wm5110_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets),
+	.dapm_routes = wm5110_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
+};
+
+static int __devinit wm5110_probe(struct platform_device *pdev)
+{
+	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+	struct wm5110_priv *wm5110;
+	int i;
+
+	wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv),
+			      GFP_KERNEL);
+	if (wm5110 == NULL)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, wm5110);
+
+	wm5110->core.arizona = arizona;
+
+	for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
+		wm5110->fll[i].vco_mult = 3;
+
+	arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1,
+			 ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK,
+			 &wm5110->fll[0]);
+	arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1,
+			 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
+			 &wm5110->fll[1]);
+
+	for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++)
+		arizona_init_dai(&wm5110->core, i);
+
+	/* Latch volume update bits */
+	for (i = 0; i < ARRAY_SIZE(wm5110_digital_vu); i++)
+		regmap_update_bits(arizona->regmap, wm5110_digital_vu[i],
+				   WM5110_DIG_VU, WM5110_DIG_VU);
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_idle(&pdev->dev);
+
+	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
+				      wm5110_dai, ARRAY_SIZE(wm5110_dai));
+}
+
+static int __devexit wm5110_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver wm5110_codec_driver = {
+	.driver = {
+		.name = "wm5110-codec",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm5110_probe,
+	.remove = __devexit_p(wm5110_remove),
+};
+
+module_platform_driver(wm5110_codec_driver);
+
+MODULE_DESCRIPTION("ASoC WM5110 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm5110-codec");
diff --git a/sound/soc/codecs/wm5110.h b/sound/soc/codecs/wm5110.h
new file mode 100644
index 000000000000..75e9351ccab0
--- /dev/null
+++ b/sound/soc/codecs/wm5110.h
@@ -0,0 +1,21 @@
+/*
+ * wm5110.h  --  WM5110 ALSA SoC Audio driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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.
+ */
+
+#ifndef _WM5110_H
+#define _WM5110_H
+
+#include "arizona.h"
+
+#define WM5110_FLL1 1
+#define WM5110_FLL2 2
+
+#endif
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 555ee146ae0d..d26c8ae4e6d9 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1,7 +1,7 @@
 /*
  * wm8350.c -- WM8350 ALSA SoC audio driver
  *
- * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
+ * Copyright (C) 2007-12 Wolfson Microelectronics PLC.
  *
  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
@@ -71,20 +71,6 @@ struct wm8350_data {
 	int fll_freq_in;
 };
 
-static unsigned int wm8350_codec_read(struct snd_soc_codec *codec,
-				      unsigned int reg)
-{
-	struct wm8350 *wm8350 = codec->control_data;
-	return wm8350_reg_read(wm8350, reg);
-}
-
-static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg,
-			      unsigned int value)
-{
-	struct wm8350 *wm8350 = codec->control_data;
-	return wm8350_reg_write(wm8350, reg, value);
-}
-
 /*
  * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown.
  */
@@ -1519,7 +1505,9 @@ static  int wm8350_codec_probe(struct snd_soc_codec *codec)
 	if (ret != 0)
 		return ret;
 
-	codec->control_data = wm8350;
+	codec->control_data = wm8350->regmap;
+
+	snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
 
 	/* Put the codec into reset if it wasn't already */
 	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
@@ -1629,8 +1617,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
 	.remove =	wm8350_codec_remove,
 	.suspend = 	wm8350_suspend,
 	.resume =	wm8350_resume,
-	.read = wm8350_codec_read,
-	.write = wm8350_codec_write,
 	.set_bias_level = wm8350_set_bias_level,
 
 	.controls = wm8350_snd_controls,
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 5dc31ebcd0e7..5d277a915f81 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -1,7 +1,7 @@
 /*
  * wm8400.c  --  WM8400 ALSA Soc Audio driver
  *
- * Copyright 2008, 2009 Wolfson Microelectronics PLC.
+ * Copyright 2008-11 Wolfson Microelectronics PLC.
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 211285164d70..7c68226376e4 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -1,7 +1,7 @@
 /*
  * wm8580.c  --  WM8580 ALSA Soc Audio driver
  *
- * Copyright 2008, 2009 Wolfson Microelectronics PLC.
+ * Copyright 2008-11 Wolfson Microelectronics PLC.
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 9d1b9b0271f1..bb1d26919b10 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -2,6 +2,7 @@
  * wm8731.c  --  WM8731 ALSA SoC Audio driver
  *
  * Copyright 2005 Openedhand Ltd.
+ * Copyright 2006-12 Wolfson Microelectronics, plc
  *
  * Author: Richard Purdie <richard@openedhand.com>
  *
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 6e849cb04243..35f3d23200e0 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -1,7 +1,7 @@
 /*
  * wm8741.c  --  WM8741 ALSA SoC Audio driver
  *
- * Copyright 2010 Wolfson Microelectronics plc
+ * Copyright 2010-1 Wolfson Microelectronics plc
  *
  * Author: Ian Lartey <ian@opensource.wolfsonmicro.com>
  *
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index a26482cd7654..13bff87ddcf5 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1,7 +1,7 @@
 /*
  * wm8753.c  --  WM8753 ALSA Soc Audio driver
  *
- * Copyright 2003 Wolfson Microelectronics PLC.
+ * Copyright 2003-11 Wolfson Microelectronics PLC.
  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  This program is free software; you can redistribute  it and/or modify it
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index a19db5a0a17a..879c356a9045 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -1,7 +1,7 @@
 /*
  * wm8776.c  --  WM8776 ALSA SoC Audio driver
  *
- * Copyright 2009 Wolfson Microelectronics plc
+ * Copyright 2009-12 Wolfson Microelectronics plc
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 6bd1b767b138..c088020172ab 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -1,7 +1,7 @@
 /*
  * wm8804.c  --  WM8804 S/PDIF transceiver driver
  *
- * Copyright 2010 Wolfson Microelectronics plc
+ * Copyright 2010-11 Wolfson Microelectronics plc
  *
  * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
  *
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 86b8a2926591..73f1c8d7bafb 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1,8 +1,8 @@
 /*
  * wm8903.c  --  WM8903 ALSA SoC Audio driver
  *
- * Copyright 2008 Wolfson Microelectronics
- * Copyright 2011 NVIDIA, Inc.
+ * Copyright 2008-12 Wolfson Microelectronics
+ * Copyright 2011-2012 NVIDIA, Inc.
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
@@ -116,6 +116,7 @@ static const struct reg_default wm8903_reg_defaults[] = {
 
 struct wm8903_priv {
 	struct wm8903_platform_data *pdata;
+	struct device *dev;
 	struct snd_soc_codec *codec;
 	struct regmap *regmap;
 
@@ -1635,17 +1636,27 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect);
 
 static irqreturn_t wm8903_irq(int irq, void *data)
 {
-	struct snd_soc_codec *codec = data;
-	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-	int mic_report;
-	int int_pol;
-	int int_val = 0;
-	int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK);
+	struct wm8903_priv *wm8903 = data;
+	int mic_report, ret;
+	unsigned int int_val, mask, int_pol;
 
-	int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask;
+	ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1_MASK,
+			  &mask);
+	if (ret != 0) {
+		dev_err(wm8903->dev, "Failed to read IRQ mask: %d\n", ret);
+		return IRQ_NONE;
+	}
+
+	ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1, &int_val);
+	if (ret != 0) {
+		dev_err(wm8903->dev, "Failed to read IRQ status: %d\n", ret);
+		return IRQ_NONE;
+	}
+
+	int_val &= ~mask;
 
 	if (int_val & WM8903_WSEQ_BUSY_EINT) {
-		dev_warn(codec->dev, "Write sequencer done\n");
+		dev_warn(wm8903->dev, "Write sequencer done\n");
 	}
 
 	/*
@@ -1656,22 +1667,28 @@ static irqreturn_t wm8903_irq(int irq, void *data)
 	 * the polarity register.
 	 */
 	mic_report = wm8903->mic_last_report;
-	int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1);
+	ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1,
+			  &int_pol);
+	if (ret != 0) {
+		dev_err(wm8903->dev, "Failed to read interrupt polarity: %d\n",
+			ret);
+		return IRQ_HANDLED;
+	}
 
 #ifndef CONFIG_SND_SOC_WM8903_MODULE
 	if (int_val & (WM8903_MICSHRT_EINT | WM8903_MICDET_EINT))
-		trace_snd_soc_jack_irq(dev_name(codec->dev));
+		trace_snd_soc_jack_irq(dev_name(wm8903->dev));
 #endif
 
 	if (int_val & WM8903_MICSHRT_EINT) {
-		dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol);
+		dev_dbg(wm8903->dev, "Microphone short (pol=%x)\n", int_pol);
 
 		mic_report ^= wm8903->mic_short;
 		int_pol ^= WM8903_MICSHRT_INV;
 	}
 
 	if (int_val & WM8903_MICDET_EINT) {
-		dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol);
+		dev_dbg(wm8903->dev, "Microphone detect (pol=%x)\n", int_pol);
 
 		mic_report ^= wm8903->mic_det;
 		int_pol ^= WM8903_MICDET_INV;
@@ -1679,8 +1696,8 @@ static irqreturn_t wm8903_irq(int irq, void *data)
 		msleep(wm8903->mic_delay);
 	}
 
-	snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1,
-			    WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol);
+	regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1,
+			   WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol);
 
 	snd_soc_jack_report(wm8903->mic_jack, mic_report,
 			    wm8903->mic_short | wm8903->mic_det);
@@ -1774,7 +1791,6 @@ static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset)
 static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
 {
 	struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
-	struct snd_soc_codec *codec = wm8903->codec;
 	unsigned int mask, val;
 	int ret;
 
@@ -1782,8 +1798,8 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
 	val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) |
 		WM8903_GP1_DIR;
 
-	ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
-				  mask, val);
+	ret = regmap_update_bits(wm8903->regmap,
+				 WM8903_GPIO_CONTROL_1 + offset, mask, val);
 	if (ret < 0)
 		return ret;
 
@@ -1793,10 +1809,9 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
 static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
-	struct snd_soc_codec *codec = wm8903->codec;
-	int reg;
+	unsigned int reg;
 
-	reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset);
+	regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, &reg);
 
 	return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT;
 }
@@ -1805,7 +1820,6 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip,
 				     unsigned offset, int value)
 {
 	struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
-	struct snd_soc_codec *codec = wm8903->codec;
 	unsigned int mask, val;
 	int ret;
 
@@ -1813,8 +1827,8 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip,
 	val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) |
 		(value << WM8903_GP2_LVL_SHIFT);
 
-	ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
-				  mask, val);
+	ret = regmap_update_bits(wm8903->regmap,
+				 WM8903_GPIO_CONTROL_1 + offset, mask, val);
 	if (ret < 0)
 		return ret;
 
@@ -1824,11 +1838,10 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip,
 static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
-	struct snd_soc_codec *codec = wm8903->codec;
 
-	snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
-			    WM8903_GP1_LVL_MASK,
-			    !!value << WM8903_GP1_LVL_SHIFT);
+	regmap_update_bits(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset,
+			   WM8903_GP1_LVL_MASK,
+			   !!value << WM8903_GP1_LVL_SHIFT);
 }
 
 static struct gpio_chip wm8903_template_chip = {
@@ -1842,15 +1855,14 @@ static struct gpio_chip wm8903_template_chip = {
 	.can_sleep		= 1,
 };
 
-static void wm8903_init_gpio(struct snd_soc_codec *codec)
+static void wm8903_init_gpio(struct wm8903_priv *wm8903)
 {
-	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 	struct wm8903_platform_data *pdata = wm8903->pdata;
 	int ret;
 
 	wm8903->gpio_chip = wm8903_template_chip;
 	wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO;
-	wm8903->gpio_chip.dev = codec->dev;
+	wm8903->gpio_chip.dev = wm8903->dev;
 
 	if (pdata->gpio_base)
 		wm8903->gpio_chip.base = pdata->gpio_base;
@@ -1859,24 +1871,23 @@ static void wm8903_init_gpio(struct snd_soc_codec *codec)
 
 	ret = gpiochip_add(&wm8903->gpio_chip);
 	if (ret != 0)
-		dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+		dev_err(wm8903->dev, "Failed to add GPIOs: %d\n", ret);
 }
 
-static void wm8903_free_gpio(struct snd_soc_codec *codec)
+static void wm8903_free_gpio(struct wm8903_priv *wm8903)
 {
-	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
 	ret = gpiochip_remove(&wm8903->gpio_chip);
 	if (ret != 0)
-		dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+		dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret);
 }
 #else
-static void wm8903_init_gpio(struct snd_soc_codec *codec)
+static void wm8903_init_gpio(struct wm8903_priv *wm8903)
 {
 }
 
-static void wm8903_free_gpio(struct snd_soc_codec *codec)
+static void wm8903_free_gpio(struct wm8903_priv *wm8903)
 {
 }
 #endif
@@ -1884,11 +1895,7 @@ static void wm8903_free_gpio(struct snd_soc_codec *codec)
 static int wm8903_probe(struct snd_soc_codec *codec)
 {
 	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-	struct wm8903_platform_data *pdata = wm8903->pdata;
-	int ret, i;
-	int trigger, irq_pol;
-	u16 val;
-	bool mic_gpio = false;
+	int ret;
 
 	wm8903->codec = codec;
 	codec->control_data = wm8903->regmap;
@@ -1899,121 +1906,16 @@ static int wm8903_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	/* Set up GPIOs, detect if any are MIC detect outputs */
-	for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
-		if ((!pdata->gpio_cfg[i]) ||
-		    (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO))
-			continue;
-
-		snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
-				pdata->gpio_cfg[i] & 0x7fff);
-
-		val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
-			>> WM8903_GP1_FN_SHIFT;
-
-		switch (val) {
-		case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
-		case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
-			mic_gpio = true;
-			break;
-		default:
-			break;
-		}
-	}
-
-	/* Set up microphone detection */
-	snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
-			pdata->micdet_cfg);
-
-	/* Microphone detection needs the WSEQ clock */
-	if (pdata->micdet_cfg)
-		snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
-				    WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
-
-	/* If microphone detection is enabled by pdata but
-	    * detected via IRQ then interrupts can be lost before
-	    * the machine driver has set up microphone detection
-	    * IRQs as the IRQs are clear on read.  The detection
-	    * will be enabled when the machine driver configures.
-	    */
-	WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
-
-	wm8903->mic_delay = pdata->micdet_delay;
-
-	if (wm8903->irq) {
-		if (pdata->irq_active_low) {
-			trigger = IRQF_TRIGGER_LOW;
-			irq_pol = WM8903_IRQ_POL;
-		} else {
-			trigger = IRQF_TRIGGER_HIGH;
-			irq_pol = 0;
-		}
-
-		snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL,
-				    WM8903_IRQ_POL, irq_pol);
-		
-		ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq,
-					   trigger | IRQF_ONESHOT,
-					   "wm8903", codec);
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to request IRQ: %d\n",
-				ret);
-			return ret;
-		}
-
-		/* Enable write sequencer interrupts */
-		snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK,
-				    WM8903_IM_WSEQ_BUSY_EINT, 0);
-	}
-
 	/* power on device */
 	wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	/* Latch volume update bits */
-	val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
-	val |= WM8903_ADCVU;
-	snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
-	snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
-
-	val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
-	val |= WM8903_DACVU;
-	snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
-	snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
-
-	val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
-	val |= WM8903_HPOUTVU;
-	snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
-	snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
-
-	val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
-	val |= WM8903_LINEOUTVU;
-	snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
-	snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
-
-	val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
-	val |= WM8903_SPKVU;
-	snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
-	snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
-
-	/* Enable DAC soft mute by default */
-	snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1,
-			    WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE,
-			    WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE);
-
-	wm8903_init_gpio(codec);
-
 	return ret;
 }
 
 /* power down chip */
 static int wm8903_remove(struct snd_soc_codec *codec)
 {
-	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-
-	wm8903_free_gpio(codec);
 	wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
-	if (wm8903->irq)
-		free_irq(wm8903->irq, codec);
 
 	return 0;
 }
@@ -2123,15 +2025,18 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
 {
 	struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
 	struct wm8903_priv *wm8903;
-	unsigned int val;
-	int ret;
+	int trigger;
+	bool mic_gpio = false;
+	unsigned int val, irq_pol;
+	int ret, i;
 
 	wm8903 = devm_kzalloc(&i2c->dev,  sizeof(struct wm8903_priv),
 			      GFP_KERNEL);
 	if (wm8903 == NULL)
 		return -ENOMEM;
+	wm8903->dev = &i2c->dev;
 
-	wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap);
+	wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap);
 	if (IS_ERR(wm8903->regmap)) {
 		ret = PTR_ERR(wm8903->regmap);
 		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -2140,7 +2045,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
 	}
 
 	i2c_set_clientdata(i2c, wm8903);
-	wm8903->irq = i2c->irq;
 
 	/* If no platform data was supplied, create storage for defaults */
 	if (pdata) {
@@ -2167,6 +2071,8 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
 		}
 	}
 
+	pdata = wm8903->pdata;
+
 	ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val);
 	if (ret != 0) {
 		dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
@@ -2189,6 +2095,107 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
 	/* Reset the device */
 	regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903);
 
+	wm8903_init_gpio(wm8903);
+
+	/* Set up GPIO pin state, detect if any are MIC detect outputs */
+	for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
+		if ((!pdata->gpio_cfg[i]) ||
+		    (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO))
+			continue;
+
+		regmap_write(wm8903->regmap, WM8903_GPIO_CONTROL_1 + i,
+				pdata->gpio_cfg[i] & 0x7fff);
+
+		val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
+			>> WM8903_GP1_FN_SHIFT;
+
+		switch (val) {
+		case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
+		case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
+			mic_gpio = true;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* Set up microphone detection */
+	regmap_write(wm8903->regmap, WM8903_MIC_BIAS_CONTROL_0,
+		     pdata->micdet_cfg);
+
+	/* Microphone detection needs the WSEQ clock */
+	if (pdata->micdet_cfg)
+		regmap_update_bits(wm8903->regmap, WM8903_WRITE_SEQUENCER_0,
+				   WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
+
+	/* If microphone detection is enabled by pdata but
+	 * detected via IRQ then interrupts can be lost before
+	 * the machine driver has set up microphone detection
+	 * IRQs as the IRQs are clear on read.  The detection
+	 * will be enabled when the machine driver configures.
+	 */
+	WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
+
+	wm8903->mic_delay = pdata->micdet_delay;
+
+	if (i2c->irq) {
+		if (pdata->irq_active_low) {
+			trigger = IRQF_TRIGGER_LOW;
+			irq_pol = WM8903_IRQ_POL;
+		} else {
+			trigger = IRQF_TRIGGER_HIGH;
+			irq_pol = 0;
+		}
+
+		regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_CONTROL,
+				   WM8903_IRQ_POL, irq_pol);
+
+		ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq,
+					   trigger | IRQF_ONESHOT,
+					   "wm8903", wm8903);
+		if (ret != 0) {
+			dev_err(wm8903->dev, "Failed to request IRQ: %d\n",
+				ret);
+			return ret;
+		}
+
+		/* Enable write sequencer interrupts */
+		regmap_update_bits(wm8903->regmap,
+				   WM8903_INTERRUPT_STATUS_1_MASK,
+				   WM8903_IM_WSEQ_BUSY_EINT, 0);
+	}
+
+	/* Latch volume update bits */
+	regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_LEFT,
+			   WM8903_ADCVU, WM8903_ADCVU);
+	regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_RIGHT,
+			   WM8903_ADCVU, WM8903_ADCVU);
+
+	regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_LEFT,
+			   WM8903_DACVU, WM8903_DACVU);
+	regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_RIGHT,
+			   WM8903_DACVU, WM8903_DACVU);
+
+	regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_LEFT,
+			   WM8903_HPOUTVU, WM8903_HPOUTVU);
+	regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_RIGHT,
+			   WM8903_HPOUTVU, WM8903_HPOUTVU);
+
+	regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_LEFT,
+			   WM8903_LINEOUTVU, WM8903_LINEOUTVU);
+	regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_RIGHT,
+			   WM8903_LINEOUTVU, WM8903_LINEOUTVU);
+
+	regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_LEFT,
+			   WM8903_SPKVU, WM8903_SPKVU);
+	regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_RIGHT,
+			   WM8903_SPKVU, WM8903_SPKVU);
+
+	/* Enable DAC soft mute by default */
+	regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_1,
+			   WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE,
+			   WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE);
+
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8903, &wm8903_dai, 1);
 	if (ret != 0)
@@ -2196,7 +2203,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
 
 	return 0;
 err:
-	regmap_exit(wm8903->regmap);
 	return ret;
 }
 
@@ -2204,7 +2210,9 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
 {
 	struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
 
-	regmap_exit(wm8903->regmap);
+	if (client->irq)
+		free_irq(client->irq, wm8903);
+	wm8903_free_gpio(wm8903);
 	snd_soc_unregister_codec(&client->dev);
 
 	return 0;
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 812acd83fb48..0013afe48e66 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1,7 +1,7 @@
 /*
  * wm8904.c  --  WM8904 ALSA SoC Audio driver
  *
- * Copyright 2009 Wolfson Microelectronics plc
+ * Copyright 2009-12 Wolfson Microelectronics plc
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
@@ -314,11 +314,6 @@ static bool wm8904_readable_register(struct device *dev, unsigned int reg)
 	}
 }
 
-static int wm8904_reset(struct snd_soc_codec *codec)
-{
-	return snd_soc_write(codec, WM8904_SW_RESET_AND_ID, 0);
-}
-
 static int wm8904_configure_clocking(struct snd_soc_codec *codec)
 {
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
@@ -1945,25 +1940,6 @@ static struct snd_soc_dai_driver wm8904_dai = {
 	.symmetric_rates = 1,
 };
 
-#ifdef CONFIG_PM
-static int wm8904_suspend(struct snd_soc_codec *codec)
-{
-	wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-	return 0;
-}
-
-static int wm8904_resume(struct snd_soc_codec *codec)
-{
-	wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-	return 0;
-}
-#else
-#define wm8904_suspend NULL
-#define wm8904_resume NULL
-#endif
-
 static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
 {
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
@@ -2078,8 +2054,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
 static int wm8904_probe(struct snd_soc_codec *codec)
 {
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
-	struct wm8904_pdata *pdata = wm8904->pdata;
-	int ret, i;
+	int ret;
 
 	codec->control_data = wm8904->regmap;
 
@@ -2101,127 +2076,17 @@ static int wm8904_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
-		wm8904->supplies[i].supply = wm8904_supply_names[i];
-
-	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8904->supplies),
-				 wm8904->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-		return ret;
-	}
-
-	ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies),
-				    wm8904->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-		goto err_get;
-	}
-
-	ret = snd_soc_read(codec, WM8904_SW_RESET_AND_ID);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to read ID register\n");
-		goto err_enable;
-	}
-	if (ret != 0x8904) {
-		dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret);
-		ret = -EINVAL;
-		goto err_enable;
-	}
-
-	ret = snd_soc_read(codec, WM8904_REVISION);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to read device revision: %d\n",
-			ret);
-		goto err_enable;
-	}
-	dev_info(codec->dev, "revision %c\n", ret + 'A');
-
-	ret = wm8904_reset(codec);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to issue reset\n");
-		goto err_enable;
-	}
-
-	regcache_cache_only(wm8904->regmap, true);
-	/* Change some default settings - latch VU and enable ZC */
-	snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT,
-			    WM8904_ADC_VU, WM8904_ADC_VU);
-	snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT,
-			    WM8904_ADC_VU, WM8904_ADC_VU);
-	snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT,
-			    WM8904_DAC_VU, WM8904_DAC_VU);
-	snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT,
-			    WM8904_DAC_VU, WM8904_DAC_VU);
-	snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT,
-			    WM8904_HPOUT_VU | WM8904_HPOUTLZC,
-			    WM8904_HPOUT_VU | WM8904_HPOUTLZC);
-	snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT,
-			    WM8904_HPOUT_VU | WM8904_HPOUTRZC,
-			    WM8904_HPOUT_VU | WM8904_HPOUTRZC);
-	snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT,
-			    WM8904_LINEOUT_VU | WM8904_LINEOUTLZC,
-			    WM8904_LINEOUT_VU | WM8904_LINEOUTLZC);
-	snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT,
-			    WM8904_LINEOUT_VU | WM8904_LINEOUTRZC,
-			    WM8904_LINEOUT_VU | WM8904_LINEOUTRZC);
-	snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0,
-			    WM8904_SR_MODE, 0);
-
-	/* Apply configuration from the platform data. */
-	if (wm8904->pdata) {
-		for (i = 0; i < WM8904_GPIO_REGS; i++) {
-			if (!pdata->gpio_cfg[i])
-				continue;
-
-			regmap_update_bits(wm8904->regmap,
-					   WM8904_GPIO_CONTROL_1 + i,
-					   0xffff,
-					   pdata->gpio_cfg[i]);
-		}
-
-		/* Zero is the default value for these anyway */
-		for (i = 0; i < WM8904_MIC_REGS; i++)
-			regmap_update_bits(wm8904->regmap,
-					   WM8904_MIC_BIAS_CONTROL_0 + i,
-					   0xffff,
-					   pdata->mic_cfg[i]);
-	}
-
-	/* Set Class W by default - this will be managed by the Class
-	 * G widget at runtime where bypass paths are available.
-	 */
-	snd_soc_update_bits(codec, WM8904_CLASS_W_0,
-			    WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR);
-
-	/* Use normal bias source */
-	snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
-			    WM8904_POBCTRL, 0);
-
-	wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-	/* Bias level configuration will have done an extra enable */
-	regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
-
 	wm8904_handle_pdata(codec);
 
 	wm8904_add_widgets(codec);
 
 	return 0;
-
-err_enable:
-	regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
-err_get:
-	regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
-	return ret;
 }
 
 static int wm8904_remove(struct snd_soc_codec *codec)
 {
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
-	wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
-	regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
 	kfree(wm8904->retune_mobile_texts);
 	kfree(wm8904->drc_texts);
 
@@ -2231,8 +2096,6 @@ static int wm8904_remove(struct snd_soc_codec *codec)
 static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
 	.probe =	wm8904_probe,
 	.remove =	wm8904_remove,
-	.suspend =	wm8904_suspend,
-	.resume =	wm8904_resume,
 	.set_bias_level = wm8904_set_bias_level,
 	.idle_bias_off = true,
 };
@@ -2254,14 +2117,15 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8904_priv *wm8904;
-	int ret;
+	unsigned int val;
+	int ret, i;
 
 	wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv),
 			      GFP_KERNEL);
 	if (wm8904 == NULL)
 		return -ENOMEM;
 
-	wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap);
+	wm8904->regmap = devm_regmap_init_i2c(i2c, &wm8904_regmap);
 	if (IS_ERR(wm8904->regmap)) {
 		ret = PTR_ERR(wm8904->regmap);
 		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -2273,23 +2137,121 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
 	i2c_set_clientdata(i2c, wm8904);
 	wm8904->pdata = i2c->dev.platform_data;
 
+	for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
+		wm8904->supplies[i].supply = wm8904_supply_names[i];
+
+	ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8904->supplies),
+				      wm8904->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies),
+				    wm8904->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+		return ret;
+	}
+
+	ret = regmap_read(wm8904->regmap, WM8904_SW_RESET_AND_ID, &val);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+		goto err_enable;
+	}
+	if (val != 0x8904) {
+		dev_err(&i2c->dev, "Device is not a WM8904, ID is %x\n", val);
+		ret = -EINVAL;
+		goto err_enable;
+	}
+
+	ret = regmap_read(wm8904->regmap, WM8904_REVISION, &val);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read device revision: %d\n",
+			ret);
+		goto err_enable;
+	}
+	dev_info(&i2c->dev, "revision %c\n", val + 'A');
+
+	ret = regmap_write(wm8904->regmap, WM8904_SW_RESET_AND_ID, 0);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
+		goto err_enable;
+	}
+
+	/* Change some default settings - latch VU and enable ZC */
+	regmap_update_bits(wm8904->regmap, WM8904_ADC_DIGITAL_VOLUME_LEFT,
+			   WM8904_ADC_VU, WM8904_ADC_VU);
+	regmap_update_bits(wm8904->regmap, WM8904_ADC_DIGITAL_VOLUME_RIGHT,
+			   WM8904_ADC_VU, WM8904_ADC_VU);
+	regmap_update_bits(wm8904->regmap, WM8904_DAC_DIGITAL_VOLUME_LEFT,
+			   WM8904_DAC_VU, WM8904_DAC_VU);
+	regmap_update_bits(wm8904->regmap, WM8904_DAC_DIGITAL_VOLUME_RIGHT,
+			   WM8904_DAC_VU, WM8904_DAC_VU);
+	regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT1_LEFT,
+			   WM8904_HPOUT_VU | WM8904_HPOUTLZC,
+			   WM8904_HPOUT_VU | WM8904_HPOUTLZC);
+	regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT1_RIGHT,
+			   WM8904_HPOUT_VU | WM8904_HPOUTRZC,
+			   WM8904_HPOUT_VU | WM8904_HPOUTRZC);
+	regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT2_LEFT,
+			   WM8904_LINEOUT_VU | WM8904_LINEOUTLZC,
+			   WM8904_LINEOUT_VU | WM8904_LINEOUTLZC);
+	regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT2_RIGHT,
+			   WM8904_LINEOUT_VU | WM8904_LINEOUTRZC,
+			   WM8904_LINEOUT_VU | WM8904_LINEOUTRZC);
+	regmap_update_bits(wm8904->regmap, WM8904_CLOCK_RATES_0,
+			   WM8904_SR_MODE, 0);
+
+	/* Apply configuration from the platform data. */
+	if (wm8904->pdata) {
+		for (i = 0; i < WM8904_GPIO_REGS; i++) {
+			if (!wm8904->pdata->gpio_cfg[i])
+				continue;
+
+			regmap_update_bits(wm8904->regmap,
+					   WM8904_GPIO_CONTROL_1 + i,
+					   0xffff,
+					   wm8904->pdata->gpio_cfg[i]);
+		}
+
+		/* Zero is the default value for these anyway */
+		for (i = 0; i < WM8904_MIC_REGS; i++)
+			regmap_update_bits(wm8904->regmap,
+					   WM8904_MIC_BIAS_CONTROL_0 + i,
+					   0xffff,
+					   wm8904->pdata->mic_cfg[i]);
+	}
+
+	/* Set Class W by default - this will be managed by the Class
+	 * G widget at runtime where bypass paths are available.
+	 */
+	regmap_update_bits(wm8904->regmap, WM8904_CLASS_W_0,
+			    WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR);
+
+	/* Use normal bias source */
+	regmap_update_bits(wm8904->regmap, WM8904_BIAS_CONTROL_0,
+			    WM8904_POBCTRL, 0);
+
+	/* Can leave the device powered off until we need it */
+	regcache_cache_only(wm8904->regmap, true);
+	regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
+
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8904, &wm8904_dai, 1);
 	if (ret != 0)
-		goto err;
+		return ret;
 
 	return 0;
 
-err:
-	regmap_exit(wm8904->regmap);
+err_enable:
+	regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
 	return ret;
 }
 
 static __devexit int wm8904_i2c_remove(struct i2c_client *client)
 {
-	struct wm8904_priv *wm8904 = i2c_get_clientdata(client);
 	snd_soc_unregister_codec(&client->dev);
-	regmap_exit(wm8904->regmap);
 	return 0;
 }
 
@@ -2311,23 +2273,7 @@ static struct i2c_driver wm8904_i2c_driver = {
 	.id_table = wm8904_i2c_id,
 };
 
-static int __init wm8904_modinit(void)
-{
-	int ret = 0;
-	ret = i2c_add_driver(&wm8904_i2c_driver);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
-		       ret);
-	}
-	return ret;
-}
-module_init(wm8904_modinit);
-
-static void __exit wm8904_exit(void)
-{
-	i2c_del_driver(&wm8904_i2c_driver);
-}
-module_exit(wm8904_exit);
+module_i2c_driver(wm8904_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8904 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 8bc659d8dd2e..96518ac8e24c 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1,6 +1,8 @@
 /*
  * wm8960.c  --  WM8960 ALSA SoC Audio driver
  *
+ * Copyright 2007-11 Wolfson Microelectronics, plc
+ *
  * Author: Liam Girdwood
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 05ea7c274093..01edbcc754d2 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -1,6 +1,8 @@
 /*
  * wm8961.c  --  WM8961 ALSA SoC Audio driver
  *
+ * Copyright 2009-10 Wolfson Microelectronics, plc
+ *
  * Author: Mark Brown
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 0cfce9999c89..eaf65863ec21 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1,7 +1,7 @@
 /*
  * wm8962.c  --  WM8962 ALSA SoC Audio driver
  *
- * Copyright 2010 Wolfson Microelectronics plc
+ * Copyright 2010-2 Wolfson Microelectronics plc
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
@@ -2580,6 +2580,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
 			    WM8962_SAMPLE_RATE_INT_MODE |
 			    WM8962_SAMPLE_RATE_MASK, adctl3);
 
+	dev_dbg(codec->dev, "hw_params set BCLK %dHz LRCLK %dHz\n",
+		wm8962->bclk, wm8962->lrclk);
+
 	if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
 		wm8962_configure_bclk(codec);
 
@@ -3722,6 +3725,9 @@ static int wm8962_runtime_resume(struct device *dev)
 	}
 
 	regcache_cache_only(wm8962->regmap, false);
+
+	wm8962_reset(wm8962);
+
 	regcache_sync(wm8962->regmap);
 
 	regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 36acfccab999..9fd80d688979 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1,7 +1,7 @@
 /*
  * wm8993.c -- WM8993 ALSA SoC audio driver
  *
- * Copyright 2009, 2010 Wolfson Microelectronics plc
+ * Copyright 2009-12 Wolfson Microelectronics plc
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 1436b6ce74d1..bb62f4b3d563 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -1,7 +1,7 @@
 /*
  * wm8994.c  --  WM8994 ALSA SoC Audio driver
  *
- * Copyright 2009 Wolfson Microelectronics plc
+ * Copyright 2009-12 Wolfson Microelectronics plc
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
@@ -2967,23 +2967,8 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
 static int wm8994_codec_suspend(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	struct wm8994 *control = wm8994->wm8994;
 	int i, ret;
 
-	switch (control->type) {
-	case WM8994:
-		snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
-		break;
-	case WM1811:
-		snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-				    WM1811_JACKDET_MODE_MASK, 0);
-		/* Fall through */
-	case WM8958:
-		snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
-				    WM8958_MICD_ENA, 0);
-		break;
-	}
-
 	for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
 		memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i],
 		       sizeof(struct wm8994_fll_config));
@@ -3033,28 +3018,6 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
 				 i + 1, ret);
 	}
 
-	switch (control->type) {
-	case WM8994:
-		if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
-			snd_soc_update_bits(codec, WM8994_MICBIAS,
-					    WM8994_MICD_ENA, WM8994_MICD_ENA);
-		break;
-	case WM1811:
-		if (wm8994->jackdet && wm8994->jack_cb) {
-			/* Restart from idle */
-			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-					    WM1811_JACKDET_MODE_MASK,
-					    WM1811_JACKDET_MODE_JACK);
-			break;
-		}
-		break;
-	case WM8958:
-		if (wm8994->jack_cb)
-			snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
-					    WM8958_MICD_ENA, WM8958_MICD_ENA);
-		break;
-	}
-
 	return 0;
 }
 #else
@@ -3729,9 +3692,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
 	if (wm8994->pdata && wm8994->pdata->micdet_irq)
 		wm8994->micdet_irq = wm8994->pdata->micdet_irq;
-	else if (wm8994->pdata && wm8994->pdata->irq_base)
-		wm8994->micdet_irq = wm8994->pdata->irq_base +
-				     WM8994_IRQ_MIC1_DET;
 
 	pm_runtime_enable(codec->dev);
 	pm_runtime_idle(codec->dev);
@@ -3870,6 +3830,10 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 				dev_warn(codec->dev,
 					 "Failed to request Mic detect IRQ: %d\n",
 					 ret);
+		} else {
+			wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_MIC1_DET,
+					   wm8958_mic_irq, "Mic detect",
+					   wm8994);
 		}
 	}
 
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index dc9b42b7fc4d..00f183dfa454 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -1,7 +1,7 @@
 /*
  * wm8996.c - WM8996 audio codec interface
  *
- * Copyright 2011 Wolfson Microelectronics PLC.
+ * Copyright 2011-2 Wolfson Microelectronics PLC.
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -296,184 +296,6 @@ static struct reg_default wm8996_reg[] = {
 	{ WM8996_RIGHT_PDM_SPEAKER, 0x1 },
 	{ WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 },
 	{ WM8996_PDM_SPEAKER_VOLUME, 0x66 },
-	{ WM8996_WRITE_SEQUENCER_0, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_1, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_3, 0x6 },
-	{ WM8996_WRITE_SEQUENCER_4, 0x40 },
-	{ WM8996_WRITE_SEQUENCER_5, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_6, 0xf },
-	{ WM8996_WRITE_SEQUENCER_7, 0x6 },
-	{ WM8996_WRITE_SEQUENCER_8, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_9, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_10, 0x104 },
-	{ WM8996_WRITE_SEQUENCER_12, 0x60 },
-	{ WM8996_WRITE_SEQUENCER_13, 0x11 },
-	{ WM8996_WRITE_SEQUENCER_14, 0x401 },
-	{ WM8996_WRITE_SEQUENCER_16, 0x50 },
-	{ WM8996_WRITE_SEQUENCER_17, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_18, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_20, 0x51 },
-	{ WM8996_WRITE_SEQUENCER_21, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_22, 0x104 },
-	{ WM8996_WRITE_SEQUENCER_23, 0xa },
-	{ WM8996_WRITE_SEQUENCER_24, 0x60 },
-	{ WM8996_WRITE_SEQUENCER_25, 0x3b },
-	{ WM8996_WRITE_SEQUENCER_26, 0x502 },
-	{ WM8996_WRITE_SEQUENCER_27, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_28, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_32, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_36, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_40, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_44, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_48, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_52, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_56, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_60, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_64, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_65, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_67, 0x6 },
-	{ WM8996_WRITE_SEQUENCER_68, 0x40 },
-	{ WM8996_WRITE_SEQUENCER_69, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_70, 0xf },
-	{ WM8996_WRITE_SEQUENCER_71, 0x6 },
-	{ WM8996_WRITE_SEQUENCER_72, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_73, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_74, 0x104 },
-	{ WM8996_WRITE_SEQUENCER_76, 0x60 },
-	{ WM8996_WRITE_SEQUENCER_77, 0x11 },
-	{ WM8996_WRITE_SEQUENCER_78, 0x401 },
-	{ WM8996_WRITE_SEQUENCER_80, 0x50 },
-	{ WM8996_WRITE_SEQUENCER_81, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_82, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_84, 0x60 },
-	{ WM8996_WRITE_SEQUENCER_85, 0x3b },
-	{ WM8996_WRITE_SEQUENCER_86, 0x502 },
-	{ WM8996_WRITE_SEQUENCER_87, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_88, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_92, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_96, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_100, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_104, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_108, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_112, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_116, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_120, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_124, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_128, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_129, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_131, 0x6 },
-	{ WM8996_WRITE_SEQUENCER_132, 0x40 },
-	{ WM8996_WRITE_SEQUENCER_133, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_134, 0xf },
-	{ WM8996_WRITE_SEQUENCER_135, 0x6 },
-	{ WM8996_WRITE_SEQUENCER_136, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_137, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_138, 0x106 },
-	{ WM8996_WRITE_SEQUENCER_140, 0x61 },
-	{ WM8996_WRITE_SEQUENCER_141, 0x11 },
-	{ WM8996_WRITE_SEQUENCER_142, 0x401 },
-	{ WM8996_WRITE_SEQUENCER_144, 0x50 },
-	{ WM8996_WRITE_SEQUENCER_145, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_146, 0x102 },
-	{ WM8996_WRITE_SEQUENCER_148, 0x51 },
-	{ WM8996_WRITE_SEQUENCER_149, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_150, 0x106 },
-	{ WM8996_WRITE_SEQUENCER_151, 0xa },
-	{ WM8996_WRITE_SEQUENCER_152, 0x61 },
-	{ WM8996_WRITE_SEQUENCER_153, 0x3b },
-	{ WM8996_WRITE_SEQUENCER_154, 0x502 },
-	{ WM8996_WRITE_SEQUENCER_155, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_156, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_160, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_164, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_168, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_172, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_176, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_180, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_184, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_188, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_192, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_193, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_195, 0x6 },
-	{ WM8996_WRITE_SEQUENCER_196, 0x40 },
-	{ WM8996_WRITE_SEQUENCER_197, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_198, 0xf },
-	{ WM8996_WRITE_SEQUENCER_199, 0x6 },
-	{ WM8996_WRITE_SEQUENCER_200, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_201, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_202, 0x106 },
-	{ WM8996_WRITE_SEQUENCER_204, 0x61 },
-	{ WM8996_WRITE_SEQUENCER_205, 0x11 },
-	{ WM8996_WRITE_SEQUENCER_206, 0x401 },
-	{ WM8996_WRITE_SEQUENCER_208, 0x50 },
-	{ WM8996_WRITE_SEQUENCER_209, 0x3 },
-	{ WM8996_WRITE_SEQUENCER_210, 0x102 },
-	{ WM8996_WRITE_SEQUENCER_212, 0x61 },
-	{ WM8996_WRITE_SEQUENCER_213, 0x3b },
-	{ WM8996_WRITE_SEQUENCER_214, 0x502 },
-	{ WM8996_WRITE_SEQUENCER_215, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_216, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_220, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_224, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_228, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_232, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_236, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_240, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_244, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_248, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_252, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_256, 0x60 },
-	{ WM8996_WRITE_SEQUENCER_258, 0x601 },
-	{ WM8996_WRITE_SEQUENCER_260, 0x50 },
-	{ WM8996_WRITE_SEQUENCER_262, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_264, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_266, 0x104 },
-	{ WM8996_WRITE_SEQUENCER_267, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_268, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_272, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_276, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_280, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_284, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_288, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_292, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_296, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_300, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_304, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_308, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_312, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_316, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_320, 0x61 },
-	{ WM8996_WRITE_SEQUENCER_322, 0x601 },
-	{ WM8996_WRITE_SEQUENCER_324, 0x50 },
-	{ WM8996_WRITE_SEQUENCER_326, 0x102 },
-	{ WM8996_WRITE_SEQUENCER_328, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_330, 0x106 },
-	{ WM8996_WRITE_SEQUENCER_331, 0x100 },
-	{ WM8996_WRITE_SEQUENCER_332, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_336, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_340, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_344, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_348, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_352, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_356, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_360, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_364, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_368, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_372, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_376, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_380, 0x2fff },
-	{ WM8996_WRITE_SEQUENCER_384, 0x60 },
-	{ WM8996_WRITE_SEQUENCER_386, 0x601 },
-	{ WM8996_WRITE_SEQUENCER_388, 0x61 },
-	{ WM8996_WRITE_SEQUENCER_390, 0x601 },
-	{ WM8996_WRITE_SEQUENCER_392, 0x50 },
-	{ WM8996_WRITE_SEQUENCER_394, 0x300 },
-	{ WM8996_WRITE_SEQUENCER_396, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_398, 0x304 },
-	{ WM8996_WRITE_SEQUENCER_400, 0x40 },
-	{ WM8996_WRITE_SEQUENCER_402, 0xf },
-	{ WM8996_WRITE_SEQUENCER_404, 0x1 },
-	{ WM8996_WRITE_SEQUENCER_407, 0x100 },
 };
 
 static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0);
@@ -1706,18 +1528,6 @@ static bool wm8996_volatile_register(struct device *dev, unsigned int reg)
 	}
 }
 
-static int wm8996_reset(struct wm8996_priv *wm8996)
-{
-	if (wm8996->pdata.ldo_ena > 0) {
-		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
-		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
-		return 0;
-	} else {
-		return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
-				    0x8915);
-	}
-}
-
 static const int bclk_divs[] = {
 	1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
 };
@@ -1809,8 +1619,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
 
 	case SND_SOC_BIAS_OFF:
 		regcache_cache_only(codec->control_data, true);
-		if (wm8996->pdata.ldo_ena >= 0)
+		if (wm8996->pdata.ldo_ena >= 0) {
 			gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+			regcache_cache_only(codec->control_data, true);
+		}
 		regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies),
 				       wm8996->supplies);
 		break;
@@ -2807,7 +2619,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
 	int ret;
 	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	struct i2c_client *i2c = to_i2c_client(codec->dev);
-	int i, irq_flags;
+	int irq_flags;
 
 	wm8996->codec = codec;
 
@@ -2822,177 +2634,12 @@ static int wm8996_probe(struct snd_soc_codec *codec)
 		goto err;
 	}
 
-	wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0;
-	wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
-	wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
-
-	/* This should really be moved into the regulator core */
-	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
-		ret = regulator_register_notifier(wm8996->supplies[i].consumer,
-						  &wm8996->disable_nb[i]);
-		if (ret != 0) {
-			dev_err(codec->dev,
-				"Failed to register regulator notifier: %d\n",
-				ret);
-		}
-	}
-
-	/* Apply platform data settings */
-	snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL,
-			    WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK,
-			    wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT |
-			    wm8996->pdata.inr_mode);
-
-	for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) {
-		if (!wm8996->pdata.gpio_default[i])
-			continue;
-
-		snd_soc_write(codec, WM8996_GPIO_1 + i,
-			      wm8996->pdata.gpio_default[i] & 0xffff);
-	}
-
-	if (wm8996->pdata.spkmute_seq)
-		snd_soc_update_bits(codec, WM8996_PDM_SPEAKER_MUTE_SEQUENCE,
-				    WM8996_SPK_MUTE_ENDIAN |
-				    WM8996_SPK_MUTE_SEQ1_MASK,
-				    wm8996->pdata.spkmute_seq);
-
-	snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2,
-			    WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC |
-			    WM8996_MICD_SRC, wm8996->pdata.micdet_def);
-
-	/* Latch volume update bits */
-	snd_soc_update_bits(codec, WM8996_LEFT_LINE_INPUT_VOLUME,
-			    WM8996_IN1_VU, WM8996_IN1_VU);
-	snd_soc_update_bits(codec, WM8996_RIGHT_LINE_INPUT_VOLUME,
-			    WM8996_IN1_VU, WM8996_IN1_VU);
-
-	snd_soc_update_bits(codec, WM8996_DAC1_LEFT_VOLUME,
-			    WM8996_DAC1_VU, WM8996_DAC1_VU);
-	snd_soc_update_bits(codec, WM8996_DAC1_RIGHT_VOLUME,
-			    WM8996_DAC1_VU, WM8996_DAC1_VU);
-	snd_soc_update_bits(codec, WM8996_DAC2_LEFT_VOLUME,
-			    WM8996_DAC2_VU, WM8996_DAC2_VU);
-	snd_soc_update_bits(codec, WM8996_DAC2_RIGHT_VOLUME,
-			    WM8996_DAC2_VU, WM8996_DAC2_VU);
-
-	snd_soc_update_bits(codec, WM8996_OUTPUT1_LEFT_VOLUME,
-			    WM8996_DAC1_VU, WM8996_DAC1_VU);
-	snd_soc_update_bits(codec, WM8996_OUTPUT1_RIGHT_VOLUME,
-			    WM8996_DAC1_VU, WM8996_DAC1_VU);
-	snd_soc_update_bits(codec, WM8996_OUTPUT2_LEFT_VOLUME,
-			    WM8996_DAC2_VU, WM8996_DAC2_VU);
-	snd_soc_update_bits(codec, WM8996_OUTPUT2_RIGHT_VOLUME,
-			    WM8996_DAC2_VU, WM8996_DAC2_VU);
-
-	snd_soc_update_bits(codec, WM8996_DSP1_TX_LEFT_VOLUME,
-			    WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
-	snd_soc_update_bits(codec, WM8996_DSP1_TX_RIGHT_VOLUME,
-			    WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
-	snd_soc_update_bits(codec, WM8996_DSP2_TX_LEFT_VOLUME,
-			    WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
-	snd_soc_update_bits(codec, WM8996_DSP2_TX_RIGHT_VOLUME,
-			    WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
-
-	snd_soc_update_bits(codec, WM8996_DSP1_RX_LEFT_VOLUME,
-			    WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
-	snd_soc_update_bits(codec, WM8996_DSP1_RX_RIGHT_VOLUME,
-			    WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
-	snd_soc_update_bits(codec, WM8996_DSP2_RX_LEFT_VOLUME,
-			    WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
-	snd_soc_update_bits(codec, WM8996_DSP2_RX_RIGHT_VOLUME,
-			    WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
-
-	/* No support currently for the underclocked TDM modes and
-	 * pick a default TDM layout with each channel pair working with
-	 * slots 0 and 1. */
-	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_0_CONFIGURATION,
-			    WM8996_AIF1RX_CHAN0_SLOTS_MASK |
-			    WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0);
-	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_1_CONFIGURATION,
-			    WM8996_AIF1RX_CHAN1_SLOTS_MASK |
-			    WM8996_AIF1RX_CHAN1_START_SLOT_MASK,
-			    1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1);
-	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_2_CONFIGURATION,
-			    WM8996_AIF1RX_CHAN2_SLOTS_MASK |
-			    WM8996_AIF1RX_CHAN2_START_SLOT_MASK,
-			    1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0);
-	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_3_CONFIGURATION,
-			    WM8996_AIF1RX_CHAN3_SLOTS_MASK |
-			    WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1);
-	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_4_CONFIGURATION,
-			    WM8996_AIF1RX_CHAN4_SLOTS_MASK |
-			    WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0);
-	snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_5_CONFIGURATION,
-			    WM8996_AIF1RX_CHAN5_SLOTS_MASK |
-			    WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1);
-
-	snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_0_CONFIGURATION,
-			    WM8996_AIF2RX_CHAN0_SLOTS_MASK |
-			    WM8996_AIF2RX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0);
-	snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_1_CONFIGURATION,
-			    WM8996_AIF2RX_CHAN1_SLOTS_MASK |
-			    WM8996_AIF2RX_CHAN1_START_SLOT_MASK,
-			    1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1);
-
-	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_0_CONFIGURATION,
-			    WM8996_AIF1TX_CHAN0_SLOTS_MASK |
-			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0);
-	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
-			    WM8996_AIF1TX_CHAN1_SLOTS_MASK |
-			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
-	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_2_CONFIGURATION,
-			    WM8996_AIF1TX_CHAN2_SLOTS_MASK |
-			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0);
-	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_3_CONFIGURATION,
-			    WM8996_AIF1TX_CHAN3_SLOTS_MASK |
-			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1);
-	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_4_CONFIGURATION,
-			    WM8996_AIF1TX_CHAN4_SLOTS_MASK |
-			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0);
-	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_5_CONFIGURATION,
-			    WM8996_AIF1TX_CHAN5_SLOTS_MASK |
-			    WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1);
-
-	snd_soc_update_bits(codec, WM8996_AIF2TX_CHANNEL_0_CONFIGURATION,
-			    WM8996_AIF2TX_CHAN0_SLOTS_MASK |
-			    WM8996_AIF2TX_CHAN0_START_SLOT_MASK,
-			    1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0);
-	snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
-			    WM8996_AIF2TX_CHAN1_SLOTS_MASK |
-			    WM8996_AIF2TX_CHAN1_START_SLOT_MASK,
-			    1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
-
 	if (wm8996->pdata.num_retune_mobile_cfgs)
 		wm8996_retune_mobile_pdata(codec);
 	else
 		snd_soc_add_codec_controls(codec, wm8996_eq_controls,
 				     ARRAY_SIZE(wm8996_eq_controls));
 
-	/* If the TX LRCLK pins are not in LRCLK mode configure the
-	 * AIFs to source their clocks from the RX LRCLKs.
-	 */
-	if ((snd_soc_read(codec, WM8996_GPIO_1)))
-		snd_soc_update_bits(codec, WM8996_AIF1_TX_LRCLK_2,
-				    WM8996_AIF1TX_LRCLK_MODE,
-				    WM8996_AIF1TX_LRCLK_MODE);
-
-	if ((snd_soc_read(codec, WM8996_GPIO_2)))
-		snd_soc_update_bits(codec, WM8996_AIF2_TX_LRCLK_2,
-				    WM8996_AIF2TX_LRCLK_MODE,
-				    WM8996_AIF2TX_LRCLK_MODE);
-
 	if (i2c->irq) {
 		if (wm8996->pdata.irq_flags)
 			irq_flags = wm8996->pdata.irq_flags;
@@ -3036,9 +2683,7 @@ err:
 
 static int wm8996_remove(struct snd_soc_codec *codec)
 {
-	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	struct i2c_client *i2c = to_i2c_client(codec->dev);
-	int i;
 
 	snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL,
 			    WM8996_IM_IRQ, WM8996_IM_IRQ);
@@ -3046,10 +2691,6 @@ static int wm8996_remove(struct snd_soc_codec *codec)
 	if (i2c->irq)
 		free_irq(i2c->irq, codec);
 
-	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
-		regulator_unregister_notifier(wm8996->supplies[i].consumer,
-					      &wm8996->disable_nb[i]);
-
 	return 0;
 }
 
@@ -3163,6 +2804,21 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
 		goto err_gpio;
 	}
 
+	wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0;
+	wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
+	wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
+
+	/* This should really be moved into the regulator core */
+	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
+		ret = regulator_register_notifier(wm8996->supplies[i].consumer,
+						  &wm8996->disable_nb[i]);
+		if (ret != 0) {
+			dev_err(&i2c->dev,
+				"Failed to register regulator notifier: %d\n",
+				ret);
+		}
+	}
+
 	ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
 				    wm8996->supplies);
 	if (ret != 0) {
@@ -3175,7 +2831,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
 		msleep(5);
 	}
 
-	wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap);
+	wm8996->regmap = devm_regmap_init_i2c(i2c, &wm8996_regmap);
 	if (IS_ERR(wm8996->regmap)) {
 		ret = PTR_ERR(wm8996->regmap);
 		dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
@@ -3203,15 +2859,199 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
 	dev_info(&i2c->dev, "revision %c\n",
 		 (reg & WM8996_CHIP_REV_MASK) + 'A');
 
-	ret = wm8996_reset(wm8996);
-	if (ret < 0) {
-		dev_err(&i2c->dev, "Failed to issue reset\n");
-		goto err_regmap;
+	if (wm8996->pdata.ldo_ena > 0) {
+		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+		regcache_cache_only(wm8996->regmap, true);
+	} else {
+		ret = regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
+				   0x8915);
+		if (ret != 0) {
+			dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
+			goto err_regmap;
+		}
 	}
 
-	regcache_cache_only(wm8996->regmap, true);
 	regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
 
+	/* Apply platform data settings */
+	regmap_update_bits(wm8996->regmap, WM8996_LINE_INPUT_CONTROL,
+			   WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK,
+			   wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT |
+			   wm8996->pdata.inr_mode);
+
+	for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) {
+		if (!wm8996->pdata.gpio_default[i])
+			continue;
+
+		regmap_write(wm8996->regmap, WM8996_GPIO_1 + i,
+			     wm8996->pdata.gpio_default[i] & 0xffff);
+	}
+
+	if (wm8996->pdata.spkmute_seq)
+		regmap_update_bits(wm8996->regmap,
+				   WM8996_PDM_SPEAKER_MUTE_SEQUENCE,
+				   WM8996_SPK_MUTE_ENDIAN |
+				   WM8996_SPK_MUTE_SEQ1_MASK,
+				   wm8996->pdata.spkmute_seq);
+
+	regmap_update_bits(wm8996->regmap, WM8996_ACCESSORY_DETECT_MODE_2,
+			   WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC |
+			   WM8996_MICD_SRC, wm8996->pdata.micdet_def);
+
+	/* Latch volume update bits */
+	regmap_update_bits(wm8996->regmap, WM8996_LEFT_LINE_INPUT_VOLUME,
+			   WM8996_IN1_VU, WM8996_IN1_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_RIGHT_LINE_INPUT_VOLUME,
+			   WM8996_IN1_VU, WM8996_IN1_VU);
+
+	regmap_update_bits(wm8996->regmap, WM8996_DAC1_LEFT_VOLUME,
+			   WM8996_DAC1_VU, WM8996_DAC1_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DAC1_RIGHT_VOLUME,
+			   WM8996_DAC1_VU, WM8996_DAC1_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DAC2_LEFT_VOLUME,
+			   WM8996_DAC2_VU, WM8996_DAC2_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DAC2_RIGHT_VOLUME,
+			   WM8996_DAC2_VU, WM8996_DAC2_VU);
+
+	regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_LEFT_VOLUME,
+			   WM8996_DAC1_VU, WM8996_DAC1_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_RIGHT_VOLUME,
+			   WM8996_DAC1_VU, WM8996_DAC1_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_LEFT_VOLUME,
+			   WM8996_DAC2_VU, WM8996_DAC2_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_RIGHT_VOLUME,
+			   WM8996_DAC2_VU, WM8996_DAC2_VU);
+
+	regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_LEFT_VOLUME,
+			   WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_RIGHT_VOLUME,
+			   WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_LEFT_VOLUME,
+			   WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_RIGHT_VOLUME,
+			   WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
+
+	regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_LEFT_VOLUME,
+			   WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_RIGHT_VOLUME,
+			   WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_LEFT_VOLUME,
+			   WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
+	regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_RIGHT_VOLUME,
+			   WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
+
+	/* No support currently for the underclocked TDM modes and
+	 * pick a default TDM layout with each channel pair working with
+	 * slots 0 and 1. */
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1RX_CHANNEL_0_CONFIGURATION,
+			   WM8996_AIF1RX_CHAN0_SLOTS_MASK |
+			   WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1RX_CHANNEL_1_CONFIGURATION,
+			   WM8996_AIF1RX_CHAN1_SLOTS_MASK |
+			   WM8996_AIF1RX_CHAN1_START_SLOT_MASK,
+			   1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1RX_CHANNEL_2_CONFIGURATION,
+			   WM8996_AIF1RX_CHAN2_SLOTS_MASK |
+			   WM8996_AIF1RX_CHAN2_START_SLOT_MASK,
+			   1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1RX_CHANNEL_3_CONFIGURATION,
+			   WM8996_AIF1RX_CHAN3_SLOTS_MASK |
+			   WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1RX_CHANNEL_4_CONFIGURATION,
+			   WM8996_AIF1RX_CHAN4_SLOTS_MASK |
+			   WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1RX_CHANNEL_5_CONFIGURATION,
+			   WM8996_AIF1RX_CHAN5_SLOTS_MASK |
+			   WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1);
+
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF2RX_CHANNEL_0_CONFIGURATION,
+			   WM8996_AIF2RX_CHAN0_SLOTS_MASK |
+			   WM8996_AIF2RX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF2RX_CHANNEL_1_CONFIGURATION,
+			   WM8996_AIF2RX_CHAN1_SLOTS_MASK |
+			   WM8996_AIF2RX_CHAN1_START_SLOT_MASK,
+			   1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1);
+
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1TX_CHANNEL_0_CONFIGURATION,
+			   WM8996_AIF1TX_CHAN0_SLOTS_MASK |
+			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
+			   WM8996_AIF1TX_CHAN1_SLOTS_MASK |
+			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1TX_CHANNEL_2_CONFIGURATION,
+			   WM8996_AIF1TX_CHAN2_SLOTS_MASK |
+			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1TX_CHANNEL_3_CONFIGURATION,
+			   WM8996_AIF1TX_CHAN3_SLOTS_MASK |
+			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1TX_CHANNEL_4_CONFIGURATION,
+			   WM8996_AIF1TX_CHAN4_SLOTS_MASK |
+			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1TX_CHANNEL_5_CONFIGURATION,
+			   WM8996_AIF1TX_CHAN5_SLOTS_MASK |
+			   WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1);
+
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF2TX_CHANNEL_0_CONFIGURATION,
+			   WM8996_AIF2TX_CHAN0_SLOTS_MASK |
+			   WM8996_AIF2TX_CHAN0_START_SLOT_MASK,
+			   1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0);
+	regmap_update_bits(wm8996->regmap,
+			   WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
+			   WM8996_AIF2TX_CHAN1_SLOTS_MASK |
+			   WM8996_AIF2TX_CHAN1_START_SLOT_MASK,
+			   1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
+
+	/* If the TX LRCLK pins are not in LRCLK mode configure the
+	 * AIFs to source their clocks from the RX LRCLKs.
+	 */
+	ret = regmap_read(wm8996->regmap, WM8996_GPIO_1, &reg);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to read GPIO1: %d\n", ret);
+		goto err_regmap;
+	}
+
+	if (reg & WM8996_GP1_FN_MASK)
+		regmap_update_bits(wm8996->regmap, WM8996_AIF1_TX_LRCLK_2,
+				   WM8996_AIF1TX_LRCLK_MODE,
+				   WM8996_AIF1TX_LRCLK_MODE);
+
+	ret = regmap_read(wm8996->regmap, WM8996_GPIO_2, &reg);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to read GPIO2: %d\n", ret);
+		goto err_regmap;
+	}
+
+	if (reg & WM8996_GP2_FN_MASK)
+		regmap_update_bits(wm8996->regmap, WM8996_AIF2_TX_LRCLK_2,
+				   WM8996_AIF2TX_LRCLK_MODE,
+				   WM8996_AIF2TX_LRCLK_MODE);
+
 	wm8996_init_gpio(wm8996);
 
 	ret = snd_soc_register_codec(&i2c->dev,
@@ -3225,7 +3065,6 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
 err_gpiolib:
 	wm8996_free_gpio(wm8996);
 err_regmap:
-	regmap_exit(wm8996->regmap);
 err_enable:
 	if (wm8996->pdata.ldo_ena > 0)
 		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
@@ -3241,14 +3080,18 @@ err:
 static __devexit int wm8996_i2c_remove(struct i2c_client *client)
 {
 	struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
+	int i;
 
 	snd_soc_unregister_codec(&client->dev);
 	wm8996_free_gpio(wm8996);
-	regmap_exit(wm8996->regmap);
 	if (wm8996->pdata.ldo_ena > 0) {
 		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
 		gpio_free(wm8996->pdata.ldo_ena);
 	}
+	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
+		regulator_unregister_notifier(wm8996->supplies[i].consumer,
+					      &wm8996->disable_nb[i]);
+
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 9328270df16c..2de74e1ea225 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -3,7 +3,7 @@
  *
  * Author: Mark Brown
  *
- * Copyright 2009 Wolfson Microelectronics plc
+ * Copyright 2009-12 Wolfson Microelectronics plc
  *
  * 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
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 4b263b6edf13..2c2346fdd637 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -1,7 +1,7 @@
 /*
  * ALSA SoC WM9090 driver
  *
- * Copyright 2009, 2010 Wolfson Microelectronics
+ * Copyright 2009-12 Wolfson Microelectronics
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index a1541414d904..099e6ec32125 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -1,7 +1,7 @@
 /*
  * wm9712.c  --  ALSA Soc WM9712 codec support
  *
- * Copyright 2006 Wolfson Microelectronics PLC.
+ * Copyright 2006-12 Wolfson Microelectronics PLC.
  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  This program is free software; you can redistribute  it and/or modify it
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 2d22cc70d536..3eb19fb71d17 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1,7 +1,7 @@
 /*
  * wm9713.c  --  ALSA Soc WM9713 codec support
  *
- * Copyright 2006 Wolfson Microelectronics PLC.
+ * Copyright 2006-10 Wolfson Microelectronics PLC.
  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  This program is free software; you can redistribute  it and/or modify it
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index dfe957a47f29..61baa48823cb 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -1,7 +1,7 @@
 /*
  * wm_hubs.c  --  WM8993/4 common code
  *
- * Copyright 2009 Wolfson Microelectronics plc
+ * Copyright 2009-12 Wolfson Microelectronics plc
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *