summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-10-27 10:43:40 +0200
committerTakashi Iwai <tiwai@suse.de>2011-10-27 10:43:40 +0200
commitbb14eb0da72afb69be261b28ec858cbd5a35e089 (patch)
treefa72a87d21e506c990b63657d782936311cfa7cf
parent9430148d800dd929ad73da4c6afb67f793f8af43 (diff)
parent5927f94700e860ae27ff24e7f3bc9e4f7b9922eb (diff)
downloadlinux-bb14eb0da72afb69be261b28ec858cbd5a35e089.tar.gz
Merge branch 'topic/asoc' into for-linus
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c1
-rw-r--r--arch/arm/mach-omap2/devices.c33
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c2
-rw-r--r--arch/arm/plat-omap/devices.c36
-rw-r--r--drivers/input/misc/twl6040-vibra.c19
-rw-r--r--drivers/mfd/twl6040-core.c31
-rw-r--r--drivers/mfd/wm8994-core.c27
-rw-r--r--drivers/regulator/core.c9
-rw-r--r--drivers/regulator/wm8994-regulator.c13
-rw-r--r--include/linux/mfd/twl6040.h38
-rw-r--r--include/linux/mfd/wm8994/core.h1
-rw-r--r--include/linux/mfd/wm8994/registers.h4
-rw-r--r--include/sound/soc-dai.h37
-rw-r--r--include/sound/soc-dapm.h14
-rw-r--r--include/sound/soc.h91
-rw-r--r--include/sound/tpa6130a2-plat.h6
-rw-r--r--include/sound/wm1250-ev1.h27
-rw-r--r--include/sound/wm5100.h59
-rw-r--r--include/trace/events/asoc.h25
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c1
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c2
-rw-r--r--sound/soc/atmel/snd-soc-afeb9260.c2
-rw-r--r--sound/soc/au1x/ac97c.c33
-rw-r--r--sound/soc/au1x/i2sc.c33
-rw-r--r--sound/soc/au1x/psc-ac97.c25
-rw-r--r--sound/soc/au1x/psc-i2s.c25
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c2
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c2
-rw-r--r--sound/soc/codecs/88pm860x-codec.c14
-rw-r--r--sound/soc/codecs/Kconfig12
-rw-r--r--sound/soc/codecs/Makefile6
-rw-r--r--sound/soc/codecs/ad193x.c31
-rw-r--r--sound/soc/codecs/ad193x.h2
-rw-r--r--sound/soc/codecs/ad1980.c1
-rw-r--r--sound/soc/codecs/adau1373.c2
-rw-r--r--sound/soc/codecs/adau1701.c3
-rw-r--r--sound/soc/codecs/ads117x.h13
-rw-r--r--sound/soc/codecs/ak4104.c2
-rw-r--r--sound/soc/codecs/ak4535.c110
-rw-r--r--sound/soc/codecs/ak4641.c3
-rw-r--r--sound/soc/codecs/ak4642.c104
-rw-r--r--sound/soc/codecs/ak4671.c22
-rw-r--r--sound/soc/codecs/alc5623.c6
-rw-r--r--sound/soc/codecs/cs4270.c14
-rw-r--r--sound/soc/codecs/cs4271.c5
-rw-r--r--sound/soc/codecs/cs42l51.c15
-rw-r--r--sound/soc/codecs/da7210.c649
-rw-r--r--sound/soc/codecs/lm4857.c2
-rw-r--r--sound/soc/codecs/max98088.c36
-rw-r--r--sound/soc/codecs/max98095.c47
-rw-r--r--sound/soc/codecs/rt5631.c1773
-rw-r--r--sound/soc/codecs/rt5631.h701
-rw-r--r--sound/soc/codecs/sgtl5000.c29
-rw-r--r--sound/soc/codecs/sgtl5000.h2
-rw-r--r--sound/soc/codecs/sn95031.c6
-rw-r--r--sound/soc/codecs/ssm2602.c104
-rw-r--r--sound/soc/codecs/ssm2602.h6
-rw-r--r--sound/soc/codecs/sta32x.c33
-rw-r--r--sound/soc/codecs/tlv320aic23.c181
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c65
-rw-r--r--sound/soc/codecs/tlv320aic3x.c25
-rw-r--r--sound/soc/codecs/tlv320dac33.c29
-rw-r--r--sound/soc/codecs/tpa6130a2.c12
-rw-r--r--sound/soc/codecs/twl4030.c69
-rw-r--r--sound/soc/codecs/twl6040.c693
-rw-r--r--sound/soc/codecs/twl6040.h13
-rw-r--r--sound/soc/codecs/wl1273.c1
-rw-r--r--sound/soc/codecs/wm1250-ev1.c122
-rw-r--r--sound/soc/codecs/wm5100-tables.c1531
-rw-r--r--sound/soc/codecs/wm5100.c2809
-rw-r--r--sound/soc/codecs/wm5100.h5155
-rw-r--r--sound/soc/codecs/wm8350.c43
-rw-r--r--sound/soc/codecs/wm8400.c2
-rw-r--r--sound/soc/codecs/wm8510.c13
-rw-r--r--sound/soc/codecs/wm8523.c1
-rw-r--r--sound/soc/codecs/wm8580.c60
-rw-r--r--sound/soc/codecs/wm8711.c25
-rw-r--r--sound/soc/codecs/wm8731.c15
-rw-r--r--sound/soc/codecs/wm8741.c16
-rw-r--r--sound/soc/codecs/wm8750.c42
-rw-r--r--sound/soc/codecs/wm8753.c4
-rw-r--r--sound/soc/codecs/wm8776.c16
-rw-r--r--sound/soc/codecs/wm8782.c2
-rw-r--r--sound/soc/codecs/wm8900.c115
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/codecs/wm8940.c51
-rw-r--r--sound/soc/codecs/wm8960.c18
-rw-r--r--sound/soc/codecs/wm8961.c4
-rw-r--r--sound/soc/codecs/wm8962.c35
-rw-r--r--sound/soc/codecs/wm8971.c42
-rw-r--r--sound/soc/codecs/wm8974.c15
-rw-r--r--sound/soc/codecs/wm8978.c3
-rw-r--r--sound/soc/codecs/wm8983.c2
-rw-r--r--sound/soc/codecs/wm8988.c33
-rw-r--r--sound/soc/codecs/wm8990.c105
-rw-r--r--sound/soc/codecs/wm8991.c24
-rw-r--r--sound/soc/codecs/wm8994.c106
-rw-r--r--sound/soc/codecs/wm8995.c19
-rw-r--r--sound/soc/codecs/wm8996.c15
-rw-r--r--sound/soc/codecs/wm9081.c10
-rw-r--r--sound/soc/codecs/wm9090.c5
-rw-r--r--sound/soc/codecs/wm_hubs.c20
-rw-r--r--sound/soc/davinci/davinci-evm.c2
-rw-r--r--sound/soc/davinci/davinci-i2s.c5
-rw-r--r--sound/soc/ep93xx/ep93xx-ac97.c2
-rw-r--r--sound/soc/imx/Kconfig3
-rw-r--r--sound/soc/imx/imx-pcm-fiq.c1
-rw-r--r--sound/soc/imx/imx-ssi.c1
-rw-r--r--sound/soc/imx/imx-ssi.h6
-rw-r--r--sound/soc/jz4740/jz4740-pcm.c2
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c2
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c2
-rw-r--r--sound/soc/mid-x86/mfld_machine.c4
-rw-r--r--sound/soc/mid-x86/sst_platform.c2
-rw-r--r--sound/soc/mxs/mxs-saif.c19
-rw-r--r--sound/soc/nuc900/nuc900-pcm.c2
-rw-r--r--sound/soc/omap/Makefile2
-rw-r--r--sound/soc/omap/am3517evm.c50
-rw-r--r--sound/soc/omap/ams-delta.c1
-rw-r--r--sound/soc/omap/igep0020.c23
-rw-r--r--sound/soc/omap/mcpdm.c470
-rw-r--r--sound/soc/omap/mcpdm.h153
-rw-r--r--sound/soc/omap/n810.c42
-rw-r--r--sound/soc/omap/omap-mcbsp.c27
-rw-r--r--sound/soc/omap/omap-mcpdm.c481
-rw-r--r--sound/soc/omap/omap-mcpdm.h107
-rw-r--r--sound/soc/omap/omap-pcm.c8
-rw-r--r--sound/soc/omap/omap3evm.c23
-rw-r--r--sound/soc/omap/omap3pandora.c28
-rw-r--r--sound/soc/omap/osk5912.c50
-rw-r--r--sound/soc/omap/overo.c23
-rw-r--r--sound/soc/omap/rx51.c22
-rw-r--r--sound/soc/omap/sdp3430.c88
-rw-r--r--sound/soc/omap/sdp4430.c47
-rw-r--r--sound/soc/omap/zoom2.c96
-rw-r--r--sound/soc/pxa/Kconfig2
-rw-r--r--sound/soc/pxa/corgi.c1
-rw-r--r--sound/soc/pxa/e740_wm9705.c2
-rw-r--r--sound/soc/pxa/e750_wm9705.c2
-rw-r--r--sound/soc/pxa/e800_wm9712.c1
-rw-r--r--sound/soc/pxa/magician.c4
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c1
-rw-r--r--sound/soc/pxa/palm27x.c4
-rw-r--r--sound/soc/pxa/poodle.c1
-rw-r--r--sound/soc/pxa/saarb.c4
-rw-r--r--sound/soc/pxa/spitz.c1
-rw-r--r--sound/soc/pxa/tavorevb3.c4
-rw-r--r--sound/soc/pxa/tosa.c1
-rw-r--r--sound/soc/pxa/z2.c4
-rw-r--r--sound/soc/pxa/zylonite.c9
-rw-r--r--sound/soc/samsung/Kconfig6
-rw-r--r--sound/soc/samsung/ac97.c2
-rw-r--r--sound/soc/samsung/goni_wm8994.c15
-rw-r--r--sound/soc/samsung/h1940_uda1380.c19
-rw-r--r--sound/soc/samsung/i2s.c2
-rw-r--r--sound/soc/samsung/jive_wm8750.c17
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c4
-rw-r--r--sound/soc/samsung/pcm.c2
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c33
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c1
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c2
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c2
-rw-r--r--sound/soc/samsung/s3c24xx_simtec.c2
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_hermes.c11
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c11
-rw-r--r--sound/soc/samsung/smartq_wm8987.c25
-rw-r--r--sound/soc/samsung/smdk_wm8580.c45
-rw-r--r--sound/soc/samsung/smdk_wm8994.c2
-rw-r--r--sound/soc/samsung/spdif.c4
-rw-r--r--sound/soc/samsung/speyside_wm8962.c41
-rw-r--r--sound/soc/sh/fsi.c10
-rw-r--r--sound/soc/sh/sh7760-ac97.c7
-rw-r--r--sound/soc/sh/ssi.c2
-rw-r--r--sound/soc/soc-core.c195
-rw-r--r--sound/soc/soc-dapm.c400
-rw-r--r--sound/soc/soc-io.c2
-rw-r--r--sound/soc/soc-jack.c2
-rw-r--r--sound/soc/soc-pcm.c55
-rw-r--r--sound/soc/tegra/tegra_das.c4
-rw-r--r--sound/soc/tegra/tegra_i2s.c2
-rw-r--r--sound/soc/tegra/tegra_pcm.c2
-rw-r--r--sound/soc/tegra/tegra_spdif.c5
-rw-r--r--sound/soc/tegra/tegra_wm8903.c2
-rw-r--r--sound/soc/tegra/trimslice.c2
-rw-r--r--sound/soc/txx9/txx9aclc-generic.c2
186 files changed, 15232 insertions, 3462 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index a676343a27bc..1dbbb278d218 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -530,6 +530,7 @@ S:	Maintained
 F:	drivers/infiniband/hw/amso1100/
 
 ANALOG DEVICES INC ASOC CODEC DRIVERS
+M:	Lars-Peter Clausen <lars@metafoo.de>
 L:	device-drivers-devel@blackfin.uclinux.org
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:	http://wiki.analog.com/
@@ -7199,6 +7200,7 @@ T:	git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
 W:	http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
 S:	Supported
 F:	Documentation/hwmon/wm83??
+F:	arch/arm/mach-s3c64xx/mach-crag6410*
 F:	drivers/leds/leds-wm83*.c
 F:	drivers/input/misc/wm831x-on.c
 F:	drivers/input/touchscreen/wm831x-ts.c
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 5a886cd2c598..ba1aa07bdb29 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -900,7 +900,6 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
 };
 
 static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = {
-	.id			= TPA6130A2,
 	.power_gpio		= 98,
 };
 
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 1077ad663f93..3f0b143cb37b 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -330,6 +330,38 @@ static void omap_init_audio(void)
 static inline void omap_init_audio(void) {}
 #endif
 
+#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
+		defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
+
+static struct omap_device_pm_latency omap_mcpdm_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+};
+
+static void omap_init_mcpdm(void)
+{
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+
+	oh = omap_hwmod_lookup("mcpdm");
+	if (!oh) {
+		printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
+		return;
+	}
+
+	od = omap_device_build("omap-mcpdm", -1, oh, NULL, 0,
+				omap_mcpdm_latency,
+				ARRAY_SIZE(omap_mcpdm_latency), 0);
+	if (IS_ERR(od))
+		printk(KERN_ERR "Could not build omap_device for omap-mcpdm-dai\n");
+}
+#else
+static inline void omap_init_mcpdm(void) {}
+#endif
+
 #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
 
 #include <plat/mcspi.h>
@@ -683,6 +715,7 @@ static int __init omap2_init_devices(void)
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_init_audio();
+	omap_init_mcpdm();
 	omap_init_camera();
 	omap_init_mbox();
 	omap_init_mcspi();
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6201422c0606..79325c65c23c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -5430,7 +5430,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	&omap44xx_mcbsp4_hwmod,
 
 	/* mcpdm class */
-/*	&omap44xx_mcpdm_hwmod, */
+	&omap44xx_mcpdm_hwmod,
 
 	/* mcspi class */
 	&omap44xx_mcspi1_hwmod,
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index ea28f98d5d6a..40eca9b30d93 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -74,41 +74,6 @@ void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
-		defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
-
-static struct resource mcpdm_resources[] = {
-	{
-		.name		= "mcpdm_mem",
-		.start		= OMAP44XX_MCPDM_BASE,
-		.end		= OMAP44XX_MCPDM_BASE + SZ_4K,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.name		= "mcpdm_irq",
-		.start		= OMAP44XX_IRQ_MCPDM,
-		.end		= OMAP44XX_IRQ_MCPDM,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device omap_mcpdm_device = {
-	.name		= "omap-mcpdm",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(mcpdm_resources),
-	.resource	= mcpdm_resources,
-};
-
-static void omap_init_mcpdm(void)
-{
-	(void) platform_device_register(&omap_mcpdm_device);
-}
-#else
-static inline void omap_init_mcpdm(void) {}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
 	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
@@ -291,7 +256,6 @@ static int __init omap_init_devices(void)
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_init_rng();
-	omap_init_mcpdm();
 	omap_init_uwire();
 	return 0;
 }
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index 154b7a324d67..2a828e53db58 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -74,12 +74,12 @@ static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
 	if (status & TWL6040_VIBLOCDET) {
 		dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
 		twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
-				   TWL6040_VIBENAL);
+				   TWL6040_VIBENA);
 	}
 	if (status & TWL6040_VIBROCDET) {
 		dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
 		twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
-				   TWL6040_VIBENAR);
+				   TWL6040_VIBENA);
 	}
 
 	return IRQ_HANDLED;
@@ -104,16 +104,16 @@ static void twl6040_vibra_enable(struct vibra_info *info)
 		 * overcurrent detection
 		 */
 		twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
-				  TWL6040_VIBENAL | TWL6040_VIBCTRLL);
+				  TWL6040_VIBENA | TWL6040_VIBCTRL);
 		twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
-				  TWL6040_VIBENAR | TWL6040_VIBCTRLR);
+				  TWL6040_VIBENA | TWL6040_VIBCTRL);
 		usleep_range(3000, 3500);
 	}
 
 	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
-			  TWL6040_VIBENAL);
+			  TWL6040_VIBENA);
 	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
-			  TWL6040_VIBENAR);
+			  TWL6040_VIBENA);
 
 	info->enabled = true;
 }
@@ -201,6 +201,13 @@ static int vibra_play(struct input_dev *input, void *data,
 	struct vibra_info *info = input_get_drvdata(input);
 	int ret;
 
+	/* Do not allow effect, while the routing is set to use audio */
+	ret = twl6040_get_vibralr_status(info->twl6040);
+	if (ret & TWL6040_VIBSEL) {
+		dev_info(&input->dev, "Vibra is configured for audio\n");
+		return -EBUSY;
+	}
+
 	info->weak_speed = effect->u.rumble.weak_magnitude;
 	info->strong_speed = effect->u.rumble.strong_magnitude;
 	info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index 7dc8c4715001..268f80fd0439 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -34,16 +34,24 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/twl6040.h>
 
+#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
+
 int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
 {
 	int ret;
 	u8 val = 0;
 
 	mutex_lock(&twl6040->io_mutex);
-	ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
-	if (ret < 0) {
-		mutex_unlock(&twl6040->io_mutex);
-		return ret;
+	/* Vibra control registers from cache */
+	if (unlikely(reg == TWL6040_REG_VIBCTLL ||
+		     reg == TWL6040_REG_VIBCTLR)) {
+		val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
+	} else {
+		ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+		if (ret < 0) {
+			mutex_unlock(&twl6040->io_mutex);
+			return ret;
+		}
 	}
 	mutex_unlock(&twl6040->io_mutex);
 
@@ -57,6 +65,9 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
 
 	mutex_lock(&twl6040->io_mutex);
 	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+	/* Cache the vibra control registers */
+	if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
+		twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
 	mutex_unlock(&twl6040->io_mutex);
 
 	return ret;
@@ -433,6 +444,18 @@ unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
 }
 EXPORT_SYMBOL(twl6040_get_sysclk);
 
+/* Get the combined status of the vibra control register */
+int twl6040_get_vibralr_status(struct twl6040 *twl6040)
+{
+	u8 status;
+
+	status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
+	status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
+
+	return status;
+}
+EXPORT_SYMBOL(twl6040_get_vibralr_status);
+
 static struct resource twl6040_vibra_rsrc[] = {
 	{
 		.flags = IORESOURCE_IRQ,
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 96479c9b1728..7c13ab2c64a4 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -243,6 +243,18 @@ static struct mfd_cell wm8994_devs[] = {
  * and should be handled via the standard regulator API supply
  * management.
  */
+static const char *wm1811_main_supplies[] = {
+	"DBVDD1",
+	"DBVDD2",
+	"DBVDD3",
+	"DCVDD",
+	"AVDD1",
+	"AVDD2",
+	"CPVDD",
+	"SPKVDD1",
+	"SPKVDD2",
+};
+
 static const char *wm8994_main_supplies[] = {
 	"DBVDD",
 	"DCVDD",
@@ -401,6 +413,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 	}
 
 	switch (wm8994->type) {
+	case WM1811:
+		wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies);
+		break;
 	case WM8994:
 		wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
 		break;
@@ -421,6 +436,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 	}
 
 	switch (wm8994->type) {
+	case WM1811:
+		for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++)
+			wm8994->supplies[i].supply = wm1811_main_supplies[i];
+		break;
 	case WM8994:
 		for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
 			wm8994->supplies[i].supply = wm8994_main_supplies[i];
@@ -454,6 +473,13 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 		goto err_enable;
 	}
 	switch (ret) {
+	case 0x1811:
+		devname = "WM1811";
+		if (wm8994->type != WM1811)
+			dev_warn(wm8994->dev, "Device registered as type %d\n",
+				 wm8994->type);
+		wm8994->type = WM1811;
+		break;
 	case 0x8994:
 		devname = "WM8994";
 		if (wm8994->type != WM8994)
@@ -651,6 +677,7 @@ static int wm8994_i2c_remove(struct i2c_client *i2c)
 }
 
 static const struct i2c_device_id wm8994_i2c_id[] = {
+	{ "wm1811", WM1811 },
 	{ "wm8994", WM8994 },
 	{ "wm8958", WM8958 },
 	{ }
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index d0bde70f3466..9e4c123c4028 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1599,13 +1599,18 @@ static void regulator_disable_work(struct work_struct *work)
 int regulator_disable_deferred(struct regulator *regulator, int ms)
 {
 	struct regulator_dev *rdev = regulator->rdev;
+	int ret;
 
 	mutex_lock(&rdev->mutex);
 	rdev->deferred_disables++;
 	mutex_unlock(&rdev->mutex);
 
-	return schedule_delayed_work(&rdev->disable_work,
-				     msecs_to_jiffies(ms));
+	ret = schedule_delayed_work(&rdev->disable_work,
+				    msecs_to_jiffies(ms));
+	if (ret < 0)
+		return ret;
+	else
+		return 0;
 }
 EXPORT_SYMBOL_GPL(regulator_disable_deferred);
 
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 1a6a690f24db..b87bf5c841f8 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -140,6 +140,14 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
 		return (selector * 100000) + 900000;
 	case WM8958:
 		return (selector * 100000) + 1000000;
+	case WM1811:
+		switch (selector) {
+		case 0:
+			return -EINVAL;
+		default:
+			return (selector * 100000) + 950000;
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -170,6 +178,11 @@ static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
 	case WM8958:
 		selector = (min_uV - 1000000) / 100000;
 		break;
+	case WM1811:
+		selector = (min_uV - 950000) / 100000;
+		if (selector == 0)
+			selector = 1;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index ec1ec794fa23..2463c2619596 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -68,8 +68,6 @@
 #define TWL6040_REG_ACCCTL		0x2D
 #define TWL6040_REG_STATUS		0x2E
 
-#define TWL6040_CACHEREGNUM		(TWL6040_REG_STATUS + 1)
-
 /* INTID (0x03) fields */
 
 #define TWL6040_THINT			0x01
@@ -122,34 +120,24 @@
 #define TWL6040_LPLLFIN			0x08
 #define TWL6040_HPLLSEL			0x10
 
-/* HSLCTL (0x10) fields */
-
-#define TWL6040_HSDACMODEL		0x02
-#define TWL6040_HSDRVMODEL		0x08
-
-/* HSRCTL (0x11) fields */
+/* HSLCTL/R (0x10/0x11) fields */
 
-#define TWL6040_HSDACMODER		0x02
-#define TWL6040_HSDRVMODER		0x08
+#define TWL6040_HSDACENA		(1 << 0)
+#define TWL6040_HSDACMODE		(1 << 1)
+#define TWL6040_HSDRVMODE		(1 << 3)
 
-/* VIBCTLL (0x18) fields */
+/* VIBCTLL/R (0x18/0x1A) fields */
 
-#define TWL6040_VIBENAL			0x01
-#define TWL6040_VIBCTRLL		0x04
-#define TWL6040_VIBCTRLLP		0x08
-#define TWL6040_VIBCTRLLN		0x10
+#define TWL6040_VIBENA			(1 << 0)
+#define TWL6040_VIBSEL			(1 << 1)
+#define TWL6040_VIBCTRL			(1 << 2)
+#define TWL6040_VIBCTRL_P		(1 << 3)
+#define TWL6040_VIBCTRL_N		(1 << 4)
 
-/* VIBDATL (0x19) fields */
+/* VIBDATL/R (0x19/0x1B) fields */
 
 #define TWL6040_VIBDAT_MAX		0x64
 
-/* VIBCTLR (0x1A) fields */
-
-#define TWL6040_VIBENAR			0x01
-#define TWL6040_VIBCTRLR		0x04
-#define TWL6040_VIBCTRLRP		0x08
-#define TWL6040_VIBCTRLRN		0x10
-
 /* GPOCTL (0x1E) fields */
 
 #define TWL6040_GPO1			0x01
@@ -197,6 +185,7 @@ struct twl6040 {
 	int audpwron;
 	int power_count;
 	int rev;
+	u8 vibra_ctrl_cache[2];
 
 	int pll;
 	unsigned int sysclk;
@@ -221,10 +210,13 @@ int twl6040_get_pll(struct twl6040 *twl6040);
 unsigned int twl6040_get_sysclk(struct twl6040 *twl6040);
 int twl6040_irq_init(struct twl6040 *twl6040);
 void twl6040_irq_exit(struct twl6040 *twl6040);
+/* Get the combined status of the vibra control register */
+int twl6040_get_vibralr_status(struct twl6040 *twl6040);
 
 static inline int twl6040_get_revid(struct twl6040 *twl6040)
 {
 	return twl6040->rev;
 }
 
+
 #endif  /* End of __TWL6040_CODEC_H__ */
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h
index f0b69cdae41c..bfb221b3abf7 100644
--- a/include/linux/mfd/wm8994/core.h
+++ b/include/linux/mfd/wm8994/core.h
@@ -20,6 +20,7 @@
 enum wm8994_type {
 	WM8994 = 0,
 	WM8958 = 1,
+	WM1811 = 2,
 };
 
 struct regulator_dev;
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h
index 83ecdcd8aaf9..fae295048a8b 100644
--- a/include/linux/mfd/wm8994/registers.h
+++ b/include/linux/mfd/wm8994/registers.h
@@ -2069,6 +2069,10 @@
 /*
  * R96 (0x60) - Analogue HP (1)
  */
+#define WM1811_HPOUT1_ATTN                      0x0100  /* HPOUT1_ATTN */
+#define WM1811_HPOUT1_ATTN_MASK                 0x0100  /* HPOUT1_ATTN */
+#define WM1811_HPOUT1_ATTN_SHIFT                     8  /* HPOUT1_ATTN */
+#define WM1811_HPOUT1_ATTN_WIDTH                     1  /* HPOUT1_ATTN */
 #define WM8994_HPOUT1L_RMV_SHORT                0x0080  /* HPOUT1L_RMV_SHORT */
 #define WM8994_HPOUT1L_RMV_SHORT_MASK           0x0080  /* HPOUT1L_RMV_SHORT */
 #define WM8994_HPOUT1L_RMV_SHORT_SHIFT               7  /* HPOUT1L_RMV_SHORT */
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 5ad5f3a50c68..2413acc54883 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -24,13 +24,13 @@ struct snd_pcm_substream;
  * Describes the physical PCM data formating and clocking. Add new formats
  * to the end.
  */
-#define SND_SOC_DAIFMT_I2S		0 /* I2S mode */
-#define SND_SOC_DAIFMT_RIGHT_J		1 /* Right Justified mode */
-#define SND_SOC_DAIFMT_LEFT_J		2 /* Left Justified mode */
-#define SND_SOC_DAIFMT_DSP_A		3 /* L data MSB after FRM LRC */
-#define SND_SOC_DAIFMT_DSP_B		4 /* L data MSB during FRM LRC */
-#define SND_SOC_DAIFMT_AC97		5 /* AC97 */
-#define SND_SOC_DAIFMT_PDM		6 /* Pulse density modulation */
+#define SND_SOC_DAIFMT_I2S		1 /* I2S mode */
+#define SND_SOC_DAIFMT_RIGHT_J		2 /* Right Justified mode */
+#define SND_SOC_DAIFMT_LEFT_J		3 /* Left Justified mode */
+#define SND_SOC_DAIFMT_DSP_A		4 /* L data MSB after FRM LRC */
+#define SND_SOC_DAIFMT_DSP_B		5 /* L data MSB during FRM LRC */
+#define SND_SOC_DAIFMT_AC97		6 /* AC97 */
+#define SND_SOC_DAIFMT_PDM		7 /* Pulse density modulation */
 
 /* left and right justified also known as MSB and LSB respectively */
 #define SND_SOC_DAIFMT_MSB		SND_SOC_DAIFMT_LEFT_J
@@ -42,8 +42,8 @@ struct snd_pcm_substream;
  * DAI bit clocks can be be gated (disabled) when the DAI is not
  * sending or receiving PCM data in a frame. This can be used to save power.
  */
-#define SND_SOC_DAIFMT_CONT		(0 << 4) /* continuous clock */
-#define SND_SOC_DAIFMT_GATED		(1 << 4) /* clock is gated */
+#define SND_SOC_DAIFMT_CONT		(1 << 4) /* continuous clock */
+#define SND_SOC_DAIFMT_GATED		(2 << 4) /* clock is gated */
 
 /*
  * DAI hardware signal inversions.
@@ -51,10 +51,10 @@ struct snd_pcm_substream;
  * Specifies whether the DAI can also support inverted clocks for the specified
  * format.
  */
-#define SND_SOC_DAIFMT_NB_NF		(0 << 8) /* normal bit clock + frame */
-#define SND_SOC_DAIFMT_NB_IF		(1 << 8) /* normal BCLK + inv FRM */
-#define SND_SOC_DAIFMT_IB_NF		(2 << 8) /* invert BCLK + nor FRM */
-#define SND_SOC_DAIFMT_IB_IF		(3 << 8) /* invert BCLK + FRM */
+#define SND_SOC_DAIFMT_NB_NF		(1 << 8) /* normal bit clock + frame */
+#define SND_SOC_DAIFMT_NB_IF		(2 << 8) /* normal BCLK + inv FRM */
+#define SND_SOC_DAIFMT_IB_NF		(3 << 8) /* invert BCLK + nor FRM */
+#define SND_SOC_DAIFMT_IB_IF		(4 << 8) /* invert BCLK + FRM */
 
 /*
  * DAI hardware clock masters.
@@ -63,10 +63,10 @@ struct snd_pcm_substream;
  * i.e. if the codec is clk and FRM master then the interface is
  * clk and frame slave.
  */
-#define SND_SOC_DAIFMT_CBM_CFM		(0 << 12) /* codec clk & FRM master */
-#define SND_SOC_DAIFMT_CBS_CFM		(1 << 12) /* codec clk slave & FRM master */
-#define SND_SOC_DAIFMT_CBM_CFS		(2 << 12) /* codec clk master & frame slave */
-#define SND_SOC_DAIFMT_CBS_CFS		(3 << 12) /* codec clk & FRM slave */
+#define SND_SOC_DAIFMT_CBM_CFM		(1 << 12) /* codec clk & FRM master */
+#define SND_SOC_DAIFMT_CBS_CFM		(2 << 12) /* codec clk slave & FRM master */
+#define SND_SOC_DAIFMT_CBM_CFS		(3 << 12) /* codec clk master & frame slave */
+#define SND_SOC_DAIFMT_CBS_CFS		(4 << 12) /* codec clk & FRM slave */
 
 #define SND_SOC_DAIFMT_FORMAT_MASK	0x000f
 #define SND_SOC_DAIFMT_CLOCK_MASK	0x00f0
@@ -242,6 +242,9 @@ struct snd_soc_dai {
 	void *playback_dma_data;
 	void *capture_dma_data;
 
+	/* Symmetry data - only valid if symmetry is being enforced */
+	unsigned int rate;
+
 	/* parent platform/codec */
 	union {
 		struct snd_soc_platform *platform;
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 350b1b395cac..17a4c17f19f5 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -381,6 +381,9 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
 				const char *pin);
 
+/* Mostly internal - should not normally be used */
+void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);
+
 /* dapm widget types */
 enum snd_soc_dapm_type {
 	snd_soc_dapm_input = 0,		/* input pin */
@@ -473,6 +476,8 @@ struct snd_soc_dapm_widget {
 	unsigned char ext:1;			/* has external widgets */
 	unsigned char force:1;			/* force state */
 	unsigned char ignore_suspend:1;         /* kept enabled over suspend */
+	unsigned char new_power:1;		/* power from this run */
+	unsigned char power_checked:1;		/* power checked this run */
 	int subseq;				/* sort within widget type */
 
 	int (*power_check)(struct snd_soc_dapm_widget *w);
@@ -492,6 +497,9 @@ struct snd_soc_dapm_widget {
 
 	/* used during DAPM updates */
 	struct list_head power_list;
+	struct list_head dirty;
+	int inputs;
+	int outputs;
 };
 
 struct snd_soc_dapm_update {
@@ -537,4 +545,10 @@ struct snd_soc_dapm_widget_list {
 	struct snd_soc_dapm_widget *widgets[0];
 };
 
+struct snd_soc_dapm_stats {
+	int power_checks;
+	int path_checks;
+	int neighbour_checks;
+};
+
 #endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 24e17be38c19..11cfb5953e06 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -28,13 +28,20 @@
 /*
  * Convenience kcontrol builders
  */
-#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
+#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \
 	((unsigned long)&(struct soc_mixer_control) \
-	{.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \
-	.platform_max = xmax, .invert = xinvert})
+	{.reg = xreg, .rreg = xreg, .shift = shift_left, \
+	.rshift = shift_right, .max = xmax, .platform_max = xmax, \
+	.invert = xinvert})
+#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
+	SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert)
 #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
 	((unsigned long)&(struct soc_mixer_control) \
 	{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
+#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \
+	((unsigned long)&(struct soc_mixer_control) \
+	{.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
+	.max = xmax, .platform_max = xmax, .invert = xinvert})
 #define SOC_SINGLE(xname, reg, shift, max, invert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
@@ -48,40 +55,36 @@
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
 	.put = snd_soc_put_volsw, \
 	.private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
-#define SOC_DOUBLE(xname, xreg, shift_left, shift_right, xmax, xinvert) \
+#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
 	.put = snd_soc_put_volsw, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
-		 .max = xmax, .platform_max = xmax, .invert = xinvert} }
+	.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
+					  max, invert) }
 #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-	.info = snd_soc_info_volsw_2r, \
-	.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-		.max = xmax, .platform_max = xmax, .invert = xinvert} }
-#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \
+	.info = snd_soc_info_volsw, \
+	.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
+	.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
+					    xmax, xinvert) }
+#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
 		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
 	.tlv.p = (tlv_array), \
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
 	.put = snd_soc_put_volsw, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = xreg, .shift = shift_left, .rshift = shift_right,\
-		 .max = xmax, .platform_max = xmax, .invert = xinvert} }
+	.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
+					  max, invert) }
 #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
 		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
 	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw_2r, \
-	.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-		.max = xmax, .platform_max = xmax, .invert = xinvert} }
+	.info = snd_soc_info_volsw, \
+	.get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
+	.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
+					    xmax, xinvert) }
 #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
 {	.iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@@ -121,14 +124,13 @@
 	.info = snd_soc_info_volsw, \
 	.get = xhandler_get, .put = xhandler_put, \
 	.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
-#define SOC_DOUBLE_EXT(xname, xreg, shift_left, shift_right, xmax, xinvert,\
+#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
 	 xhandler_get, xhandler_put) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
 	.info = snd_soc_info_volsw, \
 	.get = xhandler_get, .put = xhandler_put, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
-		 .max = xmax, .platform_max = xmax, .invert = xinvert} }
+	.private_value = \
+		SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) }
 #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
 	 xhandler_get, xhandler_put, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -146,20 +148,18 @@
 	.tlv.p = (tlv_array), \
 	.info = snd_soc_info_volsw, \
 	.get = xhandler_get, .put = xhandler_put, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
-		.max = xmax, .platform_max = xmax, .invert = xinvert} }
+	.private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
+					  xmax, xinvert) }
 #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
 	 xhandler_get, xhandler_put, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
 		 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
 	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw_2r, \
+	.info = snd_soc_info_volsw, \
 	.get = xhandler_get, .put = xhandler_put, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-		.max = xmax, .platform_max = xmax, .invert = xinvert} }
+	.private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
+					    xmax, xinvert) }
 #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_bool_ext, \
@@ -393,12 +393,8 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
-int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_info *uinfo);
-int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol);
-int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol);
+#define snd_soc_get_volsw_2r snd_soc_get_volsw
+#define snd_soc_put_volsw_2r snd_soc_put_volsw
 int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
@@ -582,6 +578,7 @@ struct snd_soc_codec {
 
 	/* dapm */
 	struct snd_soc_dapm_context dapm;
+	unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
 
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_codec_root;
@@ -713,6 +710,8 @@ struct snd_soc_dai_link {
 	const char *cpu_dai_name;
 	const char *codec_dai_name;
 
+	unsigned int dai_fmt;           /* format to set on init */
+
 	/* Keep DAI active over suspend */
 	unsigned int ignore_suspend:1;
 
@@ -825,9 +824,11 @@ struct snd_soc_card {
 	struct list_head widgets;
 	struct list_head paths;
 	struct list_head dapm_list;
+	struct list_head dapm_dirty;
 
 	/* Generic DAPM context for the card */
 	struct snd_soc_dapm_context dapm;
+	struct snd_soc_dapm_stats dapm_stats;
 
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_card_root;
@@ -850,8 +851,6 @@ struct snd_soc_pcm_runtime  {
 	unsigned int complete:1;
 	unsigned int dev_registered:1;
 
-	/* Symmetry data - only valid if symmetry is being enforced */
-	unsigned int rate;
 	long pmdown_time;
 
 	/* runtime devices */
@@ -946,6 +945,18 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
 	INIT_LIST_HEAD(&card->dapm_list);
 }
 
+static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
+{
+	if (mc->reg == mc->rreg && mc->shift == mc->rshift)
+		return 0;
+	/*
+	 * mc->reg == mc->rreg && mc->shift != mc->rshift, or
+	 * mc->reg != mc->rreg means that the control is
+	 * stereo (bits in one register or in two registers)
+	 */
+	return 1;
+}
+
 int snd_soc_util_init(void);
 void snd_soc_util_exit(void);
 
diff --git a/include/sound/tpa6130a2-plat.h b/include/sound/tpa6130a2-plat.h
index 89beccb57edd..4cc1093844c8 100644
--- a/include/sound/tpa6130a2-plat.h
+++ b/include/sound/tpa6130a2-plat.h
@@ -23,13 +23,7 @@
 #ifndef TPA6130A2_PLAT_H
 #define TPA6130A2_PLAT_H
 
-enum tpa_model {
-	TPA6130A2,
-	TPA6140A2,
-};
-
 struct tpa6130a2_platform_data {
-	enum tpa_model id;
 	int power_gpio;
 };
 
diff --git a/include/sound/wm1250-ev1.h b/include/sound/wm1250-ev1.h
new file mode 100644
index 000000000000..7dff82834123
--- /dev/null
+++ b/include/sound/wm1250-ev1.h
@@ -0,0 +1,27 @@
+/*
+ * linux/sound/wm1250-ev1.h - Platform data for WM1250-EV1
+ *
+ * Copyright 2011 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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_WM1250_EV1_H
+#define __LINUX_SND_WM1250_EV1_H
+
+#define WM1250_EV1_NUM_GPIOS 5
+
+#define WM1250_EV1_GPIO_CLK_ENA  0
+#define WM1250_EV1_GPIO_CLK_SEL0 1
+#define WM1250_EV1_GPIO_CLK_SEL1 2
+#define WM1250_EV1_GPIO_OSR      3
+#define WM1250_EV1_GPIO_MASTER   4
+
+
+struct wm1250_ev1_pdata {
+	int gpios[WM1250_EV1_NUM_GPIOS];
+};
+
+#endif
diff --git a/include/sound/wm5100.h b/include/sound/wm5100.h
new file mode 100644
index 000000000000..617d0c4a159f
--- /dev/null
+++ b/include/sound/wm5100.h
@@ -0,0 +1,59 @@
+/*
+ * linux/sound/wm5100.h -- Platform data for WM5100
+ *
+ * Copyright 2011 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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_WM5100_H
+#define __LINUX_SND_WM5100_H
+
+enum wm5100_in_mode {
+	WM5100_IN_SE = 0,
+	WM5100_IN_DIFF = 1,
+	WM5100_IN_DMIC = 2,
+};
+
+enum wm5100_dmic_sup {
+	WM5100_DMIC_SUP_MICVDD = 0,
+	WM5100_DMIC_SUP_MICBIAS1 = 1,
+	WM5100_DMIC_SUP_MICBIAS2 = 2,
+	WM5100_DMIC_SUP_MICBIAS3 = 3,
+};
+
+enum wm5100_micdet_bias {
+	WM5100_MICDET_MICBIAS1 = 0,
+	WM5100_MICDET_MICBIAS2 = 1,
+	WM5100_MICDET_MICBIAS3 = 2,
+};
+
+struct wm5100_jack_mode {
+	enum wm5100_micdet_bias bias;
+	int hp_pol;
+	int micd_src;
+};
+
+#define WM5100_GPIO_SET 0x10000
+
+struct wm5100_pdata {
+	int reset;      /** GPIO controlling /RESET, if any */
+	int ldo_ena;    /** GPIO controlling LODENA, if any */
+	int hp_pol;     /** GPIO controlling headset polarity, if any */
+	int irq_flags;
+	int gpio_base;
+
+	struct wm5100_jack_mode jack_modes[2];
+
+	/* Input pin mode selection */
+	enum wm5100_in_mode in_mode[4];
+
+	/* DMIC supply selection */
+	enum wm5100_dmic_sup dmic_sup[4];
+
+	int gpio_defaults[6];
+};
+
+#endif
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
index 603f5a0f0365..ab26f8aa3c78 100644
--- a/include/trace/events/asoc.h
+++ b/include/trace/events/asoc.h
@@ -216,6 +216,31 @@ DEFINE_EVENT(snd_soc_dapm_widget, snd_soc_dapm_widget_event_done,
 
 );
 
+TRACE_EVENT(snd_soc_dapm_walk_done,
+
+	TP_PROTO(struct snd_soc_card *card),
+
+	TP_ARGS(card),
+
+	TP_STRUCT__entry(
+		__string(	name,	card->name		)
+		__field(	int,	power_checks		)
+		__field(	int,	path_checks		)
+		__field(	int,	neighbour_checks	)
+	),
+
+	TP_fast_assign(
+		__assign_str(name, card->name);
+		__entry->power_checks = card->dapm_stats.power_checks;
+		__entry->path_checks = card->dapm_stats.path_checks;
+		__entry->neighbour_checks = card->dapm_stats.neighbour_checks;
+	),
+
+	TP_printk("%s: checks %d power, %d path, %d neighbour",
+		  __get_str(name), (int)__entry->power_checks,
+		  (int)__entry->path_checks, (int)__entry->neighbour_checks)
+);
+
 TRACE_EVENT(snd_soc_jack_irq,
 
 	TP_PROTO(const char *name),
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index 2909bfaed265..73ae99ad4578 100644
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -338,7 +338,6 @@ static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
 	/* always connected pins */
 	snd_soc_dapm_enable_pin(dapm, "Int Mic");
 	snd_soc_dapm_enable_pin(dapm, "Ext Spk");
-	snd_soc_dapm_sync(dapm);
 
 
 
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index bad3aa14d5b3..0377c5451aed 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -173,8 +173,6 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 	/* always connected */
 	snd_soc_dapm_enable_pin(dapm, "Ext Spk");
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c
index 5e4d499d8434..d427e9217ce4 100644
--- a/sound/soc/atmel/snd-soc-afeb9260.c
+++ b/sound/soc/atmel/snd-soc-afeb9260.c
@@ -117,8 +117,6 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_enable_pin(dapm, "Line In");
 	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
index 13802ff7cf05..726bd651a105 100644
--- a/sound/soc/au1x/ac97c.c
+++ b/sound/soc/au1x/ac97c.c
@@ -226,7 +226,7 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
 static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
 {
 	int ret;
-	struct resource *r;
+	struct resource *iores, *dmares;
 	struct au1xpsc_audio_data *ctx;
 
 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -235,29 +235,30 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
 
 	mutex_init(&ctx->lock);
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r) {
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iores) {
 		ret = -ENODEV;
 		goto out0;
 	}
 
 	ret = -EBUSY;
-	if (!request_mem_region(r->start, resource_size(r), pdev->name))
+	if (!request_mem_region(iores->start, resource_size(iores),
+				pdev->name))
 		goto out0;
 
-	ctx->mmio = ioremap_nocache(r->start, resource_size(r));
+	ctx->mmio = ioremap_nocache(iores->start, resource_size(iores));
 	if (!ctx->mmio)
 		goto out1;
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r)
-		goto out1;
-	ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!dmares)
+		goto out2;
+	ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!r)
-		goto out1;
-	ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (!dmares)
+		goto out2;
+	ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
 	/* switch it on */
 	WR(ctx, AC97_ENABLE, EN_D | EN_CE);
@@ -270,13 +271,15 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
 
 	ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver);
 	if (ret)
-		goto out1;
+		goto out2;
 
 	ac97c_workdata = ctx;
 	return 0;
 
+out2:
+	iounmap(ctx->mmio);
 out1:
-	release_mem_region(r->start, resource_size(r));
+	release_mem_region(iores->start, resource_size(iores));
 out0:
 	kfree(ctx);
 	return ret;
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
index 19e0d2a9c828..6bcf48f5884c 100644
--- a/sound/soc/au1x/i2sc.c
+++ b/sound/soc/au1x/i2sc.c
@@ -228,47 +228,50 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
 static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
 {
 	int ret;
-	struct resource *r;
+	struct resource *iores, *dmares;
 	struct au1xpsc_audio_data *ctx;
 
 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r) {
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iores) {
 		ret = -ENODEV;
 		goto out0;
 	}
 
 	ret = -EBUSY;
-	if (!request_mem_region(r->start, resource_size(r), pdev->name))
+	if (!request_mem_region(iores->start, resource_size(iores),
+				pdev->name))
 		goto out0;
 
-	ctx->mmio = ioremap_nocache(r->start, resource_size(r));
+	ctx->mmio = ioremap_nocache(iores->start, resource_size(iores));
 	if (!ctx->mmio)
 		goto out1;
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r)
-		goto out1;
-	ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!dmares)
+		goto out2;
+	ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!r)
-		goto out1;
-	ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (!dmares)
+		goto out2;
+	ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
 	platform_set_drvdata(pdev, ctx);
 
 	ret = snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
 	if (ret)
-		goto out1;
+		goto out2;
 
 	return 0;
 
+out2:
+	iounmap(ctx->mmio);
 out1:
-	release_mem_region(r->start, resource_size(r));
+	release_mem_region(iores->start, resource_size(iores));
 out0:
 	kfree(ctx);
 	return ret;
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 172eefd38b2d..0c6acd547141 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -364,7 +364,7 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
 static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 {
 	int ret;
-	struct resource *r;
+	struct resource *iores, *dmares;
 	unsigned long sel;
 	struct au1xpsc_audio_data *wd;
 
@@ -374,29 +374,30 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 
 	mutex_init(&wd->lock);
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r) {
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iores) {
 		ret = -ENODEV;
 		goto out0;
 	}
 
 	ret = -EBUSY;
-	if (!request_mem_region(r->start, resource_size(r), pdev->name))
+	if (!request_mem_region(iores->start, resource_size(iores),
+				pdev->name))
 		goto out0;
 
-	wd->mmio = ioremap(r->start, resource_size(r));
+	wd->mmio = ioremap(iores->start, resource_size(iores));
 	if (!wd->mmio)
 		goto out1;
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r)
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!dmares)
 		goto out2;
-	wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+	wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!r)
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (!dmares)
 		goto out2;
-	wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+	wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
 	/* configuration: max dma trigger threshold, enable ac97 */
 	wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
@@ -428,7 +429,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 out2:
 	iounmap(wd->mmio);
 out1:
-	release_mem_region(r->start, resource_size(r));
+	release_mem_region(iores->start, resource_size(iores));
 out0:
 	kfree(wd);
 	return ret;
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 7c5ae920544f..e03c5ce01b30 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -290,7 +290,7 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
 
 static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 {
-	struct resource *r;
+	struct resource *iores, *dmares;
 	unsigned long sel;
 	int ret;
 	struct au1xpsc_audio_data *wd;
@@ -299,29 +299,30 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 	if (!wd)
 		return -ENOMEM;
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r) {
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iores) {
 		ret = -ENODEV;
 		goto out0;
 	}
 
 	ret = -EBUSY;
-	if (!request_mem_region(r->start, resource_size(r), pdev->name))
+	if (!request_mem_region(iores->start, resource_size(iores),
+				pdev->name))
 		goto out0;
 
-	wd->mmio = ioremap(r->start, resource_size(r));
+	wd->mmio = ioremap(iores->start, resource_size(iores));
 	if (!wd->mmio)
 		goto out1;
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r)
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!dmares)
 		goto out2;
-	wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+	wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!r)
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (!dmares)
 		goto out2;
-	wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+	wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
 	/* preserve PSC clock source set up by platform (dev.platform_data
 	 * is already occupied by soc layer)
@@ -355,7 +356,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 out2:
 	iounmap(wd->mmio);
 out1:
-	release_mem_region(r->start, resource_size(r));
+	release_mem_region(iores->start, resource_size(iores));
 out0:
 	kfree(wd);
 	return ret;
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 9e59f680bc19..56815c1d47b3 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -418,7 +418,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
+static int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
 	struct snd_soc_dai *dai = rtd->cpu_dai;
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 61ddf942fd4d..7565e1576ffa 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -257,7 +257,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
+static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
 	struct snd_soc_dai *dai = rtd->cpu_dai;
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 19241576b6b5..5ca122e51183 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -772,11 +773,12 @@ static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
 
 
 	SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
-			    PM860X_DAC_EN_2, 0, 0),
+			    SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
-			    PM860X_DAC_EN_2, 0, 0),
+			    SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
 			     PM860X_I2S_IFACE_3, 5, 1),
+	SND_SOC_DAPM_SUPPLY("I2S CLK", PM860X_DAC_EN_2, 0, 0, NULL, 0),
 	SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
 	SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
 	SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
@@ -868,6 +870,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"Left ADC", NULL, "Left ADC MOD"},
 	{"Right ADC", NULL, "Right ADC MOD"},
 
+	/* I2S Clock */
+	{"I2S DIN", NULL, "I2S CLK"},
+	{"I2S DIN1", NULL, "I2S CLK"},
+	{"I2S DOUT", NULL, "I2S CLK"},
+
 	/* PCM/AIF1 Inputs */
 	{"PCM SDO", NULL, "ADC Left Mux"},
 	{"PCM SDO", NULL, "ADCR EC Mux"},
@@ -1173,6 +1180,9 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
 			/* Enable Audio PLL & Audio section */
+			data = AUDIO_PLL | AUDIO_SECTION_ON;
+			pm860x_reg_write(codec->control_data, REG_MISC2, data);
+			udelay(300);
 			data = AUDIO_PLL | AUDIO_SECTION_RESET
 				| AUDIO_SECTION_ON;
 			pm860x_reg_write(codec->control_data, REG_MISC2, data);
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 71b46c8f70d7..4584514d93d4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX9850 if I2C
 	select SND_SOC_MAX9877 if I2C
 	select SND_SOC_PCM3008
+	select SND_SOC_RT5631 if I2C
 	select SND_SOC_SGTL5000 if I2C
 	select SND_SOC_SN95031 if INTEL_SCU_IPC
 	select SND_SOC_SPDIF
@@ -48,7 +49,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
 	select SND_SOC_TLV320AIC23 if I2C
 	select SND_SOC_TLV320AIC26 if SPI_MASTER
-	select SND_SOC_TVL320AIC32X4 if I2C
+	select SND_SOC_TLV320AIC32X4 if I2C
 	select SND_SOC_TLV320AIC3X if I2C
 	select SND_SOC_TPA6130A2 if I2C
 	select SND_SOC_TLV320DAC33 if I2C
@@ -59,6 +60,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_WL1273 if MFD_WL1273_CORE
 	select SND_SOC_WM1250_EV1 if I2C
 	select SND_SOC_WM2000 if I2C
+	select SND_SOC_WM5100 if I2C
 	select SND_SOC_WM8350 if MFD_WM8350
 	select SND_SOC_WM8400 if MFD_WM8400
 	select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
@@ -218,6 +220,9 @@ config SND_SOC_MAX9850
 config SND_SOC_PCM3008
        tristate
 
+config SND_SOC_RT5631
+	tristate
+
 #Freescale sgtl5000 codec
 config SND_SOC_SGTL5000
 	tristate
@@ -244,7 +249,7 @@ config SND_SOC_TLV320AIC26
 	tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
 	depends on SPI
 
-config SND_SOC_TVL320AIC32X4
+config SND_SOC_TLV320AIC32X4
 	tristate
 
 config SND_SOC_TLV320AIC3X
@@ -273,6 +278,9 @@ config SND_SOC_WL1273
 config SND_SOC_WM1250_EV1
 	tristate
 
+config SND_SOC_WM5100
+	tristate
+
 config SND_SOC_WM8350
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 70c1769acd15..a2c7842e357b 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -26,6 +26,7 @@ snd-soc-max98088-objs := max98088.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-pcm3008-objs := pcm3008.o
+snd-soc-rt5631-objs := rt5631.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-sn95031-objs := sn95031.o
@@ -44,6 +45,7 @@ snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
+snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
 snd-soc-wm8510-objs := wm8510.o
@@ -125,6 +127,7 @@ obj-$(CONFIG_SND_SOC_MAX98088)	+= snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98095)	+= snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_PCM3008)	+= snd-soc-pcm3008.o
+obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SN95031)	+=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)	+= snd-soc-spdif.o
@@ -134,7 +137,7 @@ 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
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
-obj-$(CONFIG_SND_SOC_TVL320AIC32X4)     += snd-soc-tlv320aic32x4.o
+obj-$(CONFIG_SND_SOC_TLV320AIC32X4)     += snd-soc-tlv320aic32x4.o
 obj-$(CONFIG_SND_SOC_TLV320DAC33)	+= snd-soc-tlv320dac33.o
 obj-$(CONFIG_SND_SOC_TWL4030)	+= snd-soc-twl4030.o
 obj-$(CONFIG_SND_SOC_TWL6040)	+= snd-soc-twl6040.o
@@ -142,6 +145,7 @@ obj-$(CONFIG_SND_SOC_UDA134X)	+= snd-soc-uda134x.o
 obj-$(CONFIG_SND_SOC_UDA1380)	+= snd-soc-uda1380.o
 obj-$(CONFIG_SND_SOC_WL1273)	+= snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
+obj-$(CONFIG_SND_SOC_WM5100)	+= snd-soc-wm5100.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/ad193x.c b/sound/soc/codecs/ad193x.c
index f934670199a5..120602130b5c 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -103,12 +103,14 @@ static const struct snd_soc_dapm_route audio_paths[] = {
 static int ad193x_mute(struct snd_soc_dai *dai, int mute)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	int reg;
 
-	reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
-	reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg &
-		(~AD193X_DAC_MASTER_MUTE);
-	snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
+	if (mute)
+		snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+				    AD193X_DAC_MASTER_MUTE,
+				    AD193X_DAC_MASTER_MUTE);
+	else
+		snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+				    AD193X_DAC_MASTER_MUTE, 0);
 
 	return 0;
 }
@@ -262,7 +264,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
 		struct snd_pcm_hw_params *params,
 		struct snd_soc_dai *dai)
 {
-	int word_len = 0, reg = 0, master_rate = 0;
+	int word_len = 0, master_rate = 0;
 
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
@@ -297,18 +299,15 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0);
-	reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate;
-	snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg);
+	snd_soc_update_bits(codec, AD193X_PLL_CLK_CTRL0,
+			    AD193X_PLL_INPUT_MASK, master_rate);
 
-	reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
-	reg = (reg & (~AD193X_DAC_WORD_LEN_MASK))
-		| (word_len << AD193X_DAC_WORD_LEN_SHFT);
-	snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
+	snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+			    AD193X_DAC_WORD_LEN_MASK,
+			    word_len << AD193X_DAC_WORD_LEN_SHFT);
 
-	reg = snd_soc_read(codec, AD193X_ADC_CTRL1);
-	reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len;
-	snd_soc_write(codec, AD193X_ADC_CTRL1, reg);
+	snd_soc_update_bits(codec, AD193X_ADC_CTRL1,
+			    AD193X_ADC_WORD_LEN_MASK, word_len);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 536e5f2b136e..1507eaa425a3 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -11,7 +11,7 @@
 
 #define AD193X_PLL_CLK_CTRL0    0x00
 #define AD193X_PLL_POWERDOWN           0x01
-#define AD193X_PLL_INPUT_MASK   (~0x6)
+#define AD193X_PLL_INPUT_MASK   0x6
 #define AD193X_PLL_INPUT_256    (0 << 1)
 #define AD193X_PLL_INPUT_384    (1 << 1)
 #define AD193X_PLL_INPUT_512    (2 << 1)
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 4c0fc30a4ccb..e3931cc5e66c 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -148,7 +148,6 @@ static struct snd_soc_dai_driver ad1980_dai = {
 		.rates = SNDRV_PCM_RATE_48000,
 		.formats = SND_SOC_STD_AC97_FMTS, },
 };
-EXPORT_SYMBOL_GPL(ad1980_dai);
 
 static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
 {
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 2aa40c3731d0..1ccf8dd47576 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -974,7 +974,7 @@ static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		break;
 	case SND_SOC_DAIFMT_CBS_CFS:
 		ctrl = 0;
-		adau1373_dai->master = true;
+		adau1373_dai->master = false;
 		break;
 	default:
 		return -EINVAL;
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 2758d5fc60d6..8b7e1c50d6e9 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -401,7 +401,7 @@ static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute)
 }
 
 static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
-	unsigned int freq, int dir)
+	int source, unsigned int freq, int dir)
 {
 	unsigned int val;
 
@@ -458,6 +458,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
 	int ret;
 
 	codec->dapm.idle_bias_off = 1;
+	codec->control_data = to_i2c_client(codec->dev);
 
 	ret = adau1701_load_firmware(codec);
 	if (ret)
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h
deleted file mode 100644
index 3ce028614002..000000000000
--- a/sound/soc/codecs/ads117x.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * ads117x.h  --  Driver for ads1174/8 ADC chips
- *
- * Copyright 2009 ShotSpotter Inc.
- * Author: Graeme Gregory <gg@slimlogic.co.uk>
- *
- *  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;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-extern struct snd_soc_dai_driver ads117x_dai;
-extern struct snd_soc_codec_driver soc_codec_dev_ads117x;
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index cbf0b6d400b8..d3b29dce6ed7 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -247,7 +247,7 @@ static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
 	.probe =	ak4104_probe,
 	.remove =	ak4104_remove,
 	.reg_cache_size = AK4104_NUM_REGS,
-	.reg_word_size = sizeof(u16),
+	.reg_word_size = sizeof(u8),
 };
 
 static int ak4104_spi_probe(struct spi_device *spi)
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index e1a214ee757f..95d782d86e7d 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -34,74 +34,16 @@
 struct ak4535_priv {
 	unsigned int sysclk;
 	enum snd_soc_control_type control_type;
-	void *control_data;
 };
 
 /*
  * ak4535 register cache
  */
-static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
-    0x0000, 0x0080, 0x0000, 0x0003,
-    0x0002, 0x0000, 0x0011, 0x0001,
-    0x0000, 0x0040, 0x0036, 0x0010,
-    0x0000, 0x0000, 0x0057, 0x0000,
-};
-
-/*
- * read ak4535 register cache
- */
-static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
-	unsigned int reg)
-{
-	u16 *cache = codec->reg_cache;
-	if (reg >= AK4535_CACHEREGNUM)
-		return -1;
-	return cache[reg];
-}
-
-/*
- * write ak4535 register cache
- */
-static inline void ak4535_write_reg_cache(struct snd_soc_codec *codec,
-	u16 reg, unsigned int value)
-{
-	u16 *cache = codec->reg_cache;
-	if (reg >= AK4535_CACHEREGNUM)
-		return;
-	cache[reg] = value;
-}
-
-/*
- * write to the AK4535 register space
- */
-static int ak4535_write(struct snd_soc_codec *codec, unsigned int reg,
-	unsigned int value)
-{
-	u8 data[2];
-
-	/* data is
-	 *   D15..D8 AK4535 register offset
-	 *   D7...D0 register data
-	 */
-	data[0] = reg & 0xff;
-	data[1] = value & 0xff;
-
-	ak4535_write_reg_cache(codec, reg, value);
-	if (codec->hw_write(codec->control_data, data, 2) == 2)
-		return 0;
-	else
-		return -EIO;
-}
-
-static int ak4535_sync(struct snd_soc_codec *codec)
-{
-	u16 *cache = codec->reg_cache;
-	int i, r = 0;
-
-	for (i = 0; i < AK4535_CACHEREGNUM; i++)
-		r |= ak4535_write(codec, i, cache[i]);
-
-	return r;
+static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
+	0x00, 0x80, 0x00, 0x03,
+	0x02, 0x00, 0x11, 0x01,
+	0x00, 0x40, 0x36, 0x10,
+	0x00, 0x00, 0x57, 0x00,
 };
 
 static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
@@ -304,7 +246,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
-	u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
+	u8 mode2 = snd_soc_read(codec, AK4535_MODE2) & ~(0x3 << 5);
 	int rate = params_rate(params), fs = 256;
 
 	if (rate)
@@ -323,7 +265,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/* set rate */
-	ak4535_write(codec, AK4535_MODE2, mode2);
+	snd_soc_write(codec, AK4535_MODE2, mode2);
 	return 0;
 }
 
@@ -348,44 +290,37 @@ static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	/* use 32 fs for BCLK to save power */
 	mode1 |= 0x4;
 
-	ak4535_write(codec, AK4535_MODE1, mode1);
+	snd_soc_write(codec, AK4535_MODE1, mode1);
 	return 0;
 }
 
 static int ak4535_mute(struct snd_soc_dai *dai, int mute)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
+	u16 mute_reg = snd_soc_read(codec, AK4535_DAC);
 	if (!mute)
-		ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
+		snd_soc_write(codec, AK4535_DAC, mute_reg & ~0x20);
 	else
-		ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
+		snd_soc_write(codec, AK4535_DAC, mute_reg | 0x20);
 	return 0;
 }
 
 static int ak4535_set_bias_level(struct snd_soc_codec *codec,
 	enum snd_soc_bias_level level)
 {
-	u16 i, mute_reg;
-
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
-		ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
+		snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0);
 		break;
 	case SND_SOC_BIAS_PREPARE:
-		mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
-		ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
+		snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0x20);
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		i = ak4535_read_reg_cache(codec, AK4535_PM1);
-		ak4535_write(codec, AK4535_PM1, i | 0x80);
-		i = ak4535_read_reg_cache(codec, AK4535_PM2);
-		ak4535_write(codec, AK4535_PM2, i & (~0x80));
+		snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0x80);
+		snd_soc_update_bits(codec, AK4535_PM2, 0x80, 0);
 		break;
 	case SND_SOC_BIAS_OFF:
-		i = ak4535_read_reg_cache(codec, AK4535_PM1);
-		ak4535_write(codec, AK4535_PM1, i & (~0x80));
+		snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0);
 		break;
 	}
 	codec->dapm.bias_level = level;
@@ -428,7 +363,7 @@ static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int ak4535_resume(struct snd_soc_codec *codec)
 {
-	ak4535_sync(codec);
+	snd_soc_cache_sync(codec);
 	ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	return 0;
 }
@@ -436,11 +371,15 @@ static int ak4535_resume(struct snd_soc_codec *codec)
 static int ak4535_probe(struct snd_soc_codec *codec)
 {
 	struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
+	int ret;
 
 	printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
 
-	codec->control_data = ak4535->control_data;
-
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4535->control_type);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
 	/* power on device */
 	ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -461,8 +400,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
 	.remove =	ak4535_remove,
 	.suspend =	ak4535_suspend,
 	.resume =	ak4535_resume,
-	.read = ak4535_read_reg_cache,
-	.write = ak4535_write,
 	.set_bias_level = ak4535_set_bias_level,
 	.reg_cache_size = ARRAY_SIZE(ak4535_reg),
 	.reg_word_size = sizeof(u8),
@@ -485,7 +422,6 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, ak4535);
-	ak4535->control_data = i2c;
 	ak4535->control_type = SND_SOC_I2C;
 
 	ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 7a64e58cddc4..77838586f358 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -31,7 +31,6 @@
 
 /* codec private data */
 struct ak4641_priv {
-	struct snd_soc_codec *codec;
 	unsigned int sysclk;
 	int deemph;
 	int playback_fs;
@@ -226,7 +225,7 @@ static const struct snd_soc_dapm_widget ak4641_dapm_widgets[] = {
 	SND_SOC_DAPM_PGA("Mono Out 2", AK4641_PM2, 3, 0, NULL, 0),
 
 	SND_SOC_DAPM_ADC("Voice ADC", "Voice Capture", AK4641_BTIF, 0, 0),
-	SND_SOC_DAPM_ADC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0),
+	SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0),
 
 	SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4641_MIC, 3, 0),
 	SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4641_MIC, 4, 0),
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 65f46047b1cb..d8fc04486abb 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -156,81 +156,22 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
 struct ak4642_priv {
 	unsigned int sysclk;
 	enum snd_soc_control_type control_type;
-	void *control_data;
 };
 
 /*
  * ak4642 register cache
  */
-static const u16 ak4642_reg[AK4642_CACHEREGNUM] = {
-	0x0000, 0x0000, 0x0001, 0x0000,
-	0x0002, 0x0000, 0x0000, 0x0000,
-	0x00e1, 0x00e1, 0x0018, 0x0000,
-	0x00e1, 0x0018, 0x0011, 0x0008,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000,
-};
-
-/*
- * read ak4642 register cache
- */
-static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec,
-	unsigned int reg)
-{
-	u16 *cache = codec->reg_cache;
-	if (reg >= AK4642_CACHEREGNUM)
-		return -1;
-	return cache[reg];
-}
-
-/*
- * write ak4642 register cache
- */
-static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec,
-	u16 reg, unsigned int value)
-{
-	u16 *cache = codec->reg_cache;
-	if (reg >= AK4642_CACHEREGNUM)
-		return;
-
-	cache[reg] = value;
-}
-
-/*
- * write to the AK4642 register space
- */
-static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg,
-	unsigned int value)
-{
-	u8 data[2];
-
-	/* data is
-	 *   D15..D8 AK4642 register offset
-	 *   D7...D0 register data
-	 */
-	data[0] = reg & 0xff;
-	data[1] = value & 0xff;
-
-	if (codec->hw_write(codec->control_data, data, 2) == 2) {
-		ak4642_write_reg_cache(codec, reg, value);
-		return 0;
-	} else
-		return -EIO;
-}
-
-static int ak4642_sync(struct snd_soc_codec *codec)
-{
-	u16 *cache = codec->reg_cache;
-	int i, r = 0;
-
-	for (i = 0; i < AK4642_CACHEREGNUM; i++)
-		r |= ak4642_write(codec, i, cache[i]);
-
-	return r;
+static const u8 ak4642_reg[AK4642_CACHEREGNUM] = {
+	0x00, 0x00, 0x01, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0xe1, 0xe1, 0x18, 0x00,
+	0xe1, 0x18, 0x11, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00,
 };
 
 static int ak4642_dai_startup(struct snd_pcm_substream *substream,
@@ -252,8 +193,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
 		 */
 		snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
 		snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
-		ak4642_write(codec, L_IVC, 0x91); /* volume */
-		ak4642_write(codec, R_IVC, 0x91); /* volume */
+		snd_soc_write(codec, L_IVC, 0x91); /* volume */
+		snd_soc_write(codec, R_IVC, 0x91); /* volume */
 		snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC,
 						     PMVCM | PMMIN | PMDAC);
 		snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK,	PMHP);
@@ -272,9 +213,9 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
 		 * This operation came from example code of
 		 * "ASAHI KASEI AK4642" (japanese) manual p94.
 		 */
-		ak4642_write(codec, SG_SL1, PMMP | MGAIN0);
-		ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
-		ak4642_write(codec, ALC_CTL1, ALC | LMTH0);
+		snd_soc_write(codec, SG_SL1, PMMP | MGAIN0);
+		snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
+		snd_soc_write(codec, ALC_CTL1, ALC | LMTH0);
 		snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL,
 						     PMVCM | PMADL);
 		snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
@@ -462,7 +403,7 @@ static struct snd_soc_dai_driver ak4642_dai = {
 
 static int ak4642_resume(struct snd_soc_codec *codec)
 {
-	ak4642_sync(codec);
+	snd_soc_cache_sync(codec);
 	return 0;
 }
 
@@ -470,11 +411,15 @@ static int ak4642_resume(struct snd_soc_codec *codec)
 static int ak4642_probe(struct snd_soc_codec *codec)
 {
 	struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
+	int ret;
 
 	dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
 
-	codec->hw_write		= (hw_write_t)i2c_master_send;
-	codec->control_data	= ak4642->control_data;
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
 
 	snd_soc_add_controls(codec, ak4642_snd_controls,
 			     ARRAY_SIZE(ak4642_snd_controls));
@@ -485,8 +430,6 @@ static int ak4642_probe(struct snd_soc_codec *codec)
 static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
 	.probe			= ak4642_probe,
 	.resume			= ak4642_resume,
-	.read			= ak4642_read_reg_cache,
-	.write			= ak4642_write,
 	.reg_cache_size		= ARRAY_SIZE(ak4642_reg),
 	.reg_word_size		= sizeof(u8),
 	.reg_cache_default	= ak4642_reg,
@@ -504,7 +447,6 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, ak4642);
-	ak4642->control_data = i2c;
 	ak4642->control_type = SND_SOC_I2C;
 
 	ret =  snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 88b29f8c748b..de9ff66d3721 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -26,7 +26,6 @@
 /* codec private data */
 struct ak4671_priv {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 };
 
 /* ak4671 register cache & default register settings */
@@ -169,18 +168,15 @@ static int ak4671_out2_event(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	u8 reg;
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
-		reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
-		reg |= AK4671_MUTEN;
-		snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
+		snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT,
+				    AK4671_MUTEN, AK4671_MUTEN);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
-		reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
-		reg &= ~AK4671_MUTEN;
-		snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
+		snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT,
+				    AK4671_MUTEN, 0);
 		break;
 	}
 
@@ -576,15 +572,12 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static int ak4671_set_bias_level(struct snd_soc_codec *codec,
 		enum snd_soc_bias_level level)
 {
-	u8 reg;
-
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 	case SND_SOC_BIAS_PREPARE:
 	case SND_SOC_BIAS_STANDBY:
-		reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT);
-		snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT,
-				reg | AK4671_PMVCM);
+		snd_soc_update_bits(codec, AK4671_AD_DA_POWER_MANAGEMENT,
+				    AK4671_PMVCM, AK4671_PMVCM);
 		break;
 	case SND_SOC_BIAS_OFF:
 		snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
@@ -629,8 +622,6 @@ static int ak4671_probe(struct snd_soc_codec *codec)
 	struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
-	codec->hw_write = (hw_write_t)i2c_master_send;
-
 	ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -675,7 +666,6 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, ak4671);
-	ak4671->control_data = client;
 	ak4671->control_type = SND_SOC_I2C;
 
 	ret = snd_soc_register_codec(&client->dev,
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index 05173159507e..984b14bcb605 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -40,7 +40,6 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
 /* codec private data */
 struct alc5623_priv {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 	u8 id;
 	unsigned int sysclk;
 	u16 reg_cache[ALC5623_VENDOR_ID2+2];
@@ -54,8 +53,10 @@ static void alc5623_fill_cache(struct snd_soc_codec *codec)
 	u16 *cache = codec->reg_cache;
 
 	/* not really efficient ... */
+	codec->cache_bypass = 1;
 	for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
-		cache[i] = codec->hw_read(codec, i);
+		cache[i] = snd_soc_read(codec, i);
+	codec->cache_bypass = 0;
 }
 
 static inline int alc5623_reset(struct snd_soc_codec *codec)
@@ -1049,7 +1050,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
 	}
 
 	i2c_set_clientdata(client, alc5623);
-	alc5623->control_data = client;
 	alc5623->control_type = SND_SOC_I2C;
 
 	ret =  snd_soc_register_codec(&client->dev,
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 6cc8678f49f3..f1f237ecec2a 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -128,7 +128,6 @@ static const char *supply_names[] = {
 /* Private data for the CS4270 */
 struct cs4270_private {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 	unsigned int mclk; /* Input frequency of the MCLK pin */
 	unsigned int mode; /* The mode (I2S or left-justified) */
 	unsigned int slave_mode;
@@ -262,7 +261,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
 	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
-	int ret = 0;
 
 	/* set DAI format */
 	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -272,7 +270,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		break;
 	default:
 		dev_err(codec->dev, "invalid dai format\n");
-		ret = -EINVAL;
+		return -EINVAL;
 	}
 
 	/* set master/slave audio interface */
@@ -285,10 +283,11 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		break;
 	default:
 		/* all other modes are unsupported by the hardware */
-		ret = -EINVAL;
+		dev_err(codec->dev, "Unknown master/slave configuration\n");
+		return -EINVAL;
 	}
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -490,8 +489,6 @@ static int cs4270_probe(struct snd_soc_codec *codec)
 	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
 	int i, ret;
 
-	codec->control_data = cs4270->control_data;
-
 	/* Tell ASoC what kind of I/O to use to read the registers.  ASoC will
 	 * then do the I2C transactions itself.
 	 */
@@ -604,7 +601,7 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
 static int cs4270_soc_resume(struct snd_soc_codec *codec)
 {
 	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
-	struct i2c_client *i2c_client = codec->control_data;
+	struct i2c_client *i2c_client = to_i2c_client(codec->dev);
 	int reg;
 
 	regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
@@ -690,7 +687,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
 	}
 
 	i2c_set_clientdata(i2c_client, cs4270);
-	cs4270->control_data = i2c_client;
 	cs4270->control_type = SND_SOC_I2C;
 
 	ret = snd_soc_register_codec(&i2c_client->dev,
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 083aab96ca80..23d1bd5dadda 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -156,7 +156,6 @@ static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = {
 struct cs4271_private {
 	/* SND_SOC_I2C or SND_SOC_SPI */
 	enum snd_soc_control_type	bus_type;
-	void				*control_data;
 	unsigned int			mclk;
 	bool				master;
 	bool				deemph;
@@ -466,8 +465,6 @@ static int cs4271_probe(struct snd_soc_codec *codec)
 	int ret;
 	int gpio_nreset = -EINVAL;
 
-	codec->control_data = cs4271->control_data;
-
 	if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
 		gpio_nreset = cs4271plat->gpio_nreset;
 
@@ -555,7 +552,6 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
 		return -ENOMEM;
 
 	spi_set_drvdata(spi, cs4271);
-	cs4271->control_data = spi;
 	cs4271->bus_type = SND_SOC_SPI;
 
 	return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
@@ -595,7 +591,6 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, cs4271);
-	cs4271->control_data = client;
 	cs4271->bus_type = SND_SOC_I2C;
 
 	return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 8fb7070108dd..8c3c8205d19e 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -42,7 +42,6 @@ enum master_slave_mode {
 
 struct cs42l51_private {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 	unsigned int mclk;
 	unsigned int audio_mode;	/* The mode (I2S or left-justified) */
 	enum master_slave_mode func;
@@ -57,7 +56,7 @@ struct cs42l51_private {
 static int cs42l51_fill_cache(struct snd_soc_codec *codec)
 {
 	u8 *cache = codec->reg_cache + 1;
-	struct i2c_client *i2c_client = codec->control_data;
+	struct i2c_client *i2c_client = to_i2c_client(codec->dev);
 	s32 length;
 
 	length = i2c_smbus_read_i2c_block_data(i2c_client,
@@ -289,7 +288,6 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
 	struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
-	int ret = 0;
 
 	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
@@ -299,7 +297,7 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		break;
 	default:
 		dev_err(codec->dev, "invalid DAI format\n");
-		ret = -EINVAL;
+		return -EINVAL;
 	}
 
 	switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -310,11 +308,11 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		cs42l51->func = MODE_SLAVE_AUTO;
 		break;
 	default:
-		ret = -EINVAL;
-		break;
+		dev_err(codec->dev, "Unknown master/slave configuration\n");
+		return -EINVAL;
 	}
 
-	return ret;
+	return 0;
 }
 
 struct cs42l51_ratios {
@@ -520,8 +518,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret, reg;
 
-	codec->control_data = cs42l51->control_data;
-
 	ret = cs42l51_fill_cache(codec);
 	if (ret < 0) {
 		dev_err(codec->dev, "failed to fill register cache\n");
@@ -593,7 +589,6 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
 	}
 
 	i2c_set_clientdata(i2c_client, cs42l51);
-	cs42l51->control_data = i2c_client;
 	cs42l51->control_type = SND_SOC_I2C;
 
 	ret =  snd_soc_register_codec(&i2c_client->dev,
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 92fd9d7a9221..0ebcbd534490 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -26,23 +26,41 @@
 #include <sound/tlv.h>
 
 /* DA7210 register space */
+#define DA7210_CONTROL			0x01
 #define DA7210_STATUS			0x02
 #define DA7210_STARTUP1			0x03
+#define DA7210_STARTUP2			0x04
+#define DA7210_STARTUP3			0x05
 #define DA7210_MIC_L			0x07
 #define DA7210_MIC_R			0x08
+#define DA7210_AUX1_L			0x09
+#define DA7210_AUX1_R			0x0A
+#define DA7210_AUX2			0x0B
+#define DA7210_IN_GAIN			0x0C
 #define DA7210_INMIX_L			0x0D
 #define DA7210_INMIX_R			0x0E
 #define DA7210_ADC_HPF			0x0F
 #define DA7210_ADC			0x10
+#define DA7210_ADC_EQ1_2		0X11
+#define DA7210_ADC_EQ3_4		0x12
+#define DA7210_ADC_EQ5			0x13
 #define DA7210_DAC_HPF			0x14
 #define DA7210_DAC_L			0x15
 #define DA7210_DAC_R			0x16
 #define DA7210_DAC_SEL			0x17
+#define DA7210_SOFTMUTE			0x18
+#define DA7210_DAC_EQ1_2		0x19
+#define DA7210_DAC_EQ3_4		0x1A
+#define DA7210_DAC_EQ5			0x1B
 #define DA7210_OUTMIX_L			0x1C
 #define DA7210_OUTMIX_R			0x1D
+#define DA7210_OUT1_L			0x1E
+#define DA7210_OUT1_R			0x1F
+#define DA7210_OUT2			0x20
 #define DA7210_HP_L_VOL			0x21
 #define DA7210_HP_R_VOL			0x22
 #define DA7210_HP_CFG			0x23
+#define DA7210_ZERO_CROSS		0x24
 #define DA7210_DAI_SRC_SEL		0x25
 #define DA7210_DAI_CFG1			0x26
 #define DA7210_DAI_CFG3			0x28
@@ -50,6 +68,12 @@
 #define DA7210_PLL_DIV2			0x2A
 #define DA7210_PLL_DIV3			0x2B
 #define DA7210_PLL			0x2C
+#define DA7210_ALC_MAX			0x83
+#define DA7210_ALC_MIN			0x84
+#define DA7210_ALC_NOIS			0x85
+#define DA7210_ALC_ATT			0x86
+#define DA7210_ALC_REL			0x87
+#define DA7210_ALC_DEL			0x88
 #define DA7210_A_HID_UNLOCK		0x8A
 #define DA7210_A_TEST_UNLOCK		0x8B
 #define DA7210_A_PLL1			0x90
@@ -72,6 +96,7 @@
 #define DA7210_IN_R_EN			(1 << 7)
 
 /* ADC bit fields */
+#define DA7210_ADC_ALC_EN		(1 << 0)
 #define DA7210_ADC_L_EN			(1 << 3)
 #define DA7210_ADC_R_EN			(1 << 7)
 
@@ -105,12 +130,17 @@
 
 /* DAI_CFG1 bit fields */
 #define DA7210_DAI_WORD_S16_LE		(0 << 0)
+#define DA7210_DAI_WORD_S20_3LE		(1 << 0)
 #define DA7210_DAI_WORD_S24_LE		(2 << 0)
+#define DA7210_DAI_WORD_S32_LE		(3 << 0)
 #define DA7210_DAI_FLEN_64BIT		(1 << 2)
+#define DA7210_DAI_MODE_SLAVE		(0 << 7)
 #define DA7210_DAI_MODE_MASTER		(1 << 7)
 
 /* DAI_CFG3 bit fields */
 #define DA7210_DAI_FORMAT_I2SMODE	(0 << 0)
+#define DA7210_DAI_FORMAT_LEFT_J	(1 << 0)
+#define DA7210_DAI_FORMAT_RIGHT_J	(2 << 0)
 #define DA7210_DAI_OE			(1 << 3)
 #define DA7210_DAI_EN			(1 << 7)
 
@@ -133,6 +163,43 @@
 #define DA7210_PLL_FS_96000		(0xF << 0)
 #define DA7210_PLL_EN			(0x1 << 7)
 
+/* SOFTMUTE bit fields */
+#define DA7210_RAMP_EN			(1 << 6)
+
+/* CONTROL bit fields */
+#define DA7210_NOISE_SUP_EN		(1 << 3)
+
+/* IN_GAIN bit fields */
+#define DA7210_INPGA_L_VOL		(0x0F << 0)
+#define DA7210_INPGA_R_VOL		(0xF0 << 0)
+
+/* ZERO_CROSS bit fields */
+#define DA7210_AUX1_L_ZC		(1 << 0)
+#define DA7210_AUX1_R_ZC		(1 << 1)
+#define DA7210_HP_L_ZC			(1 << 6)
+#define DA7210_HP_R_ZC			(1 << 7)
+
+/* AUX1_L bit fields */
+#define DA7210_AUX1_L_VOL		(0x3F << 0)
+
+/* AUX1_R bit fields */
+#define DA7210_AUX1_R_VOL		(0x3F << 0)
+
+/* Minimum INPGA and AUX1 volume to enable noise suppression */
+#define DA7210_INPGA_MIN_VOL_NS		0x0A  /* 10.5dB */
+#define DA7210_AUX1_MIN_VOL_NS		0x35  /* 6dB */
+
+/* OUT1_L bit fields */
+#define DA7210_OUT1_L_EN		(1 << 7)
+
+/* OUT1_R bit fields */
+#define DA7210_OUT1_R_EN		(1 << 7)
+
+/* OUT2 bit fields */
+#define DA7210_OUT2_OUTMIX_R		(1 << 5)
+#define DA7210_OUT2_OUTMIX_L		(1 << 6)
+#define DA7210_OUT2_EN			(1 << 7)
+
 #define DA7210_VERSION "0.0.1"
 
 /*
@@ -144,24 +211,351 @@
  * mute		: 0x10
  * reserved	: 0x00 - 0x0F
  *
- * ** FIXME **
- *
  * Reserved area are considered as "mute".
- * -> min = -79.5 dB
  */
-static const DECLARE_TLV_DB_SCALE(hp_out_tlv, -7950, 150, 1);
+static const unsigned int hp_out_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
+	/* -54 dB to +15 dB */
+	0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0),
+};
+
+static const unsigned int lineout_vol_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
+	/* -54dB to 15dB */
+	0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0)
+};
+
+static const unsigned int mono_vol_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1),
+	/* -18dB to 6dB */
+	0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0)
+};
+
+static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1);
+static const DECLARE_TLV_DB_SCALE(dac_gain_tlv, -7725, 75, 0);
+
+/* ADC and DAC high pass filter f0 value */
+static const char const *da7210_hpf_cutoff_txt[] = {
+	"Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi"
+};
+
+static const struct soc_enum da7210_dac_hpf_cutoff =
+	SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt);
+
+static const struct soc_enum da7210_adc_hpf_cutoff =
+	SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt);
+
+/* ADC and DAC voice (8kHz) high pass cutoff value */
+static const char const *da7210_vf_cutoff_txt[] = {
+	"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
+};
+
+static const struct soc_enum da7210_dac_vf_cutoff =
+	SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt);
+
+static const struct soc_enum da7210_adc_vf_cutoff =
+	SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt);
+
+static const char *da7210_hp_mode_txt[] = {
+	"Class H", "Class G"
+};
+
+static const struct soc_enum da7210_hp_mode_sel =
+	SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt);
+
+/* ALC can be enabled only if noise suppression is disabled */
+static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	if (ucontrol->value.integer.value[0]) {
+		/* Check if noise suppression is enabled */
+		if (snd_soc_read(codec, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) {
+			dev_dbg(codec->dev,
+				"Disable noise suppression to enable ALC\n");
+			return -EINVAL;
+		}
+	}
+	/* If all conditions are met or we are actually disabling ALC */
+	return snd_soc_put_volsw(kcontrol, ucontrol);
+}
+
+/* Noise suppression can be enabled only if following conditions are met
+ *  ALC disabled
+ *  ZC enabled for HP and AUX1 PGA
+ *  INPGA_L_VOL and INPGA_R_VOL >= 10.5 dB
+ *  AUX1_L_VOL and AUX1_R_VOL >= 6 dB
+ */
+static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	u8 val;
+
+	if (ucontrol->value.integer.value[0]) {
+		/* Check if ALC is enabled */
+		if (snd_soc_read(codec, DA7210_ADC) & DA7210_ADC_ALC_EN)
+			goto err;
+
+		/* Check ZC for HP and AUX1 PGA */
+		if ((snd_soc_read(codec, DA7210_ZERO_CROSS) &
+			(DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC |
+			DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC |
+			DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC))
+			goto err;
+
+		/* Check INPGA_L_VOL and INPGA_R_VOL */
+		val = snd_soc_read(codec, DA7210_IN_GAIN);
+		if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) ||
+			(((val & DA7210_INPGA_R_VOL) >> 4) <
+			DA7210_INPGA_MIN_VOL_NS))
+			goto err;
+
+		/* Check AUX1_L_VOL and AUX1_R_VOL */
+		if (((snd_soc_read(codec, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) <
+		    DA7210_AUX1_MIN_VOL_NS) ||
+		    ((snd_soc_read(codec, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) <
+		    DA7210_AUX1_MIN_VOL_NS))
+			goto err;
+	}
+	/* If all conditions are met or we are actually disabling Noise sup */
+	return snd_soc_put_volsw(kcontrol, ucontrol);
+
+err:
+	return -EINVAL;
+}
 
 static const struct snd_kcontrol_new da7210_snd_controls[] = {
 
 	SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
 			 DA7210_HP_L_VOL, DA7210_HP_R_VOL,
 			 0, 0x3F, 0, hp_out_tlv),
+	SOC_DOUBLE_R_TLV("Digital Playback Volume",
+			 DA7210_DAC_L, DA7210_DAC_R,
+			 0, 0x77, 1, dac_gain_tlv),
+	SOC_DOUBLE_R_TLV("Lineout Playback Volume",
+			 DA7210_OUT1_L, DA7210_OUT1_R,
+			 0, 0x3f, 0, lineout_vol_tlv),
+	SOC_SINGLE_TLV("Mono Playback Volume", DA7210_OUT2, 0, 0x7, 0,
+		       mono_vol_tlv),
+
+	/* DAC Equalizer  controls */
+	SOC_SINGLE("DAC EQ Switch", DA7210_DAC_EQ5, 7, 1, 0),
+	SOC_SINGLE_TLV("DAC EQ1 Volume", DA7210_DAC_EQ1_2, 0, 0xf, 1,
+		       eq_gain_tlv),
+	SOC_SINGLE_TLV("DAC EQ2 Volume", DA7210_DAC_EQ1_2, 4, 0xf, 1,
+		       eq_gain_tlv),
+	SOC_SINGLE_TLV("DAC EQ3 Volume", DA7210_DAC_EQ3_4, 0, 0xf, 1,
+		       eq_gain_tlv),
+	SOC_SINGLE_TLV("DAC EQ4 Volume", DA7210_DAC_EQ3_4, 4, 0xf, 1,
+		       eq_gain_tlv),
+	SOC_SINGLE_TLV("DAC EQ5 Volume", DA7210_DAC_EQ5, 0, 0xf, 1,
+		       eq_gain_tlv),
+
+	/* ADC Equalizer  controls */
+	SOC_SINGLE("ADC EQ Switch", DA7210_ADC_EQ5, 7, 1, 0),
+	SOC_SINGLE_TLV("ADC EQ Master Volume", DA7210_ADC_EQ5, 4, 0x3,
+		       1, adc_eq_master_gain_tlv),
+	SOC_SINGLE_TLV("ADC EQ1 Volume", DA7210_ADC_EQ1_2, 0, 0xf, 1,
+		       eq_gain_tlv),
+	SOC_SINGLE_TLV("ADC EQ2 Volume", DA7210_ADC_EQ1_2, 4, 0xf, 1,
+		       eq_gain_tlv),
+	SOC_SINGLE_TLV("ADC EQ3 Volume", DA7210_ADC_EQ3_4, 0, 0xf, 1,
+		       eq_gain_tlv),
+	SOC_SINGLE_TLV("ADC EQ4 Volume", DA7210_ADC_EQ3_4, 4, 0xf, 1,
+		       eq_gain_tlv),
+	SOC_SINGLE_TLV("ADC EQ5 Volume", DA7210_ADC_EQ5, 0, 0xf, 1,
+		       eq_gain_tlv),
+
+	SOC_SINGLE("DAC HPF Switch", DA7210_DAC_HPF, 3, 1, 0),
+	SOC_ENUM("DAC HPF Cutoff", da7210_dac_hpf_cutoff),
+	SOC_SINGLE("DAC Voice Mode Switch", DA7210_DAC_HPF, 7, 1, 0),
+	SOC_ENUM("DAC Voice Cutoff", da7210_dac_vf_cutoff),
+
+	SOC_SINGLE("ADC HPF Switch", DA7210_ADC_HPF, 3, 1, 0),
+	SOC_ENUM("ADC HPF Cutoff", da7210_adc_hpf_cutoff),
+	SOC_SINGLE("ADC Voice Mode Switch", DA7210_ADC_HPF, 7, 1, 0),
+	SOC_ENUM("ADC Voice Cutoff", da7210_adc_vf_cutoff),
+
+	/* Mute controls */
+	SOC_DOUBLE_R("Mic Capture Switch", DA7210_MIC_L, DA7210_MIC_R, 3, 1, 0),
+	SOC_SINGLE("Aux2 Capture Switch", DA7210_AUX2, 2, 1, 0),
+	SOC_DOUBLE("ADC Capture Switch", DA7210_ADC, 2, 6, 1, 0),
+	SOC_SINGLE("Digital Soft Mute Switch", DA7210_SOFTMUTE, 7, 1, 0),
+	SOC_SINGLE("Digital Soft Mute Rate", DA7210_SOFTMUTE, 0, 0x7, 0),
+
+	/* Zero cross controls */
+	SOC_DOUBLE("Aux1 ZC Switch", DA7210_ZERO_CROSS, 0, 1, 1, 0),
+	SOC_DOUBLE("In PGA ZC Switch", DA7210_ZERO_CROSS, 2, 3, 1, 0),
+	SOC_DOUBLE("Lineout ZC Switch", DA7210_ZERO_CROSS, 4, 5, 1, 0),
+	SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0),
+
+	SOC_ENUM("Headphone Class", da7210_hp_mode_sel),
+
+	/* ALC controls */
+	SOC_SINGLE_EXT("ALC Enable Switch", DA7210_ADC, 0, 1, 0,
+		       snd_soc_get_volsw, da7210_put_alc_sw),
+	SOC_SINGLE("ALC Capture Max Volume", DA7210_ALC_MAX, 0, 0x3F, 0),
+	SOC_SINGLE("ALC Capture Min Volume", DA7210_ALC_MIN, 0, 0x3F, 0),
+	SOC_SINGLE("ALC Capture Noise Volume", DA7210_ALC_NOIS, 0, 0x3F, 0),
+	SOC_SINGLE("ALC Capture Attack Rate", DA7210_ALC_ATT, 0, 0xFF, 0),
+	SOC_SINGLE("ALC Capture Release Rate", DA7210_ALC_REL, 0, 0xFF, 0),
+	SOC_SINGLE("ALC Capture Release Delay", DA7210_ALC_DEL, 0, 0xFF, 0),
+
+	SOC_SINGLE_EXT("Noise Suppression Enable Switch", DA7210_CONTROL, 3, 1,
+		       0, snd_soc_get_volsw, da7210_put_noise_sup_sw),
+};
+
+/*
+ * DAPM Controls
+ *
+ * Current DAPM implementation covers almost all codec components e.g. IOs,
+ * mixers, PGAs,ADC and DAC.
+ */
+/* In Mixer Left */
+static const struct snd_kcontrol_new da7210_dapm_inmixl_controls[] = {
+	SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_L, 0, 1, 0),
+	SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_L, 1, 1, 0),
+};
+
+/* In Mixer Right */
+static const struct snd_kcontrol_new da7210_dapm_inmixr_controls[] = {
+	SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_R, 0, 1, 0),
+	SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_R, 1, 1, 0),
+};
+
+/* Out Mixer Left */
+static const struct snd_kcontrol_new da7210_dapm_outmixl_controls[] = {
+	SOC_DAPM_SINGLE("DAC Left Switch", DA7210_OUTMIX_L, 4, 1, 0),
+};
+
+/* Out Mixer Right */
+static const struct snd_kcontrol_new da7210_dapm_outmixr_controls[] = {
+	SOC_DAPM_SINGLE("DAC Right Switch", DA7210_OUTMIX_R, 4, 1, 0),
+};
+
+/* Mono Mixer */
+static const struct snd_kcontrol_new da7210_dapm_monomix_controls[] = {
+	SOC_DAPM_SINGLE("Outmix Right Switch", DA7210_OUT2, 5, 1, 0),
+	SOC_DAPM_SINGLE("Outmix Left Switch", DA7210_OUT2, 6, 1, 0),
+};
+
+/* DAPM widgets */
+static const struct snd_soc_dapm_widget da7210_dapm_widgets[] = {
+	/* Input Side */
+	/* Input Lines */
+	SND_SOC_DAPM_INPUT("MICL"),
+	SND_SOC_DAPM_INPUT("MICR"),
+
+	/* Input PGAs */
+	SND_SOC_DAPM_PGA("Mic Left", DA7210_STARTUP3, 0, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Mic Right", DA7210_STARTUP3, 1, 1, NULL, 0),
+
+	SND_SOC_DAPM_PGA("INPGA Left", DA7210_INMIX_L, 7, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INPGA Right", DA7210_INMIX_R, 7, 0, NULL, 0),
+
+	/* Input Mixers */
+	SND_SOC_DAPM_MIXER("In Mixer Left", SND_SOC_NOPM, 0, 0,
+		&da7210_dapm_inmixl_controls[0],
+		ARRAY_SIZE(da7210_dapm_inmixl_controls)),
+
+	SND_SOC_DAPM_MIXER("In Mixer Right", SND_SOC_NOPM, 0, 0,
+		&da7210_dapm_inmixr_controls[0],
+		ARRAY_SIZE(da7210_dapm_inmixr_controls)),
+
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC Left", "Capture", DA7210_STARTUP3, 5, 1),
+	SND_SOC_DAPM_ADC("ADC Right", "Capture", DA7210_STARTUP3, 6, 1),
+
+	/* Output Side */
+	/* DACs */
+	SND_SOC_DAPM_DAC("DAC Left", "Playback", DA7210_STARTUP2, 5, 1),
+	SND_SOC_DAPM_DAC("DAC Right", "Playback", DA7210_STARTUP2, 6, 1),
+
+	/* Output Mixers */
+	SND_SOC_DAPM_MIXER("Out Mixer Left", SND_SOC_NOPM, 0, 0,
+		&da7210_dapm_outmixl_controls[0],
+		ARRAY_SIZE(da7210_dapm_outmixl_controls)),
+
+	SND_SOC_DAPM_MIXER("Out Mixer Right", SND_SOC_NOPM, 0, 0,
+		&da7210_dapm_outmixr_controls[0],
+		ARRAY_SIZE(da7210_dapm_outmixr_controls)),
+
+	SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
+		&da7210_dapm_monomix_controls[0],
+		ARRAY_SIZE(da7210_dapm_monomix_controls)),
+
+	/* Output PGAs */
+	SND_SOC_DAPM_PGA("OUTPGA Left Enable", DA7210_OUTMIX_L, 7, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("OUTPGA Right Enable", DA7210_OUTMIX_R, 7, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA("Out1 Left", DA7210_STARTUP2, 0, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Out1 Right", DA7210_STARTUP2, 1, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Out2 Mono", DA7210_STARTUP2, 2, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Headphone Left", DA7210_STARTUP2, 3, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Headphone Right", DA7210_STARTUP2, 4, 1, NULL, 0),
+
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("OUT1L"),
+	SND_SOC_DAPM_OUTPUT("OUT1R"),
+	SND_SOC_DAPM_OUTPUT("HPL"),
+	SND_SOC_DAPM_OUTPUT("HPR"),
+	SND_SOC_DAPM_OUTPUT("OUT2"),
+};
+
+/* DAPM audio route definition */
+static const struct snd_soc_dapm_route da7210_audio_map[] = {
+	/* Dest       Connecting Widget    source */
+	/* Input path */
+	{"Mic Left", NULL, "MICL"},
+	{"Mic Right", NULL, "MICR"},
+
+	{"In Mixer Left", "Mic Left Switch", "Mic Left"},
+	{"In Mixer Left", "Mic Right Switch", "Mic Right"},
+
+	{"In Mixer Right", "Mic Right Switch", "Mic Right"},
+	{"In Mixer Right", "Mic Left Switch", "Mic Left"},
+
+	{"INPGA Left", NULL, "In Mixer Left"},
+	{"ADC Left", NULL, "INPGA Left"},
+
+	{"INPGA Right", NULL, "In Mixer Right"},
+	{"ADC Right", NULL, "INPGA Right"},
+
+	/* Output path */
+	{"Out Mixer Left", "DAC Left Switch", "DAC Left"},
+	{"Out Mixer Right", "DAC Right Switch", "DAC Right"},
+
+	{"Mono Mixer", "Outmix Right Switch", "Out Mixer Right"},
+	{"Mono Mixer", "Outmix Left Switch", "Out Mixer Left"},
+
+	{"OUTPGA Left Enable", NULL, "Out Mixer Left"},
+	{"OUTPGA Right Enable", NULL, "Out Mixer Right"},
+
+	{"Out1 Left", NULL, "OUTPGA Left Enable"},
+	{"OUT1L", NULL, "Out1 Left"},
+
+	{"Out1 Right", NULL, "OUTPGA Right Enable"},
+	{"OUT1R", NULL, "Out1 Right"},
+
+	{"Headphone Left", NULL, "OUTPGA Left Enable"},
+	{"HPL", NULL, "Headphone Left"},
+
+	{"Headphone Right", NULL, "OUTPGA Right Enable"},
+	{"HPR", NULL, "Headphone Right"},
+
+	{"Out2 Mono", NULL, "Mono Mixer"},
+	{"OUT2", NULL, "Out2 Mono"},
 };
 
 /* Codec private data */
 struct da7210_priv {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 };
 
 /*
@@ -188,72 +582,15 @@ static const u8 da7210_reg[] = {
 	0x00,						/* R88       */
 };
 
-/*
- * Read da7210 register cache
- */
-static inline u32 da7210_read_reg_cache(struct snd_soc_codec *codec, u32 reg)
-{
-	u8 *cache = codec->reg_cache;
-	BUG_ON(reg >= ARRAY_SIZE(da7210_reg));
-	return cache[reg];
-}
-
-/*
- * Write to the da7210 register space
- */
-static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)
+static int da7210_volatile_register(struct snd_soc_codec *codec,
+				    unsigned int reg)
 {
-	u8 *cache = codec->reg_cache;
-	u8 data[2];
-
-	BUG_ON(codec->driver->volatile_register);
-
-	data[0] = reg & 0xff;
-	data[1] = value & 0xff;
-
-	if (reg >= codec->driver->reg_cache_size)
-		return -EIO;
-
-	if (2 != codec->hw_write(codec->control_data, data, 2))
-		return -EIO;
-
-	cache[reg] = value;
-	return 0;
-}
-
-/*
- * Read from the da7210 register space.
- */
-static inline u32 da7210_read(struct snd_soc_codec *codec, u32 reg)
-{
-	if (DA7210_STATUS == reg)
-		return i2c_smbus_read_byte_data(codec->control_data, reg);
-
-	return da7210_read_reg_cache(codec, reg);
-}
-
-static int da7210_startup(struct snd_pcm_substream *substream,
-			  struct snd_soc_dai *dai)
-{
-	int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-	struct snd_soc_codec *codec = dai->codec;
-
-	if (is_play) {
-		/* Enable Out */
-		snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10);
-		snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10);
-
-	} else {
-		/* Volume 7 */
-		snd_soc_update_bits(codec, DA7210_MIC_L, 0x7, 0x7);
-		snd_soc_update_bits(codec, DA7210_MIC_R, 0x7, 0x7);
-
-		/* Enable Mic */
-		snd_soc_update_bits(codec, DA7210_INMIX_L, 0x1F, 0x1);
-		snd_soc_update_bits(codec, DA7210_INMIX_R, 0x1F, 0x1);
+	switch (reg) {
+	case DA7210_STATUS:
+		return 1;
+	default:
+		return 0;
 	}
-
-	return 0;
 }
 
 /*
@@ -266,93 +603,75 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
 	u32 dai_cfg1;
-	u32 hpf_reg, hpf_mask, hpf_value;
 	u32 fs, bypass;
 
 	/* set DAI source to Left and Right ADC */
-	da7210_write(codec, DA7210_DAI_SRC_SEL,
+	snd_soc_write(codec, DA7210_DAI_SRC_SEL,
 		     DA7210_DAI_OUT_R_SRC | DA7210_DAI_OUT_L_SRC);
 
 	/* Enable DAI */
-	da7210_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN);
+	snd_soc_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN);
 
-	dai_cfg1 = 0xFC & da7210_read(codec, DA7210_DAI_CFG1);
+	dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1);
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
 		dai_cfg1 |= DA7210_DAI_WORD_S16_LE;
 		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		dai_cfg1 |= DA7210_DAI_WORD_S20_3LE;
+		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
 		dai_cfg1 |= DA7210_DAI_WORD_S24_LE;
 		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		dai_cfg1 |= DA7210_DAI_WORD_S32_LE;
+		break;
 	default:
 		return -EINVAL;
 	}
 
-	da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
-
-	hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ?
-		DA7210_DAC_HPF : DA7210_ADC_HPF;
+	snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1);
 
 	switch (params_rate(params)) {
 	case 8000:
 		fs		= DA7210_PLL_FS_8000;
-		hpf_mask	= DA7210_VOICE_F0_MASK	| DA7210_VOICE_EN;
-		hpf_value	= DA7210_VOICE_F0_25	| DA7210_VOICE_EN;
 		bypass		= DA7210_PLL_BYP;
 		break;
 	case 11025:
 		fs		= DA7210_PLL_FS_11025;
-		hpf_mask	= DA7210_VOICE_F0_MASK	| DA7210_VOICE_EN;
-		hpf_value	= DA7210_VOICE_F0_25	| DA7210_VOICE_EN;
 		bypass		= 0;
 		break;
 	case 12000:
 		fs		= DA7210_PLL_FS_12000;
-		hpf_mask	= DA7210_VOICE_F0_MASK	| DA7210_VOICE_EN;
-		hpf_value	= DA7210_VOICE_F0_25	| DA7210_VOICE_EN;
 		bypass		= DA7210_PLL_BYP;
 		break;
 	case 16000:
 		fs		= DA7210_PLL_FS_16000;
-		hpf_mask	= DA7210_VOICE_F0_MASK	| DA7210_VOICE_EN;
-		hpf_value	= DA7210_VOICE_F0_25	| DA7210_VOICE_EN;
 		bypass		= DA7210_PLL_BYP;
 		break;
 	case 22050:
 		fs		= DA7210_PLL_FS_22050;
-		hpf_mask	= DA7210_VOICE_EN;
-		hpf_value	= 0;
 		bypass		= 0;
 		break;
 	case 32000:
 		fs		= DA7210_PLL_FS_32000;
-		hpf_mask	= DA7210_VOICE_EN;
-		hpf_value	= 0;
 		bypass		= DA7210_PLL_BYP;
 		break;
 	case 44100:
 		fs		= DA7210_PLL_FS_44100;
-		hpf_mask	= DA7210_VOICE_EN;
-		hpf_value	= 0;
 		bypass		= 0;
 		break;
 	case 48000:
 		fs		= DA7210_PLL_FS_48000;
-		hpf_mask	= DA7210_VOICE_EN;
-		hpf_value	= 0;
 		bypass		= DA7210_PLL_BYP;
 		break;
 	case 88200:
 		fs		= DA7210_PLL_FS_88200;
-		hpf_mask	= DA7210_VOICE_EN;
-		hpf_value	= 0;
 		bypass		= 0;
 		break;
 	case 96000:
 		fs		= DA7210_PLL_FS_96000;
-		hpf_mask	= DA7210_VOICE_EN;
-		hpf_value	= 0;
 		bypass		= DA7210_PLL_BYP;
 		break;
 	default:
@@ -362,7 +681,6 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
 	/* Disable active mode */
 	snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0);
 
-	snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value);
 	snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs);
 	snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass);
 
@@ -382,13 +700,16 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
 	u32 dai_cfg1;
 	u32 dai_cfg3;
 
-	dai_cfg1 = 0x7f & da7210_read(codec, DA7210_DAI_CFG1);
-	dai_cfg3 = 0xfc & da7210_read(codec, DA7210_DAI_CFG3);
+	dai_cfg1 = 0x7f & snd_soc_read(codec, DA7210_DAI_CFG1);
+	dai_cfg3 = 0xfc & snd_soc_read(codec, DA7210_DAI_CFG3);
 
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBM_CFM:
 		dai_cfg1 |= DA7210_DAI_MODE_MASTER;
 		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		dai_cfg1 |= DA7210_DAI_MODE_SLAVE;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -401,6 +722,12 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
 	case SND_SOC_DAIFMT_I2S:
 		dai_cfg3 |= DA7210_DAI_FORMAT_I2SMODE;
 		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		dai_cfg3 |= DA7210_DAI_FORMAT_LEFT_J;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		dai_cfg3 |= DA7210_DAI_FORMAT_RIGHT_J;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -411,19 +738,32 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
 	 */
 	dai_cfg1 |= DA7210_DAI_FLEN_64BIT;
 
-	da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
-	da7210_write(codec, DA7210_DAI_CFG3, dai_cfg3);
+	snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1);
+	snd_soc_write(codec, DA7210_DAI_CFG3, dai_cfg3);
+
+	return 0;
+}
+
+static int da7210_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u8 mute_reg = snd_soc_read(codec, DA7210_DAC_HPF) & 0xFB;
 
+	if (mute)
+		snd_soc_write(codec, DA7210_DAC_HPF, mute_reg | 0x4);
+	else
+		snd_soc_write(codec, DA7210_DAC_HPF, mute_reg);
 	return 0;
 }
 
-#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 /* DAI operations */
 static struct snd_soc_dai_ops da7210_dai_ops = {
-	.startup	= da7210_startup,
 	.hw_params	= da7210_hw_params,
 	.set_fmt	= da7210_set_dai_fmt,
+	.digital_mute	= da7210_mute,
 };
 
 static struct snd_soc_dai_driver da7210_dai = {
@@ -451,11 +791,15 @@ static struct snd_soc_dai_driver da7210_dai = {
 static int da7210_probe(struct snd_soc_codec *codec)
 {
 	struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
+	int ret;
 
 	dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
 
-	codec->control_data	= da7210->control_data;
-	codec->hw_write		= (hw_write_t)i2c_master_send;
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, da7210->control_type);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
 
 	/* FIXME
 	 *
@@ -472,8 +816,8 @@ static int da7210_probe(struct snd_soc_codec *codec)
 	/*
 	 * make sure that DA7210 use bypass mode before start up
 	 */
-	da7210_write(codec, DA7210_STARTUP1, 0);
-	da7210_write(codec, DA7210_PLL_DIV3,
+	snd_soc_write(codec, DA7210_STARTUP1, 0);
+	snd_soc_write(codec, DA7210_PLL_DIV3,
 		     DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
 
 	/*
@@ -481,36 +825,70 @@ static int da7210_probe(struct snd_soc_codec *codec)
 	 */
 
 	/* Enable Left & Right MIC PGA and Mic Bias */
-	da7210_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
-	da7210_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);
+	snd_soc_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
+	snd_soc_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);
 
 	/* Enable Left and Right input PGA */
-	da7210_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
-	da7210_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);
+	snd_soc_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
+	snd_soc_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);
 
 	/* Enable Left and Right ADC */
-	da7210_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);
+	snd_soc_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);
 
 	/*
 	 * DAC settings
 	 */
 
 	/* Enable Left and Right DAC */
-	da7210_write(codec, DA7210_DAC_SEL,
+	snd_soc_write(codec, DA7210_DAC_SEL,
 		     DA7210_DAC_L_SRC_DAI_L | DA7210_DAC_L_EN |
 		     DA7210_DAC_R_SRC_DAI_R | DA7210_DAC_R_EN);
 
 	/* Enable Left and Right out PGA */
-	da7210_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
-	da7210_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);
+	snd_soc_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
+	snd_soc_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);
 
 	/* Enable Left and Right HeadPhone PGA */
-	da7210_write(codec, DA7210_HP_CFG,
+	snd_soc_write(codec, DA7210_HP_CFG,
 		     DA7210_HP_2CAP_MODE | DA7210_HP_SENSE_EN |
 		     DA7210_HP_L_EN | DA7210_HP_MODE | DA7210_HP_R_EN);
 
+	/* Enable ramp mode for DAC gain update */
+	snd_soc_write(codec, DA7210_SOFTMUTE, DA7210_RAMP_EN);
+
+	/*
+	 * For DA7210 codec, there are two ways to enable/disable analog IOs
+	 * and ADC/DAC,
+	 * (1) Using "Enable Bit" of register associated with that IO
+	 * (or ADC/DAC)
+	 *	e.g. Mic Left can be enabled using bit 7 of MIC_L(0x7) reg
+	 *
+	 * (2) Using "Standby Bit" of STARTUP2 or STARTUP3 register
+	 *	e.g. Mic left can be put to STANDBY using bit 0 of STARTUP3(0x5)
+	 *
+	 * Out of these two methods, the one using STANDBY bits is preferred
+	 * way to enable/disable individual blocks. This is because STANDBY
+	 * registers are part of system controller which allows system power
+	 * up/down in a controlled, pop-free manner. Also, as per application
+	 * note of DA7210, STANDBY register bits are only effective if a
+	 * particular IO (or ADC/DAC) is already enabled using enable/disable
+	 * register bits. Keeping these things in mind, current DAPM
+	 * implementation manipulates only STANDBY bits.
+	 *
+	 * Overall implementation can be outlined as below,
+	 *
+	 * - "Enable bit" of an IO or ADC/DAC is used to enable it in probe()
+	 * - "STANDBY bit" is controlled by DAPM
+	 */
+
+	/* Enable Line out amplifiers */
+	snd_soc_write(codec, DA7210_OUT1_L, DA7210_OUT1_L_EN);
+	snd_soc_write(codec, DA7210_OUT1_R, DA7210_OUT1_R_EN);
+	snd_soc_write(codec, DA7210_OUT2, DA7210_OUT2_EN |
+		     DA7210_OUT2_OUTMIX_L | DA7210_OUT2_OUTMIX_R);
+
 	/* Diable PLL and bypass it */
-	da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
+	snd_soc_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
 
 	/*
 	 * If 48kHz sound came, it use bypass mode,
@@ -521,25 +899,22 @@ static int da7210_probe(struct snd_soc_codec *codec)
 	 * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit.
 	 *   see da7210_hw_params
 	 */
-	da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
-	da7210_write(codec, DA7210_PLL_DIV2, 0x99);
-	da7210_write(codec, DA7210_PLL_DIV3, 0x0A |
+	snd_soc_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
+	snd_soc_write(codec, DA7210_PLL_DIV2, 0x99);
+	snd_soc_write(codec, DA7210_PLL_DIV3, 0x0A |
 		     DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
 	snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
 
 	/* As suggested by Dialog */
-	da7210_write(codec, DA7210_A_HID_UNLOCK,	0x8B); /* unlock */
-	da7210_write(codec, DA7210_A_TEST_UNLOCK,	0xB4);
-	da7210_write(codec, DA7210_A_PLL1,		0x01);
-	da7210_write(codec, DA7210_A_CP_MODE,		0x7C);
-	da7210_write(codec, DA7210_A_HID_UNLOCK,	0x00); /* re-lock */
-	da7210_write(codec, DA7210_A_TEST_UNLOCK,	0x00);
+	snd_soc_write(codec, DA7210_A_HID_UNLOCK,	0x8B); /* unlock */
+	snd_soc_write(codec, DA7210_A_TEST_UNLOCK,	0xB4);
+	snd_soc_write(codec, DA7210_A_PLL1,		0x01);
+	snd_soc_write(codec, DA7210_A_CP_MODE,		0x7C);
+	snd_soc_write(codec, DA7210_A_HID_UNLOCK,	0x00); /* re-lock */
+	snd_soc_write(codec, DA7210_A_TEST_UNLOCK,	0x00);
 
 	/* Activate all enabled subsystem */
-	da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
-
-	snd_soc_add_controls(codec, da7210_snd_controls,
-			     ARRAY_SIZE(da7210_snd_controls));
+	snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
 
 	dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
 
@@ -548,11 +923,18 @@ static int da7210_probe(struct snd_soc_codec *codec)
 
 static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
 	.probe			= da7210_probe,
-	.read			= da7210_read,
-	.write			= da7210_write,
 	.reg_cache_size		= ARRAY_SIZE(da7210_reg),
 	.reg_word_size		= sizeof(u8),
 	.reg_cache_default	= da7210_reg,
+	.volatile_register	= da7210_volatile_register,
+
+	.controls		= da7210_snd_controls,
+	.num_controls		= ARRAY_SIZE(da7210_snd_controls),
+
+	.dapm_widgets		= da7210_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(da7210_dapm_widgets),
+	.dapm_routes		= da7210_audio_map,
+	.num_dapm_routes	= ARRAY_SIZE(da7210_audio_map),
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -567,7 +949,6 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, da7210);
-	da7210->control_data = i2c;
 	da7210->control_type = SND_SOC_I2C;
 
 	ret =  snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 2c2a681da0d7..c387dafc6ab6 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2007 Wolfson Microelectronics PLC.
  * Author: Graeme Gregory
- *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *         graeme.gregory@wolfsonmicro.com
  * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
  *
  *  This program is free software; you can redistribute  it and/or modify it
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index ac65a2d36408..ebbf63c79c34 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -40,7 +40,6 @@ struct max98088_cdata {
 
 struct max98088_priv {
        enum max98088_type devtype;
-       void *control_data;
        struct max98088_pdata *pdata;
        unsigned int sysclk;
        struct max98088_cdata dai[2];
@@ -1697,13 +1696,19 @@ static struct snd_soc_dai_driver max98088_dai[] = {
 }
 };
 
-static int max98088_get_channel(const char *name)
+static const char *eq_mode_name[] = {"EQ1 Mode", "EQ2 Mode"};
+
+static int max98088_get_channel(struct snd_soc_codec *codec, const char *name)
 {
-       if (strcmp(name, "EQ1 Mode") == 0)
-               return 0;
-       if (strcmp(name, "EQ2 Mode") == 0)
-               return 1;
-       return -EINVAL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(eq_mode_name); i++)
+		if (strcmp(name, eq_mode_name[i]) == 0)
+			return i;
+
+	/* Shouldn't happen */
+	dev_err(codec->dev, "Bad EQ channel name '%s'\n", name);
+	return -EINVAL;
 }
 
 static void max98088_setup_eq1(struct snd_soc_codec *codec)
@@ -1807,10 +1812,13 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
        struct max98088_pdata *pdata = max98088->pdata;
-       int channel = max98088_get_channel(kcontrol->id.name);
+       int channel = max98088_get_channel(codec, kcontrol->id.name);
        struct max98088_cdata *cdata;
        int sel = ucontrol->value.integer.value[0];
 
+       if (channel < 0)
+	       return channel;
+
        cdata = &max98088->dai[channel];
 
        if (sel >= pdata->eq_cfgcnt)
@@ -1835,9 +1843,12 @@ static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
-       int channel = max98088_get_channel(kcontrol->id.name);
+       int channel = max98088_get_channel(codec, kcontrol->id.name);
        struct max98088_cdata *cdata;
 
+       if (channel < 0)
+	       return channel;
+
        cdata = &max98088->dai[channel];
        ucontrol->value.enumerated.item[0] = cdata->eq_sel;
        return 0;
@@ -1852,17 +1863,17 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
        int i, j;
        const char **t;
        int ret;
-
        struct snd_kcontrol_new controls[] = {
-               SOC_ENUM_EXT("EQ1 Mode",
+               SOC_ENUM_EXT((char *)eq_mode_name[0],
                        max98088->eq_enum,
                        max98088_get_eq_enum,
                        max98088_put_eq_enum),
-               SOC_ENUM_EXT("EQ2 Mode",
+               SOC_ENUM_EXT((char *)eq_mode_name[1],
                        max98088->eq_enum,
                        max98088_get_eq_enum,
                        max98088_put_eq_enum),
        };
+       BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(eq_mode_name));
 
        cfg = pdata->eq_cfg;
        cfgcnt = pdata->eq_cfgcnt;
@@ -2066,7 +2077,6 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
        max98088->devtype = id->driver_data;
 
        i2c_set_clientdata(i2c, max98088);
-       max98088->control_data = i2c;
        max98088->pdata = i2c->dev.platform_data;
 
        ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 668434d44303..26d7b089fb9c 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -40,7 +40,6 @@ struct max98095_cdata {
 
 struct max98095_priv {
 	enum max98095_type devtype;
-	void *control_data;
 	struct max98095_pdata *pdata;
 	unsigned int sysclk;
 	struct max98095_cdata dai[3];
@@ -618,14 +617,13 @@ static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
 static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg,
 			     unsigned int value)
 {
-	u8 data[2];
+	int ret;
 
-	data[0] = reg;
-	data[1] = value;
-	if (codec->hw_write(codec->control_data, data, 2) == 2)
-		return 0;
-	else
-		return -EIO;
+	codec->cache_bypass = 1;
+	ret = snd_soc_write(codec, reg, value);
+	codec->cache_bypass = 0;
+
+	return ret ? -EIO : 0;
 }
 
 /*
@@ -1992,12 +1990,19 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
 		dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
 }
 
-static int max98095_get_bq_channel(const char *name)
+static const char *bq_mode_name[] = {"Biquad1 Mode", "Biquad2 Mode"};
+
+static int max98095_get_bq_channel(struct snd_soc_codec *codec,
+				   const char *name)
 {
-	if (strcmp(name, "Biquad1 Mode") == 0)
-		return 0;
-	if (strcmp(name, "Biquad2 Mode") == 0)
-		return 1;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bq_mode_name); i++)
+		if (strcmp(name, bq_mode_name[i]) == 0)
+			return i;
+
+	/* Shouldn't happen */
+	dev_err(codec->dev, "Bad biquad channel name '%s'\n", name);
 	return -EINVAL;
 }
 
@@ -2007,14 +2012,15 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	struct max98095_pdata *pdata = max98095->pdata;
-	int channel = max98095_get_bq_channel(kcontrol->id.name);
+	int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
 	struct max98095_cdata *cdata;
 	int sel = ucontrol->value.integer.value[0];
 	struct max98095_biquad_cfg *coef_set;
 	int fs, best, best_val, i;
 	int regmask, regsave;
 
-	BUG_ON(channel > 1);
+	if (channel < 0)
+		return channel;
 
 	if (!pdata || !max98095->bq_textcnt)
 		return 0;
@@ -2066,9 +2072,12 @@ static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
-	int channel = max98095_get_bq_channel(kcontrol->id.name);
+	int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
 	struct max98095_cdata *cdata;
 
+	if (channel < 0)
+		return channel;
+
 	cdata = &max98095->dai[channel];
 	ucontrol->value.enumerated.item[0] = cdata->bq_sel;
 
@@ -2086,15 +2095,16 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
 	int ret;
 
 	struct snd_kcontrol_new controls[] = {
-		SOC_ENUM_EXT("Biquad1 Mode",
+		SOC_ENUM_EXT((char *)bq_mode_name[0],
 			max98095->bq_enum,
 			max98095_get_bq_enum,
 			max98095_put_bq_enum),
-		SOC_ENUM_EXT("Biquad2 Mode",
+		SOC_ENUM_EXT((char *)bq_mode_name[1],
 			max98095->bq_enum,
 			max98095_get_bq_enum,
 			max98095_put_bq_enum),
 	};
+	BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(bq_mode_name));
 
 	cfg = pdata->bq_cfg;
 	cfgcnt = pdata->bq_cfgcnt;
@@ -2337,7 +2347,6 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
 
 	max98095->devtype = id->driver_data;
 	i2c_set_clientdata(i2c, max98095);
-	max98095->control_data = i2c;
 	max98095->pdata = i2c->dev.platform_data;
 
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095,
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
new file mode 100644
index 000000000000..27a078cbb6eb
--- /dev/null
+++ b/sound/soc/codecs/rt5631.c
@@ -0,0 +1,1773 @@
+/*
+ * rt5631.c  --  RT5631 ALSA Soc Audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ *
+ * Author: flove <flove@realtek.com>
+ *
+ * Based on WM8753.c
+ *
+ * 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/platform_device.h>
+#include <linux/spi/spi.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 "rt5631.h"
+
+struct rt5631_priv {
+	int codec_version;
+	int master;
+	int sysclk;
+	int rx_rate;
+	int bclk_rate;
+	int dmic_used_flag;
+};
+
+static const u16 rt5631_reg[RT5631_VENDOR_ID2 + 1] = {
+	[RT5631_SPK_OUT_VOL] = 0x8888,
+	[RT5631_HP_OUT_VOL] = 0x8080,
+	[RT5631_MONO_AXO_1_2_VOL] = 0xa080,
+	[RT5631_AUX_IN_VOL] = 0x0808,
+	[RT5631_ADC_REC_MIXER] = 0xf0f0,
+	[RT5631_VDAC_DIG_VOL] = 0x0010,
+	[RT5631_OUTMIXER_L_CTRL] = 0xffc0,
+	[RT5631_OUTMIXER_R_CTRL] = 0xffc0,
+	[RT5631_AXO1MIXER_CTRL] = 0x88c0,
+	[RT5631_AXO2MIXER_CTRL] = 0x88c0,
+	[RT5631_DIG_MIC_CTRL] = 0x3000,
+	[RT5631_MONO_INPUT_VOL] = 0x8808,
+	[RT5631_SPK_MIXER_CTRL] = 0xf8f8,
+	[RT5631_SPK_MONO_OUT_CTRL] = 0xfc00,
+	[RT5631_SPK_MONO_HP_OUT_CTRL] = 0x4440,
+	[RT5631_SDP_CTRL] = 0x8000,
+	[RT5631_MONO_SDP_CTRL] = 0x8000,
+	[RT5631_STEREO_AD_DA_CLK_CTRL] = 0x2010,
+	[RT5631_GEN_PUR_CTRL_REG] = 0x0e00,
+	[RT5631_INT_ST_IRQ_CTRL_2] = 0x071a,
+	[RT5631_MISC_CTRL] = 0x2040,
+	[RT5631_DEPOP_FUN_CTRL_2] = 0x8000,
+	[RT5631_SOFT_VOL_CTRL] = 0x07e0,
+	[RT5631_ALC_CTRL_1] = 0x0206,
+	[RT5631_ALC_CTRL_3] = 0x2000,
+	[RT5631_PSEUDO_SPATL_CTRL] = 0x0553,
+};
+
+/**
+ * rt5631_write_index - write index register of 2nd layer
+ */
+static void rt5631_write_index(struct snd_soc_codec *codec,
+		unsigned int reg, unsigned int value)
+{
+	snd_soc_write(codec, RT5631_INDEX_ADD, reg);
+	snd_soc_write(codec, RT5631_INDEX_DATA, value);
+}
+
+/**
+ * rt5631_read_index - read index register of 2nd layer
+ */
+static unsigned int rt5631_read_index(struct snd_soc_codec *codec,
+				unsigned int reg)
+{
+	unsigned int value;
+
+	snd_soc_write(codec, RT5631_INDEX_ADD, reg);
+	value = snd_soc_read(codec, RT5631_INDEX_DATA);
+
+	return value;
+}
+
+static int rt5631_reset(struct snd_soc_codec *codec)
+{
+	return snd_soc_write(codec, RT5631_RESET, 0);
+}
+
+static int rt5631_volatile_register(struct snd_soc_codec *codec,
+				    unsigned int reg)
+{
+	switch (reg) {
+	case RT5631_RESET:
+	case RT5631_INT_ST_IRQ_CTRL_2:
+	case RT5631_INDEX_ADD:
+	case RT5631_INDEX_DATA:
+	case RT5631_EQ_CTRL:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int rt5631_readable_register(struct snd_soc_codec *codec,
+				    unsigned int reg)
+{
+	switch (reg) {
+	case RT5631_RESET:
+	case RT5631_SPK_OUT_VOL:
+	case RT5631_HP_OUT_VOL:
+	case RT5631_MONO_AXO_1_2_VOL:
+	case RT5631_AUX_IN_VOL:
+	case RT5631_STEREO_DAC_VOL_1:
+	case RT5631_MIC_CTRL_1:
+	case RT5631_STEREO_DAC_VOL_2:
+	case RT5631_ADC_CTRL_1:
+	case RT5631_ADC_REC_MIXER:
+	case RT5631_ADC_CTRL_2:
+	case RT5631_VDAC_DIG_VOL:
+	case RT5631_OUTMIXER_L_CTRL:
+	case RT5631_OUTMIXER_R_CTRL:
+	case RT5631_AXO1MIXER_CTRL:
+	case RT5631_AXO2MIXER_CTRL:
+	case RT5631_MIC_CTRL_2:
+	case RT5631_DIG_MIC_CTRL:
+	case RT5631_MONO_INPUT_VOL:
+	case RT5631_SPK_MIXER_CTRL:
+	case RT5631_SPK_MONO_OUT_CTRL:
+	case RT5631_SPK_MONO_HP_OUT_CTRL:
+	case RT5631_SDP_CTRL:
+	case RT5631_MONO_SDP_CTRL:
+	case RT5631_STEREO_AD_DA_CLK_CTRL:
+	case RT5631_PWR_MANAG_ADD1:
+	case RT5631_PWR_MANAG_ADD2:
+	case RT5631_PWR_MANAG_ADD3:
+	case RT5631_PWR_MANAG_ADD4:
+	case RT5631_GEN_PUR_CTRL_REG:
+	case RT5631_GLOBAL_CLK_CTRL:
+	case RT5631_PLL_CTRL:
+	case RT5631_INT_ST_IRQ_CTRL_1:
+	case RT5631_INT_ST_IRQ_CTRL_2:
+	case RT5631_GPIO_CTRL:
+	case RT5631_MISC_CTRL:
+	case RT5631_DEPOP_FUN_CTRL_1:
+	case RT5631_DEPOP_FUN_CTRL_2:
+	case RT5631_JACK_DET_CTRL:
+	case RT5631_SOFT_VOL_CTRL:
+	case RT5631_ALC_CTRL_1:
+	case RT5631_ALC_CTRL_2:
+	case RT5631_ALC_CTRL_3:
+	case RT5631_PSEUDO_SPATL_CTRL:
+	case RT5631_INDEX_ADD:
+	case RT5631_INDEX_DATA:
+	case RT5631_EQ_CTRL:
+	case RT5631_VENDOR_ID:
+	case RT5631_VENDOR_ID1:
+	case RT5631_VENDOR_ID2:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */
+static unsigned int mic_bst_tlv[] = {
+	TLV_DB_RANGE_HEAD(6),
+	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+	1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+	2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+	3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+	6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+	7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+	8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = rt5631->dmic_used_flag;
+
+	return 0;
+}
+
+static int rt5631_dmic_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+	rt5631->dmic_used_flag = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+/* MIC Input Type */
+static const char *rt5631_input_mode[] = {
+	"Single ended", "Differential"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1,
+	RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1,
+	RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+/* MONO Input Type */
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL,
+	RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+/* SPK Ratio Gain Control */
+static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x",
+			"1.56x", "1.68x", "1.99x", "2.34x"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
+	RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio);
+
+static const struct snd_kcontrol_new rt5631_snd_controls[] = {
+	/* MIC */
+	SOC_ENUM("MIC1 Mode Control",  rt5631_mic1_mode_enum),
+	SOC_SINGLE_TLV("MIC1 Boost", RT5631_MIC_CTRL_2,
+		RT5631_MIC1_BOOST_SHIFT, 8, 0, mic_bst_tlv),
+	SOC_ENUM("MIC2 Mode Control", rt5631_mic2_mode_enum),
+	SOC_SINGLE_TLV("MIC2 Boost", RT5631_MIC_CTRL_2,
+		RT5631_MIC2_BOOST_SHIFT, 8, 0, mic_bst_tlv),
+	/* MONO IN */
+	SOC_ENUM("MONOIN Mode Control", rt5631_monoin_mode_enum),
+	SOC_DOUBLE_TLV("MONOIN_RX Capture Volume", RT5631_MONO_INPUT_VOL,
+			RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+			RT5631_VOL_MASK, 1, in_vol_tlv),
+	/* AXI */
+	SOC_DOUBLE_TLV("AXI Capture Volume", RT5631_AUX_IN_VOL,
+			RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+			RT5631_VOL_MASK, 1, in_vol_tlv),
+	/* DAC */
+	SOC_DOUBLE_TLV("PCM Playback Volume", RT5631_STEREO_DAC_VOL_2,
+			RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+			RT5631_DAC_VOL_MASK, 1, dac_vol_tlv),
+	SOC_DOUBLE("PCM Playback Switch", RT5631_STEREO_DAC_VOL_1,
+			RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+	/* AXO */
+	SOC_SINGLE("AXO1 Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+				RT5631_L_MUTE_SHIFT, 1, 1),
+	SOC_SINGLE("AXO2 Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+				RT5631_R_VOL_SHIFT, 1, 1),
+	/* OUTVOL */
+	SOC_DOUBLE("OUTVOL Channel Switch", RT5631_SPK_OUT_VOL,
+		RT5631_L_EN_SHIFT, RT5631_R_EN_SHIFT, 1, 0),
+
+	/* SPK */
+	SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL,
+		RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+	SOC_DOUBLE_TLV("Speaker Playback Volume", RT5631_SPK_OUT_VOL,
+		RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, 39, 1, out_vol_tlv),
+	/* MONO OUT */
+	SOC_SINGLE("MONO Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+				RT5631_MUTE_MONO_SHIFT, 1, 1),
+	/* HP */
+	SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL,
+		RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+	SOC_DOUBLE_TLV("HP Playback Volume", RT5631_HP_OUT_VOL,
+		RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+		RT5631_VOL_MASK, 1, out_vol_tlv),
+	/* DMIC */
+	SOC_SINGLE_EXT("DMIC Switch", 0, 0, 1, 0,
+		rt5631_dmic_get, rt5631_dmic_put),
+	SOC_DOUBLE("DMIC Capture Switch", RT5631_DIG_MIC_CTRL,
+		RT5631_DMIC_L_CH_MUTE_SHIFT,
+		RT5631_DMIC_R_CH_MUTE_SHIFT, 1, 1),
+
+	/* SPK Ratio Gain Control */
+	SOC_ENUM("SPK Ratio Control", rt5631_spk_ratio_enum),
+};
+
+static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg;
+
+	reg = snd_soc_read(source->codec, RT5631_GLOBAL_CLK_CTRL);
+	return reg & RT5631_SYSCLK_SOUR_SEL_PLL;
+}
+
+static int check_dmic_used(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(source->codec);
+	return rt5631->dmic_used_flag;
+}
+
+static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg;
+
+	reg = snd_soc_read(source->codec, RT5631_OUTMIXER_L_CTRL);
+	return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L);
+}
+
+static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg;
+
+	reg = snd_soc_read(source->codec, RT5631_OUTMIXER_R_CTRL);
+	return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R);
+}
+
+static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg;
+
+	reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
+	return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L);
+}
+
+static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg;
+
+	reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
+	return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R);
+}
+
+static int check_adcl_select(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg;
+
+	reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
+	return !(reg & RT5631_M_MIC1_TO_RECMIXER_L);
+}
+
+static int check_adcr_select(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg;
+
+	reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
+	return !(reg & RT5631_M_MIC2_TO_RECMIXER_R);
+}
+
+/**
+ * onebit_depop_power_stage - auto depop in power stage.
+ * @enable: power on/off
+ *
+ * When power on/off headphone, the depop sequence is done by hardware.
+ */
+static void onebit_depop_power_stage(struct snd_soc_codec *codec, int enable)
+{
+	unsigned int soft_vol, hp_zc;
+
+	/* enable one-bit depop function */
+	snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+				RT5631_EN_ONE_BIT_DEPOP, 0);
+
+	/* keep soft volume and zero crossing setting */
+	soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+	snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+	hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+	if (enable) {
+		/* config one-bit depop parameter */
+		rt5631_write_index(codec, RT5631_TEST_MODE_CTRL, 0x84c0);
+		rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x309f);
+		rt5631_write_index(codec, RT5631_CP_INTL_REG2, 0x6530);
+		/* power on capless block */
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2,
+				RT5631_EN_CAP_FREE_DEPOP);
+	} else {
+		/* power off capless block */
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2, 0);
+		msleep(100);
+	}
+
+	/* recover soft volume and zero crossing setting */
+	snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * onebit_depop_mute_stage - auto depop in mute stage.
+ * @enable: mute/unmute
+ *
+ * When mute/unmute headphone, the depop sequence is done by hardware.
+ */
+static void onebit_depop_mute_stage(struct snd_soc_codec *codec, int enable)
+{
+	unsigned int soft_vol, hp_zc;
+
+	/* enable one-bit depop function */
+	snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+				RT5631_EN_ONE_BIT_DEPOP, 0);
+
+	/* keep soft volume and zero crossing setting */
+	soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+	snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+	hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+	if (enable) {
+		schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+		/* config one-bit depop parameter */
+		rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x307f);
+		snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+				RT5631_L_MUTE | RT5631_R_MUTE, 0);
+		msleep(300);
+	} else {
+		snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+			RT5631_L_MUTE | RT5631_R_MUTE,
+			RT5631_L_MUTE | RT5631_R_MUTE);
+		msleep(100);
+	}
+
+	/* recover soft volume and zero crossing setting */
+	snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * onebit_depop_power_stage - step by step depop sequence in power stage.
+ * @enable: power on/off
+ *
+ * When power on/off headphone, the depop sequence is done in step by step.
+ */
+static void depop_seq_power_stage(struct snd_soc_codec *codec, int enable)
+{
+	unsigned int soft_vol, hp_zc;
+
+	/* depop control by register */
+	snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+		RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP);
+
+	/* keep soft volume and zero crossing setting */
+	soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+	snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+	hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+	if (enable) {
+		/* config depop sequence parameter */
+		rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303e);
+
+		/* power on headphone and charge pump */
+		snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+			RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+			RT5631_PWR_HP_R_AMP,
+			RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+			RT5631_PWR_HP_R_AMP);
+
+		/* power on soft generator and depop mode2 */
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+			RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP);
+		msleep(100);
+
+		/* stop depop mode */
+		snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+			RT5631_PWR_HP_DEPOP_DIS, RT5631_PWR_HP_DEPOP_DIS);
+	} else {
+		/* config depop sequence parameter */
+		rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303F);
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+			RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+			RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP);
+		msleep(75);
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+			RT5631_POW_ON_SOFT_GEN | RT5631_PD_HPAMP_L_ST_UP |
+			RT5631_PD_HPAMP_R_ST_UP);
+
+		/* start depop mode */
+		snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+				RT5631_PWR_HP_DEPOP_DIS, 0);
+
+		/* config depop sequence parameter */
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+			RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP |
+			RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP);
+		msleep(80);
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+			RT5631_POW_ON_SOFT_GEN);
+
+		/* power down headphone and charge pump */
+		snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+			RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+			RT5631_PWR_HP_R_AMP, 0);
+	}
+
+	/* recover soft volume and zero crossing setting */
+	snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * depop_seq_mute_stage - step by step depop sequence in mute stage.
+ * @enable: mute/unmute
+ *
+ * When mute/unmute headphone, the depop sequence is done in step by step.
+ */
+static void depop_seq_mute_stage(struct snd_soc_codec *codec, int enable)
+{
+	unsigned int soft_vol, hp_zc;
+
+	/* depop control by register */
+	snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+		RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP);
+
+	/* keep soft volume and zero crossing setting */
+	soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+	snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+	hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+	if (enable) {
+		schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+
+		/* config depop sequence parameter */
+		rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f);
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+			RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+			RT5631_EN_HP_R_M_UN_MUTE_DEPOP |
+			RT5631_EN_HP_L_M_UN_MUTE_DEPOP);
+
+		snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+				RT5631_L_MUTE | RT5631_R_MUTE, 0);
+		msleep(160);
+	} else {
+		/* config depop sequence parameter */
+		rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f);
+		snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+			RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+			RT5631_EN_HP_R_M_UN_MUTE_DEPOP |
+			RT5631_EN_HP_L_M_UN_MUTE_DEPOP);
+
+		snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+			RT5631_L_MUTE | RT5631_R_MUTE,
+			RT5631_L_MUTE | RT5631_R_MUTE);
+		msleep(150);
+	}
+
+	/* recover soft volume and zero crossing setting */
+	snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+static int hp_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMD:
+		if (rt5631->codec_version) {
+			onebit_depop_mute_stage(codec, 0);
+			onebit_depop_power_stage(codec, 0);
+		} else {
+			depop_seq_mute_stage(codec, 0);
+			depop_seq_power_stage(codec, 0);
+		}
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+		if (rt5631->codec_version) {
+			onebit_depop_power_stage(codec, 1);
+			onebit_depop_mute_stage(codec, 1);
+		} else {
+			depop_seq_power_stage(codec, 1);
+			depop_seq_mute_stage(codec, 1);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int set_dmic_params(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+	switch (rt5631->rx_rate) {
+	case 44100:
+	case 48000:
+		snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+			RT5631_DMIC_CLK_CTRL_MASK,
+			RT5631_DMIC_CLK_CTRL_TO_32FS);
+		break;
+
+	case 32000:
+	case 22050:
+		snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+			RT5631_DMIC_CLK_CTRL_MASK,
+			RT5631_DMIC_CLK_CTRL_TO_64FS);
+		break;
+
+	case 16000:
+	case 11025:
+	case 8000:
+		snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+			RT5631_DMIC_CLK_CTRL_MASK,
+			RT5631_DMIC_CLK_CTRL_TO_128FS);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new rt5631_recmixl_mixer_controls[] = {
+	SOC_DAPM_SINGLE("OUTMIXL Capture Switch", RT5631_ADC_REC_MIXER,
+			RT5631_M_OUTMIXL_RECMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC1_BST1 Capture Switch", RT5631_ADC_REC_MIXER,
+			RT5631_M_MIC1_RECMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("AXILVOL Capture Switch", RT5631_ADC_REC_MIXER,
+			RT5631_M_AXIL_RECMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER,
+			RT5631_M_MONO_IN_RECMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_recmixr_mixer_controls[] = {
+	SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER,
+			RT5631_M_MONO_IN_RECMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("AXIRVOL Capture Switch", RT5631_ADC_REC_MIXER,
+			RT5631_M_AXIR_RECMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC2_BST2 Capture Switch", RT5631_ADC_REC_MIXER,
+			RT5631_M_MIC2_RECMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("OUTMIXR Capture Switch", RT5631_ADC_REC_MIXER,
+			RT5631_M_OUTMIXR_RECMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spkmixl_mixer_controls[] = {
+	SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_SPK_MIXER_CTRL,
+			RT5631_M_RECMIXL_SPKMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC1_P Playback Switch", RT5631_SPK_MIXER_CTRL,
+			RT5631_M_MIC1P_SPKMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_SPK_MIXER_CTRL,
+			RT5631_M_DACL_SPKMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("OUTMIXL Playback Switch", RT5631_SPK_MIXER_CTRL,
+			RT5631_M_OUTMIXL_SPKMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spkmixr_mixer_controls[] = {
+	SOC_DAPM_SINGLE("OUTMIXR Playback Switch", RT5631_SPK_MIXER_CTRL,
+			RT5631_M_OUTMIXR_SPKMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_SPK_MIXER_CTRL,
+			RT5631_M_DACR_SPKMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC2_P Playback Switch", RT5631_SPK_MIXER_CTRL,
+			RT5631_M_MIC2P_SPKMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_SPK_MIXER_CTRL,
+			RT5631_M_RECMIXR_SPKMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_outmixl_mixer_controls[] = {
+	SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_RECMIXL_OUTMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_RECMIXR_OUTMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_DACL_OUTMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_MIC1_OUTMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_MIC2_OUTMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MONOIN_RXP Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_MONO_INP_OUTMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_AXIL_OUTMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_AXIR_OUTMIXL_BIT, 1, 1),
+	SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_L_CTRL,
+				RT5631_M_VDAC_OUTMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_outmixr_mixer_controls[] = {
+	SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_VDAC_OUTMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_AXIR_OUTMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_AXIL_OUTMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MONOIN_RXN Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_MONO_INN_OUTMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_MIC2_OUTMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_MIC1_OUTMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_DACR_OUTMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_RECMIXR_OUTMIXR_BIT, 1, 1),
+	SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+				RT5631_M_RECMIXL_OUTMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_AXO1MIX_mixer_controls[] = {
+	SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO1MIXER_CTRL,
+				RT5631_M_MIC1_AXO1MIX_BIT , 1, 1),
+	SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO1MIXER_CTRL,
+				RT5631_M_MIC2_AXO1MIX_BIT, 1, 1),
+	SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO1MIXER_CTRL,
+				RT5631_M_OUTMIXL_AXO1MIX_BIT , 1 , 1),
+	SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO1MIXER_CTRL,
+				RT5631_M_OUTMIXR_AXO1MIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_AXO2MIX_mixer_controls[] = {
+	SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO2MIXER_CTRL,
+				RT5631_M_MIC1_AXO2MIX_BIT, 1, 1),
+	SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO2MIXER_CTRL,
+				RT5631_M_MIC2_AXO2MIX_BIT, 1, 1),
+	SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO2MIXER_CTRL,
+				RT5631_M_OUTMIXL_AXO2MIX_BIT, 1, 1),
+	SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO2MIXER_CTRL,
+				RT5631_M_OUTMIXR_AXO2MIX_BIT, 1 , 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spolmix_mixer_controls[] = {
+	SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+				RT5631_M_SPKVOLL_SPOLMIX_BIT, 1, 1),
+	SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+				RT5631_M_SPKVOLR_SPOLMIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spormix_mixer_controls[] = {
+	SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+				RT5631_M_SPKVOLL_SPORMIX_BIT, 1, 1),
+	SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+				RT5631_M_SPKVOLR_SPORMIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = {
+	SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+				RT5631_M_OUTVOLL_MONOMIX_BIT, 1, 1),
+	SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+				RT5631_M_OUTVOLR_MONOMIX_BIT, 1, 1),
+};
+
+/* Left SPK Volume Input */
+static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL,
+	RT5631_L_EN_SHIFT, rt5631_spkvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_spkvoll_mux_control =
+	SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum);
+
+/* Left HP Volume Input */
+static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_hpvoll_enum, RT5631_HP_OUT_VOL,
+	RT5631_L_EN_SHIFT, rt5631_hpvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_hpvoll_mux_control =
+	SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum);
+
+/* Left Out Volume Input */
+static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL,
+	RT5631_L_EN_SHIFT, rt5631_outvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_outvoll_mux_control =
+	SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum);
+
+/* Right Out Volume Input */
+static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL,
+	RT5631_R_EN_SHIFT, rt5631_outvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_outvolr_mux_control =
+	SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum);
+
+/* Right HP Volume Input */
+static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_hpvolr_enum, RT5631_HP_OUT_VOL,
+	RT5631_R_EN_SHIFT, rt5631_hpvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_hpvolr_mux_control =
+	SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum);
+
+/* Right SPK Volume Input */
+static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL,
+	RT5631_R_EN_SHIFT, rt5631_spkvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_spkvolr_mux_control =
+	SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum);
+
+/* SPO Left Channel Input */
+static const char *rt5631_spol_src_sel[] = {
+	"SPOLMIX", "MONOIN_RX", "VDAC", "DACL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+	RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel);
+
+static const struct snd_kcontrol_new rt5631_spol_mux_control =
+	SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum);
+
+/* SPO Right Channel Input */
+static const char *rt5631_spor_src_sel[] = {
+	"SPORMIX", "MONOIN_RX", "VDAC", "DACR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+	RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel);
+
+static const struct snd_kcontrol_new rt5631_spor_mux_control =
+	SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum);
+
+/* MONO Input */
+static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+	RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel);
+
+static const struct snd_kcontrol_new rt5631_mono_mux_control =
+	SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum);
+
+/* Left HPO Input */
+static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+	RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel);
+
+static const struct snd_kcontrol_new rt5631_hpl_mux_control =
+	SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum);
+
+/* Right HPO Input */
+static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+	rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+	RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel);
+
+static const struct snd_kcontrol_new rt5631_hpr_mux_control =
+	SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum);
+
+static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = {
+	/* Vmid */
+	SND_SOC_DAPM_VMID("Vmid"),
+	/* PLL1 */
+	SND_SOC_DAPM_SUPPLY("PLL1", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_PLL1_BIT, 0, NULL, 0),
+
+	/* Input Side */
+	/* Input Lines */
+	SND_SOC_DAPM_INPUT("MIC1"),
+	SND_SOC_DAPM_INPUT("MIC2"),
+	SND_SOC_DAPM_INPUT("AXIL"),
+	SND_SOC_DAPM_INPUT("AXIR"),
+	SND_SOC_DAPM_INPUT("MONOIN_RXN"),
+	SND_SOC_DAPM_INPUT("MONOIN_RXP"),
+	SND_SOC_DAPM_INPUT("DMIC"),
+
+	/* MICBIAS */
+	SND_SOC_DAPM_MICBIAS("MIC Bias1", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_MICBIAS1_VOL_BIT, 0),
+	SND_SOC_DAPM_MICBIAS("MIC Bias2", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_MICBIAS2_VOL_BIT, 0),
+
+	/* Boost */
+	SND_SOC_DAPM_PGA("MIC1 Boost", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_MIC1_BOOT_GAIN_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("MIC2 Boost", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_MIC2_BOOT_GAIN_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("MONOIN_RXP Boost", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_MONO_IN_P_VOL_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("MONOIN_RXN Boost", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_MONO_IN_N_VOL_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("AXIL Boost", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_AXIL_IN_VOL_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("AXIR Boost", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_AXIR_IN_VOL_BIT, 0, NULL, 0),
+
+	/* MONO In */
+	SND_SOC_DAPM_MIXER("MONO_IN", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* REC Mixer */
+	SND_SOC_DAPM_MIXER("RECMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+		RT5631_PWR_RECMIXER_L_BIT, 0,
+		&rt5631_recmixl_mixer_controls[0],
+		ARRAY_SIZE(rt5631_recmixl_mixer_controls)),
+	SND_SOC_DAPM_MIXER("RECMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+		RT5631_PWR_RECMIXER_R_BIT, 0,
+		&rt5631_recmixr_mixer_controls[0],
+		ARRAY_SIZE(rt5631_recmixr_mixer_controls)),
+	/* Because of record duplication for L/R channel,
+	 * L/R ADCs need power up at the same time */
+	SND_SOC_DAPM_MIXER("ADC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* DMIC */
+	SND_SOC_DAPM_SUPPLY("DMIC Supply", RT5631_DIG_MIC_CTRL,
+		RT5631_DMIC_ENA_SHIFT, 0,
+		set_dmic_params, SND_SOC_DAPM_PRE_PMU),
+	/* ADC Data Srouce */
+	SND_SOC_DAPM_SUPPLY("Left ADC Select", RT5631_INT_ST_IRQ_CTRL_2,
+			RT5631_ADC_DATA_SEL_MIC1_SHIFT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Right ADC Select", RT5631_INT_ST_IRQ_CTRL_2,
+			RT5631_ADC_DATA_SEL_MIC2_SHIFT, 0, NULL, 0),
+
+	/* ADCs */
+	SND_SOC_DAPM_ADC("Left ADC", "HIFI Capture",
+		RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_L_CLK_BIT, 0),
+	SND_SOC_DAPM_ADC("Right ADC", "HIFI Capture",
+		RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_R_CLK_BIT, 0),
+
+	/* DAC and ADC supply power */
+	SND_SOC_DAPM_SUPPLY("I2S", RT5631_PWR_MANAG_ADD1,
+			RT5631_PWR_MAIN_I2S_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC REF", RT5631_PWR_MANAG_ADD1,
+			RT5631_PWR_DAC_REF_BIT, 0, NULL, 0),
+
+	/* Output Side */
+	/* DACs */
+	SND_SOC_DAPM_DAC("Left DAC", "HIFI Playback",
+		RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_L_CLK_BIT, 0),
+	SND_SOC_DAPM_DAC("Right DAC", "HIFI Playback",
+		RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_R_CLK_BIT, 0),
+	SND_SOC_DAPM_DAC("Voice DAC", "Voice DAC Mono Playback",
+				SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_PGA("Voice DAC Boost", SND_SOC_NOPM, 0, 0, NULL, 0),
+	/* DAC supply power */
+	SND_SOC_DAPM_SUPPLY("Left DAC To Mixer", RT5631_PWR_MANAG_ADD1,
+			RT5631_PWR_DAC_L_TO_MIXER_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Right DAC To Mixer", RT5631_PWR_MANAG_ADD1,
+			RT5631_PWR_DAC_R_TO_MIXER_BIT, 0, NULL, 0),
+
+	/* Left SPK Mixer */
+	SND_SOC_DAPM_MIXER("SPKMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_SPKMIXER_L_BIT, 0,
+			&rt5631_spkmixl_mixer_controls[0],
+			ARRAY_SIZE(rt5631_spkmixl_mixer_controls)),
+	/* Left Out Mixer */
+	SND_SOC_DAPM_MIXER("OUTMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_OUTMIXER_L_BIT, 0,
+			&rt5631_outmixl_mixer_controls[0],
+			ARRAY_SIZE(rt5631_outmixl_mixer_controls)),
+	/* Right Out Mixer */
+	SND_SOC_DAPM_MIXER("OUTMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_OUTMIXER_R_BIT, 0,
+			&rt5631_outmixr_mixer_controls[0],
+			ARRAY_SIZE(rt5631_outmixr_mixer_controls)),
+	/* Right SPK Mixer */
+	SND_SOC_DAPM_MIXER("SPKMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_SPKMIXER_R_BIT, 0,
+			&rt5631_spkmixr_mixer_controls[0],
+			ARRAY_SIZE(rt5631_spkmixr_mixer_controls)),
+
+	/* Volume Mux */
+	SND_SOC_DAPM_MUX("Left SPKVOL Mux", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_SPK_L_VOL_BIT, 0,
+			&rt5631_spkvoll_mux_control),
+	SND_SOC_DAPM_MUX("Left HPVOL Mux", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_HP_L_OUT_VOL_BIT, 0,
+			&rt5631_hpvoll_mux_control),
+	SND_SOC_DAPM_MUX("Left OUTVOL Mux", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_LOUT_VOL_BIT, 0,
+			&rt5631_outvoll_mux_control),
+	SND_SOC_DAPM_MUX("Right OUTVOL Mux", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_ROUT_VOL_BIT, 0,
+			&rt5631_outvolr_mux_control),
+	SND_SOC_DAPM_MUX("Right HPVOL Mux", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_HP_R_OUT_VOL_BIT, 0,
+			&rt5631_hpvolr_mux_control),
+	SND_SOC_DAPM_MUX("Right SPKVOL Mux", RT5631_PWR_MANAG_ADD4,
+			RT5631_PWR_SPK_R_VOL_BIT, 0,
+			&rt5631_spkvolr_mux_control),
+
+	/* DAC To HP */
+	SND_SOC_DAPM_PGA_S("Left DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA_S("Right DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* HP Depop */
+	SND_SOC_DAPM_PGA_S("HP Depop", 1, SND_SOC_NOPM, 0, 0,
+		hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+	/* AXO1 Mixer */
+	SND_SOC_DAPM_MIXER("AXO1MIX Mixer", RT5631_PWR_MANAG_ADD3,
+			RT5631_PWR_AXO1MIXER_BIT, 0,
+			&rt5631_AXO1MIX_mixer_controls[0],
+			ARRAY_SIZE(rt5631_AXO1MIX_mixer_controls)),
+	/* SPOL Mixer */
+	SND_SOC_DAPM_MIXER("SPOLMIX Mixer", SND_SOC_NOPM, 0, 0,
+			&rt5631_spolmix_mixer_controls[0],
+			ARRAY_SIZE(rt5631_spolmix_mixer_controls)),
+	/* MONO Mixer */
+	SND_SOC_DAPM_MIXER("MONOMIX Mixer", RT5631_PWR_MANAG_ADD3,
+			RT5631_PWR_MONOMIXER_BIT, 0,
+			&rt5631_monomix_mixer_controls[0],
+			ARRAY_SIZE(rt5631_monomix_mixer_controls)),
+	/* SPOR Mixer */
+	SND_SOC_DAPM_MIXER("SPORMIX Mixer", SND_SOC_NOPM, 0, 0,
+			&rt5631_spormix_mixer_controls[0],
+			ARRAY_SIZE(rt5631_spormix_mixer_controls)),
+	/* AXO2 Mixer */
+	SND_SOC_DAPM_MIXER("AXO2MIX Mixer", RT5631_PWR_MANAG_ADD3,
+			RT5631_PWR_AXO2MIXER_BIT, 0,
+			&rt5631_AXO2MIX_mixer_controls[0],
+			ARRAY_SIZE(rt5631_AXO2MIX_mixer_controls)),
+
+	/* Mux */
+	SND_SOC_DAPM_MUX("SPOL Mux", SND_SOC_NOPM, 0, 0,
+			&rt5631_spol_mux_control),
+	SND_SOC_DAPM_MUX("SPOR Mux", SND_SOC_NOPM, 0, 0,
+			&rt5631_spor_mux_control),
+	SND_SOC_DAPM_MUX("MONO Mux", SND_SOC_NOPM, 0, 0,
+			&rt5631_mono_mux_control),
+	SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0,
+			&rt5631_hpl_mux_control),
+	SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0,
+			&rt5631_hpr_mux_control),
+
+	/* AMP supply */
+	SND_SOC_DAPM_SUPPLY("MONO Depop", RT5631_PWR_MANAG_ADD3,
+			RT5631_PWR_MONO_DEPOP_DIS_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Class D", RT5631_PWR_MANAG_ADD1,
+			RT5631_PWR_CLASS_D_BIT, 0, NULL, 0),
+
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("AUXO1"),
+	SND_SOC_DAPM_OUTPUT("AUXO2"),
+	SND_SOC_DAPM_OUTPUT("SPOL"),
+	SND_SOC_DAPM_OUTPUT("SPOR"),
+	SND_SOC_DAPM_OUTPUT("HPOL"),
+	SND_SOC_DAPM_OUTPUT("HPOR"),
+	SND_SOC_DAPM_OUTPUT("MONO"),
+};
+
+static const struct snd_soc_dapm_route rt5631_dapm_routes[] = {
+	{"MIC1 Boost", NULL, "MIC1"},
+	{"MIC2 Boost", NULL, "MIC2"},
+	{"MONOIN_RXP Boost", NULL, "MONOIN_RXP"},
+	{"MONOIN_RXN Boost", NULL, "MONOIN_RXN"},
+	{"AXIL Boost", NULL, "AXIL"},
+	{"AXIR Boost", NULL, "AXIR"},
+
+	{"MONO_IN", NULL, "MONOIN_RXP Boost"},
+	{"MONO_IN", NULL, "MONOIN_RXN Boost"},
+
+	{"RECMIXL Mixer", "OUTMIXL Capture Switch", "OUTMIXL Mixer"},
+	{"RECMIXL Mixer", "MIC1_BST1 Capture Switch", "MIC1 Boost"},
+	{"RECMIXL Mixer", "AXILVOL Capture Switch", "AXIL Boost"},
+	{"RECMIXL Mixer", "MONOIN_RX Capture Switch", "MONO_IN"},
+
+	{"RECMIXR Mixer", "OUTMIXR Capture Switch", "OUTMIXR Mixer"},
+	{"RECMIXR Mixer", "MIC2_BST2 Capture Switch", "MIC2 Boost"},
+	{"RECMIXR Mixer", "AXIRVOL Capture Switch", "AXIR Boost"},
+	{"RECMIXR Mixer", "MONOIN_RX Capture Switch", "MONO_IN"},
+
+	{"ADC Mixer", NULL, "RECMIXL Mixer"},
+	{"ADC Mixer", NULL, "RECMIXR Mixer"},
+
+	{"Left ADC", NULL, "ADC Mixer"},
+	{"Left ADC", NULL, "Left ADC Select", check_adcl_select},
+	{"Left ADC", NULL, "PLL1", check_sysclk1_source},
+	{"Left ADC", NULL, "I2S"},
+	{"Left ADC", NULL, "DAC REF"},
+
+	{"Right ADC", NULL, "ADC Mixer"},
+	{"Right ADC", NULL, "Right ADC Select", check_adcr_select},
+	{"Right ADC", NULL, "PLL1", check_sysclk1_source},
+	{"Right ADC", NULL, "I2S"},
+	{"Right ADC", NULL, "DAC REF"},
+
+	{"DMIC", NULL, "DMIC Supply", check_dmic_used},
+	{"Left ADC", NULL, "DMIC"},
+	{"Right ADC", NULL, "DMIC"},
+
+	{"Left DAC", NULL, "PLL1", check_sysclk1_source},
+	{"Left DAC", NULL, "I2S"},
+	{"Left DAC", NULL, "DAC REF"},
+	{"Right DAC", NULL, "PLL1", check_sysclk1_source},
+	{"Right DAC", NULL, "I2S"},
+	{"Right DAC", NULL, "DAC REF"},
+
+	{"Voice DAC Boost", NULL, "Voice DAC"},
+
+	{"SPKMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_spkmixl},
+	{"SPKMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+	{"SPKMIXL Mixer", "MIC1_P Playback Switch", "MIC1"},
+	{"SPKMIXL Mixer", "DACL Playback Switch", "Left DAC"},
+	{"SPKMIXL Mixer", "OUTMIXL Playback Switch", "OUTMIXL Mixer"},
+
+	{"SPKMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_spkmixr},
+	{"SPKMIXR Mixer", "OUTMIXR Playback Switch", "OUTMIXR Mixer"},
+	{"SPKMIXR Mixer", "DACR Playback Switch", "Right DAC"},
+	{"SPKMIXR Mixer", "MIC2_P Playback Switch", "MIC2"},
+	{"SPKMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+
+	{"OUTMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_outmixl},
+	{"OUTMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+	{"OUTMIXL Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+	{"OUTMIXL Mixer", "DACL Playback Switch", "Left DAC"},
+	{"OUTMIXL Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+	{"OUTMIXL Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+	{"OUTMIXL Mixer", "MONOIN_RXP Playback Switch", "MONOIN_RXP Boost"},
+	{"OUTMIXL Mixer", "AXILVOL Playback Switch", "AXIL Boost"},
+	{"OUTMIXL Mixer", "AXIRVOL Playback Switch", "AXIR Boost"},
+	{"OUTMIXL Mixer", "VDAC Playback Switch", "Voice DAC Boost"},
+
+	{"OUTMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_outmixr},
+	{"OUTMIXR Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+	{"OUTMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+	{"OUTMIXR Mixer", "DACR Playback Switch", "Right DAC"},
+	{"OUTMIXR Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+	{"OUTMIXR Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+	{"OUTMIXR Mixer", "MONOIN_RXN Playback Switch", "MONOIN_RXN Boost"},
+	{"OUTMIXR Mixer", "AXILVOL Playback Switch", "AXIL Boost"},
+	{"OUTMIXR Mixer", "AXIRVOL Playback Switch", "AXIR Boost"},
+	{"OUTMIXR Mixer", "VDAC Playback Switch", "Voice DAC Boost"},
+
+	{"Left SPKVOL Mux",  "SPKMIXL", "SPKMIXL Mixer"},
+	{"Left SPKVOL Mux",  "Vmid", "Vmid"},
+	{"Left HPVOL Mux",  "OUTMIXL", "OUTMIXL Mixer"},
+	{"Left HPVOL Mux",  "Vmid", "Vmid"},
+	{"Left OUTVOL Mux",  "OUTMIXL", "OUTMIXL Mixer"},
+	{"Left OUTVOL Mux",  "Vmid", "Vmid"},
+	{"Right OUTVOL Mux",  "OUTMIXR", "OUTMIXR Mixer"},
+	{"Right OUTVOL Mux",  "Vmid", "Vmid"},
+	{"Right HPVOL Mux",  "OUTMIXR", "OUTMIXR Mixer"},
+	{"Right HPVOL Mux",  "Vmid", "Vmid"},
+	{"Right SPKVOL Mux",  "SPKMIXR", "SPKMIXR Mixer"},
+	{"Right SPKVOL Mux",  "Vmid", "Vmid"},
+
+	{"AXO1MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+	{"AXO1MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+	{"AXO1MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+	{"AXO1MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+
+	{"AXO2MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+	{"AXO2MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+	{"AXO2MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+	{"AXO2MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+
+	{"SPOLMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"},
+	{"SPOLMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"},
+
+	{"SPORMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"},
+	{"SPORMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"},
+
+	{"MONOMIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+	{"MONOMIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+
+	{"SPOL Mux", "SPOLMIX", "SPOLMIX Mixer"},
+	{"SPOL Mux", "MONOIN_RX", "MONO_IN"},
+	{"SPOL Mux", "VDAC", "Voice DAC Boost"},
+	{"SPOL Mux", "DACL", "Left DAC"},
+
+	{"SPOR Mux", "SPORMIX", "SPORMIX Mixer"},
+	{"SPOR Mux", "MONOIN_RX", "MONO_IN"},
+	{"SPOR Mux", "VDAC", "Voice DAC Boost"},
+	{"SPOR Mux", "DACR", "Right DAC"},
+
+	{"MONO Mux", "MONOMIX", "MONOMIX Mixer"},
+	{"MONO Mux", "MONOIN_RX", "MONO_IN"},
+	{"MONO Mux", "VDAC", "Voice DAC Boost"},
+
+	{"Right DAC_HP", NULL, "Right DAC"},
+	{"Left DAC_HP", NULL, "Left DAC"},
+
+	{"HPL Mux", "Left HPVOL", "Left HPVOL Mux"},
+	{"HPL Mux", "Left DAC", "Left DAC_HP"},
+	{"HPR Mux", "Right HPVOL", "Right HPVOL Mux"},
+	{"HPR Mux", "Right DAC", "Right DAC_HP"},
+
+	{"HP Depop", NULL, "HPL Mux"},
+	{"HP Depop", NULL, "HPR Mux"},
+
+	{"AUXO1", NULL, "AXO1MIX Mixer"},
+	{"AUXO2", NULL, "AXO2MIX Mixer"},
+
+	{"SPOL", NULL, "Class D"},
+	{"SPOL", NULL, "SPOL Mux"},
+	{"SPOR", NULL, "Class D"},
+	{"SPOR", NULL, "SPOR Mux"},
+
+	{"HPOL", NULL, "HP Depop"},
+	{"HPOR", NULL, "HP Depop"},
+
+	{"MONO", NULL, "MONO Depop"},
+	{"MONO", NULL, "MONO Mux"},
+};
+
+struct coeff_clk_div {
+	u32 mclk;
+	u32 bclk;
+	u32 rate;
+	u16 reg_val;
+};
+
+/* PLL divisors */
+struct pll_div {
+	u32 pll_in;
+	u32 pll_out;
+	u16 reg_val;
+};
+
+static const struct pll_div codec_master_pll_div[] = {
+	{2048000,  8192000,  0x0ea0},
+	{3686400,  8192000,  0x4e27},
+	{12000000,  8192000,  0x456b},
+	{13000000,  8192000,  0x495f},
+	{13100000,  8192000,  0x0320},
+	{2048000,  11289600,  0xf637},
+	{3686400,  11289600,  0x2f22},
+	{12000000,  11289600,  0x3e2f},
+	{13000000,  11289600,  0x4d5b},
+	{13100000,  11289600,  0x363b},
+	{2048000,  16384000,  0x1ea0},
+	{3686400,  16384000,  0x9e27},
+	{12000000,  16384000,  0x452b},
+	{13000000,  16384000,  0x542f},
+	{13100000,  16384000,  0x03a0},
+	{2048000,  16934400,  0xe625},
+	{3686400,  16934400,  0x9126},
+	{12000000,  16934400,  0x4d2c},
+	{13000000,  16934400,  0x742f},
+	{13100000,  16934400,  0x3c27},
+	{2048000,  22579200,  0x2aa0},
+	{3686400,  22579200,  0x2f20},
+	{12000000,  22579200,  0x7e2f},
+	{13000000,  22579200,  0x742f},
+	{13100000,  22579200,  0x3c27},
+	{2048000,  24576000,  0x2ea0},
+	{3686400,  24576000,  0xee27},
+	{12000000,  24576000,  0x2915},
+	{13000000,  24576000,  0x772e},
+	{13100000,  24576000,  0x0d20},
+	{26000000,  24576000,  0x2027},
+	{26000000,  22579200,  0x392f},
+	{24576000,  22579200,  0x0921},
+	{24576000,  24576000,  0x02a0},
+};
+
+static const struct pll_div codec_slave_pll_div[] = {
+	{256000,  2048000,  0x46f0},
+	{256000,  4096000,  0x3ea0},
+	{352800,  5644800,  0x3ea0},
+	{512000,  8192000,  0x3ea0},
+	{1024000,  8192000,  0x46f0},
+	{705600,  11289600,  0x3ea0},
+	{1024000,  16384000,  0x3ea0},
+	{1411200,  22579200,  0x3ea0},
+	{1536000,  24576000,  0x3ea0},
+	{2048000,  16384000,  0x1ea0},
+	{2822400,  22579200,  0x1ea0},
+	{2822400,  45158400,  0x5ec0},
+	{5644800,  45158400,  0x46f0},
+	{3072000,  24576000,  0x1ea0},
+	{3072000,  49152000,  0x5ec0},
+	{6144000,  49152000,  0x46f0},
+	{705600,  11289600,  0x3ea0},
+	{705600,  8467200,  0x3ab0},
+	{24576000,  24576000,  0x02a0},
+	{1411200,  11289600,  0x1690},
+	{2822400,  11289600,  0x0a90},
+	{1536000,  12288000,  0x1690},
+	{3072000,  12288000,  0x0a90},
+};
+
+static struct coeff_clk_div coeff_div[] = {
+	/* sysclk is 256fs */
+	{2048000,  8000 * 32,  8000, 0x1000},
+	{2048000,  8000 * 64,  8000, 0x0000},
+	{2822400,  11025 * 32,  11025,  0x1000},
+	{2822400,  11025 * 64,  11025,  0x0000},
+	{4096000,  16000 * 32,  16000,  0x1000},
+	{4096000,  16000 * 64,  16000,  0x0000},
+	{5644800,  22050 * 32,  22050,  0x1000},
+	{5644800,  22050 * 64,  22050,  0x0000},
+	{8192000,  32000 * 32,  32000,  0x1000},
+	{8192000,  32000 * 64,  32000,  0x0000},
+	{11289600,  44100 * 32,  44100,  0x1000},
+	{11289600,  44100 * 64,  44100,  0x0000},
+	{12288000,  48000 * 32,  48000,  0x1000},
+	{12288000,  48000 * 64,  48000,  0x0000},
+	{22579200,  88200 * 32,  88200,  0x1000},
+	{22579200,  88200 * 64,  88200,  0x0000},
+	{24576000,  96000 * 32,  96000,  0x1000},
+	{24576000,  96000 * 64,  96000,  0x0000},
+	/* sysclk is 512fs */
+	{4096000,  8000 * 32,  8000, 0x3000},
+	{4096000,  8000 * 64,  8000, 0x2000},
+	{5644800,  11025 * 32,  11025, 0x3000},
+	{5644800,  11025 * 64,  11025, 0x2000},
+	{8192000,  16000 * 32,  16000, 0x3000},
+	{8192000,  16000 * 64,  16000, 0x2000},
+	{11289600,  22050 * 32,  22050, 0x3000},
+	{11289600,  22050 * 64,  22050, 0x2000},
+	{16384000,  32000 * 32,  32000, 0x3000},
+	{16384000,  32000 * 64,  32000, 0x2000},
+	{22579200,  44100 * 32,  44100, 0x3000},
+	{22579200,  44100 * 64,  44100, 0x2000},
+	{24576000,  48000 * 32,  48000, 0x3000},
+	{24576000,  48000 * 64,  48000, 0x2000},
+	{45158400,  88200 * 32,  88200, 0x3000},
+	{45158400,  88200 * 64,  88200, 0x2000},
+	{49152000,  96000 * 32,  96000, 0x3000},
+	{49152000,  96000 * 64,  96000, 0x2000},
+	/* sysclk is 24.576Mhz or 22.5792Mhz */
+	{24576000,  8000 * 32,  8000,  0x7080},
+	{24576000,  8000 * 64,  8000,  0x6080},
+	{24576000,  16000 * 32,  16000,  0x5080},
+	{24576000,  16000 * 64,  16000,  0x4080},
+	{24576000,  24000 * 32,  24000,  0x5000},
+	{24576000,  24000 * 64,  24000,  0x4000},
+	{24576000,  32000 * 32,  32000,  0x3080},
+	{24576000,  32000 * 64,  32000,  0x2080},
+	{22579200,  11025 * 32,  11025,  0x7000},
+	{22579200,  11025 * 64,  11025,  0x6000},
+	{22579200,  22050 * 32,  22050,  0x5000},
+	{22579200,  22050 * 64,  22050,  0x4000},
+};
+
+static int get_coeff(int mclk, int rate, int timesofbclk)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+		if (coeff_div[i].mclk == mclk && coeff_div[i].rate == rate &&
+			(coeff_div[i].bclk / coeff_div[i].rate) == timesofbclk)
+			return i;
+	}
+	return -EINVAL;
+}
+
+static int rt5631_hifi_pcm_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;
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+	int timesofbclk = 32, coeff;
+	unsigned int iface = 0;
+
+	dev_dbg(codec->dev, "enter %s\n", __func__);
+
+	rt5631->bclk_rate = snd_soc_params_to_bclk(params);
+	if (rt5631->bclk_rate < 0) {
+		dev_err(codec->dev, "Fail to get BCLK rate\n");
+		return rt5631->bclk_rate;
+	}
+	rt5631->rx_rate = params_rate(params);
+
+	if (rt5631->master)
+		coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate,
+			rt5631->bclk_rate / rt5631->rx_rate);
+	else
+		coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate,
+					timesofbclk);
+	if (coeff < 0) {
+		dev_err(codec->dev, "Fail to get coeff\n");
+		return -EINVAL;
+	}
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		iface |= RT5631_SDP_I2S_DL_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		iface |= RT5631_SDP_I2S_DL_24;
+		break;
+	case SNDRV_PCM_FORMAT_S8:
+		iface |= RT5631_SDP_I2S_DL_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, RT5631_SDP_CTRL,
+		RT5631_SDP_I2S_DL_MASK, iface);
+	snd_soc_write(codec, RT5631_STEREO_AD_DA_CLK_CTRL,
+					coeff_div[coeff].reg_val);
+
+	return 0;
+}
+
+static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+						unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+	unsigned int iface = 0;
+
+	dev_dbg(codec->dev, "enter %s\n", __func__);
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		rt5631->master = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		iface |= RT5631_SDP_MODE_SEL_SLAVE;
+		rt5631->master = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface |= RT5631_SDP_I2S_DF_LEFT;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		iface |= RT5631_SDP_I2S_DF_PCM_A;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		iface  |= RT5631_SDP_I2S_DF_PCM_B;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		iface |= RT5631_SDP_I2S_BCLK_POL_CTRL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_write(codec, RT5631_SDP_CTRL, iface);
+
+	return 0;
+}
+
+static int rt5631_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+				int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "enter %s, syclk=%d\n", __func__, freq);
+
+	if ((freq >= (256 * 8000)) && (freq <= (512 * 96000))) {
+		rt5631->sysclk = freq;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+		int source, unsigned int freq_in, unsigned int freq_out)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+	int i, ret = -EINVAL;
+
+	dev_dbg(codec->dev, "enter %s\n", __func__);
+
+	if (!freq_in || !freq_out) {
+		dev_dbg(codec->dev, "PLL disabled\n");
+
+		snd_soc_update_bits(codec, RT5631_GLOBAL_CLK_CTRL,
+			RT5631_SYSCLK_SOUR_SEL_MASK,
+			RT5631_SYSCLK_SOUR_SEL_MCLK);
+
+		return 0;
+	}
+
+	if (rt5631->master) {
+		for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++)
+			if (freq_in == codec_master_pll_div[i].pll_in &&
+			freq_out == codec_master_pll_div[i].pll_out) {
+				dev_info(codec->dev,
+					"change PLL in master mode\n");
+				snd_soc_write(codec, RT5631_PLL_CTRL,
+					codec_master_pll_div[i].reg_val);
+				schedule_timeout_uninterruptible(
+					msecs_to_jiffies(20));
+				snd_soc_update_bits(codec,
+					RT5631_GLOBAL_CLK_CTRL,
+					RT5631_SYSCLK_SOUR_SEL_MASK |
+					RT5631_PLLCLK_SOUR_SEL_MASK,
+					RT5631_SYSCLK_SOUR_SEL_PLL |
+					RT5631_PLLCLK_SOUR_SEL_MCLK);
+				ret = 0;
+				break;
+			}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++)
+			if (freq_in == codec_slave_pll_div[i].pll_in &&
+			freq_out == codec_slave_pll_div[i].pll_out) {
+				dev_info(codec->dev,
+					"change PLL in slave mode\n");
+				snd_soc_write(codec, RT5631_PLL_CTRL,
+					codec_slave_pll_div[i].reg_val);
+				schedule_timeout_uninterruptible(
+					msecs_to_jiffies(20));
+				snd_soc_update_bits(codec,
+					RT5631_GLOBAL_CLK_CTRL,
+					RT5631_SYSCLK_SOUR_SEL_MASK |
+					RT5631_PLLCLK_SOUR_SEL_MASK,
+					RT5631_SYSCLK_SOUR_SEL_PLL |
+					RT5631_PLLCLK_SOUR_SEL_BCLK);
+				ret = 0;
+				break;
+			}
+	}
+
+	return ret;
+}
+
+static int rt5631_set_bias_level(struct snd_soc_codec *codec,
+			enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+	case SND_SOC_BIAS_PREPARE:
+		snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD2,
+			RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL,
+			RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+				RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
+				RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
+			msleep(80);
+			snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+				RT5631_PWR_FAST_VREF_CTRL,
+				RT5631_PWR_FAST_VREF_CTRL);
+			codec->cache_only = false;
+			snd_soc_cache_sync(codec);
+		}
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		snd_soc_write(codec, RT5631_PWR_MANAG_ADD1, 0x0000);
+		snd_soc_write(codec, RT5631_PWR_MANAG_ADD2, 0x0000);
+		snd_soc_write(codec, RT5631_PWR_MANAG_ADD3, 0x0000);
+		snd_soc_write(codec, RT5631_PWR_MANAG_ADD4, 0x0000);
+		break;
+
+	default:
+		break;
+	}
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static int rt5631_probe(struct snd_soc_codec *codec)
+{
+	struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val;
+	int ret;
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3);
+	if (val & 0x0002)
+		rt5631->codec_version = 1;
+	else
+		rt5631->codec_version = 0;
+
+	rt5631_reset(codec);
+	snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+		RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
+		RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
+	msleep(80);
+	snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+		RT5631_PWR_FAST_VREF_CTRL, RT5631_PWR_FAST_VREF_CTRL);
+	/* enable HP zero cross */
+	snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0f18);
+	/* power off ClassD auto Recovery */
+	if (rt5631->codec_version)
+		snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2,
+					0x2000, 0x2000);
+	else
+		snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2,
+					0x2000, 0);
+	/* DMIC */
+	if (rt5631->dmic_used_flag) {
+		snd_soc_update_bits(codec, RT5631_GPIO_CTRL,
+			RT5631_GPIO_PIN_FUN_SEL_MASK |
+			RT5631_GPIO_DMIC_FUN_SEL_MASK,
+			RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC |
+			RT5631_GPIO_DMIC_FUN_SEL_DIMC);
+		snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+			RT5631_DMIC_L_CH_LATCH_MASK |
+			RT5631_DMIC_R_CH_LATCH_MASK,
+			RT5631_DMIC_L_CH_LATCH_FALLING |
+			RT5631_DMIC_R_CH_LATCH_RISING);
+	}
+
+	codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
+
+	return 0;
+}
+
+static int rt5631_remove(struct snd_soc_codec *codec)
+{
+	rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5631_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+	rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int rt5631_resume(struct snd_soc_codec *codec)
+{
+	rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+#else
+#define rt5631_suspend NULL
+#define rt5631_resume NULL
+#endif
+
+#define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5631_FORMAT	(SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | \
+			SNDRV_PCM_FMTBIT_S8)
+
+static struct snd_soc_dai_ops rt5631_ops = {
+	.hw_params = rt5631_hifi_pcm_params,
+	.set_fmt = rt5631_hifi_codec_set_dai_fmt,
+	.set_sysclk = rt5631_hifi_codec_set_dai_sysclk,
+	.set_pll = rt5631_codec_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver rt5631_dai[] = {
+	{
+		.name = "rt5631-hifi",
+		.id = 1,
+		.playback = {
+			.stream_name = "HIFI Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5631_STEREO_RATES,
+			.formats = RT5631_FORMAT,
+		},
+		.capture = {
+			.stream_name = "HIFI Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5631_STEREO_RATES,
+			.formats = RT5631_FORMAT,
+		},
+		.ops = &rt5631_ops,
+	},
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5631 = {
+	.probe = rt5631_probe,
+	.remove = rt5631_remove,
+	.suspend = rt5631_suspend,
+	.resume = rt5631_resume,
+	.set_bias_level = rt5631_set_bias_level,
+	.reg_cache_size = RT5631_VENDOR_ID2 + 1,
+	.reg_word_size = sizeof(u16),
+	.reg_cache_default = rt5631_reg,
+	.volatile_register = rt5631_volatile_register,
+	.readable_register = rt5631_readable_register,
+	.reg_cache_step = 1,
+	.controls = rt5631_snd_controls,
+	.num_controls = ARRAY_SIZE(rt5631_snd_controls),
+	.dapm_widgets = rt5631_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets),
+	.dapm_routes = rt5631_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes),
+};
+
+static const struct i2c_device_id rt5631_i2c_id[] = {
+	{ "rt5631", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id);
+
+static int rt5631_i2c_probe(struct i2c_client *i2c,
+		    const struct i2c_device_id *id)
+{
+	struct rt5631_priv *rt5631;
+	int ret;
+
+	rt5631 = kzalloc(sizeof(struct rt5631_priv), GFP_KERNEL);
+	if (NULL == rt5631)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, rt5631);
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5631,
+			rt5631_dai, ARRAY_SIZE(rt5631_dai));
+	if (ret < 0)
+		kfree(rt5631);
+
+	return ret;
+}
+
+static __devexit int rt5631_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static struct i2c_driver rt5631_i2c_driver = {
+	.driver = {
+		.name = "rt5631",
+		.owner = THIS_MODULE,
+	},
+	.probe = rt5631_i2c_probe,
+	.remove   = __devexit_p(rt5631_i2c_remove),
+	.id_table = rt5631_i2c_id,
+};
+
+static int __init rt5631_modinit(void)
+{
+	return i2c_add_driver(&rt5631_i2c_driver);
+}
+module_init(rt5631_modinit);
+
+static void __exit rt5631_modexit(void)
+{
+	i2c_del_driver(&rt5631_i2c_driver);
+}
+module_exit(rt5631_modexit);
+
+MODULE_DESCRIPTION("ASoC RT5631 driver");
+MODULE_AUTHOR("flove <flove@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt5631.h b/sound/soc/codecs/rt5631.h
new file mode 100644
index 000000000000..13401581b0df
--- /dev/null
+++ b/sound/soc/codecs/rt5631.h
@@ -0,0 +1,701 @@
+#ifndef __RTCODEC5631_H__
+#define __RTCODEC5631_H__
+
+
+#define RT5631_RESET				0x00
+#define RT5631_SPK_OUT_VOL			0x02
+#define RT5631_HP_OUT_VOL			0x04
+#define RT5631_MONO_AXO_1_2_VOL		0x06
+#define RT5631_AUX_IN_VOL			0x0A
+#define RT5631_STEREO_DAC_VOL_1		0x0C
+#define RT5631_MIC_CTRL_1			0x0E
+#define RT5631_STEREO_DAC_VOL_2		0x10
+#define RT5631_ADC_CTRL_1			0x12
+#define RT5631_ADC_REC_MIXER			0x14
+#define RT5631_ADC_CTRL_2			0x16
+#define RT5631_VDAC_DIG_VOL			0x18
+#define RT5631_OUTMIXER_L_CTRL			0x1A
+#define RT5631_OUTMIXER_R_CTRL			0x1C
+#define RT5631_AXO1MIXER_CTRL			0x1E
+#define RT5631_AXO2MIXER_CTRL			0x20
+#define RT5631_MIC_CTRL_2			0x22
+#define RT5631_DIG_MIC_CTRL			0x24
+#define RT5631_MONO_INPUT_VOL			0x26
+#define RT5631_SPK_MIXER_CTRL			0x28
+#define RT5631_SPK_MONO_OUT_CTRL		0x2A
+#define RT5631_SPK_MONO_HP_OUT_CTRL		0x2C
+#define RT5631_SDP_CTRL				0x34
+#define RT5631_MONO_SDP_CTRL			0x36
+#define RT5631_STEREO_AD_DA_CLK_CTRL		0x38
+#define RT5631_PWR_MANAG_ADD1		0x3A
+#define RT5631_PWR_MANAG_ADD2		0x3B
+#define RT5631_PWR_MANAG_ADD3		0x3C
+#define RT5631_PWR_MANAG_ADD4		0x3E
+#define RT5631_GEN_PUR_CTRL_REG		0x40
+#define RT5631_GLOBAL_CLK_CTRL			0x42
+#define RT5631_PLL_CTRL				0x44
+#define RT5631_INT_ST_IRQ_CTRL_1		0x48
+#define RT5631_INT_ST_IRQ_CTRL_2		0x4A
+#define RT5631_GPIO_CTRL			0x4C
+#define RT5631_MISC_CTRL			0x52
+#define RT5631_DEPOP_FUN_CTRL_1		0x54
+#define RT5631_DEPOP_FUN_CTRL_2		0x56
+#define RT5631_JACK_DET_CTRL			0x5A
+#define RT5631_SOFT_VOL_CTRL			0x5C
+#define RT5631_ALC_CTRL_1			0x64
+#define RT5631_ALC_CTRL_2			0x65
+#define RT5631_ALC_CTRL_3			0x66
+#define RT5631_PSEUDO_SPATL_CTRL		0x68
+#define RT5631_INDEX_ADD			0x6A
+#define RT5631_INDEX_DATA			0x6C
+#define RT5631_EQ_CTRL				0x6E
+#define RT5631_VENDOR_ID			0x7A
+#define RT5631_VENDOR_ID1			0x7C
+#define RT5631_VENDOR_ID2			0x7E
+
+/* Index of Codec Private Register definition */
+#define RT5631_EQ_BW_LOP			0x00
+#define RT5631_EQ_GAIN_LOP			0x01
+#define RT5631_EQ_FC_BP1			0x02
+#define RT5631_EQ_BW_BP1			0x03
+#define RT5631_EQ_GAIN_BP1			0x04
+#define RT5631_EQ_FC_BP2			0x05
+#define RT5631_EQ_BW_BP2			0x06
+#define RT5631_EQ_GAIN_BP2			0x07
+#define RT5631_EQ_FC_BP3			0x08
+#define RT5631_EQ_BW_BP3			0x09
+#define RT5631_EQ_GAIN_BP3			0x0a
+#define RT5631_EQ_BW_HIP			0x0b
+#define RT5631_EQ_GAIN_HIP			0x0c
+#define RT5631_EQ_HPF_A1			0x0d
+#define RT5631_EQ_HPF_A2			0x0e
+#define RT5631_EQ_HPF_GAIN			0x0f
+#define RT5631_EQ_PRE_VOL_CTRL			0x11
+#define RT5631_EQ_POST_VOL_CTRL		0x12
+#define RT5631_TEST_MODE_CTRL			0x39
+#define RT5631_CP_INTL_REG2			0x45
+#define RT5631_ADDA_MIXER_INTL_REG3		0x52
+#define RT5631_SPK_INTL_CTRL			0x56
+
+
+/* global definition */
+#define RT5631_L_MUTE					(0x1 << 15)
+#define RT5631_L_MUTE_SHIFT				15
+#define RT5631_L_EN					(0x1 << 14)
+#define RT5631_L_EN_SHIFT				14
+#define RT5631_R_MUTE					(0x1 << 7)
+#define RT5631_R_MUTE_SHIFT				7
+#define RT5631_R_EN					(0x1 << 6)
+#define RT5631_R_EN_SHIFT				6
+#define RT5631_VOL_MASK				0x1f
+#define RT5631_L_VOL_SHIFT				8
+#define RT5631_R_VOL_SHIFT				0
+
+/* Speaker Output Control(0x02) */
+#define RT5631_SPK_L_VOL_SEL_MASK			(0x1 << 14)
+#define RT5631_SPK_L_VOL_SEL_VMID			(0x0 << 14)
+#define RT5631_SPK_L_VOL_SEL_SPKMIX_L			(0x1 << 14)
+#define RT5631_SPK_R_VOL_SEL_MASK			(0x1 << 6)
+#define RT5631_SPK_R_VOL_SEL_VMID			(0x0 << 6)
+#define RT5631_SPK_R_VOL_SEL_SPKMIX_R			(0x1 << 6)
+
+/* Headphone Output Control(0x04) */
+#define RT5631_HP_L_VOL_SEL_MASK			(0x1 << 14)
+#define RT5631_HP_L_VOL_SEL_VMID			(0x0 << 14)
+#define RT5631_HP_L_VOL_SEL_OUTMIX_L			(0x1 << 14)
+#define RT5631_HP_R_VOL_SEL_MASK			(0x1 << 6)
+#define RT5631_HP_R_VOL_SEL_VMID			(0x0 << 6)
+#define RT5631_HP_R_VOL_SEL_OUTMIX_R			(0x1 << 6)
+
+/* Output Control for AUXOUT/MONO(0x06) */
+#define RT5631_AUXOUT_1_VOL_SEL_MASK			(0x1 << 14)
+#define RT5631_AUXOUT_1_VOL_SEL_VMID			(0x0 << 14)
+#define RT5631_AUXOUT_1_VOL_SEL_OUTMIX_L		(0x1 << 14)
+#define RT5631_MUTE_MONO				(0x1 << 13)
+#define RT5631_MUTE_MONO_SHIFT			13
+#define RT5631_AUXOUT_2_VOL_SEL_MASK			(0x1 << 6)
+#define RT5631_AUXOUT_2_VOL_SEL_VMID			(0x0 << 6)
+#define RT5631_AUXOUT_2_VOL_SEL_OUTMIX_R		(0x1 << 6)
+
+/* Microphone Input Control 1(0x0E) */
+#define RT5631_MIC1_DIFF_INPUT_CTRL			(0x1 << 15)
+#define RT5631_MIC1_DIFF_INPUT_SHIFT			15
+#define RT5631_MIC2_DIFF_INPUT_CTRL			(0x1 << 7)
+#define RT5631_MIC2_DIFF_INPUT_SHIFT			7
+
+/* Stereo DAC Digital Volume2(0x10) */
+#define RT5631_DAC_VOL_MASK				0xff
+
+/* ADC Recording Mixer Control(0x14) */
+#define RT5631_M_OUTMIXER_L_TO_RECMIXER_L		(0x1 << 15)
+#define RT5631_M_OUTMIXL_RECMIXL_BIT			15
+#define RT5631_M_MIC1_TO_RECMIXER_L			(0x1 << 14)
+#define RT5631_M_MIC1_RECMIXL_BIT			14
+#define RT5631_M_AXIL_TO_RECMIXER_L			(0x1 << 13)
+#define RT5631_M_AXIL_RECMIXL_BIT			13
+#define RT5631_M_MONO_IN_TO_RECMIXER_L		(0x1 << 12)
+#define RT5631_M_MONO_IN_RECMIXL_BIT			12
+#define RT5631_M_OUTMIXER_R_TO_RECMIXER_R		(0x1 << 7)
+#define RT5631_M_OUTMIXR_RECMIXR_BIT			7
+#define RT5631_M_MIC2_TO_RECMIXER_R			(0x1 << 6)
+#define RT5631_M_MIC2_RECMIXR_BIT			6
+#define RT5631_M_AXIR_TO_RECMIXER_R			(0x1 << 5)
+#define RT5631_M_AXIR_RECMIXR_BIT			5
+#define RT5631_M_MONO_IN_TO_RECMIXER_R		(0x1 << 4)
+#define RT5631_M_MONO_IN_RECMIXR_BIT			4
+
+/* Left Output Mixer Control(0x1A) */
+#define RT5631_M_RECMIXER_L_TO_OUTMIXER_L		(0x1 << 15)
+#define RT5631_M_RECMIXL_OUTMIXL_BIT			15
+#define RT5631_M_RECMIXER_R_TO_OUTMIXER_L		(0x1 << 14)
+#define RT5631_M_RECMIXR_OUTMIXL_BIT			14
+#define RT5631_M_DAC_L_TO_OUTMIXER_L			(0x1 << 13)
+#define RT5631_M_DACL_OUTMIXL_BIT			13
+#define RT5631_M_MIC1_TO_OUTMIXER_L			(0x1 << 12)
+#define RT5631_M_MIC1_OUTMIXL_BIT			12
+#define RT5631_M_MIC2_TO_OUTMIXER_L			(0x1 << 11)
+#define RT5631_M_MIC2_OUTMIXL_BIT			11
+#define RT5631_M_MONO_IN_P_TO_OUTMIXER_L		(0x1 << 10)
+#define RT5631_M_MONO_INP_OUTMIXL_BIT		10
+#define RT5631_M_AXIL_TO_OUTMIXER_L			(0x1 << 9)
+#define RT5631_M_AXIL_OUTMIXL_BIT			9
+#define RT5631_M_AXIR_TO_OUTMIXER_L			(0x1 << 8)
+#define RT5631_M_AXIR_OUTMIXL_BIT			8
+#define RT5631_M_VDAC_TO_OUTMIXER_L			(0x1 << 7)
+#define RT5631_M_VDAC_OUTMIXL_BIT			7
+
+/* Right Output Mixer Control(0x1C) */
+#define RT5631_M_RECMIXER_L_TO_OUTMIXER_R		(0x1 << 15)
+#define RT5631_M_RECMIXL_OUTMIXR_BIT			15
+#define RT5631_M_RECMIXER_R_TO_OUTMIXER_R		(0x1 << 14)
+#define RT5631_M_RECMIXR_OUTMIXR_BIT			14
+#define RT5631_M_DAC_R_TO_OUTMIXER_R			(0x1 << 13)
+#define RT5631_M_DACR_OUTMIXR_BIT			13
+#define RT5631_M_MIC1_TO_OUTMIXER_R			(0x1 << 12)
+#define RT5631_M_MIC1_OUTMIXR_BIT			12
+#define RT5631_M_MIC2_TO_OUTMIXER_R			(0x1 << 11)
+#define RT5631_M_MIC2_OUTMIXR_BIT			11
+#define RT5631_M_MONO_IN_N_TO_OUTMIXER_R		(0x1 << 10)
+#define RT5631_M_MONO_INN_OUTMIXR_BIT		10
+#define RT5631_M_AXIL_TO_OUTMIXER_R			(0x1 << 9)
+#define RT5631_M_AXIL_OUTMIXR_BIT			9
+#define RT5631_M_AXIR_TO_OUTMIXER_R			(0x1 << 8)
+#define RT5631_M_AXIR_OUTMIXR_BIT			8
+#define RT5631_M_VDAC_TO_OUTMIXER_R			(0x1 << 7)
+#define RT5631_M_VDAC_OUTMIXR_BIT			7
+
+/* Lout Mixer Control(0x1E) */
+#define RT5631_M_MIC1_TO_AXO1MIXER			(0x1 << 15)
+#define RT5631_M_MIC1_AXO1MIX_BIT			15
+#define RT5631_M_MIC2_TO_AXO1MIXER			(0x1 << 11)
+#define RT5631_M_MIC2_AXO1MIX_BIT			11
+#define RT5631_M_OUTMIXER_L_TO_AXO1MIXER		(0x1 << 7)
+#define RT5631_M_OUTMIXL_AXO1MIX_BIT			7
+#define RT5631_M_OUTMIXER_R_TO_AXO1MIXER		(0x1 << 6)
+#define RT5631_M_OUTMIXR_AXO1MIX_BIT			6
+
+/* Rout Mixer Control(0x20) */
+#define RT5631_M_MIC1_TO_AXO2MIXER			(0x1 << 15)
+#define RT5631_M_MIC1_AXO2MIX_BIT			15
+#define RT5631_M_MIC2_TO_AXO2MIXER			(0x1 << 11)
+#define RT5631_M_MIC2_AXO2MIX_BIT			11
+#define RT5631_M_OUTMIXER_L_TO_AXO2MIXER		(0x1 << 7)
+#define RT5631_M_OUTMIXL_AXO2MIX_BIT			7
+#define RT5631_M_OUTMIXER_R_TO_AXO2MIXER		(0x1 << 6)
+#define RT5631_M_OUTMIXR_AXO2MIX_BIT			6
+
+/* Micphone Input Control 2(0x22) */
+#define RT5631_MIC_BIAS_90_PRECNET_AVDD 1
+#define RT5631_MIC_BIAS_75_PRECNET_AVDD 2
+
+#define RT5631_MIC1_BOOST_CTRL_MASK			(0xf << 12)
+#define RT5631_MIC1_BOOST_CTRL_BYPASS		(0x0 << 12)
+#define RT5631_MIC1_BOOST_CTRL_20DB			(0x1 << 12)
+#define RT5631_MIC1_BOOST_CTRL_24DB			(0x2 << 12)
+#define RT5631_MIC1_BOOST_CTRL_30DB			(0x3 << 12)
+#define RT5631_MIC1_BOOST_CTRL_35DB			(0x4 << 12)
+#define RT5631_MIC1_BOOST_CTRL_40DB			(0x5 << 12)
+#define RT5631_MIC1_BOOST_CTRL_34DB			(0x6 << 12)
+#define RT5631_MIC1_BOOST_CTRL_50DB			(0x7 << 12)
+#define RT5631_MIC1_BOOST_CTRL_52DB			(0x8 << 12)
+#define RT5631_MIC1_BOOST_SHIFT			12
+
+#define RT5631_MIC2_BOOST_CTRL_MASK			(0xf << 8)
+#define RT5631_MIC2_BOOST_CTRL_BYPASS		(0x0 << 8)
+#define RT5631_MIC2_BOOST_CTRL_20DB			(0x1 << 8)
+#define RT5631_MIC2_BOOST_CTRL_24DB			(0x2 << 8)
+#define RT5631_MIC2_BOOST_CTRL_30DB			(0x3 << 8)
+#define RT5631_MIC2_BOOST_CTRL_35DB			(0x4 << 8)
+#define RT5631_MIC2_BOOST_CTRL_40DB			(0x5 << 8)
+#define RT5631_MIC2_BOOST_CTRL_34DB			(0x6 << 8)
+#define RT5631_MIC2_BOOST_CTRL_50DB			(0x7 << 8)
+#define RT5631_MIC2_BOOST_CTRL_52DB			(0x8 << 8)
+#define RT5631_MIC2_BOOST_SHIFT			8
+
+#define RT5631_MICBIAS1_VOLT_CTRL_MASK		(0x1 << 7)
+#define RT5631_MICBIAS1_VOLT_CTRL_90P			(0x0 << 7)
+#define RT5631_MICBIAS1_VOLT_CTRL_75P			(0x1 << 7)
+
+#define RT5631_MICBIAS1_S_C_DET_MASK			(0x1 << 6)
+#define RT5631_MICBIAS1_S_C_DET_DIS			(0x0 << 6)
+#define RT5631_MICBIAS1_S_C_DET_ENA			(0x1 << 6)
+
+#define RT5631_MICBIAS1_SHORT_CURR_DET_MASK		(0x3 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_600UA	(0x0 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_1500UA	(0x1 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_2000UA	(0x2 << 4)
+
+#define RT5631_MICBIAS2_VOLT_CTRL_MASK		(0x1 << 3)
+#define RT5631_MICBIAS2_VOLT_CTRL_90P			(0x0 << 3)
+#define RT5631_MICBIAS2_VOLT_CTRL_75P			(0x1 << 3)
+
+#define RT5631_MICBIAS2_S_C_DET_MASK			(0x1 << 2)
+#define RT5631_MICBIAS2_S_C_DET_DIS			(0x0 << 2)
+#define RT5631_MICBIAS2_S_C_DET_ENA			(0x1 << 2)
+
+#define RT5631_MICBIAS2_SHORT_CURR_DET_MASK		(0x3)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_600UA	(0x0)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_1500UA	(0x1)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_2000UA	(0x2)
+
+
+/* Digital Microphone Control(0x24) */
+#define RT5631_DMIC_ENA_MASK				(0x1 << 15)
+#define RT5631_DMIC_ENA_SHIFT				15
+/* DMIC_ENA: DMIC to ADC Digital filter */
+#define RT5631_DMIC_ENA				(0x1 << 15)
+/* DMIC_DIS: ADC mixer to ADC Digital filter */
+#define RT5631_DMIC_DIS					(0x0 << 15)
+#define RT5631_DMIC_L_CH_MUTE				(0x1 << 13)
+#define RT5631_DMIC_L_CH_MUTE_SHIFT			13
+#define RT5631_DMIC_R_CH_MUTE				(0x1 << 12)
+#define RT5631_DMIC_R_CH_MUTE_SHIFT			12
+#define RT5631_DMIC_L_CH_LATCH_MASK			(0x1 << 9)
+#define RT5631_DMIC_L_CH_LATCH_RISING			(0x1 << 9)
+#define RT5631_DMIC_L_CH_LATCH_FALLING		(0x0 << 9)
+#define RT5631_DMIC_R_CH_LATCH_MASK			(0x1 << 8)
+#define RT5631_DMIC_R_CH_LATCH_RISING			(0x1 << 8)
+#define RT5631_DMIC_R_CH_LATCH_FALLING		(0x0 << 8)
+#define RT5631_DMIC_CLK_CTRL_MASK			(0x3 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_128FS			(0x0 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_64FS			(0x1 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_32FS			(0x2 << 4)
+
+/* Microphone Input Volume(0x26) */
+#define RT5631_MONO_DIFF_INPUT_SHIFT			15
+
+/* Speaker Mixer Control(0x28) */
+#define RT5631_M_RECMIXER_L_TO_SPKMIXER_L		(0x1 << 15)
+#define RT5631_M_RECMIXL_SPKMIXL_BIT			15
+#define RT5631_M_MIC1_P_TO_SPKMIXER_L		(0x1 << 14)
+#define RT5631_M_MIC1P_SPKMIXL_BIT			14
+#define RT5631_M_DAC_L_TO_SPKMIXER_L			(0x1 << 13)
+#define RT5631_M_DACL_SPKMIXL_BIT			13
+#define RT5631_M_OUTMIXER_L_TO_SPKMIXER_L		(0x1 << 12)
+#define RT5631_M_OUTMIXL_SPKMIXL_BIT			12
+
+#define RT5631_M_RECMIXER_R_TO_SPKMIXER_R		(0x1 << 7)
+#define RT5631_M_RECMIXR_SPKMIXR_BIT			7
+#define RT5631_M_MIC2_P_TO_SPKMIXER_R		(0x1 << 6)
+#define RT5631_M_MIC2P_SPKMIXR_BIT			6
+#define RT5631_M_DAC_R_TO_SPKMIXER_R			(0x1 << 5)
+#define RT5631_M_DACR_SPKMIXR_BIT			5
+#define RT5631_M_OUTMIXER_R_TO_SPKMIXER_R		(0x1 << 4)
+#define RT5631_M_OUTMIXR_SPKMIXR_BIT			4
+
+/* Speaker/Mono Output Control(0x2A) */
+#define RT5631_M_SPKVOL_L_TO_SPOL_MIXER		(0x1 << 15)
+#define RT5631_M_SPKVOLL_SPOLMIX_BIT			15
+#define RT5631_M_SPKVOL_R_TO_SPOL_MIXER		(0x1 << 14)
+#define RT5631_M_SPKVOLR_SPOLMIX_BIT			14
+#define RT5631_M_SPKVOL_L_TO_SPOR_MIXER		(0x1 << 13)
+#define RT5631_M_SPKVOLL_SPORMIX_BIT			13
+#define RT5631_M_SPKVOL_R_TO_SPOR_MIXER		(0x1 << 12)
+#define RT5631_M_SPKVOLR_SPORMIX_BIT			12
+#define RT5631_M_OUTVOL_L_TO_MONOMIXER		(0x1 << 11)
+#define RT5631_M_OUTVOLL_MONOMIX_BIT			11
+#define RT5631_M_OUTVOL_R_TO_MONOMIXER		(0x1 << 10)
+#define RT5631_M_OUTVOLR_MONOMIX_BIT			10
+
+/* Speaker/Mono/HP Output Control(0x2C) */
+#define RT5631_SPK_L_MUX_SEL_MASK			(0x3 << 14)
+#define RT5631_SPK_L_MUX_SEL_SPKMIXER_L		(0x0 << 14)
+#define RT5631_SPK_L_MUX_SEL_MONO_IN			(0x1 << 14)
+#define RT5631_SPK_L_MUX_SEL_DAC_L			(0x3 << 14)
+#define RT5631_SPK_L_MUX_SEL_SHIFT			14
+
+#define RT5631_SPK_R_MUX_SEL_MASK			(0x3 << 10)
+#define RT5631_SPK_R_MUX_SEL_SPKMIXER_R		(0x0 << 10)
+#define RT5631_SPK_R_MUX_SEL_MONO_IN			(0x1 << 10)
+#define RT5631_SPK_R_MUX_SEL_DAC_R			(0x3 << 10)
+#define RT5631_SPK_R_MUX_SEL_SHIFT			10
+
+#define RT5631_MONO_MUX_SEL_MASK			(0x3 << 6)
+#define RT5631_MONO_MUX_SEL_MONOMIXER		(0x0 << 6)
+#define RT5631_MONO_MUX_SEL_MONO_IN			(0x1 << 6)
+#define RT5631_MONO_MUX_SEL_SHIFT			6
+
+#define RT5631_HP_L_MUX_SEL_MASK			(0x1 << 3)
+#define RT5631_HP_L_MUX_SEL_HPVOL_L			(0x0 << 3)
+#define RT5631_HP_L_MUX_SEL_DAC_L			(0x1 << 3)
+#define RT5631_HP_L_MUX_SEL_SHIFT			3
+
+#define RT5631_HP_R_MUX_SEL_MASK			(0x1 << 2)
+#define RT5631_HP_R_MUX_SEL_HPVOL_R			(0x0 << 2)
+#define RT5631_HP_R_MUX_SEL_DAC_R			(0x1 << 2)
+#define RT5631_HP_R_MUX_SEL_SHIFT			2
+
+/* Stereo I2S Serial Data Port Control(0x34) */
+#define RT5631_SDP_MODE_SEL_MASK			(0x1 << 15)
+#define RT5631_SDP_MODE_SEL_MASTER			(0x0 << 15)
+#define RT5631_SDP_MODE_SEL_SLAVE			(0x1 << 15)
+
+#define RT5631_SDP_ADC_CPS_SEL_MASK			(0x3 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_OFF			(0x0 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_U_LAW			(0x1 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_A_LAW			(0x2 << 10)
+
+#define RT5631_SDP_DAC_CPS_SEL_MASK			(0x3 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_OFF			(0x0 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_U_LAW			(0x1 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_A_LAW			(0x2 << 8)
+/* 0:Normal 1:Invert */
+#define RT5631_SDP_I2S_BCLK_POL_CTRL			(0x1 << 7)
+/* 0:Normal 1:Invert */
+#define RT5631_SDP_DAC_R_INV				(0x1 << 6)
+/* 0:ADC data appear at left phase of LRCK
+ * 1:ADC data appear at right phase of LRCK
+ */
+#define RT5631_SDP_ADC_DATA_L_R_SWAP			(0x1 << 5)
+/* 0:DAC data appear at left phase of LRCK
+ * 1:DAC data appear at right phase of LRCK
+ */
+#define RT5631_SDP_DAC_DATA_L_R_SWAP			(0x1 << 4)
+
+/* Data Length Slection */
+#define RT5631_SDP_I2S_DL_MASK				(0x3 << 2)
+#define RT5631_SDP_I2S_DL_16				(0x0 << 2)
+#define RT5631_SDP_I2S_DL_20				(0x1 << 2)
+#define RT5631_SDP_I2S_DL_24				(0x2 << 2)
+#define RT5631_SDP_I2S_DL_8				(0x3 << 2)
+
+/* PCM Data Format Selection */
+#define RT5631_SDP_I2S_DF_MASK				(0x3)
+#define RT5631_SDP_I2S_DF_I2S				(0x0)
+#define RT5631_SDP_I2S_DF_LEFT				(0x1)
+#define RT5631_SDP_I2S_DF_PCM_A			(0x2)
+#define RT5631_SDP_I2S_DF_PCM_B			(0x3)
+
+/* Stereo AD/DA Clock Control(0x38h) */
+#define RT5631_I2S_PRE_DIV_MASK			(0x7 << 13)
+#define RT5631_I2S_PRE_DIV_1				(0x0 << 13)
+#define RT5631_I2S_PRE_DIV_2				(0x1 << 13)
+#define RT5631_I2S_PRE_DIV_4				(0x2 << 13)
+#define RT5631_I2S_PRE_DIV_8				(0x3 << 13)
+#define RT5631_I2S_PRE_DIV_16				(0x4 << 13)
+#define RT5631_I2S_PRE_DIV_32				(0x5 << 13)
+/* CLOCK RELATIVE OF BCLK AND LCRK */
+#define RT5631_I2S_LRCK_SEL_N_BCLK_MASK		(0x1 << 12)
+#define RT5631_I2S_LRCK_SEL_64_BCLK			(0x0 << 12) /* 64FS */
+#define RT5631_I2S_LRCK_SEL_32_BCLK			(0x1 << 12) /* 32FS */
+
+#define RT5631_DAC_OSR_SEL_MASK			(0x3 << 10)
+#define RT5631_DAC_OSR_SEL_128FS			(0x3 << 10)
+#define RT5631_DAC_OSR_SEL_64FS			(0x3 << 10)
+#define RT5631_DAC_OSR_SEL_32FS			(0x3 << 10)
+#define RT5631_DAC_OSR_SEL_16FS			(0x3 << 10)
+
+#define RT5631_ADC_OSR_SEL_MASK			(0x3 << 8)
+#define RT5631_ADC_OSR_SEL_128FS			(0x3 << 8)
+#define RT5631_ADC_OSR_SEL_64FS			(0x3 << 8)
+#define RT5631_ADC_OSR_SEL_32FS			(0x3 << 8)
+#define RT5631_ADC_OSR_SEL_16FS			(0x3 << 8)
+
+#define RT5631_ADDA_FILTER_CLK_SEL_256FS		(0 << 7) /* 256FS */
+#define RT5631_ADDA_FILTER_CLK_SEL_384FS		(1 << 7) /* 384FS */
+
+/* Power managment addition 1 (0x3A) */
+#define RT5631_PWR_MAIN_I2S_EN			(0x1 << 15)
+#define RT5631_PWR_MAIN_I2S_BIT			15
+#define RT5631_PWR_CLASS_D				(0x1 << 12)
+#define RT5631_PWR_CLASS_D_BIT			12
+#define RT5631_PWR_ADC_L_CLK				(0x1 << 11)
+#define RT5631_PWR_ADC_L_CLK_BIT			11
+#define RT5631_PWR_ADC_R_CLK				(0x1 << 10)
+#define RT5631_PWR_ADC_R_CLK_BIT			10
+#define RT5631_PWR_DAC_L_CLK				(0x1 << 9)
+#define RT5631_PWR_DAC_L_CLK_BIT			9
+#define RT5631_PWR_DAC_R_CLK				(0x1 << 8)
+#define RT5631_PWR_DAC_R_CLK_BIT			8
+#define RT5631_PWR_DAC_REF				(0x1 << 7)
+#define RT5631_PWR_DAC_REF_BIT			7
+#define RT5631_PWR_DAC_L_TO_MIXER			(0x1 << 6)
+#define RT5631_PWR_DAC_L_TO_MIXER_BIT		6
+#define RT5631_PWR_DAC_R_TO_MIXER			(0x1 << 5)
+#define RT5631_PWR_DAC_R_TO_MIXER_BIT		5
+
+/* Power managment addition 2 (0x3B) */
+#define RT5631_PWR_OUTMIXER_L				(0x1 << 15)
+#define RT5631_PWR_OUTMIXER_L_BIT			15
+#define RT5631_PWR_OUTMIXER_R				(0x1 << 14)
+#define RT5631_PWR_OUTMIXER_R_BIT			14
+#define RT5631_PWR_SPKMIXER_L				(0x1 << 13)
+#define RT5631_PWR_SPKMIXER_L_BIT			13
+#define RT5631_PWR_SPKMIXER_R				(0x1 << 12)
+#define RT5631_PWR_SPKMIXER_R_BIT			12
+#define RT5631_PWR_RECMIXER_L				(0x1 << 11)
+#define RT5631_PWR_RECMIXER_L_BIT			11
+#define RT5631_PWR_RECMIXER_R				(0x1 << 10)
+#define RT5631_PWR_RECMIXER_R_BIT			10
+#define RT5631_PWR_MIC1_BOOT_GAIN			(0x1 << 5)
+#define RT5631_PWR_MIC1_BOOT_GAIN_BIT		5
+#define RT5631_PWR_MIC2_BOOT_GAIN			(0x1 << 4)
+#define RT5631_PWR_MIC2_BOOT_GAIN_BIT		4
+#define RT5631_PWR_MICBIAS1_VOL			(0x1 << 3)
+#define RT5631_PWR_MICBIAS1_VOL_BIT			3
+#define RT5631_PWR_MICBIAS2_VOL			(0x1 << 2)
+#define RT5631_PWR_MICBIAS2_VOL_BIT			2
+#define RT5631_PWR_PLL1				(0x1 << 1)
+#define RT5631_PWR_PLL1_BIT				1
+#define RT5631_PWR_PLL2				(0x1 << 0)
+#define RT5631_PWR_PLL2_BIT				0
+
+/* Power managment addition 3(0x3C) */
+#define RT5631_PWR_VREF				(0x1 << 15)
+#define RT5631_PWR_VREF_BIT				15
+#define RT5631_PWR_FAST_VREF_CTRL			(0x1 << 14)
+#define RT5631_PWR_FAST_VREF_CTRL_BIT			14
+#define RT5631_PWR_MAIN_BIAS				(0x1 << 13)
+#define RT5631_PWR_MAIN_BIAS_BIT			13
+#define RT5631_PWR_AXO1MIXER				(0x1 << 11)
+#define RT5631_PWR_AXO1MIXER_BIT			11
+#define RT5631_PWR_AXO2MIXER				(0x1 << 10)
+#define RT5631_PWR_AXO2MIXER_BIT			10
+#define RT5631_PWR_MONOMIXER				(0x1 << 9)
+#define RT5631_PWR_MONOMIXER_BIT			9
+#define RT5631_PWR_MONO_DEPOP_DIS			(0x1 << 8)
+#define RT5631_PWR_MONO_DEPOP_DIS_BIT		8
+#define RT5631_PWR_MONO_AMP_EN			(0x1 << 7)
+#define RT5631_PWR_MONO_AMP_EN_BIT			7
+#define RT5631_PWR_CHARGE_PUMP			(0x1 << 4)
+#define RT5631_PWR_CHARGE_PUMP_BIT			4
+#define RT5631_PWR_HP_L_AMP				(0x1 << 3)
+#define RT5631_PWR_HP_L_AMP_BIT			3
+#define RT5631_PWR_HP_R_AMP				(0x1 << 2)
+#define RT5631_PWR_HP_R_AMP_BIT			2
+#define RT5631_PWR_HP_DEPOP_DIS			(0x1 << 1)
+#define RT5631_PWR_HP_DEPOP_DIS_BIT			1
+#define RT5631_PWR_HP_AMP_DRIVING			(0x1 << 0)
+#define RT5631_PWR_HP_AMP_DRIVING_BIT		0
+
+/* Power managment addition 4(0x3E) */
+#define RT5631_PWR_SPK_L_VOL				(0x1 << 15)
+#define RT5631_PWR_SPK_L_VOL_BIT			15
+#define RT5631_PWR_SPK_R_VOL				(0x1 << 14)
+#define RT5631_PWR_SPK_R_VOL_BIT			14
+#define RT5631_PWR_LOUT_VOL				(0x1 << 13)
+#define RT5631_PWR_LOUT_VOL_BIT			13
+#define RT5631_PWR_ROUT_VOL				(0x1 << 12)
+#define RT5631_PWR_ROUT_VOL_BIT			12
+#define RT5631_PWR_HP_L_OUT_VOL			(0x1 << 11)
+#define RT5631_PWR_HP_L_OUT_VOL_BIT			11
+#define RT5631_PWR_HP_R_OUT_VOL			(0x1 << 10)
+#define RT5631_PWR_HP_R_OUT_VOL_BIT			10
+#define RT5631_PWR_AXIL_IN_VOL				(0x1 << 9)
+#define RT5631_PWR_AXIL_IN_VOL_BIT			9
+#define RT5631_PWR_AXIR_IN_VOL			(0x1 << 8)
+#define RT5631_PWR_AXIR_IN_VOL_BIT			8
+#define RT5631_PWR_MONO_IN_P_VOL			(0x1 << 7)
+#define RT5631_PWR_MONO_IN_P_VOL_BIT			7
+#define RT5631_PWR_MONO_IN_N_VOL			(0x1 << 6)
+#define RT5631_PWR_MONO_IN_N_VOL_BIT			6
+
+/* General Purpose Control Register(0x40) */
+#define RT5631_SPK_AMP_AUTO_RATIO_EN			(0x1 << 15)
+
+#define RT5631_SPK_AMP_RATIO_CTRL_MASK		(0x7 << 12)
+#define RT5631_SPK_AMP_RATIO_CTRL_2_34		(0x0 << 12) /* 7.40DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_99		(0x1 << 12) /* 5.99DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_68		(0x2 << 12) /* 4.50DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_56		(0x3 << 12) /* 3.86DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_44		(0x4 << 12) /* 3.16DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_27		(0x5 << 12) /* 2.10DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_09		(0x6 << 12) /* 0.80DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_00		(0x7 << 12) /* 0.00DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_SHIFT		12
+
+#define RT5631_STEREO_DAC_HI_PASS_FILT_EN		(0x1 << 11)
+#define RT5631_STEREO_ADC_HI_PASS_FILT_EN		(0x1 << 10)
+/* Select ADC Wind Filter Clock type */
+#define RT5631_ADC_WIND_FILT_MASK			(0x3 << 4)
+#define RT5631_ADC_WIND_FILT_8_16_32K			(0x0 << 4) /*8/16/32k*/
+#define RT5631_ADC_WIND_FILT_11_22_44K		(0x1 << 4) /*11/22/44k*/
+#define RT5631_ADC_WIND_FILT_12_24_48K		(0x2 << 4) /*12/24/48k*/
+#define RT5631_ADC_WIND_FILT_EN			(0x1 << 3)
+/* SelectADC Wind Filter Corner Frequency */
+#define RT5631_ADC_WIND_CNR_FREQ_MASK	(0x7 << 0)
+#define RT5631_ADC_WIND_CNR_FREQ_82_113_122	(0x0 << 0) /* 82/113/122 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_102_141_153 (0x1 << 0) /* 102/141/153 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_131_180_156 (0x2 << 0) /* 131/180/156 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_163_225_245 (0x3 << 0) /* 163/225/245 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_204_281_306 (0x4 << 0) /* 204/281/306 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_261_360_392 (0x5 << 0) /* 261/360/392 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_327_450_490 (0x6 << 0) /* 327/450/490 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_408_563_612 (0x7 << 0) /* 408/563/612 Hz */
+
+/* Global Clock Control Register(0x42) */
+#define RT5631_SYSCLK_SOUR_SEL_MASK			(0x3 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_MCLK			(0x0 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_PLL			(0x1 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_PLL_TCK		(0x2 << 14)
+
+#define RT5631_PLLCLK_SOUR_SEL_MASK			(0x3 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_MCLK			(0x0 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_BCLK			(0x1 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_VBCLK			(0x2 << 12)
+
+#define RT5631_PLLCLK_PRE_DIV1				(0x0 << 11)
+#define RT5631_PLLCLK_PRE_DIV2				(0x1 << 11)
+
+/* PLL Control(0x44) */
+#define RT5631_PLL_CTRL_M_VAL(m)			((m)&0xf)
+#define RT5631_PLL_CTRL_K_VAL(k)			(((k)&0x7) << 4)
+#define RT5631_PLL_CTRL_N_VAL(n)			(((n)&0xff) << 8)
+
+/* Internal Status and IRQ Control2(0x4A) */
+#define RT5631_ADC_DATA_SEL_MASK			(0x3 << 14)
+#define RT5631_ADC_DATA_SEL_Disable			(0x0 << 14)
+#define RT5631_ADC_DATA_SEL_MIC1			(0x1 << 14)
+#define RT5631_ADC_DATA_SEL_MIC1_SHIFT		14
+#define RT5631_ADC_DATA_SEL_MIC2			(0x2 << 14)
+#define RT5631_ADC_DATA_SEL_MIC2_SHIFT		15
+#define RT5631_ADC_DATA_SEL_STO			(0x3 << 14)
+#define RT5631_ADC_DATA_SEL_SHIFT			14
+
+/* GPIO Pin Configuration(0x4C) */
+#define RT5631_GPIO_PIN_FUN_SEL_MASK			(0x1 << 15)
+#define RT5631_GPIO_PIN_FUN_SEL_IRQ			(0x1 << 15)
+#define RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC		(0x0 << 15)
+
+#define RT5631_GPIO_DMIC_FUN_SEL_MASK		(0x1 << 3)
+#define RT5631_GPIO_DMIC_FUN_SEL_DIMC		(0x1 << 3)
+#define RT5631_GPIO_DMIC_FUN_SEL_GPIO			(0x0 << 3)
+
+#define RT5631_GPIO_PIN_CON_MASK			(0x1 << 2)
+#define RT5631_GPIO_PIN_SET_INPUT			(0x0 << 2)
+#define RT5631_GPIO_PIN_SET_OUTPUT			(0x1 << 2)
+
+/* De-POP function Control 1(0x54) */
+#define RT5631_POW_ON_SOFT_GEN			(0x1 << 15)
+#define RT5631_EN_MUTE_UNMUTE_DEPOP			(0x1 << 14)
+#define RT5631_EN_DEPOP2_FOR_HP			(0x1 << 7)
+/* Power Down HPAMP_L Starts Up Signal */
+#define RT5631_PD_HPAMP_L_ST_UP			(0x1 << 5)
+/* Power Down HPAMP_R Starts Up Signal */
+#define RT5631_PD_HPAMP_R_ST_UP			(0x1 << 4)
+/* Enable left HP mute/unmute depop */
+#define RT5631_EN_HP_L_M_UN_MUTE_DEPOP		(0x1 << 1)
+/* Enable right HP mute/unmute depop */
+#define RT5631_EN_HP_R_M_UN_MUTE_DEPOP		(0x1 << 0)
+
+/* De-POP Fnction Control(0x56) */
+#define RT5631_EN_ONE_BIT_DEPOP			(0x1 << 15)
+#define RT5631_EN_CAP_FREE_DEPOP			(0x1 << 14)
+
+/* Jack Detect Control Register(0x5A) */
+#define RT5631_JD_USE_MASK				(0x3 << 14)
+#define RT5631_JD_USE_JD2				(0x3 << 14)
+#define RT5631_JD_USE_JD1				(0x2 << 14)
+#define RT5631_JD_USE_GPIO				(0x1 << 14)
+#define RT5631_JD_OFF					(0x0 << 14)
+/* JD trigger enable for HP */
+#define RT5631_JD_HP_EN					(0x1 << 11)
+#define RT5631_JD_HP_TRI_MASK				(0x1 << 10)
+#define RT5631_JD_HP_TRI_HI				(0x1 << 10)
+#define RT5631_JD_HP_TRI_LO				(0x1 << 10)
+/* JD trigger enable for speaker LP/LN */
+#define RT5631_JD_SPK_L_EN				(0x1 << 9)
+#define RT5631_JD_SPK_L_TRI_MASK			(0x1 << 8)
+#define RT5631_JD_SPK_L_TRI_HI				(0x1 << 8)
+#define RT5631_JD_SPK_L_TRI_LO				(0x0 << 8)
+/* JD trigger enable for speaker RP/RN */
+#define RT5631_JD_SPK_R_EN				(0x1 << 7)
+#define RT5631_JD_SPK_R_TRI_MASK			(0x1 << 6)
+#define RT5631_JD_SPK_R_TRI_HI				(0x1 << 6)
+#define RT5631_JD_SPK_R_TRI_LO				(0x0 << 6)
+/* JD trigger enable for monoout */
+#define RT5631_JD_MONO_EN				(0x1 << 5)
+#define RT5631_JD_MONO_TRI_MASK			(0x1 << 4)
+#define RT5631_JD_MONO_TRI_HI				(0x1 << 4)
+#define RT5631_JD_MONO_TRI_LO				(0x0 << 4)
+/* JD trigger enable for Lout */
+#define RT5631_JD_AUX_1_EN				(0x1 << 3)
+#define RT5631_JD_AUX_1_MASK				(0x1 << 2)
+#define RT5631_JD_AUX_1_TRI_HI				(0x1 << 2)
+#define RT5631_JD_AUX_1_TRI_LO				(0x0 << 2)
+/* JD trigger enable for Rout */
+#define RT5631_JD_AUX_2_EN				(0x1 << 1)
+#define RT5631_JD_AUX_2_MASK				(0x1 << 0)
+#define RT5631_JD_AUX_2_TRI_HI				(0x1 << 0)
+#define RT5631_JD_AUX_2_TRI_LO				(0x0 << 0)
+
+/* ALC CONTROL 1(0x64) */
+#define RT5631_ALC_ATTACK_RATE_MASK			(0x1F << 8)
+#define RT5631_ALC_RECOVERY_RATE_MASK		(0x1F << 0)
+
+/* ALC CONTROL 2(0x65) */
+/* select Compensation gain for Noise gate function */
+#define RT5631_ALC_COM_NOISE_GATE_MASK		(0xF << 0)
+
+/* ALC CONTROL 3(0x66) */
+#define RT5631_ALC_FUN_MASK				(0x3 << 14)
+#define RT5631_ALC_FUN_DIS				(0x0 << 14)
+#define RT5631_ALC_ENA_DAC_PATH			(0x1 << 14)
+#define RT5631_ALC_ENA_ADC_PATH			(0x3 << 14)
+#define RT5631_ALC_PARA_UPDATE			(0x1 << 13)
+#define RT5631_ALC_LIMIT_LEVEL_MASK			(0x1F << 8)
+#define RT5631_ALC_NOISE_GATE_FUN_MASK		(0x1 << 7)
+#define RT5631_ALC_NOISE_GATE_FUN_DIS			(0x0 << 7)
+#define RT5631_ALC_NOISE_GATE_FUN_ENA		(0x1 << 7)
+/* ALC noise gate hold data function */
+#define RT5631_ALC_NOISE_GATE_H_D_MASK		(0x1 << 6)
+#define RT5631_ALC_NOISE_GATE_H_D_DIS			(0x0 << 6)
+#define RT5631_ALC_NOISE_GATE_H_D_ENA		(0x1 << 6)
+
+/* Psedueo Stereo & Spatial Effect Block Control(0x68) */
+#define RT5631_SPATIAL_CTRL_EN				(0x1 << 15)
+#define RT5631_ALL_PASS_FILTER_EN			(0x1 << 14)
+#define RT5631_PSEUDO_STEREO_EN			(0x1 << 13)
+#define RT5631_STEREO_EXPENSION_EN			(0x1 << 12)
+/* 3D gain parameter */
+#define RT5631_GAIN_3D_PARA_MASK		(0x3 << 6)
+#define RT5631_GAIN_3D_PARA_1_00		(0x0 << 6) /* 3D gain 1.0 */
+#define RT5631_GAIN_3D_PARA_1_50		(0x1 << 6) /* 3D gain 1.5 */
+#define RT5631_GAIN_3D_PARA_2_00		(0x2 << 6) /* 3D gain 2.0 */
+/* 3D ratio parameter */
+#define RT5631_RATIO_3D_MASK			(0x3 << 4)
+#define RT5631_RATIO_3D_0_0			(0x0 << 4) /* 3D ratio 0.0 */
+#define RT5631_RATIO_3D_0_66			(0x1 << 4) /* 3D ratio 0.66 */
+#define RT5631_RATIO_3D_1_0			(0x2 << 4) /* 3D ratio 1.0 */
+/* select samplerate for all pass filter */
+#define RT5631_APF_FUN_SLE_MASK			(0x3 << 0)
+#define RT5631_APF_FUN_SEL_48K				(0x3 << 0)
+#define RT5631_APF_FUN_SEL_44_1K			(0x2 << 0)
+#define RT5631_APF_FUN_SEL_32K				(0x1 << 0)
+#define RT5631_APF_FUN_DIS				(0x0 << 0)
+
+/* EQ CONTROL 1(0x6E) */
+#define RT5631_HW_EQ_PATH_SEL_MASK			(0x1 << 15)
+#define RT5631_HW_EQ_PATH_SEL_DAC			(0x0 << 15)
+#define RT5631_HW_EQ_PATH_SEL_ADC			(0x1 << 15)
+#define RT5631_HW_EQ_UPDATE_CTRL			(0x1 << 14)
+
+#define RT5631_EN_HW_EQ_HPF2				(0x1 << 5)
+#define RT5631_EN_HW_EQ_HPF1				(0x1 << 4)
+#define RT5631_EN_HW_EQ_BP3				(0x1 << 3)
+#define RT5631_EN_HW_EQ_BP2				(0x1 << 2)
+#define RT5631_EN_HW_EQ_BP1				(0x1 << 1)
+#define RT5631_EN_HW_EQ_LPF				(0x1 << 0)
+
+
+#endif /* __RTCODEC5631_H__ */
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 91130fbc6913..d15695d1c273 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -131,16 +131,13 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
 	case SND_SOC_DAPM_POST_PMU:
 		/* change mic bias resistor to 4Kohm */
 		snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
-				SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k);
+				SGTL5000_BIAS_R_MASK,
+				SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT);
 		break;
 
 	case SND_SOC_DAPM_PRE_PMD:
-		/*
-		 * SGTL5000_BIAS_R_8k as mask to clean the two bits
-		 * of mic bias and output impedance
-		 */
 		snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
-				SGTL5000_BIAS_R_8k, 0);
+				SGTL5000_BIAS_R_MASK, 0);
 		break;
 	}
 	return 0;
@@ -726,7 +723,9 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl, i2s_ctl);
+	snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL,
+			    SGTL5000_I2S_DLEN_MASK | SGTL5000_I2S_SCLKFREQ_MASK,
+			    i2s_ctl);
 
 	return 0;
 }
@@ -757,7 +756,7 @@ static int ldo_regulator_enable(struct regulator_dev *dev)
 
 	/* set voltage to register */
 	snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
-				(0x1 << 4) - 1, reg);
+				SGTL5000_LINREG_VDDD_MASK, reg);
 
 	snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
 				SGTL5000_LINEREG_D_POWERUP,
@@ -783,7 +782,7 @@ static int ldo_regulator_disable(struct regulator_dev *dev)
 
 	/* clear voltage info */
 	snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
-				(0x1 << 4) - 1, 0);
+				SGTL5000_LINREG_VDDD_MASK, 0);
 
 	ldo->enabled = 0;
 
@@ -809,6 +808,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
 				int voltage)
 {
 	struct ldo_regulator *ldo;
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
 
 	ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
 
@@ -843,6 +843,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
 
 		return ret;
 	}
+	sgtl5000->ldo = ldo;
 
 	return 0;
 }
@@ -1116,7 +1117,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
 
 	/* set voltage to register */
 	snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
-				(0x1 << 4) - 1, 0x8);
+				SGTL5000_LINREG_VDDD_MASK, 0x8);
 
 	/*
 	 * if vddd linear reg has been enabled,
@@ -1147,8 +1148,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
 		vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP;
 
 	snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
-			vag << SGTL5000_ANA_GND_SHIFT,
-			vag << SGTL5000_ANA_GND_SHIFT);
+			SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT);
 
 	/* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */
 	vag = vddio / 2;
@@ -1162,9 +1162,8 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
 		    SGTL5000_LINE_OUT_GND_STP;
 
 	snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
-			vag << SGTL5000_LINE_OUT_GND_SHIFT |
-			SGTL5000_LINE_OUT_CURRENT_360u <<
-				SGTL5000_LINE_OUT_CURRENT_SHIFT,
+			SGTL5000_LINE_OUT_CURRENT_MASK |
+			SGTL5000_LINE_OUT_GND_MASK,
 			vag << SGTL5000_LINE_OUT_GND_SHIFT |
 			SGTL5000_LINE_OUT_CURRENT_360u <<
 				SGTL5000_LINE_OUT_CURRENT_SHIFT);
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h
index eec3ab368f39..8a9f43534b79 100644
--- a/sound/soc/codecs/sgtl5000.h
+++ b/sound/soc/codecs/sgtl5000.h
@@ -280,7 +280,7 @@
 /*
  * SGTL5000_CHIP_MIC_CTRL
  */
-#define SGTL5000_BIAS_R_MASK			0x0200
+#define SGTL5000_BIAS_R_MASK			0x0300
 #define SGTL5000_BIAS_R_SHIFT			8
 #define SGTL5000_BIAS_R_WIDTH			2
 #define SGTL5000_BIAS_R_off			0x0
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 29945b004135..f681e41fc12e 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -102,7 +102,7 @@ static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec)
 {
 	int base_addr, chnl_addr;
 	int value;
-	static int channel_index;
+	int channel_index;
 
 	/* Index of the first channel in which the stop bit is set */
 	channel_index = find_free_channel(sn95031_codec);
@@ -161,7 +161,6 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
 	pr_debug("mic bias = %dmV\n", mic_bias);
 	return mic_bias;
 }
-EXPORT_SYMBOL_GPL(sn95031_get_mic_bias);
 /*end - adc helper functions */
 
 static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
@@ -716,7 +715,7 @@ static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
 	.hw_params	= sn95031_pcm_hw_params,
 };
 
-struct snd_soc_dai_driver sn95031_dais[] = {
+static struct snd_soc_dai_driver sn95031_dais[] = {
 {
 	.name = "SN95031 Headset",
 	.playback = {
@@ -827,7 +826,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
 {
 	pr_debug("codec_probe called\n");
 
-	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
 	codec->dapm.idle_bias_off = 1;
 
 	/* PCM interface config
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 32d6c5141860..3cb3271c5fe2 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -59,6 +59,7 @@ struct ssm2602_priv {
 	struct snd_pcm_substream *slave_substream;
 
 	enum ssm2602_type type;
+	unsigned int clk_out_pwr;
 };
 
 /*
@@ -342,12 +343,14 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
 static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE;
+
 	if (mute)
-		snd_soc_write(codec, SSM2602_APDIGI,
-				mute_reg | APDIGI_ENABLE_DAC_MUTE);
+		snd_soc_update_bits(codec, SSM2602_APDIGI,
+				    APDIGI_ENABLE_DAC_MUTE,
+				    APDIGI_ENABLE_DAC_MUTE);
 	else
-		snd_soc_write(codec, SSM2602_APDIGI, mute_reg);
+		snd_soc_update_bits(codec, SSM2602_APDIGI,
+				    APDIGI_ENABLE_DAC_MUTE, 0);
 	return 0;
 }
 
@@ -356,16 +359,46 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
 	struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-	switch (freq) {
-	case 11289600:
-	case 12000000:
-	case 12288000:
-	case 16934400:
-	case 18432000:
-		ssm2602->sysclk = freq;
-		return 0;
+
+	if (dir == SND_SOC_CLOCK_IN) {
+		if (clk_id != SSM2602_SYSCLK)
+			return -EINVAL;
+
+		switch (freq) {
+		case 11289600:
+		case 12000000:
+		case 12288000:
+		case 16934400:
+		case 18432000:
+			ssm2602->sysclk = freq;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		unsigned int mask;
+
+		switch (clk_id) {
+		case SSM2602_CLK_CLKOUT:
+			mask = PWR_CLK_OUT_PDN;
+			break;
+		case SSM2602_CLK_XTO:
+			mask = PWR_OSC_PDN;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if (freq == 0)
+			ssm2602->clk_out_pwr |= mask;
+		else
+			ssm2602->clk_out_pwr &= ~mask;
+
+		snd_soc_update_bits(codec, SSM2602_PWR,
+			PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
 	}
-	return -EINVAL;
+
+	return 0;
 }
 
 static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -430,23 +463,27 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
 static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
-	u16 reg = snd_soc_read(codec, SSM2602_PWR);
-	reg &= ~(PWR_POWER_OFF | PWR_OSC_PDN);
+	struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		/* vref/mid, osc on, dac unmute */
-		snd_soc_write(codec, SSM2602_PWR, reg);
+		/* vref/mid on, osc and clkout on if enabled */
+		snd_soc_update_bits(codec, SSM2602_PWR,
+			PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
+			ssm2602->clk_out_pwr);
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
 		/* everything off except vref/vmid, */
-		snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
+		snd_soc_update_bits(codec, SSM2602_PWR,
+			PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
+			PWR_CLK_OUT_PDN | PWR_OSC_PDN);
 		break;
 	case SND_SOC_BIAS_OFF:
-		/* everything off, dac mute, inactive */
-		snd_soc_write(codec, SSM2602_PWR, 0xffff);
+		/* everything off */
+		snd_soc_update_bits(codec, SSM2602_PWR,
+			PWR_POWER_OFF, PWR_POWER_OFF);
 		break;
 
 	}
@@ -505,12 +542,12 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
 static int ssm2602_probe(struct snd_soc_codec *codec)
 {
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int ret, reg;
+	int ret;
 
-	reg = snd_soc_read(codec, SSM2602_LOUT1V);
-	snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH);
-	reg = snd_soc_read(codec, SSM2602_ROUT1V);
-	snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
+	snd_soc_update_bits(codec, SSM2602_LOUT1V,
+			    LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH);
+	snd_soc_update_bits(codec, SSM2602_ROUT1V,
+			    ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
 
 	ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
 			ARRAY_SIZE(ssm2602_snd_controls));
@@ -543,7 +580,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec)
 static int ssm260x_probe(struct snd_soc_codec *codec)
 {
 	struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-	int ret, reg;
+	int ret;
 
 	pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
 
@@ -560,10 +597,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
 	}
 
 	/* set the update bits */
-	reg = snd_soc_read(codec, SSM2602_LINVOL);
-	snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH);
-	reg = snd_soc_read(codec, SSM2602_RINVOL);
-	snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH);
+	snd_soc_update_bits(codec, SSM2602_LINVOL,
+			    LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
+	snd_soc_update_bits(codec, SSM2602_RINVOL,
+			    RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH);
 	/*select Line in as default input*/
 	snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
 			APANA_ENABLE_MIC_BOOST);
@@ -577,7 +614,12 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
 		break;
 	}
 
-	return ret;
+	if (ret)
+		return ret;
+
+	ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	return 0;
 }
 
 /* remove everything here */
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h
index b98c69168036..fbd07d7b73ca 100644
--- a/sound/soc/codecs/ssm2602.h
+++ b/sound/soc/codecs/ssm2602.h
@@ -116,6 +116,10 @@
 
 #define SSM2602_CACHEREGNUM 	10
 
-#define SSM2602_SYSCLK	0
+enum ssm2602_clk {
+	SSM2602_SYSCLK,
+	SSM2602_CLK_CLKOUT,
+	SSM2602_CLK_XTO
+};
 
 #endif
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index 5c7def3979c0..bb82408ab8e1 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -756,25 +756,19 @@ static int sta32x_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	/* read reg reset values into cache */
-	for (i = 0; i < STA32X_REGISTER_COUNT; i++)
-		snd_soc_cache_write(codec, i, sta32x_regs[i]);
-
-	/* preserve reset values of reserved register bits */
-	snd_soc_cache_write(codec, STA32X_CONFC,
-			    codec->hw_read(codec, STA32X_CONFC));
-	snd_soc_cache_write(codec, STA32X_CONFE,
-			    codec->hw_read(codec, STA32X_CONFE));
-	snd_soc_cache_write(codec, STA32X_CONFF,
-			    codec->hw_read(codec, STA32X_CONFF));
-	snd_soc_cache_write(codec, STA32X_MMUTE,
-			    codec->hw_read(codec, STA32X_MMUTE));
-	snd_soc_cache_write(codec, STA32X_AUTO1,
-			    codec->hw_read(codec, STA32X_AUTO1));
-	snd_soc_cache_write(codec, STA32X_AUTO3,
-			    codec->hw_read(codec, STA32X_AUTO3));
-	snd_soc_cache_write(codec, STA32X_C3CFG,
-			    codec->hw_read(codec, STA32X_C3CFG));
+	/* Chip documentation explicitly requires that the reset values
+	 * of reserved register bits are left untouched.
+	 * Write the register default value to cache for reserved registers,
+	 * so the write to the these registers are suppressed by the cache
+	 * restore code when it skips writes of default registers.
+	 */
+	snd_soc_cache_write(codec, STA32X_CONFC, 0xc2);
+	snd_soc_cache_write(codec, STA32X_CONFE, 0xc2);
+	snd_soc_cache_write(codec, STA32X_CONFF, 0x5c);
+	snd_soc_cache_write(codec, STA32X_MMUTE, 0x10);
+	snd_soc_cache_write(codec, STA32X_AUTO1, 0x60);
+	snd_soc_cache_write(codec, STA32X_AUTO3, 0x00);
+	snd_soc_cache_write(codec, STA32X_C3CFG, 0x40);
 
 	/* FIXME enable thermal warning adjustment and recovery  */
 	snd_soc_update_bits(codec, STA32X_CONFA,
@@ -837,6 +831,7 @@ static const struct snd_soc_codec_driver sta32x_codec = {
 	.resume =		sta32x_resume,
 	.reg_cache_size =	STA32X_REGISTER_COUNT,
 	.reg_word_size =	sizeof(u8),
+	.reg_cache_default =	sta32x_regs,
 	.volatile_register =	sta32x_reg_is_volatile,
 	.set_bias_level =	sta32x_set_bias_level,
 	.controls =		sta32x_snd_controls,
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 33bb52f3f683..ab27dbcd1262 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -47,63 +47,6 @@ static const u16 tlv320aic23_reg[] = {
 	0x0000, 0x0000, 0x0000, 0x0000,	/* 12 */
 };
 
-/*
- * read tlv320aic23 register cache
- */
-static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
-						      *codec, unsigned int reg)
-{
-	u16 *cache = codec->reg_cache;
-	if (reg >= ARRAY_SIZE(tlv320aic23_reg))
-		return -1;
-	return cache[reg];
-}
-
-/*
- * write tlv320aic23 register cache
- */
-static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
-					       u8 reg, u16 value)
-{
-	u16 *cache = codec->reg_cache;
-	if (reg >= ARRAY_SIZE(tlv320aic23_reg))
-		return;
-	cache[reg] = value;
-}
-
-/*
- * write to the tlv320aic23 register space
- */
-static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
-			     unsigned int value)
-{
-
-	u8 data[2];
-
-	/* TLV320AIC23 has 7 bit address and 9 bits of data
-	 * so we need to switch one data bit into reg and rest
-	 * of data into val
-	 */
-
-	if (reg > 9 && reg != 15) {
-		printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
-		return -1;
-	}
-
-	data[0] = (reg << 1) | (value >> 8 & 0x01);
-	data[1] = value & 0xff;
-
-	tlv320aic23_write_reg_cache(codec, reg, value);
-
-	if (codec->hw_write(codec->control_data, data, 2) == 2)
-		return 0;
-
-	printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__,
-	       value, reg);
-
-	return -EIO;
-}
-
 static const char *rec_src_text[] = { "Line", "Mic" };
 static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
 
@@ -139,8 +82,8 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
 	*/
 	val = (val >= 4) ? 4  : (3 - val);
 
-	reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
-	tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
+	reg = snd_soc_read(codec, TLV320AIC23_ANLG) & (~0x1C0);
+	snd_soc_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
 
 	return 0;
 }
@@ -151,7 +94,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	u16 val;
 
-	val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
+	val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0);
 	val = val >> 6;
 	val = (val >= 4) ? 4  : (3 -  val);
 	ucontrol->value.integer.value[0] = val;
@@ -159,15 +102,6 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
 
 }
 
-#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
-	.put = snd_soc_tlv320aic23_put_volsw, \
-	.private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
-
 static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
 	SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
 			 TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
@@ -178,8 +112,9 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
 			 TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
 	SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
 	SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
-	SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
-				  6, 4, 0, sidetone_vol_tlv),
+	SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0,
+			   snd_soc_tlv320aic23_get_volsw,
+			   snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv),
 	SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
 };
 
@@ -240,7 +175,6 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
 /* AIC23 driver data */
 struct aic23 {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 	int mclk;
 	int requested_adc;
 	int requested_dac;
@@ -352,7 +286,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac)
 static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
 		u32 *sample_rate_adc, u32 *sample_rate_dac)
 {
-	int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
+	int src = snd_soc_read(codec, TLV320AIC23_SRATE);
 	int sr = (src >> 2) & 0x0f;
 	int val = (mclk / bosr_usb_divisor_table[src & 3]);
 	int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
@@ -376,7 +310,7 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
 				__func__, sample_rate_adc, sample_rate_dac);
 		return -EINVAL;
 	}
-	tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+	snd_soc_write(codec, TLV320AIC23_SRATE, data);
 #ifdef DEBUG
 	{
 		u32 adc, dac;
@@ -415,9 +349,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
 	if (ret < 0)
 		return ret;
 
-	iface_reg =
-	    tlv320aic23_read_reg_cache(codec,
-				       TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+	iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
 		break;
@@ -431,7 +364,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
 		iface_reg |= (0x03 << 2);
 		break;
 	}
-	tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+	snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
 
 	return 0;
 }
@@ -443,7 +376,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
 	struct snd_soc_codec *codec = rtd->codec;
 
 	/* set active */
-	tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
+	snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001);
 
 	return 0;
 }
@@ -458,7 +391,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
 	/* deactivate */
 	if (!codec->active) {
 		udelay(50);
-		tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+		snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
 	}
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		aic23->requested_dac = 0;
@@ -471,14 +404,14 @@ static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
 	struct snd_soc_codec *codec = dai->codec;
 	u16 reg;
 
-	reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
+	reg = snd_soc_read(codec, TLV320AIC23_DIGT);
 	if (mute)
 		reg |= TLV320AIC23_DACM_MUTE;
 
 	else
 		reg &= ~TLV320AIC23_DACM_MUTE;
 
-	tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
+	snd_soc_write(codec, TLV320AIC23_DIGT, reg);
 
 	return 0;
 }
@@ -489,8 +422,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 iface_reg;
 
-	iface_reg =
-	    tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
+	iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
 
 	/* set master/slave audio interface */
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -524,7 +456,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
 
 	}
 
-	tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+	snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
 
 	return 0;
 }
@@ -540,26 +472,26 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
 				      enum snd_soc_bias_level level)
 {
-	u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
+	u16 reg = snd_soc_read(codec, TLV320AIC23_PWR) & 0xff7f;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		/* vref/mid, osc on, dac unmute */
 		reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \
 			TLV320AIC23_DAC_OFF);
-		tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
+		snd_soc_write(codec, TLV320AIC23_PWR, reg);
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
 		/* everything off except vref/vmid, */
-		tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \
-			TLV320AIC23_CLK_OFF);
+		snd_soc_write(codec, TLV320AIC23_PWR,
+			      reg | TLV320AIC23_CLK_OFF);
 		break;
 	case SND_SOC_BIAS_OFF:
 		/* everything off, dac mute, inactive */
-		tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
-		tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
+		snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
+		snd_soc_write(codec, TLV320AIC23_PWR, 0xffff);
 		break;
 	}
 	codec->dapm.bias_level = level;
@@ -606,13 +538,7 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec,
 
 static int tlv320aic23_resume(struct snd_soc_codec *codec)
 {
-	u16 reg;
-
-	/* Sync reg_cache with the hardware */
-	for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) {
-		u16 val = tlv320aic23_read_reg_cache(codec, reg);
-		tlv320aic23_write(codec, reg, val);
-	}
+	snd_soc_cache_sync(codec);
 	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	return 0;
@@ -621,46 +547,52 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec)
 static int tlv320aic23_probe(struct snd_soc_codec *codec)
 {
 	struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
-	int reg;
+	int ret;
 
 	printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
-	codec->control_data = aic23->control_data;
-	codec->hw_write = (hw_write_t)i2c_master_send;
-	codec->hw_read = NULL;
+
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
 
 	/* Reset codec */
-	tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
+	snd_soc_write(codec, TLV320AIC23_RESET, 0);
+
+	/* Write the register default value to cache for reserved registers,
+	 * so the write to the these registers are suppressed by the cache
+	 * restore code when it skips writes of default registers.
+	 */
+	snd_soc_cache_write(codec, 0x0A, 0);
+	snd_soc_cache_write(codec, 0x0B, 0);
+	snd_soc_cache_write(codec, 0x0C, 0);
+	snd_soc_cache_write(codec, 0x0D, 0);
+	snd_soc_cache_write(codec, 0x0E, 0);
 
 	/* power on device */
 	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
+	snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
 
 	/* Unmute input */
-	reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
-	tlv320aic23_write(codec, TLV320AIC23_LINVOL,
-			  (reg & (~TLV320AIC23_LIM_MUTED)) |
-			  (TLV320AIC23_LRS_ENABLED));
+	snd_soc_update_bits(codec, TLV320AIC23_LINVOL,
+			    TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
 
-	reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
-	tlv320aic23_write(codec, TLV320AIC23_RINVOL,
-			  (reg & (~TLV320AIC23_LIM_MUTED)) |
-			  TLV320AIC23_LRS_ENABLED);
+	snd_soc_update_bits(codec, TLV320AIC23_RINVOL,
+			    TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
 
-	reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
-	tlv320aic23_write(codec, TLV320AIC23_ANLG,
-			 (reg) & (~TLV320AIC23_BYPASS_ON) &
-			 (~TLV320AIC23_MICM_MUTED));
+	snd_soc_update_bits(codec, TLV320AIC23_ANLG,
+			    TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED,
+			    0);
 
 	/* Default output volume */
-	tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
-			  TLV320AIC23_DEFAULT_OUT_VOL &
-			  TLV320AIC23_OUT_VOL_MASK);
-	tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
-			  TLV320AIC23_DEFAULT_OUT_VOL &
-			  TLV320AIC23_OUT_VOL_MASK);
+	snd_soc_write(codec, TLV320AIC23_LCHNVOL,
+		      TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
+	snd_soc_write(codec, TLV320AIC23_RCHNVOL,
+		      TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
 
-	tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
+	snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
 
 	snd_soc_add_controls(codec, tlv320aic23_snd_controls,
 				ARRAY_SIZE(tlv320aic23_snd_controls));
@@ -682,8 +614,6 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
 	.remove = tlv320aic23_remove,
 	.suspend = tlv320aic23_suspend,
 	.resume = tlv320aic23_resume,
-	.read = tlv320aic23_read_reg_cache,
-	.write = tlv320aic23_write,
 	.set_bias_level = tlv320aic23_set_bias_level,
 	.dapm_widgets = tlv320aic23_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
@@ -710,7 +640,6 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, aic23);
-	aic23->control_data = i2c;
 	aic23->control_type = SND_SOC_I2C;
 
 	ret =  snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index e93b9d1ae1dd..b21c610051c0 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -528,40 +528,33 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
 				  enum snd_soc_bias_level level)
 {
 	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-	u8 value;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		if (aic32x4->master) {
 			/* Switch on PLL */
-			value = snd_soc_read(codec, AIC32X4_PLLPR);
-			snd_soc_write(codec, AIC32X4_PLLPR,
-				      (value | AIC32X4_PLLEN));
+			snd_soc_update_bits(codec, AIC32X4_PLLPR,
+					    AIC32X4_PLLEN, AIC32X4_PLLEN);
 
 			/* Switch on NDAC Divider */
-			value = snd_soc_read(codec, AIC32X4_NDAC);
-			snd_soc_write(codec, AIC32X4_NDAC,
-				      value | AIC32X4_NDACEN);
+			snd_soc_update_bits(codec, AIC32X4_NDAC,
+					    AIC32X4_NDACEN, AIC32X4_NDACEN);
 
 			/* Switch on MDAC Divider */
-			value = snd_soc_read(codec, AIC32X4_MDAC);
-			snd_soc_write(codec, AIC32X4_MDAC,
-				      value | AIC32X4_MDACEN);
+			snd_soc_update_bits(codec, AIC32X4_MDAC,
+					    AIC32X4_MDACEN, AIC32X4_MDACEN);
 
 			/* Switch on NADC Divider */
-			value = snd_soc_read(codec, AIC32X4_NADC);
-			snd_soc_write(codec, AIC32X4_NADC,
-				      value | AIC32X4_MDACEN);
+			snd_soc_update_bits(codec, AIC32X4_NADC,
+					    AIC32X4_NADCEN, AIC32X4_NADCEN);
 
 			/* Switch on MADC Divider */
-			value = snd_soc_read(codec, AIC32X4_MADC);
-			snd_soc_write(codec, AIC32X4_MADC,
-				      value | AIC32X4_MDACEN);
+			snd_soc_update_bits(codec, AIC32X4_MADC,
+					    AIC32X4_MADCEN, AIC32X4_MADCEN);
 
 			/* Switch on BCLK_N Divider */
-			value = snd_soc_read(codec, AIC32X4_BCLKN);
-			snd_soc_write(codec, AIC32X4_BCLKN,
-				      value | AIC32X4_BCLKEN);
+			snd_soc_update_bits(codec, AIC32X4_BCLKN,
+					    AIC32X4_BCLKEN, AIC32X4_BCLKEN);
 		}
 		break;
 	case SND_SOC_BIAS_PREPARE:
@@ -569,34 +562,28 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
 	case SND_SOC_BIAS_STANDBY:
 		if (aic32x4->master) {
 			/* Switch off PLL */
-			value = snd_soc_read(codec, AIC32X4_PLLPR);
-			snd_soc_write(codec, AIC32X4_PLLPR,
-				      (value & ~AIC32X4_PLLEN));
+			snd_soc_update_bits(codec, AIC32X4_PLLPR,
+					    AIC32X4_PLLEN, 0);
 
 			/* Switch off NDAC Divider */
-			value = snd_soc_read(codec, AIC32X4_NDAC);
-			snd_soc_write(codec, AIC32X4_NDAC,
-				      value & ~AIC32X4_NDACEN);
+			snd_soc_update_bits(codec, AIC32X4_NDAC,
+					    AIC32X4_NDACEN, 0);
 
 			/* Switch off MDAC Divider */
-			value = snd_soc_read(codec, AIC32X4_MDAC);
-			snd_soc_write(codec, AIC32X4_MDAC,
-				      value & ~AIC32X4_MDACEN);
+			snd_soc_update_bits(codec, AIC32X4_MDAC,
+					    AIC32X4_MDACEN, 0);
 
 			/* Switch off NADC Divider */
-			value = snd_soc_read(codec, AIC32X4_NADC);
-			snd_soc_write(codec, AIC32X4_NADC,
-				      value & ~AIC32X4_NDACEN);
+			snd_soc_update_bits(codec, AIC32X4_NADC,
+					    AIC32X4_NADCEN, 0);
 
 			/* Switch off MADC Divider */
-			value = snd_soc_read(codec, AIC32X4_MADC);
-			snd_soc_write(codec, AIC32X4_MADC,
-				      value & ~AIC32X4_MDACEN);
-			value = snd_soc_read(codec, AIC32X4_BCLKN);
+			snd_soc_update_bits(codec, AIC32X4_MADC,
+					    AIC32X4_MADCEN, 0);
 
 			/* Switch off BCLK_N Divider */
-			snd_soc_write(codec, AIC32X4_BCLKN,
-				      value & ~AIC32X4_BCLKEN);
+			snd_soc_update_bits(codec, AIC32X4_BCLKN,
+					    AIC32X4_BCLKEN, 0);
 		}
 		break;
 	case SND_SOC_BIAS_OFF:
@@ -685,10 +672,10 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
 	}
 
 	/* Mic PGA routing */
-	if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
+	if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
 		snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K);
 	}
-	if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
+	if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
 		snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K);
 	}
 
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 0963c4c7a83f..7a49390bc30d 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -76,7 +76,6 @@ struct aic3x_priv {
 	struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
 	enum snd_soc_control_type control_type;
 	struct aic3x_setup_data *setup;
-	void *control_data;
 	unsigned int sysclk;
 	struct list_head list;
 	int master;
@@ -138,7 +137,10 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
 	if (reg >= AIC3X_CACHEREGNUM)
 		return -1;
 
-	*value = codec->hw_read(codec, reg);
+	codec->cache_bypass = 1;
+	*value = snd_soc_read(codec, reg);
+	codec->cache_bypass = 0;
+
 	cache[reg] = *value;
 
 	return 0;
@@ -198,6 +200,10 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
 			else
 				/* old connection must be powered down */
 				path->connect = invert ? 1 : 0;
+
+			dapm_mark_dirty(path->source, "tlv320aic3x source");
+			dapm_mark_dirty(path->sink, "tlv320aic3x sink");
+
 			break;
 		}
 
@@ -1383,7 +1389,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 	int ret, i;
 
 	INIT_LIST_HEAD(&aic3x->list);
-	codec->control_data = aic3x->control_data;
 	aic3x->codec = codec;
 	codec->dapm.idle_bias_off = 1;
 
@@ -1495,9 +1500,9 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
  */
 
 static const struct i2c_device_id aic3x_i2c_id[] = {
-	[AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
-	[AIC3X_MODEL_33] = { "tlv320aic33", 0 },
-	[AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
+	{ "tlv320aic3x", AIC3X_MODEL_3X },
+	{ "tlv320aic33", AIC3X_MODEL_33 },
+	{ "tlv320aic3007", AIC3X_MODEL_3007 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@@ -1512,7 +1517,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 	struct aic3x_pdata *pdata = i2c->dev.platform_data;
 	struct aic3x_priv *aic3x;
 	int ret;
-	const struct i2c_device_id *tbl;
 
 	aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
 	if (aic3x == NULL) {
@@ -1520,7 +1524,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 	}
 
-	aic3x->control_data = i2c;
 	aic3x->control_type = SND_SOC_I2C;
 
 	i2c_set_clientdata(i2c, aic3x);
@@ -1531,11 +1534,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 		aic3x->gpio_reset = -1;
 	}
 
-	for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
-		if (!strcmp(tbl->name, id->name))
-			break;
-	}
-	aic3x->model = tbl - aic3x_i2c_id;
+	aic3x->model = id->driver_data;
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_aic3x, &aic3x_dai, 1);
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 243d17711211..dc8a2b2bdc1c 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -55,13 +55,13 @@
 #define BURST_BASEFREQ_HZ	49152000
 
 #define SAMPLES_TO_US(rate, samples) \
-	(1000000000 / ((rate * 1000) / samples))
+	(1000000000 / (((rate) * 1000) / (samples)))
 
 #define US_TO_SAMPLES(rate, us) \
-	(rate / (1000000 / (us < 1000000 ? us : 1000000)))
+	((rate) / (1000000 / ((us) < 1000000 ? (us) : 1000000)))
 
 #define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
-	((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
+	(((samples)*5000) / (((burstrate)*5000) / ((burstrate) - (playrate))))
 
 static void dac33_calculate_times(struct snd_pcm_substream *substream);
 static int dac33_prepare_chip(struct snd_pcm_substream *substream);
@@ -627,18 +627,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"RIGHT_LO", NULL, "Codec Power"},
 };
 
-static int dac33_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	snd_soc_dapm_new_controls(dapm, dac33_dapm_widgets,
-				  ARRAY_SIZE(dac33_dapm_widgets));
-	/* set up audio path interconnects */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	return 0;
-}
-
 static int dac33_set_bias_level(struct snd_soc_codec *codec,
 				enum snd_soc_bias_level level)
 {
@@ -1451,15 +1439,11 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
 		}
 	}
 
-	snd_soc_add_controls(codec, dac33_snd_controls,
-			     ARRAY_SIZE(dac33_snd_controls));
 	/* Only add the FIFO controls, if we have valid IRQ number */
 	if (dac33->irq >= 0)
 		snd_soc_add_controls(codec, dac33_mode_snd_controls,
 				     ARRAY_SIZE(dac33_mode_snd_controls));
 
-	dac33_add_widgets(codec);
-
 err_power:
 	return ret;
 }
@@ -1502,6 +1486,13 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
 	.remove = dac33_soc_remove,
 	.suspend = dac33_soc_suspend,
 	.resume = dac33_soc_resume,
+
+	.controls = dac33_snd_controls,
+	.num_controls = ARRAY_SIZE(dac33_snd_controls),
+	.dapm_widgets = dac33_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 #define DAC33_RATES	(SNDRV_PCM_RATE_44100 | \
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index b2572c451c35..7eeca79d7387 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -33,6 +33,11 @@
 
 #include "tpa6130a2.h"
 
+enum tpa_model {
+	TPA6130A2,
+	TPA6140A2,
+};
+
 static struct i2c_client *tpa6130a2_client;
 
 /* This struct is used to save the context */
@@ -383,7 +388,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
 
 	pdata = client->dev.platform_data;
 	data->power_gpio = pdata->power_gpio;
-	data->id = pdata->id;
+	data->id = id->driver_data;
 
 	mutex_init(&data->mutex);
 
@@ -405,7 +410,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
 	switch (data->id) {
 	default:
 		dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
-			 pdata->id);
+			 data->id);
 	case TPA6130A2:
 		regulator = "Vdd";
 		break;
@@ -469,7 +474,8 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id tpa6130a2_id[] = {
-	{ "tpa6130a2", 0 },
+	{ "tpa6130a2", TPA6130A2 },
+	{ "tpa6140a2", TPA6140A2 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 71674bec9604..f798247ac1b2 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -863,34 +863,6 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
  * Inverting not going to help with these.
  * Custom volsw and volsw_2r get/put functions to handle these gain bits.
  */
-#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
-			       xinvert, tlv_array) \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
-	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw, \
-	.get = snd_soc_get_volsw_twl4030, \
-	.put = snd_soc_put_volsw_twl4030, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = xreg, .shift = shift_left, .rshift = shift_right,\
-		 .max = xmax, .invert = xinvert} }
-#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
-				 xinvert, tlv_array) \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
-	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw_2r, \
-	.get = snd_soc_get_volsw_r2_twl4030,\
-	.put = snd_soc_put_volsw_r2_twl4030, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-		 .rshift = xshift, .max = xmax, .invert = xinvert} }
-#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
-	SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
-			       xinvert, tlv_array)
-
 static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
@@ -1197,19 +1169,23 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
 		TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
 
 	/* Separate output gain controls */
-	SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
+	SOC_DOUBLE_R_EXT_TLV("PreDriv Playback Volume",
 		TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
-		4, 3, 0, output_tvl),
+		4, 3, 0, snd_soc_get_volsw_r2_twl4030,
+		snd_soc_put_volsw_r2_twl4030, output_tvl),
 
-	SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume",
-		TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl),
+	SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
+		TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, snd_soc_get_volsw_twl4030,
+		snd_soc_put_volsw_twl4030, output_tvl),
 
-	SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume",
+	SOC_DOUBLE_R_EXT_TLV("Carkit Playback Volume",
 		TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL,
-		4, 3, 0, output_tvl),
+		4, 3, 0, snd_soc_get_volsw_r2_twl4030,
+		snd_soc_put_volsw_r2_twl4030, output_tvl),
 
-	SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
-		TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl),
+	SOC_SINGLE_EXT_TLV("Earpiece Playback Volume",
+		TWL4030_REG_EAR_CTL, 4, 3, 0, snd_soc_get_volsw_twl4030,
+		snd_soc_put_volsw_twl4030, output_ear_tvl),
 
 	/* Common capture gain controls */
 	SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume",
@@ -1633,17 +1609,6 @@ static const struct snd_soc_dapm_route intercon[] = {
 
 };
 
-static int twl4030_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	snd_soc_dapm_new_controls(dapm, twl4030_dapm_widgets,
-				 ARRAY_SIZE(twl4030_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
-	return 0;
-}
-
 static int twl4030_set_bias_level(struct snd_soc_codec *codec,
 				  enum snd_soc_bias_level level)
 {
@@ -2265,9 +2230,6 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
 
 	twl4030_init_chip(codec);
 
-	snd_soc_add_controls(codec, twl4030_snd_controls,
-				ARRAY_SIZE(twl4030_snd_controls));
-	twl4030_add_widgets(codec);
 	return 0;
 }
 
@@ -2293,6 +2255,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
 	.reg_cache_size = sizeof(twl4030_reg),
 	.reg_word_size = sizeof(u8),
 	.reg_cache_default = twl4030_reg,
+
+	.controls = twl4030_snd_controls,
+	.num_controls = ARRAY_SIZE(twl4030_snd_controls),
+	.dapm_widgets = twl4030_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets),
+	.dapm_routes = intercon,
+	.num_dapm_routes = ARRAY_SIZE(intercon),
 };
 
 static int __devinit twl4030_codec_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 81645c632447..73e11f022ded 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -57,6 +57,13 @@
 #define TWL6040_HF_VOL_MASK	0x1F
 #define TWL6040_HF_VOL_SHIFT	0
 
+/* Shadow register used by the driver */
+#define TWL6040_REG_SW_SHADOW	0x2F
+#define TWL6040_CACHEREGNUM	(TWL6040_REG_SW_SHADOW + 1)
+
+/* TWL6040_REG_SW_SHADOW (0x2F) fields */
+#define TWL6040_EAR_PATH_ENABLE	0x01
+
 struct twl6040_output {
 	u16 active;
 	u16 left_vol;
@@ -65,12 +72,13 @@ struct twl6040_output {
 	u16 right_step;
 	unsigned int step_delay;
 	u16 ramp;
-	u16 mute;
+	struct delayed_work work;
 	struct completion ramp_done;
 };
 
 struct twl6040_jack_data {
 	struct snd_soc_jack *jack;
+	struct delayed_work work;
 	int report;
 };
 
@@ -79,7 +87,6 @@ struct twl6040_data {
 	int plug_irq;
 	int codec_powered;
 	int pll;
-	int non_lp;
 	int pll_power_mode;
 	int hs_power_mode;
 	int hs_power_mode_locked;
@@ -92,67 +99,64 @@ struct twl6040_data {
 	struct twl6040_jack_data hs_jack;
 	struct snd_soc_codec *codec;
 	struct workqueue_struct *workqueue;
-	struct delayed_work delayed_work;
 	struct mutex mutex;
 	struct twl6040_output headset;
 	struct twl6040_output handsfree;
-	struct workqueue_struct *hf_workqueue;
-	struct workqueue_struct *hs_workqueue;
-	struct delayed_work hs_delayed_work;
-	struct delayed_work hf_delayed_work;
 };
 
 /*
  * twl6040 register cache & default register settings
  */
 static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
-	0x00, /* not used		0x00	*/
-	0x4B, /* TWL6040_ASICID (ro)	0x01	*/
-	0x00, /* TWL6040_ASICREV (ro)	0x02	*/
-	0x00, /* TWL6040_INTID		0x03	*/
-	0x00, /* TWL6040_INTMR		0x04	*/
-	0x00, /* TWL6040_NCPCTRL	0x05	*/
-	0x00, /* TWL6040_LDOCTL		0x06	*/
-	0x60, /* TWL6040_HPPLLCTL	0x07	*/
-	0x00, /* TWL6040_LPPLLCTL	0x08	*/
-	0x4A, /* TWL6040_LPPLLDIV	0x09	*/
-	0x00, /* TWL6040_AMICBCTL	0x0A	*/
-	0x00, /* TWL6040_DMICBCTL	0x0B	*/
-	0x00, /* TWL6040_MICLCTL	0x0C	*/
-	0x00, /* TWL6040_MICRCTL	0x0D	*/
-	0x00, /* TWL6040_MICGAIN	0x0E	*/
-	0x1B, /* TWL6040_LINEGAIN	0x0F	*/
-	0x00, /* TWL6040_HSLCTL		0x10	*/
-	0x00, /* TWL6040_HSRCTL		0x11	*/
-	0x00, /* TWL6040_HSGAIN		0x12	*/
-	0x00, /* TWL6040_EARCTL		0x13	*/
-	0x00, /* TWL6040_HFLCTL		0x14	*/
-	0x00, /* TWL6040_HFLGAIN	0x15	*/
-	0x00, /* TWL6040_HFRCTL		0x16	*/
-	0x00, /* TWL6040_HFRGAIN	0x17	*/
-	0x00, /* TWL6040_VIBCTLL	0x18	*/
-	0x00, /* TWL6040_VIBDATL	0x19	*/
-	0x00, /* TWL6040_VIBCTLR	0x1A	*/
-	0x00, /* TWL6040_VIBDATR	0x1B	*/
-	0x00, /* TWL6040_HKCTL1		0x1C	*/
-	0x00, /* TWL6040_HKCTL2		0x1D	*/
-	0x00, /* TWL6040_GPOCTL		0x1E	*/
-	0x00, /* TWL6040_ALB		0x1F	*/
-	0x00, /* TWL6040_DLB		0x20	*/
-	0x00, /* not used		0x21	*/
-	0x00, /* not used		0x22	*/
-	0x00, /* not used		0x23	*/
-	0x00, /* not used		0x24	*/
-	0x00, /* not used		0x25	*/
-	0x00, /* not used		0x26	*/
-	0x00, /* not used		0x27	*/
-	0x00, /* TWL6040_TRIM1		0x28	*/
-	0x00, /* TWL6040_TRIM2		0x29	*/
-	0x00, /* TWL6040_TRIM3		0x2A	*/
-	0x00, /* TWL6040_HSOTRIM	0x2B	*/
-	0x00, /* TWL6040_HFOTRIM	0x2C	*/
-	0x09, /* TWL6040_ACCCTL		0x2D	*/
-	0x00, /* TWL6040_STATUS (ro)	0x2E	*/
+	0x00, /* not used	0x00	*/
+	0x4B, /* REG_ASICID	0x01 (ro) */
+	0x00, /* REG_ASICREV	0x02 (ro) */
+	0x00, /* REG_INTID	0x03	*/
+	0x00, /* REG_INTMR	0x04	*/
+	0x00, /* REG_NCPCTRL	0x05	*/
+	0x00, /* REG_LDOCTL	0x06	*/
+	0x60, /* REG_HPPLLCTL	0x07	*/
+	0x00, /* REG_LPPLLCTL	0x08	*/
+	0x4A, /* REG_LPPLLDIV	0x09	*/
+	0x00, /* REG_AMICBCTL	0x0A	*/
+	0x00, /* REG_DMICBCTL	0x0B	*/
+	0x00, /* REG_MICLCTL	0x0C	*/
+	0x00, /* REG_MICRCTL	0x0D	*/
+	0x00, /* REG_MICGAIN	0x0E	*/
+	0x1B, /* REG_LINEGAIN	0x0F	*/
+	0x00, /* REG_HSLCTL	0x10	*/
+	0x00, /* REG_HSRCTL	0x11	*/
+	0x00, /* REG_HSGAIN	0x12	*/
+	0x00, /* REG_EARCTL	0x13	*/
+	0x00, /* REG_HFLCTL	0x14	*/
+	0x00, /* REG_HFLGAIN	0x15	*/
+	0x00, /* REG_HFRCTL	0x16	*/
+	0x00, /* REG_HFRGAIN	0x17	*/
+	0x00, /* REG_VIBCTLL	0x18	*/
+	0x00, /* REG_VIBDATL	0x19	*/
+	0x00, /* REG_VIBCTLR	0x1A	*/
+	0x00, /* REG_VIBDATR	0x1B	*/
+	0x00, /* REG_HKCTL1	0x1C	*/
+	0x00, /* REG_HKCTL2	0x1D	*/
+	0x00, /* REG_GPOCTL	0x1E	*/
+	0x00, /* REG_ALB	0x1F	*/
+	0x00, /* REG_DLB	0x20	*/
+	0x00, /* not used	0x21	*/
+	0x00, /* not used	0x22	*/
+	0x00, /* not used	0x23	*/
+	0x00, /* not used	0x24	*/
+	0x00, /* not used	0x25	*/
+	0x00, /* not used	0x26	*/
+	0x00, /* not used	0x27	*/
+	0x00, /* REG_TRIM1	0x28	*/
+	0x00, /* REG_TRIM2	0x29	*/
+	0x00, /* REG_TRIM3	0x2A	*/
+	0x00, /* REG_HSOTRIM	0x2B	*/
+	0x00, /* REG_HFOTRIM	0x2C	*/
+	0x09, /* REG_ACCCTL	0x2D	*/
+	0x00, /* REG_STATUS	0x2E (ro) */
+
+	0x00, /* REG_SW_SHADOW	0x2F - Shadow, non HW register */
 };
 
 /* List of registers to be restored after power up */
@@ -236,8 +240,12 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
 	if (reg >= TWL6040_CACHEREGNUM)
 		return -EIO;
 
-	value = twl6040_reg_read(twl6040, reg);
-	twl6040_write_reg_cache(codec, reg, value);
+	if (likely(reg < TWL6040_REG_SW_SHADOW)) {
+		value = twl6040_reg_read(twl6040, reg);
+		twl6040_write_reg_cache(codec, reg, value);
+	} else {
+		value = twl6040_read_reg_cache(codec, reg);
+	}
 
 	return value;
 }
@@ -254,7 +262,10 @@ static int twl6040_write(struct snd_soc_codec *codec,
 		return -EIO;
 
 	twl6040_write_reg_cache(codec, reg, value);
-	return twl6040_reg_write(twl6040, reg, value);
+	if (likely(reg < TWL6040_REG_SW_SHADOW))
+		return twl6040_reg_write(twl6040, reg, value);
+	else
+		return 0;
 }
 
 static void twl6040_init_chip(struct snd_soc_codec *codec)
@@ -262,13 +273,31 @@ static void twl6040_init_chip(struct snd_soc_codec *codec)
 	struct twl6040 *twl6040 = codec->control_data;
 	u8 val;
 
+	/* Update reg_cache: ASICREV, and TRIM values */
 	val = twl6040_get_revid(twl6040);
 	twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val);
 
+	twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1);
+	twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2);
+	twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3);
+	twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM);
+	twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM);
+
 	/* Change chip defaults */
 	/* No imput selected for microphone amplifiers */
 	twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18);
 	twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18);
+
+	/*
+	 * We need to lower the default gain values, so the ramp code
+	 * can work correctly for the first playback.
+	 * This reduces the pop noise heard at the first playback.
+	 */
+	twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff);
+	twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e);
+	twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d);
+	twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d);
+	twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0);
 }
 
 static void twl6040_restore_regs(struct snd_soc_codec *codec)
@@ -456,18 +485,17 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
 static void twl6040_pga_hs_work(struct work_struct *work)
 {
 	struct twl6040_data *priv =
-		container_of(work, struct twl6040_data, hs_delayed_work.work);
+		container_of(work, struct twl6040_data, headset.work.work);
 	struct snd_soc_codec *codec = priv->codec;
 	struct twl6040_output *headset = &priv->headset;
-	unsigned int delay = headset->step_delay;
 	int i, headset_complete;
 
 	/* do we need to ramp at all ? */
 	if (headset->ramp == TWL6040_RAMP_NONE)
 		return;
 
-	/* HS PGA volumes have 4 bits of resolution to ramp */
-	for (i = 0; i <= 16; i++) {
+	/* HS PGA gain range: 0x0 - 0xf (0 - 15) */
+	for (i = 0; i < 16; i++) {
 		headset_complete = twl6040_hs_ramp_step(codec,
 						headset->left_step,
 						headset->right_step);
@@ -476,15 +504,8 @@ static void twl6040_pga_hs_work(struct work_struct *work)
 		if (headset_complete)
 			break;
 
-		/*
-		 * TODO: tune: delay is longer over 0dB
-		 * as increases are larger.
-		 */
-		if (i >= 8)
-			schedule_timeout_interruptible(msecs_to_jiffies(delay +
-							(delay >> 1)));
-		else
-			schedule_timeout_interruptible(msecs_to_jiffies(delay));
+		schedule_timeout_interruptible(
+				msecs_to_jiffies(headset->step_delay));
 	}
 
 	if (headset->ramp == TWL6040_RAMP_DOWN) {
@@ -499,18 +520,18 @@ static void twl6040_pga_hs_work(struct work_struct *work)
 static void twl6040_pga_hf_work(struct work_struct *work)
 {
 	struct twl6040_data *priv =
-		container_of(work, struct twl6040_data, hf_delayed_work.work);
+		container_of(work, struct twl6040_data, handsfree.work.work);
 	struct snd_soc_codec *codec = priv->codec;
 	struct twl6040_output *handsfree = &priv->handsfree;
-	unsigned int delay = handsfree->step_delay;
 	int i, handsfree_complete;
 
 	/* do we need to ramp at all ? */
 	if (handsfree->ramp == TWL6040_RAMP_NONE)
 		return;
 
-	/* HF PGA volumes have 5 bits of resolution to ramp */
-	for (i = 0; i <= 32; i++) {
+	/*
+	 * HF PGA gain range: 0x00 - 0x1d (0 - 29) */
+	for (i = 0; i < 30; i++) {
 		handsfree_complete = twl6040_hf_ramp_step(codec,
 						handsfree->left_step,
 						handsfree->right_step);
@@ -519,15 +540,8 @@ static void twl6040_pga_hf_work(struct work_struct *work)
 		if (handsfree_complete)
 			break;
 
-		/*
-		 * TODO: tune: delay is longer over 0dB
-		 * as increases are larger.
-		 */
-		if (i >= 16)
-			schedule_timeout_interruptible(msecs_to_jiffies(delay +
-						       (delay >> 1)));
-		else
-			schedule_timeout_interruptible(msecs_to_jiffies(delay));
+		schedule_timeout_interruptible(
+				msecs_to_jiffies(handsfree->step_delay));
 	}
 
 
@@ -539,36 +553,40 @@ static void twl6040_pga_hf_work(struct work_struct *work)
 	handsfree->ramp = TWL6040_RAMP_NONE;
 }
 
-static int pga_event(struct snd_soc_dapm_widget *w,
+static int out_drv_event(struct snd_soc_dapm_widget *w,
 			struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 	struct twl6040_output *out;
 	struct delayed_work *work;
-	struct workqueue_struct *queue;
 
 	switch (w->shift) {
-	case 2:
-	case 3:
+	case 2: /* Headset output driver */
 		out = &priv->headset;
-		work = &priv->hs_delayed_work;
-		queue = priv->hs_workqueue;
+		work = &out->work;
+		/*
+		 * Make sure, that we do not mess up variables for already
+		 * executing work.
+		 */
+		cancel_delayed_work_sync(work);
+
 		out->left_step = priv->hs_left_step;
 		out->right_step = priv->hs_right_step;
 		out->step_delay = 5;	/* 5 ms between volume ramp steps */
 		break;
-	case 4:
+	case 4: /* Handsfree output driver */
 		out = &priv->handsfree;
-		work = &priv->hf_delayed_work;
-		queue = priv->hf_workqueue;
+		work = &out->work;
+		/*
+		 * Make sure, that we do not mess up variables for already
+		 * executing work.
+		 */
+		cancel_delayed_work_sync(work);
+
 		out->left_step = priv->hf_left_step;
 		out->right_step = priv->hf_right_step;
 		out->step_delay = 5;	/* 5 ms between volume ramp steps */
-		if (SND_SOC_DAPM_EVENT_ON(event))
-			priv->non_lp++;
-		else
-			priv->non_lp--;
 		break;
 	default:
 		return -1;
@@ -580,31 +598,25 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 			break;
 
 		/* don't use volume ramp for power-up */
+		out->ramp = TWL6040_RAMP_UP;
 		out->left_step = out->left_vol;
 		out->right_step = out->right_vol;
 
-		if (!delayed_work_pending(work)) {
-			out->ramp = TWL6040_RAMP_UP;
-			queue_delayed_work(queue, work,
-					msecs_to_jiffies(1));
-		}
+		queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
 		break;
 
 	case SND_SOC_DAPM_PRE_PMD:
 		if (!out->active)
 			break;
 
-		if (!delayed_work_pending(work)) {
-			/* use volume ramp for power-down */
-			out->ramp = TWL6040_RAMP_DOWN;
-			INIT_COMPLETION(out->ramp_done);
+		/* use volume ramp for power-down */
+		out->ramp = TWL6040_RAMP_DOWN;
+		INIT_COMPLETION(out->ramp_done);
 
-			queue_delayed_work(queue, work,
-					msecs_to_jiffies(1));
+		queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
 
-			wait_for_completion_timeout(&out->ramp_done,
-					msecs_to_jiffies(2000));
-		}
+		wait_for_completion_timeout(&out->ramp_done,
+					    msecs_to_jiffies(2000));
 		break;
 	}
 
@@ -615,7 +627,7 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 {
 	int hslctl, hsrctl;
-	int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;
+	int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE;
 
 	hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
 	hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
@@ -637,11 +649,31 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
 			struct snd_kcontrol *kcontrol, int event)
 {
+	struct snd_soc_codec *codec = w->codec;
+	u8 hslctl, hsrctl;
+
+	/*
+	 * Workaround for Headset DC offset caused pop noise:
+	 * Both HS DAC need to be turned on (before the HS driver) and off at
+	 * the same time.
+	 */
+	hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
+	hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		hslctl |= TWL6040_HSDACENA;
+		hsrctl |= TWL6040_HSDACENA;
+	} else {
+		hslctl &= ~TWL6040_HSDACENA;
+		hsrctl &= ~TWL6040_HSDACENA;
+	}
+	twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
+	twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
+
 	msleep(1);
 	return 0;
 }
 
-static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
+static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w,
 			struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
@@ -649,18 +681,12 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
 	int ret = 0;
 
 	if (SND_SOC_DAPM_EVENT_ON(event)) {
-		priv->non_lp++;
-		if (!strcmp(w->name, "Earphone Driver")) {
-			/* Earphone doesn't support low power mode */
-			priv->hs_power_mode_locked = 1;
-			ret = headset_power_mode(codec, 1);
-		}
+		/* Earphone doesn't support low power mode */
+		priv->hs_power_mode_locked = 1;
+		ret = headset_power_mode(codec, 1);
 	} else {
-		priv->non_lp--;
-		if (!strcmp(w->name, "Earphone Driver")) {
-			priv->hs_power_mode_locked = 0;
-			ret = headset_power_mode(codec, priv->hs_power_mode);
-		}
+		priv->hs_power_mode_locked = 0;
+		ret = headset_power_mode(codec, priv->hs_power_mode);
 	}
 
 	msleep(1);
@@ -702,7 +728,7 @@ EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
 static void twl6040_accessory_work(struct work_struct *work)
 {
 	struct twl6040_data *priv = container_of(work,
-					struct twl6040_data, delayed_work.work);
+					struct twl6040_data, hs_jack.work.work);
 	struct snd_soc_codec *codec = priv->codec;
 	struct twl6040_jack_data *hs_jack = &priv->hs_jack;
 
@@ -713,15 +739,10 @@ static void twl6040_accessory_work(struct work_struct *work)
 static irqreturn_t twl6040_audio_handler(int irq, void *data)
 {
 	struct snd_soc_codec *codec = data;
-	struct twl6040 *twl6040 = codec->control_data;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-	u8 intid;
 
-	intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
-	if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
-		queue_delayed_work(priv->workqueue, &priv->delayed_work,
-							msecs_to_jiffies(200));
+	queue_delayed_work(priv->workqueue, &priv->hs_jack.work,
+			   msecs_to_jiffies(200));
 
 	return IRQ_HANDLED;
 }
@@ -735,25 +756,27 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	int ret;
-	unsigned int reg = mc->reg;
 
 	/* For HS and HF we shadow the values and only actually write
 	 * them out when active in order to ensure the amplifier comes on
 	 * as quietly as possible. */
-	switch (reg) {
+	switch (mc->reg) {
 	case TWL6040_REG_HSGAIN:
 		out = &twl6040_priv->headset;
 		break;
-	default:
+	case TWL6040_REG_HFLGAIN:
+		out = &twl6040_priv->handsfree;
 		break;
+	default:
+		dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
+					__func__, mc->reg);
+		return -EINVAL;
 	}
 
-	if (out) {
-		out->left_vol = ucontrol->value.integer.value[0];
-		out->right_vol = ucontrol->value.integer.value[1];
-		if (!out->active)
-			return 1;
-	}
+	out->left_vol = ucontrol->value.integer.value[0];
+	out->right_vol = ucontrol->value.integer.value[1];
+	if (!out->active)
+		return 1;
 
 	ret = snd_soc_put_volsw(kcontrol, ucontrol);
 	if (ret < 0)
@@ -770,112 +793,42 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
 	struct twl6040_output *out = &twl6040_priv->headset;
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	unsigned int reg = mc->reg;
 
-	switch (reg) {
+	switch (mc->reg) {
 	case TWL6040_REG_HSGAIN:
 		out = &twl6040_priv->headset;
-		ucontrol->value.integer.value[0] = out->left_vol;
-		ucontrol->value.integer.value[1] = out->right_vol;
-		return 0;
-
-	default:
 		break;
-	}
-
-	return snd_soc_get_volsw(kcontrol, ucontrol);
-}
-
-static int twl6040_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
-				  struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
-	struct twl6040_output *out = NULL;
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	int ret;
-	unsigned int reg = mc->reg;
-
-	/* For HS and HF we shadow the values and only actually write
-	 * them out when active in order to ensure the amplifier comes on
-	 * as quietly as possible. */
-	switch (reg) {
 	case TWL6040_REG_HFLGAIN:
-	case TWL6040_REG_HFRGAIN:
 		out = &twl6040_priv->handsfree;
 		break;
 	default:
-		break;
-	}
-
-	if (out) {
-		out->left_vol = ucontrol->value.integer.value[0];
-		out->right_vol = ucontrol->value.integer.value[1];
-		if (!out->active)
-			return 1;
+		dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
+					__func__, mc->reg);
+		return -EINVAL;
 	}
 
-	ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
-	if (ret < 0)
-		return ret;
-
-	return 1;
+	ucontrol->value.integer.value[0] = out->left_vol;
+	ucontrol->value.integer.value[1] = out->right_vol;
+	return 0;
 }
 
-static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
+static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
-	struct twl6040_output *out = &twl6040_priv->handsfree;
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	unsigned int reg = mc->reg;
-
-	/* If these are cached registers use the cache */
-	switch (reg) {
-	case TWL6040_REG_HFLGAIN:
-	case TWL6040_REG_HFRGAIN:
-		out = &twl6040_priv->handsfree;
-		ucontrol->value.integer.value[0] = out->left_vol;
-		ucontrol->value.integer.value[1] = out->right_vol;
-		return 0;
-
-	default:
-		break;
-	}
-
-	return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+	struct snd_soc_codec *codec = widget->codec;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int val;
+
+	/* Do not allow changes while Input/FF efect is running */
+	val = twl6040_read_reg_volatile(codec, e->reg);
+	if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL))
+		return -EBUSY;
+
+	return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
 }
 
-/* double control with volume update */
-#define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\
-							xinvert, tlv_array)\
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
-	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw, .get = twl6040_get_volsw, \
-	.put = twl6040_put_volsw, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = xreg, .shift = shift_left, .rshift = shift_right,\
-		 .max = xmax, .platform_max = xmax, .invert = xinvert} }
-
-/* double control with volume update */
-#define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\
-				xinvert, tlv_array)\
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
-	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
-		SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw_2r, \
-	.get = twl6040_get_volsw_2r, .put = twl6040_put_volsw_2r_vu, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-		 .rshift = xshift, .max = xmax, .invert = xinvert}, }
-
 /*
  * MICATT volume control:
  * from -6 to 0 dB in 6 dB steps
@@ -947,6 +900,19 @@ static const struct soc_enum twl6040_hf_enum[] = {
 			twl6040_hf_texts),
 };
 
+static const char *twl6040_vibrapath_texts[] = {
+	"Input FF", "Audio PDM"
+};
+
+static const struct soc_enum twl6040_vibra_enum[] = {
+	SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1,
+			ARRAY_SIZE(twl6040_vibrapath_texts),
+			twl6040_vibrapath_texts),
+	SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1,
+			ARRAY_SIZE(twl6040_vibrapath_texts),
+			twl6040_vibrapath_texts),
+};
+
 static const struct snd_kcontrol_new amicl_control =
 	SOC_DAPM_ENUM("Route", twl6040_enum[0]);
 
@@ -967,8 +933,25 @@ static const struct snd_kcontrol_new hfl_mux_controls =
 static const struct snd_kcontrol_new hfr_mux_controls =
 	SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
 
-static const struct snd_kcontrol_new ep_driver_switch_controls =
-	SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
+static const struct snd_kcontrol_new ep_path_enable_control =
+	SOC_DAPM_SINGLE("Switch", TWL6040_REG_SW_SHADOW, 0, 1, 0);
+
+static const struct snd_kcontrol_new auxl_switch_control =
+	SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0);
+
+static const struct snd_kcontrol_new auxr_switch_control =
+	SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0);
+
+/* Vibra playback switches */
+static const struct snd_kcontrol_new vibral_mux_controls =
+	SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0],
+		snd_soc_dapm_get_enum_double,
+		twl6040_soc_dapm_put_vibra_enum);
+
+static const struct snd_kcontrol_new vibrar_mux_controls =
+	SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1],
+		snd_soc_dapm_get_enum_double,
+		twl6040_soc_dapm_put_vibra_enum);
 
 /* Headset power mode */
 static const char *twl6040_power_mode_texts[] = {
@@ -1037,6 +1020,15 @@ int twl6040_get_clk_id(struct snd_soc_codec *codec)
 }
 EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
 
+int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
+{
+	if (unlikely(trim >= TWL6040_TRIM_INVAL))
+		return -EINVAL;
+
+	return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim);
+}
+EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
+
 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
 	/* Capture gains */
 	SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1049,10 +1041,12 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
 		TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
 
 	/* Playback gains */
-	SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume",
-		TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
-	SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume",
-		TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
+	SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
+		TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, twl6040_get_volsw,
+		twl6040_put_volsw, hs_tlv),
+	SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume",
+		TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1,
+		twl6040_get_volsw, twl6040_put_volsw, hf_tlv),
 	SOC_SINGLE_TLV("Earphone Playback Volume",
 		TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
 
@@ -1078,6 +1072,10 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("HFL"),
 	SND_SOC_DAPM_OUTPUT("HFR"),
 	SND_SOC_DAPM_OUTPUT("EP"),
+	SND_SOC_DAPM_OUTPUT("AUXL"),
+	SND_SOC_DAPM_OUTPUT("AUXR"),
+	SND_SOC_DAPM_OUTPUT("VIBRAL"),
+	SND_SOC_DAPM_OUTPUT("VIBRAR"),
 
 	/* Analog input muxes for the capture amplifiers */
 	SND_SOC_DAPM_MUX("Analog Left Capture Route",
@@ -1114,59 +1112,76 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
 			TWL6040_REG_DMICBCTL, 4, 0),
 
 	/* DACs */
-	SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback",
-			TWL6040_REG_HSLCTL, 0, 0,
-			twl6040_hs_dac_event,
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_DAC_E("HSDAC Right", "Headset Playback",
-			TWL6040_REG_HSRCTL, 0, 0,
-			twl6040_hs_dac_event,
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
-			TWL6040_REG_HFLCTL, 0, 0,
-			twl6040_power_mode_event,
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
-			TWL6040_REG_HFRCTL, 0, 0,
-			twl6040_power_mode_event,
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_MUX("HF Left Playback",
+	SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback",
+			 TWL6040_REG_HFLCTL, 0, 0),
+	SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback",
+			 TWL6040_REG_HFRCTL, 0, 0),
+	/* Virtual DAC for vibra path (DL4 channel) */
+	SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback",
+			SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MUX("Handsfree Left Playback",
 			SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
-	SND_SOC_DAPM_MUX("HF Right Playback",
+	SND_SOC_DAPM_MUX("Handsfree Right Playback",
 			SND_SOC_NOPM, 0, 0, &hfr_mux_controls),
 	/* Analog playback Muxes */
-	SND_SOC_DAPM_MUX("HS Left Playback",
+	SND_SOC_DAPM_MUX("Headset Left Playback",
 			SND_SOC_NOPM, 0, 0, &hsl_mux_controls),
-	SND_SOC_DAPM_MUX("HS Right Playback",
+	SND_SOC_DAPM_MUX("Headset Right Playback",
 			SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
 
+	SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0,
+			&vibral_mux_controls),
+	SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0,
+			&vibrar_mux_controls),
+
+	SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
+			&ep_path_enable_control),
+	SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0,
+			&auxl_switch_control),
+	SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0,
+			&auxr_switch_control),
+
 	/* Analog playback drivers */
-	SND_SOC_DAPM_OUT_DRV_E("Handsfree Left Driver",
+	SND_SOC_DAPM_OUT_DRV_E("HF Left Driver",
 			TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
-			pga_event,
+			out_drv_event,
 			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-	SND_SOC_DAPM_OUT_DRV_E("Handsfree Right Driver",
+	SND_SOC_DAPM_OUT_DRV_E("HF Right Driver",
 			TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
-			pga_event,
+			out_drv_event,
 			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-	SND_SOC_DAPM_OUT_DRV_E("Headset Left Driver",
+	SND_SOC_DAPM_OUT_DRV_E("HS Left Driver",
 			TWL6040_REG_HSLCTL, 2, 0, NULL, 0,
-			pga_event,
+			out_drv_event,
 			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-	SND_SOC_DAPM_OUT_DRV_E("Headset Right Driver",
+	SND_SOC_DAPM_OUT_DRV_E("HS Right Driver",
 			TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
-			pga_event,
+			out_drv_event,
 			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-	SND_SOC_DAPM_SWITCH_E("Earphone Driver",
-			SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
-			twl6040_power_mode_event,
-			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
+			TWL6040_REG_EARCTL, 0, 0, NULL, 0,
+			twl6040_ep_drv_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_OUT_DRV("Vibra Left Driver",
+			TWL6040_REG_VIBCTLL, 0, 0, NULL, 0),
+	SND_SOC_DAPM_OUT_DRV("Vibra Right Driver",
+			TWL6040_REG_VIBCTLR, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0,
+			    NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0,
+			    NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0,
+			      twl6040_hs_dac_event,
+			      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 	/* Analog playback PGAs */
-	SND_SOC_DAPM_PGA("HFDAC Left PGA",
+	SND_SOC_DAPM_PGA("HF Left PGA",
 			TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HFDAC Right PGA",
+	SND_SOC_DAPM_PGA("HF Right PGA",
 			TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
 
 };
@@ -1188,52 +1203,62 @@ static const struct snd_soc_dapm_route intercon[] = {
 	{"ADC Right", NULL, "MicAmpR"},
 
 	/* AFM path */
-	{"AFMAmpL", "NULL", "AFML"},
-	{"AFMAmpR", "NULL", "AFMR"},
+	{"AFMAmpL", NULL, "AFML"},
+	{"AFMAmpR", NULL, "AFMR"},
 
-	{"HS Left Playback", "HS DAC", "HSDAC Left"},
-	{"HS Left Playback", "Line-In amp", "AFMAmpL"},
+	{"HSDAC Left", NULL, "HSDAC Power"},
+	{"HSDAC Right", NULL, "HSDAC Power"},
 
-	{"HS Right Playback", "HS DAC", "HSDAC Right"},
-	{"HS Right Playback", "Line-In amp", "AFMAmpR"},
+	{"Headset Left Playback", "HS DAC", "HSDAC Left"},
+	{"Headset Left Playback", "Line-In amp", "AFMAmpL"},
 
-	{"Headset Left Driver", "NULL", "HS Left Playback"},
-	{"Headset Right Driver", "NULL", "HS Right Playback"},
+	{"Headset Right Playback", "HS DAC", "HSDAC Right"},
+	{"Headset Right Playback", "Line-In amp", "AFMAmpR"},
 
-	{"HSOL", NULL, "Headset Left Driver"},
-	{"HSOR", NULL, "Headset Right Driver"},
+	{"HS Left Driver", NULL, "Headset Left Playback"},
+	{"HS Right Driver", NULL, "Headset Right Playback"},
+
+	{"HSOL", NULL, "HS Left Driver"},
+	{"HSOR", NULL, "HS Right Driver"},
 
 	/* Earphone playback path */
-	{"Earphone Driver", "Switch", "HSDAC Left"},
+	{"Earphone Playback", "Switch", "HSDAC Left"},
+	{"Earphone Driver", NULL, "Earphone Playback"},
 	{"EP", NULL, "Earphone Driver"},
 
-	{"HF Left Playback", "HF DAC", "HFDAC Left"},
-	{"HF Left Playback", "Line-In amp", "AFMAmpL"},
+	{"Handsfree Left Playback", "HF DAC", "HFDAC Left"},
+	{"Handsfree Left Playback", "Line-In amp", "AFMAmpL"},
 
-	{"HF Right Playback", "HF DAC", "HFDAC Right"},
-	{"HF Right Playback", "Line-In amp", "AFMAmpR"},
+	{"Handsfree Right Playback", "HF DAC", "HFDAC Right"},
+	{"Handsfree Right Playback", "Line-In amp", "AFMAmpR"},
 
-	{"HFDAC Left PGA", NULL, "HF Left Playback"},
-	{"HFDAC Right PGA", NULL, "HF Right Playback"},
+	{"HF Left PGA", NULL, "Handsfree Left Playback"},
+	{"HF Right PGA", NULL, "Handsfree Right Playback"},
 
-	{"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
-	{"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
+	{"HF Left Driver", NULL, "HF Left PGA"},
+	{"HF Right Driver", NULL, "HF Right PGA"},
 
-	{"HFL", NULL, "Handsfree Left Driver"},
-	{"HFR", NULL, "Handsfree Right Driver"},
-};
+	{"HFL", NULL, "HF Left Driver"},
+	{"HFR", NULL, "HF Right Driver"},
 
-static int twl6040_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	{"AUXL Playback", "Switch", "HF Left PGA"},
+	{"AUXR Playback", "Switch", "HF Right PGA"},
 
-	snd_soc_dapm_new_controls(dapm, twl6040_dapm_widgets,
-				 ARRAY_SIZE(twl6040_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-	snd_soc_dapm_new_widgets(dapm);
+	{"AUXL", NULL, "AUXL Playback"},
+	{"AUXR", NULL, "AUXR Playback"},
 
-	return 0;
-}
+	/* Vibrator paths */
+	{"Vibra Left Playback", "Audio PDM", "VIBRA DAC"},
+	{"Vibra Right Playback", "Audio PDM", "VIBRA DAC"},
+
+	{"Vibra Left Driver", NULL, "Vibra Left Playback"},
+	{"Vibra Right Driver", NULL, "Vibra Right Playback"},
+	{"Vibra Left Driver", NULL, "Vibra Left Control"},
+	{"Vibra Right Driver", NULL, "Vibra Right Control"},
+
+	{"VIBRAL", NULL, "Vibra Left Driver"},
+	{"VIBRAR", NULL, "Vibra Right Driver"},
+};
 
 static int twl6040_set_bias_level(struct snd_soc_codec *codec,
 				enum snd_soc_bias_level level)
@@ -1311,13 +1336,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
 				rate);
 			return -EINVAL;
 		}
-		/* Capture is not supported with 17.64MHz sysclk */
-		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-			dev_err(codec->dev,
-				"capture mode is not supported at %dHz\n",
-				rate);
-			return -EINVAL;
-		}
 		priv->sysclk = 17640000;
 		break;
 	case 8000:
@@ -1350,13 +1368,6 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	if ((priv->sysclk == 17640000) && priv->non_lp) {
-			dev_err(codec->dev,
-				"some enabled paths aren't supported at %dHz\n",
-				priv->sysclk);
-			return -EPERM;
-	}
-
 	ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk);
 	if (ret) {
 		dev_err(codec->dev, "Can not set PLL (%d)\n", ret);
@@ -1395,7 +1406,7 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
 
 static struct snd_soc_dai_driver twl6040_dai[] = {
 {
-	.name = "twl6040-hifi",
+	.name = "twl6040-legacy",
 	.playback = {
 		.stream_name = "Playback",
 		.channels_min = 1,
@@ -1493,6 +1504,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
 	priv->codec = codec;
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	codec->ignore_pmdown_time = 1;
 
 	if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
 		priv->hs_left_step = pdata->hs_left_step;
@@ -1517,33 +1529,21 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 		goto work_err;
 	}
 
-	priv->workqueue = create_singlethread_workqueue("twl6040-codec");
+	priv->workqueue = alloc_workqueue("twl6040-codec", 0, 0);
 	if (!priv->workqueue) {
 		ret = -ENOMEM;
 		goto work_err;
 	}
 
-	INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
+	INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
+	INIT_DELAYED_WORK(&priv->headset.work, twl6040_pga_hs_work);
+	INIT_DELAYED_WORK(&priv->handsfree.work, twl6040_pga_hf_work);
 
 	mutex_init(&priv->mutex);
 
 	init_completion(&priv->headset.ramp_done);
 	init_completion(&priv->handsfree.ramp_done);
 
-	priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
-	if (priv->hf_workqueue == NULL) {
-		ret = -ENOMEM;
-		goto hfwq_err;
-	}
-	priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
-	if (priv->hs_workqueue == NULL) {
-		ret = -ENOMEM;
-		goto hswq_err;
-	}
-
-	INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
-	INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
-
 	ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler,
 				   0, "twl6040_irq_plug", codec);
 	if (ret) {
@@ -1555,22 +1555,12 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
 	/* power on device */
 	ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	if (ret)
-		goto bias_err;
-
-	snd_soc_add_controls(codec, twl6040_snd_controls,
-				ARRAY_SIZE(twl6040_snd_controls));
-	twl6040_add_widgets(codec);
-
-	return 0;
+	if (!ret)
+		return 0;
 
-bias_err:
+	/* Error path */
 	free_irq(priv->plug_irq, codec);
 plugirq_err:
-	destroy_workqueue(priv->hs_workqueue);
-hswq_err:
-	destroy_workqueue(priv->hf_workqueue);
-hfwq_err:
 	destroy_workqueue(priv->workqueue);
 work_err:
 	kfree(priv);
@@ -1584,8 +1574,6 @@ static int twl6040_remove(struct snd_soc_codec *codec)
 	twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	free_irq(priv->plug_irq, codec);
 	destroy_workqueue(priv->workqueue);
-	destroy_workqueue(priv->hf_workqueue);
-	destroy_workqueue(priv->hs_workqueue);
 	kfree(priv);
 
 	return 0;
@@ -1602,6 +1590,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
 	.reg_cache_size = ARRAY_SIZE(twl6040_reg),
 	.reg_word_size = sizeof(u8),
 	.reg_cache_default = twl6040_reg,
+
+	.controls = twl6040_snd_controls,
+	.num_controls = ARRAY_SIZE(twl6040_snd_controls),
+	.dapm_widgets = twl6040_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
+	.dapm_routes = intercon,
+	.num_dapm_routes = ARRAY_SIZE(intercon),
 };
 
 static int __devinit twl6040_codec_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index d8de67869dd9..a83277bdb851 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -22,8 +22,21 @@
 #ifndef __TWL6040_H__
 #define __TWL6040_H__
 
+enum twl6040_trim {
+	TWL6040_TRIM_TRIM1 = 0,
+	TWL6040_TRIM_TRIM2,
+	TWL6040_TRIM_TRIM3,
+	TWL6040_TRIM_HSOTRIM,
+	TWL6040_TRIM_HFOTRIM,
+	TWL6040_TRIM_INVAL,
+};
+
+#define TWL6040_HSF_TRIM_LEFT(x)	(x & 0x0f)
+#define TWL6040_HSF_TRIM_RIGHT(x)	((x >> 4) & 0x0f)
+
 void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
 			    struct snd_soc_jack *jack, int report);
 int twl6040_get_clk_id(struct snd_soc_codec *codec);
+int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim);
 
 #endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 5836201834d9..9fa14299cf2c 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -462,7 +462,6 @@ static int wl1273_probe(struct snd_soc_codec *codec)
 	wl1273->core = *core;
 
 	snd_soc_codec_set_drvdata(codec, wl1273);
-	mutex_init(&codec->mutex);
 
 	r = snd_soc_add_controls(codec, wl1273_controls,
 				 ARRAY_SIZE(wl1273_controls));
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index 4523c4cec02b..cd0ec0fd1dba 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -12,10 +12,59 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
 
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/wm1250-ev1.h>
+
+static const char *wm1250_gpio_names[WM1250_EV1_NUM_GPIOS] = {
+	"WM1250 CLK_ENA",
+	"WM1250 CLK_SEL0",
+	"WM1250 CLK_SEL1",
+	"WM1250 OSR",
+	"WM1250 MASTER",
+};
+
+struct wm1250_priv {
+	struct gpio gpios[WM1250_EV1_NUM_GPIOS];
+};
+
+static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec,
+				     enum snd_soc_bias_level level)
+{
+	struct wm1250_priv *wm1250 = dev_get_drvdata(codec->dev);
+	int ena;
+
+	if (wm1250)
+		ena = wm1250->gpios[WM1250_EV1_GPIO_CLK_ENA].gpio;
+	else
+		ena = -1;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (ena >= 0)
+			gpio_set_value_cansleep(ena, 1);
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		if (ena >= 0)
+			gpio_set_value_cansleep(ena, 0);
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
 
 static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = {
 SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0),
@@ -53,12 +102,67 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
 	.num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets),
 	.dapm_routes = wm1250_ev1_dapm_routes,
 	.num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes),
+
+	.set_bias_level = wm1250_ev1_set_bias_level,
+	.idle_bias_off = true,
 };
 
+static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
+{
+	struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
+	struct wm1250_priv *wm1250;
+	int i, ret;
+
+	if (!pdata)
+		return 0;
+
+	wm1250 = kzalloc(sizeof(*wm1250), GFP_KERNEL);
+	if (!wm1250) {
+		dev_err(&i2c->dev, "Unable to allocate private data\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm1250->gpios); i++) {
+		wm1250->gpios[i].gpio = pdata->gpios[i];
+		wm1250->gpios[i].label = wm1250_gpio_names[i];
+		wm1250->gpios[i].flags = GPIOF_OUT_INIT_LOW;
+	}
+	wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].flags = GPIOF_OUT_INIT_HIGH;
+	wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].flags = GPIOF_OUT_INIT_HIGH;
+
+	ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret);
+		goto err_alloc;
+	}
+
+	dev_set_drvdata(&i2c->dev, wm1250);
+
+	return ret;
+
+err_alloc:
+	kfree(wm1250);
+err:
+	return ret;
+}
+
+static void wm1250_ev1_free(struct i2c_client *i2c)
+{
+	struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev);
+
+	if (wm1250) {
+		gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+		kfree(wm1250);
+	}
+}
+
 static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *i2c_id)
 {
-	int id, board, rev;
+	int id, board, rev, ret;
+
+	dev_set_drvdata(&i2c->dev, NULL);
 
 	board = i2c_smbus_read_byte_data(i2c, 0);
 	if (board < 0) {
@@ -76,13 +180,25 @@ static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
 
 	dev_info(&i2c->dev, "revision %d\n", rev + 1);
 
-	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
-				      &wm1250_ev1_dai, 1);
+	ret = wm1250_ev1_pdata(i2c);
+	if (ret != 0)
+		return ret;
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
+				     &wm1250_ev1_dai, 1);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+		wm1250_ev1_free(i2c);
+		return ret;
+	}
+
+	return 0;
 }
 
 static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
 {
 	snd_soc_unregister_codec(&i2c->dev);
+	wm1250_ev1_free(i2c);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c
new file mode 100644
index 000000000000..e9ce81a57b85
--- /dev/null
+++ b/sound/soc/codecs/wm5100-tables.c
@@ -0,0 +1,1531 @@
+/*
+ * wm5100-tables.c  --  WM5100 ALSA SoC Audio driver data
+ *
+ * Copyright 2011 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 "wm5100.h"
+
+int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+{
+	switch (reg) {
+	case WM5100_SOFTWARE_RESET:
+	case WM5100_DEVICE_REVISION:
+	case WM5100_FX_CTRL:
+	case WM5100_INTERRUPT_STATUS_1:
+	case WM5100_INTERRUPT_STATUS_2:
+	case WM5100_INTERRUPT_STATUS_3:
+	case WM5100_INTERRUPT_STATUS_4:
+	case WM5100_INTERRUPT_RAW_STATUS_2:
+	case WM5100_INTERRUPT_RAW_STATUS_3:
+	case WM5100_INTERRUPT_RAW_STATUS_4:
+	case WM5100_OUTPUT_STATUS_1:
+	case WM5100_OUTPUT_STATUS_2:
+	case WM5100_INPUT_ENABLES_STATUS:
+	case WM5100_MIC_DETECT_3:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg)
+{
+	switch (reg) {
+	case WM5100_SOFTWARE_RESET:
+	case WM5100_DEVICE_REVISION:
+	case WM5100_CTRL_IF_1:
+	case WM5100_TONE_GENERATOR_1:
+	case WM5100_PWM_DRIVE_1:
+	case WM5100_PWM_DRIVE_2:
+	case WM5100_PWM_DRIVE_3:
+	case WM5100_CLOCKING_1:
+	case WM5100_CLOCKING_3:
+	case WM5100_CLOCKING_4:
+	case WM5100_CLOCKING_5:
+	case WM5100_CLOCKING_6:
+	case WM5100_CLOCKING_7:
+	case WM5100_CLOCKING_8:
+	case WM5100_ASRC_ENABLE:
+	case WM5100_ASRC_STATUS:
+	case WM5100_ASRC_RATE1:
+	case WM5100_ISRC_1_CTRL_1:
+	case WM5100_ISRC_1_CTRL_2:
+	case WM5100_ISRC_2_CTRL1:
+	case WM5100_ISRC_2_CTRL_2:
+	case WM5100_FLL1_CONTROL_1:
+	case WM5100_FLL1_CONTROL_2:
+	case WM5100_FLL1_CONTROL_3:
+	case WM5100_FLL1_CONTROL_5:
+	case WM5100_FLL1_CONTROL_6:
+	case WM5100_FLL1_EFS_1:
+	case WM5100_FLL2_CONTROL_1:
+	case WM5100_FLL2_CONTROL_2:
+	case WM5100_FLL2_CONTROL_3:
+	case WM5100_FLL2_CONTROL_5:
+	case WM5100_FLL2_CONTROL_6:
+	case WM5100_FLL2_EFS_1:
+	case WM5100_MIC_CHARGE_PUMP_1:
+	case WM5100_MIC_CHARGE_PUMP_2:
+	case WM5100_HP_CHARGE_PUMP_1:
+	case WM5100_LDO1_CONTROL:
+	case WM5100_MIC_BIAS_CTRL_1:
+	case WM5100_MIC_BIAS_CTRL_2:
+	case WM5100_MIC_BIAS_CTRL_3:
+	case WM5100_ACCESSORY_DETECT_MODE_1:
+	case WM5100_HEADPHONE_DETECT_1:
+	case WM5100_HEADPHONE_DETECT_2:
+	case WM5100_MIC_DETECT_1:
+	case WM5100_MIC_DETECT_2:
+	case WM5100_MIC_DETECT_3:
+	case WM5100_INPUT_ENABLES:
+	case WM5100_INPUT_ENABLES_STATUS:
+	case WM5100_IN1L_CONTROL:
+	case WM5100_IN1R_CONTROL:
+	case WM5100_IN2L_CONTROL:
+	case WM5100_IN2R_CONTROL:
+	case WM5100_IN3L_CONTROL:
+	case WM5100_IN3R_CONTROL:
+	case WM5100_IN4L_CONTROL:
+	case WM5100_IN4R_CONTROL:
+	case WM5100_RXANC_SRC:
+	case WM5100_INPUT_VOLUME_RAMP:
+	case WM5100_ADC_DIGITAL_VOLUME_1L:
+	case WM5100_ADC_DIGITAL_VOLUME_1R:
+	case WM5100_ADC_DIGITAL_VOLUME_2L:
+	case WM5100_ADC_DIGITAL_VOLUME_2R:
+	case WM5100_ADC_DIGITAL_VOLUME_3L:
+	case WM5100_ADC_DIGITAL_VOLUME_3R:
+	case WM5100_ADC_DIGITAL_VOLUME_4L:
+	case WM5100_ADC_DIGITAL_VOLUME_4R:
+	case WM5100_OUTPUT_ENABLES_2:
+	case WM5100_OUTPUT_STATUS_1:
+	case WM5100_OUTPUT_STATUS_2:
+	case WM5100_CHANNEL_ENABLES_1:
+	case WM5100_OUT_VOLUME_1L:
+	case WM5100_OUT_VOLUME_1R:
+	case WM5100_DAC_VOLUME_LIMIT_1L:
+	case WM5100_DAC_VOLUME_LIMIT_1R:
+	case WM5100_OUT_VOLUME_2L:
+	case WM5100_OUT_VOLUME_2R:
+	case WM5100_DAC_VOLUME_LIMIT_2L:
+	case WM5100_DAC_VOLUME_LIMIT_2R:
+	case WM5100_OUT_VOLUME_3L:
+	case WM5100_OUT_VOLUME_3R:
+	case WM5100_DAC_VOLUME_LIMIT_3L:
+	case WM5100_DAC_VOLUME_LIMIT_3R:
+	case WM5100_OUT_VOLUME_4L:
+	case WM5100_OUT_VOLUME_4R:
+	case WM5100_DAC_VOLUME_LIMIT_5L:
+	case WM5100_DAC_VOLUME_LIMIT_5R:
+	case WM5100_DAC_VOLUME_LIMIT_6L:
+	case WM5100_DAC_VOLUME_LIMIT_6R:
+	case WM5100_DAC_AEC_CONTROL_1:
+	case WM5100_OUTPUT_VOLUME_RAMP:
+	case WM5100_DAC_DIGITAL_VOLUME_1L:
+	case WM5100_DAC_DIGITAL_VOLUME_1R:
+	case WM5100_DAC_DIGITAL_VOLUME_2L:
+	case WM5100_DAC_DIGITAL_VOLUME_2R:
+	case WM5100_DAC_DIGITAL_VOLUME_3L:
+	case WM5100_DAC_DIGITAL_VOLUME_3R:
+	case WM5100_DAC_DIGITAL_VOLUME_4L:
+	case WM5100_DAC_DIGITAL_VOLUME_4R:
+	case WM5100_DAC_DIGITAL_VOLUME_5L:
+	case WM5100_DAC_DIGITAL_VOLUME_5R:
+	case WM5100_DAC_DIGITAL_VOLUME_6L:
+	case WM5100_DAC_DIGITAL_VOLUME_6R:
+	case WM5100_PDM_SPK1_CTRL_1:
+	case WM5100_PDM_SPK1_CTRL_2:
+	case WM5100_PDM_SPK2_CTRL_1:
+	case WM5100_PDM_SPK2_CTRL_2:
+	case WM5100_AUDIO_IF_1_1:
+	case WM5100_AUDIO_IF_1_2:
+	case WM5100_AUDIO_IF_1_3:
+	case WM5100_AUDIO_IF_1_4:
+	case WM5100_AUDIO_IF_1_5:
+	case WM5100_AUDIO_IF_1_6:
+	case WM5100_AUDIO_IF_1_7:
+	case WM5100_AUDIO_IF_1_8:
+	case WM5100_AUDIO_IF_1_9:
+	case WM5100_AUDIO_IF_1_10:
+	case WM5100_AUDIO_IF_1_11:
+	case WM5100_AUDIO_IF_1_12:
+	case WM5100_AUDIO_IF_1_13:
+	case WM5100_AUDIO_IF_1_14:
+	case WM5100_AUDIO_IF_1_15:
+	case WM5100_AUDIO_IF_1_16:
+	case WM5100_AUDIO_IF_1_17:
+	case WM5100_AUDIO_IF_1_18:
+	case WM5100_AUDIO_IF_1_19:
+	case WM5100_AUDIO_IF_1_20:
+	case WM5100_AUDIO_IF_1_21:
+	case WM5100_AUDIO_IF_1_22:
+	case WM5100_AUDIO_IF_1_23:
+	case WM5100_AUDIO_IF_1_24:
+	case WM5100_AUDIO_IF_1_25:
+	case WM5100_AUDIO_IF_1_26:
+	case WM5100_AUDIO_IF_1_27:
+	case WM5100_AUDIO_IF_2_1:
+	case WM5100_AUDIO_IF_2_2:
+	case WM5100_AUDIO_IF_2_3:
+	case WM5100_AUDIO_IF_2_4:
+	case WM5100_AUDIO_IF_2_5:
+	case WM5100_AUDIO_IF_2_6:
+	case WM5100_AUDIO_IF_2_7:
+	case WM5100_AUDIO_IF_2_8:
+	case WM5100_AUDIO_IF_2_9:
+	case WM5100_AUDIO_IF_2_10:
+	case WM5100_AUDIO_IF_2_11:
+	case WM5100_AUDIO_IF_2_18:
+	case WM5100_AUDIO_IF_2_19:
+	case WM5100_AUDIO_IF_2_26:
+	case WM5100_AUDIO_IF_2_27:
+	case WM5100_AUDIO_IF_3_1:
+	case WM5100_AUDIO_IF_3_2:
+	case WM5100_AUDIO_IF_3_3:
+	case WM5100_AUDIO_IF_3_4:
+	case WM5100_AUDIO_IF_3_5:
+	case WM5100_AUDIO_IF_3_6:
+	case WM5100_AUDIO_IF_3_7:
+	case WM5100_AUDIO_IF_3_8:
+	case WM5100_AUDIO_IF_3_9:
+	case WM5100_AUDIO_IF_3_10:
+	case WM5100_AUDIO_IF_3_11:
+	case WM5100_AUDIO_IF_3_18:
+	case WM5100_AUDIO_IF_3_19:
+	case WM5100_AUDIO_IF_3_26:
+	case WM5100_AUDIO_IF_3_27:
+	case WM5100_PWM1MIX_INPUT_1_SOURCE:
+	case WM5100_PWM1MIX_INPUT_1_VOLUME:
+	case WM5100_PWM1MIX_INPUT_2_SOURCE:
+	case WM5100_PWM1MIX_INPUT_2_VOLUME:
+	case WM5100_PWM1MIX_INPUT_3_SOURCE:
+	case WM5100_PWM1MIX_INPUT_3_VOLUME:
+	case WM5100_PWM1MIX_INPUT_4_SOURCE:
+	case WM5100_PWM1MIX_INPUT_4_VOLUME:
+	case WM5100_PWM2MIX_INPUT_1_SOURCE:
+	case WM5100_PWM2MIX_INPUT_1_VOLUME:
+	case WM5100_PWM2MIX_INPUT_2_SOURCE:
+	case WM5100_PWM2MIX_INPUT_2_VOLUME:
+	case WM5100_PWM2MIX_INPUT_3_SOURCE:
+	case WM5100_PWM2MIX_INPUT_3_VOLUME:
+	case WM5100_PWM2MIX_INPUT_4_SOURCE:
+	case WM5100_PWM2MIX_INPUT_4_VOLUME:
+	case WM5100_OUT1LMIX_INPUT_1_SOURCE:
+	case WM5100_OUT1LMIX_INPUT_1_VOLUME:
+	case WM5100_OUT1LMIX_INPUT_2_SOURCE:
+	case WM5100_OUT1LMIX_INPUT_2_VOLUME:
+	case WM5100_OUT1LMIX_INPUT_3_SOURCE:
+	case WM5100_OUT1LMIX_INPUT_3_VOLUME:
+	case WM5100_OUT1LMIX_INPUT_4_SOURCE:
+	case WM5100_OUT1LMIX_INPUT_4_VOLUME:
+	case WM5100_OUT1RMIX_INPUT_1_SOURCE:
+	case WM5100_OUT1RMIX_INPUT_1_VOLUME:
+	case WM5100_OUT1RMIX_INPUT_2_SOURCE:
+	case WM5100_OUT1RMIX_INPUT_2_VOLUME:
+	case WM5100_OUT1RMIX_INPUT_3_SOURCE:
+	case WM5100_OUT1RMIX_INPUT_3_VOLUME:
+	case WM5100_OUT1RMIX_INPUT_4_SOURCE:
+	case WM5100_OUT1RMIX_INPUT_4_VOLUME:
+	case WM5100_OUT2LMIX_INPUT_1_SOURCE:
+	case WM5100_OUT2LMIX_INPUT_1_VOLUME:
+	case WM5100_OUT2LMIX_INPUT_2_SOURCE:
+	case WM5100_OUT2LMIX_INPUT_2_VOLUME:
+	case WM5100_OUT2LMIX_INPUT_3_SOURCE:
+	case WM5100_OUT2LMIX_INPUT_3_VOLUME:
+	case WM5100_OUT2LMIX_INPUT_4_SOURCE:
+	case WM5100_OUT2LMIX_INPUT_4_VOLUME:
+	case WM5100_OUT2RMIX_INPUT_1_SOURCE:
+	case WM5100_OUT2RMIX_INPUT_1_VOLUME:
+	case WM5100_OUT2RMIX_INPUT_2_SOURCE:
+	case WM5100_OUT2RMIX_INPUT_2_VOLUME:
+	case WM5100_OUT2RMIX_INPUT_3_SOURCE:
+	case WM5100_OUT2RMIX_INPUT_3_VOLUME:
+	case WM5100_OUT2RMIX_INPUT_4_SOURCE:
+	case WM5100_OUT2RMIX_INPUT_4_VOLUME:
+	case WM5100_OUT3LMIX_INPUT_1_SOURCE:
+	case WM5100_OUT3LMIX_INPUT_1_VOLUME:
+	case WM5100_OUT3LMIX_INPUT_2_SOURCE:
+	case WM5100_OUT3LMIX_INPUT_2_VOLUME:
+	case WM5100_OUT3LMIX_INPUT_3_SOURCE:
+	case WM5100_OUT3LMIX_INPUT_3_VOLUME:
+	case WM5100_OUT3LMIX_INPUT_4_SOURCE:
+	case WM5100_OUT3LMIX_INPUT_4_VOLUME:
+	case WM5100_OUT3RMIX_INPUT_1_SOURCE:
+	case WM5100_OUT3RMIX_INPUT_1_VOLUME:
+	case WM5100_OUT3RMIX_INPUT_2_SOURCE:
+	case WM5100_OUT3RMIX_INPUT_2_VOLUME:
+	case WM5100_OUT3RMIX_INPUT_3_SOURCE:
+	case WM5100_OUT3RMIX_INPUT_3_VOLUME:
+	case WM5100_OUT3RMIX_INPUT_4_SOURCE:
+	case WM5100_OUT3RMIX_INPUT_4_VOLUME:
+	case WM5100_OUT4LMIX_INPUT_1_SOURCE:
+	case WM5100_OUT4LMIX_INPUT_1_VOLUME:
+	case WM5100_OUT4LMIX_INPUT_2_SOURCE:
+	case WM5100_OUT4LMIX_INPUT_2_VOLUME:
+	case WM5100_OUT4LMIX_INPUT_3_SOURCE:
+	case WM5100_OUT4LMIX_INPUT_3_VOLUME:
+	case WM5100_OUT4LMIX_INPUT_4_SOURCE:
+	case WM5100_OUT4LMIX_INPUT_4_VOLUME:
+	case WM5100_OUT4RMIX_INPUT_1_SOURCE:
+	case WM5100_OUT4RMIX_INPUT_1_VOLUME:
+	case WM5100_OUT4RMIX_INPUT_2_SOURCE:
+	case WM5100_OUT4RMIX_INPUT_2_VOLUME:
+	case WM5100_OUT4RMIX_INPUT_3_SOURCE:
+	case WM5100_OUT4RMIX_INPUT_3_VOLUME:
+	case WM5100_OUT4RMIX_INPUT_4_SOURCE:
+	case WM5100_OUT4RMIX_INPUT_4_VOLUME:
+	case WM5100_OUT5LMIX_INPUT_1_SOURCE:
+	case WM5100_OUT5LMIX_INPUT_1_VOLUME:
+	case WM5100_OUT5LMIX_INPUT_2_SOURCE:
+	case WM5100_OUT5LMIX_INPUT_2_VOLUME:
+	case WM5100_OUT5LMIX_INPUT_3_SOURCE:
+	case WM5100_OUT5LMIX_INPUT_3_VOLUME:
+	case WM5100_OUT5LMIX_INPUT_4_SOURCE:
+	case WM5100_OUT5LMIX_INPUT_4_VOLUME:
+	case WM5100_OUT5RMIX_INPUT_1_SOURCE:
+	case WM5100_OUT5RMIX_INPUT_1_VOLUME:
+	case WM5100_OUT5RMIX_INPUT_2_SOURCE:
+	case WM5100_OUT5RMIX_INPUT_2_VOLUME:
+	case WM5100_OUT5RMIX_INPUT_3_SOURCE:
+	case WM5100_OUT5RMIX_INPUT_3_VOLUME:
+	case WM5100_OUT5RMIX_INPUT_4_SOURCE:
+	case WM5100_OUT5RMIX_INPUT_4_VOLUME:
+	case WM5100_OUT6LMIX_INPUT_1_SOURCE:
+	case WM5100_OUT6LMIX_INPUT_1_VOLUME:
+	case WM5100_OUT6LMIX_INPUT_2_SOURCE:
+	case WM5100_OUT6LMIX_INPUT_2_VOLUME:
+	case WM5100_OUT6LMIX_INPUT_3_SOURCE:
+	case WM5100_OUT6LMIX_INPUT_3_VOLUME:
+	case WM5100_OUT6LMIX_INPUT_4_SOURCE:
+	case WM5100_OUT6LMIX_INPUT_4_VOLUME:
+	case WM5100_OUT6RMIX_INPUT_1_SOURCE:
+	case WM5100_OUT6RMIX_INPUT_1_VOLUME:
+	case WM5100_OUT6RMIX_INPUT_2_SOURCE:
+	case WM5100_OUT6RMIX_INPUT_2_VOLUME:
+	case WM5100_OUT6RMIX_INPUT_3_SOURCE:
+	case WM5100_OUT6RMIX_INPUT_3_VOLUME:
+	case WM5100_OUT6RMIX_INPUT_4_SOURCE:
+	case WM5100_OUT6RMIX_INPUT_4_VOLUME:
+	case WM5100_AIF1TX1MIX_INPUT_1_SOURCE:
+	case WM5100_AIF1TX1MIX_INPUT_1_VOLUME:
+	case WM5100_AIF1TX1MIX_INPUT_2_SOURCE:
+	case WM5100_AIF1TX1MIX_INPUT_2_VOLUME:
+	case WM5100_AIF1TX1MIX_INPUT_3_SOURCE:
+	case WM5100_AIF1TX1MIX_INPUT_3_VOLUME:
+	case WM5100_AIF1TX1MIX_INPUT_4_SOURCE:
+	case WM5100_AIF1TX1MIX_INPUT_4_VOLUME:
+	case WM5100_AIF1TX2MIX_INPUT_1_SOURCE:
+	case WM5100_AIF1TX2MIX_INPUT_1_VOLUME:
+	case WM5100_AIF1TX2MIX_INPUT_2_SOURCE:
+	case WM5100_AIF1TX2MIX_INPUT_2_VOLUME:
+	case WM5100_AIF1TX2MIX_INPUT_3_SOURCE:
+	case WM5100_AIF1TX2MIX_INPUT_3_VOLUME:
+	case WM5100_AIF1TX2MIX_INPUT_4_SOURCE:
+	case WM5100_AIF1TX2MIX_INPUT_4_VOLUME:
+	case WM5100_AIF1TX3MIX_INPUT_1_SOURCE:
+	case WM5100_AIF1TX3MIX_INPUT_1_VOLUME:
+	case WM5100_AIF1TX3MIX_INPUT_2_SOURCE:
+	case WM5100_AIF1TX3MIX_INPUT_2_VOLUME:
+	case WM5100_AIF1TX3MIX_INPUT_3_SOURCE:
+	case WM5100_AIF1TX3MIX_INPUT_3_VOLUME:
+	case WM5100_AIF1TX3MIX_INPUT_4_SOURCE:
+	case WM5100_AIF1TX3MIX_INPUT_4_VOLUME:
+	case WM5100_AIF1TX4MIX_INPUT_1_SOURCE:
+	case WM5100_AIF1TX4MIX_INPUT_1_VOLUME:
+	case WM5100_AIF1TX4MIX_INPUT_2_SOURCE:
+	case WM5100_AIF1TX4MIX_INPUT_2_VOLUME:
+	case WM5100_AIF1TX4MIX_INPUT_3_SOURCE:
+	case WM5100_AIF1TX4MIX_INPUT_3_VOLUME:
+	case WM5100_AIF1TX4MIX_INPUT_4_SOURCE:
+	case WM5100_AIF1TX4MIX_INPUT_4_VOLUME:
+	case WM5100_AIF1TX5MIX_INPUT_1_SOURCE:
+	case WM5100_AIF1TX5MIX_INPUT_1_VOLUME:
+	case WM5100_AIF1TX5MIX_INPUT_2_SOURCE:
+	case WM5100_AIF1TX5MIX_INPUT_2_VOLUME:
+	case WM5100_AIF1TX5MIX_INPUT_3_SOURCE:
+	case WM5100_AIF1TX5MIX_INPUT_3_VOLUME:
+	case WM5100_AIF1TX5MIX_INPUT_4_SOURCE:
+	case WM5100_AIF1TX5MIX_INPUT_4_VOLUME:
+	case WM5100_AIF1TX6MIX_INPUT_1_SOURCE:
+	case WM5100_AIF1TX6MIX_INPUT_1_VOLUME:
+	case WM5100_AIF1TX6MIX_INPUT_2_SOURCE:
+	case WM5100_AIF1TX6MIX_INPUT_2_VOLUME:
+	case WM5100_AIF1TX6MIX_INPUT_3_SOURCE:
+	case WM5100_AIF1TX6MIX_INPUT_3_VOLUME:
+	case WM5100_AIF1TX6MIX_INPUT_4_SOURCE:
+	case WM5100_AIF1TX6MIX_INPUT_4_VOLUME:
+	case WM5100_AIF1TX7MIX_INPUT_1_SOURCE:
+	case WM5100_AIF1TX7MIX_INPUT_1_VOLUME:
+	case WM5100_AIF1TX7MIX_INPUT_2_SOURCE:
+	case WM5100_AIF1TX7MIX_INPUT_2_VOLUME:
+	case WM5100_AIF1TX7MIX_INPUT_3_SOURCE:
+	case WM5100_AIF1TX7MIX_INPUT_3_VOLUME:
+	case WM5100_AIF1TX7MIX_INPUT_4_SOURCE:
+	case WM5100_AIF1TX7MIX_INPUT_4_VOLUME:
+	case WM5100_AIF1TX8MIX_INPUT_1_SOURCE:
+	case WM5100_AIF1TX8MIX_INPUT_1_VOLUME:
+	case WM5100_AIF1TX8MIX_INPUT_2_SOURCE:
+	case WM5100_AIF1TX8MIX_INPUT_2_VOLUME:
+	case WM5100_AIF1TX8MIX_INPUT_3_SOURCE:
+	case WM5100_AIF1TX8MIX_INPUT_3_VOLUME:
+	case WM5100_AIF1TX8MIX_INPUT_4_SOURCE:
+	case WM5100_AIF1TX8MIX_INPUT_4_VOLUME:
+	case WM5100_AIF2TX1MIX_INPUT_1_SOURCE:
+	case WM5100_AIF2TX1MIX_INPUT_1_VOLUME:
+	case WM5100_AIF2TX1MIX_INPUT_2_SOURCE:
+	case WM5100_AIF2TX1MIX_INPUT_2_VOLUME:
+	case WM5100_AIF2TX1MIX_INPUT_3_SOURCE:
+	case WM5100_AIF2TX1MIX_INPUT_3_VOLUME:
+	case WM5100_AIF2TX1MIX_INPUT_4_SOURCE:
+	case WM5100_AIF2TX1MIX_INPUT_4_VOLUME:
+	case WM5100_AIF2TX2MIX_INPUT_1_SOURCE:
+	case WM5100_AIF2TX2MIX_INPUT_1_VOLUME:
+	case WM5100_AIF2TX2MIX_INPUT_2_SOURCE:
+	case WM5100_AIF2TX2MIX_INPUT_2_VOLUME:
+	case WM5100_AIF2TX2MIX_INPUT_3_SOURCE:
+	case WM5100_AIF2TX2MIX_INPUT_3_VOLUME:
+	case WM5100_AIF2TX2MIX_INPUT_4_SOURCE:
+	case WM5100_AIF2TX2MIX_INPUT_4_VOLUME:
+	case WM5100_AIF3TX1MIX_INPUT_1_SOURCE:
+	case WM5100_AIF3TX1MIX_INPUT_1_VOLUME:
+	case WM5100_AIF3TX1MIX_INPUT_2_SOURCE:
+	case WM5100_AIF3TX1MIX_INPUT_2_VOLUME:
+	case WM5100_AIF3TX1MIX_INPUT_3_SOURCE:
+	case WM5100_AIF3TX1MIX_INPUT_3_VOLUME:
+	case WM5100_AIF3TX1MIX_INPUT_4_SOURCE:
+	case WM5100_AIF3TX1MIX_INPUT_4_VOLUME:
+	case WM5100_AIF3TX2MIX_INPUT_1_SOURCE:
+	case WM5100_AIF3TX2MIX_INPUT_1_VOLUME:
+	case WM5100_AIF3TX2MIX_INPUT_2_SOURCE:
+	case WM5100_AIF3TX2MIX_INPUT_2_VOLUME:
+	case WM5100_AIF3TX2MIX_INPUT_3_SOURCE:
+	case WM5100_AIF3TX2MIX_INPUT_3_VOLUME:
+	case WM5100_AIF3TX2MIX_INPUT_4_SOURCE:
+	case WM5100_AIF3TX2MIX_INPUT_4_VOLUME:
+	case WM5100_EQ1MIX_INPUT_1_SOURCE:
+	case WM5100_EQ1MIX_INPUT_1_VOLUME:
+	case WM5100_EQ1MIX_INPUT_2_SOURCE:
+	case WM5100_EQ1MIX_INPUT_2_VOLUME:
+	case WM5100_EQ1MIX_INPUT_3_SOURCE:
+	case WM5100_EQ1MIX_INPUT_3_VOLUME:
+	case WM5100_EQ1MIX_INPUT_4_SOURCE:
+	case WM5100_EQ1MIX_INPUT_4_VOLUME:
+	case WM5100_EQ2MIX_INPUT_1_SOURCE:
+	case WM5100_EQ2MIX_INPUT_1_VOLUME:
+	case WM5100_EQ2MIX_INPUT_2_SOURCE:
+	case WM5100_EQ2MIX_INPUT_2_VOLUME:
+	case WM5100_EQ2MIX_INPUT_3_SOURCE:
+	case WM5100_EQ2MIX_INPUT_3_VOLUME:
+	case WM5100_EQ2MIX_INPUT_4_SOURCE:
+	case WM5100_EQ2MIX_INPUT_4_VOLUME:
+	case WM5100_EQ3MIX_INPUT_1_SOURCE:
+	case WM5100_EQ3MIX_INPUT_1_VOLUME:
+	case WM5100_EQ3MIX_INPUT_2_SOURCE:
+	case WM5100_EQ3MIX_INPUT_2_VOLUME:
+	case WM5100_EQ3MIX_INPUT_3_SOURCE:
+	case WM5100_EQ3MIX_INPUT_3_VOLUME:
+	case WM5100_EQ3MIX_INPUT_4_SOURCE:
+	case WM5100_EQ3MIX_INPUT_4_VOLUME:
+	case WM5100_EQ4MIX_INPUT_1_SOURCE:
+	case WM5100_EQ4MIX_INPUT_1_VOLUME:
+	case WM5100_EQ4MIX_INPUT_2_SOURCE:
+	case WM5100_EQ4MIX_INPUT_2_VOLUME:
+	case WM5100_EQ4MIX_INPUT_3_SOURCE:
+	case WM5100_EQ4MIX_INPUT_3_VOLUME:
+	case WM5100_EQ4MIX_INPUT_4_SOURCE:
+	case WM5100_EQ4MIX_INPUT_4_VOLUME:
+	case WM5100_DRC1LMIX_INPUT_1_SOURCE:
+	case WM5100_DRC1LMIX_INPUT_1_VOLUME:
+	case WM5100_DRC1LMIX_INPUT_2_SOURCE:
+	case WM5100_DRC1LMIX_INPUT_2_VOLUME:
+	case WM5100_DRC1LMIX_INPUT_3_SOURCE:
+	case WM5100_DRC1LMIX_INPUT_3_VOLUME:
+	case WM5100_DRC1LMIX_INPUT_4_SOURCE:
+	case WM5100_DRC1LMIX_INPUT_4_VOLUME:
+	case WM5100_DRC1RMIX_INPUT_1_SOURCE:
+	case WM5100_DRC1RMIX_INPUT_1_VOLUME:
+	case WM5100_DRC1RMIX_INPUT_2_SOURCE:
+	case WM5100_DRC1RMIX_INPUT_2_VOLUME:
+	case WM5100_DRC1RMIX_INPUT_3_SOURCE:
+	case WM5100_DRC1RMIX_INPUT_3_VOLUME:
+	case WM5100_DRC1RMIX_INPUT_4_SOURCE:
+	case WM5100_DRC1RMIX_INPUT_4_VOLUME:
+	case WM5100_HPLP1MIX_INPUT_1_SOURCE:
+	case WM5100_HPLP1MIX_INPUT_1_VOLUME:
+	case WM5100_HPLP1MIX_INPUT_2_SOURCE:
+	case WM5100_HPLP1MIX_INPUT_2_VOLUME:
+	case WM5100_HPLP1MIX_INPUT_3_SOURCE:
+	case WM5100_HPLP1MIX_INPUT_3_VOLUME:
+	case WM5100_HPLP1MIX_INPUT_4_SOURCE:
+	case WM5100_HPLP1MIX_INPUT_4_VOLUME:
+	case WM5100_HPLP2MIX_INPUT_1_SOURCE:
+	case WM5100_HPLP2MIX_INPUT_1_VOLUME:
+	case WM5100_HPLP2MIX_INPUT_2_SOURCE:
+	case WM5100_HPLP2MIX_INPUT_2_VOLUME:
+	case WM5100_HPLP2MIX_INPUT_3_SOURCE:
+	case WM5100_HPLP2MIX_INPUT_3_VOLUME:
+	case WM5100_HPLP2MIX_INPUT_4_SOURCE:
+	case WM5100_HPLP2MIX_INPUT_4_VOLUME:
+	case WM5100_HPLP3MIX_INPUT_1_SOURCE:
+	case WM5100_HPLP3MIX_INPUT_1_VOLUME:
+	case WM5100_HPLP3MIX_INPUT_2_SOURCE:
+	case WM5100_HPLP3MIX_INPUT_2_VOLUME:
+	case WM5100_HPLP3MIX_INPUT_3_SOURCE:
+	case WM5100_HPLP3MIX_INPUT_3_VOLUME:
+	case WM5100_HPLP3MIX_INPUT_4_SOURCE:
+	case WM5100_HPLP3MIX_INPUT_4_VOLUME:
+	case WM5100_HPLP4MIX_INPUT_1_SOURCE:
+	case WM5100_HPLP4MIX_INPUT_1_VOLUME:
+	case WM5100_HPLP4MIX_INPUT_2_SOURCE:
+	case WM5100_HPLP4MIX_INPUT_2_VOLUME:
+	case WM5100_HPLP4MIX_INPUT_3_SOURCE:
+	case WM5100_HPLP4MIX_INPUT_3_VOLUME:
+	case WM5100_HPLP4MIX_INPUT_4_SOURCE:
+	case WM5100_HPLP4MIX_INPUT_4_VOLUME:
+	case WM5100_DSP1LMIX_INPUT_1_SOURCE:
+	case WM5100_DSP1LMIX_INPUT_1_VOLUME:
+	case WM5100_DSP1LMIX_INPUT_2_SOURCE:
+	case WM5100_DSP1LMIX_INPUT_2_VOLUME:
+	case WM5100_DSP1LMIX_INPUT_3_SOURCE:
+	case WM5100_DSP1LMIX_INPUT_3_VOLUME:
+	case WM5100_DSP1LMIX_INPUT_4_SOURCE:
+	case WM5100_DSP1LMIX_INPUT_4_VOLUME:
+	case WM5100_DSP1RMIX_INPUT_1_SOURCE:
+	case WM5100_DSP1RMIX_INPUT_1_VOLUME:
+	case WM5100_DSP1RMIX_INPUT_2_SOURCE:
+	case WM5100_DSP1RMIX_INPUT_2_VOLUME:
+	case WM5100_DSP1RMIX_INPUT_3_SOURCE:
+	case WM5100_DSP1RMIX_INPUT_3_VOLUME:
+	case WM5100_DSP1RMIX_INPUT_4_SOURCE:
+	case WM5100_DSP1RMIX_INPUT_4_VOLUME:
+	case WM5100_DSP1AUX1MIX_INPUT_1_SOURCE:
+	case WM5100_DSP1AUX2MIX_INPUT_1_SOURCE:
+	case WM5100_DSP1AUX3MIX_INPUT_1_SOURCE:
+	case WM5100_DSP1AUX4MIX_INPUT_1_SOURCE:
+	case WM5100_DSP1AUX5MIX_INPUT_1_SOURCE:
+	case WM5100_DSP1AUX6MIX_INPUT_1_SOURCE:
+	case WM5100_DSP2LMIX_INPUT_1_SOURCE:
+	case WM5100_DSP2LMIX_INPUT_1_VOLUME:
+	case WM5100_DSP2LMIX_INPUT_2_SOURCE:
+	case WM5100_DSP2LMIX_INPUT_2_VOLUME:
+	case WM5100_DSP2LMIX_INPUT_3_SOURCE:
+	case WM5100_DSP2LMIX_INPUT_3_VOLUME:
+	case WM5100_DSP2LMIX_INPUT_4_SOURCE:
+	case WM5100_DSP2LMIX_INPUT_4_VOLUME:
+	case WM5100_DSP2RMIX_INPUT_1_SOURCE:
+	case WM5100_DSP2RMIX_INPUT_1_VOLUME:
+	case WM5100_DSP2RMIX_INPUT_2_SOURCE:
+	case WM5100_DSP2RMIX_INPUT_2_VOLUME:
+	case WM5100_DSP2RMIX_INPUT_3_SOURCE:
+	case WM5100_DSP2RMIX_INPUT_3_VOLUME:
+	case WM5100_DSP2RMIX_INPUT_4_SOURCE:
+	case WM5100_DSP2RMIX_INPUT_4_VOLUME:
+	case WM5100_DSP2AUX1MIX_INPUT_1_SOURCE:
+	case WM5100_DSP2AUX2MIX_INPUT_1_SOURCE:
+	case WM5100_DSP2AUX3MIX_INPUT_1_SOURCE:
+	case WM5100_DSP2AUX4MIX_INPUT_1_SOURCE:
+	case WM5100_DSP2AUX5MIX_INPUT_1_SOURCE:
+	case WM5100_DSP2AUX6MIX_INPUT_1_SOURCE:
+	case WM5100_DSP3LMIX_INPUT_1_SOURCE:
+	case WM5100_DSP3LMIX_INPUT_1_VOLUME:
+	case WM5100_DSP3LMIX_INPUT_2_SOURCE:
+	case WM5100_DSP3LMIX_INPUT_2_VOLUME:
+	case WM5100_DSP3LMIX_INPUT_3_SOURCE:
+	case WM5100_DSP3LMIX_INPUT_3_VOLUME:
+	case WM5100_DSP3LMIX_INPUT_4_SOURCE:
+	case WM5100_DSP3LMIX_INPUT_4_VOLUME:
+	case WM5100_DSP3RMIX_INPUT_1_SOURCE:
+	case WM5100_DSP3RMIX_INPUT_1_VOLUME:
+	case WM5100_DSP3RMIX_INPUT_2_SOURCE:
+	case WM5100_DSP3RMIX_INPUT_2_VOLUME:
+	case WM5100_DSP3RMIX_INPUT_3_SOURCE:
+	case WM5100_DSP3RMIX_INPUT_3_VOLUME:
+	case WM5100_DSP3RMIX_INPUT_4_SOURCE:
+	case WM5100_DSP3RMIX_INPUT_4_VOLUME:
+	case WM5100_DSP3AUX1MIX_INPUT_1_SOURCE:
+	case WM5100_DSP3AUX2MIX_INPUT_1_SOURCE:
+	case WM5100_DSP3AUX3MIX_INPUT_1_SOURCE:
+	case WM5100_DSP3AUX4MIX_INPUT_1_SOURCE:
+	case WM5100_DSP3AUX5MIX_INPUT_1_SOURCE:
+	case WM5100_DSP3AUX6MIX_INPUT_1_SOURCE:
+	case WM5100_ASRC1LMIX_INPUT_1_SOURCE:
+	case WM5100_ASRC1RMIX_INPUT_1_SOURCE:
+	case WM5100_ASRC2LMIX_INPUT_1_SOURCE:
+	case WM5100_ASRC2RMIX_INPUT_1_SOURCE:
+	case WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC1INT1MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC1INT2MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC1INT3MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC1INT4MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC2INT1MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC2INT2MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC2INT3MIX_INPUT_1_SOURCE:
+	case WM5100_ISRC2INT4MIX_INPUT_1_SOURCE:
+	case WM5100_GPIO_CTRL_1:
+	case WM5100_GPIO_CTRL_2:
+	case WM5100_GPIO_CTRL_3:
+	case WM5100_GPIO_CTRL_4:
+	case WM5100_GPIO_CTRL_5:
+	case WM5100_GPIO_CTRL_6:
+	case WM5100_MISC_PAD_CTRL_1:
+	case WM5100_MISC_PAD_CTRL_2:
+	case WM5100_MISC_PAD_CTRL_3:
+	case WM5100_MISC_PAD_CTRL_4:
+	case WM5100_MISC_PAD_CTRL_5:
+	case WM5100_MISC_GPIO_1:
+	case WM5100_INTERRUPT_STATUS_1:
+	case WM5100_INTERRUPT_STATUS_2:
+	case WM5100_INTERRUPT_STATUS_3:
+	case WM5100_INTERRUPT_STATUS_4:
+	case WM5100_INTERRUPT_RAW_STATUS_2:
+	case WM5100_INTERRUPT_RAW_STATUS_3:
+	case WM5100_INTERRUPT_RAW_STATUS_4:
+	case WM5100_INTERRUPT_STATUS_1_MASK:
+	case WM5100_INTERRUPT_STATUS_2_MASK:
+	case WM5100_INTERRUPT_STATUS_3_MASK:
+	case WM5100_INTERRUPT_STATUS_4_MASK:
+	case WM5100_INTERRUPT_CONTROL:
+	case WM5100_IRQ_DEBOUNCE_1:
+	case WM5100_IRQ_DEBOUNCE_2:
+	case WM5100_FX_CTRL:
+	case WM5100_EQ1_1:
+	case WM5100_EQ1_2:
+	case WM5100_EQ1_3:
+	case WM5100_EQ1_4:
+	case WM5100_EQ1_5:
+	case WM5100_EQ1_6:
+	case WM5100_EQ1_7:
+	case WM5100_EQ1_8:
+	case WM5100_EQ1_9:
+	case WM5100_EQ1_10:
+	case WM5100_EQ1_11:
+	case WM5100_EQ1_12:
+	case WM5100_EQ1_13:
+	case WM5100_EQ1_14:
+	case WM5100_EQ1_15:
+	case WM5100_EQ1_16:
+	case WM5100_EQ1_17:
+	case WM5100_EQ1_18:
+	case WM5100_EQ1_19:
+	case WM5100_EQ1_20:
+	case WM5100_EQ2_1:
+	case WM5100_EQ2_2:
+	case WM5100_EQ2_3:
+	case WM5100_EQ2_4:
+	case WM5100_EQ2_5:
+	case WM5100_EQ2_6:
+	case WM5100_EQ2_7:
+	case WM5100_EQ2_8:
+	case WM5100_EQ2_9:
+	case WM5100_EQ2_10:
+	case WM5100_EQ2_11:
+	case WM5100_EQ2_12:
+	case WM5100_EQ2_13:
+	case WM5100_EQ2_14:
+	case WM5100_EQ2_15:
+	case WM5100_EQ2_16:
+	case WM5100_EQ2_17:
+	case WM5100_EQ2_18:
+	case WM5100_EQ2_19:
+	case WM5100_EQ2_20:
+	case WM5100_EQ3_1:
+	case WM5100_EQ3_2:
+	case WM5100_EQ3_3:
+	case WM5100_EQ3_4:
+	case WM5100_EQ3_5:
+	case WM5100_EQ3_6:
+	case WM5100_EQ3_7:
+	case WM5100_EQ3_8:
+	case WM5100_EQ3_9:
+	case WM5100_EQ3_10:
+	case WM5100_EQ3_11:
+	case WM5100_EQ3_12:
+	case WM5100_EQ3_13:
+	case WM5100_EQ3_14:
+	case WM5100_EQ3_15:
+	case WM5100_EQ3_16:
+	case WM5100_EQ3_17:
+	case WM5100_EQ3_18:
+	case WM5100_EQ3_19:
+	case WM5100_EQ3_20:
+	case WM5100_EQ4_1:
+	case WM5100_EQ4_2:
+	case WM5100_EQ4_3:
+	case WM5100_EQ4_4:
+	case WM5100_EQ4_5:
+	case WM5100_EQ4_6:
+	case WM5100_EQ4_7:
+	case WM5100_EQ4_8:
+	case WM5100_EQ4_9:
+	case WM5100_EQ4_10:
+	case WM5100_EQ4_11:
+	case WM5100_EQ4_12:
+	case WM5100_EQ4_13:
+	case WM5100_EQ4_14:
+	case WM5100_EQ4_15:
+	case WM5100_EQ4_16:
+	case WM5100_EQ4_17:
+	case WM5100_EQ4_18:
+	case WM5100_EQ4_19:
+	case WM5100_EQ4_20:
+	case WM5100_DRC1_CTRL1:
+	case WM5100_DRC1_CTRL2:
+	case WM5100_DRC1_CTRL3:
+	case WM5100_DRC1_CTRL4:
+	case WM5100_DRC1_CTRL5:
+	case WM5100_HPLPF1_1:
+	case WM5100_HPLPF1_2:
+	case WM5100_HPLPF2_1:
+	case WM5100_HPLPF2_2:
+	case WM5100_HPLPF3_1:
+	case WM5100_HPLPF3_2:
+	case WM5100_HPLPF4_1:
+	case WM5100_HPLPF4_2:
+	case WM5100_DSP1_DM_0:
+	case WM5100_DSP1_DM_1:
+	case WM5100_DSP1_DM_2:
+	case WM5100_DSP1_DM_3:
+	case WM5100_DSP1_DM_508:
+	case WM5100_DSP1_DM_509:
+	case WM5100_DSP1_DM_510:
+	case WM5100_DSP1_DM_511:
+	case WM5100_DSP1_PM_0:
+	case WM5100_DSP1_PM_1:
+	case WM5100_DSP1_PM_2:
+	case WM5100_DSP1_PM_3:
+	case WM5100_DSP1_PM_4:
+	case WM5100_DSP1_PM_5:
+	case WM5100_DSP1_PM_1530:
+	case WM5100_DSP1_PM_1531:
+	case WM5100_DSP1_PM_1532:
+	case WM5100_DSP1_PM_1533:
+	case WM5100_DSP1_PM_1534:
+	case WM5100_DSP1_PM_1535:
+	case WM5100_DSP1_ZM_0:
+	case WM5100_DSP1_ZM_1:
+	case WM5100_DSP1_ZM_2:
+	case WM5100_DSP1_ZM_3:
+	case WM5100_DSP1_ZM_2044:
+	case WM5100_DSP1_ZM_2045:
+	case WM5100_DSP1_ZM_2046:
+	case WM5100_DSP1_ZM_2047:
+	case WM5100_DSP2_DM_0:
+	case WM5100_DSP2_DM_1:
+	case WM5100_DSP2_DM_2:
+	case WM5100_DSP2_DM_3:
+	case WM5100_DSP2_DM_508:
+	case WM5100_DSP2_DM_509:
+	case WM5100_DSP2_DM_510:
+	case WM5100_DSP2_DM_511:
+	case WM5100_DSP2_PM_0:
+	case WM5100_DSP2_PM_1:
+	case WM5100_DSP2_PM_2:
+	case WM5100_DSP2_PM_3:
+	case WM5100_DSP2_PM_4:
+	case WM5100_DSP2_PM_5:
+	case WM5100_DSP2_PM_1530:
+	case WM5100_DSP2_PM_1531:
+	case WM5100_DSP2_PM_1532:
+	case WM5100_DSP2_PM_1533:
+	case WM5100_DSP2_PM_1534:
+	case WM5100_DSP2_PM_1535:
+	case WM5100_DSP2_ZM_0:
+	case WM5100_DSP2_ZM_1:
+	case WM5100_DSP2_ZM_2:
+	case WM5100_DSP2_ZM_3:
+	case WM5100_DSP2_ZM_2044:
+	case WM5100_DSP2_ZM_2045:
+	case WM5100_DSP2_ZM_2046:
+	case WM5100_DSP2_ZM_2047:
+	case WM5100_DSP3_DM_0:
+	case WM5100_DSP3_DM_1:
+	case WM5100_DSP3_DM_2:
+	case WM5100_DSP3_DM_3:
+	case WM5100_DSP3_DM_508:
+	case WM5100_DSP3_DM_509:
+	case WM5100_DSP3_DM_510:
+	case WM5100_DSP3_DM_511:
+	case WM5100_DSP3_PM_0:
+	case WM5100_DSP3_PM_1:
+	case WM5100_DSP3_PM_2:
+	case WM5100_DSP3_PM_3:
+	case WM5100_DSP3_PM_4:
+	case WM5100_DSP3_PM_5:
+	case WM5100_DSP3_PM_1530:
+	case WM5100_DSP3_PM_1531:
+	case WM5100_DSP3_PM_1532:
+	case WM5100_DSP3_PM_1533:
+	case WM5100_DSP3_PM_1534:
+	case WM5100_DSP3_PM_1535:
+	case WM5100_DSP3_ZM_0:
+	case WM5100_DSP3_ZM_1:
+	case WM5100_DSP3_ZM_2:
+	case WM5100_DSP3_ZM_3:
+	case WM5100_DSP3_ZM_2044:
+	case WM5100_DSP3_ZM_2045:
+	case WM5100_DSP3_ZM_2046:
+	case WM5100_DSP3_ZM_2047:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1] = {
+	[0x0000] = 0x0000,     /* R0     - software reset */
+	[0x0001] = 0x0000,     /* R1     - Device Revision */
+	[0x0010] = 0x0801,     /* R16    - Ctrl IF 1 */
+	[0x0020] = 0x0000,     /* R32    - Tone Generator 1 */
+	[0x0030] = 0x0000,     /* R48    - PWM Drive 1 */
+	[0x0031] = 0x0100,     /* R49    - PWM Drive 2 */
+	[0x0032] = 0x0100,     /* R50    - PWM Drive 3 */
+	[0x0100] = 0x0002,     /* R256   - Clocking 1 */
+	[0x0101] = 0x0000,     /* R257   - Clocking 3 */
+	[0x0102] = 0x0011,     /* R258   - Clocking 4 */
+	[0x0103] = 0x0011,     /* R259   - Clocking 5 */
+	[0x0104] = 0x0011,     /* R260   - Clocking 6 */
+	[0x0107] = 0x0000,     /* R263   - Clocking 7 */
+	[0x0108] = 0x0000,     /* R264   - Clocking 8 */
+	[0x0120] = 0x0000,     /* R288   - ASRC_ENABLE */
+	[0x0121] = 0x0000,     /* R289   - ASRC_STATUS */
+	[0x0122] = 0x0000,     /* R290   - ASRC_RATE1 */
+	[0x0141] = 0x8000,     /* R321   - ISRC 1 CTRL 1 */
+	[0x0142] = 0x0000,     /* R322   - ISRC 1 CTRL 2 */
+	[0x0143] = 0x8000,     /* R323   - ISRC 2 CTRL1 */
+	[0x0144] = 0x0000,     /* R324   - ISRC 2 CTRL 2 */
+	[0x0182] = 0x0000,     /* R386   - FLL1 Control 1 */
+	[0x0183] = 0x0000,     /* R387   - FLL1 Control 2 */
+	[0x0184] = 0x0000,     /* R388   - FLL1 Control 3 */
+	[0x0186] = 0x0177,     /* R390   - FLL1 Control 5 */
+	[0x0187] = 0x0001,     /* R391   - FLL1 Control 6 */
+	[0x0188] = 0x0000,     /* R392   - FLL1 EFS 1 */
+	[0x01A2] = 0x0000,     /* R418   - FLL2 Control 1 */
+	[0x01A3] = 0x0000,     /* R419   - FLL2 Control 2 */
+	[0x01A4] = 0x0000,     /* R420   - FLL2 Control 3 */
+	[0x01A6] = 0x0177,     /* R422   - FLL2 Control 5 */
+	[0x01A7] = 0x0001,     /* R423   - FLL2 Control 6 */
+	[0x01A8] = 0x0000,     /* R424   - FLL2 EFS 1 */
+	[0x0200] = 0x0020,     /* R512   - Mic Charge Pump 1 */
+	[0x0201] = 0xB084,     /* R513   - Mic Charge Pump 2 */
+	[0x0202] = 0xBBDE,     /* R514   - HP Charge Pump 1 */
+	[0x0211] = 0x20D4,     /* R529   - LDO1 Control */
+	[0x0215] = 0x0062,     /* R533   - Mic Bias Ctrl 1 */
+	[0x0216] = 0x0062,     /* R534   - Mic Bias Ctrl 2 */
+	[0x0217] = 0x0062,     /* R535   - Mic Bias Ctrl 3 */
+	[0x0280] = 0x0004,     /* R640   - Accessory Detect Mode 1 */
+	[0x0288] = 0x0020,     /* R648   - Headphone Detect 1 */
+	[0x0289] = 0x0000,     /* R649   - Headphone Detect 2 */
+	[0x0290] = 0x1100,     /* R656   - Mic Detect 1 */
+	[0x0291] = 0x009F,     /* R657   - Mic Detect 2 */
+	[0x0292] = 0x0000,     /* R658   - Mic Detect 3 */
+	[0x0301] = 0x0000,     /* R769   - Input Enables */
+	[0x0302] = 0x0000,     /* R770   - Input Enables Status */
+	[0x0310] = 0x2280,     /* R784   - Status */
+	[0x0311] = 0x0080,     /* R785   - IN1R Control */
+	[0x0312] = 0x2280,     /* R786   - IN2L Control */
+	[0x0313] = 0x0080,     /* R787   - IN2R Control */
+	[0x0314] = 0x2280,     /* R788   - IN3L Control */
+	[0x0315] = 0x0080,     /* R789   - IN3R Control */
+	[0x0316] = 0x2280,     /* R790   - IN4L Control */
+	[0x0317] = 0x0080,     /* R791   - IN4R Control */
+	[0x0318] = 0x0000,     /* R792   - RXANC_SRC */
+	[0x0319] = 0x0022,     /* R793   - Input Volume Ramp */
+	[0x0320] = 0x0180,     /* R800   - ADC Digital Volume 1L */
+	[0x0321] = 0x0180,     /* R801   - ADC Digital Volume 1R */
+	[0x0322] = 0x0180,     /* R802   - ADC Digital Volume 2L */
+	[0x0323] = 0x0180,     /* R803   - ADC Digital Volume 2R */
+	[0x0324] = 0x0180,     /* R804   - ADC Digital Volume 3L */
+	[0x0325] = 0x0180,     /* R805   - ADC Digital Volume 3R */
+	[0x0326] = 0x0180,     /* R806   - ADC Digital Volume 4L */
+	[0x0327] = 0x0180,     /* R807   - ADC Digital Volume 4R */
+	[0x0401] = 0x0000,     /* R1025  - Output Enables 2 */
+	[0x0402] = 0x0000,     /* R1026  - Output Status 1 */
+	[0x0403] = 0x0000,     /* R1027  - Output Status 2 */
+	[0x0408] = 0x0000,     /* R1032  - Channel Enables 1 */
+	[0x0410] = 0x0080,     /* R1040  - Out Volume 1L */
+	[0x0411] = 0x0080,     /* R1041  - Out Volume 1R */
+	[0x0412] = 0x0080,     /* R1042  - DAC Volume Limit 1L */
+	[0x0413] = 0x0080,     /* R1043  - DAC Volume Limit 1R */
+	[0x0414] = 0x0080,     /* R1044  - Out Volume 2L */
+	[0x0415] = 0x0080,     /* R1045  - Out Volume 2R */
+	[0x0416] = 0x0080,     /* R1046  - DAC Volume Limit 2L */
+	[0x0417] = 0x0080,     /* R1047  - DAC Volume Limit 2R */
+	[0x0418] = 0x0080,     /* R1048  - Out Volume 3L */
+	[0x0419] = 0x0080,     /* R1049  - Out Volume 3R */
+	[0x041A] = 0x0080,     /* R1050  - DAC Volume Limit 3L */
+	[0x041B] = 0x0080,     /* R1051  - DAC Volume Limit 3R */
+	[0x041C] = 0x0080,     /* R1052  - Out Volume 4L */
+	[0x041D] = 0x0080,     /* R1053  - Out Volume 4R */
+	[0x041E] = 0x0080,     /* R1054  - DAC Volume Limit 5L */
+	[0x041F] = 0x0080,     /* R1055  - DAC Volume Limit 5R */
+	[0x0420] = 0x0080,     /* R1056  - DAC Volume Limit 6L */
+	[0x0421] = 0x0080,     /* R1057  - DAC Volume Limit 6R */
+	[0x0440] = 0x0000,     /* R1088  - DAC AEC Control 1 */
+	[0x0441] = 0x0022,     /* R1089  - Output Volume Ramp */
+	[0x0480] = 0x0180,     /* R1152  - DAC Digital Volume 1L */
+	[0x0481] = 0x0180,     /* R1153  - DAC Digital Volume 1R */
+	[0x0482] = 0x0180,     /* R1154  - DAC Digital Volume 2L */
+	[0x0483] = 0x0180,     /* R1155  - DAC Digital Volume 2R */
+	[0x0484] = 0x0180,     /* R1156  - DAC Digital Volume 3L */
+	[0x0485] = 0x0180,     /* R1157  - DAC Digital Volume 3R */
+	[0x0486] = 0x0180,     /* R1158  - DAC Digital Volume 4L */
+	[0x0487] = 0x0180,     /* R1159  - DAC Digital Volume 4R */
+	[0x0488] = 0x0180,     /* R1160  - DAC Digital Volume 5L */
+	[0x0489] = 0x0180,     /* R1161  - DAC Digital Volume 5R */
+	[0x048A] = 0x0180,     /* R1162  - DAC Digital Volume 6L */
+	[0x048B] = 0x0180,     /* R1163  - DAC Digital Volume 6R */
+	[0x04C0] = 0x0069,     /* R1216  - PDM SPK1 CTRL 1 */
+	[0x04C1] = 0x0000,     /* R1217  - PDM SPK1 CTRL 2 */
+	[0x04C2] = 0x0069,     /* R1218  - PDM SPK2 CTRL 1 */
+	[0x04C3] = 0x0000,     /* R1219  - PDM SPK2 CTRL 2 */
+	[0x0500] = 0x000C,     /* R1280  - Audio IF 1_1 */
+	[0x0501] = 0x0008,     /* R1281  - Audio IF 1_2 */
+	[0x0502] = 0x0000,     /* R1282  - Audio IF 1_3 */
+	[0x0503] = 0x0000,     /* R1283  - Audio IF 1_4 */
+	[0x0504] = 0x0000,     /* R1284  - Audio IF 1_5 */
+	[0x0505] = 0x0300,     /* R1285  - Audio IF 1_6 */
+	[0x0506] = 0x0300,     /* R1286  - Audio IF 1_7 */
+	[0x0507] = 0x1820,     /* R1287  - Audio IF 1_8 */
+	[0x0508] = 0x1820,     /* R1288  - Audio IF 1_9 */
+	[0x0509] = 0x0000,     /* R1289  - Audio IF 1_10 */
+	[0x050A] = 0x0001,     /* R1290  - Audio IF 1_11 */
+	[0x050B] = 0x0002,     /* R1291  - Audio IF 1_12 */
+	[0x050C] = 0x0003,     /* R1292  - Audio IF 1_13 */
+	[0x050D] = 0x0004,     /* R1293  - Audio IF 1_14 */
+	[0x050E] = 0x0005,     /* R1294  - Audio IF 1_15 */
+	[0x050F] = 0x0006,     /* R1295  - Audio IF 1_16 */
+	[0x0510] = 0x0007,     /* R1296  - Audio IF 1_17 */
+	[0x0511] = 0x0000,     /* R1297  - Audio IF 1_18 */
+	[0x0512] = 0x0001,     /* R1298  - Audio IF 1_19 */
+	[0x0513] = 0x0002,     /* R1299  - Audio IF 1_20 */
+	[0x0514] = 0x0003,     /* R1300  - Audio IF 1_21 */
+	[0x0515] = 0x0004,     /* R1301  - Audio IF 1_22 */
+	[0x0516] = 0x0005,     /* R1302  - Audio IF 1_23 */
+	[0x0517] = 0x0006,     /* R1303  - Audio IF 1_24 */
+	[0x0518] = 0x0007,     /* R1304  - Audio IF 1_25 */
+	[0x0519] = 0x0000,     /* R1305  - Audio IF 1_26 */
+	[0x051A] = 0x0000,     /* R1306  - Audio IF 1_27 */
+	[0x0540] = 0x000C,     /* R1344  - Audio IF 2_1 */
+	[0x0541] = 0x0008,     /* R1345  - Audio IF 2_2 */
+	[0x0542] = 0x0000,     /* R1346  - Audio IF 2_3 */
+	[0x0543] = 0x0000,     /* R1347  - Audio IF 2_4 */
+	[0x0544] = 0x0000,     /* R1348  - Audio IF 2_5 */
+	[0x0545] = 0x0300,     /* R1349  - Audio IF 2_6 */
+	[0x0546] = 0x0300,     /* R1350  - Audio IF 2_7 */
+	[0x0547] = 0x1820,     /* R1351  - Audio IF 2_8 */
+	[0x0548] = 0x1820,     /* R1352  - Audio IF 2_9 */
+	[0x0549] = 0x0000,     /* R1353  - Audio IF 2_10 */
+	[0x054A] = 0x0001,     /* R1354  - Audio IF 2_11 */
+	[0x0551] = 0x0000,     /* R1361  - Audio IF 2_18 */
+	[0x0552] = 0x0001,     /* R1362  - Audio IF 2_19 */
+	[0x0559] = 0x0000,     /* R1369  - Audio IF 2_26 */
+	[0x055A] = 0x0000,     /* R1370  - Audio IF 2_27 */
+	[0x0580] = 0x000C,     /* R1408  - Audio IF 3_1 */
+	[0x0581] = 0x0008,     /* R1409  - Audio IF 3_2 */
+	[0x0582] = 0x0000,     /* R1410  - Audio IF 3_3 */
+	[0x0583] = 0x0000,     /* R1411  - Audio IF 3_4 */
+	[0x0584] = 0x0000,     /* R1412  - Audio IF 3_5 */
+	[0x0585] = 0x0300,     /* R1413  - Audio IF 3_6 */
+	[0x0586] = 0x0300,     /* R1414  - Audio IF 3_7 */
+	[0x0587] = 0x1820,     /* R1415  - Audio IF 3_8 */
+	[0x0588] = 0x1820,     /* R1416  - Audio IF 3_9 */
+	[0x0589] = 0x0000,     /* R1417  - Audio IF 3_10 */
+	[0x058A] = 0x0001,     /* R1418  - Audio IF 3_11 */
+	[0x0591] = 0x0000,     /* R1425  - Audio IF 3_18 */
+	[0x0592] = 0x0001,     /* R1426  - Audio IF 3_19 */
+	[0x0599] = 0x0000,     /* R1433  - Audio IF 3_26 */
+	[0x059A] = 0x0000,     /* R1434  - Audio IF 3_27 */
+	[0x0640] = 0x0000,     /* R1600  - PWM1MIX Input 1 Source */
+	[0x0641] = 0x0080,     /* R1601  - PWM1MIX Input 1 Volume */
+	[0x0642] = 0x0000,     /* R1602  - PWM1MIX Input 2 Source */
+	[0x0643] = 0x0080,     /* R1603  - PWM1MIX Input 2 Volume */
+	[0x0644] = 0x0000,     /* R1604  - PWM1MIX Input 3 Source */
+	[0x0645] = 0x0080,     /* R1605  - PWM1MIX Input 3 Volume */
+	[0x0646] = 0x0000,     /* R1606  - PWM1MIX Input 4 Source */
+	[0x0647] = 0x0080,     /* R1607  - PWM1MIX Input 4 Volume */
+	[0x0648] = 0x0000,     /* R1608  - PWM2MIX Input 1 Source */
+	[0x0649] = 0x0080,     /* R1609  - PWM2MIX Input 1 Volume */
+	[0x064A] = 0x0000,     /* R1610  - PWM2MIX Input 2 Source */
+	[0x064B] = 0x0080,     /* R1611  - PWM2MIX Input 2 Volume */
+	[0x064C] = 0x0000,     /* R1612  - PWM2MIX Input 3 Source */
+	[0x064D] = 0x0080,     /* R1613  - PWM2MIX Input 3 Volume */
+	[0x064E] = 0x0000,     /* R1614  - PWM2MIX Input 4 Source */
+	[0x064F] = 0x0080,     /* R1615  - PWM2MIX Input 4 Volume */
+	[0x0680] = 0x0000,     /* R1664  - OUT1LMIX Input 1 Source */
+	[0x0681] = 0x0080,     /* R1665  - OUT1LMIX Input 1 Volume */
+	[0x0682] = 0x0000,     /* R1666  - OUT1LMIX Input 2 Source */
+	[0x0683] = 0x0080,     /* R1667  - OUT1LMIX Input 2 Volume */
+	[0x0684] = 0x0000,     /* R1668  - OUT1LMIX Input 3 Source */
+	[0x0685] = 0x0080,     /* R1669  - OUT1LMIX Input 3 Volume */
+	[0x0686] = 0x0000,     /* R1670  - OUT1LMIX Input 4 Source */
+	[0x0687] = 0x0080,     /* R1671  - OUT1LMIX Input 4 Volume */
+	[0x0688] = 0x0000,     /* R1672  - OUT1RMIX Input 1 Source */
+	[0x0689] = 0x0080,     /* R1673  - OUT1RMIX Input 1 Volume */
+	[0x068A] = 0x0000,     /* R1674  - OUT1RMIX Input 2 Source */
+	[0x068B] = 0x0080,     /* R1675  - OUT1RMIX Input 2 Volume */
+	[0x068C] = 0x0000,     /* R1676  - OUT1RMIX Input 3 Source */
+	[0x068D] = 0x0080,     /* R1677  - OUT1RMIX Input 3 Volume */
+	[0x068E] = 0x0000,     /* R1678  - OUT1RMIX Input 4 Source */
+	[0x068F] = 0x0080,     /* R1679  - OUT1RMIX Input 4 Volume */
+	[0x0690] = 0x0000,     /* R1680  - OUT2LMIX Input 1 Source */
+	[0x0691] = 0x0080,     /* R1681  - OUT2LMIX Input 1 Volume */
+	[0x0692] = 0x0000,     /* R1682  - OUT2LMIX Input 2 Source */
+	[0x0693] = 0x0080,     /* R1683  - OUT2LMIX Input 2 Volume */
+	[0x0694] = 0x0000,     /* R1684  - OUT2LMIX Input 3 Source */
+	[0x0695] = 0x0080,     /* R1685  - OUT2LMIX Input 3 Volume */
+	[0x0696] = 0x0000,     /* R1686  - OUT2LMIX Input 4 Source */
+	[0x0697] = 0x0080,     /* R1687  - OUT2LMIX Input 4 Volume */
+	[0x0698] = 0x0000,     /* R1688  - OUT2RMIX Input 1 Source */
+	[0x0699] = 0x0080,     /* R1689  - OUT2RMIX Input 1 Volume */
+	[0x069A] = 0x0000,     /* R1690  - OUT2RMIX Input 2 Source */
+	[0x069B] = 0x0080,     /* R1691  - OUT2RMIX Input 2 Volume */
+	[0x069C] = 0x0000,     /* R1692  - OUT2RMIX Input 3 Source */
+	[0x069D] = 0x0080,     /* R1693  - OUT2RMIX Input 3 Volume */
+	[0x069E] = 0x0000,     /* R1694  - OUT2RMIX Input 4 Source */
+	[0x069F] = 0x0080,     /* R1695  - OUT2RMIX Input 4 Volume */
+	[0x06A0] = 0x0000,     /* R1696  - OUT3LMIX Input 1 Source */
+	[0x06A1] = 0x0080,     /* R1697  - OUT3LMIX Input 1 Volume */
+	[0x06A2] = 0x0000,     /* R1698  - OUT3LMIX Input 2 Source */
+	[0x06A3] = 0x0080,     /* R1699  - OUT3LMIX Input 2 Volume */
+	[0x06A4] = 0x0000,     /* R1700  - OUT3LMIX Input 3 Source */
+	[0x06A5] = 0x0080,     /* R1701  - OUT3LMIX Input 3 Volume */
+	[0x06A6] = 0x0000,     /* R1702  - OUT3LMIX Input 4 Source */
+	[0x06A7] = 0x0080,     /* R1703  - OUT3LMIX Input 4 Volume */
+	[0x06A8] = 0x0000,     /* R1704  - OUT3RMIX Input 1 Source */
+	[0x06A9] = 0x0080,     /* R1705  - OUT3RMIX Input 1 Volume */
+	[0x06AA] = 0x0000,     /* R1706  - OUT3RMIX Input 2 Source */
+	[0x06AB] = 0x0080,     /* R1707  - OUT3RMIX Input 2 Volume */
+	[0x06AC] = 0x0000,     /* R1708  - OUT3RMIX Input 3 Source */
+	[0x06AD] = 0x0080,     /* R1709  - OUT3RMIX Input 3 Volume */
+	[0x06AE] = 0x0000,     /* R1710  - OUT3RMIX Input 4 Source */
+	[0x06AF] = 0x0080,     /* R1711  - OUT3RMIX Input 4 Volume */
+	[0x06B0] = 0x0000,     /* R1712  - OUT4LMIX Input 1 Source */
+	[0x06B1] = 0x0080,     /* R1713  - OUT4LMIX Input 1 Volume */
+	[0x06B2] = 0x0000,     /* R1714  - OUT4LMIX Input 2 Source */
+	[0x06B3] = 0x0080,     /* R1715  - OUT4LMIX Input 2 Volume */
+	[0x06B4] = 0x0000,     /* R1716  - OUT4LMIX Input 3 Source */
+	[0x06B5] = 0x0080,     /* R1717  - OUT4LMIX Input 3 Volume */
+	[0x06B6] = 0x0000,     /* R1718  - OUT4LMIX Input 4 Source */
+	[0x06B7] = 0x0080,     /* R1719  - OUT4LMIX Input 4 Volume */
+	[0x06B8] = 0x0000,     /* R1720  - OUT4RMIX Input 1 Source */
+	[0x06B9] = 0x0080,     /* R1721  - OUT4RMIX Input 1 Volume */
+	[0x06BA] = 0x0000,     /* R1722  - OUT4RMIX Input 2 Source */
+	[0x06BB] = 0x0080,     /* R1723  - OUT4RMIX Input 2 Volume */
+	[0x06BC] = 0x0000,     /* R1724  - OUT4RMIX Input 3 Source */
+	[0x06BD] = 0x0080,     /* R1725  - OUT4RMIX Input 3 Volume */
+	[0x06BE] = 0x0000,     /* R1726  - OUT4RMIX Input 4 Source */
+	[0x06BF] = 0x0080,     /* R1727  - OUT4RMIX Input 4 Volume */
+	[0x06C0] = 0x0000,     /* R1728  - OUT5LMIX Input 1 Source */
+	[0x06C1] = 0x0080,     /* R1729  - OUT5LMIX Input 1 Volume */
+	[0x06C2] = 0x0000,     /* R1730  - OUT5LMIX Input 2 Source */
+	[0x06C3] = 0x0080,     /* R1731  - OUT5LMIX Input 2 Volume */
+	[0x06C4] = 0x0000,     /* R1732  - OUT5LMIX Input 3 Source */
+	[0x06C5] = 0x0080,     /* R1733  - OUT5LMIX Input 3 Volume */
+	[0x06C6] = 0x0000,     /* R1734  - OUT5LMIX Input 4 Source */
+	[0x06C7] = 0x0080,     /* R1735  - OUT5LMIX Input 4 Volume */
+	[0x06C8] = 0x0000,     /* R1736  - OUT5RMIX Input 1 Source */
+	[0x06C9] = 0x0080,     /* R1737  - OUT5RMIX Input 1 Volume */
+	[0x06CA] = 0x0000,     /* R1738  - OUT5RMIX Input 2 Source */
+	[0x06CB] = 0x0080,     /* R1739  - OUT5RMIX Input 2 Volume */
+	[0x06CC] = 0x0000,     /* R1740  - OUT5RMIX Input 3 Source */
+	[0x06CD] = 0x0080,     /* R1741  - OUT5RMIX Input 3 Volume */
+	[0x06CE] = 0x0000,     /* R1742  - OUT5RMIX Input 4 Source */
+	[0x06CF] = 0x0080,     /* R1743  - OUT5RMIX Input 4 Volume */
+	[0x06D0] = 0x0000,     /* R1744  - OUT6LMIX Input 1 Source */
+	[0x06D1] = 0x0080,     /* R1745  - OUT6LMIX Input 1 Volume */
+	[0x06D2] = 0x0000,     /* R1746  - OUT6LMIX Input 2 Source */
+	[0x06D3] = 0x0080,     /* R1747  - OUT6LMIX Input 2 Volume */
+	[0x06D4] = 0x0000,     /* R1748  - OUT6LMIX Input 3 Source */
+	[0x06D5] = 0x0080,     /* R1749  - OUT6LMIX Input 3 Volume */
+	[0x06D6] = 0x0000,     /* R1750  - OUT6LMIX Input 4 Source */
+	[0x06D7] = 0x0080,     /* R1751  - OUT6LMIX Input 4 Volume */
+	[0x06D8] = 0x0000,     /* R1752  - OUT6RMIX Input 1 Source */
+	[0x06D9] = 0x0080,     /* R1753  - OUT6RMIX Input 1 Volume */
+	[0x06DA] = 0x0000,     /* R1754  - OUT6RMIX Input 2 Source */
+	[0x06DB] = 0x0080,     /* R1755  - OUT6RMIX Input 2 Volume */
+	[0x06DC] = 0x0000,     /* R1756  - OUT6RMIX Input 3 Source */
+	[0x06DD] = 0x0080,     /* R1757  - OUT6RMIX Input 3 Volume */
+	[0x06DE] = 0x0000,     /* R1758  - OUT6RMIX Input 4 Source */
+	[0x06DF] = 0x0080,     /* R1759  - OUT6RMIX Input 4 Volume */
+	[0x0700] = 0x0000,     /* R1792  - AIF1TX1MIX Input 1 Source */
+	[0x0701] = 0x0080,     /* R1793  - AIF1TX1MIX Input 1 Volume */
+	[0x0702] = 0x0000,     /* R1794  - AIF1TX1MIX Input 2 Source */
+	[0x0703] = 0x0080,     /* R1795  - AIF1TX1MIX Input 2 Volume */
+	[0x0704] = 0x0000,     /* R1796  - AIF1TX1MIX Input 3 Source */
+	[0x0705] = 0x0080,     /* R1797  - AIF1TX1MIX Input 3 Volume */
+	[0x0706] = 0x0000,     /* R1798  - AIF1TX1MIX Input 4 Source */
+	[0x0707] = 0x0080,     /* R1799  - AIF1TX1MIX Input 4 Volume */
+	[0x0708] = 0x0000,     /* R1800  - AIF1TX2MIX Input 1 Source */
+	[0x0709] = 0x0080,     /* R1801  - AIF1TX2MIX Input 1 Volume */
+	[0x070A] = 0x0000,     /* R1802  - AIF1TX2MIX Input 2 Source */
+	[0x070B] = 0x0080,     /* R1803  - AIF1TX2MIX Input 2 Volume */
+	[0x070C] = 0x0000,     /* R1804  - AIF1TX2MIX Input 3 Source */
+	[0x070D] = 0x0080,     /* R1805  - AIF1TX2MIX Input 3 Volume */
+	[0x070E] = 0x0000,     /* R1806  - AIF1TX2MIX Input 4 Source */
+	[0x070F] = 0x0080,     /* R1807  - AIF1TX2MIX Input 4 Volume */
+	[0x0710] = 0x0000,     /* R1808  - AIF1TX3MIX Input 1 Source */
+	[0x0711] = 0x0080,     /* R1809  - AIF1TX3MIX Input 1 Volume */
+	[0x0712] = 0x0000,     /* R1810  - AIF1TX3MIX Input 2 Source */
+	[0x0713] = 0x0080,     /* R1811  - AIF1TX3MIX Input 2 Volume */
+	[0x0714] = 0x0000,     /* R1812  - AIF1TX3MIX Input 3 Source */
+	[0x0715] = 0x0080,     /* R1813  - AIF1TX3MIX Input 3 Volume */
+	[0x0716] = 0x0000,     /* R1814  - AIF1TX3MIX Input 4 Source */
+	[0x0717] = 0x0080,     /* R1815  - AIF1TX3MIX Input 4 Volume */
+	[0x0718] = 0x0000,     /* R1816  - AIF1TX4MIX Input 1 Source */
+	[0x0719] = 0x0080,     /* R1817  - AIF1TX4MIX Input 1 Volume */
+	[0x071A] = 0x0000,     /* R1818  - AIF1TX4MIX Input 2 Source */
+	[0x071B] = 0x0080,     /* R1819  - AIF1TX4MIX Input 2 Volume */
+	[0x071C] = 0x0000,     /* R1820  - AIF1TX4MIX Input 3 Source */
+	[0x071D] = 0x0080,     /* R1821  - AIF1TX4MIX Input 3 Volume */
+	[0x071E] = 0x0000,     /* R1822  - AIF1TX4MIX Input 4 Source */
+	[0x071F] = 0x0080,     /* R1823  - AIF1TX4MIX Input 4 Volume */
+	[0x0720] = 0x0000,     /* R1824  - AIF1TX5MIX Input 1 Source */
+	[0x0721] = 0x0080,     /* R1825  - AIF1TX5MIX Input 1 Volume */
+	[0x0722] = 0x0000,     /* R1826  - AIF1TX5MIX Input 2 Source */
+	[0x0723] = 0x0080,     /* R1827  - AIF1TX5MIX Input 2 Volume */
+	[0x0724] = 0x0000,     /* R1828  - AIF1TX5MIX Input 3 Source */
+	[0x0725] = 0x0080,     /* R1829  - AIF1TX5MIX Input 3 Volume */
+	[0x0726] = 0x0000,     /* R1830  - AIF1TX5MIX Input 4 Source */
+	[0x0727] = 0x0080,     /* R1831  - AIF1TX5MIX Input 4 Volume */
+	[0x0728] = 0x0000,     /* R1832  - AIF1TX6MIX Input 1 Source */
+	[0x0729] = 0x0080,     /* R1833  - AIF1TX6MIX Input 1 Volume */
+	[0x072A] = 0x0000,     /* R1834  - AIF1TX6MIX Input 2 Source */
+	[0x072B] = 0x0080,     /* R1835  - AIF1TX6MIX Input 2 Volume */
+	[0x072C] = 0x0000,     /* R1836  - AIF1TX6MIX Input 3 Source */
+	[0x072D] = 0x0080,     /* R1837  - AIF1TX6MIX Input 3 Volume */
+	[0x072E] = 0x0000,     /* R1838  - AIF1TX6MIX Input 4 Source */
+	[0x072F] = 0x0080,     /* R1839  - AIF1TX6MIX Input 4 Volume */
+	[0x0730] = 0x0000,     /* R1840  - AIF1TX7MIX Input 1 Source */
+	[0x0731] = 0x0080,     /* R1841  - AIF1TX7MIX Input 1 Volume */
+	[0x0732] = 0x0000,     /* R1842  - AIF1TX7MIX Input 2 Source */
+	[0x0733] = 0x0080,     /* R1843  - AIF1TX7MIX Input 2 Volume */
+	[0x0734] = 0x0000,     /* R1844  - AIF1TX7MIX Input 3 Source */
+	[0x0735] = 0x0080,     /* R1845  - AIF1TX7MIX Input 3 Volume */
+	[0x0736] = 0x0000,     /* R1846  - AIF1TX7MIX Input 4 Source */
+	[0x0737] = 0x0080,     /* R1847  - AIF1TX7MIX Input 4 Volume */
+	[0x0738] = 0x0000,     /* R1848  - AIF1TX8MIX Input 1 Source */
+	[0x0739] = 0x0080,     /* R1849  - AIF1TX8MIX Input 1 Volume */
+	[0x073A] = 0x0000,     /* R1850  - AIF1TX8MIX Input 2 Source */
+	[0x073B] = 0x0080,     /* R1851  - AIF1TX8MIX Input 2 Volume */
+	[0x073C] = 0x0000,     /* R1852  - AIF1TX8MIX Input 3 Source */
+	[0x073D] = 0x0080,     /* R1853  - AIF1TX8MIX Input 3 Volume */
+	[0x073E] = 0x0000,     /* R1854  - AIF1TX8MIX Input 4 Source */
+	[0x073F] = 0x0080,     /* R1855  - AIF1TX8MIX Input 4 Volume */
+	[0x0740] = 0x0000,     /* R1856  - AIF2TX1MIX Input 1 Source */
+	[0x0741] = 0x0080,     /* R1857  - AIF2TX1MIX Input 1 Volume */
+	[0x0742] = 0x0000,     /* R1858  - AIF2TX1MIX Input 2 Source */
+	[0x0743] = 0x0080,     /* R1859  - AIF2TX1MIX Input 2 Volume */
+	[0x0744] = 0x0000,     /* R1860  - AIF2TX1MIX Input 3 Source */
+	[0x0745] = 0x0080,     /* R1861  - AIF2TX1MIX Input 3 Volume */
+	[0x0746] = 0x0000,     /* R1862  - AIF2TX1MIX Input 4 Source */
+	[0x0747] = 0x0080,     /* R1863  - AIF2TX1MIX Input 4 Volume */
+	[0x0748] = 0x0000,     /* R1864  - AIF2TX2MIX Input 1 Source */
+	[0x0749] = 0x0080,     /* R1865  - AIF2TX2MIX Input 1 Volume */
+	[0x074A] = 0x0000,     /* R1866  - AIF2TX2MIX Input 2 Source */
+	[0x074B] = 0x0080,     /* R1867  - AIF2TX2MIX Input 2 Volume */
+	[0x074C] = 0x0000,     /* R1868  - AIF2TX2MIX Input 3 Source */
+	[0x074D] = 0x0080,     /* R1869  - AIF2TX2MIX Input 3 Volume */
+	[0x074E] = 0x0000,     /* R1870  - AIF2TX2MIX Input 4 Source */
+	[0x074F] = 0x0080,     /* R1871  - AIF2TX2MIX Input 4 Volume */
+	[0x0780] = 0x0000,     /* R1920  - AIF3TX1MIX Input 1 Source */
+	[0x0781] = 0x0080,     /* R1921  - AIF3TX1MIX Input 1 Volume */
+	[0x0782] = 0x0000,     /* R1922  - AIF3TX1MIX Input 2 Source */
+	[0x0783] = 0x0080,     /* R1923  - AIF3TX1MIX Input 2 Volume */
+	[0x0784] = 0x0000,     /* R1924  - AIF3TX1MIX Input 3 Source */
+	[0x0785] = 0x0080,     /* R1925  - AIF3TX1MIX Input 3 Volume */
+	[0x0786] = 0x0000,     /* R1926  - AIF3TX1MIX Input 4 Source */
+	[0x0787] = 0x0080,     /* R1927  - AIF3TX1MIX Input 4 Volume */
+	[0x0788] = 0x0000,     /* R1928  - AIF3TX2MIX Input 1 Source */
+	[0x0789] = 0x0080,     /* R1929  - AIF3TX2MIX Input 1 Volume */
+	[0x078A] = 0x0000,     /* R1930  - AIF3TX2MIX Input 2 Source */
+	[0x078B] = 0x0080,     /* R1931  - AIF3TX2MIX Input 2 Volume */
+	[0x078C] = 0x0000,     /* R1932  - AIF3TX2MIX Input 3 Source */
+	[0x078D] = 0x0080,     /* R1933  - AIF3TX2MIX Input 3 Volume */
+	[0x078E] = 0x0000,     /* R1934  - AIF3TX2MIX Input 4 Source */
+	[0x078F] = 0x0080,     /* R1935  - AIF3TX2MIX Input 4 Volume */
+	[0x0880] = 0x0000,     /* R2176  - EQ1MIX Input 1 Source */
+	[0x0881] = 0x0080,     /* R2177  - EQ1MIX Input 1 Volume */
+	[0x0882] = 0x0000,     /* R2178  - EQ1MIX Input 2 Source */
+	[0x0883] = 0x0080,     /* R2179  - EQ1MIX Input 2 Volume */
+	[0x0884] = 0x0000,     /* R2180  - EQ1MIX Input 3 Source */
+	[0x0885] = 0x0080,     /* R2181  - EQ1MIX Input 3 Volume */
+	[0x0886] = 0x0000,     /* R2182  - EQ1MIX Input 4 Source */
+	[0x0887] = 0x0080,     /* R2183  - EQ1MIX Input 4 Volume */
+	[0x0888] = 0x0000,     /* R2184  - EQ2MIX Input 1 Source */
+	[0x0889] = 0x0080,     /* R2185  - EQ2MIX Input 1 Volume */
+	[0x088A] = 0x0000,     /* R2186  - EQ2MIX Input 2 Source */
+	[0x088B] = 0x0080,     /* R2187  - EQ2MIX Input 2 Volume */
+	[0x088C] = 0x0000,     /* R2188  - EQ2MIX Input 3 Source */
+	[0x088D] = 0x0080,     /* R2189  - EQ2MIX Input 3 Volume */
+	[0x088E] = 0x0000,     /* R2190  - EQ2MIX Input 4 Source */
+	[0x088F] = 0x0080,     /* R2191  - EQ2MIX Input 4 Volume */
+	[0x0890] = 0x0000,     /* R2192  - EQ3MIX Input 1 Source */
+	[0x0891] = 0x0080,     /* R2193  - EQ3MIX Input 1 Volume */
+	[0x0892] = 0x0000,     /* R2194  - EQ3MIX Input 2 Source */
+	[0x0893] = 0x0080,     /* R2195  - EQ3MIX Input 2 Volume */
+	[0x0894] = 0x0000,     /* R2196  - EQ3MIX Input 3 Source */
+	[0x0895] = 0x0080,     /* R2197  - EQ3MIX Input 3 Volume */
+	[0x0896] = 0x0000,     /* R2198  - EQ3MIX Input 4 Source */
+	[0x0897] = 0x0080,     /* R2199  - EQ3MIX Input 4 Volume */
+	[0x0898] = 0x0000,     /* R2200  - EQ4MIX Input 1 Source */
+	[0x0899] = 0x0080,     /* R2201  - EQ4MIX Input 1 Volume */
+	[0x089A] = 0x0000,     /* R2202  - EQ4MIX Input 2 Source */
+	[0x089B] = 0x0080,     /* R2203  - EQ4MIX Input 2 Volume */
+	[0x089C] = 0x0000,     /* R2204  - EQ4MIX Input 3 Source */
+	[0x089D] = 0x0080,     /* R2205  - EQ4MIX Input 3 Volume */
+	[0x089E] = 0x0000,     /* R2206  - EQ4MIX Input 4 Source */
+	[0x089F] = 0x0080,     /* R2207  - EQ4MIX Input 4 Volume */
+	[0x08C0] = 0x0000,     /* R2240  - DRC1LMIX Input 1 Source */
+	[0x08C1] = 0x0080,     /* R2241  - DRC1LMIX Input 1 Volume */
+	[0x08C2] = 0x0000,     /* R2242  - DRC1LMIX Input 2 Source */
+	[0x08C3] = 0x0080,     /* R2243  - DRC1LMIX Input 2 Volume */
+	[0x08C4] = 0x0000,     /* R2244  - DRC1LMIX Input 3 Source */
+	[0x08C5] = 0x0080,     /* R2245  - DRC1LMIX Input 3 Volume */
+	[0x08C6] = 0x0000,     /* R2246  - DRC1LMIX Input 4 Source */
+	[0x08C7] = 0x0080,     /* R2247  - DRC1LMIX Input 4 Volume */
+	[0x08C8] = 0x0000,     /* R2248  - DRC1RMIX Input 1 Source */
+	[0x08C9] = 0x0080,     /* R2249  - DRC1RMIX Input 1 Volume */
+	[0x08CA] = 0x0000,     /* R2250  - DRC1RMIX Input 2 Source */
+	[0x08CB] = 0x0080,     /* R2251  - DRC1RMIX Input 2 Volume */
+	[0x08CC] = 0x0000,     /* R2252  - DRC1RMIX Input 3 Source */
+	[0x08CD] = 0x0080,     /* R2253  - DRC1RMIX Input 3 Volume */
+	[0x08CE] = 0x0000,     /* R2254  - DRC1RMIX Input 4 Source */
+	[0x08CF] = 0x0080,     /* R2255  - DRC1RMIX Input 4 Volume */
+	[0x0900] = 0x0000,     /* R2304  - HPLP1MIX Input 1 Source */
+	[0x0901] = 0x0080,     /* R2305  - HPLP1MIX Input 1 Volume */
+	[0x0902] = 0x0000,     /* R2306  - HPLP1MIX Input 2 Source */
+	[0x0903] = 0x0080,     /* R2307  - HPLP1MIX Input 2 Volume */
+	[0x0904] = 0x0000,     /* R2308  - HPLP1MIX Input 3 Source */
+	[0x0905] = 0x0080,     /* R2309  - HPLP1MIX Input 3 Volume */
+	[0x0906] = 0x0000,     /* R2310  - HPLP1MIX Input 4 Source */
+	[0x0907] = 0x0080,     /* R2311  - HPLP1MIX Input 4 Volume */
+	[0x0908] = 0x0000,     /* R2312  - HPLP2MIX Input 1 Source */
+	[0x0909] = 0x0080,     /* R2313  - HPLP2MIX Input 1 Volume */
+	[0x090A] = 0x0000,     /* R2314  - HPLP2MIX Input 2 Source */
+	[0x090B] = 0x0080,     /* R2315  - HPLP2MIX Input 2 Volume */
+	[0x090C] = 0x0000,     /* R2316  - HPLP2MIX Input 3 Source */
+	[0x090D] = 0x0080,     /* R2317  - HPLP2MIX Input 3 Volume */
+	[0x090E] = 0x0000,     /* R2318  - HPLP2MIX Input 4 Source */
+	[0x090F] = 0x0080,     /* R2319  - HPLP2MIX Input 4 Volume */
+	[0x0910] = 0x0000,     /* R2320  - HPLP3MIX Input 1 Source */
+	[0x0911] = 0x0080,     /* R2321  - HPLP3MIX Input 1 Volume */
+	[0x0912] = 0x0000,     /* R2322  - HPLP3MIX Input 2 Source */
+	[0x0913] = 0x0080,     /* R2323  - HPLP3MIX Input 2 Volume */
+	[0x0914] = 0x0000,     /* R2324  - HPLP3MIX Input 3 Source */
+	[0x0915] = 0x0080,     /* R2325  - HPLP3MIX Input 3 Volume */
+	[0x0916] = 0x0000,     /* R2326  - HPLP3MIX Input 4 Source */
+	[0x0917] = 0x0080,     /* R2327  - HPLP3MIX Input 4 Volume */
+	[0x0918] = 0x0000,     /* R2328  - HPLP4MIX Input 1 Source */
+	[0x0919] = 0x0080,     /* R2329  - HPLP4MIX Input 1 Volume */
+	[0x091A] = 0x0000,     /* R2330  - HPLP4MIX Input 2 Source */
+	[0x091B] = 0x0080,     /* R2331  - HPLP4MIX Input 2 Volume */
+	[0x091C] = 0x0000,     /* R2332  - HPLP4MIX Input 3 Source */
+	[0x091D] = 0x0080,     /* R2333  - HPLP4MIX Input 3 Volume */
+	[0x091E] = 0x0000,     /* R2334  - HPLP4MIX Input 4 Source */
+	[0x091F] = 0x0080,     /* R2335  - HPLP4MIX Input 4 Volume */
+	[0x0940] = 0x0000,     /* R2368  - DSP1LMIX Input 1 Source */
+	[0x0941] = 0x0080,     /* R2369  - DSP1LMIX Input 1 Volume */
+	[0x0942] = 0x0000,     /* R2370  - DSP1LMIX Input 2 Source */
+	[0x0943] = 0x0080,     /* R2371  - DSP1LMIX Input 2 Volume */
+	[0x0944] = 0x0000,     /* R2372  - DSP1LMIX Input 3 Source */
+	[0x0945] = 0x0080,     /* R2373  - DSP1LMIX Input 3 Volume */
+	[0x0946] = 0x0000,     /* R2374  - DSP1LMIX Input 4 Source */
+	[0x0947] = 0x0080,     /* R2375  - DSP1LMIX Input 4 Volume */
+	[0x0948] = 0x0000,     /* R2376  - DSP1RMIX Input 1 Source */
+	[0x0949] = 0x0080,     /* R2377  - DSP1RMIX Input 1 Volume */
+	[0x094A] = 0x0000,     /* R2378  - DSP1RMIX Input 2 Source */
+	[0x094B] = 0x0080,     /* R2379  - DSP1RMIX Input 2 Volume */
+	[0x094C] = 0x0000,     /* R2380  - DSP1RMIX Input 3 Source */
+	[0x094D] = 0x0080,     /* R2381  - DSP1RMIX Input 3 Volume */
+	[0x094E] = 0x0000,     /* R2382  - DSP1RMIX Input 4 Source */
+	[0x094F] = 0x0080,     /* R2383  - DSP1RMIX Input 4 Volume */
+	[0x0950] = 0x0000,     /* R2384  - DSP1AUX1MIX Input 1 Source */
+	[0x0958] = 0x0000,     /* R2392  - DSP1AUX2MIX Input 1 Source */
+	[0x0960] = 0x0000,     /* R2400  - DSP1AUX3MIX Input 1 Source */
+	[0x0968] = 0x0000,     /* R2408  - DSP1AUX4MIX Input 1 Source */
+	[0x0970] = 0x0000,     /* R2416  - DSP1AUX5MIX Input 1 Source */
+	[0x0978] = 0x0000,     /* R2424  - DSP1AUX6MIX Input 1 Source */
+	[0x0980] = 0x0000,     /* R2432  - DSP2LMIX Input 1 Source */
+	[0x0981] = 0x0080,     /* R2433  - DSP2LMIX Input 1 Volume */
+	[0x0982] = 0x0000,     /* R2434  - DSP2LMIX Input 2 Source */
+	[0x0983] = 0x0080,     /* R2435  - DSP2LMIX Input 2 Volume */
+	[0x0984] = 0x0000,     /* R2436  - DSP2LMIX Input 3 Source */
+	[0x0985] = 0x0080,     /* R2437  - DSP2LMIX Input 3 Volume */
+	[0x0986] = 0x0000,     /* R2438  - DSP2LMIX Input 4 Source */
+	[0x0987] = 0x0080,     /* R2439  - DSP2LMIX Input 4 Volume */
+	[0x0988] = 0x0000,     /* R2440  - DSP2RMIX Input 1 Source */
+	[0x0989] = 0x0080,     /* R2441  - DSP2RMIX Input 1 Volume */
+	[0x098A] = 0x0000,     /* R2442  - DSP2RMIX Input 2 Source */
+	[0x098B] = 0x0080,     /* R2443  - DSP2RMIX Input 2 Volume */
+	[0x098C] = 0x0000,     /* R2444  - DSP2RMIX Input 3 Source */
+	[0x098D] = 0x0080,     /* R2445  - DSP2RMIX Input 3 Volume */
+	[0x098E] = 0x0000,     /* R2446  - DSP2RMIX Input 4 Source */
+	[0x098F] = 0x0080,     /* R2447  - DSP2RMIX Input 4 Volume */
+	[0x0990] = 0x0000,     /* R2448  - DSP2AUX1MIX Input 1 Source */
+	[0x0998] = 0x0000,     /* R2456  - DSP2AUX2MIX Input 1 Source */
+	[0x09A0] = 0x0000,     /* R2464  - DSP2AUX3MIX Input 1 Source */
+	[0x09A8] = 0x0000,     /* R2472  - DSP2AUX4MIX Input 1 Source */
+	[0x09B0] = 0x0000,     /* R2480  - DSP2AUX5MIX Input 1 Source */
+	[0x09B8] = 0x0000,     /* R2488  - DSP2AUX6MIX Input 1 Source */
+	[0x09C0] = 0x0000,     /* R2496  - DSP3LMIX Input 1 Source */
+	[0x09C1] = 0x0080,     /* R2497  - DSP3LMIX Input 1 Volume */
+	[0x09C2] = 0x0000,     /* R2498  - DSP3LMIX Input 2 Source */
+	[0x09C3] = 0x0080,     /* R2499  - DSP3LMIX Input 2 Volume */
+	[0x09C4] = 0x0000,     /* R2500  - DSP3LMIX Input 3 Source */
+	[0x09C5] = 0x0080,     /* R2501  - DSP3LMIX Input 3 Volume */
+	[0x09C6] = 0x0000,     /* R2502  - DSP3LMIX Input 4 Source */
+	[0x09C7] = 0x0080,     /* R2503  - DSP3LMIX Input 4 Volume */
+	[0x09C8] = 0x0000,     /* R2504  - DSP3RMIX Input 1 Source */
+	[0x09C9] = 0x0080,     /* R2505  - DSP3RMIX Input 1 Volume */
+	[0x09CA] = 0x0000,     /* R2506  - DSP3RMIX Input 2 Source */
+	[0x09CB] = 0x0080,     /* R2507  - DSP3RMIX Input 2 Volume */
+	[0x09CC] = 0x0000,     /* R2508  - DSP3RMIX Input 3 Source */
+	[0x09CD] = 0x0080,     /* R2509  - DSP3RMIX Input 3 Volume */
+	[0x09CE] = 0x0000,     /* R2510  - DSP3RMIX Input 4 Source */
+	[0x09CF] = 0x0080,     /* R2511  - DSP3RMIX Input 4 Volume */
+	[0x09D0] = 0x0000,     /* R2512  - DSP3AUX1MIX Input 1 Source */
+	[0x09D8] = 0x0000,     /* R2520  - DSP3AUX2MIX Input 1 Source */
+	[0x09E0] = 0x0000,     /* R2528  - DSP3AUX3MIX Input 1 Source */
+	[0x09E8] = 0x0000,     /* R2536  - DSP3AUX4MIX Input 1 Source */
+	[0x09F0] = 0x0000,     /* R2544  - DSP3AUX5MIX Input 1 Source */
+	[0x09F8] = 0x0000,     /* R2552  - DSP3AUX6MIX Input 1 Source */
+	[0x0A80] = 0x0000,     /* R2688  - ASRC1LMIX Input 1 Source */
+	[0x0A88] = 0x0000,     /* R2696  - ASRC1RMIX Input 1 Source */
+	[0x0A90] = 0x0000,     /* R2704  - ASRC2LMIX Input 1 Source */
+	[0x0A98] = 0x0000,     /* R2712  - ASRC2RMIX Input 1 Source */
+	[0x0B00] = 0x0000,     /* R2816  - ISRC1DEC1MIX Input 1 Source */
+	[0x0B08] = 0x0000,     /* R2824  - ISRC1DEC2MIX Input 1 Source */
+	[0x0B10] = 0x0000,     /* R2832  - ISRC1DEC3MIX Input 1 Source */
+	[0x0B18] = 0x0000,     /* R2840  - ISRC1DEC4MIX Input 1 Source */
+	[0x0B20] = 0x0000,     /* R2848  - ISRC1INT1MIX Input 1 Source */
+	[0x0B28] = 0x0000,     /* R2856  - ISRC1INT2MIX Input 1 Source */
+	[0x0B30] = 0x0000,     /* R2864  - ISRC1INT3MIX Input 1 Source */
+	[0x0B38] = 0x0000,     /* R2872  - ISRC1INT4MIX Input 1 Source */
+	[0x0B40] = 0x0000,     /* R2880  - ISRC2DEC1MIX Input 1 Source */
+	[0x0B48] = 0x0000,     /* R2888  - ISRC2DEC2MIX Input 1 Source */
+	[0x0B50] = 0x0000,     /* R2896  - ISRC2DEC3MIX Input 1 Source */
+	[0x0B58] = 0x0000,     /* R2904  - ISRC2DEC4MIX Input 1 Source */
+	[0x0B60] = 0x0000,     /* R2912  - ISRC2INT1MIX Input 1 Source */
+	[0x0B68] = 0x0000,     /* R2920  - ISRC2INT2MIX Input 1 Source */
+	[0x0B70] = 0x0000,     /* R2928  - ISRC2INT3MIX Input 1 Source */
+	[0x0B78] = 0x0000,     /* R2936  - ISRC2INT4MIX Input 1 Source */
+	[0x0C00] = 0xA001,     /* R3072  - GPIO CTRL 1 */
+	[0x0C01] = 0xA001,     /* R3073  - GPIO CTRL 2 */
+	[0x0C02] = 0xA001,     /* R3074  - GPIO CTRL 3 */
+	[0x0C03] = 0xA001,     /* R3075  - GPIO CTRL 4 */
+	[0x0C04] = 0xA001,     /* R3076  - GPIO CTRL 5 */
+	[0x0C05] = 0xA001,     /* R3077  - GPIO CTRL 6 */
+	[0x0C23] = 0x4003,     /* R3107  - Misc Pad Ctrl 1 */
+	[0x0C24] = 0x0000,     /* R3108  - Misc Pad Ctrl 2 */
+	[0x0C25] = 0x0000,     /* R3109  - Misc Pad Ctrl 3 */
+	[0x0C26] = 0x0000,     /* R3110  - Misc Pad Ctrl 4 */
+	[0x0C27] = 0x0000,     /* R3111  - Misc Pad Ctrl 5 */
+	[0x0C28] = 0x0000,     /* R3112  - Misc GPIO 1 */
+	[0x0D00] = 0x0000,     /* R3328  - Interrupt Status 1 */
+	[0x0D01] = 0x0000,     /* R3329  - Interrupt Status 2 */
+	[0x0D02] = 0x0000,     /* R3330  - Interrupt Status 3 */
+	[0x0D03] = 0x0000,     /* R3331  - Interrupt Status 4 */
+	[0x0D04] = 0x0000,     /* R3332  - Interrupt Raw Status 2 */
+	[0x0D05] = 0x0000,     /* R3333  - Interrupt Raw Status 3 */
+	[0x0D06] = 0x0000,     /* R3334  - Interrupt Raw Status 4 */
+	[0x0D07] = 0xFFFF,     /* R3335  - Interrupt Status 1 Mask */
+	[0x0D08] = 0xFFFF,     /* R3336  - Interrupt Status 2 Mask */
+	[0x0D09] = 0xFFFF,     /* R3337  - Interrupt Status 3 Mask */
+	[0x0D0A] = 0xFFFF,     /* R3338  - Interrupt Status 4 Mask */
+	[0x0D1F] = 0x0000,     /* R3359  - Interrupt Control */
+	[0x0D20] = 0xFFFF,     /* R3360  - IRQ Debounce 1 */
+	[0x0D21] = 0xFFFF,     /* R3361  - IRQ Debounce 2 */
+	[0x0E00] = 0x0000,     /* R3584  - FX_Ctrl */
+	[0x0E10] = 0x6318,     /* R3600  - EQ1_1 */
+	[0x0E11] = 0x6300,     /* R3601  - EQ1_2 */
+	[0x0E12] = 0x0FC8,     /* R3602  - EQ1_3 */
+	[0x0E13] = 0x03FE,     /* R3603  - EQ1_4 */
+	[0x0E14] = 0x00E0,     /* R3604  - EQ1_5 */
+	[0x0E15] = 0x1EC4,     /* R3605  - EQ1_6 */
+	[0x0E16] = 0xF136,     /* R3606  - EQ1_7 */
+	[0x0E17] = 0x0409,     /* R3607  - EQ1_8 */
+	[0x0E18] = 0x04CC,     /* R3608  - EQ1_9 */
+	[0x0E19] = 0x1C9B,     /* R3609  - EQ1_10 */
+	[0x0E1A] = 0xF337,     /* R3610  - EQ1_11 */
+	[0x0E1B] = 0x040B,     /* R3611  - EQ1_12 */
+	[0x0E1C] = 0x0CBB,     /* R3612  - EQ1_13 */
+	[0x0E1D] = 0x16F8,     /* R3613  - EQ1_14 */
+	[0x0E1E] = 0xF7D9,     /* R3614  - EQ1_15 */
+	[0x0E1F] = 0x040A,     /* R3615  - EQ1_16 */
+	[0x0E20] = 0x1F14,     /* R3616  - EQ1_17 */
+	[0x0E21] = 0x058C,     /* R3617  - EQ1_18 */
+	[0x0E22] = 0x0563,     /* R3618  - EQ1_19 */
+	[0x0E23] = 0x4000,     /* R3619  - EQ1_20 */
+	[0x0E26] = 0x6318,     /* R3622  - EQ2_1 */
+	[0x0E27] = 0x6300,     /* R3623  - EQ2_2 */
+	[0x0E28] = 0x0FC8,     /* R3624  - EQ2_3 */
+	[0x0E29] = 0x03FE,     /* R3625  - EQ2_4 */
+	[0x0E2A] = 0x00E0,     /* R3626  - EQ2_5 */
+	[0x0E2B] = 0x1EC4,     /* R3627  - EQ2_6 */
+	[0x0E2C] = 0xF136,     /* R3628  - EQ2_7 */
+	[0x0E2D] = 0x0409,     /* R3629  - EQ2_8 */
+	[0x0E2E] = 0x04CC,     /* R3630  - EQ2_9 */
+	[0x0E2F] = 0x1C9B,     /* R3631  - EQ2_10 */
+	[0x0E30] = 0xF337,     /* R3632  - EQ2_11 */
+	[0x0E31] = 0x040B,     /* R3633  - EQ2_12 */
+	[0x0E32] = 0x0CBB,     /* R3634  - EQ2_13 */
+	[0x0E33] = 0x16F8,     /* R3635  - EQ2_14 */
+	[0x0E34] = 0xF7D9,     /* R3636  - EQ2_15 */
+	[0x0E35] = 0x040A,     /* R3637  - EQ2_16 */
+	[0x0E36] = 0x1F14,     /* R3638  - EQ2_17 */
+	[0x0E37] = 0x058C,     /* R3639  - EQ2_18 */
+	[0x0E38] = 0x0563,     /* R3640  - EQ2_19 */
+	[0x0E39] = 0x4000,     /* R3641  - EQ2_20 */
+	[0x0E3C] = 0x6318,     /* R3644  - EQ3_1 */
+	[0x0E3D] = 0x6300,     /* R3645  - EQ3_2 */
+	[0x0E3E] = 0x0FC8,     /* R3646  - EQ3_3 */
+	[0x0E3F] = 0x03FE,     /* R3647  - EQ3_4 */
+	[0x0E40] = 0x00E0,     /* R3648  - EQ3_5 */
+	[0x0E41] = 0x1EC4,     /* R3649  - EQ3_6 */
+	[0x0E42] = 0xF136,     /* R3650  - EQ3_7 */
+	[0x0E43] = 0x0409,     /* R3651  - EQ3_8 */
+	[0x0E44] = 0x04CC,     /* R3652  - EQ3_9 */
+	[0x0E45] = 0x1C9B,     /* R3653  - EQ3_10 */
+	[0x0E46] = 0xF337,     /* R3654  - EQ3_11 */
+	[0x0E47] = 0x040B,     /* R3655  - EQ3_12 */
+	[0x0E48] = 0x0CBB,     /* R3656  - EQ3_13 */
+	[0x0E49] = 0x16F8,     /* R3657  - EQ3_14 */
+	[0x0E4A] = 0xF7D9,     /* R3658  - EQ3_15 */
+	[0x0E4B] = 0x040A,     /* R3659  - EQ3_16 */
+	[0x0E4C] = 0x1F14,     /* R3660  - EQ3_17 */
+	[0x0E4D] = 0x058C,     /* R3661  - EQ3_18 */
+	[0x0E4E] = 0x0563,     /* R3662  - EQ3_19 */
+	[0x0E4F] = 0x4000,     /* R3663  - EQ3_20 */
+	[0x0E52] = 0x6318,     /* R3666  - EQ4_1 */
+	[0x0E53] = 0x6300,     /* R3667  - EQ4_2 */
+	[0x0E54] = 0x0FC8,     /* R3668  - EQ4_3 */
+	[0x0E55] = 0x03FE,     /* R3669  - EQ4_4 */
+	[0x0E56] = 0x00E0,     /* R3670  - EQ4_5 */
+	[0x0E57] = 0x1EC4,     /* R3671  - EQ4_6 */
+	[0x0E58] = 0xF136,     /* R3672  - EQ4_7 */
+	[0x0E59] = 0x0409,     /* R3673  - EQ4_8 */
+	[0x0E5A] = 0x04CC,     /* R3674  - EQ4_9 */
+	[0x0E5B] = 0x1C9B,     /* R3675  - EQ4_10 */
+	[0x0E5C] = 0xF337,     /* R3676  - EQ4_11 */
+	[0x0E5D] = 0x040B,     /* R3677  - EQ4_12 */
+	[0x0E5E] = 0x0CBB,     /* R3678  - EQ4_13 */
+	[0x0E5F] = 0x16F8,     /* R3679  - EQ4_14 */
+	[0x0E60] = 0xF7D9,     /* R3680  - EQ4_15 */
+	[0x0E61] = 0x040A,     /* R3681  - EQ4_16 */
+	[0x0E62] = 0x1F14,     /* R3682  - EQ4_17 */
+	[0x0E63] = 0x058C,     /* R3683  - EQ4_18 */
+	[0x0E64] = 0x0563,     /* R3684  - EQ4_19 */
+	[0x0E65] = 0x4000,     /* R3685  - EQ4_20 */
+	[0x0E80] = 0x0018,     /* R3712  - DRC1 ctrl1 */
+	[0x0E81] = 0x0933,     /* R3713  - DRC1 ctrl2 */
+	[0x0E82] = 0x0018,     /* R3714  - DRC1 ctrl3 */
+	[0x0E83] = 0x0000,     /* R3715  - DRC1 ctrl4 */
+	[0x0E84] = 0x0000,     /* R3716  - DRC1 ctrl5 */
+	[0x0EC0] = 0x0000,     /* R3776  - HPLPF1_1 */
+	[0x0EC1] = 0x0000,     /* R3777  - HPLPF1_2 */
+	[0x0EC4] = 0x0000,     /* R3780  - HPLPF2_1 */
+	[0x0EC5] = 0x0000,     /* R3781  - HPLPF2_2 */
+	[0x0EC8] = 0x0000,     /* R3784  - HPLPF3_1 */
+	[0x0EC9] = 0x0000,     /* R3785  - HPLPF3_2 */
+	[0x0ECC] = 0x0000,     /* R3788  - HPLPF4_1 */
+	[0x0ECD] = 0x0000,     /* R3789  - HPLPF4_2 */
+	[0x4000] = 0x0000,     /* R16384 - DSP1 DM 0 */
+	[0x4001] = 0x0000,     /* R16385 - DSP1 DM 1 */
+	[0x4002] = 0x0000,     /* R16386 - DSP1 DM 2 */
+	[0x4003] = 0x0000,     /* R16387 - DSP1 DM 3 */
+	[0x41FC] = 0x0000,     /* R16892 - DSP1 DM 508 */
+	[0x41FD] = 0x0000,     /* R16893 - DSP1 DM 509 */
+	[0x41FE] = 0x0000,     /* R16894 - DSP1 DM 510 */
+	[0x41FF] = 0x0000,     /* R16895 - DSP1 DM 511 */
+	[0x4800] = 0x0000,     /* R18432 - DSP1 PM 0 */
+	[0x4801] = 0x0000,     /* R18433 - DSP1 PM 1 */
+	[0x4802] = 0x0000,     /* R18434 - DSP1 PM 2 */
+	[0x4803] = 0x0000,     /* R18435 - DSP1 PM 3 */
+	[0x4804] = 0x0000,     /* R18436 - DSP1 PM 4 */
+	[0x4805] = 0x0000,     /* R18437 - DSP1 PM 5 */
+	[0x4DFA] = 0x0000,     /* R19962 - DSP1 PM 1530 */
+	[0x4DFB] = 0x0000,     /* R19963 - DSP1 PM 1531 */
+	[0x4DFC] = 0x0000,     /* R19964 - DSP1 PM 1532 */
+	[0x4DFD] = 0x0000,     /* R19965 - DSP1 PM 1533 */
+	[0x4DFE] = 0x0000,     /* R19966 - DSP1 PM 1534 */
+	[0x4DFF] = 0x0000,     /* R19967 - DSP1 PM 1535 */
+	[0x5000] = 0x0000,     /* R20480 - DSP1 ZM 0 */
+	[0x5001] = 0x0000,     /* R20481 - DSP1 ZM 1 */
+	[0x5002] = 0x0000,     /* R20482 - DSP1 ZM 2 */
+	[0x5003] = 0x0000,     /* R20483 - DSP1 ZM 3 */
+	[0x57FC] = 0x0000,     /* R22524 - DSP1 ZM 2044 */
+	[0x57FD] = 0x0000,     /* R22525 - DSP1 ZM 2045 */
+	[0x57FE] = 0x0000,     /* R22526 - DSP1 ZM 2046 */
+	[0x57FF] = 0x0000,     /* R22527 - DSP1 ZM 2047 */
+	[0x6000] = 0x0000,     /* R24576 - DSP2 DM 0 */
+	[0x6001] = 0x0000,     /* R24577 - DSP2 DM 1 */
+	[0x6002] = 0x0000,     /* R24578 - DSP2 DM 2 */
+	[0x6003] = 0x0000,     /* R24579 - DSP2 DM 3 */
+	[0x61FC] = 0x0000,     /* R25084 - DSP2 DM 508 */
+	[0x61FD] = 0x0000,     /* R25085 - DSP2 DM 509 */
+	[0x61FE] = 0x0000,     /* R25086 - DSP2 DM 510 */
+	[0x61FF] = 0x0000,     /* R25087 - DSP2 DM 511 */
+	[0x6800] = 0x0000,     /* R26624 - DSP2 PM 0 */
+	[0x6801] = 0x0000,     /* R26625 - DSP2 PM 1 */
+	[0x6802] = 0x0000,     /* R26626 - DSP2 PM 2 */
+	[0x6803] = 0x0000,     /* R26627 - DSP2 PM 3 */
+	[0x6804] = 0x0000,     /* R26628 - DSP2 PM 4 */
+	[0x6805] = 0x0000,     /* R26629 - DSP2 PM 5 */
+	[0x6DFA] = 0x0000,     /* R28154 - DSP2 PM 1530 */
+	[0x6DFB] = 0x0000,     /* R28155 - DSP2 PM 1531 */
+	[0x6DFC] = 0x0000,     /* R28156 - DSP2 PM 1532 */
+	[0x6DFD] = 0x0000,     /* R28157 - DSP2 PM 1533 */
+	[0x6DFE] = 0x0000,     /* R28158 - DSP2 PM 1534 */
+	[0x6DFF] = 0x0000,     /* R28159 - DSP2 PM 1535 */
+	[0x7000] = 0x0000,     /* R28672 - DSP2 ZM 0 */
+	[0x7001] = 0x0000,     /* R28673 - DSP2 ZM 1 */
+	[0x7002] = 0x0000,     /* R28674 - DSP2 ZM 2 */
+	[0x7003] = 0x0000,     /* R28675 - DSP2 ZM 3 */
+	[0x77FC] = 0x0000,     /* R30716 - DSP2 ZM 2044 */
+	[0x77FD] = 0x0000,     /* R30717 - DSP2 ZM 2045 */
+	[0x77FE] = 0x0000,     /* R30718 - DSP2 ZM 2046 */
+	[0x77FF] = 0x0000,     /* R30719 - DSP2 ZM 2047 */
+	[0x8000] = 0x0000,     /* R32768 - DSP3 DM 0 */
+	[0x8001] = 0x0000,     /* R32769 - DSP3 DM 1 */
+	[0x8002] = 0x0000,     /* R32770 - DSP3 DM 2 */
+	[0x8003] = 0x0000,     /* R32771 - DSP3 DM 3 */
+	[0x81FC] = 0x0000,     /* R33276 - DSP3 DM 508 */
+	[0x81FD] = 0x0000,     /* R33277 - DSP3 DM 509 */
+	[0x81FE] = 0x0000,     /* R33278 - DSP3 DM 510 */
+	[0x81FF] = 0x0000,     /* R33279 - DSP3 DM 511 */
+	[0x8800] = 0x0000,     /* R34816 - DSP3 PM 0 */
+	[0x8801] = 0x0000,     /* R34817 - DSP3 PM 1 */
+	[0x8802] = 0x0000,     /* R34818 - DSP3 PM 2 */
+	[0x8803] = 0x0000,     /* R34819 - DSP3 PM 3 */
+	[0x8804] = 0x0000,     /* R34820 - DSP3 PM 4 */
+	[0x8805] = 0x0000,     /* R34821 - DSP3 PM 5 */
+	[0x8DFA] = 0x0000,     /* R36346 - DSP3 PM 1530 */
+	[0x8DFB] = 0x0000,     /* R36347 - DSP3 PM 1531 */
+	[0x8DFC] = 0x0000,     /* R36348 - DSP3 PM 1532 */
+	[0x8DFD] = 0x0000,     /* R36349 - DSP3 PM 1533 */
+	[0x8DFE] = 0x0000,     /* R36350 - DSP3 PM 1534 */
+	[0x8DFF] = 0x0000,     /* R36351 - DSP3 PM 1535 */
+	[0x9000] = 0x0000,     /* R36864 - DSP3 ZM 0 */
+	[0x9001] = 0x0000,     /* R36865 - DSP3 ZM 1 */
+	[0x9002] = 0x0000,     /* R36866 - DSP3 ZM 2 */
+	[0x9003] = 0x0000,     /* R36867 - DSP3 ZM 3 */
+	[0x97FC] = 0x0000,     /* R38908 - DSP3 ZM 2044 */
+	[0x97FD] = 0x0000,     /* R38909 - DSP3 ZM 2045 */
+	[0x97FE] = 0x0000,     /* R38910 - DSP3 ZM 2046 */
+	[0x97FF] = 0x0000      /* R38911 - DSP3 ZM 2047 */
+};
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
new file mode 100644
index 000000000000..5d88c99aaea6
--- /dev/null
+++ b/sound/soc/codecs/wm5100.c
@@ -0,0 +1,2809 @@
+/*
+ * wm5100.c  --  WM5100 ALSA SoC Audio driver
+ *
+ * Copyright 2011 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/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.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 <sound/wm5100.h>
+
+#include "wm5100.h"
+
+#define WM5100_NUM_CORE_SUPPLIES 2
+static const char *wm5100_core_supply_names[WM5100_NUM_CORE_SUPPLIES] = {
+	"DBVDD1",
+	"LDOVDD", /* If DCVDD is supplied externally specify as LDOVDD */
+};
+
+#define WM5100_AIFS     3
+#define WM5100_SYNC_SRS 3
+
+struct wm5100_fll {
+	int fref;
+	int fout;
+	int src;
+	struct completion lock;
+};
+
+/* codec private data */
+struct wm5100_priv {
+	struct snd_soc_codec *codec;
+
+	struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
+	struct regulator *cpvdd;
+	struct regulator *dbvdd2;
+	struct regulator *dbvdd3;
+
+	int rev;
+
+	int sysclk;
+	int asyncclk;
+
+	bool aif_async[WM5100_AIFS];
+	bool aif_symmetric[WM5100_AIFS];
+	int sr_ref[WM5100_SYNC_SRS];
+
+	bool out_ena[2];
+
+	struct snd_soc_jack *jack;
+	bool jack_detecting;
+	bool jack_mic;
+	int jack_mode;
+
+	struct wm5100_fll fll[2];
+
+	struct wm5100_pdata pdata;
+
+#ifdef CONFIG_GPIOLIB
+	struct gpio_chip gpio_chip;
+#endif
+};
+
+static int wm5100_sr_code[] = {
+	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 wm5100_sr_regs[WM5100_SYNC_SRS] = {
+	WM5100_CLOCKING_4,
+	WM5100_CLOCKING_5,
+	WM5100_CLOCKING_6,
+};
+
+static int wm5100_alloc_sr(struct snd_soc_codec *codec, int rate)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int sr_code, sr_free, i;
+
+	for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+		if (wm5100_sr_code[i] == rate)
+			break;
+	if (i == ARRAY_SIZE(wm5100_sr_code)) {
+		dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
+		return -EINVAL;
+	}
+	sr_code = i;
+
+	if ((wm5100->sysclk % rate) == 0) {
+		/* Is this rate already in use? */
+		sr_free = -1;
+		for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
+			if (!wm5100->sr_ref[i] && sr_free == -1) {
+				sr_free = i;
+				continue;
+			}
+			if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
+			     WM5100_SAMPLE_RATE_1_MASK) == sr_code)
+				break;
+		}
+
+		if (i < ARRAY_SIZE(wm5100_sr_regs)) {
+			wm5100->sr_ref[i]++;
+			dev_dbg(codec->dev, "SR %dHz, slot %d, ref %d\n",
+				rate, i, wm5100->sr_ref[i]);
+			return i;
+		}
+
+		if (sr_free == -1) {
+			dev_err(codec->dev, "All SR slots already in use\n");
+			return -EBUSY;
+		}
+
+		dev_dbg(codec->dev, "Allocating SR slot %d for %dHz\n",
+			sr_free, rate);
+		wm5100->sr_ref[sr_free]++;
+		snd_soc_update_bits(codec, wm5100_sr_regs[sr_free],
+				    WM5100_SAMPLE_RATE_1_MASK,
+				    sr_code);
+
+		return sr_free;
+
+	} else {
+		dev_err(codec->dev,
+			"SR %dHz incompatible with %dHz SYSCLK and %dHz ASYNCCLK\n",
+			rate, wm5100->sysclk, wm5100->asyncclk);
+		return -EINVAL;
+	}
+}
+
+static void wm5100_free_sr(struct snd_soc_codec *codec, int rate)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int i, sr_code;
+
+	for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+		if (wm5100_sr_code[i] == rate)
+			break;
+	if (i == ARRAY_SIZE(wm5100_sr_code)) {
+		dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
+		return;
+	}
+	sr_code = wm5100_sr_code[i];
+
+	for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
+		if (!wm5100->sr_ref[i])
+			continue;
+
+		if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
+		     WM5100_SAMPLE_RATE_1_MASK) == sr_code)
+			break;
+	}
+	if (i < ARRAY_SIZE(wm5100_sr_regs)) {
+		wm5100->sr_ref[i]--;
+		dev_dbg(codec->dev, "Dereference SR %dHz, count now %d\n",
+			rate, wm5100->sr_ref[i]);
+	} else {
+		dev_warn(codec->dev, "Freeing unreferenced sample rate %dHz\n",
+			 rate);
+	}
+}
+
+static int wm5100_reset(struct snd_soc_codec *codec)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+
+	if (wm5100->pdata.reset) {
+		gpio_set_value_cansleep(wm5100->pdata.reset, 0);
+		gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+
+		return 0;
+	} else {
+		return snd_soc_write(codec, WM5100_SOFTWARE_RESET, 0);
+	}
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static DECLARE_TLV_DB_SCALE(mixer_tlv, -3200, 100, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+
+static const char *wm5100_mixer_texts[] = {
+	"None",
+	"Tone Generator 1",
+	"Tone Generator 2",
+	"AEC loopback",
+	"IN1L",
+	"IN1R",
+	"IN2L",
+	"IN2R",
+	"IN3L",
+	"IN3R",
+	"IN4L",
+	"IN4R",
+	"AIF1RX1",
+	"AIF1RX2",
+	"AIF1RX3",
+	"AIF1RX4",
+	"AIF1RX5",
+	"AIF1RX6",
+	"AIF1RX7",
+	"AIF1RX8",
+	"AIF2RX1",
+	"AIF2RX2",
+	"AIF3RX1",
+	"AIF3RX2",
+	"EQ1",
+	"EQ2",
+	"EQ3",
+	"EQ4",
+	"DRC1L",
+	"DRC1R",
+	"LHPF1",
+	"LHPF2",
+	"LHPF3",
+	"LHPF4",
+	"DSP1.1",
+	"DSP1.2",
+	"DSP1.3",
+	"DSP1.4",
+	"DSP1.5",
+	"DSP1.6",
+	"DSP2.1",
+	"DSP2.2",
+	"DSP2.3",
+	"DSP2.4",
+	"DSP2.5",
+	"DSP2.6",
+	"DSP3.1",
+	"DSP3.2",
+	"DSP3.3",
+	"DSP3.4",
+	"DSP3.5",
+	"DSP3.6",
+	"ASRC1L",
+	"ASRC1R",
+	"ASRC2L",
+	"ASRC2R",
+	"ISRC1INT1",
+	"ISRC1INT2",
+	"ISRC1INT3",
+	"ISRC1INT4",
+	"ISRC2INT1",
+	"ISRC2INT2",
+	"ISRC2INT3",
+	"ISRC2INT4",
+	"ISRC1DEC1",
+	"ISRC1DEC2",
+	"ISRC1DEC3",
+	"ISRC1DEC4",
+	"ISRC2DEC1",
+	"ISRC2DEC2",
+	"ISRC2DEC3",
+	"ISRC2DEC4",
+};
+
+static int wm5100_mixer_values[] = {
+	0x00,
+	0x04,   /* Tone */
+	0x05,
+	0x08,   /* AEC */
+	0x10,   /* Input */
+	0x11,
+	0x12,
+	0x13,
+	0x14,
+	0x15,
+	0x16,
+	0x17,
+	0x20,   /* AIF */
+	0x21,
+	0x22,
+	0x23,
+	0x24,
+	0x25,
+	0x26,
+	0x27,
+	0x28,
+	0x29,
+	0x30,   /* AIF3 - check */
+	0x31,
+	0x50,   /* EQ */
+	0x51,
+	0x52,
+	0x53,
+	0x54,
+	0x58,   /* DRC */
+	0x59,
+	0x60,   /* LHPF1 */
+	0x61,   /* LHPF2 */
+	0x62,   /* LHPF3 */
+	0x63,   /* LHPF4 */
+	0x68,   /* DSP1 */
+	0x69,
+	0x6a,
+	0x6b,
+	0x6c,
+	0x6d,
+	0x70,   /* DSP2 */
+	0x71,
+	0x72,
+	0x73,
+	0x74,
+	0x75,
+	0x78,   /* DSP3 */
+	0x79,
+	0x7a,
+	0x7b,
+	0x7c,
+	0x7d,
+	0x90,   /* ASRC1 */
+	0x91,
+	0x92,   /* ASRC2 */
+	0x93,
+	0xa0,   /* ISRC1DEC1 */
+	0xa1,
+	0xa2,
+	0xa3,
+	0xa4,   /* ISRC1INT1 */
+	0xa5,
+	0xa6,
+	0xa7,
+	0xa8,   /* ISRC2DEC1 */
+	0xa9,
+	0xaa,
+	0xab,
+	0xac,   /* ISRC2INT1 */
+	0xad,
+	0xae,
+	0xaf,
+};
+
+#define WM5100_MIXER_CONTROLS(name, base) \
+	SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+		       WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+	SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+		       WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+	SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+		       WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+	SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+		       WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM5100_MUX_ENUM_DECL(name, reg) \
+	SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, 			\
+				   wm5100_mixer_texts, wm5100_mixer_values)
+
+#define WM5100_MUX_CTL_DECL(name) \
+	const struct snd_kcontrol_new name##_mux =	\
+		SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM5100_MIXER_ENUMS(name, base_reg) \
+	static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg);	     \
+	static WM5100_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
+	static WM5100_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
+	static WM5100_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
+	static WM5100_MUX_CTL_DECL(name##_in1); \
+	static WM5100_MUX_CTL_DECL(name##_in2); \
+	static WM5100_MUX_CTL_DECL(name##_in3); \
+	static WM5100_MUX_CTL_DECL(name##_in4) 
+
+WM5100_MIXER_ENUMS(HPOUT1L, WM5100_OUT1LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT1R, WM5100_OUT1RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT2L, WM5100_OUT2LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT2R, WM5100_OUT2RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT3L, WM5100_OUT3LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT3R, WM5100_OUT3RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(SPKOUTL, WM5100_OUT4LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKOUTR, WM5100_OUT4RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT1L, WM5100_OUT5LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT1R, WM5100_OUT5RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT2L, WM5100_OUT6LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT2R, WM5100_OUT6RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(PWM1, WM5100_PWM1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(PWM2, WM5100_PWM1MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF1TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX3, WM5100_AIF1TX3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX4, WM5100_AIF1TX4MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX5, WM5100_AIF1TX5MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX6, WM5100_AIF1TX6MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX7, WM5100_AIF1TX7MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX8, WM5100_AIF1TX8MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF2TX1, WM5100_AIF2TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF2TX2, WM5100_AIF2TX2MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF3TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF3TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(EQ1, WM5100_EQ1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ2, WM5100_EQ2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ3, WM5100_EQ3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ4, WM5100_EQ4MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(DRC1L, WM5100_DRC1LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(DRC1R, WM5100_DRC1RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(LHPF1, WM5100_HPLP1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF2, WM5100_HPLP2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE);
+
+#define WM5100_MUX(name, ctrl) \
+	SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM5100_MIXER_WIDGETS(name, name_str)	\
+	WM5100_MUX(name_str " Input 1", &name##_in1_mux), \
+	WM5100_MUX(name_str " Input 2", &name##_in2_mux), \
+	WM5100_MUX(name_str " Input 3", &name##_in3_mux), \
+	WM5100_MUX(name_str " Input 4", &name##_in4_mux), \
+	SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM5100_MIXER_INPUT_ROUTES(name)	\
+	{ 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, "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, "LHPF1", "LHPF1" }, \
+        { name, "LHPF2", "LHPF2" }, \
+        { name, "LHPF3", "LHPF3" }, \
+        { name, "LHPF4", "LHPF4" }
+
+#define WM5100_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" }, \
+	WM5100_MIXER_INPUT_ROUTES(name " Input 1"), \
+	WM5100_MIXER_INPUT_ROUTES(name " Input 2"), \
+	WM5100_MIXER_INPUT_ROUTES(name " Input 3"), \
+	WM5100_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const char *wm5100_lhpf_mode_text[] = {
+	"Low-pass", "High-pass"
+};
+
+static const struct soc_enum wm5100_lhpf1_mode =
+	SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2,
+			wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf2_mode =
+	SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2,
+			wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf3_mode =
+	SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2,
+			wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf4_mode =
+	SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2,
+			wm5100_lhpf_mode_text);
+
+static const struct snd_kcontrol_new wm5100_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL,
+	   WM5100_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM5100_IN2L_CONTROL,
+	   WM5100_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM5100_IN3L_CONTROL,
+	   WM5100_IN3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN4 High Performance Switch", WM5100_IN4L_CONTROL,
+	   WM5100_IN4_OSR_SHIFT, 1, 0),
+
+/* Only applicable for analogue inputs */
+SOC_DOUBLE_R_TLV("IN1 Volume", WM5100_IN1L_CONTROL, WM5100_IN1R_CONTROL,
+		 WM5100_IN1L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM5100_IN2L_CONTROL, WM5100_IN2R_CONTROL,
+		 WM5100_IN2L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM5100_IN3L_CONTROL, WM5100_IN3R_CONTROL,
+		 WM5100_IN3L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN4 Volume", WM5100_IN4L_CONTROL, WM5100_IN4R_CONTROL,
+		 WM5100_IN4L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_1L,
+		 WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_VOL_SHIFT, 191,
+		 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_2L,
+		 WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_VOL_SHIFT, 191,
+		 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_3L,
+		 WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_VOL_SHIFT, 191,
+		 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN4 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_4L,
+		 WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_VOL_SHIFT, 191,
+		 0, digital_tlv),
+
+SOC_DOUBLE_R("IN1 Switch", WM5100_ADC_DIGITAL_VOLUME_1L,
+	     WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Switch", WM5100_ADC_DIGITAL_VOLUME_2L,
+	     WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Switch", WM5100_ADC_DIGITAL_VOLUME_3L,
+	     WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN4 Switch", WM5100_ADC_DIGITAL_VOLUME_4L,
+	     WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_MUTE_SHIFT, 1, 1),
+
+SOC_SINGLE("HPOUT1 High Performance Switch", WM5100_OUT_VOLUME_1L,
+	   WM5100_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT2 High Performance Switch", WM5100_OUT_VOLUME_2L,
+	   WM5100_OUT2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT3 High Performance Switch", WM5100_OUT_VOLUME_3L,
+	   WM5100_OUT3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKOUT High Performance Switch", WM5100_OUT_VOLUME_4L,
+	   WM5100_OUT4_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT1 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_5L,
+	   WM5100_OUT5_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT2 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_6L,
+	   WM5100_OUT6_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_1L,
+		 WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_VOL_SHIFT, 159, 0,
+		 digital_tlv),
+SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_2L,
+		 WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_VOL_SHIFT, 159, 0,
+		 digital_tlv),
+SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_3L,
+		 WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_VOL_SHIFT, 159, 0,
+		 digital_tlv),
+SOC_DOUBLE_R_TLV("SPKOUT Digital Volume", WM5100_DAC_DIGITAL_VOLUME_4L,
+		 WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_VOL_SHIFT, 159, 0,
+		 digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_5L,
+		 WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_VOL_SHIFT, 159, 0,
+		 digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_6L,
+		 WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_VOL_SHIFT, 159, 0,
+		 digital_tlv),
+
+SOC_DOUBLE_R("HPOUT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_1L,
+	     WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("HPOUT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_2L,
+	     WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("HPOUT3 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_3L,
+	     WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKOUT Digital Switch", WM5100_DAC_DIGITAL_VOLUME_4L,
+	     WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_5L,
+	     WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_6L,
+	     WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_MUTE_SHIFT, 1, 1),
+
+/* FIXME: Only valid from -12dB to 0dB (52-64) */
+SOC_DOUBLE_R_TLV("HPOUT1 Volume", WM5100_OUT_VOLUME_1L, WM5100_OUT_VOLUME_1R,
+		 WM5100_OUT1L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("HPOUT2 Volume", WM5100_OUT_VOLUME_2L, WM5100_OUT_VOLUME_2R,
+		 WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("HPOUT3 Volume", WM5100_OUT_VOLUME_3L, WM5100_OUT_VOLUME_3R,
+		 WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+
+SOC_DOUBLE("SPKDAT1 Switch", WM5100_PDM_SPK1_CTRL_1, WM5100_SPK1L_MUTE_SHIFT,
+	   WM5100_SPK1R_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE("SPKDAT2 Switch", WM5100_PDM_SPK2_CTRL_1, WM5100_SPK2L_MUTE_SHIFT,
+	   WM5100_SPK2R_MUTE_SHIFT, 1, 1),
+
+SOC_SINGLE_TLV("EQ1 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ1_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 2 Volume", WM5100_EQ1_1, WM5100_EQ1_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 3 Volume", WM5100_EQ1_1, WM5100_EQ1_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 4 Volume", WM5100_EQ1_2, WM5100_EQ1_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 5 Volume", WM5100_EQ1_2, WM5100_EQ1_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ2 Band 1 Volume", WM5100_EQ2_1, WM5100_EQ2_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 2 Volume", WM5100_EQ2_1, WM5100_EQ2_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 3 Volume", WM5100_EQ2_1, WM5100_EQ2_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 4 Volume", WM5100_EQ2_2, WM5100_EQ2_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 5 Volume", WM5100_EQ2_2, WM5100_EQ2_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ3 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ3_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 2 Volume", WM5100_EQ3_1, WM5100_EQ3_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 3 Volume", WM5100_EQ3_1, WM5100_EQ3_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 4 Volume", WM5100_EQ3_2, WM5100_EQ3_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 5 Volume", WM5100_EQ3_2, WM5100_EQ3_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ4 Band 1 Volume", WM5100_EQ4_1, WM5100_EQ4_B1_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 2 Volume", WM5100_EQ4_1, WM5100_EQ4_B2_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 3 Volume", WM5100_EQ4_1, WM5100_EQ4_B3_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 4 Volume", WM5100_EQ4_2, WM5100_EQ4_B4_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 5 Volume", WM5100_EQ4_2, WM5100_EQ4_B5_GAIN_SHIFT,
+	       24, 0, eq_tlv),
+
+SOC_ENUM("LHPF1 Mode", wm5100_lhpf1_mode),
+SOC_ENUM("LHPF2 Mode", wm5100_lhpf2_mode),
+SOC_ENUM("LHPF3 Mode", wm5100_lhpf3_mode),
+SOC_ENUM("LHPF4 Mode", wm5100_lhpf4_mode),
+
+WM5100_MIXER_CONTROLS("HPOUT1L", WM5100_OUT1LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT1R", WM5100_OUT1RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT2L", WM5100_OUT2LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT2R", WM5100_OUT2RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT3L", WM5100_OUT3LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT3R", WM5100_OUT3RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("SPKOUTL", WM5100_OUT4LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKOUTR", WM5100_OUT4RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT1L", WM5100_OUT5LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT1R", WM5100_OUT5RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT2L", WM5100_OUT6LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT2R", WM5100_OUT6RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("PWM1", WM5100_PWM1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("PWM2", WM5100_PWM2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF1TX1", WM5100_AIF1TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX2", WM5100_AIF1TX2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX3", WM5100_AIF1TX3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX4", WM5100_AIF1TX4MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX5", WM5100_AIF1TX5MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX6", WM5100_AIF1TX6MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX7", WM5100_AIF1TX7MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX8", WM5100_AIF1TX8MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF2TX1", WM5100_AIF2TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF2TX2", WM5100_AIF2TX2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF3TX1", WM5100_AIF3TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF3TX2", WM5100_AIF3TX2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("EQ1", WM5100_EQ1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ2", WM5100_EQ2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ3", WM5100_EQ3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF3", WM5100_HPLP3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE),
+};
+
+static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm,
+				enum snd_soc_dapm_type event, int subseq)
+{
+	struct snd_soc_codec *codec = container_of(dapm,
+						   struct snd_soc_codec, dapm);
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	u16 val, expect, i;
+
+	/* Wait for the outputs to flag themselves as enabled */
+	if (wm5100->out_ena[0]) {
+		expect = snd_soc_read(codec, WM5100_CHANNEL_ENABLES_1);
+		for (i = 0; i < 200; i++) {
+			val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_1);
+			if (val == expect) {
+				wm5100->out_ena[0] = false;
+				break;
+			}
+		}
+		if (i == 200) {
+			dev_err(codec->dev, "Timeout waiting for OUTPUT1 %x\n",
+				expect);
+		}
+	}
+
+	if (wm5100->out_ena[1]) {
+		expect = snd_soc_read(codec, WM5100_OUTPUT_ENABLES_2);
+		for (i = 0; i < 200; i++) {
+			val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_2);
+			if (val == expect) {
+				wm5100->out_ena[1] = false;
+				break;
+			}
+		}
+		if (i == 200) {
+			dev_err(codec->dev, "Timeout waiting for OUTPUT2 %x\n",
+				expect);
+		}
+	}
+}
+
+static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol,
+			 int event)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec);
+
+	switch (w->reg) {
+	case WM5100_CHANNEL_ENABLES_1:
+		wm5100->out_ena[0] = true;
+		break;
+	case WM5100_OUTPUT_ENABLES_2:
+		wm5100->out_ena[0] = true;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int wm5100_cp_ev(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *kcontrol,
+			int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = regulator_enable(wm5100->cpvdd);
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
+				ret);
+			return ret;
+		}
+		return ret;
+
+	case SND_SOC_DAPM_POST_PMD:
+		ret = regulator_disable_deferred(wm5100->cpvdd, 20);
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to disable CPVDD: %d\n",
+				ret);
+			return ret;
+		}
+		return ret;
+
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol,
+			   int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	struct regulator *regulator;
+	int ret;
+
+	switch (w->shift) {
+	case 2:
+		regulator = wm5100->dbvdd2;
+		break;
+	case 3:
+		regulator = wm5100->dbvdd3;
+		break;
+	default:
+		BUG();
+		return 0;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = regulator_enable(regulator);
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
+				w->shift, ret);
+			return ret;
+		}
+		return ret;
+
+	case SND_SOC_DAPM_POST_PMD:
+		ret = regulator_disable(regulator);
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
+				w->shift, ret);
+			return ret;
+		}
+		return ret;
+
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static void wm5100_log_status3(struct snd_soc_codec *codec, int val)
+{
+	if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
+		dev_crit(codec->dev, "Speaker shutdown warning\n");
+	if (val & WM5100_SPK_SHUTDOWN_EINT)
+		dev_crit(codec->dev, "Speaker shutdown\n");
+	if (val & WM5100_CLKGEN_ERR_EINT)
+		dev_crit(codec->dev, "SYSCLK underclocked\n");
+	if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
+		dev_crit(codec->dev, "ASYNCCLK underclocked\n");
+}
+
+static void wm5100_log_status4(struct snd_soc_codec *codec, int val)
+{
+	if (val & WM5100_AIF3_ERR_EINT)
+		dev_err(codec->dev, "AIF3 configuration error\n");
+	if (val & WM5100_AIF2_ERR_EINT)
+		dev_err(codec->dev, "AIF2 configuration error\n");
+	if (val & WM5100_AIF1_ERR_EINT)
+		dev_err(codec->dev, "AIF1 configuration error\n");
+	if (val & WM5100_CTRLIF_ERR_EINT)
+		dev_err(codec->dev, "Control interface error\n");
+	if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "ISRC2 underclocked\n");
+	if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "ISRC1 underclocked\n");
+	if (val & WM5100_FX_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "FX underclocked\n");
+	if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "AIF3 underclocked\n");
+	if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "AIF2 underclocked\n");
+	if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "AIF1 underclocked\n");
+	if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "ASRC underclocked\n");
+	if (val & WM5100_DAC_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "DAC underclocked\n");
+	if (val & WM5100_ADC_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "ADC underclocked\n");
+	if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
+		dev_err(codec->dev, "Mixer underclocked\n");
+}
+
+static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol,
+			  int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	int ret;
+
+	ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
+	ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
+		WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
+		WM5100_CLKGEN_ERR_ASYNC_STS;
+	wm5100_log_status3(codec, ret);
+
+	ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
+	wm5100_log_status4(codec, ret);
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget wm5100_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
+		    NULL, 0),
+SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
+		    0, NULL, 0),
+
+SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
+		    wm5100_cp_ev,
+		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
+		    NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
+		    WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev,
+		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev,
+		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev,
+		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
+		    0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM5100_MIC_BIAS_CTRL_2, WM5100_MICB2_ENA_SHIFT,
+		    0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS3", WM5100_MIC_BIAS_CTRL_3, WM5100_MICB3_ENA_SHIFT,
+		    0, NULL, 0),
+
+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_INPUT("TONE"),
+
+SND_SOC_DAPM_PGA_E("IN1L PGA", WM5100_INPUT_ENABLES, WM5100_IN1L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN1R PGA", WM5100_INPUT_ENABLES, WM5100_IN1R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2L PGA", WM5100_INPUT_ENABLES, WM5100_IN2L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2R PGA", WM5100_INPUT_ENABLES, WM5100_IN2R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3L PGA", WM5100_INPUT_ENABLES, WM5100_IN3L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3R PGA", WM5100_INPUT_ENABLES, WM5100_IN3R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4L PGA", WM5100_INPUT_ENABLES, WM5100_IN4L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4R PGA", WM5100_INPUT_ENABLES, WM5100_IN4R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("Tone Generator 1", WM5100_TONE_GENERATOR_1,
+		 WM5100_TONE1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Tone Generator 2", WM5100_TONE_GENERATOR_1,
+		 WM5100_TONE2_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 0,
+		    WM5100_AUDIO_IF_1_27, WM5100_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 1,
+		    WM5100_AUDIO_IF_1_27, WM5100_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 2,
+		    WM5100_AUDIO_IF_1_27, WM5100_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 3,
+		    WM5100_AUDIO_IF_1_27, WM5100_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 4,
+		    WM5100_AUDIO_IF_1_27, WM5100_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "AIF1 Playback", 5,
+		    WM5100_AUDIO_IF_1_27, WM5100_AIF1RX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX7", "AIF1 Playback", 6,
+		    WM5100_AUDIO_IF_1_27, WM5100_AIF1RX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX8", "AIF1 Playback", 7,
+		    WM5100_AUDIO_IF_1_27, WM5100_AIF1RX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
+		    WM5100_AUDIO_IF_2_27, WM5100_AIF2RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX2", "AIF2 Playback", 1,
+		    WM5100_AUDIO_IF_2_27, WM5100_AIF2RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF3RX1", "AIF3 Playback", 0,
+		    WM5100_AUDIO_IF_3_27, WM5100_AIF3RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF3RX2", "AIF3 Playback", 1,
+		    WM5100_AUDIO_IF_3_27, WM5100_AIF3RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 0,
+		    WM5100_AUDIO_IF_1_26, WM5100_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 1,
+		    WM5100_AUDIO_IF_1_26, WM5100_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 2,
+		    WM5100_AUDIO_IF_1_26, WM5100_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 3,
+		    WM5100_AUDIO_IF_1_26, WM5100_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 4,
+		    WM5100_AUDIO_IF_1_26, WM5100_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "AIF1 Capture", 5,
+		    WM5100_AUDIO_IF_1_26, WM5100_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX7", "AIF1 Capture", 6,
+		    WM5100_AUDIO_IF_1_26, WM5100_AIF1TX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX8", "AIF1 Capture", 7,
+		    WM5100_AUDIO_IF_1_26, WM5100_AIF1TX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
+		    WM5100_AUDIO_IF_2_26, WM5100_AIF2TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX2", "AIF2 Capture", 1,
+		    WM5100_AUDIO_IF_2_26, WM5100_AIF2TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF3TX1", "AIF3 Capture", 0,
+		    WM5100_AUDIO_IF_3_26, WM5100_AIF3TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3TX2", "AIF3 Capture", 1,
+		    WM5100_AUDIO_IF_3_26, WM5100_AIF3TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_E("OUT6L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT6R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3L", WM5100_CHANNEL_ENABLES_1, WM5100_HP3L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3R", WM5100_CHANNEL_ENABLES_1, WM5100_HP3R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2L", WM5100_CHANNEL_ENABLES_1, WM5100_HP2L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2R", WM5100_CHANNEL_ENABLES_1, WM5100_HP2R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1L", WM5100_CHANNEL_ENABLES_1, WM5100_HP1L_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1R", WM5100_CHANNEL_ENABLES_1, WM5100_HP1R_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("PWM1 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM1_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("PWM2 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM2_ENA_SHIFT, 0,
+		   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("EQ1", WM5100_EQ1_1, WM5100_EQ1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ2", WM5100_EQ2_1, WM5100_EQ2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ3", WM5100_EQ3_1, WM5100_EQ3_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ4", WM5100_EQ4_1, WM5100_EQ4_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("DRC1L", WM5100_DRC1_CTRL1, WM5100_DRCL_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("DRC1R", WM5100_DRC1_CTRL1, WM5100_DRCR_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM5100_HPLPF1_1, WM5100_LHPF1_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM5100_HPLPF2_1, WM5100_LHPF2_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF3", WM5100_HPLPF3_1, WM5100_LHPF3_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF4", WM5100_HPLPF4_1, WM5100_LHPF4_ENA_SHIFT, 0,
+		 NULL, 0),
+
+WM5100_MIXER_WIDGETS(EQ1, "EQ1"),
+WM5100_MIXER_WIDGETS(EQ2, "EQ2"),
+WM5100_MIXER_WIDGETS(EQ3, "EQ3"),
+WM5100_MIXER_WIDGETS(EQ4, "EQ4"),
+
+WM5100_MIXER_WIDGETS(DRC1L, "DRC1L"),
+WM5100_MIXER_WIDGETS(DRC1R, "DRC1R"),
+
+WM5100_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM5100_MIXER_WIDGETS(LHPF2, "LHPF2"),
+WM5100_MIXER_WIDGETS(LHPF3, "LHPF3"),
+WM5100_MIXER_WIDGETS(LHPF4, "LHPF4"),
+
+WM5100_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM5100_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM5100_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM5100_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM5100_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM5100_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+WM5100_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
+WM5100_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
+
+WM5100_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
+WM5100_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+
+WM5100_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
+WM5100_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
+
+WM5100_MIXER_WIDGETS(HPOUT1L, "HPOUT1L"),
+WM5100_MIXER_WIDGETS(HPOUT1R, "HPOUT1R"),
+WM5100_MIXER_WIDGETS(HPOUT2L, "HPOUT2L"),
+WM5100_MIXER_WIDGETS(HPOUT2R, "HPOUT2R"),
+WM5100_MIXER_WIDGETS(HPOUT3L, "HPOUT3L"),
+WM5100_MIXER_WIDGETS(HPOUT3R, "HPOUT3R"),
+
+WM5100_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
+WM5100_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
+WM5100_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
+WM5100_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
+WM5100_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"),
+WM5100_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"),
+
+WM5100_MIXER_WIDGETS(PWM1, "PWM1"),
+WM5100_MIXER_WIDGETS(PWM2, "PWM2"),
+
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("HPOUT2L"),
+SND_SOC_DAPM_OUTPUT("HPOUT2R"),
+SND_SOC_DAPM_OUTPUT("HPOUT3L"),
+SND_SOC_DAPM_OUTPUT("HPOUT3R"),
+SND_SOC_DAPM_OUTPUT("SPKOUTL"),
+SND_SOC_DAPM_OUTPUT("SPKOUTR"),
+SND_SOC_DAPM_OUTPUT("SPKDAT1"),
+SND_SOC_DAPM_OUTPUT("SPKDAT2"),
+SND_SOC_DAPM_OUTPUT("PWM1"),
+SND_SOC_DAPM_OUTPUT("PWM2"),
+};
+
+/* We register a _POST event if we don't have IRQ support so we can
+ * look at the error status from the CODEC - if we've got the IRQ
+ * hooked up then we will get prompted to look by an interrupt.
+ */
+static const struct snd_soc_dapm_widget wm5100_dapm_widgets_noirq[] = {
+SND_SOC_DAPM_POST("Post", wm5100_post_ev),
+};
+
+static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+	{ "IN1L", NULL, "SYSCLK" },
+	{ "IN1R", NULL, "SYSCLK" },
+	{ "IN2L", NULL, "SYSCLK" },
+	{ "IN2R", NULL, "SYSCLK" },
+	{ "IN3L", NULL, "SYSCLK" },
+	{ "IN3R", NULL, "SYSCLK" },
+	{ "IN4L", NULL, "SYSCLK" },
+	{ "IN4R", NULL, "SYSCLK" },
+
+	{ "OUT1L", NULL, "SYSCLK" },
+	{ "OUT1R", NULL, "SYSCLK" },
+	{ "OUT2L", NULL, "SYSCLK" },
+	{ "OUT2R", NULL, "SYSCLK" },
+	{ "OUT3L", NULL, "SYSCLK" },
+	{ "OUT3R", NULL, "SYSCLK" },
+	{ "OUT4L", NULL, "SYSCLK" },
+	{ "OUT4R", NULL, "SYSCLK" },
+	{ "OUT5L", NULL, "SYSCLK" },
+	{ "OUT5R", NULL, "SYSCLK" },
+	{ "OUT6L", NULL, "SYSCLK" },
+	{ "OUT6R", NULL, "SYSCLK" },
+
+	{ "AIF1RX1", NULL, "SYSCLK" },
+	{ "AIF1RX2", NULL, "SYSCLK" },
+	{ "AIF1RX3", NULL, "SYSCLK" },
+	{ "AIF1RX4", NULL, "SYSCLK" },
+	{ "AIF1RX5", NULL, "SYSCLK" },
+	{ "AIF1RX6", NULL, "SYSCLK" },
+	{ "AIF1RX7", NULL, "SYSCLK" },
+	{ "AIF1RX8", NULL, "SYSCLK" },
+
+	{ "AIF2RX1", NULL, "SYSCLK" },
+	{ "AIF2RX1", NULL, "DBVDD2" },
+	{ "AIF2RX2", NULL, "SYSCLK" },
+	{ "AIF2RX2", NULL, "DBVDD2" },
+
+	{ "AIF3RX1", NULL, "SYSCLK" },
+	{ "AIF3RX1", NULL, "DBVDD3" },
+	{ "AIF3RX2", NULL, "SYSCLK" },
+	{ "AIF3RX2", NULL, "DBVDD3" },
+
+	{ "AIF1TX1", NULL, "SYSCLK" },
+	{ "AIF1TX2", NULL, "SYSCLK" },
+	{ "AIF1TX3", NULL, "SYSCLK" },
+	{ "AIF1TX4", NULL, "SYSCLK" },
+	{ "AIF1TX5", NULL, "SYSCLK" },
+	{ "AIF1TX6", NULL, "SYSCLK" },
+	{ "AIF1TX7", NULL, "SYSCLK" },
+	{ "AIF1TX8", NULL, "SYSCLK" },
+
+	{ "AIF2TX1", NULL, "SYSCLK" },
+	{ "AIF2TX1", NULL, "DBVDD2" },
+	{ "AIF2TX2", NULL, "SYSCLK" },
+	{ "AIF2TX2", NULL, "DBVDD2" },
+
+	{ "AIF3TX1", NULL, "SYSCLK" },
+	{ "AIF3TX1", NULL, "DBVDD3" },
+	{ "AIF3TX2", NULL, "SYSCLK" },
+	{ "AIF3TX2", NULL, "DBVDD3" },
+
+	{ "MICBIAS1", NULL, "CP2" },
+	{ "MICBIAS2", NULL, "CP2" },
+	{ "MICBIAS3", NULL, "CP2" },
+
+	{ "IN1L PGA", NULL, "CP2" },
+	{ "IN1R PGA", NULL, "CP2" },
+	{ "IN2L PGA", NULL, "CP2" },
+	{ "IN2R PGA", NULL, "CP2" },
+	{ "IN3L PGA", NULL, "CP2" },
+	{ "IN3R PGA", NULL, "CP2" },
+	{ "IN4L PGA", NULL, "CP2" },
+	{ "IN4R PGA", NULL, "CP2" },
+
+	{ "IN1L PGA", NULL, "CP2 Active" },
+	{ "IN1R PGA", NULL, "CP2 Active" },
+	{ "IN2L PGA", NULL, "CP2 Active" },
+	{ "IN2R PGA", NULL, "CP2 Active" },
+	{ "IN3L PGA", NULL, "CP2 Active" },
+	{ "IN3R PGA", NULL, "CP2 Active" },
+	{ "IN4L PGA", NULL, "CP2 Active" },
+	{ "IN4R PGA", NULL, "CP2 Active" },
+
+	{ "OUT1L", NULL, "CP1" },
+	{ "OUT1R", NULL, "CP1" },
+	{ "OUT2L", NULL, "CP1" },
+	{ "OUT2R", NULL, "CP1" },
+	{ "OUT3L", NULL, "CP1" },
+	{ "OUT3R", NULL, "CP1" },
+
+	{ "Tone Generator 1", NULL, "TONE" },
+	{ "Tone Generator 2", NULL, "TONE" },
+
+	{ "IN1L PGA", NULL, "IN1L" },
+	{ "IN1R PGA", NULL, "IN1R" },
+	{ "IN2L PGA", NULL, "IN2L" },
+	{ "IN2R PGA", NULL, "IN2R" },
+	{ "IN3L PGA", NULL, "IN3L" },
+	{ "IN3R PGA", NULL, "IN3R" },
+	{ "IN4L PGA", NULL, "IN4L" },
+	{ "IN4R PGA", NULL, "IN4R" },
+
+	WM5100_MIXER_ROUTES("OUT1L", "HPOUT1L"),
+	WM5100_MIXER_ROUTES("OUT1R", "HPOUT1R"),
+	WM5100_MIXER_ROUTES("OUT2L", "HPOUT2L"),
+	WM5100_MIXER_ROUTES("OUT2R", "HPOUT2R"),
+	WM5100_MIXER_ROUTES("OUT3L", "HPOUT3L"),
+	WM5100_MIXER_ROUTES("OUT3R", "HPOUT3R"),
+
+	WM5100_MIXER_ROUTES("OUT4L", "SPKOUTL"),
+	WM5100_MIXER_ROUTES("OUT4R", "SPKOUTR"),
+	WM5100_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
+	WM5100_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
+	WM5100_MIXER_ROUTES("OUT6L", "SPKDAT2L"),
+	WM5100_MIXER_ROUTES("OUT6R", "SPKDAT2R"),
+
+	WM5100_MIXER_ROUTES("PWM1 Driver", "PWM1"),
+	WM5100_MIXER_ROUTES("PWM2 Driver", "PWM2"),
+
+	WM5100_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+	WM5100_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+	WM5100_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+	WM5100_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+	WM5100_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+	WM5100_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+	WM5100_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
+	WM5100_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
+
+	WM5100_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
+	WM5100_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+
+	WM5100_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
+	WM5100_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
+
+	WM5100_MIXER_ROUTES("EQ1", "EQ1"),
+	WM5100_MIXER_ROUTES("EQ2", "EQ2"),
+	WM5100_MIXER_ROUTES("EQ3", "EQ3"),
+	WM5100_MIXER_ROUTES("EQ4", "EQ4"),
+
+	WM5100_MIXER_ROUTES("DRC1L", "DRC1L"),
+	WM5100_MIXER_ROUTES("DRC1R", "DRC1R"),
+
+	WM5100_MIXER_ROUTES("LHPF1", "LHPF1"),
+	WM5100_MIXER_ROUTES("LHPF2", "LHPF2"),
+	WM5100_MIXER_ROUTES("LHPF3", "LHPF3"),
+	WM5100_MIXER_ROUTES("LHPF4", "LHPF4"),
+
+	{ "HPOUT1L", NULL, "OUT1L" },
+	{ "HPOUT1R", NULL, "OUT1R" },
+	{ "HPOUT2L", NULL, "OUT2L" },
+	{ "HPOUT2R", NULL, "OUT2R" },
+	{ "HPOUT3L", NULL, "OUT3L" },
+	{ "HPOUT3R", NULL, "OUT3R" },
+	{ "SPKOUTL", NULL, "OUT4L" },
+	{ "SPKOUTR", NULL, "OUT4R" },
+	{ "SPKDAT1", NULL, "OUT5L" },
+	{ "SPKDAT1", NULL, "OUT5R" },
+	{ "SPKDAT2", NULL, "OUT6L" },
+	{ "SPKDAT2", NULL, "OUT6R" },
+	{ "PWM1", NULL, "PWM1 Driver" },
+	{ "PWM2", NULL, "PWM2 Driver" },
+};
+
+static struct {
+	int reg;
+	int val;
+} wm5100_reva_patches[] = {
+	{ WM5100_AUDIO_IF_1_10, 0 },
+	{ WM5100_AUDIO_IF_1_11, 1 },
+	{ WM5100_AUDIO_IF_1_12, 2 },
+	{ WM5100_AUDIO_IF_1_13, 3 },
+	{ WM5100_AUDIO_IF_1_14, 4 },
+	{ WM5100_AUDIO_IF_1_15, 5 },
+	{ WM5100_AUDIO_IF_1_16, 6 },
+	{ WM5100_AUDIO_IF_1_17, 7 },
+
+	{ WM5100_AUDIO_IF_1_18, 0 },
+	{ WM5100_AUDIO_IF_1_19, 1 },
+	{ WM5100_AUDIO_IF_1_20, 2 },
+	{ WM5100_AUDIO_IF_1_21, 3 },
+	{ WM5100_AUDIO_IF_1_22, 4 },
+	{ WM5100_AUDIO_IF_1_23, 5 },
+	{ WM5100_AUDIO_IF_1_24, 6 },
+	{ WM5100_AUDIO_IF_1_25, 7 },
+
+	{ WM5100_AUDIO_IF_2_10, 0 },
+	{ WM5100_AUDIO_IF_2_11, 1 },
+
+	{ WM5100_AUDIO_IF_2_18, 0 },
+	{ WM5100_AUDIO_IF_2_19, 1 },
+
+	{ WM5100_AUDIO_IF_3_10, 0 },
+	{ WM5100_AUDIO_IF_3_11, 1 },
+
+	{ WM5100_AUDIO_IF_3_18, 0 },
+	{ WM5100_AUDIO_IF_3_19, 1 },
+};
+
+static int wm5100_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int ret, i;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+						    wm5100->core_supplies);
+			if (ret != 0) {
+				dev_err(codec->dev,
+					"Failed to enable supplies: %d\n",
+					ret);
+				return ret;
+			}
+
+			if (wm5100->pdata.ldo_ena) {
+				gpio_set_value_cansleep(wm5100->pdata.ldo_ena,
+							1);
+				msleep(2);
+			}
+
+			codec->cache_only = false;
+
+			switch (wm5100->rev) {
+			case 0:
+				snd_soc_write(codec, 0x11, 0x3);
+				snd_soc_write(codec, 0x203, 0xc);
+				snd_soc_write(codec, 0x206, 0);
+				snd_soc_write(codec, 0x207, 0xf0);
+				snd_soc_write(codec, 0x208, 0x3c);
+				snd_soc_write(codec, 0x209, 0);
+				snd_soc_write(codec, 0x211, 0x20d8);
+				snd_soc_write(codec, 0x11, 0);
+
+				for (i = 0;
+				     i < ARRAY_SIZE(wm5100_reva_patches);
+				     i++)
+					snd_soc_write(codec,
+						      wm5100_reva_patches[i].reg,
+						      wm5100_reva_patches[i].val);
+				break;
+			default:
+				break;
+			}
+
+			snd_soc_cache_sync(codec);
+		}
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		if (wm5100->pdata.ldo_ena)
+			gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+		regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+				       wm5100->core_supplies);
+		break;
+	}
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static int wm5100_dai_to_base(struct snd_soc_dai *dai)
+{
+	switch (dai->id) {
+	case 0:
+		return WM5100_AUDIO_IF_1_1 - 1;
+	case 1:
+		return WM5100_AUDIO_IF_2_1 - 1;
+	case 2:
+		return WM5100_AUDIO_IF_3_1 - 1;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+}
+
+static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	int lrclk, bclk, mask, base;
+
+	base = wm5100_dai_to_base(dai);
+	if (base < 0)
+		return base;
+
+	lrclk = 0;
+	bclk = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+		mask = 0;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		mask = 1;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		mask = 2;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		mask = 3;
+		break;
+	default:
+		dev_err(codec->dev, "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 |= WM5100_AIF1TX_LRCLK_MSTR;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		bclk |= WM5100_AIF1_BCLK_MSTR;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
+		bclk |= WM5100_AIF1_BCLK_MSTR;
+		break;
+	default:
+		dev_err(codec->dev, "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 |= WM5100_AIF1_BCLK_INV;
+		lrclk |= WM5100_AIF1TX_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		bclk |= WM5100_AIF1_BCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		lrclk |= WM5100_AIF1TX_LRCLK_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_MSTR |
+			    WM5100_AIF1_BCLK_INV, bclk);
+	snd_soc_update_bits(codec, base + 2, WM5100_AIF1TX_LRCLK_MSTR |
+			    WM5100_AIF1TX_LRCLK_INV, lrclk);
+	snd_soc_update_bits(codec, base + 3, WM5100_AIF1TX_LRCLK_MSTR |
+			    WM5100_AIF1TX_LRCLK_INV, lrclk);
+	snd_soc_update_bits(codec, base + 5, WM5100_AIF1_FMT_MASK, mask);
+
+	return 0;
+}
+
+#define WM5100_NUM_BCLK_RATES 19
+
+static int wm5100_bclk_rates_dat[WM5100_NUM_BCLK_RATES] = {
+	32000,
+	48000,
+	64000,
+	96000,
+	128000,
+	192000,
+	256000,
+	384000,
+	512000,
+	768000,
+	1024000,
+	1536000,
+	2048000,
+	3072000,
+	4096000,
+	6144000,
+	8192000,
+	12288000,
+	24576000,
+};
+
+static int wm5100_bclk_rates_cd[WM5100_NUM_BCLK_RATES] = {
+	29400,
+	44100,
+	58800,
+	88200,
+	117600,
+	176400,
+	235200,
+	352800,
+	470400,
+	705600,
+	940800,
+	1411200,
+	1881600,
+	2882400,
+	3763200,
+	5644800,
+	7526400,
+	11289600,
+	22579600,
+};
+
+static int wm5100_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 wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	bool async = wm5100->aif_async[dai->id];
+	int i, base, bclk, aif_rate, lrclk, wl, fl, sr;
+	int *bclk_rates;
+
+	base = wm5100_dai_to_base(dai);
+	if (base < 0)
+		return base;
+
+	/* Data sizes if not using TDM */
+	wl = snd_pcm_format_width(params_format(params));
+	if (wl < 0)
+		return wl;
+	fl = snd_soc_params_to_frame_size(params);
+	if (fl < 0)
+		return fl;
+
+	dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+		wl, fl);
+
+	/* Target BCLK rate */
+	bclk = snd_soc_params_to_bclk(params);
+	if (bclk < 0)
+		return bclk;
+
+	/* Root for BCLK depends on SYS/ASYNCCLK */
+	if (!async) {
+		aif_rate = wm5100->sysclk;
+		sr = wm5100_alloc_sr(codec, params_rate(params));
+		if (sr < 0)
+			return sr;
+	} else {
+		/* If we're in ASYNCCLK set the ASYNC sample rate */
+		aif_rate = wm5100->asyncclk;
+		sr = 3;
+
+		for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+			if (params_rate(params) == wm5100_sr_code[i])
+				break;
+		if (i == ARRAY_SIZE(wm5100_sr_code)) {
+			dev_err(codec->dev, "Invalid rate %dHzn",
+				params_rate(params));
+			return -EINVAL;
+		}
+
+		/* TODO: We should really check for symmetry */
+		snd_soc_update_bits(codec, WM5100_CLOCKING_8,
+				    WM5100_ASYNC_SAMPLE_RATE_MASK, i);
+	}
+
+	if (!aif_rate) {
+		dev_err(codec->dev, "%s has no rate set\n",
+			async ? "ASYNCCLK" : "SYSCLK");
+		return -EINVAL;
+	}
+
+	dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz %s\n",
+		bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
+
+	if (aif_rate % 4000)
+		bclk_rates = wm5100_bclk_rates_cd;
+	else
+		bclk_rates = wm5100_bclk_rates_dat;
+
+	for (i = 0; i < WM5100_NUM_BCLK_RATES; i++)
+		if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+			break;
+	if (i == WM5100_NUM_BCLK_RATES) {
+		dev_err(codec->dev,
+			"No valid BCLK for %dHz found from %dHz %s\n",
+			bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
+		return -EINVAL;
+	}
+
+	bclk = i;
+	dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+	snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_FREQ_MASK, bclk);
+
+	lrclk = bclk_rates[bclk] / params_rate(params);
+	dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+	    wm5100->aif_symmetric[dai->id])
+		snd_soc_update_bits(codec, base + 7,
+				    WM5100_AIF1RX_BCPF_MASK, lrclk);
+	else
+		snd_soc_update_bits(codec, base + 6,
+				    WM5100_AIF1TX_BCPF_MASK, lrclk);
+
+	i = (wl << WM5100_AIF1TX_WL_SHIFT) | fl;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_update_bits(codec, base + 9,
+				    WM5100_AIF1RX_WL_MASK |
+				    WM5100_AIF1RX_SLOT_LEN_MASK, i);
+	else
+		snd_soc_update_bits(codec, base + 8,
+				    WM5100_AIF1TX_WL_MASK |
+				    WM5100_AIF1TX_SLOT_LEN_MASK, i);
+
+	snd_soc_update_bits(codec, base + 4, WM5100_AIF1_RATE_MASK, sr);
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops wm5100_dai_ops = {
+	.set_fmt = wm5100_set_fmt,
+	.hw_params = wm5100_hw_params,
+};
+
+static int wm5100_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+			     int source, unsigned int freq, int dir)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int *rate_store;
+	int fval, audio_rate, ret, reg;
+
+	switch (clk_id) {
+	case WM5100_CLK_SYSCLK:
+		reg = WM5100_CLOCKING_3;
+		rate_store = &wm5100->sysclk;
+		break;
+	case WM5100_CLK_ASYNCCLK:
+		reg = WM5100_CLOCKING_7;
+		rate_store = &wm5100->asyncclk;
+		break;
+	case WM5100_CLK_32KHZ:
+		/* The 32kHz clock is slightly different to the others */
+		switch (source) {
+		case WM5100_CLKSRC_MCLK1:
+		case WM5100_CLKSRC_MCLK2:
+		case WM5100_CLKSRC_SYSCLK:
+			snd_soc_update_bits(codec, WM5100_CLOCKING_1,
+					    WM5100_CLK_32K_SRC_MASK,
+					    source);
+			break;
+		default:
+			return -EINVAL;
+		}
+		return 0;
+
+	case WM5100_CLK_AIF1:
+	case WM5100_CLK_AIF2:
+	case WM5100_CLK_AIF3:
+		/* Not real clocks, record which clock domain they're in */
+		switch (source) {
+		case WM5100_CLKSRC_SYSCLK:
+			wm5100->aif_async[clk_id - 1] = false;
+			break;
+		case WM5100_CLKSRC_ASYNCCLK:
+			wm5100->aif_async[clk_id - 1] = true;
+			break;
+		default:
+			dev_err(codec->dev, "Invalid source %d\n", source);
+			return -EINVAL;
+		}	
+		return 0;
+
+	case WM5100_CLK_OPCLK:
+		switch (freq) {
+		case 5644800:
+		case 6144000:
+			snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+					    WM5100_OPCLK_SEL_MASK, 0);
+			break;
+		case 11289600:
+		case 12288000:
+			snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+					    WM5100_OPCLK_SEL_MASK, 0);
+			break;
+		case 22579200:
+		case 24576000:
+			snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+					    WM5100_OPCLK_SEL_MASK, 0);
+			break;
+		default:
+			dev_err(codec->dev, "Unsupported OPCLK %dHz\n",
+				freq);
+			return -EINVAL;
+		}
+		return 0;
+
+	default:
+		dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+		return -EINVAL;
+	}
+
+	switch (source) {
+	case WM5100_CLKSRC_SYSCLK:
+	case WM5100_CLKSRC_ASYNCCLK:
+		dev_err(codec->dev, "Invalid source %d\n", source);
+		return -EINVAL;
+	}
+
+	switch (freq) {
+	case 5644800:
+	case 6144000:
+		fval = 0;
+		break;
+	case 11289600:
+	case 12288000:
+		fval = 1;
+		break;
+	case 22579200:
+	case 24576000:
+		fval = 2;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+		return -EINVAL;
+	}
+
+	switch (freq) {
+	case 5644800:
+	case 11289600:
+	case 22579200:
+		audio_rate = 44100;
+		break;
+
+	case 6144000:
+	case 12288000:
+	case 24576000:
+		audio_rate = 48000;
+		break;
+
+	default:
+		BUG();
+		audio_rate = 0;
+		break;
+	}
+
+	/* TODO: Check if MCLKs are in use and enable/disable pulls to
+	 * match.
+	 */
+
+	snd_soc_update_bits(codec, reg, WM5100_SYSCLK_FREQ_MASK |
+			    WM5100_SYSCLK_SRC_MASK,
+			    fval << WM5100_SYSCLK_FREQ_SHIFT | source);
+
+	/* If this is SYSCLK then configure the clock rate for the
+	 * internal audio functions to the natural sample rate for
+	 * this clock rate.
+	 */
+	if (clk_id == WM5100_CLK_SYSCLK) {
+		dev_dbg(codec->dev, "Setting primary audio rate to %dHz",
+			audio_rate);
+		if (0 && *rate_store)
+			wm5100_free_sr(codec, audio_rate);
+		ret = wm5100_alloc_sr(codec, audio_rate);
+		if (ret != 0)
+			dev_warn(codec->dev, "Primary audio slot is %d\n",
+				 ret);
+	}
+
+	*rate_store = freq;
+
+	return 0;
+}
+
+struct _fll_div {
+	u16 fll_fratio;
+	u16 fll_outdiv;
+	u16 fll_refclk_div;
+	u16 n;
+	u16 theta;
+	u16 lambda;
+};
+
+static struct {
+	unsigned int min;
+	unsigned int max;
+	u16 fll_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 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+		       unsigned int Fout)
+{
+	unsigned int target;
+	unsigned int div;
+	unsigned int fratio, gcd_fll;
+	int i;
+
+	/* Fref must be <=13.5MHz */
+	div = 1;
+	fll_div->fll_refclk_div = 0;
+	while ((Fref / div) > 13500000) {
+		div *= 2;
+		fll_div->fll_refclk_div++;
+
+		if (div > 8) {
+			pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+			       Fref);
+			return -EINVAL;
+		}
+	}
+
+	pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+	/* Apply the division for our remaining calculations */
+	Fref /= div;
+
+	/* Fvco should be 90-100MHz; don't check the upper bound */
+	div = 2;
+	while (Fout * div < 90000000) {
+		div++;
+		if (div > 64) {
+			pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+			       Fout);
+			return -EINVAL;
+		}
+	}
+	target = Fout * div;
+	fll_div->fll_outdiv = div - 1;
+
+	pr_debug("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) {
+			fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+			fratio = fll_fratios[i].ratio;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(fll_fratios)) {
+		pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+		return -EINVAL;
+	}
+
+	fll_div->n = target / (fratio * Fref);
+
+	if (target % Fref == 0) {
+		fll_div->theta = 0;
+		fll_div->lambda = 0;
+	} else {
+		gcd_fll = gcd(target, fratio * Fref);
+
+		fll_div->theta = (target - (fll_div->n * fratio * Fref))
+			/ gcd_fll;
+		fll_div->lambda = (fratio * Fref) / gcd_fll;
+	}
+
+	pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+		 fll_div->n, fll_div->theta, fll_div->lambda);
+	pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+		 fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+		 fll_div->fll_refclk_div);
+
+	return 0;
+}
+
+static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+			  unsigned int Fref, unsigned int Fout)
+{
+	struct i2c_client *i2c = to_i2c_client(codec->dev);
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	struct _fll_div factors;
+	struct wm5100_fll *fll;
+	int ret, base, lock, i, timeout;
+
+	switch (fll_id) {
+	case WM5100_FLL1:
+		fll = &wm5100->fll[0];
+		base = WM5100_FLL1_CONTROL_1 - 1;
+		lock = WM5100_FLL1_LOCK_STS;
+		break;
+	case WM5100_FLL2:
+		fll = &wm5100->fll[1];
+		base = WM5100_FLL2_CONTROL_2 - 1;
+		lock = WM5100_FLL2_LOCK_STS;
+		break;
+	default:
+		dev_err(codec->dev, "Unknown FLL %d\n",fll_id);
+		return -EINVAL;
+	}
+
+	if (!Fout) {
+		dev_dbg(codec->dev, "FLL%d disabled", fll_id);
+		fll->fout = 0;
+		snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
+		return 0;
+	}
+
+	switch (source) {
+	case WM5100_FLL_SRC_MCLK1:
+	case WM5100_FLL_SRC_MCLK2:
+	case WM5100_FLL_SRC_FLL1:
+	case WM5100_FLL_SRC_FLL2:
+	case WM5100_FLL_SRC_AIF1BCLK:
+	case WM5100_FLL_SRC_AIF2BCLK:
+	case WM5100_FLL_SRC_AIF3BCLK:
+		break;
+	default:
+		dev_err(codec->dev, "Invalid FLL source %d\n", source);
+		return -EINVAL;
+	}
+
+	ret = fll_factors(&factors, Fref, Fout);
+	if (ret < 0)
+		return ret;
+
+	/* Disable the FLL while we reconfigure */
+	snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
+
+	snd_soc_update_bits(codec, base + 2,
+			    WM5100_FLL1_OUTDIV_MASK | WM5100_FLL1_FRATIO_MASK,
+			    (factors.fll_outdiv << WM5100_FLL1_OUTDIV_SHIFT) |
+			    factors.fll_fratio);
+	snd_soc_update_bits(codec, base + 3, WM5100_FLL1_THETA_MASK,
+			    factors.theta);
+	snd_soc_update_bits(codec, base + 5, WM5100_FLL1_N_MASK, factors.n);
+	snd_soc_update_bits(codec, base + 6,
+			    WM5100_FLL1_REFCLK_DIV_MASK |
+			    WM5100_FLL1_REFCLK_SRC_MASK,
+			    (factors.fll_refclk_div
+			     << WM5100_FLL1_REFCLK_DIV_SHIFT) | source);
+	snd_soc_update_bits(codec, base + 7, WM5100_FLL1_LAMBDA_MASK,
+			    factors.lambda);
+
+	/* Clear any pending completions */
+	try_wait_for_completion(&fll->lock);
+
+	snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
+
+	if (i2c->irq)
+		timeout = 2;
+	else
+		timeout = 50;
+
+	/* Poll for the lock; will use interrupt when we can test */
+	for (i = 0; i < timeout; i++) {
+		if (i2c->irq) {
+			ret = wait_for_completion_timeout(&fll->lock,
+							  msecs_to_jiffies(25));
+			if (ret > 0)
+				break;
+		} else {
+			msleep(1);
+		}
+
+		ret = snd_soc_read(codec,
+				   WM5100_INTERRUPT_RAW_STATUS_3);
+		if (ret < 0) {
+			dev_err(codec->dev,
+				"Failed to read FLL status: %d\n",
+				ret);
+			continue;
+		}
+		if (ret & lock)
+			break;
+	}
+	if (i == timeout) {
+		dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
+		return -ETIMEDOUT;
+	}
+
+	fll->src = source;
+	fll->fref = Fref;
+	fll->fout = Fout;
+
+	dev_dbg(codec->dev, "FLL%d running %dHz->%dHz\n", fll_id,
+		Fref, Fout);
+
+	return 0;
+}
+
+/* Actually go much higher */
+#define WM5100_RATES SNDRV_PCM_RATE_8000_192000
+
+#define WM5100_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 wm5100_dai[] = {
+	{
+		.name = "wm5100-aif1",
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = WM5100_RATES,
+			.formats = WM5100_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF1 Capture",
+			 .channels_min = 2,
+			 .channels_max = 2,
+			 .rates = WM5100_RATES,
+			 .formats = WM5100_FORMATS,
+		 },
+		.ops = &wm5100_dai_ops,
+	},
+	{
+		.name = "wm5100-aif2",
+		.id = 1,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = WM5100_RATES,
+			.formats = WM5100_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF2 Capture",
+			 .channels_min = 2,
+			 .channels_max = 2,
+			 .rates = WM5100_RATES,
+			 .formats = WM5100_FORMATS,
+		 },
+		.ops = &wm5100_dai_ops,
+	},
+	{
+		.name = "wm5100-aif3",
+		.id = 2,
+		.playback = {
+			.stream_name = "AIF3 Playback",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = WM5100_RATES,
+			.formats = WM5100_FORMATS,
+		},
+		.capture = {
+			 .stream_name = "AIF3 Capture",
+			 .channels_min = 2,
+			 .channels_max = 2,
+			 .rates = WM5100_RATES,
+			 .formats = WM5100_FORMATS,
+		 },
+		.ops = &wm5100_dai_ops,
+	},
+};
+
+static int wm5100_dig_vu[] = {
+	WM5100_ADC_DIGITAL_VOLUME_1L,
+	WM5100_ADC_DIGITAL_VOLUME_1R,
+	WM5100_ADC_DIGITAL_VOLUME_2L,
+	WM5100_ADC_DIGITAL_VOLUME_2R,
+	WM5100_ADC_DIGITAL_VOLUME_3L,
+	WM5100_ADC_DIGITAL_VOLUME_3R,
+	WM5100_ADC_DIGITAL_VOLUME_4L,
+	WM5100_ADC_DIGITAL_VOLUME_4R,
+
+	WM5100_DAC_DIGITAL_VOLUME_1L,
+	WM5100_DAC_DIGITAL_VOLUME_1R,
+	WM5100_DAC_DIGITAL_VOLUME_2L,
+	WM5100_DAC_DIGITAL_VOLUME_2R,
+	WM5100_DAC_DIGITAL_VOLUME_3L,
+	WM5100_DAC_DIGITAL_VOLUME_3R,
+	WM5100_DAC_DIGITAL_VOLUME_4L,
+	WM5100_DAC_DIGITAL_VOLUME_4R,
+	WM5100_DAC_DIGITAL_VOLUME_5L,
+	WM5100_DAC_DIGITAL_VOLUME_5R,
+	WM5100_DAC_DIGITAL_VOLUME_6L,
+	WM5100_DAC_DIGITAL_VOLUME_6R,
+};
+
+static void wm5100_set_detect_mode(struct snd_soc_codec *codec, int the_mode)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
+
+	BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
+
+	gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
+	snd_soc_update_bits(codec, WM5100_ACCESSORY_DETECT_MODE_1,
+			    WM5100_ACCDET_BIAS_SRC_MASK |
+			    WM5100_ACCDET_SRC,
+			    (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
+			    mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
+	snd_soc_update_bits(codec, WM5100_MISC_CONTROL,
+			    WM5100_HPCOM_SRC,
+			    mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
+
+	wm5100->jack_mode = the_mode;
+
+	dev_dbg(codec->dev, "Set microphone polarity to %d\n",
+		wm5100->jack_mode);
+}
+
+static void wm5100_micd_irq(struct snd_soc_codec *codec)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int val;
+
+	val = snd_soc_read(codec, WM5100_MIC_DETECT_3);
+
+	dev_dbg(codec->dev, "Microphone event: %x\n", val);
+
+	if (!(val & WM5100_ACCDET_VALID)) {
+		dev_warn(codec->dev, "Microphone detection state invalid\n");
+		return;
+	}
+
+	/* No accessory, reset everything and report removal */
+	if (!(val & WM5100_ACCDET_STS)) {
+		dev_dbg(codec->dev, "Jack removal detected\n");
+		wm5100->jack_mic = false;
+		wm5100->jack_detecting = true;
+		snd_soc_jack_report(wm5100->jack, 0,
+				    SND_JACK_LINEOUT | SND_JACK_HEADSET |
+				    SND_JACK_BTN_0);
+
+		snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+				    WM5100_ACCDET_RATE_MASK,
+				    WM5100_ACCDET_RATE_MASK);
+		return;
+	}
+
+	/* If the measurement is very high we've got a microphone,
+	 * either we just detected one or if we already reported then
+	 * we've got a button release event.
+	 */
+	if (val & 0x400) {
+		if (wm5100->jack_detecting) {
+			dev_dbg(codec->dev, "Microphone detected\n");
+			wm5100->jack_mic = true;
+			snd_soc_jack_report(wm5100->jack,
+					    SND_JACK_HEADSET,
+					    SND_JACK_HEADSET | SND_JACK_BTN_0);
+
+			/* Increase poll rate to give better responsiveness
+			 * for buttons */
+			snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+					    WM5100_ACCDET_RATE_MASK,
+					    5 << WM5100_ACCDET_RATE_SHIFT);
+		} else {
+			dev_dbg(codec->dev, "Mic button up\n");
+			snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0);
+		}
+
+		return;
+	}
+
+	/* If we detected a lower impedence during initial startup
+	 * then we probably have the wrong polarity, flip it.  Don't
+	 * do this for the lowest impedences to speed up detection of
+	 * plain headphones.
+	 */
+	if (wm5100->jack_detecting && (val & 0x3f8)) {
+		wm5100_set_detect_mode(codec, !wm5100->jack_mode);
+
+		return;
+	}
+
+	/* Don't distinguish between buttons, just report any low
+	 * impedence as BTN_0.
+	 */
+	if (val & 0x3fc) {
+		if (wm5100->jack_mic) {
+			dev_dbg(codec->dev, "Mic button detected\n");
+			snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
+					    SND_JACK_BTN_0);
+		} else if (wm5100->jack_detecting) {
+			dev_dbg(codec->dev, "Headphone detected\n");
+			snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
+					    SND_JACK_HEADPHONE);
+
+			/* Increase the detection rate a bit for
+			 * responsiveness.
+			 */
+			snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+					    WM5100_ACCDET_RATE_MASK,
+					    7 << WM5100_ACCDET_RATE_SHIFT);
+		}
+	}
+}
+
+int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+
+	if (jack) {
+		wm5100->jack = jack;
+		wm5100->jack_detecting = true;
+
+		wm5100_set_detect_mode(codec, 0);
+
+		/* Slowest detection rate, gives debounce for initial
+		 * detection */
+		snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+				    WM5100_ACCDET_BIAS_STARTTIME_MASK |
+				    WM5100_ACCDET_RATE_MASK,
+				    (7 << WM5100_ACCDET_BIAS_STARTTIME_SHIFT) |
+				    WM5100_ACCDET_RATE_MASK);
+
+		/* We need the charge pump to power MICBIAS */
+		snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2");
+		snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
+		snd_soc_dapm_sync(&codec->dapm);
+
+		/* We start off just enabling microphone detection - even a
+		 * plain headphone will trigger detection.
+		 */
+		snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+				    WM5100_ACCDET_ENA, WM5100_ACCDET_ENA);
+
+		snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK,
+				    WM5100_IM_ACCDET_EINT, 0);
+	} else {
+		snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK,
+				    WM5100_IM_HPDET_EINT |
+				    WM5100_IM_ACCDET_EINT,
+				    WM5100_IM_HPDET_EINT |
+				    WM5100_IM_ACCDET_EINT);
+		snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+				    WM5100_ACCDET_ENA, 0);
+		wm5100->jack = NULL;
+	}
+
+	return 0;
+}
+
+static irqreturn_t wm5100_irq(int irq, void *data)
+{
+	struct snd_soc_codec *codec = data;
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	irqreturn_t status = IRQ_NONE;
+	int irq_val;
+
+	irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3);
+	if (irq_val < 0) {
+		dev_err(codec->dev, "Failed to read IRQ status 3: %d\n",
+			irq_val);
+		irq_val = 0;
+	}
+	irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK);
+
+	snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val);
+
+	if (irq_val)
+		status = IRQ_HANDLED;
+
+	wm5100_log_status3(codec, irq_val);
+
+	if (irq_val & WM5100_FLL1_LOCK_EINT) {
+		dev_dbg(codec->dev, "FLL1 locked\n");
+		complete(&wm5100->fll[0].lock);
+	}
+	if (irq_val & WM5100_FLL2_LOCK_EINT) {
+		dev_dbg(codec->dev, "FLL2 locked\n");
+		complete(&wm5100->fll[1].lock);
+	}
+
+	if (irq_val & WM5100_ACCDET_EINT)
+		wm5100_micd_irq(codec);
+
+	irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4);
+	if (irq_val < 0) {
+		dev_err(codec->dev, "Failed to read IRQ status 4: %d\n",
+			irq_val);
+		irq_val = 0;
+	}
+	irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK);
+
+	if (irq_val)
+		status = IRQ_HANDLED;
+
+	snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val);
+
+	wm5100_log_status4(codec, irq_val);
+
+	return status;
+}
+
+static irqreturn_t wm5100_edge_irq(int irq, void *data)
+{
+	irqreturn_t ret = IRQ_NONE;
+	irqreturn_t val;
+
+	do {
+		val = wm5100_irq(irq, data);
+		if (val != IRQ_NONE)
+			ret = val;
+	} while (val != IRQ_NONE);
+
+	return ret;
+}
+
+#ifdef CONFIG_GPIOLIB
+static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip)
+{
+	return container_of(chip, struct wm5100_priv, gpio_chip);
+}
+
+static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+	struct snd_soc_codec *codec = wm5100->codec;
+
+	snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+			    WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT);
+}
+
+static int wm5100_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+	struct snd_soc_codec *codec = wm5100->codec;
+	int val;
+
+	val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT);
+
+	return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+				   WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
+				   WM5100_GP1_LVL, val);
+}
+
+static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+	struct snd_soc_codec *codec = wm5100->codec;
+	int ret;
+
+	ret = snd_soc_read(codec, WM5100_GPIO_CTRL_1 + offset);
+	if (ret < 0)
+		return ret;
+
+	return (ret & WM5100_GP1_LVL) != 0;
+}
+
+static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+	struct snd_soc_codec *codec = wm5100->codec;
+
+	return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+				   WM5100_GP1_FN_MASK | WM5100_GP1_DIR,
+				   (1 << WM5100_GP1_FN_SHIFT) |
+				   (1 << WM5100_GP1_DIR_SHIFT));
+}
+
+static struct gpio_chip wm5100_template_chip = {
+	.label			= "wm5100",
+	.owner			= THIS_MODULE,
+	.direction_output	= wm5100_gpio_direction_out,
+	.set			= wm5100_gpio_set,
+	.direction_input	= wm5100_gpio_direction_in,
+	.get			= wm5100_gpio_get,
+	.can_sleep		= 1,
+};
+
+static void wm5100_init_gpio(struct snd_soc_codec *codec)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	wm5100->gpio_chip = wm5100_template_chip;
+	wm5100->gpio_chip.ngpio = 6;
+	wm5100->gpio_chip.dev = codec->dev;
+
+	if (wm5100->pdata.gpio_base)
+		wm5100->gpio_chip.base = wm5100->pdata.gpio_base;
+	else
+		wm5100->gpio_chip.base = -1;
+
+	ret = gpiochip_add(&wm5100->gpio_chip);
+	if (ret != 0)
+		dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+}
+
+static void wm5100_free_gpio(struct snd_soc_codec *codec)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = gpiochip_remove(&wm5100->gpio_chip);
+	if (ret != 0)
+		dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+}
+#else
+static void wm5100_init_gpio(struct snd_soc_codec *codec)
+{
+}
+
+static void wm5100_free_gpio(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+static int wm5100_probe(struct snd_soc_codec *codec)
+{
+	struct i2c_client *i2c = to_i2c_client(codec->dev);
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	int ret, i, irq_flags;
+
+	wm5100->codec = codec;
+
+	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
+		wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
+
+	ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies),
+				 wm5100->core_supplies);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to request core supplies: %d\n",
+			ret);
+		return ret;
+	}
+
+	wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD");
+	if (IS_ERR(wm5100->cpvdd)) {
+		ret = PTR_ERR(wm5100->cpvdd);
+		dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
+		goto err_core;
+	}
+
+	wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2");
+	if (IS_ERR(wm5100->dbvdd2)) {
+		ret = PTR_ERR(wm5100->dbvdd2);
+		dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
+		goto err_cpvdd;
+	}
+
+	wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3");
+	if (IS_ERR(wm5100->dbvdd3)) {
+		ret = PTR_ERR(wm5100->dbvdd3);
+		dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
+		goto err_dbvdd2;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+				    wm5100->core_supplies);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to enable core supplies: %d\n",
+			ret);
+		goto err_dbvdd3;
+	}
+
+	if (wm5100->pdata.ldo_ena) {
+		ret = gpio_request_one(wm5100->pdata.ldo_ena,
+				       GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA");
+		if (ret < 0) {
+			dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+				wm5100->pdata.ldo_ena, ret);
+			goto err_enable;
+		}
+		msleep(2);
+	}
+
+	if (wm5100->pdata.reset) {
+		ret = gpio_request_one(wm5100->pdata.reset,
+				       GPIOF_OUT_INIT_HIGH, "WM5100 /RESET");
+		if (ret < 0) {
+			dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+				wm5100->pdata.reset, ret);
+			goto err_ldo;
+		}
+	}
+
+	ret = snd_soc_read(codec, WM5100_SOFTWARE_RESET);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to read ID register\n");
+		goto err_reset;
+	}
+	switch (ret) {
+	case 0x8997:
+	case 0x5100:
+		break;
+
+	default:
+		dev_err(codec->dev, "Device is not a WM5100, ID is %x\n", ret);
+		ret = -EINVAL;
+		goto err_reset;
+	}
+
+	ret = snd_soc_read(codec, WM5100_DEVICE_REVISION);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to read revision register\n");
+		goto err_reset;
+	}
+	wm5100->rev = ret & WM5100_DEVICE_REVISION_MASK;
+
+	dev_info(codec->dev, "revision %c\n", wm5100->rev + 'A');
+
+	ret = wm5100_reset(codec);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to issue reset\n");
+		goto err_reset;
+	}
+
+	codec->cache_only = true;
+
+	wm5100_init_gpio(codec);
+
+	for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
+		snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
+				    WM5100_OUT_VU);
+
+	for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
+		snd_soc_update_bits(codec, WM5100_IN1L_CONTROL,
+				    WM5100_IN1_MODE_MASK |
+				    WM5100_IN1_DMIC_SUP_MASK,
+				    (wm5100->pdata.in_mode[i] <<
+				     WM5100_IN1_MODE_SHIFT) |
+				    (wm5100->pdata.dmic_sup[i] <<
+				     WM5100_IN1_DMIC_SUP_SHIFT));
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
+		if (!wm5100->pdata.gpio_defaults[i])
+			continue;
+
+		snd_soc_write(codec, WM5100_GPIO_CTRL_1 + i,
+			      wm5100->pdata.gpio_defaults[i]);
+	}
+
+	/* Don't debounce interrupts to support use of SYSCLK only */
+	snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_1, 0);
+	snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_2, 0);
+
+	/* TODO: check if we're symmetric */
+
+	if (i2c->irq) {
+		if (wm5100->pdata.irq_flags)
+			irq_flags = wm5100->pdata.irq_flags;
+		else
+			irq_flags = IRQF_TRIGGER_LOW;
+
+		irq_flags |= IRQF_ONESHOT;
+
+		if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+			ret = request_threaded_irq(i2c->irq, NULL,
+						   wm5100_edge_irq,
+						   irq_flags, "wm5100", codec);
+		else
+			ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
+						   irq_flags, "wm5100", codec);
+
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
+				i2c->irq, ret);
+		} else {
+			/* Enable default interrupts */
+			snd_soc_update_bits(codec,
+					    WM5100_INTERRUPT_STATUS_3_MASK,
+					    WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
+					    WM5100_IM_SPK_SHUTDOWN_EINT |
+					    WM5100_IM_ASRC2_LOCK_EINT |
+					    WM5100_IM_ASRC1_LOCK_EINT |
+					    WM5100_IM_FLL2_LOCK_EINT |
+					    WM5100_IM_FLL1_LOCK_EINT |
+					    WM5100_CLKGEN_ERR_EINT |
+					    WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
+
+			snd_soc_update_bits(codec,
+					    WM5100_INTERRUPT_STATUS_4_MASK,
+					    WM5100_AIF3_ERR_EINT |
+					    WM5100_AIF2_ERR_EINT |
+					    WM5100_AIF1_ERR_EINT |
+					    WM5100_CTRLIF_ERR_EINT |
+					    WM5100_ISRC2_UNDERCLOCKED_EINT |
+					    WM5100_ISRC1_UNDERCLOCKED_EINT |
+					    WM5100_FX_UNDERCLOCKED_EINT |
+					    WM5100_AIF3_UNDERCLOCKED_EINT |
+					    WM5100_AIF2_UNDERCLOCKED_EINT |
+					    WM5100_AIF1_UNDERCLOCKED_EINT |
+					    WM5100_ASRC_UNDERCLOCKED_EINT |
+					    WM5100_DAC_UNDERCLOCKED_EINT |
+					    WM5100_ADC_UNDERCLOCKED_EINT |
+					    WM5100_MIXER_UNDERCLOCKED_EINT, 0);
+		}
+	} else {
+		snd_soc_dapm_new_controls(&codec->dapm,
+					  wm5100_dapm_widgets_noirq,
+					  ARRAY_SIZE(wm5100_dapm_widgets_noirq));
+	}
+
+	if (wm5100->pdata.hp_pol) {
+		ret = gpio_request_one(wm5100->pdata.hp_pol,
+				       GPIOF_OUT_INIT_HIGH, "WM5100 HP_POL");
+		if (ret < 0) {
+			dev_err(&i2c->dev, "Failed to request HP_POL %d: %d\n",
+				wm5100->pdata.hp_pol, ret);
+			goto err_gpio;
+		}
+	}
+
+	/* We'll get woken up again when the system has something useful
+	 * for us to do.
+	 */
+	if (wm5100->pdata.ldo_ena)
+		gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+	regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+			       wm5100->core_supplies);
+
+	return 0;
+
+err_gpio:
+	if (i2c->irq)
+		free_irq(i2c->irq, codec);
+	wm5100_free_gpio(codec);
+err_reset:
+	if (wm5100->pdata.reset) {
+		gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+		gpio_free(wm5100->pdata.reset);
+	}
+err_ldo:
+	if (wm5100->pdata.ldo_ena) {
+		gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+		gpio_free(wm5100->pdata.ldo_ena);
+	}
+err_enable:
+	regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+			       wm5100->core_supplies);
+err_dbvdd3:
+	regulator_put(wm5100->dbvdd3);
+err_dbvdd2:
+	regulator_put(wm5100->dbvdd2);
+err_cpvdd:
+	regulator_put(wm5100->cpvdd);
+err_core:
+	regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
+			    wm5100->core_supplies);
+
+	return ret;
+}
+
+static int wm5100_remove(struct snd_soc_codec *codec)
+{
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	struct i2c_client *i2c = to_i2c_client(codec->dev);
+
+	wm5100_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	if (wm5100->pdata.hp_pol) {
+		gpio_free(wm5100->pdata.hp_pol);
+	}
+	if (i2c->irq)
+		free_irq(i2c->irq, codec);
+	wm5100_free_gpio(codec);
+	if (wm5100->pdata.reset) {
+		gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+		gpio_free(wm5100->pdata.reset);
+	}
+	if (wm5100->pdata.ldo_ena) {
+		gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+		gpio_free(wm5100->pdata.ldo_ena);
+	}
+	regulator_put(wm5100->dbvdd3);
+	regulator_put(wm5100->dbvdd2);
+	regulator_put(wm5100->cpvdd);
+	regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
+			    wm5100->core_supplies);
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
+	.probe =	wm5100_probe,
+	.remove =	wm5100_remove,
+
+	.set_sysclk = wm5100_set_sysclk,
+	.set_pll = wm5100_set_fll,
+	.set_bias_level = wm5100_set_bias_level,
+	.idle_bias_off = 1,
+
+	.seq_notifier = wm5100_seq_notifier,
+	.controls = wm5100_snd_controls,
+	.num_controls = ARRAY_SIZE(wm5100_snd_controls),
+	.dapm_widgets = wm5100_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets),
+	.dapm_routes = wm5100_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes),
+
+	.reg_cache_size = ARRAY_SIZE(wm5100_reg_defaults),
+	.reg_word_size = sizeof(u16),
+	.compress_type = SND_SOC_RBTREE_COMPRESSION,
+	.reg_cache_default = wm5100_reg_defaults,
+
+	.volatile_register = wm5100_volatile_register,
+	.readable_register = wm5100_readable_register,
+};
+
+static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
+	struct wm5100_priv *wm5100;
+	int ret, i;
+
+	wm5100 = kzalloc(sizeof(struct wm5100_priv), GFP_KERNEL);
+	if (wm5100 == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(wm5100->fll); i++)
+		init_completion(&wm5100->fll[i].lock);
+
+	if (pdata)
+		wm5100->pdata = *pdata;
+
+	i2c_set_clientdata(i2c, wm5100);
+
+	ret = snd_soc_register_codec(&i2c->dev,
+				     &soc_codec_dev_wm5100, wm5100_dai,
+				     ARRAY_SIZE(wm5100_dai));
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret);
+		kfree(wm5100);
+	}
+
+	return ret;
+}
+
+static __devexit int wm5100_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id wm5100_i2c_id[] = {
+	{ "wm5100", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id);
+
+static struct i2c_driver wm5100_i2c_driver = {
+	.driver = {
+		.name = "wm5100",
+		.owner = THIS_MODULE,
+	},
+	.probe =    wm5100_i2c_probe,
+	.remove =   __devexit_p(wm5100_i2c_remove),
+	.id_table = wm5100_i2c_id,
+};
+
+static int __init wm5100_modinit(void)
+{
+	return i2c_add_driver(&wm5100_i2c_driver);
+}
+module_init(wm5100_modinit);
+
+static void __exit wm5100_exit(void)
+{
+	i2c_del_driver(&wm5100_i2c_driver);
+}
+module_exit(wm5100_exit);
+
+MODULE_DESCRIPTION("ASoC WM5100 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm5100.h b/sound/soc/codecs/wm5100.h
new file mode 100644
index 000000000000..970759636bdc
--- /dev/null
+++ b/sound/soc/codecs/wm5100.h
@@ -0,0 +1,5155 @@
+/*
+ * wm5100.h  --  WM5100 ALSA SoC Audio driver
+ *
+ * Copyright 2011 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 WM5100_ASOC_H
+#define WM5100_ASOC_H
+
+#include <sound/soc.h>
+
+int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
+
+#define WM5100_CLK_AIF1     1
+#define WM5100_CLK_AIF2     2
+#define WM5100_CLK_AIF3     3
+#define WM5100_CLK_SYSCLK   4
+#define WM5100_CLK_ASYNCCLK 5
+#define WM5100_CLK_32KHZ    6
+#define WM5100_CLK_OPCLK    7
+
+#define WM5100_CLKSRC_MCLK1    0
+#define WM5100_CLKSRC_MCLK2    1
+#define WM5100_CLKSRC_SYSCLK   2
+#define WM5100_CLKSRC_FLL1     4
+#define WM5100_CLKSRC_FLL2     5
+#define WM5100_CLKSRC_AIF1BCLK 8
+#define WM5100_CLKSRC_AIF2BCLK 9
+#define WM5100_CLKSRC_AIF3BCLK 10
+#define WM5100_CLKSRC_ASYNCCLK 0x100
+
+#define WM5100_FLL1 1
+#define WM5100_FLL2 2
+
+#define WM5100_FLL_SRC_MCLK1    0x0
+#define WM5100_FLL_SRC_MCLK2    0x1
+#define WM5100_FLL_SRC_FLL1     0x4
+#define WM5100_FLL_SRC_FLL2     0x5
+#define WM5100_FLL_SRC_AIF1BCLK 0x8
+#define WM5100_FLL_SRC_AIF2BCLK 0x9
+#define WM5100_FLL_SRC_AIF3BCLK 0xa
+
+/*
+ * Register values.
+ */
+#define WM5100_SOFTWARE_RESET                   0x00
+#define WM5100_DEVICE_REVISION                  0x01
+#define WM5100_CTRL_IF_1                        0x10
+#define WM5100_TONE_GENERATOR_1                 0x20
+#define WM5100_PWM_DRIVE_1                      0x30
+#define WM5100_PWM_DRIVE_2                      0x31
+#define WM5100_PWM_DRIVE_3                      0x32
+#define WM5100_CLOCKING_1                       0x100
+#define WM5100_CLOCKING_3                       0x101
+#define WM5100_CLOCKING_4                       0x102
+#define WM5100_CLOCKING_5                       0x103
+#define WM5100_CLOCKING_6                       0x104
+#define WM5100_CLOCKING_7                       0x107
+#define WM5100_CLOCKING_8                       0x108
+#define WM5100_ASRC_ENABLE                      0x120
+#define WM5100_ASRC_STATUS                      0x121
+#define WM5100_ASRC_RATE1                       0x122
+#define WM5100_ISRC_1_CTRL_1                    0x141
+#define WM5100_ISRC_1_CTRL_2                    0x142
+#define WM5100_ISRC_2_CTRL1                     0x143
+#define WM5100_ISRC_2_CTRL_2                    0x144
+#define WM5100_FLL1_CONTROL_1                   0x182
+#define WM5100_FLL1_CONTROL_2                   0x183
+#define WM5100_FLL1_CONTROL_3                   0x184
+#define WM5100_FLL1_CONTROL_5                   0x186
+#define WM5100_FLL1_CONTROL_6                   0x187
+#define WM5100_FLL1_EFS_1                       0x188
+#define WM5100_FLL2_CONTROL_1                   0x1A2
+#define WM5100_FLL2_CONTROL_2                   0x1A3
+#define WM5100_FLL2_CONTROL_3                   0x1A4
+#define WM5100_FLL2_CONTROL_5                   0x1A6
+#define WM5100_FLL2_CONTROL_6                   0x1A7
+#define WM5100_FLL2_EFS_1                       0x1A8
+#define WM5100_MIC_CHARGE_PUMP_1                0x200
+#define WM5100_MIC_CHARGE_PUMP_2                0x201
+#define WM5100_HP_CHARGE_PUMP_1                 0x202
+#define WM5100_LDO1_CONTROL                     0x211
+#define WM5100_MIC_BIAS_CTRL_1                  0x215
+#define WM5100_MIC_BIAS_CTRL_2                  0x216
+#define WM5100_MIC_BIAS_CTRL_3                  0x217
+#define WM5100_ACCESSORY_DETECT_MODE_1          0x280
+#define WM5100_HEADPHONE_DETECT_1               0x288
+#define WM5100_HEADPHONE_DETECT_2               0x289
+#define WM5100_MIC_DETECT_1                     0x290
+#define WM5100_MIC_DETECT_2                     0x291
+#define WM5100_MIC_DETECT_3                     0x292
+#define WM5100_MISC_CONTROL                     0x2BB
+#define WM5100_INPUT_ENABLES                    0x301
+#define WM5100_INPUT_ENABLES_STATUS             0x302
+#define WM5100_IN1L_CONTROL                     0x310
+#define WM5100_IN1R_CONTROL                     0x311
+#define WM5100_IN2L_CONTROL                     0x312
+#define WM5100_IN2R_CONTROL                     0x313
+#define WM5100_IN3L_CONTROL                     0x314
+#define WM5100_IN3R_CONTROL                     0x315
+#define WM5100_IN4L_CONTROL                     0x316
+#define WM5100_IN4R_CONTROL                     0x317
+#define WM5100_RXANC_SRC                        0x318
+#define WM5100_INPUT_VOLUME_RAMP                0x319
+#define WM5100_ADC_DIGITAL_VOLUME_1L            0x320
+#define WM5100_ADC_DIGITAL_VOLUME_1R            0x321
+#define WM5100_ADC_DIGITAL_VOLUME_2L            0x322
+#define WM5100_ADC_DIGITAL_VOLUME_2R            0x323
+#define WM5100_ADC_DIGITAL_VOLUME_3L            0x324
+#define WM5100_ADC_DIGITAL_VOLUME_3R            0x325
+#define WM5100_ADC_DIGITAL_VOLUME_4L            0x326
+#define WM5100_ADC_DIGITAL_VOLUME_4R            0x327
+#define WM5100_OUTPUT_ENABLES_2                 0x401
+#define WM5100_OUTPUT_STATUS_1                  0x402
+#define WM5100_OUTPUT_STATUS_2                  0x403
+#define WM5100_CHANNEL_ENABLES_1                0x408
+#define WM5100_OUT_VOLUME_1L                    0x410
+#define WM5100_OUT_VOLUME_1R                    0x411
+#define WM5100_DAC_VOLUME_LIMIT_1L              0x412
+#define WM5100_DAC_VOLUME_LIMIT_1R              0x413
+#define WM5100_OUT_VOLUME_2L                    0x414
+#define WM5100_OUT_VOLUME_2R                    0x415
+#define WM5100_DAC_VOLUME_LIMIT_2L              0x416
+#define WM5100_DAC_VOLUME_LIMIT_2R              0x417
+#define WM5100_OUT_VOLUME_3L                    0x418
+#define WM5100_OUT_VOLUME_3R                    0x419
+#define WM5100_DAC_VOLUME_LIMIT_3L              0x41A
+#define WM5100_DAC_VOLUME_LIMIT_3R              0x41B
+#define WM5100_OUT_VOLUME_4L                    0x41C
+#define WM5100_OUT_VOLUME_4R                    0x41D
+#define WM5100_DAC_VOLUME_LIMIT_5L              0x41E
+#define WM5100_DAC_VOLUME_LIMIT_5R              0x41F
+#define WM5100_DAC_VOLUME_LIMIT_6L              0x420
+#define WM5100_DAC_VOLUME_LIMIT_6R              0x421
+#define WM5100_DAC_AEC_CONTROL_1                0x440
+#define WM5100_OUTPUT_VOLUME_RAMP               0x441
+#define WM5100_DAC_DIGITAL_VOLUME_1L            0x480
+#define WM5100_DAC_DIGITAL_VOLUME_1R            0x481
+#define WM5100_DAC_DIGITAL_VOLUME_2L            0x482
+#define WM5100_DAC_DIGITAL_VOLUME_2R            0x483
+#define WM5100_DAC_DIGITAL_VOLUME_3L            0x484
+#define WM5100_DAC_DIGITAL_VOLUME_3R            0x485
+#define WM5100_DAC_DIGITAL_VOLUME_4L            0x486
+#define WM5100_DAC_DIGITAL_VOLUME_4R            0x487
+#define WM5100_DAC_DIGITAL_VOLUME_5L            0x488
+#define WM5100_DAC_DIGITAL_VOLUME_5R            0x489
+#define WM5100_DAC_DIGITAL_VOLUME_6L            0x48A
+#define WM5100_DAC_DIGITAL_VOLUME_6R            0x48B
+#define WM5100_PDM_SPK1_CTRL_1                  0x4C0
+#define WM5100_PDM_SPK1_CTRL_2                  0x4C1
+#define WM5100_PDM_SPK2_CTRL_1                  0x4C2
+#define WM5100_PDM_SPK2_CTRL_2                  0x4C3
+#define WM5100_AUDIO_IF_1_1                     0x500
+#define WM5100_AUDIO_IF_1_2                     0x501
+#define WM5100_AUDIO_IF_1_3                     0x502
+#define WM5100_AUDIO_IF_1_4                     0x503
+#define WM5100_AUDIO_IF_1_5                     0x504
+#define WM5100_AUDIO_IF_1_6                     0x505
+#define WM5100_AUDIO_IF_1_7                     0x506
+#define WM5100_AUDIO_IF_1_8                     0x507
+#define WM5100_AUDIO_IF_1_9                     0x508
+#define WM5100_AUDIO_IF_1_10                    0x509
+#define WM5100_AUDIO_IF_1_11                    0x50A
+#define WM5100_AUDIO_IF_1_12                    0x50B
+#define WM5100_AUDIO_IF_1_13                    0x50C
+#define WM5100_AUDIO_IF_1_14                    0x50D
+#define WM5100_AUDIO_IF_1_15                    0x50E
+#define WM5100_AUDIO_IF_1_16                    0x50F
+#define WM5100_AUDIO_IF_1_17                    0x510
+#define WM5100_AUDIO_IF_1_18                    0x511
+#define WM5100_AUDIO_IF_1_19                    0x512
+#define WM5100_AUDIO_IF_1_20                    0x513
+#define WM5100_AUDIO_IF_1_21                    0x514
+#define WM5100_AUDIO_IF_1_22                    0x515
+#define WM5100_AUDIO_IF_1_23                    0x516
+#define WM5100_AUDIO_IF_1_24                    0x517
+#define WM5100_AUDIO_IF_1_25                    0x518
+#define WM5100_AUDIO_IF_1_26                    0x519
+#define WM5100_AUDIO_IF_1_27                    0x51A
+#define WM5100_AUDIO_IF_2_1                     0x540
+#define WM5100_AUDIO_IF_2_2                     0x541
+#define WM5100_AUDIO_IF_2_3                     0x542
+#define WM5100_AUDIO_IF_2_4                     0x543
+#define WM5100_AUDIO_IF_2_5                     0x544
+#define WM5100_AUDIO_IF_2_6                     0x545
+#define WM5100_AUDIO_IF_2_7                     0x546
+#define WM5100_AUDIO_IF_2_8                     0x547
+#define WM5100_AUDIO_IF_2_9                     0x548
+#define WM5100_AUDIO_IF_2_10                    0x549
+#define WM5100_AUDIO_IF_2_11                    0x54A
+#define WM5100_AUDIO_IF_2_18                    0x551
+#define WM5100_AUDIO_IF_2_19                    0x552
+#define WM5100_AUDIO_IF_2_26                    0x559
+#define WM5100_AUDIO_IF_2_27                    0x55A
+#define WM5100_AUDIO_IF_3_1                     0x580
+#define WM5100_AUDIO_IF_3_2                     0x581
+#define WM5100_AUDIO_IF_3_3                     0x582
+#define WM5100_AUDIO_IF_3_4                     0x583
+#define WM5100_AUDIO_IF_3_5                     0x584
+#define WM5100_AUDIO_IF_3_6                     0x585
+#define WM5100_AUDIO_IF_3_7                     0x586
+#define WM5100_AUDIO_IF_3_8                     0x587
+#define WM5100_AUDIO_IF_3_9                     0x588
+#define WM5100_AUDIO_IF_3_10                    0x589
+#define WM5100_AUDIO_IF_3_11                    0x58A
+#define WM5100_AUDIO_IF_3_18                    0x591
+#define WM5100_AUDIO_IF_3_19                    0x592
+#define WM5100_AUDIO_IF_3_26                    0x599
+#define WM5100_AUDIO_IF_3_27                    0x59A
+#define WM5100_PWM1MIX_INPUT_1_SOURCE           0x640
+#define WM5100_PWM1MIX_INPUT_1_VOLUME           0x641
+#define WM5100_PWM1MIX_INPUT_2_SOURCE           0x642
+#define WM5100_PWM1MIX_INPUT_2_VOLUME           0x643
+#define WM5100_PWM1MIX_INPUT_3_SOURCE           0x644
+#define WM5100_PWM1MIX_INPUT_3_VOLUME           0x645
+#define WM5100_PWM1MIX_INPUT_4_SOURCE           0x646
+#define WM5100_PWM1MIX_INPUT_4_VOLUME           0x647
+#define WM5100_PWM2MIX_INPUT_1_SOURCE           0x648
+#define WM5100_PWM2MIX_INPUT_1_VOLUME           0x649
+#define WM5100_PWM2MIX_INPUT_2_SOURCE           0x64A
+#define WM5100_PWM2MIX_INPUT_2_VOLUME           0x64B
+#define WM5100_PWM2MIX_INPUT_3_SOURCE           0x64C
+#define WM5100_PWM2MIX_INPUT_3_VOLUME           0x64D
+#define WM5100_PWM2MIX_INPUT_4_SOURCE           0x64E
+#define WM5100_PWM2MIX_INPUT_4_VOLUME           0x64F
+#define WM5100_OUT1LMIX_INPUT_1_SOURCE          0x680
+#define WM5100_OUT1LMIX_INPUT_1_VOLUME          0x681
+#define WM5100_OUT1LMIX_INPUT_2_SOURCE          0x682
+#define WM5100_OUT1LMIX_INPUT_2_VOLUME          0x683
+#define WM5100_OUT1LMIX_INPUT_3_SOURCE          0x684
+#define WM5100_OUT1LMIX_INPUT_3_VOLUME          0x685
+#define WM5100_OUT1LMIX_INPUT_4_SOURCE          0x686
+#define WM5100_OUT1LMIX_INPUT_4_VOLUME          0x687
+#define WM5100_OUT1RMIX_INPUT_1_SOURCE          0x688
+#define WM5100_OUT1RMIX_INPUT_1_VOLUME          0x689
+#define WM5100_OUT1RMIX_INPUT_2_SOURCE          0x68A
+#define WM5100_OUT1RMIX_INPUT_2_VOLUME          0x68B
+#define WM5100_OUT1RMIX_INPUT_3_SOURCE          0x68C
+#define WM5100_OUT1RMIX_INPUT_3_VOLUME          0x68D
+#define WM5100_OUT1RMIX_INPUT_4_SOURCE          0x68E
+#define WM5100_OUT1RMIX_INPUT_4_VOLUME          0x68F
+#define WM5100_OUT2LMIX_INPUT_1_SOURCE          0x690
+#define WM5100_OUT2LMIX_INPUT_1_VOLUME          0x691
+#define WM5100_OUT2LMIX_INPUT_2_SOURCE          0x692
+#define WM5100_OUT2LMIX_INPUT_2_VOLUME          0x693
+#define WM5100_OUT2LMIX_INPUT_3_SOURCE          0x694
+#define WM5100_OUT2LMIX_INPUT_3_VOLUME          0x695
+#define WM5100_OUT2LMIX_INPUT_4_SOURCE          0x696
+#define WM5100_OUT2LMIX_INPUT_4_VOLUME          0x697
+#define WM5100_OUT2RMIX_INPUT_1_SOURCE          0x698
+#define WM5100_OUT2RMIX_INPUT_1_VOLUME          0x699
+#define WM5100_OUT2RMIX_INPUT_2_SOURCE          0x69A
+#define WM5100_OUT2RMIX_INPUT_2_VOLUME          0x69B
+#define WM5100_OUT2RMIX_INPUT_3_SOURCE          0x69C
+#define WM5100_OUT2RMIX_INPUT_3_VOLUME          0x69D
+#define WM5100_OUT2RMIX_INPUT_4_SOURCE          0x69E
+#define WM5100_OUT2RMIX_INPUT_4_VOLUME          0x69F
+#define WM5100_OUT3LMIX_INPUT_1_SOURCE          0x6A0
+#define WM5100_OUT3LMIX_INPUT_1_VOLUME          0x6A1
+#define WM5100_OUT3LMIX_INPUT_2_SOURCE          0x6A2
+#define WM5100_OUT3LMIX_INPUT_2_VOLUME          0x6A3
+#define WM5100_OUT3LMIX_INPUT_3_SOURCE          0x6A4
+#define WM5100_OUT3LMIX_INPUT_3_VOLUME          0x6A5
+#define WM5100_OUT3LMIX_INPUT_4_SOURCE          0x6A6
+#define WM5100_OUT3LMIX_INPUT_4_VOLUME          0x6A7
+#define WM5100_OUT3RMIX_INPUT_1_SOURCE          0x6A8
+#define WM5100_OUT3RMIX_INPUT_1_VOLUME          0x6A9
+#define WM5100_OUT3RMIX_INPUT_2_SOURCE          0x6AA
+#define WM5100_OUT3RMIX_INPUT_2_VOLUME          0x6AB
+#define WM5100_OUT3RMIX_INPUT_3_SOURCE          0x6AC
+#define WM5100_OUT3RMIX_INPUT_3_VOLUME          0x6AD
+#define WM5100_OUT3RMIX_INPUT_4_SOURCE          0x6AE
+#define WM5100_OUT3RMIX_INPUT_4_VOLUME          0x6AF
+#define WM5100_OUT4LMIX_INPUT_1_SOURCE          0x6B0
+#define WM5100_OUT4LMIX_INPUT_1_VOLUME          0x6B1
+#define WM5100_OUT4LMIX_INPUT_2_SOURCE          0x6B2
+#define WM5100_OUT4LMIX_INPUT_2_VOLUME          0x6B3
+#define WM5100_OUT4LMIX_INPUT_3_SOURCE          0x6B4
+#define WM5100_OUT4LMIX_INPUT_3_VOLUME          0x6B5
+#define WM5100_OUT4LMIX_INPUT_4_SOURCE          0x6B6
+#define WM5100_OUT4LMIX_INPUT_4_VOLUME          0x6B7
+#define WM5100_OUT4RMIX_INPUT_1_SOURCE          0x6B8
+#define WM5100_OUT4RMIX_INPUT_1_VOLUME          0x6B9
+#define WM5100_OUT4RMIX_INPUT_2_SOURCE          0x6BA
+#define WM5100_OUT4RMIX_INPUT_2_VOLUME          0x6BB
+#define WM5100_OUT4RMIX_INPUT_3_SOURCE          0x6BC
+#define WM5100_OUT4RMIX_INPUT_3_VOLUME          0x6BD
+#define WM5100_OUT4RMIX_INPUT_4_SOURCE          0x6BE
+#define WM5100_OUT4RMIX_INPUT_4_VOLUME          0x6BF
+#define WM5100_OUT5LMIX_INPUT_1_SOURCE          0x6C0
+#define WM5100_OUT5LMIX_INPUT_1_VOLUME          0x6C1
+#define WM5100_OUT5LMIX_INPUT_2_SOURCE          0x6C2
+#define WM5100_OUT5LMIX_INPUT_2_VOLUME          0x6C3
+#define WM5100_OUT5LMIX_INPUT_3_SOURCE          0x6C4
+#define WM5100_OUT5LMIX_INPUT_3_VOLUME          0x6C5
+#define WM5100_OUT5LMIX_INPUT_4_SOURCE          0x6C6
+#define WM5100_OUT5LMIX_INPUT_4_VOLUME          0x6C7
+#define WM5100_OUT5RMIX_INPUT_1_SOURCE          0x6C8
+#define WM5100_OUT5RMIX_INPUT_1_VOLUME          0x6C9
+#define WM5100_OUT5RMIX_INPUT_2_SOURCE          0x6CA
+#define WM5100_OUT5RMIX_INPUT_2_VOLUME          0x6CB
+#define WM5100_OUT5RMIX_INPUT_3_SOURCE          0x6CC
+#define WM5100_OUT5RMIX_INPUT_3_VOLUME          0x6CD
+#define WM5100_OUT5RMIX_INPUT_4_SOURCE          0x6CE
+#define WM5100_OUT5RMIX_INPUT_4_VOLUME          0x6CF
+#define WM5100_OUT6LMIX_INPUT_1_SOURCE          0x6D0
+#define WM5100_OUT6LMIX_INPUT_1_VOLUME          0x6D1
+#define WM5100_OUT6LMIX_INPUT_2_SOURCE          0x6D2
+#define WM5100_OUT6LMIX_INPUT_2_VOLUME          0x6D3
+#define WM5100_OUT6LMIX_INPUT_3_SOURCE          0x6D4
+#define WM5100_OUT6LMIX_INPUT_3_VOLUME          0x6D5
+#define WM5100_OUT6LMIX_INPUT_4_SOURCE          0x6D6
+#define WM5100_OUT6LMIX_INPUT_4_VOLUME          0x6D7
+#define WM5100_OUT6RMIX_INPUT_1_SOURCE          0x6D8
+#define WM5100_OUT6RMIX_INPUT_1_VOLUME          0x6D9
+#define WM5100_OUT6RMIX_INPUT_2_SOURCE          0x6DA
+#define WM5100_OUT6RMIX_INPUT_2_VOLUME          0x6DB
+#define WM5100_OUT6RMIX_INPUT_3_SOURCE          0x6DC
+#define WM5100_OUT6RMIX_INPUT_3_VOLUME          0x6DD
+#define WM5100_OUT6RMIX_INPUT_4_SOURCE          0x6DE
+#define WM5100_OUT6RMIX_INPUT_4_VOLUME          0x6DF
+#define WM5100_AIF1TX1MIX_INPUT_1_SOURCE        0x700
+#define WM5100_AIF1TX1MIX_INPUT_1_VOLUME        0x701
+#define WM5100_AIF1TX1MIX_INPUT_2_SOURCE        0x702
+#define WM5100_AIF1TX1MIX_INPUT_2_VOLUME        0x703
+#define WM5100_AIF1TX1MIX_INPUT_3_SOURCE        0x704
+#define WM5100_AIF1TX1MIX_INPUT_3_VOLUME        0x705
+#define WM5100_AIF1TX1MIX_INPUT_4_SOURCE        0x706
+#define WM5100_AIF1TX1MIX_INPUT_4_VOLUME        0x707
+#define WM5100_AIF1TX2MIX_INPUT_1_SOURCE        0x708
+#define WM5100_AIF1TX2MIX_INPUT_1_VOLUME        0x709
+#define WM5100_AIF1TX2MIX_INPUT_2_SOURCE        0x70A
+#define WM5100_AIF1TX2MIX_INPUT_2_VOLUME        0x70B
+#define WM5100_AIF1TX2MIX_INPUT_3_SOURCE        0x70C
+#define WM5100_AIF1TX2MIX_INPUT_3_VOLUME        0x70D
+#define WM5100_AIF1TX2MIX_INPUT_4_SOURCE        0x70E
+#define WM5100_AIF1TX2MIX_INPUT_4_VOLUME        0x70F
+#define WM5100_AIF1TX3MIX_INPUT_1_SOURCE        0x710
+#define WM5100_AIF1TX3MIX_INPUT_1_VOLUME        0x711
+#define WM5100_AIF1TX3MIX_INPUT_2_SOURCE        0x712
+#define WM5100_AIF1TX3MIX_INPUT_2_VOLUME        0x713
+#define WM5100_AIF1TX3MIX_INPUT_3_SOURCE        0x714
+#define WM5100_AIF1TX3MIX_INPUT_3_VOLUME        0x715
+#define WM5100_AIF1TX3MIX_INPUT_4_SOURCE        0x716
+#define WM5100_AIF1TX3MIX_INPUT_4_VOLUME        0x717
+#define WM5100_AIF1TX4MIX_INPUT_1_SOURCE        0x718
+#define WM5100_AIF1TX4MIX_INPUT_1_VOLUME        0x719
+#define WM5100_AIF1TX4MIX_INPUT_2_SOURCE        0x71A
+#define WM5100_AIF1TX4MIX_INPUT_2_VOLUME        0x71B
+#define WM5100_AIF1TX4MIX_INPUT_3_SOURCE        0x71C
+#define WM5100_AIF1TX4MIX_INPUT_3_VOLUME        0x71D
+#define WM5100_AIF1TX4MIX_INPUT_4_SOURCE        0x71E
+#define WM5100_AIF1TX4MIX_INPUT_4_VOLUME        0x71F
+#define WM5100_AIF1TX5MIX_INPUT_1_SOURCE        0x720
+#define WM5100_AIF1TX5MIX_INPUT_1_VOLUME        0x721
+#define WM5100_AIF1TX5MIX_INPUT_2_SOURCE        0x722
+#define WM5100_AIF1TX5MIX_INPUT_2_VOLUME        0x723
+#define WM5100_AIF1TX5MIX_INPUT_3_SOURCE        0x724
+#define WM5100_AIF1TX5MIX_INPUT_3_VOLUME        0x725
+#define WM5100_AIF1TX5MIX_INPUT_4_SOURCE        0x726
+#define WM5100_AIF1TX5MIX_INPUT_4_VOLUME        0x727
+#define WM5100_AIF1TX6MIX_INPUT_1_SOURCE        0x728
+#define WM5100_AIF1TX6MIX_INPUT_1_VOLUME        0x729
+#define WM5100_AIF1TX6MIX_INPUT_2_SOURCE        0x72A
+#define WM5100_AIF1TX6MIX_INPUT_2_VOLUME        0x72B
+#define WM5100_AIF1TX6MIX_INPUT_3_SOURCE        0x72C
+#define WM5100_AIF1TX6MIX_INPUT_3_VOLUME        0x72D
+#define WM5100_AIF1TX6MIX_INPUT_4_SOURCE        0x72E
+#define WM5100_AIF1TX6MIX_INPUT_4_VOLUME        0x72F
+#define WM5100_AIF1TX7MIX_INPUT_1_SOURCE        0x730
+#define WM5100_AIF1TX7MIX_INPUT_1_VOLUME        0x731
+#define WM5100_AIF1TX7MIX_INPUT_2_SOURCE        0x732
+#define WM5100_AIF1TX7MIX_INPUT_2_VOLUME        0x733
+#define WM5100_AIF1TX7MIX_INPUT_3_SOURCE        0x734
+#define WM5100_AIF1TX7MIX_INPUT_3_VOLUME        0x735
+#define WM5100_AIF1TX7MIX_INPUT_4_SOURCE        0x736
+#define WM5100_AIF1TX7MIX_INPUT_4_VOLUME        0x737
+#define WM5100_AIF1TX8MIX_INPUT_1_SOURCE        0x738
+#define WM5100_AIF1TX8MIX_INPUT_1_VOLUME        0x739
+#define WM5100_AIF1TX8MIX_INPUT_2_SOURCE        0x73A
+#define WM5100_AIF1TX8MIX_INPUT_2_VOLUME        0x73B
+#define WM5100_AIF1TX8MIX_INPUT_3_SOURCE        0x73C
+#define WM5100_AIF1TX8MIX_INPUT_3_VOLUME        0x73D
+#define WM5100_AIF1TX8MIX_INPUT_4_SOURCE        0x73E
+#define WM5100_AIF1TX8MIX_INPUT_4_VOLUME        0x73F
+#define WM5100_AIF2TX1MIX_INPUT_1_SOURCE        0x740
+#define WM5100_AIF2TX1MIX_INPUT_1_VOLUME        0x741
+#define WM5100_AIF2TX1MIX_INPUT_2_SOURCE        0x742
+#define WM5100_AIF2TX1MIX_INPUT_2_VOLUME        0x743
+#define WM5100_AIF2TX1MIX_INPUT_3_SOURCE        0x744
+#define WM5100_AIF2TX1MIX_INPUT_3_VOLUME        0x745
+#define WM5100_AIF2TX1MIX_INPUT_4_SOURCE        0x746
+#define WM5100_AIF2TX1MIX_INPUT_4_VOLUME        0x747
+#define WM5100_AIF2TX2MIX_INPUT_1_SOURCE        0x748
+#define WM5100_AIF2TX2MIX_INPUT_1_VOLUME        0x749
+#define WM5100_AIF2TX2MIX_INPUT_2_SOURCE        0x74A
+#define WM5100_AIF2TX2MIX_INPUT_2_VOLUME        0x74B
+#define WM5100_AIF2TX2MIX_INPUT_3_SOURCE        0x74C
+#define WM5100_AIF2TX2MIX_INPUT_3_VOLUME        0x74D
+#define WM5100_AIF2TX2MIX_INPUT_4_SOURCE        0x74E
+#define WM5100_AIF2TX2MIX_INPUT_4_VOLUME        0x74F
+#define WM5100_AIF3TX1MIX_INPUT_1_SOURCE        0x780
+#define WM5100_AIF3TX1MIX_INPUT_1_VOLUME        0x781
+#define WM5100_AIF3TX1MIX_INPUT_2_SOURCE        0x782
+#define WM5100_AIF3TX1MIX_INPUT_2_VOLUME        0x783
+#define WM5100_AIF3TX1MIX_INPUT_3_SOURCE        0x784
+#define WM5100_AIF3TX1MIX_INPUT_3_VOLUME        0x785
+#define WM5100_AIF3TX1MIX_INPUT_4_SOURCE        0x786
+#define WM5100_AIF3TX1MIX_INPUT_4_VOLUME        0x787
+#define WM5100_AIF3TX2MIX_INPUT_1_SOURCE        0x788
+#define WM5100_AIF3TX2MIX_INPUT_1_VOLUME        0x789
+#define WM5100_AIF3TX2MIX_INPUT_2_SOURCE        0x78A
+#define WM5100_AIF3TX2MIX_INPUT_2_VOLUME        0x78B
+#define WM5100_AIF3TX2MIX_INPUT_3_SOURCE        0x78C
+#define WM5100_AIF3TX2MIX_INPUT_3_VOLUME        0x78D
+#define WM5100_AIF3TX2MIX_INPUT_4_SOURCE        0x78E
+#define WM5100_AIF3TX2MIX_INPUT_4_VOLUME        0x78F
+#define WM5100_EQ1MIX_INPUT_1_SOURCE            0x880
+#define WM5100_EQ1MIX_INPUT_1_VOLUME            0x881
+#define WM5100_EQ1MIX_INPUT_2_SOURCE            0x882
+#define WM5100_EQ1MIX_INPUT_2_VOLUME            0x883
+#define WM5100_EQ1MIX_INPUT_3_SOURCE            0x884
+#define WM5100_EQ1MIX_INPUT_3_VOLUME            0x885
+#define WM5100_EQ1MIX_INPUT_4_SOURCE            0x886
+#define WM5100_EQ1MIX_INPUT_4_VOLUME            0x887
+#define WM5100_EQ2MIX_INPUT_1_SOURCE            0x888
+#define WM5100_EQ2MIX_INPUT_1_VOLUME            0x889
+#define WM5100_EQ2MIX_INPUT_2_SOURCE            0x88A
+#define WM5100_EQ2MIX_INPUT_2_VOLUME            0x88B
+#define WM5100_EQ2MIX_INPUT_3_SOURCE            0x88C
+#define WM5100_EQ2MIX_INPUT_3_VOLUME            0x88D
+#define WM5100_EQ2MIX_INPUT_4_SOURCE            0x88E
+#define WM5100_EQ2MIX_INPUT_4_VOLUME            0x88F
+#define WM5100_EQ3MIX_INPUT_1_SOURCE            0x890
+#define WM5100_EQ3MIX_INPUT_1_VOLUME            0x891
+#define WM5100_EQ3MIX_INPUT_2_SOURCE            0x892
+#define WM5100_EQ3MIX_INPUT_2_VOLUME            0x893
+#define WM5100_EQ3MIX_INPUT_3_SOURCE            0x894
+#define WM5100_EQ3MIX_INPUT_3_VOLUME            0x895
+#define WM5100_EQ3MIX_INPUT_4_SOURCE            0x896
+#define WM5100_EQ3MIX_INPUT_4_VOLUME            0x897
+#define WM5100_EQ4MIX_INPUT_1_SOURCE            0x898
+#define WM5100_EQ4MIX_INPUT_1_VOLUME            0x899
+#define WM5100_EQ4MIX_INPUT_2_SOURCE            0x89A
+#define WM5100_EQ4MIX_INPUT_2_VOLUME            0x89B
+#define WM5100_EQ4MIX_INPUT_3_SOURCE            0x89C
+#define WM5100_EQ4MIX_INPUT_3_VOLUME            0x89D
+#define WM5100_EQ4MIX_INPUT_4_SOURCE            0x89E
+#define WM5100_EQ4MIX_INPUT_4_VOLUME            0x89F
+#define WM5100_DRC1LMIX_INPUT_1_SOURCE          0x8C0
+#define WM5100_DRC1LMIX_INPUT_1_VOLUME          0x8C1
+#define WM5100_DRC1LMIX_INPUT_2_SOURCE          0x8C2
+#define WM5100_DRC1LMIX_INPUT_2_VOLUME          0x8C3
+#define WM5100_DRC1LMIX_INPUT_3_SOURCE          0x8C4
+#define WM5100_DRC1LMIX_INPUT_3_VOLUME          0x8C5
+#define WM5100_DRC1LMIX_INPUT_4_SOURCE          0x8C6
+#define WM5100_DRC1LMIX_INPUT_4_VOLUME          0x8C7
+#define WM5100_DRC1RMIX_INPUT_1_SOURCE          0x8C8
+#define WM5100_DRC1RMIX_INPUT_1_VOLUME          0x8C9
+#define WM5100_DRC1RMIX_INPUT_2_SOURCE          0x8CA
+#define WM5100_DRC1RMIX_INPUT_2_VOLUME          0x8CB
+#define WM5100_DRC1RMIX_INPUT_3_SOURCE          0x8CC
+#define WM5100_DRC1RMIX_INPUT_3_VOLUME          0x8CD
+#define WM5100_DRC1RMIX_INPUT_4_SOURCE          0x8CE
+#define WM5100_DRC1RMIX_INPUT_4_VOLUME          0x8CF
+#define WM5100_HPLP1MIX_INPUT_1_SOURCE          0x900
+#define WM5100_HPLP1MIX_INPUT_1_VOLUME          0x901
+#define WM5100_HPLP1MIX_INPUT_2_SOURCE          0x902
+#define WM5100_HPLP1MIX_INPUT_2_VOLUME          0x903
+#define WM5100_HPLP1MIX_INPUT_3_SOURCE          0x904
+#define WM5100_HPLP1MIX_INPUT_3_VOLUME          0x905
+#define WM5100_HPLP1MIX_INPUT_4_SOURCE          0x906
+#define WM5100_HPLP1MIX_INPUT_4_VOLUME          0x907
+#define WM5100_HPLP2MIX_INPUT_1_SOURCE          0x908
+#define WM5100_HPLP2MIX_INPUT_1_VOLUME          0x909
+#define WM5100_HPLP2MIX_INPUT_2_SOURCE          0x90A
+#define WM5100_HPLP2MIX_INPUT_2_VOLUME          0x90B
+#define WM5100_HPLP2MIX_INPUT_3_SOURCE          0x90C
+#define WM5100_HPLP2MIX_INPUT_3_VOLUME          0x90D
+#define WM5100_HPLP2MIX_INPUT_4_SOURCE          0x90E
+#define WM5100_HPLP2MIX_INPUT_4_VOLUME          0x90F
+#define WM5100_HPLP3MIX_INPUT_1_SOURCE          0x910
+#define WM5100_HPLP3MIX_INPUT_1_VOLUME          0x911
+#define WM5100_HPLP3MIX_INPUT_2_SOURCE          0x912
+#define WM5100_HPLP3MIX_INPUT_2_VOLUME          0x913
+#define WM5100_HPLP3MIX_INPUT_3_SOURCE          0x914
+#define WM5100_HPLP3MIX_INPUT_3_VOLUME          0x915
+#define WM5100_HPLP3MIX_INPUT_4_SOURCE          0x916
+#define WM5100_HPLP3MIX_INPUT_4_VOLUME          0x917
+#define WM5100_HPLP4MIX_INPUT_1_SOURCE          0x918
+#define WM5100_HPLP4MIX_INPUT_1_VOLUME          0x919
+#define WM5100_HPLP4MIX_INPUT_2_SOURCE          0x91A
+#define WM5100_HPLP4MIX_INPUT_2_VOLUME          0x91B
+#define WM5100_HPLP4MIX_INPUT_3_SOURCE          0x91C
+#define WM5100_HPLP4MIX_INPUT_3_VOLUME          0x91D
+#define WM5100_HPLP4MIX_INPUT_4_SOURCE          0x91E
+#define WM5100_HPLP4MIX_INPUT_4_VOLUME          0x91F
+#define WM5100_DSP1LMIX_INPUT_1_SOURCE          0x940
+#define WM5100_DSP1LMIX_INPUT_1_VOLUME          0x941
+#define WM5100_DSP1LMIX_INPUT_2_SOURCE          0x942
+#define WM5100_DSP1LMIX_INPUT_2_VOLUME          0x943
+#define WM5100_DSP1LMIX_INPUT_3_SOURCE          0x944
+#define WM5100_DSP1LMIX_INPUT_3_VOLUME          0x945
+#define WM5100_DSP1LMIX_INPUT_4_SOURCE          0x946
+#define WM5100_DSP1LMIX_INPUT_4_VOLUME          0x947
+#define WM5100_DSP1RMIX_INPUT_1_SOURCE          0x948
+#define WM5100_DSP1RMIX_INPUT_1_VOLUME          0x949
+#define WM5100_DSP1RMIX_INPUT_2_SOURCE          0x94A
+#define WM5100_DSP1RMIX_INPUT_2_VOLUME          0x94B
+#define WM5100_DSP1RMIX_INPUT_3_SOURCE          0x94C
+#define WM5100_DSP1RMIX_INPUT_3_VOLUME          0x94D
+#define WM5100_DSP1RMIX_INPUT_4_SOURCE          0x94E
+#define WM5100_DSP1RMIX_INPUT_4_VOLUME          0x94F
+#define WM5100_DSP1AUX1MIX_INPUT_1_SOURCE       0x950
+#define WM5100_DSP1AUX2MIX_INPUT_1_SOURCE       0x958
+#define WM5100_DSP1AUX3MIX_INPUT_1_SOURCE       0x960
+#define WM5100_DSP1AUX4MIX_INPUT_1_SOURCE       0x968
+#define WM5100_DSP1AUX5MIX_INPUT_1_SOURCE       0x970
+#define WM5100_DSP1AUX6MIX_INPUT_1_SOURCE       0x978
+#define WM5100_DSP2LMIX_INPUT_1_SOURCE          0x980
+#define WM5100_DSP2LMIX_INPUT_1_VOLUME          0x981
+#define WM5100_DSP2LMIX_INPUT_2_SOURCE          0x982
+#define WM5100_DSP2LMIX_INPUT_2_VOLUME          0x983
+#define WM5100_DSP2LMIX_INPUT_3_SOURCE          0x984
+#define WM5100_DSP2LMIX_INPUT_3_VOLUME          0x985
+#define WM5100_DSP2LMIX_INPUT_4_SOURCE          0x986
+#define WM5100_DSP2LMIX_INPUT_4_VOLUME          0x987
+#define WM5100_DSP2RMIX_INPUT_1_SOURCE          0x988
+#define WM5100_DSP2RMIX_INPUT_1_VOLUME          0x989
+#define WM5100_DSP2RMIX_INPUT_2_SOURCE          0x98A
+#define WM5100_DSP2RMIX_INPUT_2_VOLUME          0x98B
+#define WM5100_DSP2RMIX_INPUT_3_SOURCE          0x98C
+#define WM5100_DSP2RMIX_INPUT_3_VOLUME          0x98D
+#define WM5100_DSP2RMIX_INPUT_4_SOURCE          0x98E
+#define WM5100_DSP2RMIX_INPUT_4_VOLUME          0x98F
+#define WM5100_DSP2AUX1MIX_INPUT_1_SOURCE       0x990
+#define WM5100_DSP2AUX2MIX_INPUT_1_SOURCE       0x998
+#define WM5100_DSP2AUX3MIX_INPUT_1_SOURCE       0x9A0
+#define WM5100_DSP2AUX4MIX_INPUT_1_SOURCE       0x9A8
+#define WM5100_DSP2AUX5MIX_INPUT_1_SOURCE       0x9B0
+#define WM5100_DSP2AUX6MIX_INPUT_1_SOURCE       0x9B8
+#define WM5100_DSP3LMIX_INPUT_1_SOURCE          0x9C0
+#define WM5100_DSP3LMIX_INPUT_1_VOLUME          0x9C1
+#define WM5100_DSP3LMIX_INPUT_2_SOURCE          0x9C2
+#define WM5100_DSP3LMIX_INPUT_2_VOLUME          0x9C3
+#define WM5100_DSP3LMIX_INPUT_3_SOURCE          0x9C4
+#define WM5100_DSP3LMIX_INPUT_3_VOLUME          0x9C5
+#define WM5100_DSP3LMIX_INPUT_4_SOURCE          0x9C6
+#define WM5100_DSP3LMIX_INPUT_4_VOLUME          0x9C7
+#define WM5100_DSP3RMIX_INPUT_1_SOURCE          0x9C8
+#define WM5100_DSP3RMIX_INPUT_1_VOLUME          0x9C9
+#define WM5100_DSP3RMIX_INPUT_2_SOURCE          0x9CA
+#define WM5100_DSP3RMIX_INPUT_2_VOLUME          0x9CB
+#define WM5100_DSP3RMIX_INPUT_3_SOURCE          0x9CC
+#define WM5100_DSP3RMIX_INPUT_3_VOLUME          0x9CD
+#define WM5100_DSP3RMIX_INPUT_4_SOURCE          0x9CE
+#define WM5100_DSP3RMIX_INPUT_4_VOLUME          0x9CF
+#define WM5100_DSP3AUX1MIX_INPUT_1_SOURCE       0x9D0
+#define WM5100_DSP3AUX2MIX_INPUT_1_SOURCE       0x9D8
+#define WM5100_DSP3AUX3MIX_INPUT_1_SOURCE       0x9E0
+#define WM5100_DSP3AUX4MIX_INPUT_1_SOURCE       0x9E8
+#define WM5100_DSP3AUX5MIX_INPUT_1_SOURCE       0x9F0
+#define WM5100_DSP3AUX6MIX_INPUT_1_SOURCE       0x9F8
+#define WM5100_ASRC1LMIX_INPUT_1_SOURCE         0xA80
+#define WM5100_ASRC1RMIX_INPUT_1_SOURCE         0xA88
+#define WM5100_ASRC2LMIX_INPUT_1_SOURCE         0xA90
+#define WM5100_ASRC2RMIX_INPUT_1_SOURCE         0xA98
+#define WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE      0xB00
+#define WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE      0xB08
+#define WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE      0xB10
+#define WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE      0xB18
+#define WM5100_ISRC1INT1MIX_INPUT_1_SOURCE      0xB20
+#define WM5100_ISRC1INT2MIX_INPUT_1_SOURCE      0xB28
+#define WM5100_ISRC1INT3MIX_INPUT_1_SOURCE      0xB30
+#define WM5100_ISRC1INT4MIX_INPUT_1_SOURCE      0xB38
+#define WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE      0xB40
+#define WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE      0xB48
+#define WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE      0xB50
+#define WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE      0xB58
+#define WM5100_ISRC2INT1MIX_INPUT_1_SOURCE      0xB60
+#define WM5100_ISRC2INT2MIX_INPUT_1_SOURCE      0xB68
+#define WM5100_ISRC2INT3MIX_INPUT_1_SOURCE      0xB70
+#define WM5100_ISRC2INT4MIX_INPUT_1_SOURCE      0xB78
+#define WM5100_GPIO_CTRL_1                      0xC00
+#define WM5100_GPIO_CTRL_2                      0xC01
+#define WM5100_GPIO_CTRL_3                      0xC02
+#define WM5100_GPIO_CTRL_4                      0xC03
+#define WM5100_GPIO_CTRL_5                      0xC04
+#define WM5100_GPIO_CTRL_6                      0xC05
+#define WM5100_MISC_PAD_CTRL_1                  0xC23
+#define WM5100_MISC_PAD_CTRL_2                  0xC24
+#define WM5100_MISC_PAD_CTRL_3                  0xC25
+#define WM5100_MISC_PAD_CTRL_4                  0xC26
+#define WM5100_MISC_PAD_CTRL_5                  0xC27
+#define WM5100_MISC_GPIO_1                      0xC28
+#define WM5100_INTERRUPT_STATUS_1               0xD00
+#define WM5100_INTERRUPT_STATUS_2               0xD01
+#define WM5100_INTERRUPT_STATUS_3               0xD02
+#define WM5100_INTERRUPT_STATUS_4               0xD03
+#define WM5100_INTERRUPT_RAW_STATUS_2           0xD04
+#define WM5100_INTERRUPT_RAW_STATUS_3           0xD05
+#define WM5100_INTERRUPT_RAW_STATUS_4           0xD06
+#define WM5100_INTERRUPT_STATUS_1_MASK          0xD07
+#define WM5100_INTERRUPT_STATUS_2_MASK          0xD08
+#define WM5100_INTERRUPT_STATUS_3_MASK          0xD09
+#define WM5100_INTERRUPT_STATUS_4_MASK          0xD0A
+#define WM5100_INTERRUPT_CONTROL                0xD1F
+#define WM5100_IRQ_DEBOUNCE_1                   0xD20
+#define WM5100_IRQ_DEBOUNCE_2                   0xD21
+#define WM5100_FX_CTRL                          0xE00
+#define WM5100_EQ1_1                            0xE10
+#define WM5100_EQ1_2                            0xE11
+#define WM5100_EQ1_3                            0xE12
+#define WM5100_EQ1_4                            0xE13
+#define WM5100_EQ1_5                            0xE14
+#define WM5100_EQ1_6                            0xE15
+#define WM5100_EQ1_7                            0xE16
+#define WM5100_EQ1_8                            0xE17
+#define WM5100_EQ1_9                            0xE18
+#define WM5100_EQ1_10                           0xE19
+#define WM5100_EQ1_11                           0xE1A
+#define WM5100_EQ1_12                           0xE1B
+#define WM5100_EQ1_13                           0xE1C
+#define WM5100_EQ1_14                           0xE1D
+#define WM5100_EQ1_15                           0xE1E
+#define WM5100_EQ1_16                           0xE1F
+#define WM5100_EQ1_17                           0xE20
+#define WM5100_EQ1_18                           0xE21
+#define WM5100_EQ1_19                           0xE22
+#define WM5100_EQ1_20                           0xE23
+#define WM5100_EQ2_1                            0xE26
+#define WM5100_EQ2_2                            0xE27
+#define WM5100_EQ2_3                            0xE28
+#define WM5100_EQ2_4                            0xE29
+#define WM5100_EQ2_5                            0xE2A
+#define WM5100_EQ2_6                            0xE2B
+#define WM5100_EQ2_7                            0xE2C
+#define WM5100_EQ2_8                            0xE2D
+#define WM5100_EQ2_9                            0xE2E
+#define WM5100_EQ2_10                           0xE2F
+#define WM5100_EQ2_11                           0xE30
+#define WM5100_EQ2_12                           0xE31
+#define WM5100_EQ2_13                           0xE32
+#define WM5100_EQ2_14                           0xE33
+#define WM5100_EQ2_15                           0xE34
+#define WM5100_EQ2_16                           0xE35
+#define WM5100_EQ2_17                           0xE36
+#define WM5100_EQ2_18                           0xE37
+#define WM5100_EQ2_19                           0xE38
+#define WM5100_EQ2_20                           0xE39
+#define WM5100_EQ3_1                            0xE3C
+#define WM5100_EQ3_2                            0xE3D
+#define WM5100_EQ3_3                            0xE3E
+#define WM5100_EQ3_4                            0xE3F
+#define WM5100_EQ3_5                            0xE40
+#define WM5100_EQ3_6                            0xE41
+#define WM5100_EQ3_7                            0xE42
+#define WM5100_EQ3_8                            0xE43
+#define WM5100_EQ3_9                            0xE44
+#define WM5100_EQ3_10                           0xE45
+#define WM5100_EQ3_11                           0xE46
+#define WM5100_EQ3_12                           0xE47
+#define WM5100_EQ3_13                           0xE48
+#define WM5100_EQ3_14                           0xE49
+#define WM5100_EQ3_15                           0xE4A
+#define WM5100_EQ3_16                           0xE4B
+#define WM5100_EQ3_17                           0xE4C
+#define WM5100_EQ3_18                           0xE4D
+#define WM5100_EQ3_19                           0xE4E
+#define WM5100_EQ3_20                           0xE4F
+#define WM5100_EQ4_1                            0xE52
+#define WM5100_EQ4_2                            0xE53
+#define WM5100_EQ4_3                            0xE54
+#define WM5100_EQ4_4                            0xE55
+#define WM5100_EQ4_5                            0xE56
+#define WM5100_EQ4_6                            0xE57
+#define WM5100_EQ4_7                            0xE58
+#define WM5100_EQ4_8                            0xE59
+#define WM5100_EQ4_9                            0xE5A
+#define WM5100_EQ4_10                           0xE5B
+#define WM5100_EQ4_11                           0xE5C
+#define WM5100_EQ4_12                           0xE5D
+#define WM5100_EQ4_13                           0xE5E
+#define WM5100_EQ4_14                           0xE5F
+#define WM5100_EQ4_15                           0xE60
+#define WM5100_EQ4_16                           0xE61
+#define WM5100_EQ4_17                           0xE62
+#define WM5100_EQ4_18                           0xE63
+#define WM5100_EQ4_19                           0xE64
+#define WM5100_EQ4_20                           0xE65
+#define WM5100_DRC1_CTRL1                       0xE80
+#define WM5100_DRC1_CTRL2                       0xE81
+#define WM5100_DRC1_CTRL3                       0xE82
+#define WM5100_DRC1_CTRL4                       0xE83
+#define WM5100_DRC1_CTRL5                       0xE84
+#define WM5100_HPLPF1_1                         0xEC0
+#define WM5100_HPLPF1_2                         0xEC1
+#define WM5100_HPLPF2_1                         0xEC4
+#define WM5100_HPLPF2_2                         0xEC5
+#define WM5100_HPLPF3_1                         0xEC8
+#define WM5100_HPLPF3_2                         0xEC9
+#define WM5100_HPLPF4_1                         0xECC
+#define WM5100_HPLPF4_2                         0xECD
+#define WM5100_DSP1_DM_0                        0x4000
+#define WM5100_DSP1_DM_1                        0x4001
+#define WM5100_DSP1_DM_2                        0x4002
+#define WM5100_DSP1_DM_3                        0x4003
+#define WM5100_DSP1_DM_508                      0x41FC
+#define WM5100_DSP1_DM_509                      0x41FD
+#define WM5100_DSP1_DM_510                      0x41FE
+#define WM5100_DSP1_DM_511                      0x41FF
+#define WM5100_DSP1_PM_0                        0x4800
+#define WM5100_DSP1_PM_1                        0x4801
+#define WM5100_DSP1_PM_2                        0x4802
+#define WM5100_DSP1_PM_3                        0x4803
+#define WM5100_DSP1_PM_4                        0x4804
+#define WM5100_DSP1_PM_5                        0x4805
+#define WM5100_DSP1_PM_1530                     0x4DFA
+#define WM5100_DSP1_PM_1531                     0x4DFB
+#define WM5100_DSP1_PM_1532                     0x4DFC
+#define WM5100_DSP1_PM_1533                     0x4DFD
+#define WM5100_DSP1_PM_1534                     0x4DFE
+#define WM5100_DSP1_PM_1535                     0x4DFF
+#define WM5100_DSP1_ZM_0                        0x5000
+#define WM5100_DSP1_ZM_1                        0x5001
+#define WM5100_DSP1_ZM_2                        0x5002
+#define WM5100_DSP1_ZM_3                        0x5003
+#define WM5100_DSP1_ZM_2044                     0x57FC
+#define WM5100_DSP1_ZM_2045                     0x57FD
+#define WM5100_DSP1_ZM_2046                     0x57FE
+#define WM5100_DSP1_ZM_2047                     0x57FF
+#define WM5100_DSP2_DM_0                        0x6000
+#define WM5100_DSP2_DM_1                        0x6001
+#define WM5100_DSP2_DM_2                        0x6002
+#define WM5100_DSP2_DM_3                        0x6003
+#define WM5100_DSP2_DM_508                      0x61FC
+#define WM5100_DSP2_DM_509                      0x61FD
+#define WM5100_DSP2_DM_510                      0x61FE
+#define WM5100_DSP2_DM_511                      0x61FF
+#define WM5100_DSP2_PM_0                        0x6800
+#define WM5100_DSP2_PM_1                        0x6801
+#define WM5100_DSP2_PM_2                        0x6802
+#define WM5100_DSP2_PM_3                        0x6803
+#define WM5100_DSP2_PM_4                        0x6804
+#define WM5100_DSP2_PM_5                        0x6805
+#define WM5100_DSP2_PM_1530                     0x6DFA
+#define WM5100_DSP2_PM_1531                     0x6DFB
+#define WM5100_DSP2_PM_1532                     0x6DFC
+#define WM5100_DSP2_PM_1533                     0x6DFD
+#define WM5100_DSP2_PM_1534                     0x6DFE
+#define WM5100_DSP2_PM_1535                     0x6DFF
+#define WM5100_DSP2_ZM_0                        0x7000
+#define WM5100_DSP2_ZM_1                        0x7001
+#define WM5100_DSP2_ZM_2                        0x7002
+#define WM5100_DSP2_ZM_3                        0x7003
+#define WM5100_DSP2_ZM_2044                     0x77FC
+#define WM5100_DSP2_ZM_2045                     0x77FD
+#define WM5100_DSP2_ZM_2046                     0x77FE
+#define WM5100_DSP2_ZM_2047                     0x77FF
+#define WM5100_DSP3_DM_0                        0x8000
+#define WM5100_DSP3_DM_1                        0x8001
+#define WM5100_DSP3_DM_2                        0x8002
+#define WM5100_DSP3_DM_3                        0x8003
+#define WM5100_DSP3_DM_508                      0x81FC
+#define WM5100_DSP3_DM_509                      0x81FD
+#define WM5100_DSP3_DM_510                      0x81FE
+#define WM5100_DSP3_DM_511                      0x81FF
+#define WM5100_DSP3_PM_0                        0x8800
+#define WM5100_DSP3_PM_1                        0x8801
+#define WM5100_DSP3_PM_2                        0x8802
+#define WM5100_DSP3_PM_3                        0x8803
+#define WM5100_DSP3_PM_4                        0x8804
+#define WM5100_DSP3_PM_5                        0x8805
+#define WM5100_DSP3_PM_1530                     0x8DFA
+#define WM5100_DSP3_PM_1531                     0x8DFB
+#define WM5100_DSP3_PM_1532                     0x8DFC
+#define WM5100_DSP3_PM_1533                     0x8DFD
+#define WM5100_DSP3_PM_1534                     0x8DFE
+#define WM5100_DSP3_PM_1535                     0x8DFF
+#define WM5100_DSP3_ZM_0                        0x9000
+#define WM5100_DSP3_ZM_1                        0x9001
+#define WM5100_DSP3_ZM_2                        0x9002
+#define WM5100_DSP3_ZM_3                        0x9003
+#define WM5100_DSP3_ZM_2044                     0x97FC
+#define WM5100_DSP3_ZM_2045                     0x97FD
+#define WM5100_DSP3_ZM_2046                     0x97FE
+#define WM5100_DSP3_ZM_2047                     0x97FF
+
+#define WM5100_REGISTER_COUNT                   1435
+#define WM5100_MAX_REGISTER                     0x97FF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM5100_SW_RST_DEV_ID1_MASK              0xFFFF  /* SW_RST_DEV_ID1 - [15:0] */
+#define WM5100_SW_RST_DEV_ID1_SHIFT                  0  /* SW_RST_DEV_ID1 - [15:0] */
+#define WM5100_SW_RST_DEV_ID1_WIDTH                 16  /* SW_RST_DEV_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM5100_DEVICE_REVISION_MASK             0x000F  /* DEVICE_REVISION - [3:0] */
+#define WM5100_DEVICE_REVISION_SHIFT                 0  /* DEVICE_REVISION - [3:0] */
+#define WM5100_DEVICE_REVISION_WIDTH                 4  /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R16 (0x10) - Ctrl IF 1
+ */
+#define WM5100_AUTO_INC                         0x0001  /* AUTO_INC */
+#define WM5100_AUTO_INC_MASK                    0x0001  /* AUTO_INC */
+#define WM5100_AUTO_INC_SHIFT                        0  /* AUTO_INC */
+#define WM5100_AUTO_INC_WIDTH                        1  /* AUTO_INC */
+
+/*
+ * R32 (0x20) - Tone Generator 1
+ */
+#define WM5100_TONE_RATE_MASK                   0x3000  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_RATE_SHIFT                      12  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_RATE_WIDTH                       2  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_OFFSET_MASK                 0x0300  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE_OFFSET_SHIFT                     8  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE_OFFSET_WIDTH                     2  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE2_ENA                        0x0002  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_MASK                   0x0002  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_SHIFT                       1  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_WIDTH                       1  /* TONE2_ENA */
+#define WM5100_TONE1_ENA                        0x0001  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_MASK                   0x0001  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_SHIFT                       0  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_WIDTH                       1  /* TONE1_ENA */
+
+/*
+ * R48 (0x30) - PWM Drive 1
+ */
+#define WM5100_PWM_RATE_MASK                    0x3000  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_RATE_SHIFT                       12  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_RATE_WIDTH                        2  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_CLK_SEL_MASK                 0x0300  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM_CLK_SEL_SHIFT                     8  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM_CLK_SEL_WIDTH                     2  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM2_OVD                         0x0020  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_MASK                    0x0020  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_SHIFT                        5  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_WIDTH                        1  /* PWM2_OVD */
+#define WM5100_PWM1_OVD                         0x0010  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_MASK                    0x0010  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_SHIFT                        4  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_WIDTH                        1  /* PWM1_OVD */
+#define WM5100_PWM2_ENA                         0x0002  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_MASK                    0x0002  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_SHIFT                        1  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_WIDTH                        1  /* PWM2_ENA */
+#define WM5100_PWM1_ENA                         0x0001  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_MASK                    0x0001  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_SHIFT                        0  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_WIDTH                        1  /* PWM1_ENA */
+
+/*
+ * R49 (0x31) - PWM Drive 2
+ */
+#define WM5100_PWM1_LVL_MASK                    0x03FF  /* PWM1_LVL - [9:0] */
+#define WM5100_PWM1_LVL_SHIFT                        0  /* PWM1_LVL - [9:0] */
+#define WM5100_PWM1_LVL_WIDTH                       10  /* PWM1_LVL - [9:0] */
+
+/*
+ * R50 (0x32) - PWM Drive 3
+ */
+#define WM5100_PWM2_LVL_MASK                    0x03FF  /* PWM2_LVL - [9:0] */
+#define WM5100_PWM2_LVL_SHIFT                        0  /* PWM2_LVL - [9:0] */
+#define WM5100_PWM2_LVL_WIDTH                       10  /* PWM2_LVL - [9:0] */
+
+/*
+ * R256 (0x100) - Clocking 1
+ */
+#define WM5100_CLK_32K_SRC_MASK                 0x000F  /* CLK_32K_SRC - [3:0] */
+#define WM5100_CLK_32K_SRC_SHIFT                     0  /* CLK_32K_SRC - [3:0] */
+#define WM5100_CLK_32K_SRC_WIDTH                     4  /* CLK_32K_SRC - [3:0] */
+
+/*
+ * R257 (0x101) - Clocking 3
+ */
+#define WM5100_SYSCLK_FREQ_MASK                 0x0700  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_FREQ_SHIFT                     8  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_FREQ_WIDTH                     3  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_ENA                       0x0040  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_MASK                  0x0040  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_SHIFT                      6  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_SRC_MASK                  0x000F  /* SYSCLK_SRC - [3:0] */
+#define WM5100_SYSCLK_SRC_SHIFT                      0  /* SYSCLK_SRC - [3:0] */
+#define WM5100_SYSCLK_SRC_WIDTH                      4  /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R258 (0x102) - Clocking 4
+ */
+#define WM5100_SAMPLE_RATE_1_MASK               0x001F  /* SAMPLE_RATE_1 - [4:0] */
+#define WM5100_SAMPLE_RATE_1_SHIFT                   0  /* SAMPLE_RATE_1 - [4:0] */
+#define WM5100_SAMPLE_RATE_1_WIDTH                   5  /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R259 (0x103) - Clocking 5
+ */
+#define WM5100_SAMPLE_RATE_2_MASK               0x001F  /* SAMPLE_RATE_2 - [4:0] */
+#define WM5100_SAMPLE_RATE_2_SHIFT                   0  /* SAMPLE_RATE_2 - [4:0] */
+#define WM5100_SAMPLE_RATE_2_WIDTH                   5  /* SAMPLE_RATE_2 - [4:0] */
+
+/*
+ * R260 (0x104) - Clocking 6
+ */
+#define WM5100_SAMPLE_RATE_3_MASK               0x001F  /* SAMPLE_RATE_3 - [4:0] */
+#define WM5100_SAMPLE_RATE_3_SHIFT                   0  /* SAMPLE_RATE_3 - [4:0] */
+#define WM5100_SAMPLE_RATE_3_WIDTH                   5  /* SAMPLE_RATE_3 - [4:0] */
+
+/*
+ * R263 (0x107) - Clocking 7
+ */
+#define WM5100_ASYNC_CLK_FREQ_MASK              0x0700  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_FREQ_SHIFT                  8  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_FREQ_WIDTH                  3  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_ENA                    0x0040  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_MASK               0x0040  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_SHIFT                   6  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_WIDTH                   1  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_SRC_MASK               0x000F  /* ASYNC_CLK_SRC - [3:0] */
+#define WM5100_ASYNC_CLK_SRC_SHIFT                   0  /* ASYNC_CLK_SRC - [3:0] */
+#define WM5100_ASYNC_CLK_SRC_WIDTH                   4  /* ASYNC_CLK_SRC - [3:0] */
+
+/*
+ * R264 (0x108) - Clocking 8
+ */
+#define WM5100_ASYNC_SAMPLE_RATE_MASK           0x001F  /* ASYNC_SAMPLE_RATE - [4:0] */
+#define WM5100_ASYNC_SAMPLE_RATE_SHIFT               0  /* ASYNC_SAMPLE_RATE - [4:0] */
+#define WM5100_ASYNC_SAMPLE_RATE_WIDTH               5  /* ASYNC_SAMPLE_RATE - [4:0] */
+
+/*
+ * R288 (0x120) - ASRC_ENABLE
+ */
+#define WM5100_ASRC2L_ENA                       0x0008  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_MASK                  0x0008  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_SHIFT                      3  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_WIDTH                      1  /* ASRC2L_ENA */
+#define WM5100_ASRC2R_ENA                       0x0004  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_MASK                  0x0004  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_SHIFT                      2  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_WIDTH                      1  /* ASRC2R_ENA */
+#define WM5100_ASRC1L_ENA                       0x0002  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_MASK                  0x0002  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_SHIFT                      1  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_WIDTH                      1  /* ASRC1L_ENA */
+#define WM5100_ASRC1R_ENA                       0x0001  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_MASK                  0x0001  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_SHIFT                      0  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_WIDTH                      1  /* ASRC1R_ENA */
+
+/*
+ * R289 (0x121) - ASRC_STATUS
+ */
+#define WM5100_ASRC2L_ENA_STS                   0x0008  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_MASK              0x0008  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_SHIFT                  3  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_WIDTH                  1  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS                   0x0004  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_MASK              0x0004  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_SHIFT                  2  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_WIDTH                  1  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS                   0x0002  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_MASK              0x0002  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_SHIFT                  1  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_WIDTH                  1  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS                   0x0001  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_MASK              0x0001  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_SHIFT                  0  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_WIDTH                  1  /* ASRC1R_ENA_STS */
+
+/*
+ * R290 (0x122) - ASRC_RATE1
+ */
+#define WM5100_ASRC_RATE1_MASK                  0x0006  /* ASRC_RATE1 - [2:1] */
+#define WM5100_ASRC_RATE1_SHIFT                      1  /* ASRC_RATE1 - [2:1] */
+#define WM5100_ASRC_RATE1_WIDTH                      2  /* ASRC_RATE1 - [2:1] */
+
+/*
+ * R321 (0x141) - ISRC 1 CTRL 1
+ */
+#define WM5100_ISRC1_DFS_ENA                    0x2000  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_MASK               0x2000  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_SHIFT                  13  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_WIDTH                   1  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_CLK_SEL_MASK               0x0300  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_CLK_SEL_SHIFT                   8  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_CLK_SEL_WIDTH                   2  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_FSH_MASK                   0x000C  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSH_SHIFT                       2  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSH_WIDTH                       2  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSL_MASK                   0x0003  /* ISRC1_FSL - [1:0] */
+#define WM5100_ISRC1_FSL_SHIFT                       0  /* ISRC1_FSL - [1:0] */
+#define WM5100_ISRC1_FSL_WIDTH                       2  /* ISRC1_FSL - [1:0] */
+
+/*
+ * R322 (0x142) - ISRC 1 CTRL 2
+ */
+#define WM5100_ISRC1_INT1_ENA                   0x8000  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_MASK              0x8000  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_SHIFT                 15  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_WIDTH                  1  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT2_ENA                   0x4000  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_MASK              0x4000  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_SHIFT                 14  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_WIDTH                  1  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT3_ENA                   0x2000  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_MASK              0x2000  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_SHIFT                 13  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_WIDTH                  1  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT4_ENA                   0x1000  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_MASK              0x1000  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_SHIFT                 12  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_WIDTH                  1  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_DEC1_ENA                   0x0200  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_MASK              0x0200  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_SHIFT                  9  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_WIDTH                  1  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC2_ENA                   0x0100  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_MASK              0x0100  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_SHIFT                  8  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_WIDTH                  1  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC3_ENA                   0x0080  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_MASK              0x0080  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_SHIFT                  7  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_WIDTH                  1  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC4_ENA                   0x0040  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_MASK              0x0040  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_SHIFT                  6  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_WIDTH                  1  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_NOTCH_ENA                  0x0001  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_MASK             0x0001  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_SHIFT                 0  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_WIDTH                 1  /* ISRC1_NOTCH_ENA */
+
+/*
+ * R323 (0x143) - ISRC 2 CTRL1
+ */
+#define WM5100_ISRC2_DFS_ENA                    0x2000  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_MASK               0x2000  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_SHIFT                  13  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_WIDTH                   1  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_CLK_SEL_MASK               0x0300  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_CLK_SEL_SHIFT                   8  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_CLK_SEL_WIDTH                   2  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_FSH_MASK                   0x000C  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSH_SHIFT                       2  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSH_WIDTH                       2  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSL_MASK                   0x0003  /* ISRC2_FSL - [1:0] */
+#define WM5100_ISRC2_FSL_SHIFT                       0  /* ISRC2_FSL - [1:0] */
+#define WM5100_ISRC2_FSL_WIDTH                       2  /* ISRC2_FSL - [1:0] */
+
+/*
+ * R324 (0x144) - ISRC 2 CTRL 2
+ */
+#define WM5100_ISRC2_INT1_ENA                   0x8000  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_MASK              0x8000  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_SHIFT                 15  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_WIDTH                  1  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT2_ENA                   0x4000  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_MASK              0x4000  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_SHIFT                 14  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_WIDTH                  1  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT3_ENA                   0x2000  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_MASK              0x2000  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_SHIFT                 13  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_WIDTH                  1  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT4_ENA                   0x1000  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_MASK              0x1000  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_SHIFT                 12  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_WIDTH                  1  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_DEC1_ENA                   0x0200  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_MASK              0x0200  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_SHIFT                  9  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_WIDTH                  1  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC2_ENA                   0x0100  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_MASK              0x0100  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_SHIFT                  8  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_WIDTH                  1  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC3_ENA                   0x0080  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_MASK              0x0080  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_SHIFT                  7  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_WIDTH                  1  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC4_ENA                   0x0040  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_MASK              0x0040  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_SHIFT                  6  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_WIDTH                  1  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_NOTCH_ENA                  0x0001  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_MASK             0x0001  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_SHIFT                 0  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_WIDTH                 1  /* ISRC2_NOTCH_ENA */
+
+/*
+ * R386 (0x182) - FLL1 Control 1
+ */
+#define WM5100_FLL1_ENA                         0x0001  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_MASK                    0x0001  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_SHIFT                        0  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_WIDTH                        1  /* FLL1_ENA */
+
+/*
+ * R387 (0x183) - FLL1 Control 2
+ */
+#define WM5100_FLL1_OUTDIV_MASK                 0x3F00  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_OUTDIV_SHIFT                     8  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_OUTDIV_WIDTH                     6  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_FRATIO_MASK                 0x0007  /* FLL1_FRATIO - [2:0] */
+#define WM5100_FLL1_FRATIO_SHIFT                     0  /* FLL1_FRATIO - [2:0] */
+#define WM5100_FLL1_FRATIO_WIDTH                     3  /* FLL1_FRATIO - [2:0] */
+
+/*
+ * R388 (0x184) - FLL1 Control 3
+ */
+#define WM5100_FLL1_THETA_MASK                  0xFFFF  /* FLL1_THETA - [15:0] */
+#define WM5100_FLL1_THETA_SHIFT                      0  /* FLL1_THETA - [15:0] */
+#define WM5100_FLL1_THETA_WIDTH                     16  /* FLL1_THETA - [15:0] */
+
+/*
+ * R390 (0x186) - FLL1 Control 5
+ */
+#define WM5100_FLL1_N_MASK                      0x03FF  /* FLL1_N - [9:0] */
+#define WM5100_FLL1_N_SHIFT                          0  /* FLL1_N - [9:0] */
+#define WM5100_FLL1_N_WIDTH                         10  /* FLL1_N - [9:0] */
+
+/*
+ * R391 (0x187) - FLL1 Control 6
+ */
+#define WM5100_FLL1_REFCLK_DIV_MASK             0x00C0  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_DIV_SHIFT                 6  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_DIV_WIDTH                 2  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_SRC_MASK             0x000F  /* FLL1_REFCLK_SRC - [3:0] */
+#define WM5100_FLL1_REFCLK_SRC_SHIFT                 0  /* FLL1_REFCLK_SRC - [3:0] */
+#define WM5100_FLL1_REFCLK_SRC_WIDTH                 4  /* FLL1_REFCLK_SRC - [3:0] */
+
+/*
+ * R392 (0x188) - FLL1 EFS 1
+ */
+#define WM5100_FLL1_LAMBDA_MASK                 0xFFFF  /* FLL1_LAMBDA - [15:0] */
+#define WM5100_FLL1_LAMBDA_SHIFT                     0  /* FLL1_LAMBDA - [15:0] */
+#define WM5100_FLL1_LAMBDA_WIDTH                    16  /* FLL1_LAMBDA - [15:0] */
+
+/*
+ * R418 (0x1A2) - FLL2 Control 1
+ */
+#define WM5100_FLL2_ENA                         0x0001  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_MASK                    0x0001  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_SHIFT                        0  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_WIDTH                        1  /* FLL2_ENA */
+
+/*
+ * R419 (0x1A3) - FLL2 Control 2
+ */
+#define WM5100_FLL2_OUTDIV_MASK                 0x3F00  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_OUTDIV_SHIFT                     8  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_OUTDIV_WIDTH                     6  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_FRATIO_MASK                 0x0007  /* FLL2_FRATIO - [2:0] */
+#define WM5100_FLL2_FRATIO_SHIFT                     0  /* FLL2_FRATIO - [2:0] */
+#define WM5100_FLL2_FRATIO_WIDTH                     3  /* FLL2_FRATIO - [2:0] */
+
+/*
+ * R420 (0x1A4) - FLL2 Control 3
+ */
+#define WM5100_FLL2_THETA_MASK                  0xFFFF  /* FLL2_THETA - [15:0] */
+#define WM5100_FLL2_THETA_SHIFT                      0  /* FLL2_THETA - [15:0] */
+#define WM5100_FLL2_THETA_WIDTH                     16  /* FLL2_THETA - [15:0] */
+
+/*
+ * R422 (0x1A6) - FLL2 Control 5
+ */
+#define WM5100_FLL2_N_MASK                      0x03FF  /* FLL2_N - [9:0] */
+#define WM5100_FLL2_N_SHIFT                          0  /* FLL2_N - [9:0] */
+#define WM5100_FLL2_N_WIDTH                         10  /* FLL2_N - [9:0] */
+
+/*
+ * R423 (0x1A7) - FLL2 Control 6
+ */
+#define WM5100_FLL2_REFCLK_DIV_MASK             0x00C0  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_DIV_SHIFT                 6  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_DIV_WIDTH                 2  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_SRC_MASK             0x000F  /* FLL2_REFCLK_SRC - [3:0] */
+#define WM5100_FLL2_REFCLK_SRC_SHIFT                 0  /* FLL2_REFCLK_SRC - [3:0] */
+#define WM5100_FLL2_REFCLK_SRC_WIDTH                 4  /* FLL2_REFCLK_SRC - [3:0] */
+
+/*
+ * R424 (0x1A8) - FLL2 EFS 1
+ */
+#define WM5100_FLL2_LAMBDA_MASK                 0xFFFF  /* FLL2_LAMBDA - [15:0] */
+#define WM5100_FLL2_LAMBDA_SHIFT                     0  /* FLL2_LAMBDA - [15:0] */
+#define WM5100_FLL2_LAMBDA_WIDTH                    16  /* FLL2_LAMBDA - [15:0] */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM5100_CP2_BYPASS                       0x0020  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_MASK                  0x0020  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_SHIFT                      5  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_WIDTH                      1  /* CP2_BYPASS */
+#define WM5100_CP2_ENA                          0x0001  /* CP2_ENA */
+#define WM5100_CP2_ENA_MASK                     0x0001  /* CP2_ENA */
+#define WM5100_CP2_ENA_SHIFT                         0  /* CP2_ENA */
+#define WM5100_CP2_ENA_WIDTH                         1  /* CP2_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM5100_LDO2_VSEL_MASK                   0xF800  /* LDO2_VSEL - [15:11] */
+#define WM5100_LDO2_VSEL_SHIFT                      11  /* LDO2_VSEL - [15:11] */
+#define WM5100_LDO2_VSEL_WIDTH                       5  /* LDO2_VSEL - [15:11] */
+
+/*
+ * R514 (0x202) - HP Charge Pump 1
+ */
+#define WM5100_CP1_ENA                          0x0001  /* CP1_ENA */
+#define WM5100_CP1_ENA_MASK                     0x0001  /* CP1_ENA */
+#define WM5100_CP1_ENA_SHIFT                         0  /* CP1_ENA */
+#define WM5100_CP1_ENA_WIDTH                         1  /* CP1_ENA */
+
+/*
+ * R529 (0x211) - LDO1 Control
+ */
+#define WM5100_LDO1_BYPASS                      0x0002  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_MASK                 0x0002  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_SHIFT                     1  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_WIDTH                     1  /* LDO1_BYPASS */
+
+/*
+ * R533 (0x215) - Mic Bias Ctrl 1
+ */
+#define WM5100_MICB1_DISCH                      0x0040  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_MASK                 0x0040  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_SHIFT                     6  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
+#define WM5100_MICB1_RATE                       0x0020  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_MASK                  0x0020  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_SHIFT                      5  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_WIDTH                      1  /* MICB1_RATE */
+#define WM5100_MICB1_LVL_MASK                   0x001C  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_LVL_SHIFT                       2  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_LVL_WIDTH                       3  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_BYPASS                     0x0002  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_MASK                0x0002  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_SHIFT                    1  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_WIDTH                    1  /* MICB1_BYPASS */
+#define WM5100_MICB1_ENA                        0x0001  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_MASK                   0x0001  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_SHIFT                       0  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
+
+/*
+ * R534 (0x216) - Mic Bias Ctrl 2
+ */
+#define WM5100_MICB2_DISCH                      0x0040  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_MASK                 0x0040  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_SHIFT                     6  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
+#define WM5100_MICB2_RATE                       0x0020  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_MASK                  0x0020  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_SHIFT                      5  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_WIDTH                      1  /* MICB2_RATE */
+#define WM5100_MICB2_LVL_MASK                   0x001C  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_LVL_SHIFT                       2  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_LVL_WIDTH                       3  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_BYPASS                     0x0002  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_MASK                0x0002  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_SHIFT                    1  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_WIDTH                    1  /* MICB2_BYPASS */
+#define WM5100_MICB2_ENA                        0x0001  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_MASK                   0x0001  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_SHIFT                       0  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
+
+/*
+ * R535 (0x217) - Mic Bias Ctrl 3
+ */
+#define WM5100_MICB3_DISCH                      0x0040  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_MASK                 0x0040  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_SHIFT                     6  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_WIDTH                     1  /* MICB3_DISCH */
+#define WM5100_MICB3_RATE                       0x0020  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_MASK                  0x0020  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_SHIFT                      5  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_WIDTH                      1  /* MICB3_RATE */
+#define WM5100_MICB3_LVL_MASK                   0x001C  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_LVL_SHIFT                       2  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_LVL_WIDTH                       3  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_BYPASS                     0x0002  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_MASK                0x0002  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_SHIFT                    1  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_WIDTH                    1  /* MICB3_BYPASS */
+#define WM5100_MICB3_ENA                        0x0001  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_MASK                   0x0001  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_SHIFT                       0  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_WIDTH                       1  /* MICB3_ENA */
+
+/*
+ * R640 (0x280) - Accessory Detect Mode 1
+ */
+#define WM5100_ACCDET_BIAS_SRC_MASK             0xC000  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_BIAS_SRC_SHIFT                14  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_BIAS_SRC_WIDTH                 2  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_SRC                       0x2000  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_MASK                  0x2000  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_SHIFT                     13  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_WIDTH                      1  /* ACCDET_SRC */
+#define WM5100_ACCDET_MODE_MASK                 0x0003  /* ACCDET_MODE - [1:0] */
+#define WM5100_ACCDET_MODE_SHIFT                     0  /* ACCDET_MODE - [1:0] */
+#define WM5100_ACCDET_MODE_WIDTH                     2  /* ACCDET_MODE - [1:0] */
+
+/*
+ * R648 (0x288) - Headphone Detect 1
+ */
+#define WM5100_HP_HOLDTIME_MASK                 0x00E0  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_HOLDTIME_SHIFT                     5  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_HOLDTIME_WIDTH                     3  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_CLK_DIV_MASK                  0x0018  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_CLK_DIV_SHIFT                      3  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_CLK_DIV_WIDTH                      2  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_STEP_SIZE                     0x0002  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_MASK                0x0002  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_SHIFT                    1  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_WIDTH                    1  /* HP_STEP_SIZE */
+#define WM5100_HP_POLL                          0x0001  /* HP_POLL */
+#define WM5100_HP_POLL_MASK                     0x0001  /* HP_POLL */
+#define WM5100_HP_POLL_SHIFT                         0  /* HP_POLL */
+#define WM5100_HP_POLL_WIDTH                         1  /* HP_POLL */
+
+/*
+ * R649 (0x289) - Headphone Detect 2
+ */
+#define WM5100_HP_DONE                          0x0080  /* HP_DONE */
+#define WM5100_HP_DONE_MASK                     0x0080  /* HP_DONE */
+#define WM5100_HP_DONE_SHIFT                         7  /* HP_DONE */
+#define WM5100_HP_DONE_WIDTH                         1  /* HP_DONE */
+#define WM5100_HP_LVL_MASK                      0x007F  /* HP_LVL - [6:0] */
+#define WM5100_HP_LVL_SHIFT                          0  /* HP_LVL - [6:0] */
+#define WM5100_HP_LVL_WIDTH                          7  /* HP_LVL - [6:0] */
+
+/*
+ * R656 (0x290) - Mic Detect 1
+ */
+#define WM5100_ACCDET_BIAS_STARTTIME_MASK       0xF000  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_BIAS_STARTTIME_SHIFT          12  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_BIAS_STARTTIME_WIDTH           4  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_RATE_MASK                 0x0F00  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_RATE_SHIFT                     8  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_RATE_WIDTH                     4  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_DBTIME                    0x0002  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_MASK               0x0002  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_SHIFT                   1  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_WIDTH                   1  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_ENA                       0x0001  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_MASK                  0x0001  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_SHIFT                      0  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_WIDTH                      1  /* ACCDET_ENA */
+
+/*
+ * R657 (0x291) - Mic Detect 2
+ */
+#define WM5100_ACCDET_LVL_SEL_MASK              0x00FF  /* ACCDET_LVL_SEL - [7:0] */
+#define WM5100_ACCDET_LVL_SEL_SHIFT                  0  /* ACCDET_LVL_SEL - [7:0] */
+#define WM5100_ACCDET_LVL_SEL_WIDTH                  8  /* ACCDET_LVL_SEL - [7:0] */
+
+/*
+ * R658 (0x292) - Mic Detect 3
+ */
+#define WM5100_ACCDET_LVL_MASK                  0x07FC  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_LVL_SHIFT                      2  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_LVL_WIDTH                      9  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_VALID                     0x0002  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_MASK                0x0002  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_SHIFT                    1  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_WIDTH                    1  /* ACCDET_VALID */
+#define WM5100_ACCDET_STS                       0x0001  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_MASK                  0x0001  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_SHIFT                      0  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_WIDTH                      1  /* ACCDET_STS */
+
+/*
+ * R699 (0x2BB) - Misc Control
+ */
+#define WM5100_HPCOM_SRC                         0x200  /* HPCOM_SRC */
+#define WM5100_HPCOM_SRC_SHIFT                       9  /* HPCOM_SRC */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM5100_IN4L_ENA                         0x0080  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_MASK                    0x0080  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_SHIFT                        7  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_WIDTH                        1  /* IN4L_ENA */
+#define WM5100_IN4R_ENA                         0x0040  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_MASK                    0x0040  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_SHIFT                        6  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_WIDTH                        1  /* IN4R_ENA */
+#define WM5100_IN3L_ENA                         0x0020  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_MASK                    0x0020  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_SHIFT                        5  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_WIDTH                        1  /* IN3L_ENA */
+#define WM5100_IN3R_ENA                         0x0010  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_MASK                    0x0010  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_SHIFT                        4  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_WIDTH                        1  /* IN3R_ENA */
+#define WM5100_IN2L_ENA                         0x0008  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_MASK                    0x0008  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_SHIFT                        3  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_WIDTH                        1  /* IN2L_ENA */
+#define WM5100_IN2R_ENA                         0x0004  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_MASK                    0x0004  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_SHIFT                        2  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_WIDTH                        1  /* IN2R_ENA */
+#define WM5100_IN1L_ENA                         0x0002  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_MASK                    0x0002  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_SHIFT                        1  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_WIDTH                        1  /* IN1L_ENA */
+#define WM5100_IN1R_ENA                         0x0001  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_MASK                    0x0001  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_SHIFT                        0  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_WIDTH                        1  /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - Input Enables Status
+ */
+#define WM5100_IN4L_ENA_STS                     0x0080  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_MASK                0x0080  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_SHIFT                    7  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_WIDTH                    1  /* IN4L_ENA_STS */
+#define WM5100_IN4R_ENA_STS                     0x0040  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_MASK                0x0040  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_SHIFT                    6  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_WIDTH                    1  /* IN4R_ENA_STS */
+#define WM5100_IN3L_ENA_STS                     0x0020  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_MASK                0x0020  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_SHIFT                    5  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_WIDTH                    1  /* IN3L_ENA_STS */
+#define WM5100_IN3R_ENA_STS                     0x0010  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_MASK                0x0010  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_SHIFT                    4  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_WIDTH                    1  /* IN3R_ENA_STS */
+#define WM5100_IN2L_ENA_STS                     0x0008  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_MASK                0x0008  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_SHIFT                    3  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_WIDTH                    1  /* IN2L_ENA_STS */
+#define WM5100_IN2R_ENA_STS                     0x0004  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_MASK                0x0004  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_SHIFT                    2  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_WIDTH                    1  /* IN2R_ENA_STS */
+#define WM5100_IN1L_ENA_STS                     0x0002  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_MASK                0x0002  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_SHIFT                    1  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_WIDTH                    1  /* IN1L_ENA_STS */
+#define WM5100_IN1R_ENA_STS                     0x0001  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_MASK                0x0001  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_SHIFT                    0  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_WIDTH                    1  /* IN1R_ENA_STS */
+
+/*
+ * R784 (0x310) - IN1L Control
+ */
+#define WM5100_IN_RATE_MASK                     0xC000  /* IN_RATE - [15:14] */
+#define WM5100_IN_RATE_SHIFT                        14  /* IN_RATE - [15:14] */
+#define WM5100_IN_RATE_WIDTH                         2  /* IN_RATE - [15:14] */
+#define WM5100_IN1_OSR                          0x2000  /* IN1_OSR */
+#define WM5100_IN1_OSR_MASK                     0x2000  /* IN1_OSR */
+#define WM5100_IN1_OSR_SHIFT                        13  /* IN1_OSR */
+#define WM5100_IN1_OSR_WIDTH                         1  /* IN1_OSR */
+#define WM5100_IN1_DMIC_SUP_MASK                0x1800  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_DMIC_SUP_SHIFT                   11  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_DMIC_SUP_WIDTH                    2  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_MODE_MASK                    0x0600  /* IN1_MODE - [10:9] */
+#define WM5100_IN1_MODE_SHIFT                        9  /* IN1_MODE - [10:9] */
+#define WM5100_IN1_MODE_WIDTH                        2  /* IN1_MODE - [10:9] */
+#define WM5100_IN1L_PGA_VOL_MASK                0x00FE  /* IN1L_PGA_VOL - [7:1] */
+#define WM5100_IN1L_PGA_VOL_SHIFT                    1  /* IN1L_PGA_VOL - [7:1] */
+#define WM5100_IN1L_PGA_VOL_WIDTH                    7  /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R785 (0x311) - IN1R Control
+ */
+#define WM5100_IN1R_PGA_VOL_MASK                0x00FE  /* IN1R_PGA_VOL - [7:1] */
+#define WM5100_IN1R_PGA_VOL_SHIFT                    1  /* IN1R_PGA_VOL - [7:1] */
+#define WM5100_IN1R_PGA_VOL_WIDTH                    7  /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R786 (0x312) - IN2L Control
+ */
+#define WM5100_IN2_OSR                          0x2000  /* IN2_OSR */
+#define WM5100_IN2_OSR_MASK                     0x2000  /* IN2_OSR */
+#define WM5100_IN2_OSR_SHIFT                        13  /* IN2_OSR */
+#define WM5100_IN2_OSR_WIDTH                         1  /* IN2_OSR */
+#define WM5100_IN2_DMIC_SUP_MASK                0x1800  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_DMIC_SUP_SHIFT                   11  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_DMIC_SUP_WIDTH                    2  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_MODE_MASK                    0x0600  /* IN2_MODE - [10:9] */
+#define WM5100_IN2_MODE_SHIFT                        9  /* IN2_MODE - [10:9] */
+#define WM5100_IN2_MODE_WIDTH                        2  /* IN2_MODE - [10:9] */
+#define WM5100_IN2L_PGA_VOL_MASK                0x00FE  /* IN2L_PGA_VOL - [7:1] */
+#define WM5100_IN2L_PGA_VOL_SHIFT                    1  /* IN2L_PGA_VOL - [7:1] */
+#define WM5100_IN2L_PGA_VOL_WIDTH                    7  /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R787 (0x313) - IN2R Control
+ */
+#define WM5100_IN2R_PGA_VOL_MASK                0x00FE  /* IN2R_PGA_VOL - [7:1] */
+#define WM5100_IN2R_PGA_VOL_SHIFT                    1  /* IN2R_PGA_VOL - [7:1] */
+#define WM5100_IN2R_PGA_VOL_WIDTH                    7  /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R788 (0x314) - IN3L Control
+ */
+#define WM5100_IN3_OSR                          0x2000  /* IN3_OSR */
+#define WM5100_IN3_OSR_MASK                     0x2000  /* IN3_OSR */
+#define WM5100_IN3_OSR_SHIFT                        13  /* IN3_OSR */
+#define WM5100_IN3_OSR_WIDTH                         1  /* IN3_OSR */
+#define WM5100_IN3_DMIC_SUP_MASK                0x1800  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_DMIC_SUP_SHIFT                   11  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_DMIC_SUP_WIDTH                    2  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_MODE_MASK                    0x0600  /* IN3_MODE - [10:9] */
+#define WM5100_IN3_MODE_SHIFT                        9  /* IN3_MODE - [10:9] */
+#define WM5100_IN3_MODE_WIDTH                        2  /* IN3_MODE - [10:9] */
+#define WM5100_IN3L_PGA_VOL_MASK                0x00FE  /* IN3L_PGA_VOL - [7:1] */
+#define WM5100_IN3L_PGA_VOL_SHIFT                    1  /* IN3L_PGA_VOL - [7:1] */
+#define WM5100_IN3L_PGA_VOL_WIDTH                    7  /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R789 (0x315) - IN3R Control
+ */
+#define WM5100_IN3R_PGA_VOL_MASK                0x00FE  /* IN3R_PGA_VOL - [7:1] */
+#define WM5100_IN3R_PGA_VOL_SHIFT                    1  /* IN3R_PGA_VOL - [7:1] */
+#define WM5100_IN3R_PGA_VOL_WIDTH                    7  /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R790 (0x316) - IN4L Control
+ */
+#define WM5100_IN4_OSR                          0x2000  /* IN4_OSR */
+#define WM5100_IN4_OSR_MASK                     0x2000  /* IN4_OSR */
+#define WM5100_IN4_OSR_SHIFT                        13  /* IN4_OSR */
+#define WM5100_IN4_OSR_WIDTH                         1  /* IN4_OSR */
+#define WM5100_IN4_DMIC_SUP_MASK                0x1800  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_DMIC_SUP_SHIFT                   11  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_DMIC_SUP_WIDTH                    2  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_MODE_MASK                    0x0600  /* IN4_MODE - [10:9] */
+#define WM5100_IN4_MODE_SHIFT                        9  /* IN4_MODE - [10:9] */
+#define WM5100_IN4_MODE_WIDTH                        2  /* IN4_MODE - [10:9] */
+#define WM5100_IN4L_PGA_VOL_MASK                0x00FE  /* IN4L_PGA_VOL - [7:1] */
+#define WM5100_IN4L_PGA_VOL_SHIFT                    1  /* IN4L_PGA_VOL - [7:1] */
+#define WM5100_IN4L_PGA_VOL_WIDTH                    7  /* IN4L_PGA_VOL - [7:1] */
+
+/*
+ * R791 (0x317) - IN4R Control
+ */
+#define WM5100_IN4R_PGA_VOL_MASK                0x00FE  /* IN4R_PGA_VOL - [7:1] */
+#define WM5100_IN4R_PGA_VOL_SHIFT                    1  /* IN4R_PGA_VOL - [7:1] */
+#define WM5100_IN4R_PGA_VOL_WIDTH                    7  /* IN4R_PGA_VOL - [7:1] */
+
+/*
+ * R792 (0x318) - RXANC_SRC
+ */
+#define WM5100_IN_RXANC_SEL_MASK                0x0007  /* IN_RXANC_SEL - [2:0] */
+#define WM5100_IN_RXANC_SEL_SHIFT                    0  /* IN_RXANC_SEL - [2:0] */
+#define WM5100_IN_RXANC_SEL_WIDTH                    3  /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R793 (0x319) - Input Volume Ramp
+ */
+#define WM5100_IN_VD_RAMP_MASK                  0x0070  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VD_RAMP_SHIFT                      4  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VD_RAMP_WIDTH                      3  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VI_RAMP_MASK                  0x0007  /* IN_VI_RAMP - [2:0] */
+#define WM5100_IN_VI_RAMP_SHIFT                      0  /* IN_VI_RAMP - [2:0] */
+#define WM5100_IN_VI_RAMP_WIDTH                      3  /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R800 (0x320) - ADC Digital Volume 1L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN1L_MUTE                        0x0100  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_MASK                   0x0100  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_SHIFT                       8  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_WIDTH                       1  /* IN1L_MUTE */
+#define WM5100_IN1L_VOL_MASK                    0x00FF  /* IN1L_VOL - [7:0] */
+#define WM5100_IN1L_VOL_SHIFT                        0  /* IN1L_VOL - [7:0] */
+#define WM5100_IN1L_VOL_WIDTH                        8  /* IN1L_VOL - [7:0] */
+
+/*
+ * R801 (0x321) - ADC Digital Volume 1R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN1R_MUTE                        0x0100  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_MASK                   0x0100  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_SHIFT                       8  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_WIDTH                       1  /* IN1R_MUTE */
+#define WM5100_IN1R_VOL_MASK                    0x00FF  /* IN1R_VOL - [7:0] */
+#define WM5100_IN1R_VOL_SHIFT                        0  /* IN1R_VOL - [7:0] */
+#define WM5100_IN1R_VOL_WIDTH                        8  /* IN1R_VOL - [7:0] */
+
+/*
+ * R802 (0x322) - ADC Digital Volume 2L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN2L_MUTE                        0x0100  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_MASK                   0x0100  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_SHIFT                       8  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_WIDTH                       1  /* IN2L_MUTE */
+#define WM5100_IN2L_VOL_MASK                    0x00FF  /* IN2L_VOL - [7:0] */
+#define WM5100_IN2L_VOL_SHIFT                        0  /* IN2L_VOL - [7:0] */
+#define WM5100_IN2L_VOL_WIDTH                        8  /* IN2L_VOL - [7:0] */
+
+/*
+ * R803 (0x323) - ADC Digital Volume 2R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN2R_MUTE                        0x0100  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_MASK                   0x0100  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_SHIFT                       8  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_WIDTH                       1  /* IN2R_MUTE */
+#define WM5100_IN2R_VOL_MASK                    0x00FF  /* IN2R_VOL - [7:0] */
+#define WM5100_IN2R_VOL_SHIFT                        0  /* IN2R_VOL - [7:0] */
+#define WM5100_IN2R_VOL_WIDTH                        8  /* IN2R_VOL - [7:0] */
+
+/*
+ * R804 (0x324) - ADC Digital Volume 3L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN3L_MUTE                        0x0100  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_MASK                   0x0100  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_SHIFT                       8  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_WIDTH                       1  /* IN3L_MUTE */
+#define WM5100_IN3L_VOL_MASK                    0x00FF  /* IN3L_VOL - [7:0] */
+#define WM5100_IN3L_VOL_SHIFT                        0  /* IN3L_VOL - [7:0] */
+#define WM5100_IN3L_VOL_WIDTH                        8  /* IN3L_VOL - [7:0] */
+
+/*
+ * R805 (0x325) - ADC Digital Volume 3R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN3R_MUTE                        0x0100  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_MASK                   0x0100  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_SHIFT                       8  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_WIDTH                       1  /* IN3R_MUTE */
+#define WM5100_IN3R_VOL_MASK                    0x00FF  /* IN3R_VOL - [7:0] */
+#define WM5100_IN3R_VOL_SHIFT                        0  /* IN3R_VOL - [7:0] */
+#define WM5100_IN3R_VOL_WIDTH                        8  /* IN3R_VOL - [7:0] */
+
+/*
+ * R806 (0x326) - ADC Digital Volume 4L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN4L_MUTE                        0x0100  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_MASK                   0x0100  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_SHIFT                       8  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_WIDTH                       1  /* IN4L_MUTE */
+#define WM5100_IN4L_VOL_MASK                    0x00FF  /* IN4L_VOL - [7:0] */
+#define WM5100_IN4L_VOL_SHIFT                        0  /* IN4L_VOL - [7:0] */
+#define WM5100_IN4L_VOL_WIDTH                        8  /* IN4L_VOL - [7:0] */
+
+/*
+ * R807 (0x327) - ADC Digital Volume 4R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN4R_MUTE                        0x0100  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_MASK                   0x0100  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_SHIFT                       8  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_WIDTH                       1  /* IN4R_MUTE */
+#define WM5100_IN4R_VOL_MASK                    0x00FF  /* IN4R_VOL - [7:0] */
+#define WM5100_IN4R_VOL_SHIFT                        0  /* IN4R_VOL - [7:0] */
+#define WM5100_IN4R_VOL_WIDTH                        8  /* IN4R_VOL - [7:0] */
+
+/*
+ * R1025 (0x401) - Output Enables 2
+ */
+#define WM5100_OUT6L_ENA                        0x0800  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_MASK                   0x0800  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_SHIFT                      11  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_WIDTH                       1  /* OUT6L_ENA */
+#define WM5100_OUT6R_ENA                        0x0400  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_MASK                   0x0400  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_SHIFT                      10  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_WIDTH                       1  /* OUT6R_ENA */
+#define WM5100_OUT5L_ENA                        0x0200  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_MASK                   0x0200  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_SHIFT                       9  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_WIDTH                       1  /* OUT5L_ENA */
+#define WM5100_OUT5R_ENA                        0x0100  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_MASK                   0x0100  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_SHIFT                       8  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_WIDTH                       1  /* OUT5R_ENA */
+#define WM5100_OUT4L_ENA                        0x0080  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_MASK                   0x0080  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_SHIFT                       7  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_WIDTH                       1  /* OUT4L_ENA */
+#define WM5100_OUT4R_ENA                        0x0040  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_MASK                   0x0040  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_SHIFT                       6  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_WIDTH                       1  /* OUT4R_ENA */
+
+/*
+ * R1026 (0x402) - Output Status 1
+ */
+#define WM5100_OUT3L_ENA_STS                    0x0020  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_MASK               0x0020  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_SHIFT                   5  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_WIDTH                   1  /* OUT3L_ENA_STS */
+#define WM5100_OUT3R_ENA_STS                    0x0010  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_MASK               0x0010  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_SHIFT                   4  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_WIDTH                   1  /* OUT3R_ENA_STS */
+#define WM5100_OUT2L_ENA_STS                    0x0008  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_MASK               0x0008  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_SHIFT                   3  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_WIDTH                   1  /* OUT2L_ENA_STS */
+#define WM5100_OUT2R_ENA_STS                    0x0004  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_MASK               0x0004  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_SHIFT                   2  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_WIDTH                   1  /* OUT2R_ENA_STS */
+#define WM5100_OUT1L_ENA_STS                    0x0002  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_MASK               0x0002  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_SHIFT                   1  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_WIDTH                   1  /* OUT1L_ENA_STS */
+#define WM5100_OUT1R_ENA_STS                    0x0001  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_MASK               0x0001  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_SHIFT                   0  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_WIDTH                   1  /* OUT1R_ENA_STS */
+
+/*
+ * R1027 (0x403) - Output Status 2
+ */
+#define WM5100_OUT6L_ENA_STS                    0x0800  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_MASK               0x0800  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_SHIFT                  11  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_WIDTH                   1  /* OUT6L_ENA_STS */
+#define WM5100_OUT6R_ENA_STS                    0x0400  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_MASK               0x0400  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_SHIFT                  10  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_WIDTH                   1  /* OUT6R_ENA_STS */
+#define WM5100_OUT5L_ENA_STS                    0x0200  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_MASK               0x0200  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_SHIFT                   9  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_WIDTH                   1  /* OUT5L_ENA_STS */
+#define WM5100_OUT5R_ENA_STS                    0x0100  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_MASK               0x0100  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_SHIFT                   8  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_WIDTH                   1  /* OUT5R_ENA_STS */
+#define WM5100_OUT4L_ENA_STS                    0x0080  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_MASK               0x0080  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_SHIFT                   7  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_WIDTH                   1  /* OUT4L_ENA_STS */
+#define WM5100_OUT4R_ENA_STS                    0x0040  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_MASK               0x0040  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_SHIFT                   6  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_WIDTH                   1  /* OUT4R_ENA_STS */
+
+/*
+ * R1032 (0x408) - Channel Enables 1
+ */
+#define WM5100_HP3L_ENA                         0x0020  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_MASK                    0x0020  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_SHIFT                        5  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_WIDTH                        1  /* HP3L_ENA */
+#define WM5100_HP3R_ENA                         0x0010  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_MASK                    0x0010  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_SHIFT                        4  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_WIDTH                        1  /* HP3R_ENA */
+#define WM5100_HP2L_ENA                         0x0008  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_MASK                    0x0008  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_SHIFT                        3  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_WIDTH                        1  /* HP2L_ENA */
+#define WM5100_HP2R_ENA                         0x0004  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_MASK                    0x0004  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_SHIFT                        2  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_WIDTH                        1  /* HP2R_ENA */
+#define WM5100_HP1L_ENA                         0x0002  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_MASK                    0x0002  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_SHIFT                        1  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_WIDTH                        1  /* HP1L_ENA */
+#define WM5100_HP1R_ENA                         0x0001  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_MASK                    0x0001  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_SHIFT                        0  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_WIDTH                        1  /* HP1R_ENA */
+
+/*
+ * R1040 (0x410) - Out Volume 1L
+ */
+#define WM5100_OUT_RATE_MASK                    0xC000  /* OUT_RATE - [15:14] */
+#define WM5100_OUT_RATE_SHIFT                       14  /* OUT_RATE - [15:14] */
+#define WM5100_OUT_RATE_WIDTH                        2  /* OUT_RATE - [15:14] */
+#define WM5100_OUT1_OSR                         0x2000  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_MASK                    0x2000  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_SHIFT                       13  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_WIDTH                        1  /* OUT1_OSR */
+#define WM5100_OUT1_MONO                        0x1000  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_MASK                   0x1000  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_SHIFT                      12  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_WIDTH                       1  /* OUT1_MONO */
+#define WM5100_OUT1L_ANC_SRC                    0x0800  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_MASK               0x0800  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_SHIFT                  11  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_WIDTH                   1  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_PGA_VOL_MASK               0x00FE  /* OUT1L_PGA_VOL - [7:1] */
+#define WM5100_OUT1L_PGA_VOL_SHIFT                   1  /* OUT1L_PGA_VOL - [7:1] */
+#define WM5100_OUT1L_PGA_VOL_WIDTH                   7  /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1041 (0x411) - Out Volume 1R
+ */
+#define WM5100_OUT1R_ANC_SRC                    0x0800  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_MASK               0x0800  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_SHIFT                  11  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_WIDTH                   1  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_PGA_VOL_MASK               0x00FE  /* OUT1R_PGA_VOL - [7:1] */
+#define WM5100_OUT1R_PGA_VOL_SHIFT                   1  /* OUT1R_PGA_VOL - [7:1] */
+#define WM5100_OUT1R_PGA_VOL_WIDTH                   7  /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1042 (0x412) - DAC Volume Limit 1L
+ */
+#define WM5100_OUT1L_VOL_LIM_MASK               0x00FF  /* OUT1L_VOL_LIM - [7:0] */
+#define WM5100_OUT1L_VOL_LIM_SHIFT                   0  /* OUT1L_VOL_LIM - [7:0] */
+#define WM5100_OUT1L_VOL_LIM_WIDTH                   8  /* OUT1L_VOL_LIM - [7:0] */
+
+/*
+ * R1043 (0x413) - DAC Volume Limit 1R
+ */
+#define WM5100_OUT1R_VOL_LIM_MASK               0x00FF  /* OUT1R_VOL_LIM - [7:0] */
+#define WM5100_OUT1R_VOL_LIM_SHIFT                   0  /* OUT1R_VOL_LIM - [7:0] */
+#define WM5100_OUT1R_VOL_LIM_WIDTH                   8  /* OUT1R_VOL_LIM - [7:0] */
+
+/*
+ * R1044 (0x414) - Out Volume 2L
+ */
+#define WM5100_OUT2_OSR                         0x2000  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_MASK                    0x2000  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_SHIFT                       13  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_WIDTH                        1  /* OUT2_OSR */
+#define WM5100_OUT2_MONO                        0x1000  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_MASK                   0x1000  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_SHIFT                      12  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_WIDTH                       1  /* OUT2_MONO */
+#define WM5100_OUT2L_ANC_SRC                    0x0800  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_MASK               0x0800  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_SHIFT                  11  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_WIDTH                   1  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_PGA_VOL_MASK               0x00FE  /* OUT2L_PGA_VOL - [7:1] */
+#define WM5100_OUT2L_PGA_VOL_SHIFT                   1  /* OUT2L_PGA_VOL - [7:1] */
+#define WM5100_OUT2L_PGA_VOL_WIDTH                   7  /* OUT2L_PGA_VOL - [7:1] */
+
+/*
+ * R1045 (0x415) - Out Volume 2R
+ */
+#define WM5100_OUT2R_ANC_SRC                    0x0800  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_MASK               0x0800  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_SHIFT                  11  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_WIDTH                   1  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_PGA_VOL_MASK               0x00FE  /* OUT2R_PGA_VOL - [7:1] */
+#define WM5100_OUT2R_PGA_VOL_SHIFT                   1  /* OUT2R_PGA_VOL - [7:1] */
+#define WM5100_OUT2R_PGA_VOL_WIDTH                   7  /* OUT2R_PGA_VOL - [7:1] */
+
+/*
+ * R1046 (0x416) - DAC Volume Limit 2L
+ */
+#define WM5100_OUT2L_VOL_LIM_MASK               0x00FF  /* OUT2L_VOL_LIM - [7:0] */
+#define WM5100_OUT2L_VOL_LIM_SHIFT                   0  /* OUT2L_VOL_LIM - [7:0] */
+#define WM5100_OUT2L_VOL_LIM_WIDTH                   8  /* OUT2L_VOL_LIM - [7:0] */
+
+/*
+ * R1047 (0x417) - DAC Volume Limit 2R
+ */
+#define WM5100_OUT2R_VOL_LIM_MASK               0x00FF  /* OUT2R_VOL_LIM - [7:0] */
+#define WM5100_OUT2R_VOL_LIM_SHIFT                   0  /* OUT2R_VOL_LIM - [7:0] */
+#define WM5100_OUT2R_VOL_LIM_WIDTH                   8  /* OUT2R_VOL_LIM - [7:0] */
+
+/*
+ * R1048 (0x418) - Out Volume 3L
+ */
+#define WM5100_OUT3_OSR                         0x2000  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_MASK                    0x2000  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_SHIFT                       13  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_WIDTH                        1  /* OUT3_OSR */
+#define WM5100_OUT3_MONO                        0x1000  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_MASK                   0x1000  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_SHIFT                      12  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_WIDTH                       1  /* OUT3_MONO */
+#define WM5100_OUT3L_ANC_SRC                    0x0800  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_MASK               0x0800  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_SHIFT                  11  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_WIDTH                   1  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_PGA_VOL_MASK               0x00FE  /* OUT3L_PGA_VOL - [7:1] */
+#define WM5100_OUT3L_PGA_VOL_SHIFT                   1  /* OUT3L_PGA_VOL - [7:1] */
+#define WM5100_OUT3L_PGA_VOL_WIDTH                   7  /* OUT3L_PGA_VOL - [7:1] */
+
+/*
+ * R1049 (0x419) - Out Volume 3R
+ */
+#define WM5100_OUT3R_ANC_SRC                    0x0800  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_MASK               0x0800  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_SHIFT                  11  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_WIDTH                   1  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_PGA_VOL_MASK               0x00FE  /* OUT3R_PGA_VOL - [7:1] */
+#define WM5100_OUT3R_PGA_VOL_SHIFT                   1  /* OUT3R_PGA_VOL - [7:1] */
+#define WM5100_OUT3R_PGA_VOL_WIDTH                   7  /* OUT3R_PGA_VOL - [7:1] */
+
+/*
+ * R1050 (0x41A) - DAC Volume Limit 3L
+ */
+#define WM5100_OUT3L_VOL_LIM_MASK               0x00FF  /* OUT3L_VOL_LIM - [7:0] */
+#define WM5100_OUT3L_VOL_LIM_SHIFT                   0  /* OUT3L_VOL_LIM - [7:0] */
+#define WM5100_OUT3L_VOL_LIM_WIDTH                   8  /* OUT3L_VOL_LIM - [7:0] */
+
+/*
+ * R1051 (0x41B) - DAC Volume Limit 3R
+ */
+#define WM5100_OUT3R_VOL_LIM_MASK               0x00FF  /* OUT3R_VOL_LIM - [7:0] */
+#define WM5100_OUT3R_VOL_LIM_SHIFT                   0  /* OUT3R_VOL_LIM - [7:0] */
+#define WM5100_OUT3R_VOL_LIM_WIDTH                   8  /* OUT3R_VOL_LIM - [7:0] */
+
+/*
+ * R1052 (0x41C) - Out Volume 4L
+ */
+#define WM5100_OUT4_OSR                         0x2000  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_MASK                    0x2000  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_SHIFT                       13  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_WIDTH                        1  /* OUT4_OSR */
+#define WM5100_OUT4L_ANC_SRC                    0x0800  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_MASK               0x0800  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_SHIFT                  11  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_WIDTH                   1  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_VOL_LIM_MASK               0x00FF  /* OUT4L_VOL_LIM - [7:0] */
+#define WM5100_OUT4L_VOL_LIM_SHIFT                   0  /* OUT4L_VOL_LIM - [7:0] */
+#define WM5100_OUT4L_VOL_LIM_WIDTH                   8  /* OUT4L_VOL_LIM - [7:0] */
+
+/*
+ * R1053 (0x41D) - Out Volume 4R
+ */
+#define WM5100_OUT4R_ANC_SRC                    0x0800  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_MASK               0x0800  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_SHIFT                  11  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_WIDTH                   1  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_VOL_LIM_MASK               0x00FF  /* OUT4R_VOL_LIM - [7:0] */
+#define WM5100_OUT4R_VOL_LIM_SHIFT                   0  /* OUT4R_VOL_LIM - [7:0] */
+#define WM5100_OUT4R_VOL_LIM_WIDTH                   8  /* OUT4R_VOL_LIM - [7:0] */
+
+/*
+ * R1054 (0x41E) - DAC Volume Limit 5L
+ */
+#define WM5100_OUT5_OSR                         0x2000  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_MASK                    0x2000  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_SHIFT                       13  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_WIDTH                        1  /* OUT5_OSR */
+#define WM5100_OUT5L_ANC_SRC                    0x0800  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_MASK               0x0800  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_SHIFT                  11  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_WIDTH                   1  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_VOL_LIM_MASK               0x00FF  /* OUT5L_VOL_LIM - [7:0] */
+#define WM5100_OUT5L_VOL_LIM_SHIFT                   0  /* OUT5L_VOL_LIM - [7:0] */
+#define WM5100_OUT5L_VOL_LIM_WIDTH                   8  /* OUT5L_VOL_LIM - [7:0] */
+
+/*
+ * R1055 (0x41F) - DAC Volume Limit 5R
+ */
+#define WM5100_OUT5R_ANC_SRC                    0x0800  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_MASK               0x0800  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_SHIFT                  11  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_WIDTH                   1  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_VOL_LIM_MASK               0x00FF  /* OUT5R_VOL_LIM - [7:0] */
+#define WM5100_OUT5R_VOL_LIM_SHIFT                   0  /* OUT5R_VOL_LIM - [7:0] */
+#define WM5100_OUT5R_VOL_LIM_WIDTH                   8  /* OUT5R_VOL_LIM - [7:0] */
+
+/*
+ * R1056 (0x420) - DAC Volume Limit 6L
+ */
+#define WM5100_OUT6_OSR                         0x2000  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_MASK                    0x2000  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_SHIFT                       13  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_WIDTH                        1  /* OUT6_OSR */
+#define WM5100_OUT6L_ANC_SRC                    0x0800  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_MASK               0x0800  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_SHIFT                  11  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_WIDTH                   1  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_VOL_LIM_MASK               0x00FF  /* OUT6L_VOL_LIM - [7:0] */
+#define WM5100_OUT6L_VOL_LIM_SHIFT                   0  /* OUT6L_VOL_LIM - [7:0] */
+#define WM5100_OUT6L_VOL_LIM_WIDTH                   8  /* OUT6L_VOL_LIM - [7:0] */
+
+/*
+ * R1057 (0x421) - DAC Volume Limit 6R
+ */
+#define WM5100_OUT6R_ANC_SRC                    0x0800  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_MASK               0x0800  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_SHIFT                  11  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_WIDTH                   1  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_VOL_LIM_MASK               0x00FF  /* OUT6R_VOL_LIM - [7:0] */
+#define WM5100_OUT6R_VOL_LIM_SHIFT                   0  /* OUT6R_VOL_LIM - [7:0] */
+#define WM5100_OUT6R_VOL_LIM_WIDTH                   8  /* OUT6R_VOL_LIM - [7:0] */
+
+/*
+ * R1088 (0x440) - DAC AEC Control 1
+ */
+#define WM5100_AEC_LOOPBACK_SRC_MASK            0x003C  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_LOOPBACK_SRC_SHIFT                2  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_LOOPBACK_SRC_WIDTH                4  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_ENA_STS                      0x0002  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_MASK                 0x0002  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_SHIFT                     1  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_WIDTH                     1  /* AEC_ENA_STS */
+#define WM5100_AEC_LOOPBACK_ENA                 0x0001  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_MASK            0x0001  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_SHIFT                0  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_WIDTH                1  /* AEC_LOOPBACK_ENA */
+
+/*
+ * R1089 (0x441) - Output Volume Ramp
+ */
+#define WM5100_OUT_VD_RAMP_MASK                 0x0070  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VD_RAMP_SHIFT                     4  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VD_RAMP_WIDTH                     3  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VI_RAMP_MASK                 0x0007  /* OUT_VI_RAMP - [2:0] */
+#define WM5100_OUT_VI_RAMP_SHIFT                     0  /* OUT_VI_RAMP - [2:0] */
+#define WM5100_OUT_VI_RAMP_WIDTH                     3  /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1152 (0x480) - DAC Digital Volume 1L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT1L_MUTE                       0x0100  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_MASK                  0x0100  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_SHIFT                      8  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_WIDTH                      1  /* OUT1L_MUTE */
+#define WM5100_OUT1L_VOL_MASK                   0x00FF  /* OUT1L_VOL - [7:0] */
+#define WM5100_OUT1L_VOL_SHIFT                       0  /* OUT1L_VOL - [7:0] */
+#define WM5100_OUT1L_VOL_WIDTH                       8  /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1153 (0x481) - DAC Digital Volume 1R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT1R_MUTE                       0x0100  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_MASK                  0x0100  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_SHIFT                      8  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_WIDTH                      1  /* OUT1R_MUTE */
+#define WM5100_OUT1R_VOL_MASK                   0x00FF  /* OUT1R_VOL - [7:0] */
+#define WM5100_OUT1R_VOL_SHIFT                       0  /* OUT1R_VOL - [7:0] */
+#define WM5100_OUT1R_VOL_WIDTH                       8  /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1154 (0x482) - DAC Digital Volume 2L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT2L_MUTE                       0x0100  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_MASK                  0x0100  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_SHIFT                      8  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_WIDTH                      1  /* OUT2L_MUTE */
+#define WM5100_OUT2L_VOL_MASK                   0x00FF  /* OUT2L_VOL - [7:0] */
+#define WM5100_OUT2L_VOL_SHIFT                       0  /* OUT2L_VOL - [7:0] */
+#define WM5100_OUT2L_VOL_WIDTH                       8  /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1155 (0x483) - DAC Digital Volume 2R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT2R_MUTE                       0x0100  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_MASK                  0x0100  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_SHIFT                      8  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_WIDTH                      1  /* OUT2R_MUTE */
+#define WM5100_OUT2R_VOL_MASK                   0x00FF  /* OUT2R_VOL - [7:0] */
+#define WM5100_OUT2R_VOL_SHIFT                       0  /* OUT2R_VOL - [7:0] */
+#define WM5100_OUT2R_VOL_WIDTH                       8  /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1156 (0x484) - DAC Digital Volume 3L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT3L_MUTE                       0x0100  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_MASK                  0x0100  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_SHIFT                      8  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_WIDTH                      1  /* OUT3L_MUTE */
+#define WM5100_OUT3L_VOL_MASK                   0x00FF  /* OUT3L_VOL - [7:0] */
+#define WM5100_OUT3L_VOL_SHIFT                       0  /* OUT3L_VOL - [7:0] */
+#define WM5100_OUT3L_VOL_WIDTH                       8  /* OUT3L_VOL - [7:0] */
+
+/*
+ * R1157 (0x485) - DAC Digital Volume 3R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT3R_MUTE                       0x0100  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_MASK                  0x0100  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_SHIFT                      8  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_WIDTH                      1  /* OUT3R_MUTE */
+#define WM5100_OUT3R_VOL_MASK                   0x00FF  /* OUT3R_VOL - [7:0] */
+#define WM5100_OUT3R_VOL_SHIFT                       0  /* OUT3R_VOL - [7:0] */
+#define WM5100_OUT3R_VOL_WIDTH                       8  /* OUT3R_VOL - [7:0] */
+
+/*
+ * R1158 (0x486) - DAC Digital Volume 4L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT4L_MUTE                       0x0100  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_MASK                  0x0100  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_SHIFT                      8  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_WIDTH                      1  /* OUT4L_MUTE */
+#define WM5100_OUT4L_VOL_MASK                   0x00FF  /* OUT4L_VOL - [7:0] */
+#define WM5100_OUT4L_VOL_SHIFT                       0  /* OUT4L_VOL - [7:0] */
+#define WM5100_OUT4L_VOL_WIDTH                       8  /* OUT4L_VOL - [7:0] */
+
+/*
+ * R1159 (0x487) - DAC Digital Volume 4R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT4R_MUTE                       0x0100  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_MASK                  0x0100  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_SHIFT                      8  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_WIDTH                      1  /* OUT4R_MUTE */
+#define WM5100_OUT4R_VOL_MASK                   0x00FF  /* OUT4R_VOL - [7:0] */
+#define WM5100_OUT4R_VOL_SHIFT                       0  /* OUT4R_VOL - [7:0] */
+#define WM5100_OUT4R_VOL_WIDTH                       8  /* OUT4R_VOL - [7:0] */
+
+/*
+ * R1160 (0x488) - DAC Digital Volume 5L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT5L_MUTE                       0x0100  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_MASK                  0x0100  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_SHIFT                      8  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_WIDTH                      1  /* OUT5L_MUTE */
+#define WM5100_OUT5L_VOL_MASK                   0x00FF  /* OUT5L_VOL - [7:0] */
+#define WM5100_OUT5L_VOL_SHIFT                       0  /* OUT5L_VOL - [7:0] */
+#define WM5100_OUT5L_VOL_WIDTH                       8  /* OUT5L_VOL - [7:0] */
+
+/*
+ * R1161 (0x489) - DAC Digital Volume 5R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT5R_MUTE                       0x0100  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_MASK                  0x0100  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_SHIFT                      8  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_WIDTH                      1  /* OUT5R_MUTE */
+#define WM5100_OUT5R_VOL_MASK                   0x00FF  /* OUT5R_VOL - [7:0] */
+#define WM5100_OUT5R_VOL_SHIFT                       0  /* OUT5R_VOL - [7:0] */
+#define WM5100_OUT5R_VOL_WIDTH                       8  /* OUT5R_VOL - [7:0] */
+
+/*
+ * R1162 (0x48A) - DAC Digital Volume 6L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT6L_MUTE                       0x0100  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_MASK                  0x0100  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_SHIFT                      8  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_WIDTH                      1  /* OUT6L_MUTE */
+#define WM5100_OUT6L_VOL_MASK                   0x00FF  /* OUT6L_VOL - [7:0] */
+#define WM5100_OUT6L_VOL_SHIFT                       0  /* OUT6L_VOL - [7:0] */
+#define WM5100_OUT6L_VOL_WIDTH                       8  /* OUT6L_VOL - [7:0] */
+
+/*
+ * R1163 (0x48B) - DAC Digital Volume 6R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT6R_MUTE                       0x0100  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_MASK                  0x0100  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_SHIFT                      8  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_WIDTH                      1  /* OUT6R_MUTE */
+#define WM5100_OUT6R_VOL_MASK                   0x00FF  /* OUT6R_VOL - [7:0] */
+#define WM5100_OUT6R_VOL_SHIFT                       0  /* OUT6R_VOL - [7:0] */
+#define WM5100_OUT6R_VOL_WIDTH                       8  /* OUT6R_VOL - [7:0] */
+
+/*
+ * R1216 (0x4C0) - PDM SPK1 CTRL 1
+ */
+#define WM5100_SPK1R_MUTE                       0x2000  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_MASK                  0x2000  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_SHIFT                     13  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_WIDTH                      1  /* SPK1R_MUTE */
+#define WM5100_SPK1L_MUTE                       0x1000  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_MASK                  0x1000  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_SHIFT                     12  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_WIDTH                      1  /* SPK1L_MUTE */
+#define WM5100_SPK1_MUTE_ENDIAN                 0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_MASK            0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_SHIFT                8  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_WIDTH                1  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_SEQ1_MASK              0x00FF  /* SPK1_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK1_MUTE_SEQ1_SHIFT                  0  /* SPK1_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK1_MUTE_SEQ1_WIDTH                  8  /* SPK1_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R1217 (0x4C1) - PDM SPK1 CTRL 2
+ */
+#define WM5100_SPK1_FMT                         0x0001  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_MASK                    0x0001  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_SHIFT                        0  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_WIDTH                        1  /* SPK1_FMT */
+
+/*
+ * R1218 (0x4C2) - PDM SPK2 CTRL 1
+ */
+#define WM5100_SPK2R_MUTE                       0x2000  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_MASK                  0x2000  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_SHIFT                     13  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_WIDTH                      1  /* SPK2R_MUTE */
+#define WM5100_SPK2L_MUTE                       0x1000  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_MASK                  0x1000  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_SHIFT                     12  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_WIDTH                      1  /* SPK2L_MUTE */
+#define WM5100_SPK2_MUTE_ENDIAN                 0x0100  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_MASK            0x0100  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_SHIFT                8  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_WIDTH                1  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_SEQ1_MASK              0x00FF  /* SPK2_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK2_MUTE_SEQ1_SHIFT                  0  /* SPK2_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK2_MUTE_SEQ1_WIDTH                  8  /* SPK2_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R1219 (0x4C3) - PDM SPK2 CTRL 2
+ */
+#define WM5100_SPK2_FMT                         0x0001  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_MASK                    0x0001  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_SHIFT                        0  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_WIDTH                        1  /* SPK2_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM5100_AIF1_BCLK_INV                    0x0080  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_MASK               0x0080  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_SHIFT                   7  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_WIDTH                   1  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_FRC                    0x0040  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_MASK               0x0040  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_SHIFT                   6  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_WIDTH                   1  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_MSTR                   0x0020  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_MASK              0x0020  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_SHIFT                  5  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_WIDTH                  1  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_FREQ_MASK              0x001F  /* AIF1_BCLK_FREQ - [4:0] */
+#define WM5100_AIF1_BCLK_FREQ_SHIFT                  0  /* AIF1_BCLK_FREQ - [4:0] */
+#define WM5100_AIF1_BCLK_FREQ_WIDTH                  5  /* AIF1_BCLK_FREQ - [4:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM5100_AIF1TX_DAT_TRI                   0x0020  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_MASK              0x0020  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_SHIFT                  5  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_WIDTH                  1  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_LRCLK_SRC                 0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_MASK            0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_SHIFT                3  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_WIDTH                1  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_INV                 0x0004  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_MASK            0x0004  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_SHIFT                2  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_WIDTH                1  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_FRC                 0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_MASK            0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_SHIFT                1  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_WIDTH                1  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_MSTR                0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_MASK           0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_SHIFT               0  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_WIDTH               1  /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM5100_AIF1RX_LRCLK_INV                 0x0004  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_MASK            0x0004  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_SHIFT                2  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_WIDTH                1  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_FRC                 0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_MASK            0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_SHIFT                1  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_WIDTH                1  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_MSTR                0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_MASK           0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_SHIFT               0  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_WIDTH               1  /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM5100_AIF1_TRI                         0x0040  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_MASK                    0x0040  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_SHIFT                        6  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_WIDTH                        1  /* AIF1_TRI */
+#define WM5100_AIF1_RATE_MASK                   0x0003  /* AIF1_RATE - [1:0] */
+#define WM5100_AIF1_RATE_SHIFT                       0  /* AIF1_RATE - [1:0] */
+#define WM5100_AIF1_RATE_WIDTH                       2  /* AIF1_RATE - [1:0] */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM5100_AIF1_FMT_MASK                    0x0007  /* AIF1_FMT - [2:0] */
+#define WM5100_AIF1_FMT_SHIFT                        0  /* AIF1_FMT - [2:0] */
+#define WM5100_AIF1_FMT_WIDTH                        3  /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM5100_AIF1TX_BCPF_MASK                 0x1FFF  /* AIF1TX_BCPF - [12:0] */
+#define WM5100_AIF1TX_BCPF_SHIFT                     0  /* AIF1TX_BCPF - [12:0] */
+#define WM5100_AIF1TX_BCPF_WIDTH                    13  /* AIF1TX_BCPF - [12:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM5100_AIF1RX_BCPF_MASK                 0x1FFF  /* AIF1RX_BCPF - [12:0] */
+#define WM5100_AIF1RX_BCPF_SHIFT                     0  /* AIF1RX_BCPF - [12:0] */
+#define WM5100_AIF1RX_BCPF_WIDTH                    13  /* AIF1RX_BCPF - [12:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM5100_AIF1TX_WL_MASK                   0x3F00  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_WL_SHIFT                       8  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_WL_WIDTH                       6  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_SLOT_LEN_MASK             0x00FF  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1TX_SLOT_LEN_SHIFT                 0  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1TX_SLOT_LEN_WIDTH                 8  /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM5100_AIF1RX_WL_MASK                   0x3F00  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_WL_SHIFT                       8  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_WL_WIDTH                       6  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_SLOT_LEN_MASK             0x00FF  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1RX_SLOT_LEN_SHIFT                 0  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1RX_SLOT_LEN_WIDTH                 8  /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM5100_AIF1TX1_SLOT_MASK                0x003F  /* AIF1TX1_SLOT - [5:0] */
+#define WM5100_AIF1TX1_SLOT_SHIFT                    0  /* AIF1TX1_SLOT - [5:0] */
+#define WM5100_AIF1TX1_SLOT_WIDTH                    6  /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM5100_AIF1TX2_SLOT_MASK                0x003F  /* AIF1TX2_SLOT - [5:0] */
+#define WM5100_AIF1TX2_SLOT_SHIFT                    0  /* AIF1TX2_SLOT - [5:0] */
+#define WM5100_AIF1TX2_SLOT_WIDTH                    6  /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM5100_AIF1TX3_SLOT_MASK                0x003F  /* AIF1TX3_SLOT - [5:0] */
+#define WM5100_AIF1TX3_SLOT_SHIFT                    0  /* AIF1TX3_SLOT - [5:0] */
+#define WM5100_AIF1TX3_SLOT_WIDTH                    6  /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM5100_AIF1TX4_SLOT_MASK                0x003F  /* AIF1TX4_SLOT - [5:0] */
+#define WM5100_AIF1TX4_SLOT_SHIFT                    0  /* AIF1TX4_SLOT - [5:0] */
+#define WM5100_AIF1TX4_SLOT_WIDTH                    6  /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM5100_AIF1TX5_SLOT_MASK                0x003F  /* AIF1TX5_SLOT - [5:0] */
+#define WM5100_AIF1TX5_SLOT_SHIFT                    0  /* AIF1TX5_SLOT - [5:0] */
+#define WM5100_AIF1TX5_SLOT_WIDTH                    6  /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM5100_AIF1TX6_SLOT_MASK                0x003F  /* AIF1TX6_SLOT - [5:0] */
+#define WM5100_AIF1TX6_SLOT_SHIFT                    0  /* AIF1TX6_SLOT - [5:0] */
+#define WM5100_AIF1TX6_SLOT_WIDTH                    6  /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM5100_AIF1TX7_SLOT_MASK                0x003F  /* AIF1TX7_SLOT - [5:0] */
+#define WM5100_AIF1TX7_SLOT_SHIFT                    0  /* AIF1TX7_SLOT - [5:0] */
+#define WM5100_AIF1TX7_SLOT_WIDTH                    6  /* AIF1TX7_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM5100_AIF1TX8_SLOT_MASK                0x003F  /* AIF1TX8_SLOT - [5:0] */
+#define WM5100_AIF1TX8_SLOT_SHIFT                    0  /* AIF1TX8_SLOT - [5:0] */
+#define WM5100_AIF1TX8_SLOT_WIDTH                    6  /* AIF1TX8_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM5100_AIF1RX1_SLOT_MASK                0x003F  /* AIF1RX1_SLOT - [5:0] */
+#define WM5100_AIF1RX1_SLOT_SHIFT                    0  /* AIF1RX1_SLOT - [5:0] */
+#define WM5100_AIF1RX1_SLOT_WIDTH                    6  /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM5100_AIF1RX2_SLOT_MASK                0x003F  /* AIF1RX2_SLOT - [5:0] */
+#define WM5100_AIF1RX2_SLOT_SHIFT                    0  /* AIF1RX2_SLOT - [5:0] */
+#define WM5100_AIF1RX2_SLOT_WIDTH                    6  /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM5100_AIF1RX3_SLOT_MASK                0x003F  /* AIF1RX3_SLOT - [5:0] */
+#define WM5100_AIF1RX3_SLOT_SHIFT                    0  /* AIF1RX3_SLOT - [5:0] */
+#define WM5100_AIF1RX3_SLOT_WIDTH                    6  /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM5100_AIF1RX4_SLOT_MASK                0x003F  /* AIF1RX4_SLOT - [5:0] */
+#define WM5100_AIF1RX4_SLOT_SHIFT                    0  /* AIF1RX4_SLOT - [5:0] */
+#define WM5100_AIF1RX4_SLOT_WIDTH                    6  /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM5100_AIF1RX5_SLOT_MASK                0x003F  /* AIF1RX5_SLOT - [5:0] */
+#define WM5100_AIF1RX5_SLOT_SHIFT                    0  /* AIF1RX5_SLOT - [5:0] */
+#define WM5100_AIF1RX5_SLOT_WIDTH                    6  /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1302 (0x516) - Audio IF 1_23
+ */
+#define WM5100_AIF1RX6_SLOT_MASK                0x003F  /* AIF1RX6_SLOT - [5:0] */
+#define WM5100_AIF1RX6_SLOT_SHIFT                    0  /* AIF1RX6_SLOT - [5:0] */
+#define WM5100_AIF1RX6_SLOT_WIDTH                    6  /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1303 (0x517) - Audio IF 1_24
+ */
+#define WM5100_AIF1RX7_SLOT_MASK                0x003F  /* AIF1RX7_SLOT - [5:0] */
+#define WM5100_AIF1RX7_SLOT_SHIFT                    0  /* AIF1RX7_SLOT - [5:0] */
+#define WM5100_AIF1RX7_SLOT_WIDTH                    6  /* AIF1RX7_SLOT - [5:0] */
+
+/*
+ * R1304 (0x518) - Audio IF 1_25
+ */
+#define WM5100_AIF1RX8_SLOT_MASK                0x003F  /* AIF1RX8_SLOT - [5:0] */
+#define WM5100_AIF1RX8_SLOT_SHIFT                    0  /* AIF1RX8_SLOT - [5:0] */
+#define WM5100_AIF1RX8_SLOT_WIDTH                    6  /* AIF1RX8_SLOT - [5:0] */
+
+/*
+ * R1305 (0x519) - Audio IF 1_26
+ */
+#define WM5100_AIF1TX8_ENA                      0x0080  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_MASK                 0x0080  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_SHIFT                     7  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_WIDTH                     1  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX7_ENA                      0x0040  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_MASK                 0x0040  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_SHIFT                     6  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_WIDTH                     1  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX6_ENA                      0x0020  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_MASK                 0x0020  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_SHIFT                     5  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_WIDTH                     1  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX5_ENA                      0x0010  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_MASK                 0x0010  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_SHIFT                     4  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_WIDTH                     1  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX4_ENA                      0x0008  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_MASK                 0x0008  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_SHIFT                     3  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_WIDTH                     1  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX3_ENA                      0x0004  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_MASK                 0x0004  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_SHIFT                     2  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_WIDTH                     1  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX2_ENA                      0x0002  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_MASK                 0x0002  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_SHIFT                     1  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_WIDTH                     1  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX1_ENA                      0x0001  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_MASK                 0x0001  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_SHIFT                     0  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_WIDTH                     1  /* AIF1TX1_ENA */
+
+/*
+ * R1306 (0x51A) - Audio IF 1_27
+ */
+#define WM5100_AIF1RX8_ENA                      0x0080  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_MASK                 0x0080  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_SHIFT                     7  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_WIDTH                     1  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX7_ENA                      0x0040  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_MASK                 0x0040  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_SHIFT                     6  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_WIDTH                     1  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX6_ENA                      0x0020  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_MASK                 0x0020  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_SHIFT                     5  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_WIDTH                     1  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX5_ENA                      0x0010  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_MASK                 0x0010  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_SHIFT                     4  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_WIDTH                     1  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX4_ENA                      0x0008  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_MASK                 0x0008  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_SHIFT                     3  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_WIDTH                     1  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX3_ENA                      0x0004  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_MASK                 0x0004  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_SHIFT                     2  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_WIDTH                     1  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX2_ENA                      0x0002  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_MASK                 0x0002  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_SHIFT                     1  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_WIDTH                     1  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX1_ENA                      0x0001  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_MASK                 0x0001  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_SHIFT                     0  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_WIDTH                     1  /* AIF1RX1_ENA */
+
+/*
+ * R1344 (0x540) - Audio IF 2_1
+ */
+#define WM5100_AIF2_BCLK_INV                    0x0080  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_MASK               0x0080  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_SHIFT                   7  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_WIDTH                   1  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_FRC                    0x0040  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_MASK               0x0040  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_SHIFT                   6  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_WIDTH                   1  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_MSTR                   0x0020  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_MASK              0x0020  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_SHIFT                  5  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_WIDTH                  1  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_FREQ_MASK              0x001F  /* AIF2_BCLK_FREQ - [4:0] */
+#define WM5100_AIF2_BCLK_FREQ_SHIFT                  0  /* AIF2_BCLK_FREQ - [4:0] */
+#define WM5100_AIF2_BCLK_FREQ_WIDTH                  5  /* AIF2_BCLK_FREQ - [4:0] */
+
+/*
+ * R1345 (0x541) - Audio IF 2_2
+ */
+#define WM5100_AIF2TX_DAT_TRI                   0x0020  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_MASK              0x0020  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_SHIFT                  5  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_WIDTH                  1  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_LRCLK_SRC                 0x0008  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_MASK            0x0008  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_SHIFT                3  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_WIDTH                1  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_INV                 0x0004  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_MASK            0x0004  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_SHIFT                2  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_WIDTH                1  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_FRC                 0x0002  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_MASK            0x0002  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_SHIFT                1  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_WIDTH                1  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_MSTR                0x0001  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_MASK           0x0001  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_SHIFT               0  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_WIDTH               1  /* AIF2TX_LRCLK_MSTR */
+
+/*
+ * R1346 (0x542) - Audio IF 2_3
+ */
+#define WM5100_AIF2RX_LRCLK_INV                 0x0004  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_MASK            0x0004  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_SHIFT                2  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_WIDTH                1  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_FRC                 0x0002  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_MASK            0x0002  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_SHIFT                1  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_WIDTH                1  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_MSTR                0x0001  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_MASK           0x0001  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_SHIFT               0  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_WIDTH               1  /* AIF2RX_LRCLK_MSTR */
+
+/*
+ * R1347 (0x543) - Audio IF 2_4
+ */
+#define WM5100_AIF2_TRI                         0x0040  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_MASK                    0x0040  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_SHIFT                        6  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_WIDTH                        1  /* AIF2_TRI */
+#define WM5100_AIF2_RATE_MASK                   0x0003  /* AIF2_RATE - [1:0] */
+#define WM5100_AIF2_RATE_SHIFT                       0  /* AIF2_RATE - [1:0] */
+#define WM5100_AIF2_RATE_WIDTH                       2  /* AIF2_RATE - [1:0] */
+
+/*
+ * R1348 (0x544) - Audio IF 2_5
+ */
+#define WM5100_AIF2_FMT_MASK                    0x0007  /* AIF2_FMT - [2:0] */
+#define WM5100_AIF2_FMT_SHIFT                        0  /* AIF2_FMT - [2:0] */
+#define WM5100_AIF2_FMT_WIDTH                        3  /* AIF2_FMT - [2:0] */
+
+/*
+ * R1349 (0x545) - Audio IF 2_6
+ */
+#define WM5100_AIF2TX_BCPF_MASK                 0x1FFF  /* AIF2TX_BCPF - [12:0] */
+#define WM5100_AIF2TX_BCPF_SHIFT                     0  /* AIF2TX_BCPF - [12:0] */
+#define WM5100_AIF2TX_BCPF_WIDTH                    13  /* AIF2TX_BCPF - [12:0] */
+
+/*
+ * R1350 (0x546) - Audio IF 2_7
+ */
+#define WM5100_AIF2RX_BCPF_MASK                 0x1FFF  /* AIF2RX_BCPF - [12:0] */
+#define WM5100_AIF2RX_BCPF_SHIFT                     0  /* AIF2RX_BCPF - [12:0] */
+#define WM5100_AIF2RX_BCPF_WIDTH                    13  /* AIF2RX_BCPF - [12:0] */
+
+/*
+ * R1351 (0x547) - Audio IF 2_8
+ */
+#define WM5100_AIF2TX_WL_MASK                   0x3F00  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_WL_SHIFT                       8  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_WL_WIDTH                       6  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_SLOT_LEN_MASK             0x00FF  /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2TX_SLOT_LEN_SHIFT                 0  /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2TX_SLOT_LEN_WIDTH                 8  /* AIF2TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1352 (0x548) - Audio IF 2_9
+ */
+#define WM5100_AIF2RX_WL_MASK                   0x3F00  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_WL_SHIFT                       8  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_WL_WIDTH                       6  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_SLOT_LEN_MASK             0x00FF  /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2RX_SLOT_LEN_SHIFT                 0  /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2RX_SLOT_LEN_WIDTH                 8  /* AIF2RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1353 (0x549) - Audio IF 2_10
+ */
+#define WM5100_AIF2TX1_SLOT_MASK                0x003F  /* AIF2TX1_SLOT - [5:0] */
+#define WM5100_AIF2TX1_SLOT_SHIFT                    0  /* AIF2TX1_SLOT - [5:0] */
+#define WM5100_AIF2TX1_SLOT_WIDTH                    6  /* AIF2TX1_SLOT - [5:0] */
+
+/*
+ * R1354 (0x54A) - Audio IF 2_11
+ */
+#define WM5100_AIF2TX2_SLOT_MASK                0x003F  /* AIF2TX2_SLOT - [5:0] */
+#define WM5100_AIF2TX2_SLOT_SHIFT                    0  /* AIF2TX2_SLOT - [5:0] */
+#define WM5100_AIF2TX2_SLOT_WIDTH                    6  /* AIF2TX2_SLOT - [5:0] */
+
+/*
+ * R1361 (0x551) - Audio IF 2_18
+ */
+#define WM5100_AIF2RX1_SLOT_MASK                0x003F  /* AIF2RX1_SLOT - [5:0] */
+#define WM5100_AIF2RX1_SLOT_SHIFT                    0  /* AIF2RX1_SLOT - [5:0] */
+#define WM5100_AIF2RX1_SLOT_WIDTH                    6  /* AIF2RX1_SLOT - [5:0] */
+
+/*
+ * R1362 (0x552) - Audio IF 2_19
+ */
+#define WM5100_AIF2RX2_SLOT_MASK                0x003F  /* AIF2RX2_SLOT - [5:0] */
+#define WM5100_AIF2RX2_SLOT_SHIFT                    0  /* AIF2RX2_SLOT - [5:0] */
+#define WM5100_AIF2RX2_SLOT_WIDTH                    6  /* AIF2RX2_SLOT - [5:0] */
+
+/*
+ * R1369 (0x559) - Audio IF 2_26
+ */
+#define WM5100_AIF2TX2_ENA                      0x0002  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_MASK                 0x0002  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_SHIFT                     1  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_WIDTH                     1  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX1_ENA                      0x0001  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_MASK                 0x0001  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_SHIFT                     0  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_WIDTH                     1  /* AIF2TX1_ENA */
+
+/*
+ * R1370 (0x55A) - Audio IF 2_27
+ */
+#define WM5100_AIF2RX2_ENA                      0x0002  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_MASK                 0x0002  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_SHIFT                     1  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_WIDTH                     1  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX1_ENA                      0x0001  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_MASK                 0x0001  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_SHIFT                     0  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_WIDTH                     1  /* AIF2RX1_ENA */
+
+/*
+ * R1408 (0x580) - Audio IF 3_1
+ */
+#define WM5100_AIF3_BCLK_INV                    0x0080  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_MASK               0x0080  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_SHIFT                   7  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_WIDTH                   1  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_FRC                    0x0040  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_MASK               0x0040  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_SHIFT                   6  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_WIDTH                   1  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_MSTR                   0x0020  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_MASK              0x0020  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_SHIFT                  5  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_WIDTH                  1  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_FREQ_MASK              0x001F  /* AIF3_BCLK_FREQ - [4:0] */
+#define WM5100_AIF3_BCLK_FREQ_SHIFT                  0  /* AIF3_BCLK_FREQ - [4:0] */
+#define WM5100_AIF3_BCLK_FREQ_WIDTH                  5  /* AIF3_BCLK_FREQ - [4:0] */
+
+/*
+ * R1409 (0x581) - Audio IF 3_2
+ */
+#define WM5100_AIF3TX_DAT_TRI                   0x0020  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_MASK              0x0020  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_SHIFT                  5  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_WIDTH                  1  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_LRCLK_SRC                 0x0008  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_MASK            0x0008  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_SHIFT                3  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_WIDTH                1  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_INV                 0x0004  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_MASK            0x0004  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_SHIFT                2  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_WIDTH                1  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_FRC                 0x0002  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_MASK            0x0002  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_SHIFT                1  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_WIDTH                1  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_MSTR                0x0001  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_MASK           0x0001  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_SHIFT               0  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_WIDTH               1  /* AIF3TX_LRCLK_MSTR */
+
+/*
+ * R1410 (0x582) - Audio IF 3_3
+ */
+#define WM5100_AIF3RX_LRCLK_INV                 0x0004  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_MASK            0x0004  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_SHIFT                2  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_WIDTH                1  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_FRC                 0x0002  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_MASK            0x0002  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_SHIFT                1  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_WIDTH                1  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_MSTR                0x0001  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_MASK           0x0001  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_SHIFT               0  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_WIDTH               1  /* AIF3RX_LRCLK_MSTR */
+
+/*
+ * R1411 (0x583) - Audio IF 3_4
+ */
+#define WM5100_AIF3_TRI                         0x0040  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_MASK                    0x0040  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_SHIFT                        6  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_WIDTH                        1  /* AIF3_TRI */
+#define WM5100_AIF3_RATE_MASK                   0x0003  /* AIF3_RATE - [1:0] */
+#define WM5100_AIF3_RATE_SHIFT                       0  /* AIF3_RATE - [1:0] */
+#define WM5100_AIF3_RATE_WIDTH                       2  /* AIF3_RATE - [1:0] */
+
+/*
+ * R1412 (0x584) - Audio IF 3_5
+ */
+#define WM5100_AIF3_FMT_MASK                    0x0007  /* AIF3_FMT - [2:0] */
+#define WM5100_AIF3_FMT_SHIFT                        0  /* AIF3_FMT - [2:0] */
+#define WM5100_AIF3_FMT_WIDTH                        3  /* AIF3_FMT - [2:0] */
+
+/*
+ * R1413 (0x585) - Audio IF 3_6
+ */
+#define WM5100_AIF3TX_BCPF_MASK                 0x1FFF  /* AIF3TX_BCPF - [12:0] */
+#define WM5100_AIF3TX_BCPF_SHIFT                     0  /* AIF3TX_BCPF - [12:0] */
+#define WM5100_AIF3TX_BCPF_WIDTH                    13  /* AIF3TX_BCPF - [12:0] */
+
+/*
+ * R1414 (0x586) - Audio IF 3_7
+ */
+#define WM5100_AIF3RX_BCPF_MASK                 0x1FFF  /* AIF3RX_BCPF - [12:0] */
+#define WM5100_AIF3RX_BCPF_SHIFT                     0  /* AIF3RX_BCPF - [12:0] */
+#define WM5100_AIF3RX_BCPF_WIDTH                    13  /* AIF3RX_BCPF - [12:0] */
+
+/*
+ * R1415 (0x587) - Audio IF 3_8
+ */
+#define WM5100_AIF3TX_WL_MASK                   0x3F00  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_WL_SHIFT                       8  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_WL_WIDTH                       6  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_SLOT_LEN_MASK             0x00FF  /* AIF3TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3TX_SLOT_LEN_SHIFT                 0  /* AIF3TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3TX_SLOT_LEN_WIDTH                 8  /* AIF3TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1416 (0x588) - Audio IF 3_9
+ */
+#define WM5100_AIF3RX_WL_MASK                   0x3F00  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_WL_SHIFT                       8  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_WL_WIDTH                       6  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_SLOT_LEN_MASK             0x00FF  /* AIF3RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3RX_SLOT_LEN_SHIFT                 0  /* AIF3RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3RX_SLOT_LEN_WIDTH                 8  /* AIF3RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1417 (0x589) - Audio IF 3_10
+ */
+#define WM5100_AIF3TX1_SLOT_MASK                0x003F  /* AIF3TX1_SLOT - [5:0] */
+#define WM5100_AIF3TX1_SLOT_SHIFT                    0  /* AIF3TX1_SLOT - [5:0] */
+#define WM5100_AIF3TX1_SLOT_WIDTH                    6  /* AIF3TX1_SLOT - [5:0] */
+
+/*
+ * R1418 (0x58A) - Audio IF 3_11
+ */
+#define WM5100_AIF3TX2_SLOT_MASK                0x003F  /* AIF3TX2_SLOT - [5:0] */
+#define WM5100_AIF3TX2_SLOT_SHIFT                    0  /* AIF3TX2_SLOT - [5:0] */
+#define WM5100_AIF3TX2_SLOT_WIDTH                    6  /* AIF3TX2_SLOT - [5:0] */
+
+/*
+ * R1425 (0x591) - Audio IF 3_18
+ */
+#define WM5100_AIF3RX1_SLOT_MASK                0x003F  /* AIF3RX1_SLOT - [5:0] */
+#define WM5100_AIF3RX1_SLOT_SHIFT                    0  /* AIF3RX1_SLOT - [5:0] */
+#define WM5100_AIF3RX1_SLOT_WIDTH                    6  /* AIF3RX1_SLOT - [5:0] */
+
+/*
+ * R1426 (0x592) - Audio IF 3_19
+ */
+#define WM5100_AIF3RX2_SLOT_MASK                0x003F  /* AIF3RX2_SLOT - [5:0] */
+#define WM5100_AIF3RX2_SLOT_SHIFT                    0  /* AIF3RX2_SLOT - [5:0] */
+#define WM5100_AIF3RX2_SLOT_WIDTH                    6  /* AIF3RX2_SLOT - [5:0] */
+
+/*
+ * R1433 (0x599) - Audio IF 3_26
+ */
+#define WM5100_AIF3TX2_ENA                      0x0002  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_MASK                 0x0002  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_SHIFT                     1  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_WIDTH                     1  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX1_ENA                      0x0001  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_MASK                 0x0001  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_SHIFT                     0  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_WIDTH                     1  /* AIF3TX1_ENA */
+
+/*
+ * R1434 (0x59A) - Audio IF 3_27
+ */
+#define WM5100_AIF3RX2_ENA                      0x0002  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_MASK                 0x0002  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_SHIFT                     1  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_WIDTH                     1  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX1_ENA                      0x0001  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_MASK                 0x0001  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_SHIFT                     0  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_WIDTH                     1  /* AIF3RX1_ENA */
+
+#define WM5100_MIXER_VOL_MASK                0x00FE  /* MIXER_VOL - [7:1] */
+#define WM5100_MIXER_VOL_SHIFT                    1  /* MIXER_VOL - [7:1] */
+#define WM5100_MIXER_VOL_WIDTH                    7  /* MIXER_VOL - [7:1] */
+
+/*
+ * R3072 (0xC00) - GPIO CTRL 1
+ */
+#define WM5100_GP1_DIR                          0x8000  /* GP1_DIR */
+#define WM5100_GP1_DIR_MASK                     0x8000  /* GP1_DIR */
+#define WM5100_GP1_DIR_SHIFT                        15  /* GP1_DIR */
+#define WM5100_GP1_DIR_WIDTH                         1  /* GP1_DIR */
+#define WM5100_GP1_PU                           0x4000  /* GP1_PU */
+#define WM5100_GP1_PU_MASK                      0x4000  /* GP1_PU */
+#define WM5100_GP1_PU_SHIFT                         14  /* GP1_PU */
+#define WM5100_GP1_PU_WIDTH                          1  /* GP1_PU */
+#define WM5100_GP1_PD                           0x2000  /* GP1_PD */
+#define WM5100_GP1_PD_MASK                      0x2000  /* GP1_PD */
+#define WM5100_GP1_PD_SHIFT                         13  /* GP1_PD */
+#define WM5100_GP1_PD_WIDTH                          1  /* GP1_PD */
+#define WM5100_GP1_POL                          0x0400  /* GP1_POL */
+#define WM5100_GP1_POL_MASK                     0x0400  /* GP1_POL */
+#define WM5100_GP1_POL_SHIFT                        10  /* GP1_POL */
+#define WM5100_GP1_POL_WIDTH                         1  /* GP1_POL */
+#define WM5100_GP1_OP_CFG                       0x0200  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_MASK                  0x0200  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_SHIFT                      9  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_WIDTH                      1  /* GP1_OP_CFG */
+#define WM5100_GP1_DB                           0x0100  /* GP1_DB */
+#define WM5100_GP1_DB_MASK                      0x0100  /* GP1_DB */
+#define WM5100_GP1_DB_SHIFT                          8  /* GP1_DB */
+#define WM5100_GP1_DB_WIDTH                          1  /* GP1_DB */
+#define WM5100_GP1_LVL                          0x0040  /* GP1_LVL */
+#define WM5100_GP1_LVL_MASK                     0x0040  /* GP1_LVL */
+#define WM5100_GP1_LVL_SHIFT                         6  /* GP1_LVL */
+#define WM5100_GP1_LVL_WIDTH                         1  /* GP1_LVL */
+#define WM5100_GP1_FN_MASK                      0x003F  /* GP1_FN - [5:0] */
+#define WM5100_GP1_FN_SHIFT                          0  /* GP1_FN - [5:0] */
+#define WM5100_GP1_FN_WIDTH                          6  /* GP1_FN - [5:0] */
+
+/*
+ * R3073 (0xC01) - GPIO CTRL 2
+ */
+#define WM5100_GP2_DIR                          0x8000  /* GP2_DIR */
+#define WM5100_GP2_DIR_MASK                     0x8000  /* GP2_DIR */
+#define WM5100_GP2_DIR_SHIFT                        15  /* GP2_DIR */
+#define WM5100_GP2_DIR_WIDTH                         1  /* GP2_DIR */
+#define WM5100_GP2_PU                           0x4000  /* GP2_PU */
+#define WM5100_GP2_PU_MASK                      0x4000  /* GP2_PU */
+#define WM5100_GP2_PU_SHIFT                         14  /* GP2_PU */
+#define WM5100_GP2_PU_WIDTH                          1  /* GP2_PU */
+#define WM5100_GP2_PD                           0x2000  /* GP2_PD */
+#define WM5100_GP2_PD_MASK                      0x2000  /* GP2_PD */
+#define WM5100_GP2_PD_SHIFT                         13  /* GP2_PD */
+#define WM5100_GP2_PD_WIDTH                          1  /* GP2_PD */
+#define WM5100_GP2_POL                          0x0400  /* GP2_POL */
+#define WM5100_GP2_POL_MASK                     0x0400  /* GP2_POL */
+#define WM5100_GP2_POL_SHIFT                        10  /* GP2_POL */
+#define WM5100_GP2_POL_WIDTH                         1  /* GP2_POL */
+#define WM5100_GP2_OP_CFG                       0x0200  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_MASK                  0x0200  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_SHIFT                      9  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_WIDTH                      1  /* GP2_OP_CFG */
+#define WM5100_GP2_DB                           0x0100  /* GP2_DB */
+#define WM5100_GP2_DB_MASK                      0x0100  /* GP2_DB */
+#define WM5100_GP2_DB_SHIFT                          8  /* GP2_DB */
+#define WM5100_GP2_DB_WIDTH                          1  /* GP2_DB */
+#define WM5100_GP2_LVL                          0x0040  /* GP2_LVL */
+#define WM5100_GP2_LVL_MASK                     0x0040  /* GP2_LVL */
+#define WM5100_GP2_LVL_SHIFT                         6  /* GP2_LVL */
+#define WM5100_GP2_LVL_WIDTH                         1  /* GP2_LVL */
+#define WM5100_GP2_FN_MASK                      0x003F  /* GP2_FN - [5:0] */
+#define WM5100_GP2_FN_SHIFT                          0  /* GP2_FN - [5:0] */
+#define WM5100_GP2_FN_WIDTH                          6  /* GP2_FN - [5:0] */
+
+/*
+ * R3074 (0xC02) - GPIO CTRL 3
+ */
+#define WM5100_GP3_DIR                          0x8000  /* GP3_DIR */
+#define WM5100_GP3_DIR_MASK                     0x8000  /* GP3_DIR */
+#define WM5100_GP3_DIR_SHIFT                        15  /* GP3_DIR */
+#define WM5100_GP3_DIR_WIDTH                         1  /* GP3_DIR */
+#define WM5100_GP3_PU                           0x4000  /* GP3_PU */
+#define WM5100_GP3_PU_MASK                      0x4000  /* GP3_PU */
+#define WM5100_GP3_PU_SHIFT                         14  /* GP3_PU */
+#define WM5100_GP3_PU_WIDTH                          1  /* GP3_PU */
+#define WM5100_GP3_PD                           0x2000  /* GP3_PD */
+#define WM5100_GP3_PD_MASK                      0x2000  /* GP3_PD */
+#define WM5100_GP3_PD_SHIFT                         13  /* GP3_PD */
+#define WM5100_GP3_PD_WIDTH                          1  /* GP3_PD */
+#define WM5100_GP3_POL                          0x0400  /* GP3_POL */
+#define WM5100_GP3_POL_MASK                     0x0400  /* GP3_POL */
+#define WM5100_GP3_POL_SHIFT                        10  /* GP3_POL */
+#define WM5100_GP3_POL_WIDTH                         1  /* GP3_POL */
+#define WM5100_GP3_OP_CFG                       0x0200  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_MASK                  0x0200  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_SHIFT                      9  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_WIDTH                      1  /* GP3_OP_CFG */
+#define WM5100_GP3_DB                           0x0100  /* GP3_DB */
+#define WM5100_GP3_DB_MASK                      0x0100  /* GP3_DB */
+#define WM5100_GP3_DB_SHIFT                          8  /* GP3_DB */
+#define WM5100_GP3_DB_WIDTH                          1  /* GP3_DB */
+#define WM5100_GP3_LVL                          0x0040  /* GP3_LVL */
+#define WM5100_GP3_LVL_MASK                     0x0040  /* GP3_LVL */
+#define WM5100_GP3_LVL_SHIFT                         6  /* GP3_LVL */
+#define WM5100_GP3_LVL_WIDTH                         1  /* GP3_LVL */
+#define WM5100_GP3_FN_MASK                      0x003F  /* GP3_FN - [5:0] */
+#define WM5100_GP3_FN_SHIFT                          0  /* GP3_FN - [5:0] */
+#define WM5100_GP3_FN_WIDTH                          6  /* GP3_FN - [5:0] */
+
+/*
+ * R3075 (0xC03) - GPIO CTRL 4
+ */
+#define WM5100_GP4_DIR                          0x8000  /* GP4_DIR */
+#define WM5100_GP4_DIR_MASK                     0x8000  /* GP4_DIR */
+#define WM5100_GP4_DIR_SHIFT                        15  /* GP4_DIR */
+#define WM5100_GP4_DIR_WIDTH                         1  /* GP4_DIR */
+#define WM5100_GP4_PU                           0x4000  /* GP4_PU */
+#define WM5100_GP4_PU_MASK                      0x4000  /* GP4_PU */
+#define WM5100_GP4_PU_SHIFT                         14  /* GP4_PU */
+#define WM5100_GP4_PU_WIDTH                          1  /* GP4_PU */
+#define WM5100_GP4_PD                           0x2000  /* GP4_PD */
+#define WM5100_GP4_PD_MASK                      0x2000  /* GP4_PD */
+#define WM5100_GP4_PD_SHIFT                         13  /* GP4_PD */
+#define WM5100_GP4_PD_WIDTH                          1  /* GP4_PD */
+#define WM5100_GP4_POL                          0x0400  /* GP4_POL */
+#define WM5100_GP4_POL_MASK                     0x0400  /* GP4_POL */
+#define WM5100_GP4_POL_SHIFT                        10  /* GP4_POL */
+#define WM5100_GP4_POL_WIDTH                         1  /* GP4_POL */
+#define WM5100_GP4_OP_CFG                       0x0200  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_MASK                  0x0200  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_SHIFT                      9  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_WIDTH                      1  /* GP4_OP_CFG */
+#define WM5100_GP4_DB                           0x0100  /* GP4_DB */
+#define WM5100_GP4_DB_MASK                      0x0100  /* GP4_DB */
+#define WM5100_GP4_DB_SHIFT                          8  /* GP4_DB */
+#define WM5100_GP4_DB_WIDTH                          1  /* GP4_DB */
+#define WM5100_GP4_LVL                          0x0040  /* GP4_LVL */
+#define WM5100_GP4_LVL_MASK                     0x0040  /* GP4_LVL */
+#define WM5100_GP4_LVL_SHIFT                         6  /* GP4_LVL */
+#define WM5100_GP4_LVL_WIDTH                         1  /* GP4_LVL */
+#define WM5100_GP4_FN_MASK                      0x003F  /* GP4_FN - [5:0] */
+#define WM5100_GP4_FN_SHIFT                          0  /* GP4_FN - [5:0] */
+#define WM5100_GP4_FN_WIDTH                          6  /* GP4_FN - [5:0] */
+
+/*
+ * R3076 (0xC04) - GPIO CTRL 5
+ */
+#define WM5100_GP5_DIR                          0x8000  /* GP5_DIR */
+#define WM5100_GP5_DIR_MASK                     0x8000  /* GP5_DIR */
+#define WM5100_GP5_DIR_SHIFT                        15  /* GP5_DIR */
+#define WM5100_GP5_DIR_WIDTH                         1  /* GP5_DIR */
+#define WM5100_GP5_PU                           0x4000  /* GP5_PU */
+#define WM5100_GP5_PU_MASK                      0x4000  /* GP5_PU */
+#define WM5100_GP5_PU_SHIFT                         14  /* GP5_PU */
+#define WM5100_GP5_PU_WIDTH                          1  /* GP5_PU */
+#define WM5100_GP5_PD                           0x2000  /* GP5_PD */
+#define WM5100_GP5_PD_MASK                      0x2000  /* GP5_PD */
+#define WM5100_GP5_PD_SHIFT                         13  /* GP5_PD */
+#define WM5100_GP5_PD_WIDTH                          1  /* GP5_PD */
+#define WM5100_GP5_POL                          0x0400  /* GP5_POL */
+#define WM5100_GP5_POL_MASK                     0x0400  /* GP5_POL */
+#define WM5100_GP5_POL_SHIFT                        10  /* GP5_POL */
+#define WM5100_GP5_POL_WIDTH                         1  /* GP5_POL */
+#define WM5100_GP5_OP_CFG                       0x0200  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_MASK                  0x0200  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_SHIFT                      9  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_WIDTH                      1  /* GP5_OP_CFG */
+#define WM5100_GP5_DB                           0x0100  /* GP5_DB */
+#define WM5100_GP5_DB_MASK                      0x0100  /* GP5_DB */
+#define WM5100_GP5_DB_SHIFT                          8  /* GP5_DB */
+#define WM5100_GP5_DB_WIDTH                          1  /* GP5_DB */
+#define WM5100_GP5_LVL                          0x0040  /* GP5_LVL */
+#define WM5100_GP5_LVL_MASK                     0x0040  /* GP5_LVL */
+#define WM5100_GP5_LVL_SHIFT                         6  /* GP5_LVL */
+#define WM5100_GP5_LVL_WIDTH                         1  /* GP5_LVL */
+#define WM5100_GP5_FN_MASK                      0x003F  /* GP5_FN - [5:0] */
+#define WM5100_GP5_FN_SHIFT                          0  /* GP5_FN - [5:0] */
+#define WM5100_GP5_FN_WIDTH                          6  /* GP5_FN - [5:0] */
+
+/*
+ * R3077 (0xC05) - GPIO CTRL 6
+ */
+#define WM5100_GP6_DIR                          0x8000  /* GP6_DIR */
+#define WM5100_GP6_DIR_MASK                     0x8000  /* GP6_DIR */
+#define WM5100_GP6_DIR_SHIFT                        15  /* GP6_DIR */
+#define WM5100_GP6_DIR_WIDTH                         1  /* GP6_DIR */
+#define WM5100_GP6_PU                           0x4000  /* GP6_PU */
+#define WM5100_GP6_PU_MASK                      0x4000  /* GP6_PU */
+#define WM5100_GP6_PU_SHIFT                         14  /* GP6_PU */
+#define WM5100_GP6_PU_WIDTH                          1  /* GP6_PU */
+#define WM5100_GP6_PD                           0x2000  /* GP6_PD */
+#define WM5100_GP6_PD_MASK                      0x2000  /* GP6_PD */
+#define WM5100_GP6_PD_SHIFT                         13  /* GP6_PD */
+#define WM5100_GP6_PD_WIDTH                          1  /* GP6_PD */
+#define WM5100_GP6_POL                          0x0400  /* GP6_POL */
+#define WM5100_GP6_POL_MASK                     0x0400  /* GP6_POL */
+#define WM5100_GP6_POL_SHIFT                        10  /* GP6_POL */
+#define WM5100_GP6_POL_WIDTH                         1  /* GP6_POL */
+#define WM5100_GP6_OP_CFG                       0x0200  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_MASK                  0x0200  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_SHIFT                      9  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_WIDTH                      1  /* GP6_OP_CFG */
+#define WM5100_GP6_DB                           0x0100  /* GP6_DB */
+#define WM5100_GP6_DB_MASK                      0x0100  /* GP6_DB */
+#define WM5100_GP6_DB_SHIFT                          8  /* GP6_DB */
+#define WM5100_GP6_DB_WIDTH                          1  /* GP6_DB */
+#define WM5100_GP6_LVL                          0x0040  /* GP6_LVL */
+#define WM5100_GP6_LVL_MASK                     0x0040  /* GP6_LVL */
+#define WM5100_GP6_LVL_SHIFT                         6  /* GP6_LVL */
+#define WM5100_GP6_LVL_WIDTH                         1  /* GP6_LVL */
+#define WM5100_GP6_FN_MASK                      0x003F  /* GP6_FN - [5:0] */
+#define WM5100_GP6_FN_SHIFT                          0  /* GP6_FN - [5:0] */
+#define WM5100_GP6_FN_WIDTH                          6  /* GP6_FN - [5:0] */
+
+/*
+ * R3107 (0xC23) - Misc Pad Ctrl 1
+ */
+#define WM5100_LDO1ENA_PD                       0x8000  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_MASK                  0x8000  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_SHIFT                     15  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_WIDTH                      1  /* LDO1ENA_PD */
+#define WM5100_MCLK2_PD                         0x2000  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_MASK                    0x2000  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_SHIFT                       13  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_WIDTH                        1  /* MCLK2_PD */
+#define WM5100_MCLK1_PD                         0x1000  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_MASK                    0x1000  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_SHIFT                       12  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_WIDTH                        1  /* MCLK1_PD */
+#define WM5100_RESET_PU                         0x0002  /* RESET_PU */
+#define WM5100_RESET_PU_MASK                    0x0002  /* RESET_PU */
+#define WM5100_RESET_PU_SHIFT                        1  /* RESET_PU */
+#define WM5100_RESET_PU_WIDTH                        1  /* RESET_PU */
+#define WM5100_ADDR_PD                          0x0001  /* ADDR_PD */
+#define WM5100_ADDR_PD_MASK                     0x0001  /* ADDR_PD */
+#define WM5100_ADDR_PD_SHIFT                         0  /* ADDR_PD */
+#define WM5100_ADDR_PD_WIDTH                         1  /* ADDR_PD */
+
+/*
+ * R3108 (0xC24) - Misc Pad Ctrl 2
+ */
+#define WM5100_DMICDAT4_PD                      0x0008  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_MASK                 0x0008  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_SHIFT                     3  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_WIDTH                     1  /* DMICDAT4_PD */
+#define WM5100_DMICDAT3_PD                      0x0004  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_MASK                 0x0004  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_SHIFT                     2  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_WIDTH                     1  /* DMICDAT3_PD */
+#define WM5100_DMICDAT2_PD                      0x0002  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_MASK                 0x0002  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_SHIFT                     1  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_WIDTH                     1  /* DMICDAT2_PD */
+#define WM5100_DMICDAT1_PD                      0x0001  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_MASK                 0x0001  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_SHIFT                     0  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_WIDTH                     1  /* DMICDAT1_PD */
+
+/*
+ * R3109 (0xC25) - Misc Pad Ctrl 3
+ */
+#define WM5100_AIF1RXLRCLK_PU                   0x0020  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_MASK              0x0020  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_SHIFT                  5  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_WIDTH                  1  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PD                   0x0010  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_MASK              0x0010  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_SHIFT                  4  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_WIDTH                  1  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1BCLK_PU                      0x0008  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_MASK                 0x0008  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_SHIFT                     3  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_WIDTH                     1  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PD                      0x0004  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_MASK                 0x0004  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_SHIFT                     2  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_WIDTH                     1  /* AIF1BCLK_PD */
+#define WM5100_AIF1RXDAT_PU                     0x0002  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_MASK                0x0002  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_SHIFT                    1  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_WIDTH                    1  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PD                     0x0001  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_MASK                0x0001  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_SHIFT                    0  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_WIDTH                    1  /* AIF1RXDAT_PD */
+
+/*
+ * R3110 (0xC26) - Misc Pad Ctrl 4
+ */
+#define WM5100_AIF2RXLRCLK_PU                   0x0020  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_MASK              0x0020  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_SHIFT                  5  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_WIDTH                  1  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PD                   0x0010  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_MASK              0x0010  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_SHIFT                  4  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_WIDTH                  1  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2BCLK_PU                      0x0008  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_MASK                 0x0008  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_SHIFT                     3  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_WIDTH                     1  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PD                      0x0004  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_MASK                 0x0004  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_SHIFT                     2  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_WIDTH                     1  /* AIF2BCLK_PD */
+#define WM5100_AIF2RXDAT_PU                     0x0002  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_MASK                0x0002  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_SHIFT                    1  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_WIDTH                    1  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PD                     0x0001  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_MASK                0x0001  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_SHIFT                    0  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_WIDTH                    1  /* AIF2RXDAT_PD */
+
+/*
+ * R3111 (0xC27) - Misc Pad Ctrl 5
+ */
+#define WM5100_AIF3RXLRCLK_PU                   0x0020  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_MASK              0x0020  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_SHIFT                  5  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_WIDTH                  1  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PD                   0x0010  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_MASK              0x0010  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_SHIFT                  4  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_WIDTH                  1  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3BCLK_PU                      0x0008  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_MASK                 0x0008  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_SHIFT                     3  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_WIDTH                     1  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PD                      0x0004  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_MASK                 0x0004  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_SHIFT                     2  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_WIDTH                     1  /* AIF3BCLK_PD */
+#define WM5100_AIF3RXDAT_PU                     0x0002  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_MASK                0x0002  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_SHIFT                    1  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_WIDTH                    1  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PD                     0x0001  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_MASK                0x0001  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_SHIFT                    0  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_WIDTH                    1  /* AIF3RXDAT_PD */
+
+/*
+ * R3112 (0xC28) - Misc GPIO 1
+ */
+#define WM5100_OPCLK_SEL_MASK                   0x0003  /* OPCLK_SEL - [1:0] */
+#define WM5100_OPCLK_SEL_SHIFT                       0  /* OPCLK_SEL - [1:0] */
+#define WM5100_OPCLK_SEL_WIDTH                       2  /* OPCLK_SEL - [1:0] */
+
+/*
+ * R3328 (0xD00) - Interrupt Status 1
+ */
+#define WM5100_GP6_EINT                         0x0020  /* GP6_EINT */
+#define WM5100_GP6_EINT_MASK                    0x0020  /* GP6_EINT */
+#define WM5100_GP6_EINT_SHIFT                        5  /* GP6_EINT */
+#define WM5100_GP6_EINT_WIDTH                        1  /* GP6_EINT */
+#define WM5100_GP5_EINT                         0x0010  /* GP5_EINT */
+#define WM5100_GP5_EINT_MASK                    0x0010  /* GP5_EINT */
+#define WM5100_GP5_EINT_SHIFT                        4  /* GP5_EINT */
+#define WM5100_GP5_EINT_WIDTH                        1  /* GP5_EINT */
+#define WM5100_GP4_EINT                         0x0008  /* GP4_EINT */
+#define WM5100_GP4_EINT_MASK                    0x0008  /* GP4_EINT */
+#define WM5100_GP4_EINT_SHIFT                        3  /* GP4_EINT */
+#define WM5100_GP4_EINT_WIDTH                        1  /* GP4_EINT */
+#define WM5100_GP3_EINT                         0x0004  /* GP3_EINT */
+#define WM5100_GP3_EINT_MASK                    0x0004  /* GP3_EINT */
+#define WM5100_GP3_EINT_SHIFT                        2  /* GP3_EINT */
+#define WM5100_GP3_EINT_WIDTH                        1  /* GP3_EINT */
+#define WM5100_GP2_EINT                         0x0002  /* GP2_EINT */
+#define WM5100_GP2_EINT_MASK                    0x0002  /* GP2_EINT */
+#define WM5100_GP2_EINT_SHIFT                        1  /* GP2_EINT */
+#define WM5100_GP2_EINT_WIDTH                        1  /* GP2_EINT */
+#define WM5100_GP1_EINT                         0x0001  /* GP1_EINT */
+#define WM5100_GP1_EINT_MASK                    0x0001  /* GP1_EINT */
+#define WM5100_GP1_EINT_SHIFT                        0  /* GP1_EINT */
+#define WM5100_GP1_EINT_WIDTH                        1  /* GP1_EINT */
+
+/*
+ * R3329 (0xD01) - Interrupt Status 2
+ */
+#define WM5100_DSP_IRQ6_EINT                    0x0020  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_MASK               0x0020  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_SHIFT                   5  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_WIDTH                   1  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ5_EINT                    0x0010  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_MASK               0x0010  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_SHIFT                   4  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_WIDTH                   1  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ4_EINT                    0x0008  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_MASK               0x0008  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_SHIFT                   3  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_WIDTH                   1  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ3_EINT                    0x0004  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_MASK               0x0004  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_SHIFT                   2  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_WIDTH                   1  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ2_EINT                    0x0002  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_MASK               0x0002  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_SHIFT                   1  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_WIDTH                   1  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ1_EINT                    0x0001  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_MASK               0x0001  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_SHIFT                   0  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_WIDTH                   1  /* DSP_IRQ1_EINT */
+
+/*
+ * R3330 (0xD02) - Interrupt Status 3
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT           0x8000  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_MASK      0x8000  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_SHIFT         15  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_WIDTH          1  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT                0x4000  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_MASK           0x4000  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_SHIFT              14  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_WIDTH               1  /* SPK_SHUTDOWN_EINT */
+#define WM5100_HPDET_EINT                       0x2000  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_MASK                  0x2000  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_SHIFT                     13  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_WIDTH                      1  /* HPDET_EINT */
+#define WM5100_ACCDET_EINT                      0x1000  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_MASK                 0x1000  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_SHIFT                    12  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_WIDTH                     1  /* ACCDET_EINT */
+#define WM5100_DRC_SIG_DET_EINT                 0x0200  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_MASK            0x0200  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_SHIFT                9  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_WIDTH                1  /* DRC_SIG_DET_EINT */
+#define WM5100_ASRC2_LOCK_EINT                  0x0100  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_MASK             0x0100  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_SHIFT                 8  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_WIDTH                 1  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT                  0x0080  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_MASK             0x0080  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_SHIFT                 7  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_WIDTH                 1  /* ASRC1_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT                   0x0008  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_MASK              0x0008  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_SHIFT                  3  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_WIDTH                  1  /* FLL2_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT                   0x0004  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_MASK              0x0004  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_SHIFT                  2  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_WIDTH                  1  /* FLL1_LOCK_EINT */
+#define WM5100_CLKGEN_ERR_EINT                  0x0002  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_MASK             0x0002  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_SHIFT                 1  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_WIDTH                 1  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT            0x0001  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_MASK       0x0001  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_SHIFT           0  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_WIDTH           1  /* CLKGEN_ERR_ASYNC_EINT */
+
+/*
+ * R3331 (0xD03) - Interrupt Status 4
+ */
+#define WM5100_AIF3_ERR_EINT                    0x2000  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_MASK               0x2000  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_SHIFT                  13  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_WIDTH                   1  /* AIF3_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT                    0x1000  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_MASK               0x1000  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_SHIFT                  12  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_WIDTH                   1  /* AIF2_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT                    0x0800  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_MASK               0x0800  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_SHIFT                  11  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_WIDTH                   1  /* AIF1_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT                  0x0400  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_MASK             0x0400  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_SHIFT                10  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_WIDTH                 1  /* CTRLIF_ERR_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT          0x0200  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_MASK     0x0200  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_SHIFT         9  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_WIDTH         1  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT          0x0100  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_MASK     0x0100  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_SHIFT         8  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_WIDTH         1  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT             0x0080  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_MASK        0x0080  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_SHIFT            7  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_WIDTH            1  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT           0x0040  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_MASK      0x0040  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_SHIFT          6  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_WIDTH          1  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT           0x0020  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_MASK      0x0020  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_SHIFT          5  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_WIDTH          1  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT           0x0010  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_MASK      0x0010  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_SHIFT          4  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_WIDTH          1  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT           0x0008  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_MASK      0x0008  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_SHIFT          3  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_WIDTH          1  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT            0x0004  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_MASK       0x0004  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_SHIFT           2  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_WIDTH           1  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT            0x0002  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_MASK       0x0002  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_SHIFT           1  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_WIDTH           1  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT          0x0001  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_MASK     0x0001  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_SHIFT         0  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_WIDTH         1  /* MIXER_UNDERCLOCKED_EINT */
+
+/*
+ * R3332 (0xD04) - Interrupt Raw Status 2
+ */
+#define WM5100_DSP_IRQ6_STS                     0x0020  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_MASK                0x0020  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_SHIFT                    5  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_WIDTH                    1  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ5_STS                     0x0010  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_MASK                0x0010  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_SHIFT                    4  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_WIDTH                    1  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ4_STS                     0x0008  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_MASK                0x0008  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_SHIFT                    3  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_WIDTH                    1  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ3_STS                     0x0004  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_MASK                0x0004  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_SHIFT                    2  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_WIDTH                    1  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ2_STS                     0x0002  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_MASK                0x0002  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_SHIFT                    1  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_WIDTH                    1  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ1_STS                     0x0001  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_MASK                0x0001  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_SHIFT                    0  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_WIDTH                    1  /* DSP_IRQ1_STS */
+
+/*
+ * R3333 (0xD05) - Interrupt Raw Status 3
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_STS            0x8000  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_MASK       0x8000  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_SHIFT          15  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_WIDTH           1  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_STS                 0x4000  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_MASK            0x4000  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_SHIFT               14  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_WIDTH                1  /* SPK_SHUTDOWN_STS */
+#define WM5100_HPDET_STS                        0x2000  /* HPDET_STS */
+#define WM5100_HPDET_STS_MASK                   0x2000  /* HPDET_STS */
+#define WM5100_HPDET_STS_SHIFT                      13  /* HPDET_STS */
+#define WM5100_HPDET_STS_WIDTH                       1  /* HPDET_STS */
+#define WM5100_DRC_SID_DET_STS                  0x0200  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_MASK             0x0200  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_SHIFT                 9  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_WIDTH                 1  /* DRC_SID_DET_STS */
+#define WM5100_ASRC2_LOCK_STS                   0x0100  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_MASK              0x0100  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_SHIFT                  8  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_WIDTH                  1  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS                   0x0080  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_MASK              0x0080  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_SHIFT                  7  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_WIDTH                  1  /* ASRC1_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS                    0x0008  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_MASK               0x0008  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_SHIFT                   3  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_WIDTH                   1  /* FLL2_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS                    0x0004  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_MASK               0x0004  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_SHIFT                   2  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_WIDTH                   1  /* FLL1_LOCK_STS */
+#define WM5100_CLKGEN_ERR_STS                   0x0002  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_MASK              0x0002  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_SHIFT                  1  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_WIDTH                  1  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS             0x0001  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_MASK        0x0001  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_SHIFT            0  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_WIDTH            1  /* CLKGEN_ERR_ASYNC_STS */
+
+/*
+ * R3334 (0xD06) - Interrupt Raw Status 4
+ */
+#define WM5100_AIF3_ERR_STS                     0x2000  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_MASK                0x2000  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_SHIFT                   13  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_WIDTH                    1  /* AIF3_ERR_STS */
+#define WM5100_AIF2_ERR_STS                     0x1000  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_MASK                0x1000  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_SHIFT                   12  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_WIDTH                    1  /* AIF2_ERR_STS */
+#define WM5100_AIF1_ERR_STS                     0x0800  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_MASK                0x0800  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_SHIFT                   11  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_WIDTH                    1  /* AIF1_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS                   0x0400  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_MASK              0x0400  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_SHIFT                 10  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_WIDTH                  1  /* CTRLIF_ERR_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS           0x0200  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_MASK      0x0200  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_SHIFT          9  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_WIDTH          1  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS           0x0100  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_MASK      0x0100  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_SHIFT          8  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_WIDTH          1  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS              0x0080  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_MASK         0x0080  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_SHIFT             7  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_WIDTH             1  /* FX_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS            0x0040  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_MASK       0x0040  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_SHIFT           6  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_WIDTH           1  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS            0x0020  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_MASK       0x0020  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_SHIFT           5  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_WIDTH           1  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS            0x0010  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_MASK       0x0010  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_SHIFT           4  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_WIDTH           1  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS            0x0008  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_MASK       0x0008  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_SHIFT           3  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_WIDTH           1  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS             0x0004  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_MASK        0x0004  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_SHIFT            2  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_WIDTH            1  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS             0x0002  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_MASK        0x0002  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_SHIFT            1  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_WIDTH            1  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS           0x0001  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_MASK      0x0001  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_SHIFT          0  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_WIDTH          1  /* MIXER_UNDERCLOCKED_STS */
+
+/*
+ * R3335 (0xD07) - Interrupt Status 1 Mask
+ */
+#define WM5100_IM_GP6_EINT                      0x0020  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_MASK                 0x0020  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_SHIFT                     5  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_WIDTH                     1  /* IM_GP6_EINT */
+#define WM5100_IM_GP5_EINT                      0x0010  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_MASK                 0x0010  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_SHIFT                     4  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_WIDTH                     1  /* IM_GP5_EINT */
+#define WM5100_IM_GP4_EINT                      0x0008  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_MASK                 0x0008  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_SHIFT                     3  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_WIDTH                     1  /* IM_GP4_EINT */
+#define WM5100_IM_GP3_EINT                      0x0004  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_MASK                 0x0004  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_SHIFT                     2  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_WIDTH                     1  /* IM_GP3_EINT */
+#define WM5100_IM_GP2_EINT                      0x0002  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_MASK                 0x0002  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_SHIFT                     1  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_WIDTH                     1  /* IM_GP2_EINT */
+#define WM5100_IM_GP1_EINT                      0x0001  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_MASK                 0x0001  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_SHIFT                     0  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_WIDTH                     1  /* IM_GP1_EINT */
+
+/*
+ * R3336 (0xD08) - Interrupt Status 2 Mask
+ */
+#define WM5100_IM_DSP_IRQ6_EINT                 0x0020  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_MASK            0x0020  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_SHIFT                5  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_WIDTH                1  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT                 0x0010  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_MASK            0x0010  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_SHIFT                4  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_WIDTH                1  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT                 0x0008  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_MASK            0x0008  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_SHIFT                3  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_WIDTH                1  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT                 0x0004  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_MASK            0x0004  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_SHIFT                2  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_WIDTH                1  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT                 0x0002  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_MASK            0x0002  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_SHIFT                1  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_WIDTH                1  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT                 0x0001  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_MASK            0x0001  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_SHIFT                0  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_WIDTH                1  /* IM_DSP_IRQ1_EINT */
+
+/*
+ * R3337 (0xD09) - Interrupt Status 3 Mask
+ */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT        0x8000  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_MASK   0x8000  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_SHIFT      15  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_WIDTH       1  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT             0x4000  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_MASK        0x4000  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_SHIFT           14  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_WIDTH            1  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_HPDET_EINT                    0x2000  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_MASK               0x2000  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_SHIFT                  13  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_WIDTH                   1  /* IM_HPDET_EINT */
+#define WM5100_IM_ACCDET_EINT                   0x1000  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_MASK              0x1000  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_SHIFT                 12  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_WIDTH                  1  /* IM_ACCDET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT              0x0200  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_MASK         0x0200  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_SHIFT             9  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_WIDTH             1  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT               0x0100  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_MASK          0x0100  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_SHIFT              8  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_WIDTH              1  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT               0x0080  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_MASK          0x0080  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_SHIFT              7  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_WIDTH              1  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT                0x0008  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_MASK           0x0008  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_SHIFT               3  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_WIDTH               1  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT                0x0004  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_MASK           0x0004  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_SHIFT               2  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_WIDTH               1  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT               0x0002  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_MASK          0x0002  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_SHIFT              1  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_WIDTH              1  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT         0x0001  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_MASK    0x0001  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_SHIFT        0  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_WIDTH        1  /* IM_CLKGEN_ERR_ASYNC_EINT */
+
+/*
+ * R3338 (0xD0A) - Interrupt Status 4 Mask
+ */
+#define WM5100_IM_AIF3_ERR_EINT                 0x2000  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_MASK            0x2000  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_SHIFT               13  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_WIDTH                1  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT                 0x1000  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_MASK            0x1000  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_SHIFT               12  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_WIDTH                1  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT                 0x0800  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_MASK            0x0800  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_SHIFT               11  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_WIDTH                1  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT               0x0400  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_MASK          0x0400  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_SHIFT             10  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_WIDTH              1  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT       0x0200  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_MASK  0x0200  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_SHIFT      9  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_WIDTH      1  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT       0x0100  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_MASK  0x0100  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_SHIFT      8  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_WIDTH      1  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT          0x0080  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_MASK     0x0080  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_SHIFT         7  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_WIDTH         1  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT        0x0040  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_MASK   0x0040  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_SHIFT       6  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT        0x0020  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_MASK   0x0020  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_SHIFT       5  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT        0x0010  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_MASK   0x0010  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_SHIFT       4  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT        0x0008  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_MASK   0x0008  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_SHIFT       3  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_WIDTH       1  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT         0x0004  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_MASK    0x0004  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_SHIFT        2  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_WIDTH        1  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT         0x0002  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_MASK    0x0002  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_SHIFT        1  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_WIDTH        1  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT       0x0001  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_MASK  0x0001  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_SHIFT      0  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_WIDTH      1  /* IM_MIXER_UNDERCLOCKED_EINT */
+
+/*
+ * R3359 (0xD1F) - Interrupt Control
+ */
+#define WM5100_IM_IRQ                           0x0001  /* IM_IRQ */
+#define WM5100_IM_IRQ_MASK                      0x0001  /* IM_IRQ */
+#define WM5100_IM_IRQ_SHIFT                          0  /* IM_IRQ */
+#define WM5100_IM_IRQ_WIDTH                          1  /* IM_IRQ */
+
+/*
+ * R3360 (0xD20) - IRQ Debounce 1
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_DB             0x0200  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_MASK        0x0200  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_SHIFT            9  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_WIDTH            1  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_DB                  0x0100  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_MASK             0x0100  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_SHIFT                 8  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_WIDTH                 1  /* SPK_SHUTDOWN_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB                 0x0008  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_MASK            0x0008  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_SHIFT                3  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_WIDTH                1  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB                 0x0004  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_MASK            0x0004  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_SHIFT                2  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_WIDTH                1  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB                0x0002  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_MASK           0x0002  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_SHIFT               1  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_WIDTH               1  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB          0x0001  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_MASK     0x0001  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_SHIFT         0  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_WIDTH         1  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+
+/*
+ * R3361 (0xD21) - IRQ Debounce 2
+ */
+#define WM5100_AIF_ERR_DB                       0x0001  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_MASK                  0x0001  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_SHIFT                      0  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_WIDTH                      1  /* AIF_ERR_DB */
+
+/*
+ * R3584 (0xE00) - FX_Ctrl
+ */
+#define WM5100_FX_STS_MASK                      0xFFC0  /* FX_STS - [15:6] */
+#define WM5100_FX_STS_SHIFT                          6  /* FX_STS - [15:6] */
+#define WM5100_FX_STS_WIDTH                         10  /* FX_STS - [15:6] */
+#define WM5100_FX_RATE_MASK                     0x0003  /* FX_RATE - [1:0] */
+#define WM5100_FX_RATE_SHIFT                         0  /* FX_RATE - [1:0] */
+#define WM5100_FX_RATE_WIDTH                         2  /* FX_RATE - [1:0] */
+
+/*
+ * R3600 (0xE10) - EQ1_1
+ */
+#define WM5100_EQ1_B1_GAIN_MASK                 0xF800  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B1_GAIN_SHIFT                    11  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B1_GAIN_WIDTH                     5  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B2_GAIN_MASK                 0x07C0  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B2_GAIN_SHIFT                     6  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B2_GAIN_WIDTH                     5  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B3_GAIN_MASK                 0x003E  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_B3_GAIN_SHIFT                     1  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_B3_GAIN_WIDTH                     5  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_ENA                          0x0001  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_MASK                     0x0001  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_SHIFT                         0  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_WIDTH                         1  /* EQ1_ENA */
+
+/*
+ * R3601 (0xE11) - EQ1_2
+ */
+#define WM5100_EQ1_B4_GAIN_MASK                 0xF800  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B4_GAIN_SHIFT                    11  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B4_GAIN_WIDTH                     5  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B5_GAIN_MASK                 0x07C0  /* EQ1_B5_GAIN - [10:6] */
+#define WM5100_EQ1_B5_GAIN_SHIFT                     6  /* EQ1_B5_GAIN - [10:6] */
+#define WM5100_EQ1_B5_GAIN_WIDTH                     5  /* EQ1_B5_GAIN - [10:6] */
+
+/*
+ * R3602 (0xE12) - EQ1_3
+ */
+#define WM5100_EQ1_B1_A_MASK                    0xFFFF  /* EQ1_B1_A - [15:0] */
+#define WM5100_EQ1_B1_A_SHIFT                        0  /* EQ1_B1_A - [15:0] */
+#define WM5100_EQ1_B1_A_WIDTH                       16  /* EQ1_B1_A - [15:0] */
+
+/*
+ * R3603 (0xE13) - EQ1_4
+ */
+#define WM5100_EQ1_B1_B_MASK                    0xFFFF  /* EQ1_B1_B - [15:0] */
+#define WM5100_EQ1_B1_B_SHIFT                        0  /* EQ1_B1_B - [15:0] */
+#define WM5100_EQ1_B1_B_WIDTH                       16  /* EQ1_B1_B - [15:0] */
+
+/*
+ * R3604 (0xE14) - EQ1_5
+ */
+#define WM5100_EQ1_B1_PG_MASK                   0xFFFF  /* EQ1_B1_PG - [15:0] */
+#define WM5100_EQ1_B1_PG_SHIFT                       0  /* EQ1_B1_PG - [15:0] */
+#define WM5100_EQ1_B1_PG_WIDTH                      16  /* EQ1_B1_PG - [15:0] */
+
+/*
+ * R3605 (0xE15) - EQ1_6
+ */
+#define WM5100_EQ1_B2_A_MASK                    0xFFFF  /* EQ1_B2_A - [15:0] */
+#define WM5100_EQ1_B2_A_SHIFT                        0  /* EQ1_B2_A - [15:0] */
+#define WM5100_EQ1_B2_A_WIDTH                       16  /* EQ1_B2_A - [15:0] */
+
+/*
+ * R3606 (0xE16) - EQ1_7
+ */
+#define WM5100_EQ1_B2_B_MASK                    0xFFFF  /* EQ1_B2_B - [15:0] */
+#define WM5100_EQ1_B2_B_SHIFT                        0  /* EQ1_B2_B - [15:0] */
+#define WM5100_EQ1_B2_B_WIDTH                       16  /* EQ1_B2_B - [15:0] */
+
+/*
+ * R3607 (0xE17) - EQ1_8
+ */
+#define WM5100_EQ1_B2_C_MASK                    0xFFFF  /* EQ1_B2_C - [15:0] */
+#define WM5100_EQ1_B2_C_SHIFT                        0  /* EQ1_B2_C - [15:0] */
+#define WM5100_EQ1_B2_C_WIDTH                       16  /* EQ1_B2_C - [15:0] */
+
+/*
+ * R3608 (0xE18) - EQ1_9
+ */
+#define WM5100_EQ1_B2_PG_MASK                   0xFFFF  /* EQ1_B2_PG - [15:0] */
+#define WM5100_EQ1_B2_PG_SHIFT                       0  /* EQ1_B2_PG - [15:0] */
+#define WM5100_EQ1_B2_PG_WIDTH                      16  /* EQ1_B2_PG - [15:0] */
+
+/*
+ * R3609 (0xE19) - EQ1_10
+ */
+#define WM5100_EQ1_B3_A_MASK                    0xFFFF  /* EQ1_B3_A - [15:0] */
+#define WM5100_EQ1_B3_A_SHIFT                        0  /* EQ1_B3_A - [15:0] */
+#define WM5100_EQ1_B3_A_WIDTH                       16  /* EQ1_B3_A - [15:0] */
+
+/*
+ * R3610 (0xE1A) - EQ1_11
+ */
+#define WM5100_EQ1_B3_B_MASK                    0xFFFF  /* EQ1_B3_B - [15:0] */
+#define WM5100_EQ1_B3_B_SHIFT                        0  /* EQ1_B3_B - [15:0] */
+#define WM5100_EQ1_B3_B_WIDTH                       16  /* EQ1_B3_B - [15:0] */
+
+/*
+ * R3611 (0xE1B) - EQ1_12
+ */
+#define WM5100_EQ1_B3_C_MASK                    0xFFFF  /* EQ1_B3_C - [15:0] */
+#define WM5100_EQ1_B3_C_SHIFT                        0  /* EQ1_B3_C - [15:0] */
+#define WM5100_EQ1_B3_C_WIDTH                       16  /* EQ1_B3_C - [15:0] */
+
+/*
+ * R3612 (0xE1C) - EQ1_13
+ */
+#define WM5100_EQ1_B3_PG_MASK                   0xFFFF  /* EQ1_B3_PG - [15:0] */
+#define WM5100_EQ1_B3_PG_SHIFT                       0  /* EQ1_B3_PG - [15:0] */
+#define WM5100_EQ1_B3_PG_WIDTH                      16  /* EQ1_B3_PG - [15:0] */
+
+/*
+ * R3613 (0xE1D) - EQ1_14
+ */
+#define WM5100_EQ1_B4_A_MASK                    0xFFFF  /* EQ1_B4_A - [15:0] */
+#define WM5100_EQ1_B4_A_SHIFT                        0  /* EQ1_B4_A - [15:0] */
+#define WM5100_EQ1_B4_A_WIDTH                       16  /* EQ1_B4_A - [15:0] */
+
+/*
+ * R3614 (0xE1E) - EQ1_15
+ */
+#define WM5100_EQ1_B4_B_MASK                    0xFFFF  /* EQ1_B4_B - [15:0] */
+#define WM5100_EQ1_B4_B_SHIFT                        0  /* EQ1_B4_B - [15:0] */
+#define WM5100_EQ1_B4_B_WIDTH                       16  /* EQ1_B4_B - [15:0] */
+
+/*
+ * R3615 (0xE1F) - EQ1_16
+ */
+#define WM5100_EQ1_B4_C_MASK                    0xFFFF  /* EQ1_B4_C - [15:0] */
+#define WM5100_EQ1_B4_C_SHIFT                        0  /* EQ1_B4_C - [15:0] */
+#define WM5100_EQ1_B4_C_WIDTH                       16  /* EQ1_B4_C - [15:0] */
+
+/*
+ * R3616 (0xE20) - EQ1_17
+ */
+#define WM5100_EQ1_B4_PG_MASK                   0xFFFF  /* EQ1_B4_PG - [15:0] */
+#define WM5100_EQ1_B4_PG_SHIFT                       0  /* EQ1_B4_PG - [15:0] */
+#define WM5100_EQ1_B4_PG_WIDTH                      16  /* EQ1_B4_PG - [15:0] */
+
+/*
+ * R3617 (0xE21) - EQ1_18
+ */
+#define WM5100_EQ1_B5_A_MASK                    0xFFFF  /* EQ1_B5_A - [15:0] */
+#define WM5100_EQ1_B5_A_SHIFT                        0  /* EQ1_B5_A - [15:0] */
+#define WM5100_EQ1_B5_A_WIDTH                       16  /* EQ1_B5_A - [15:0] */
+
+/*
+ * R3618 (0xE22) - EQ1_19
+ */
+#define WM5100_EQ1_B5_B_MASK                    0xFFFF  /* EQ1_B5_B - [15:0] */
+#define WM5100_EQ1_B5_B_SHIFT                        0  /* EQ1_B5_B - [15:0] */
+#define WM5100_EQ1_B5_B_WIDTH                       16  /* EQ1_B5_B - [15:0] */
+
+/*
+ * R3619 (0xE23) - EQ1_20
+ */
+#define WM5100_EQ1_B5_PG_MASK                   0xFFFF  /* EQ1_B5_PG - [15:0] */
+#define WM5100_EQ1_B5_PG_SHIFT                       0  /* EQ1_B5_PG - [15:0] */
+#define WM5100_EQ1_B5_PG_WIDTH                      16  /* EQ1_B5_PG - [15:0] */
+
+/*
+ * R3622 (0xE26) - EQ2_1
+ */
+#define WM5100_EQ2_B1_GAIN_MASK                 0xF800  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B1_GAIN_SHIFT                    11  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B1_GAIN_WIDTH                     5  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B2_GAIN_MASK                 0x07C0  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B2_GAIN_SHIFT                     6  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B2_GAIN_WIDTH                     5  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B3_GAIN_MASK                 0x003E  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_B3_GAIN_SHIFT                     1  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_B3_GAIN_WIDTH                     5  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_ENA                          0x0001  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_MASK                     0x0001  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_SHIFT                         0  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_WIDTH                         1  /* EQ2_ENA */
+
+/*
+ * R3623 (0xE27) - EQ2_2
+ */
+#define WM5100_EQ2_B4_GAIN_MASK                 0xF800  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B4_GAIN_SHIFT                    11  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B4_GAIN_WIDTH                     5  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B5_GAIN_MASK                 0x07C0  /* EQ2_B5_GAIN - [10:6] */
+#define WM5100_EQ2_B5_GAIN_SHIFT                     6  /* EQ2_B5_GAIN - [10:6] */
+#define WM5100_EQ2_B5_GAIN_WIDTH                     5  /* EQ2_B5_GAIN - [10:6] */
+
+/*
+ * R3624 (0xE28) - EQ2_3
+ */
+#define WM5100_EQ2_B1_A_MASK                    0xFFFF  /* EQ2_B1_A - [15:0] */
+#define WM5100_EQ2_B1_A_SHIFT                        0  /* EQ2_B1_A - [15:0] */
+#define WM5100_EQ2_B1_A_WIDTH                       16  /* EQ2_B1_A - [15:0] */
+
+/*
+ * R3625 (0xE29) - EQ2_4
+ */
+#define WM5100_EQ2_B1_B_MASK                    0xFFFF  /* EQ2_B1_B - [15:0] */
+#define WM5100_EQ2_B1_B_SHIFT                        0  /* EQ2_B1_B - [15:0] */
+#define WM5100_EQ2_B1_B_WIDTH                       16  /* EQ2_B1_B - [15:0] */
+
+/*
+ * R3626 (0xE2A) - EQ2_5
+ */
+#define WM5100_EQ2_B1_PG_MASK                   0xFFFF  /* EQ2_B1_PG - [15:0] */
+#define WM5100_EQ2_B1_PG_SHIFT                       0  /* EQ2_B1_PG - [15:0] */
+#define WM5100_EQ2_B1_PG_WIDTH                      16  /* EQ2_B1_PG - [15:0] */
+
+/*
+ * R3627 (0xE2B) - EQ2_6
+ */
+#define WM5100_EQ2_B2_A_MASK                    0xFFFF  /* EQ2_B2_A - [15:0] */
+#define WM5100_EQ2_B2_A_SHIFT                        0  /* EQ2_B2_A - [15:0] */
+#define WM5100_EQ2_B2_A_WIDTH                       16  /* EQ2_B2_A - [15:0] */
+
+/*
+ * R3628 (0xE2C) - EQ2_7
+ */
+#define WM5100_EQ2_B2_B_MASK                    0xFFFF  /* EQ2_B2_B - [15:0] */
+#define WM5100_EQ2_B2_B_SHIFT                        0  /* EQ2_B2_B - [15:0] */
+#define WM5100_EQ2_B2_B_WIDTH                       16  /* EQ2_B2_B - [15:0] */
+
+/*
+ * R3629 (0xE2D) - EQ2_8
+ */
+#define WM5100_EQ2_B2_C_MASK                    0xFFFF  /* EQ2_B2_C - [15:0] */
+#define WM5100_EQ2_B2_C_SHIFT                        0  /* EQ2_B2_C - [15:0] */
+#define WM5100_EQ2_B2_C_WIDTH                       16  /* EQ2_B2_C - [15:0] */
+
+/*
+ * R3630 (0xE2E) - EQ2_9
+ */
+#define WM5100_EQ2_B2_PG_MASK                   0xFFFF  /* EQ2_B2_PG - [15:0] */
+#define WM5100_EQ2_B2_PG_SHIFT                       0  /* EQ2_B2_PG - [15:0] */
+#define WM5100_EQ2_B2_PG_WIDTH                      16  /* EQ2_B2_PG - [15:0] */
+
+/*
+ * R3631 (0xE2F) - EQ2_10
+ */
+#define WM5100_EQ2_B3_A_MASK                    0xFFFF  /* EQ2_B3_A - [15:0] */
+#define WM5100_EQ2_B3_A_SHIFT                        0  /* EQ2_B3_A - [15:0] */
+#define WM5100_EQ2_B3_A_WIDTH                       16  /* EQ2_B3_A - [15:0] */
+
+/*
+ * R3632 (0xE30) - EQ2_11
+ */
+#define WM5100_EQ2_B3_B_MASK                    0xFFFF  /* EQ2_B3_B - [15:0] */
+#define WM5100_EQ2_B3_B_SHIFT                        0  /* EQ2_B3_B - [15:0] */
+#define WM5100_EQ2_B3_B_WIDTH                       16  /* EQ2_B3_B - [15:0] */
+
+/*
+ * R3633 (0xE31) - EQ2_12
+ */
+#define WM5100_EQ2_B3_C_MASK                    0xFFFF  /* EQ2_B3_C - [15:0] */
+#define WM5100_EQ2_B3_C_SHIFT                        0  /* EQ2_B3_C - [15:0] */
+#define WM5100_EQ2_B3_C_WIDTH                       16  /* EQ2_B3_C - [15:0] */
+
+/*
+ * R3634 (0xE32) - EQ2_13
+ */
+#define WM5100_EQ2_B3_PG_MASK                   0xFFFF  /* EQ2_B3_PG - [15:0] */
+#define WM5100_EQ2_B3_PG_SHIFT                       0  /* EQ2_B3_PG - [15:0] */
+#define WM5100_EQ2_B3_PG_WIDTH                      16  /* EQ2_B3_PG - [15:0] */
+
+/*
+ * R3635 (0xE33) - EQ2_14
+ */
+#define WM5100_EQ2_B4_A_MASK                    0xFFFF  /* EQ2_B4_A - [15:0] */
+#define WM5100_EQ2_B4_A_SHIFT                        0  /* EQ2_B4_A - [15:0] */
+#define WM5100_EQ2_B4_A_WIDTH                       16  /* EQ2_B4_A - [15:0] */
+
+/*
+ * R3636 (0xE34) - EQ2_15
+ */
+#define WM5100_EQ2_B4_B_MASK                    0xFFFF  /* EQ2_B4_B - [15:0] */
+#define WM5100_EQ2_B4_B_SHIFT                        0  /* EQ2_B4_B - [15:0] */
+#define WM5100_EQ2_B4_B_WIDTH                       16  /* EQ2_B4_B - [15:0] */
+
+/*
+ * R3637 (0xE35) - EQ2_16
+ */
+#define WM5100_EQ2_B4_C_MASK                    0xFFFF  /* EQ2_B4_C - [15:0] */
+#define WM5100_EQ2_B4_C_SHIFT                        0  /* EQ2_B4_C - [15:0] */
+#define WM5100_EQ2_B4_C_WIDTH                       16  /* EQ2_B4_C - [15:0] */
+
+/*
+ * R3638 (0xE36) - EQ2_17
+ */
+#define WM5100_EQ2_B4_PG_MASK                   0xFFFF  /* EQ2_B4_PG - [15:0] */
+#define WM5100_EQ2_B4_PG_SHIFT                       0  /* EQ2_B4_PG - [15:0] */
+#define WM5100_EQ2_B4_PG_WIDTH                      16  /* EQ2_B4_PG - [15:0] */
+
+/*
+ * R3639 (0xE37) - EQ2_18
+ */
+#define WM5100_EQ2_B5_A_MASK                    0xFFFF  /* EQ2_B5_A - [15:0] */
+#define WM5100_EQ2_B5_A_SHIFT                        0  /* EQ2_B5_A - [15:0] */
+#define WM5100_EQ2_B5_A_WIDTH                       16  /* EQ2_B5_A - [15:0] */
+
+/*
+ * R3640 (0xE38) - EQ2_19
+ */
+#define WM5100_EQ2_B5_B_MASK                    0xFFFF  /* EQ2_B5_B - [15:0] */
+#define WM5100_EQ2_B5_B_SHIFT                        0  /* EQ2_B5_B - [15:0] */
+#define WM5100_EQ2_B5_B_WIDTH                       16  /* EQ2_B5_B - [15:0] */
+
+/*
+ * R3641 (0xE39) - EQ2_20
+ */
+#define WM5100_EQ2_B5_PG_MASK                   0xFFFF  /* EQ2_B5_PG - [15:0] */
+#define WM5100_EQ2_B5_PG_SHIFT                       0  /* EQ2_B5_PG - [15:0] */
+#define WM5100_EQ2_B5_PG_WIDTH                      16  /* EQ2_B5_PG - [15:0] */
+
+/*
+ * R3644 (0xE3C) - EQ3_1
+ */
+#define WM5100_EQ3_B1_GAIN_MASK                 0xF800  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B1_GAIN_SHIFT                    11  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B1_GAIN_WIDTH                     5  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B2_GAIN_MASK                 0x07C0  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B2_GAIN_SHIFT                     6  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B2_GAIN_WIDTH                     5  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B3_GAIN_MASK                 0x003E  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_B3_GAIN_SHIFT                     1  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_B3_GAIN_WIDTH                     5  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_ENA                          0x0001  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_MASK                     0x0001  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_SHIFT                         0  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_WIDTH                         1  /* EQ3_ENA */
+
+/*
+ * R3645 (0xE3D) - EQ3_2
+ */
+#define WM5100_EQ3_B4_GAIN_MASK                 0xF800  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B4_GAIN_SHIFT                    11  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B4_GAIN_WIDTH                     5  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B5_GAIN_MASK                 0x07C0  /* EQ3_B5_GAIN - [10:6] */
+#define WM5100_EQ3_B5_GAIN_SHIFT                     6  /* EQ3_B5_GAIN - [10:6] */
+#define WM5100_EQ3_B5_GAIN_WIDTH                     5  /* EQ3_B5_GAIN - [10:6] */
+
+/*
+ * R3646 (0xE3E) - EQ3_3
+ */
+#define WM5100_EQ3_B1_A_MASK                    0xFFFF  /* EQ3_B1_A - [15:0] */
+#define WM5100_EQ3_B1_A_SHIFT                        0  /* EQ3_B1_A - [15:0] */
+#define WM5100_EQ3_B1_A_WIDTH                       16  /* EQ3_B1_A - [15:0] */
+
+/*
+ * R3647 (0xE3F) - EQ3_4
+ */
+#define WM5100_EQ3_B1_B_MASK                    0xFFFF  /* EQ3_B1_B - [15:0] */
+#define WM5100_EQ3_B1_B_SHIFT                        0  /* EQ3_B1_B - [15:0] */
+#define WM5100_EQ3_B1_B_WIDTH                       16  /* EQ3_B1_B - [15:0] */
+
+/*
+ * R3648 (0xE40) - EQ3_5
+ */
+#define WM5100_EQ3_B1_PG_MASK                   0xFFFF  /* EQ3_B1_PG - [15:0] */
+#define WM5100_EQ3_B1_PG_SHIFT                       0  /* EQ3_B1_PG - [15:0] */
+#define WM5100_EQ3_B1_PG_WIDTH                      16  /* EQ3_B1_PG - [15:0] */
+
+/*
+ * R3649 (0xE41) - EQ3_6
+ */
+#define WM5100_EQ3_B2_A_MASK                    0xFFFF  /* EQ3_B2_A - [15:0] */
+#define WM5100_EQ3_B2_A_SHIFT                        0  /* EQ3_B2_A - [15:0] */
+#define WM5100_EQ3_B2_A_WIDTH                       16  /* EQ3_B2_A - [15:0] */
+
+/*
+ * R3650 (0xE42) - EQ3_7
+ */
+#define WM5100_EQ3_B2_B_MASK                    0xFFFF  /* EQ3_B2_B - [15:0] */
+#define WM5100_EQ3_B2_B_SHIFT                        0  /* EQ3_B2_B - [15:0] */
+#define WM5100_EQ3_B2_B_WIDTH                       16  /* EQ3_B2_B - [15:0] */
+
+/*
+ * R3651 (0xE43) - EQ3_8
+ */
+#define WM5100_EQ3_B2_C_MASK                    0xFFFF  /* EQ3_B2_C - [15:0] */
+#define WM5100_EQ3_B2_C_SHIFT                        0  /* EQ3_B2_C - [15:0] */
+#define WM5100_EQ3_B2_C_WIDTH                       16  /* EQ3_B2_C - [15:0] */
+
+/*
+ * R3652 (0xE44) - EQ3_9
+ */
+#define WM5100_EQ3_B2_PG_MASK                   0xFFFF  /* EQ3_B2_PG - [15:0] */
+#define WM5100_EQ3_B2_PG_SHIFT                       0  /* EQ3_B2_PG - [15:0] */
+#define WM5100_EQ3_B2_PG_WIDTH                      16  /* EQ3_B2_PG - [15:0] */
+
+/*
+ * R3653 (0xE45) - EQ3_10
+ */
+#define WM5100_EQ3_B3_A_MASK                    0xFFFF  /* EQ3_B3_A - [15:0] */
+#define WM5100_EQ3_B3_A_SHIFT                        0  /* EQ3_B3_A - [15:0] */
+#define WM5100_EQ3_B3_A_WIDTH                       16  /* EQ3_B3_A - [15:0] */
+
+/*
+ * R3654 (0xE46) - EQ3_11
+ */
+#define WM5100_EQ3_B3_B_MASK                    0xFFFF  /* EQ3_B3_B - [15:0] */
+#define WM5100_EQ3_B3_B_SHIFT                        0  /* EQ3_B3_B - [15:0] */
+#define WM5100_EQ3_B3_B_WIDTH                       16  /* EQ3_B3_B - [15:0] */
+
+/*
+ * R3655 (0xE47) - EQ3_12
+ */
+#define WM5100_EQ3_B3_C_MASK                    0xFFFF  /* EQ3_B3_C - [15:0] */
+#define WM5100_EQ3_B3_C_SHIFT                        0  /* EQ3_B3_C - [15:0] */
+#define WM5100_EQ3_B3_C_WIDTH                       16  /* EQ3_B3_C - [15:0] */
+
+/*
+ * R3656 (0xE48) - EQ3_13
+ */
+#define WM5100_EQ3_B3_PG_MASK                   0xFFFF  /* EQ3_B3_PG - [15:0] */
+#define WM5100_EQ3_B3_PG_SHIFT                       0  /* EQ3_B3_PG - [15:0] */
+#define WM5100_EQ3_B3_PG_WIDTH                      16  /* EQ3_B3_PG - [15:0] */
+
+/*
+ * R3657 (0xE49) - EQ3_14
+ */
+#define WM5100_EQ3_B4_A_MASK                    0xFFFF  /* EQ3_B4_A - [15:0] */
+#define WM5100_EQ3_B4_A_SHIFT                        0  /* EQ3_B4_A - [15:0] */
+#define WM5100_EQ3_B4_A_WIDTH                       16  /* EQ3_B4_A - [15:0] */
+
+/*
+ * R3658 (0xE4A) - EQ3_15
+ */
+#define WM5100_EQ3_B4_B_MASK                    0xFFFF  /* EQ3_B4_B - [15:0] */
+#define WM5100_EQ3_B4_B_SHIFT                        0  /* EQ3_B4_B - [15:0] */
+#define WM5100_EQ3_B4_B_WIDTH                       16  /* EQ3_B4_B - [15:0] */
+
+/*
+ * R3659 (0xE4B) - EQ3_16
+ */
+#define WM5100_EQ3_B4_C_MASK                    0xFFFF  /* EQ3_B4_C - [15:0] */
+#define WM5100_EQ3_B4_C_SHIFT                        0  /* EQ3_B4_C - [15:0] */
+#define WM5100_EQ3_B4_C_WIDTH                       16  /* EQ3_B4_C - [15:0] */
+
+/*
+ * R3660 (0xE4C) - EQ3_17
+ */
+#define WM5100_EQ3_B4_PG_MASK                   0xFFFF  /* EQ3_B4_PG - [15:0] */
+#define WM5100_EQ3_B4_PG_SHIFT                       0  /* EQ3_B4_PG - [15:0] */
+#define WM5100_EQ3_B4_PG_WIDTH                      16  /* EQ3_B4_PG - [15:0] */
+
+/*
+ * R3661 (0xE4D) - EQ3_18
+ */
+#define WM5100_EQ3_B5_A_MASK                    0xFFFF  /* EQ3_B5_A - [15:0] */
+#define WM5100_EQ3_B5_A_SHIFT                        0  /* EQ3_B5_A - [15:0] */
+#define WM5100_EQ3_B5_A_WIDTH                       16  /* EQ3_B5_A - [15:0] */
+
+/*
+ * R3662 (0xE4E) - EQ3_19
+ */
+#define WM5100_EQ3_B5_B_MASK                    0xFFFF  /* EQ3_B5_B - [15:0] */
+#define WM5100_EQ3_B5_B_SHIFT                        0  /* EQ3_B5_B - [15:0] */
+#define WM5100_EQ3_B5_B_WIDTH                       16  /* EQ3_B5_B - [15:0] */
+
+/*
+ * R3663 (0xE4F) - EQ3_20
+ */
+#define WM5100_EQ3_B5_PG_MASK                   0xFFFF  /* EQ3_B5_PG - [15:0] */
+#define WM5100_EQ3_B5_PG_SHIFT                       0  /* EQ3_B5_PG - [15:0] */
+#define WM5100_EQ3_B5_PG_WIDTH                      16  /* EQ3_B5_PG - [15:0] */
+
+/*
+ * R3666 (0xE52) - EQ4_1
+ */
+#define WM5100_EQ4_B1_GAIN_MASK                 0xF800  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B1_GAIN_SHIFT                    11  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B1_GAIN_WIDTH                     5  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B2_GAIN_MASK                 0x07C0  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B2_GAIN_SHIFT                     6  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B2_GAIN_WIDTH                     5  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B3_GAIN_MASK                 0x003E  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_B3_GAIN_SHIFT                     1  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_B3_GAIN_WIDTH                     5  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_ENA                          0x0001  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_MASK                     0x0001  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_SHIFT                         0  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_WIDTH                         1  /* EQ4_ENA */
+
+/*
+ * R3667 (0xE53) - EQ4_2
+ */
+#define WM5100_EQ4_B4_GAIN_MASK                 0xF800  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B4_GAIN_SHIFT                    11  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B4_GAIN_WIDTH                     5  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B5_GAIN_MASK                 0x07C0  /* EQ4_B5_GAIN - [10:6] */
+#define WM5100_EQ4_B5_GAIN_SHIFT                     6  /* EQ4_B5_GAIN - [10:6] */
+#define WM5100_EQ4_B5_GAIN_WIDTH                     5  /* EQ4_B5_GAIN - [10:6] */
+
+/*
+ * R3668 (0xE54) - EQ4_3
+ */
+#define WM5100_EQ4_B1_A_MASK                    0xFFFF  /* EQ4_B1_A - [15:0] */
+#define WM5100_EQ4_B1_A_SHIFT                        0  /* EQ4_B1_A - [15:0] */
+#define WM5100_EQ4_B1_A_WIDTH                       16  /* EQ4_B1_A - [15:0] */
+
+/*
+ * R3669 (0xE55) - EQ4_4
+ */
+#define WM5100_EQ4_B1_B_MASK                    0xFFFF  /* EQ4_B1_B - [15:0] */
+#define WM5100_EQ4_B1_B_SHIFT                        0  /* EQ4_B1_B - [15:0] */
+#define WM5100_EQ4_B1_B_WIDTH                       16  /* EQ4_B1_B - [15:0] */
+
+/*
+ * R3670 (0xE56) - EQ4_5
+ */
+#define WM5100_EQ4_B1_PG_MASK                   0xFFFF  /* EQ4_B1_PG - [15:0] */
+#define WM5100_EQ4_B1_PG_SHIFT                       0  /* EQ4_B1_PG - [15:0] */
+#define WM5100_EQ4_B1_PG_WIDTH                      16  /* EQ4_B1_PG - [15:0] */
+
+/*
+ * R3671 (0xE57) - EQ4_6
+ */
+#define WM5100_EQ4_B2_A_MASK                    0xFFFF  /* EQ4_B2_A - [15:0] */
+#define WM5100_EQ4_B2_A_SHIFT                        0  /* EQ4_B2_A - [15:0] */
+#define WM5100_EQ4_B2_A_WIDTH                       16  /* EQ4_B2_A - [15:0] */
+
+/*
+ * R3672 (0xE58) - EQ4_7
+ */
+#define WM5100_EQ4_B2_B_MASK                    0xFFFF  /* EQ4_B2_B - [15:0] */
+#define WM5100_EQ4_B2_B_SHIFT                        0  /* EQ4_B2_B - [15:0] */
+#define WM5100_EQ4_B2_B_WIDTH                       16  /* EQ4_B2_B - [15:0] */
+
+/*
+ * R3673 (0xE59) - EQ4_8
+ */
+#define WM5100_EQ4_B2_C_MASK                    0xFFFF  /* EQ4_B2_C - [15:0] */
+#define WM5100_EQ4_B2_C_SHIFT                        0  /* EQ4_B2_C - [15:0] */
+#define WM5100_EQ4_B2_C_WIDTH                       16  /* EQ4_B2_C - [15:0] */
+
+/*
+ * R3674 (0xE5A) - EQ4_9
+ */
+#define WM5100_EQ4_B2_PG_MASK                   0xFFFF  /* EQ4_B2_PG - [15:0] */
+#define WM5100_EQ4_B2_PG_SHIFT                       0  /* EQ4_B2_PG - [15:0] */
+#define WM5100_EQ4_B2_PG_WIDTH                      16  /* EQ4_B2_PG - [15:0] */
+
+/*
+ * R3675 (0xE5B) - EQ4_10
+ */
+#define WM5100_EQ4_B3_A_MASK                    0xFFFF  /* EQ4_B3_A - [15:0] */
+#define WM5100_EQ4_B3_A_SHIFT                        0  /* EQ4_B3_A - [15:0] */
+#define WM5100_EQ4_B3_A_WIDTH                       16  /* EQ4_B3_A - [15:0] */
+
+/*
+ * R3676 (0xE5C) - EQ4_11
+ */
+#define WM5100_EQ4_B3_B_MASK                    0xFFFF  /* EQ4_B3_B - [15:0] */
+#define WM5100_EQ4_B3_B_SHIFT                        0  /* EQ4_B3_B - [15:0] */
+#define WM5100_EQ4_B3_B_WIDTH                       16  /* EQ4_B3_B - [15:0] */
+
+/*
+ * R3677 (0xE5D) - EQ4_12
+ */
+#define WM5100_EQ4_B3_C_MASK                    0xFFFF  /* EQ4_B3_C - [15:0] */
+#define WM5100_EQ4_B3_C_SHIFT                        0  /* EQ4_B3_C - [15:0] */
+#define WM5100_EQ4_B3_C_WIDTH                       16  /* EQ4_B3_C - [15:0] */
+
+/*
+ * R3678 (0xE5E) - EQ4_13
+ */
+#define WM5100_EQ4_B3_PG_MASK                   0xFFFF  /* EQ4_B3_PG - [15:0] */
+#define WM5100_EQ4_B3_PG_SHIFT                       0  /* EQ4_B3_PG - [15:0] */
+#define WM5100_EQ4_B3_PG_WIDTH                      16  /* EQ4_B3_PG - [15:0] */
+
+/*
+ * R3679 (0xE5F) - EQ4_14
+ */
+#define WM5100_EQ4_B4_A_MASK                    0xFFFF  /* EQ4_B4_A - [15:0] */
+#define WM5100_EQ4_B4_A_SHIFT                        0  /* EQ4_B4_A - [15:0] */
+#define WM5100_EQ4_B4_A_WIDTH                       16  /* EQ4_B4_A - [15:0] */
+
+/*
+ * R3680 (0xE60) - EQ4_15
+ */
+#define WM5100_EQ4_B4_B_MASK                    0xFFFF  /* EQ4_B4_B - [15:0] */
+#define WM5100_EQ4_B4_B_SHIFT                        0  /* EQ4_B4_B - [15:0] */
+#define WM5100_EQ4_B4_B_WIDTH                       16  /* EQ4_B4_B - [15:0] */
+
+/*
+ * R3681 (0xE61) - EQ4_16
+ */
+#define WM5100_EQ4_B4_C_MASK                    0xFFFF  /* EQ4_B4_C - [15:0] */
+#define WM5100_EQ4_B4_C_SHIFT                        0  /* EQ4_B4_C - [15:0] */
+#define WM5100_EQ4_B4_C_WIDTH                       16  /* EQ4_B4_C - [15:0] */
+
+/*
+ * R3682 (0xE62) - EQ4_17
+ */
+#define WM5100_EQ4_B4_PG_MASK                   0xFFFF  /* EQ4_B4_PG - [15:0] */
+#define WM5100_EQ4_B4_PG_SHIFT                       0  /* EQ4_B4_PG - [15:0] */
+#define WM5100_EQ4_B4_PG_WIDTH                      16  /* EQ4_B4_PG - [15:0] */
+
+/*
+ * R3683 (0xE63) - EQ4_18
+ */
+#define WM5100_EQ4_B5_A_MASK                    0xFFFF  /* EQ4_B5_A - [15:0] */
+#define WM5100_EQ4_B5_A_SHIFT                        0  /* EQ4_B5_A - [15:0] */
+#define WM5100_EQ4_B5_A_WIDTH                       16  /* EQ4_B5_A - [15:0] */
+
+/*
+ * R3684 (0xE64) - EQ4_19
+ */
+#define WM5100_EQ4_B5_B_MASK                    0xFFFF  /* EQ4_B5_B - [15:0] */
+#define WM5100_EQ4_B5_B_SHIFT                        0  /* EQ4_B5_B - [15:0] */
+#define WM5100_EQ4_B5_B_WIDTH                       16  /* EQ4_B5_B - [15:0] */
+
+/*
+ * R3685 (0xE65) - EQ4_20
+ */
+#define WM5100_EQ4_B5_PG_MASK                   0xFFFF  /* EQ4_B5_PG - [15:0] */
+#define WM5100_EQ4_B5_PG_SHIFT                       0  /* EQ4_B5_PG - [15:0] */
+#define WM5100_EQ4_B5_PG_WIDTH                      16  /* EQ4_B5_PG - [15:0] */
+
+/*
+ * R3712 (0xE80) - DRC1 ctrl1
+ */
+#define WM5100_DRC_SIG_DET_RMS_MASK             0xF800  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_RMS_SHIFT                11  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_RMS_WIDTH                 5  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_PK_MASK              0x0600  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_SIG_DET_PK_SHIFT                  9  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_SIG_DET_PK_WIDTH                  2  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_NG_ENA                       0x0100  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_MASK                  0x0100  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_SHIFT                      8  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_WIDTH                      1  /* DRC_NG_ENA */
+#define WM5100_DRC_SIG_DET_MODE                 0x0080  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_MASK            0x0080  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_SHIFT                7  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_WIDTH                1  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET                      0x0040  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_MASK                 0x0040  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_SHIFT                     6  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_WIDTH                     1  /* DRC_SIG_DET */
+#define WM5100_DRC_KNEE2_OP_ENA                 0x0020  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_MASK            0x0020  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_SHIFT                5  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_WIDTH                1  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_QR                           0x0010  /* DRC_QR */
+#define WM5100_DRC_QR_MASK                      0x0010  /* DRC_QR */
+#define WM5100_DRC_QR_SHIFT                          4  /* DRC_QR */
+#define WM5100_DRC_QR_WIDTH                          1  /* DRC_QR */
+#define WM5100_DRC_ANTICLIP                     0x0008  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_MASK                0x0008  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_SHIFT                    3  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_WIDTH                    1  /* DRC_ANTICLIP */
+#define WM5100_DRCL_ENA                         0x0002  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_MASK                    0x0002  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_SHIFT                        1  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_WIDTH                        1  /* DRCL_ENA */
+#define WM5100_DRCR_ENA                         0x0001  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_MASK                    0x0001  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_SHIFT                        0  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_WIDTH                        1  /* DRCR_ENA */
+
+/*
+ * R3713 (0xE81) - DRC1 ctrl2
+ */
+#define WM5100_DRC_ATK_MASK                     0x1E00  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_ATK_SHIFT                         9  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_ATK_WIDTH                         4  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_DCY_MASK                     0x01E0  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_DCY_SHIFT                         5  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_DCY_WIDTH                         4  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_MINGAIN_MASK                 0x001C  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MINGAIN_SHIFT                     2  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MINGAIN_WIDTH                     3  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MAXGAIN_MASK                 0x0003  /* DRC_MAXGAIN - [1:0] */
+#define WM5100_DRC_MAXGAIN_SHIFT                     0  /* DRC_MAXGAIN - [1:0] */
+#define WM5100_DRC_MAXGAIN_WIDTH                     2  /* DRC_MAXGAIN - [1:0] */
+
+/*
+ * R3714 (0xE82) - DRC1 ctrl3
+ */
+#define WM5100_DRC_NG_MINGAIN_MASK              0xF000  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_MINGAIN_SHIFT                 12  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_MINGAIN_WIDTH                  4  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_EXP_MASK                  0x0C00  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_NG_EXP_SHIFT                     10  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_NG_EXP_WIDTH                      2  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_QR_THR_MASK                  0x0300  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_THR_SHIFT                      8  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_THR_WIDTH                      2  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_DCY_MASK                  0x00C0  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_QR_DCY_SHIFT                      6  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_QR_DCY_WIDTH                      2  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_HI_COMP_MASK                 0x0038  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_HI_COMP_SHIFT                     3  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_HI_COMP_WIDTH                     3  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_LO_COMP_MASK                 0x0007  /* DRC_LO_COMP - [2:0] */
+#define WM5100_DRC_LO_COMP_SHIFT                     0  /* DRC_LO_COMP - [2:0] */
+#define WM5100_DRC_LO_COMP_WIDTH                     3  /* DRC_LO_COMP - [2:0] */
+
+/*
+ * R3715 (0xE83) - DRC1 ctrl4
+ */
+#define WM5100_DRC_KNEE_IP_MASK                 0x07E0  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_IP_SHIFT                     5  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_IP_WIDTH                     6  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_OP_MASK                 0x001F  /* DRC_KNEE_OP - [4:0] */
+#define WM5100_DRC_KNEE_OP_SHIFT                     0  /* DRC_KNEE_OP - [4:0] */
+#define WM5100_DRC_KNEE_OP_WIDTH                     5  /* DRC_KNEE_OP - [4:0] */
+
+/*
+ * R3716 (0xE84) - DRC1 ctrl5
+ */
+#define WM5100_DRC_KNEE2_IP_MASK                0x03E0  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_IP_SHIFT                    5  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_IP_WIDTH                    5  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_OP_MASK                0x001F  /* DRC_KNEE2_OP - [4:0] */
+#define WM5100_DRC_KNEE2_OP_SHIFT                    0  /* DRC_KNEE2_OP - [4:0] */
+#define WM5100_DRC_KNEE2_OP_WIDTH                    5  /* DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R3776 (0xEC0) - HPLPF1_1
+ */
+#define WM5100_LHPF1_MODE                       0x0002  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_MASK                  0x0002  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_SHIFT                      1  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_WIDTH                      1  /* LHPF1_MODE */
+#define WM5100_LHPF1_ENA                        0x0001  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_MASK                   0x0001  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_SHIFT                       0  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_WIDTH                       1  /* LHPF1_ENA */
+
+/*
+ * R3777 (0xEC1) - HPLPF1_2
+ */
+#define WM5100_LHPF1_COEFF_MASK                 0xFFFF  /* LHPF1_COEFF - [15:0] */
+#define WM5100_LHPF1_COEFF_SHIFT                     0  /* LHPF1_COEFF - [15:0] */
+#define WM5100_LHPF1_COEFF_WIDTH                    16  /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R3780 (0xEC4) - HPLPF2_1
+ */
+#define WM5100_LHPF2_MODE                       0x0002  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_MASK                  0x0002  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_SHIFT                      1  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_WIDTH                      1  /* LHPF2_MODE */
+#define WM5100_LHPF2_ENA                        0x0001  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_MASK                   0x0001  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_SHIFT                       0  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_WIDTH                       1  /* LHPF2_ENA */
+
+/*
+ * R3781 (0xEC5) - HPLPF2_2
+ */
+#define WM5100_LHPF2_COEFF_MASK                 0xFFFF  /* LHPF2_COEFF - [15:0] */
+#define WM5100_LHPF2_COEFF_SHIFT                     0  /* LHPF2_COEFF - [15:0] */
+#define WM5100_LHPF2_COEFF_WIDTH                    16  /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R3784 (0xEC8) - HPLPF3_1
+ */
+#define WM5100_LHPF3_MODE                       0x0002  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_MASK                  0x0002  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_SHIFT                      1  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_WIDTH                      1  /* LHPF3_MODE */
+#define WM5100_LHPF3_ENA                        0x0001  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_MASK                   0x0001  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_SHIFT                       0  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_WIDTH                       1  /* LHPF3_ENA */
+
+/*
+ * R3785 (0xEC9) - HPLPF3_2
+ */
+#define WM5100_LHPF3_COEFF_MASK                 0xFFFF  /* LHPF3_COEFF - [15:0] */
+#define WM5100_LHPF3_COEFF_SHIFT                     0  /* LHPF3_COEFF - [15:0] */
+#define WM5100_LHPF3_COEFF_WIDTH                    16  /* LHPF3_COEFF - [15:0] */
+
+/*
+ * R3788 (0xECC) - HPLPF4_1
+ */
+#define WM5100_LHPF4_MODE                       0x0002  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_MASK                  0x0002  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_SHIFT                      1  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_WIDTH                      1  /* LHPF4_MODE */
+#define WM5100_LHPF4_ENA                        0x0001  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_MASK                   0x0001  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_SHIFT                       0  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_WIDTH                       1  /* LHPF4_ENA */
+
+/*
+ * R3789 (0xECD) - HPLPF4_2
+ */
+#define WM5100_LHPF4_COEFF_MASK                 0xFFFF  /* LHPF4_COEFF - [15:0] */
+#define WM5100_LHPF4_COEFF_SHIFT                     0  /* LHPF4_COEFF - [15:0] */
+#define WM5100_LHPF4_COEFF_WIDTH                    16  /* LHPF4_COEFF - [15:0] */
+
+/*
+ * R16384 (0x4000) - DSP1 DM 0
+ */
+#define WM5100_DSP1_DM_START_1_MASK             0x00FF  /* DSP1_DM_START - [7:0] */
+#define WM5100_DSP1_DM_START_1_SHIFT                 0  /* DSP1_DM_START - [7:0] */
+#define WM5100_DSP1_DM_START_1_WIDTH                 8  /* DSP1_DM_START - [7:0] */
+
+/*
+ * R16385 (0x4001) - DSP1 DM 1
+ */
+#define WM5100_DSP1_DM_START_MASK               0xFFFF  /* DSP1_DM_START - [15:0] */
+#define WM5100_DSP1_DM_START_SHIFT                   0  /* DSP1_DM_START - [15:0] */
+#define WM5100_DSP1_DM_START_WIDTH                  16  /* DSP1_DM_START - [15:0] */
+
+/*
+ * R16386 (0x4002) - DSP1 DM 2
+ */
+#define WM5100_DSP1_DM_1_1_MASK                 0x00FF  /* DSP1_DM_1 - [7:0] */
+#define WM5100_DSP1_DM_1_1_SHIFT                     0  /* DSP1_DM_1 - [7:0] */
+#define WM5100_DSP1_DM_1_1_WIDTH                     8  /* DSP1_DM_1 - [7:0] */
+
+/*
+ * R16387 (0x4003) - DSP1 DM 3
+ */
+#define WM5100_DSP1_DM_1_MASK                   0xFFFF  /* DSP1_DM_1 - [15:0] */
+#define WM5100_DSP1_DM_1_SHIFT                       0  /* DSP1_DM_1 - [15:0] */
+#define WM5100_DSP1_DM_1_WIDTH                      16  /* DSP1_DM_1 - [15:0] */
+
+/*
+ * R16892 (0x41FC) - DSP1 DM 508
+ */
+#define WM5100_DSP1_DM_254_1_MASK               0x00FF  /* DSP1_DM_254 - [7:0] */
+#define WM5100_DSP1_DM_254_1_SHIFT                   0  /* DSP1_DM_254 - [7:0] */
+#define WM5100_DSP1_DM_254_1_WIDTH                   8  /* DSP1_DM_254 - [7:0] */
+
+/*
+ * R16893 (0x41FD) - DSP1 DM 509
+ */
+#define WM5100_DSP1_DM_254_MASK                 0xFFFF  /* DSP1_DM_254 - [15:0] */
+#define WM5100_DSP1_DM_254_SHIFT                     0  /* DSP1_DM_254 - [15:0] */
+#define WM5100_DSP1_DM_254_WIDTH                    16  /* DSP1_DM_254 - [15:0] */
+
+/*
+ * R16894 (0x41FE) - DSP1 DM 510
+ */
+#define WM5100_DSP1_DM_END_1_MASK               0x00FF  /* DSP1_DM_END - [7:0] */
+#define WM5100_DSP1_DM_END_1_SHIFT                   0  /* DSP1_DM_END - [7:0] */
+#define WM5100_DSP1_DM_END_1_WIDTH                   8  /* DSP1_DM_END - [7:0] */
+
+/*
+ * R16895 (0x41FF) - DSP1 DM 511
+ */
+#define WM5100_DSP1_DM_END_MASK                 0xFFFF  /* DSP1_DM_END - [15:0] */
+#define WM5100_DSP1_DM_END_SHIFT                     0  /* DSP1_DM_END - [15:0] */
+#define WM5100_DSP1_DM_END_WIDTH                    16  /* DSP1_DM_END - [15:0] */
+
+/*
+ * R18432 (0x4800) - DSP1 PM 0
+ */
+#define WM5100_DSP1_PM_START_2_MASK             0x00FF  /* DSP1_PM_START - [7:0] */
+#define WM5100_DSP1_PM_START_2_SHIFT                 0  /* DSP1_PM_START - [7:0] */
+#define WM5100_DSP1_PM_START_2_WIDTH                 8  /* DSP1_PM_START - [7:0] */
+
+/*
+ * R18433 (0x4801) - DSP1 PM 1
+ */
+#define WM5100_DSP1_PM_START_1_MASK             0xFFFF  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_1_SHIFT                 0  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_1_WIDTH                16  /* DSP1_PM_START - [15:0] */
+
+/*
+ * R18434 (0x4802) - DSP1 PM 2
+ */
+#define WM5100_DSP1_PM_START_MASK               0xFFFF  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_SHIFT                   0  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_WIDTH                  16  /* DSP1_PM_START - [15:0] */
+
+/*
+ * R18435 (0x4803) - DSP1 PM 3
+ */
+#define WM5100_DSP1_PM_1_2_MASK                 0x00FF  /* DSP1_PM_1 - [7:0] */
+#define WM5100_DSP1_PM_1_2_SHIFT                     0  /* DSP1_PM_1 - [7:0] */
+#define WM5100_DSP1_PM_1_2_WIDTH                     8  /* DSP1_PM_1 - [7:0] */
+
+/*
+ * R18436 (0x4804) - DSP1 PM 4
+ */
+#define WM5100_DSP1_PM_1_1_MASK                 0xFFFF  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_1_SHIFT                     0  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_1_WIDTH                    16  /* DSP1_PM_1 - [15:0] */
+
+/*
+ * R18437 (0x4805) - DSP1 PM 5
+ */
+#define WM5100_DSP1_PM_1_MASK                   0xFFFF  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_SHIFT                       0  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_WIDTH                      16  /* DSP1_PM_1 - [15:0] */
+
+/*
+ * R19962 (0x4DFA) - DSP1 PM 1530
+ */
+#define WM5100_DSP1_PM_510_2_MASK               0x00FF  /* DSP1_PM_510 - [7:0] */
+#define WM5100_DSP1_PM_510_2_SHIFT                   0  /* DSP1_PM_510 - [7:0] */
+#define WM5100_DSP1_PM_510_2_WIDTH                   8  /* DSP1_PM_510 - [7:0] */
+
+/*
+ * R19963 (0x4DFB) - DSP1 PM 1531
+ */
+#define WM5100_DSP1_PM_510_1_MASK               0xFFFF  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_1_SHIFT                   0  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_1_WIDTH                  16  /* DSP1_PM_510 - [15:0] */
+
+/*
+ * R19964 (0x4DFC) - DSP1 PM 1532
+ */
+#define WM5100_DSP1_PM_510_MASK                 0xFFFF  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_SHIFT                     0  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_WIDTH                    16  /* DSP1_PM_510 - [15:0] */
+
+/*
+ * R19965 (0x4DFD) - DSP1 PM 1533
+ */
+#define WM5100_DSP1_PM_END_2_MASK               0x00FF  /* DSP1_PM_END - [7:0] */
+#define WM5100_DSP1_PM_END_2_SHIFT                   0  /* DSP1_PM_END - [7:0] */
+#define WM5100_DSP1_PM_END_2_WIDTH                   8  /* DSP1_PM_END - [7:0] */
+
+/*
+ * R19966 (0x4DFE) - DSP1 PM 1534
+ */
+#define WM5100_DSP1_PM_END_1_MASK               0xFFFF  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_1_SHIFT                   0  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_1_WIDTH                  16  /* DSP1_PM_END - [15:0] */
+
+/*
+ * R19967 (0x4DFF) - DSP1 PM 1535
+ */
+#define WM5100_DSP1_PM_END_MASK                 0xFFFF  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_SHIFT                     0  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_WIDTH                    16  /* DSP1_PM_END - [15:0] */
+
+/*
+ * R20480 (0x5000) - DSP1 ZM 0
+ */
+#define WM5100_DSP1_ZM_START_1_MASK             0x00FF  /* DSP1_ZM_START - [7:0] */
+#define WM5100_DSP1_ZM_START_1_SHIFT                 0  /* DSP1_ZM_START - [7:0] */
+#define WM5100_DSP1_ZM_START_1_WIDTH                 8  /* DSP1_ZM_START - [7:0] */
+
+/*
+ * R20481 (0x5001) - DSP1 ZM 1
+ */
+#define WM5100_DSP1_ZM_START_MASK               0xFFFF  /* DSP1_ZM_START - [15:0] */
+#define WM5100_DSP1_ZM_START_SHIFT                   0  /* DSP1_ZM_START - [15:0] */
+#define WM5100_DSP1_ZM_START_WIDTH                  16  /* DSP1_ZM_START - [15:0] */
+
+/*
+ * R20482 (0x5002) - DSP1 ZM 2
+ */
+#define WM5100_DSP1_ZM_1_1_MASK                 0x00FF  /* DSP1_ZM_1 - [7:0] */
+#define WM5100_DSP1_ZM_1_1_SHIFT                     0  /* DSP1_ZM_1 - [7:0] */
+#define WM5100_DSP1_ZM_1_1_WIDTH                     8  /* DSP1_ZM_1 - [7:0] */
+
+/*
+ * R20483 (0x5003) - DSP1 ZM 3
+ */
+#define WM5100_DSP1_ZM_1_MASK                   0xFFFF  /* DSP1_ZM_1 - [15:0] */
+#define WM5100_DSP1_ZM_1_SHIFT                       0  /* DSP1_ZM_1 - [15:0] */
+#define WM5100_DSP1_ZM_1_WIDTH                      16  /* DSP1_ZM_1 - [15:0] */
+
+/*
+ * R22524 (0x57FC) - DSP1 ZM 2044
+ */
+#define WM5100_DSP1_ZM_1022_1_MASK              0x00FF  /* DSP1_ZM_1022 - [7:0] */
+#define WM5100_DSP1_ZM_1022_1_SHIFT                  0  /* DSP1_ZM_1022 - [7:0] */
+#define WM5100_DSP1_ZM_1022_1_WIDTH                  8  /* DSP1_ZM_1022 - [7:0] */
+
+/*
+ * R22525 (0x57FD) - DSP1 ZM 2045
+ */
+#define WM5100_DSP1_ZM_1022_MASK                0xFFFF  /* DSP1_ZM_1022 - [15:0] */
+#define WM5100_DSP1_ZM_1022_SHIFT                    0  /* DSP1_ZM_1022 - [15:0] */
+#define WM5100_DSP1_ZM_1022_WIDTH                   16  /* DSP1_ZM_1022 - [15:0] */
+
+/*
+ * R22526 (0x57FE) - DSP1 ZM 2046
+ */
+#define WM5100_DSP1_ZM_END_1_MASK               0x00FF  /* DSP1_ZM_END - [7:0] */
+#define WM5100_DSP1_ZM_END_1_SHIFT                   0  /* DSP1_ZM_END - [7:0] */
+#define WM5100_DSP1_ZM_END_1_WIDTH                   8  /* DSP1_ZM_END - [7:0] */
+
+/*
+ * R22527 (0x57FF) - DSP1 ZM 2047
+ */
+#define WM5100_DSP1_ZM_END_MASK                 0xFFFF  /* DSP1_ZM_END - [15:0] */
+#define WM5100_DSP1_ZM_END_SHIFT                     0  /* DSP1_ZM_END - [15:0] */
+#define WM5100_DSP1_ZM_END_WIDTH                    16  /* DSP1_ZM_END - [15:0] */
+
+/*
+ * R24576 (0x6000) - DSP2 DM 0
+ */
+#define WM5100_DSP2_DM_START_1_MASK             0x00FF  /* DSP2_DM_START - [7:0] */
+#define WM5100_DSP2_DM_START_1_SHIFT                 0  /* DSP2_DM_START - [7:0] */
+#define WM5100_DSP2_DM_START_1_WIDTH                 8  /* DSP2_DM_START - [7:0] */
+
+/*
+ * R24577 (0x6001) - DSP2 DM 1
+ */
+#define WM5100_DSP2_DM_START_MASK               0xFFFF  /* DSP2_DM_START - [15:0] */
+#define WM5100_DSP2_DM_START_SHIFT                   0  /* DSP2_DM_START - [15:0] */
+#define WM5100_DSP2_DM_START_WIDTH                  16  /* DSP2_DM_START - [15:0] */
+
+/*
+ * R24578 (0x6002) - DSP2 DM 2
+ */
+#define WM5100_DSP2_DM_1_1_MASK                 0x00FF  /* DSP2_DM_1 - [7:0] */
+#define WM5100_DSP2_DM_1_1_SHIFT                     0  /* DSP2_DM_1 - [7:0] */
+#define WM5100_DSP2_DM_1_1_WIDTH                     8  /* DSP2_DM_1 - [7:0] */
+
+/*
+ * R24579 (0x6003) - DSP2 DM 3
+ */
+#define WM5100_DSP2_DM_1_MASK                   0xFFFF  /* DSP2_DM_1 - [15:0] */
+#define WM5100_DSP2_DM_1_SHIFT                       0  /* DSP2_DM_1 - [15:0] */
+#define WM5100_DSP2_DM_1_WIDTH                      16  /* DSP2_DM_1 - [15:0] */
+
+/*
+ * R25084 (0x61FC) - DSP2 DM 508
+ */
+#define WM5100_DSP2_DM_254_1_MASK               0x00FF  /* DSP2_DM_254 - [7:0] */
+#define WM5100_DSP2_DM_254_1_SHIFT                   0  /* DSP2_DM_254 - [7:0] */
+#define WM5100_DSP2_DM_254_1_WIDTH                   8  /* DSP2_DM_254 - [7:0] */
+
+/*
+ * R25085 (0x61FD) - DSP2 DM 509
+ */
+#define WM5100_DSP2_DM_254_MASK                 0xFFFF  /* DSP2_DM_254 - [15:0] */
+#define WM5100_DSP2_DM_254_SHIFT                     0  /* DSP2_DM_254 - [15:0] */
+#define WM5100_DSP2_DM_254_WIDTH                    16  /* DSP2_DM_254 - [15:0] */
+
+/*
+ * R25086 (0x61FE) - DSP2 DM 510
+ */
+#define WM5100_DSP2_DM_END_1_MASK               0x00FF  /* DSP2_DM_END - [7:0] */
+#define WM5100_DSP2_DM_END_1_SHIFT                   0  /* DSP2_DM_END - [7:0] */
+#define WM5100_DSP2_DM_END_1_WIDTH                   8  /* DSP2_DM_END - [7:0] */
+
+/*
+ * R25087 (0x61FF) - DSP2 DM 511
+ */
+#define WM5100_DSP2_DM_END_MASK                 0xFFFF  /* DSP2_DM_END - [15:0] */
+#define WM5100_DSP2_DM_END_SHIFT                     0  /* DSP2_DM_END - [15:0] */
+#define WM5100_DSP2_DM_END_WIDTH                    16  /* DSP2_DM_END - [15:0] */
+
+/*
+ * R26624 (0x6800) - DSP2 PM 0
+ */
+#define WM5100_DSP2_PM_START_2_MASK             0x00FF  /* DSP2_PM_START - [7:0] */
+#define WM5100_DSP2_PM_START_2_SHIFT                 0  /* DSP2_PM_START - [7:0] */
+#define WM5100_DSP2_PM_START_2_WIDTH                 8  /* DSP2_PM_START - [7:0] */
+
+/*
+ * R26625 (0x6801) - DSP2 PM 1
+ */
+#define WM5100_DSP2_PM_START_1_MASK             0xFFFF  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_1_SHIFT                 0  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_1_WIDTH                16  /* DSP2_PM_START - [15:0] */
+
+/*
+ * R26626 (0x6802) - DSP2 PM 2
+ */
+#define WM5100_DSP2_PM_START_MASK               0xFFFF  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_SHIFT                   0  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_WIDTH                  16  /* DSP2_PM_START - [15:0] */
+
+/*
+ * R26627 (0x6803) - DSP2 PM 3
+ */
+#define WM5100_DSP2_PM_1_2_MASK                 0x00FF  /* DSP2_PM_1 - [7:0] */
+#define WM5100_DSP2_PM_1_2_SHIFT                     0  /* DSP2_PM_1 - [7:0] */
+#define WM5100_DSP2_PM_1_2_WIDTH                     8  /* DSP2_PM_1 - [7:0] */
+
+/*
+ * R26628 (0x6804) - DSP2 PM 4
+ */
+#define WM5100_DSP2_PM_1_1_MASK                 0xFFFF  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_1_SHIFT                     0  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_1_WIDTH                    16  /* DSP2_PM_1 - [15:0] */
+
+/*
+ * R26629 (0x6805) - DSP2 PM 5
+ */
+#define WM5100_DSP2_PM_1_MASK                   0xFFFF  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_SHIFT                       0  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_WIDTH                      16  /* DSP2_PM_1 - [15:0] */
+
+/*
+ * R28154 (0x6DFA) - DSP2 PM 1530
+ */
+#define WM5100_DSP2_PM_510_2_MASK               0x00FF  /* DSP2_PM_510 - [7:0] */
+#define WM5100_DSP2_PM_510_2_SHIFT                   0  /* DSP2_PM_510 - [7:0] */
+#define WM5100_DSP2_PM_510_2_WIDTH                   8  /* DSP2_PM_510 - [7:0] */
+
+/*
+ * R28155 (0x6DFB) - DSP2 PM 1531
+ */
+#define WM5100_DSP2_PM_510_1_MASK               0xFFFF  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_1_SHIFT                   0  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_1_WIDTH                  16  /* DSP2_PM_510 - [15:0] */
+
+/*
+ * R28156 (0x6DFC) - DSP2 PM 1532
+ */
+#define WM5100_DSP2_PM_510_MASK                 0xFFFF  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_SHIFT                     0  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_WIDTH                    16  /* DSP2_PM_510 - [15:0] */
+
+/*
+ * R28157 (0x6DFD) - DSP2 PM 1533
+ */
+#define WM5100_DSP2_PM_END_2_MASK               0x00FF  /* DSP2_PM_END - [7:0] */
+#define WM5100_DSP2_PM_END_2_SHIFT                   0  /* DSP2_PM_END - [7:0] */
+#define WM5100_DSP2_PM_END_2_WIDTH                   8  /* DSP2_PM_END - [7:0] */
+
+/*
+ * R28158 (0x6DFE) - DSP2 PM 1534
+ */
+#define WM5100_DSP2_PM_END_1_MASK               0xFFFF  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_1_SHIFT                   0  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_1_WIDTH                  16  /* DSP2_PM_END - [15:0] */
+
+/*
+ * R28159 (0x6DFF) - DSP2 PM 1535
+ */
+#define WM5100_DSP2_PM_END_MASK                 0xFFFF  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_SHIFT                     0  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_WIDTH                    16  /* DSP2_PM_END - [15:0] */
+
+/*
+ * R28672 (0x7000) - DSP2 ZM 0
+ */
+#define WM5100_DSP2_ZM_START_1_MASK             0x00FF  /* DSP2_ZM_START - [7:0] */
+#define WM5100_DSP2_ZM_START_1_SHIFT                 0  /* DSP2_ZM_START - [7:0] */
+#define WM5100_DSP2_ZM_START_1_WIDTH                 8  /* DSP2_ZM_START - [7:0] */
+
+/*
+ * R28673 (0x7001) - DSP2 ZM 1
+ */
+#define WM5100_DSP2_ZM_START_MASK               0xFFFF  /* DSP2_ZM_START - [15:0] */
+#define WM5100_DSP2_ZM_START_SHIFT                   0  /* DSP2_ZM_START - [15:0] */
+#define WM5100_DSP2_ZM_START_WIDTH                  16  /* DSP2_ZM_START - [15:0] */
+
+/*
+ * R28674 (0x7002) - DSP2 ZM 2
+ */
+#define WM5100_DSP2_ZM_1_1_MASK                 0x00FF  /* DSP2_ZM_1 - [7:0] */
+#define WM5100_DSP2_ZM_1_1_SHIFT                     0  /* DSP2_ZM_1 - [7:0] */
+#define WM5100_DSP2_ZM_1_1_WIDTH                     8  /* DSP2_ZM_1 - [7:0] */
+
+/*
+ * R28675 (0x7003) - DSP2 ZM 3
+ */
+#define WM5100_DSP2_ZM_1_MASK                   0xFFFF  /* DSP2_ZM_1 - [15:0] */
+#define WM5100_DSP2_ZM_1_SHIFT                       0  /* DSP2_ZM_1 - [15:0] */
+#define WM5100_DSP2_ZM_1_WIDTH                      16  /* DSP2_ZM_1 - [15:0] */
+
+/*
+ * R30716 (0x77FC) - DSP2 ZM 2044
+ */
+#define WM5100_DSP2_ZM_1022_1_MASK              0x00FF  /* DSP2_ZM_1022 - [7:0] */
+#define WM5100_DSP2_ZM_1022_1_SHIFT                  0  /* DSP2_ZM_1022 - [7:0] */
+#define WM5100_DSP2_ZM_1022_1_WIDTH                  8  /* DSP2_ZM_1022 - [7:0] */
+
+/*
+ * R30717 (0x77FD) - DSP2 ZM 2045
+ */
+#define WM5100_DSP2_ZM_1022_MASK                0xFFFF  /* DSP2_ZM_1022 - [15:0] */
+#define WM5100_DSP2_ZM_1022_SHIFT                    0  /* DSP2_ZM_1022 - [15:0] */
+#define WM5100_DSP2_ZM_1022_WIDTH                   16  /* DSP2_ZM_1022 - [15:0] */
+
+/*
+ * R30718 (0x77FE) - DSP2 ZM 2046
+ */
+#define WM5100_DSP2_ZM_END_1_MASK               0x00FF  /* DSP2_ZM_END - [7:0] */
+#define WM5100_DSP2_ZM_END_1_SHIFT                   0  /* DSP2_ZM_END - [7:0] */
+#define WM5100_DSP2_ZM_END_1_WIDTH                   8  /* DSP2_ZM_END - [7:0] */
+
+/*
+ * R30719 (0x77FF) - DSP2 ZM 2047
+ */
+#define WM5100_DSP2_ZM_END_MASK                 0xFFFF  /* DSP2_ZM_END - [15:0] */
+#define WM5100_DSP2_ZM_END_SHIFT                     0  /* DSP2_ZM_END - [15:0] */
+#define WM5100_DSP2_ZM_END_WIDTH                    16  /* DSP2_ZM_END - [15:0] */
+
+/*
+ * R32768 (0x8000) - DSP3 DM 0
+ */
+#define WM5100_DSP3_DM_START_1_MASK             0x00FF  /* DSP3_DM_START - [7:0] */
+#define WM5100_DSP3_DM_START_1_SHIFT                 0  /* DSP3_DM_START - [7:0] */
+#define WM5100_DSP3_DM_START_1_WIDTH                 8  /* DSP3_DM_START - [7:0] */
+
+/*
+ * R32769 (0x8001) - DSP3 DM 1
+ */
+#define WM5100_DSP3_DM_START_MASK               0xFFFF  /* DSP3_DM_START - [15:0] */
+#define WM5100_DSP3_DM_START_SHIFT                   0  /* DSP3_DM_START - [15:0] */
+#define WM5100_DSP3_DM_START_WIDTH                  16  /* DSP3_DM_START - [15:0] */
+
+/*
+ * R32770 (0x8002) - DSP3 DM 2
+ */
+#define WM5100_DSP3_DM_1_1_MASK                 0x00FF  /* DSP3_DM_1 - [7:0] */
+#define WM5100_DSP3_DM_1_1_SHIFT                     0  /* DSP3_DM_1 - [7:0] */
+#define WM5100_DSP3_DM_1_1_WIDTH                     8  /* DSP3_DM_1 - [7:0] */
+
+/*
+ * R32771 (0x8003) - DSP3 DM 3
+ */
+#define WM5100_DSP3_DM_1_MASK                   0xFFFF  /* DSP3_DM_1 - [15:0] */
+#define WM5100_DSP3_DM_1_SHIFT                       0  /* DSP3_DM_1 - [15:0] */
+#define WM5100_DSP3_DM_1_WIDTH                      16  /* DSP3_DM_1 - [15:0] */
+
+/*
+ * R33276 (0x81FC) - DSP3 DM 508
+ */
+#define WM5100_DSP3_DM_254_1_MASK               0x00FF  /* DSP3_DM_254 - [7:0] */
+#define WM5100_DSP3_DM_254_1_SHIFT                   0  /* DSP3_DM_254 - [7:0] */
+#define WM5100_DSP3_DM_254_1_WIDTH                   8  /* DSP3_DM_254 - [7:0] */
+
+/*
+ * R33277 (0x81FD) - DSP3 DM 509
+ */
+#define WM5100_DSP3_DM_254_MASK                 0xFFFF  /* DSP3_DM_254 - [15:0] */
+#define WM5100_DSP3_DM_254_SHIFT                     0  /* DSP3_DM_254 - [15:0] */
+#define WM5100_DSP3_DM_254_WIDTH                    16  /* DSP3_DM_254 - [15:0] */
+
+/*
+ * R33278 (0x81FE) - DSP3 DM 510
+ */
+#define WM5100_DSP3_DM_END_1_MASK               0x00FF  /* DSP3_DM_END - [7:0] */
+#define WM5100_DSP3_DM_END_1_SHIFT                   0  /* DSP3_DM_END - [7:0] */
+#define WM5100_DSP3_DM_END_1_WIDTH                   8  /* DSP3_DM_END - [7:0] */
+
+/*
+ * R33279 (0x81FF) - DSP3 DM 511
+ */
+#define WM5100_DSP3_DM_END_MASK                 0xFFFF  /* DSP3_DM_END - [15:0] */
+#define WM5100_DSP3_DM_END_SHIFT                     0  /* DSP3_DM_END - [15:0] */
+#define WM5100_DSP3_DM_END_WIDTH                    16  /* DSP3_DM_END - [15:0] */
+
+/*
+ * R34816 (0x8800) - DSP3 PM 0
+ */
+#define WM5100_DSP3_PM_START_2_MASK             0x00FF  /* DSP3_PM_START - [7:0] */
+#define WM5100_DSP3_PM_START_2_SHIFT                 0  /* DSP3_PM_START - [7:0] */
+#define WM5100_DSP3_PM_START_2_WIDTH                 8  /* DSP3_PM_START - [7:0] */
+
+/*
+ * R34817 (0x8801) - DSP3 PM 1
+ */
+#define WM5100_DSP3_PM_START_1_MASK             0xFFFF  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_1_SHIFT                 0  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_1_WIDTH                16  /* DSP3_PM_START - [15:0] */
+
+/*
+ * R34818 (0x8802) - DSP3 PM 2
+ */
+#define WM5100_DSP3_PM_START_MASK               0xFFFF  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_SHIFT                   0  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_WIDTH                  16  /* DSP3_PM_START - [15:0] */
+
+/*
+ * R34819 (0x8803) - DSP3 PM 3
+ */
+#define WM5100_DSP3_PM_1_2_MASK                 0x00FF  /* DSP3_PM_1 - [7:0] */
+#define WM5100_DSP3_PM_1_2_SHIFT                     0  /* DSP3_PM_1 - [7:0] */
+#define WM5100_DSP3_PM_1_2_WIDTH                     8  /* DSP3_PM_1 - [7:0] */
+
+/*
+ * R34820 (0x8804) - DSP3 PM 4
+ */
+#define WM5100_DSP3_PM_1_1_MASK                 0xFFFF  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_1_SHIFT                     0  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_1_WIDTH                    16  /* DSP3_PM_1 - [15:0] */
+
+/*
+ * R34821 (0x8805) - DSP3 PM 5
+ */
+#define WM5100_DSP3_PM_1_MASK                   0xFFFF  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_SHIFT                       0  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_WIDTH                      16  /* DSP3_PM_1 - [15:0] */
+
+/*
+ * R36346 (0x8DFA) - DSP3 PM 1530
+ */
+#define WM5100_DSP3_PM_510_2_MASK               0x00FF  /* DSP3_PM_510 - [7:0] */
+#define WM5100_DSP3_PM_510_2_SHIFT                   0  /* DSP3_PM_510 - [7:0] */
+#define WM5100_DSP3_PM_510_2_WIDTH                   8  /* DSP3_PM_510 - [7:0] */
+
+/*
+ * R36347 (0x8DFB) - DSP3 PM 1531
+ */
+#define WM5100_DSP3_PM_510_1_MASK               0xFFFF  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_1_SHIFT                   0  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_1_WIDTH                  16  /* DSP3_PM_510 - [15:0] */
+
+/*
+ * R36348 (0x8DFC) - DSP3 PM 1532
+ */
+#define WM5100_DSP3_PM_510_MASK                 0xFFFF  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_SHIFT                     0  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_WIDTH                    16  /* DSP3_PM_510 - [15:0] */
+
+/*
+ * R36349 (0x8DFD) - DSP3 PM 1533
+ */
+#define WM5100_DSP3_PM_END_2_MASK               0x00FF  /* DSP3_PM_END - [7:0] */
+#define WM5100_DSP3_PM_END_2_SHIFT                   0  /* DSP3_PM_END - [7:0] */
+#define WM5100_DSP3_PM_END_2_WIDTH                   8  /* DSP3_PM_END - [7:0] */
+
+/*
+ * R36350 (0x8DFE) - DSP3 PM 1534
+ */
+#define WM5100_DSP3_PM_END_1_MASK               0xFFFF  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_1_SHIFT                   0  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_1_WIDTH                  16  /* DSP3_PM_END - [15:0] */
+
+/*
+ * R36351 (0x8DFF) - DSP3 PM 1535
+ */
+#define WM5100_DSP3_PM_END_MASK                 0xFFFF  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_SHIFT                     0  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_WIDTH                    16  /* DSP3_PM_END - [15:0] */
+
+/*
+ * R36864 (0x9000) - DSP3 ZM 0
+ */
+#define WM5100_DSP3_ZM_START_1_MASK             0x00FF  /* DSP3_ZM_START - [7:0] */
+#define WM5100_DSP3_ZM_START_1_SHIFT                 0  /* DSP3_ZM_START - [7:0] */
+#define WM5100_DSP3_ZM_START_1_WIDTH                 8  /* DSP3_ZM_START - [7:0] */
+
+/*
+ * R36865 (0x9001) - DSP3 ZM 1
+ */
+#define WM5100_DSP3_ZM_START_MASK               0xFFFF  /* DSP3_ZM_START - [15:0] */
+#define WM5100_DSP3_ZM_START_SHIFT                   0  /* DSP3_ZM_START - [15:0] */
+#define WM5100_DSP3_ZM_START_WIDTH                  16  /* DSP3_ZM_START - [15:0] */
+
+/*
+ * R36866 (0x9002) - DSP3 ZM 2
+ */
+#define WM5100_DSP3_ZM_1_1_MASK                 0x00FF  /* DSP3_ZM_1 - [7:0] */
+#define WM5100_DSP3_ZM_1_1_SHIFT                     0  /* DSP3_ZM_1 - [7:0] */
+#define WM5100_DSP3_ZM_1_1_WIDTH                     8  /* DSP3_ZM_1 - [7:0] */
+
+/*
+ * R36867 (0x9003) - DSP3 ZM 3
+ */
+#define WM5100_DSP3_ZM_1_MASK                   0xFFFF  /* DSP3_ZM_1 - [15:0] */
+#define WM5100_DSP3_ZM_1_SHIFT                       0  /* DSP3_ZM_1 - [15:0] */
+#define WM5100_DSP3_ZM_1_WIDTH                      16  /* DSP3_ZM_1 - [15:0] */
+
+/*
+ * R38908 (0x97FC) - DSP3 ZM 2044
+ */
+#define WM5100_DSP3_ZM_1022_1_MASK              0x00FF  /* DSP3_ZM_1022 - [7:0] */
+#define WM5100_DSP3_ZM_1022_1_SHIFT                  0  /* DSP3_ZM_1022 - [7:0] */
+#define WM5100_DSP3_ZM_1022_1_WIDTH                  8  /* DSP3_ZM_1022 - [7:0] */
+
+/*
+ * R38909 (0x97FD) - DSP3 ZM 2045
+ */
+#define WM5100_DSP3_ZM_1022_MASK                0xFFFF  /* DSP3_ZM_1022 - [15:0] */
+#define WM5100_DSP3_ZM_1022_SHIFT                    0  /* DSP3_ZM_1022 - [15:0] */
+#define WM5100_DSP3_ZM_1022_WIDTH                   16  /* DSP3_ZM_1022 - [15:0] */
+
+/*
+ * R38910 (0x97FE) - DSP3 ZM 2046
+ */
+#define WM5100_DSP3_ZM_END_1_MASK               0x00FF  /* DSP3_ZM_END - [7:0] */
+#define WM5100_DSP3_ZM_END_1_SHIFT                   0  /* DSP3_ZM_END - [7:0] */
+#define WM5100_DSP3_ZM_END_1_WIDTH                   8  /* DSP3_ZM_END - [7:0] */
+
+/*
+ * R38911 (0x97FF) - DSP3 ZM 2047
+ */
+#define WM5100_DSP3_ZM_END_MASK                 0xFFFF  /* DSP3_ZM_END - [15:0] */
+#define WM5100_DSP3_ZM_END_SHIFT                     0  /* DSP3_ZM_END - [15:0] */
+#define WM5100_DSP3_ZM_END_WIDTH                    16  /* DSP3_ZM_END - [15:0] */
+
+int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg);
+int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg);
+
+extern u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1];
+
+#endif
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 6d6dc9efe914..35f3ad83dfb6 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -355,7 +355,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
 			return 1;
 	}
 
-	ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+	ret = snd_soc_put_volsw(kcontrol, ucontrol);
 	if (ret < 0)
 		return ret;
 
@@ -392,23 +392,9 @@ static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
 		break;
 	}
 
-	return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+	return snd_soc_get_volsw(kcontrol, ucontrol);
 }
 
-/* double control with volume update */
-#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
-				xinvert, tlv_array) \
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
-		SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw_2r, \
-	.get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-		 .rshift = xshift, .max = xmax, .invert = xinvert}, }
-
 static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
 static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
 static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
@@ -443,26 +429,29 @@ static const unsigned int capture_sd_tlv[] = {
 static const struct snd_kcontrol_new wm8350_snd_controls[] = {
 	SOC_ENUM("Playback Deemphasis", wm8350_enum[0]),
 	SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]),
-	SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume",
+	SOC_DOUBLE_R_EXT_TLV("Playback PCM Volume",
 				WM8350_DAC_DIGITAL_VOLUME_L,
 				WM8350_DAC_DIGITAL_VOLUME_R,
-				0, 255, 0, dac_pcm_tlv),
+				0, 255, 0, wm8350_get_volsw_2r,
+				wm8350_put_volsw_2r_vu, dac_pcm_tlv),
 	SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
 	SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
 	SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
 	SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
 	SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
-	SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
+	SOC_DOUBLE_R_EXT_TLV("Capture PCM Volume",
 				WM8350_ADC_DIGITAL_VOLUME_L,
 				WM8350_ADC_DIGITAL_VOLUME_R,
-				0, 255, 0, adc_pcm_tlv),
+				0, 255, 0, wm8350_get_volsw_2r,
+				wm8350_put_volsw_2r_vu, adc_pcm_tlv),
 	SOC_DOUBLE_TLV("Capture Sidetone Volume",
 		       WM8350_ADC_DIVIDER,
 		       8, 4, 15, 1, capture_sd_tlv),
-	SOC_WM8350_DOUBLE_R_TLV("Capture Volume",
+	SOC_DOUBLE_R_EXT_TLV("Capture Volume",
 				WM8350_LEFT_INPUT_VOLUME,
 				WM8350_RIGHT_INPUT_VOLUME,
-				2, 63, 0, pre_amp_tlv),
+				2, 63, 0, wm8350_get_volsw_2r,
+				wm8350_put_volsw_2r_vu, pre_amp_tlv),
 	SOC_DOUBLE_R("Capture ZC Switch",
 		     WM8350_LEFT_INPUT_VOLUME,
 		     WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0),
@@ -490,17 +479,19 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
 	SOC_SINGLE_TLV("Out4 Capture Volume",
 		       WM8350_INPUT_MIXER_VOLUME,
 		       1, 7, 0, out_mix_tlv),
-	SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume",
+	SOC_DOUBLE_R_EXT_TLV("Out1 Playback Volume",
 				WM8350_LOUT1_VOLUME,
 				WM8350_ROUT1_VOLUME,
-				2, 63, 0, out_pga_tlv),
+				2, 63, 0, wm8350_get_volsw_2r,
+				wm8350_put_volsw_2r_vu, out_pga_tlv),
 	SOC_DOUBLE_R("Out1 Playback ZC Switch",
 		     WM8350_LOUT1_VOLUME,
 		     WM8350_ROUT1_VOLUME, 13, 1, 0),
-	SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume",
+	SOC_DOUBLE_R_EXT_TLV("Out2 Playback Volume",
 				WM8350_LOUT2_VOLUME,
 				WM8350_ROUT2_VOLUME,
-				2, 63, 0, out_pga_tlv),
+				2, 63, 0, wm8350_get_volsw_2r,
+				wm8350_put_volsw_2r_vu, out_pga_tlv),
 	SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME,
 		     WM8350_ROUT2_VOLUME, 13, 1, 0),
 	SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0),
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index fbee556cbf35..dc13be2a09c5 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -383,7 +383,7 @@ static int inmixer_event (struct snd_soc_dapm_widget *w,
 		(1 << WM8400_AINRMUX_PWR))) {
 		reg |= WM8400_AINR_ENA;
 	} else {
-		reg &= ~WM8400_AINL_ENA;
+		reg &= ~WM8400_AINR_ENA;
 	}
 	wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
 
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 55a4c830e111..07c9cc759e97 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -480,6 +480,8 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
 		power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
 
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			snd_soc_cache_sync(codec);
+
 			/* Initial cap charge at VMID 5k */
 			snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
 			mdelay(100);
@@ -541,18 +543,7 @@ static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8510_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) {
-		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
 	wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 5355a7a944f7..db7a6819499f 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -406,7 +406,6 @@ static int wm8523_probe(struct snd_soc_codec *codec)
 	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
 	int ret, i;
 
-	codec->hw_write = (hw_write_t)i2c_master_send;
 	wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
 	wm8523->rate_constraint.count =
 		ARRAY_SIZE(wm8523->rate_constraint_list);
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 4664c3a76c78..8212b3c8bfdd 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -213,7 +213,7 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
 	reg_cache[reg] = 0;
 	reg_cache[reg2] = 0;
 
-	ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+	ret = snd_soc_put_volsw(kcontrol, ucontrol);
 	if (ret < 0)
 		return ret;
 
@@ -224,31 +224,19 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
-				    xinvert, tlv_array)			\
-{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-		SNDRV_CTL_ELEM_ACCESS_READWRITE,  \
-	.tlv.p = (tlv_array), \
-	.info = snd_soc_info_volsw_2r, \
-	.get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \
-	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-		.max = xmax, .invert = xinvert} }
-
 static const struct snd_kcontrol_new wm8580_snd_controls[] = {
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume",
-			    WM8580_DIGITAL_ATTENUATION_DACL1,
-			    WM8580_DIGITAL_ATTENUATION_DACR1,
-			    0, 0xff, 0, dac_tlv),
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume",
-			    WM8580_DIGITAL_ATTENUATION_DACL2,
-			    WM8580_DIGITAL_ATTENUATION_DACR2,
-			    0, 0xff, 0, dac_tlv),
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume",
-			    WM8580_DIGITAL_ATTENUATION_DACL3,
-			    WM8580_DIGITAL_ATTENUATION_DACR3,
-			    0, 0xff, 0, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume",
+		     WM8580_DIGITAL_ATTENUATION_DACL1,
+		     WM8580_DIGITAL_ATTENUATION_DACR1,
+		     0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume",
+		     WM8580_DIGITAL_ATTENUATION_DACL2,
+		     WM8580_DIGITAL_ATTENUATION_DACR2,
+		     0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume",
+		     WM8580_DIGITAL_ATTENUATION_DACL3,
+		     WM8580_DIGITAL_ATTENUATION_DACR3,
+		     0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
 
 SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0),
 SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0),
@@ -442,8 +430,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
 	/* Always disable the PLL - it is not safe to leave it running
 	 * while reprogramming it.
 	 */
-	reg = snd_soc_read(codec, WM8580_PWRDN2);
-	snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
+	snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, pwr_mask);
 
 	if (!freq_in || !freq_out)
 		return 0;
@@ -461,8 +448,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
 	snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
 
 	/* All done, turn it on */
-	reg = snd_soc_read(codec, WM8580_PWRDN2);
-	snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
+	snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, 0);
 
 	return 0;
 }
@@ -760,7 +746,6 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 static int wm8580_set_bias_level(struct snd_soc_codec *codec,
 	enum snd_soc_bias_level level)
 {
-	u16 reg;
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 	case SND_SOC_BIAS_PREPARE:
@@ -769,20 +754,19 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
 			/* Power up and get individual control of the DACs */
-			reg = snd_soc_read(codec, WM8580_PWRDN1);
-			reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
-			snd_soc_write(codec, WM8580_PWRDN1, reg);
+			snd_soc_update_bits(codec, WM8580_PWRDN1,
+					    WM8580_PWRDN1_PWDN |
+					    WM8580_PWRDN1_ALLDACPD, 0);
 
 			/* Make VMID high impedance */
-			reg = snd_soc_read(codec,  WM8580_ADC_CONTROL1);
-			reg &= ~0x100;
-			snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
+			snd_soc_update_bits(codec, WM8580_ADC_CONTROL1,
+					    0x100, 0);
 		}
 		break;
 
 	case SND_SOC_BIAS_OFF:
-		reg = snd_soc_read(codec, WM8580_PWRDN1);
-		snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
+		snd_soc_update_bits(codec, WM8580_PWRDN1,
+				    WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN);
 		break;
 	}
 	codec->dapm.bias_level = level;
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index 8457d3cb5962..8d0347cf0e9a 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2006 Wolfson Microelectronics
  *
- * Author: Mike Arthur <linux@wolfsonmicro.com>
+ * Author: Mike Arthur <Mike.Arthur@wolfsonmicro.com>
  *
  * Based on wm8731.c by Richard Purdie
  *
@@ -287,7 +287,6 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
-
 static int wm8711_set_bias_level(struct snd_soc_codec *codec,
 	enum snd_soc_bias_level level)
 {
@@ -300,6 +299,9 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec,
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+			snd_soc_cache_sync(codec);
+
 		snd_soc_write(codec, WM8711_PWR, reg | 0x0040);
 		break;
 	case SND_SOC_BIAS_OFF:
@@ -346,25 +348,14 @@ static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8711_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) {
-		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
 	wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	return 0;
 }
 
 static int wm8711_probe(struct snd_soc_codec *codec)
 {
 	struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
-	int ret, reg;
+	int ret;
 
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);
 	if (ret < 0) {
@@ -381,10 +372,8 @@ static int wm8711_probe(struct snd_soc_codec *codec)
 	wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	/* Latch the update bits */
-	reg = snd_soc_read(codec, WM8711_LOUT1V);
-	snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8711_ROUT1V);
-	snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
+	snd_soc_update_bits(codec, WM8711_LOUT1V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8711_ROUT1V, 0x0100, 0x0100);
 
 	snd_soc_add_controls(codec, wm8711_snd_controls,
 			     ARRAY_SIZE(wm8711_snd_controls));
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index f76b6fc6766a..7e5ec03f6f8d 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -427,9 +427,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
 	struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
-	int i, ret;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
+	int ret;
 	u16 reg;
 
 	switch (level) {
@@ -444,16 +442,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
 			if (ret != 0)
 				return ret;
 
-			/* Sync reg_cache with the hardware */
-			for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
-				if (cache[i] == wm8731_reg[i])
-					continue;
-
-				data[0] = (i << 1) | ((cache[i] >> 8)
-						      & 0x0001);
-				data[1] = cache[i] & 0x00ff;
-				codec->hw_write(codec->control_data, data, 2);
-			}
+			snd_soc_cache_sync(codec);
 		}
 
 		/* Clear PWROFF, gate CLKOUT, everything else as-is */
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 78c9e5ab3fa5..57ad22aacc51 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -339,10 +339,10 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		iface |= 0x0004;
 		break;
 	case SND_SOC_DAIFMT_DSP_A:
-		iface |= 0x0003;
+		iface |= 0x000C;
 		break;
 	case SND_SOC_DAIFMT_DSP_B:
-		iface |= 0x0013;
+		iface |= 0x001C;
 		break;
 	default:
 		return -EINVAL;
@@ -404,15 +404,7 @@ static struct snd_soc_dai_driver wm8741_dai = {
 #ifdef CONFIG_PM
 static int wm8741_resume(struct snd_soc_codec *codec)
 {
-	u16 *cache = codec->reg_cache;
-	int i;
-
-	/* RESTORE REG Cache */
-	for (i = 0; i < WM8741_REGISTER_COUNT; i++) {
-		if (cache[i] == wm8741_reg_defaults[i] || WM8741_RESET == i)
-			continue;
-		snd_soc_write(codec, i, cache[i]);
-	}
+	snd_soc_cache_sync(codec);
 	return 0;
 }
 #else
@@ -462,7 +454,7 @@ static int wm8741_probe(struct snd_soc_codec *codec)
 			    WM8741_UPDATELM, WM8741_UPDATELM);
 	snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
 			    WM8741_UPDATERL, WM8741_UPDATERL);
-	snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
+	snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION,
 			    WM8741_UPDATERM, WM8741_UPDATERM);
 
 	snd_soc_add_controls(codec, wm8741_snd_controls,
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 15f03721ec6f..ca75a8180708 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -616,6 +616,8 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
 		break;
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			snd_soc_cache_sync(codec);
+
 			/* Set VMID to 5k */
 			snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
 
@@ -673,28 +675,14 @@ static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8750_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) {
-		if (i == WM8750_RESET)
-			continue;
-		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
-
 	wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	return 0;
 }
 
 static int wm8750_probe(struct snd_soc_codec *codec)
 {
 	struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
-	int reg, ret;
+	int ret;
 
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
 	if (ret < 0) {
@@ -712,22 +700,14 @@ static int wm8750_probe(struct snd_soc_codec *codec)
 	wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	/* set the update bits */
-	reg = snd_soc_read(codec, WM8750_LDAC);
-	snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8750_RDAC);
-	snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8750_LOUT1V);
-	snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8750_ROUT1V);
-	snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8750_LOUT2V);
-	snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8750_ROUT2V);
-	snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8750_LINVOL);
-	snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8750_RINVOL);
-	snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
+	snd_soc_update_bits(codec, WM8750_LDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8750_RDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8750_LOUT1V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8750_ROUT1V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8750_LOUT2V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8750_ROUT2V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8750_LINVOL, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8750_RINVOL, 0x0100, 0x0100);
 
 	snd_soc_add_controls(codec, wm8750_snd_controls,
 				ARRAY_SIZE(wm8750_snd_controls));
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index fe04a101d657..a9504710bb69 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1455,8 +1455,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
 	/* set the update bits */
 	snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
 	snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
-	snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
-	snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_LADC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_RADC, 0x0100, 0x0100);
 	snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
 	snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
 	snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index 00d8846fae8a..bfdc52370ad0 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -308,6 +308,8 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
 		break;
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			snd_soc_cache_sync(codec);
+
 			/* Disable the global powerdown; DAPM does the rest */
 			snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
 		}
@@ -379,21 +381,7 @@ static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8776_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
-		if (cache[i] == wm8776_reg[i])
-			continue;
-		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
-
 	wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	return 0;
 }
 #else
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c
index a2a09f85ea99..f2ced71328b0 100644
--- a/sound/soc/codecs/wm8782.c
+++ b/sound/soc/codecs/wm8782.c
@@ -60,7 +60,7 @@ static struct platform_driver wm8782_codec_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = wm8782_probe,
-	.remove = wm8782_remove,
+	.remove = __devexit_p(wm8782_remove),
 };
 
 static int __init wm8782_init(void)
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 082040eda8a2..3d0dc1591ecc 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -110,8 +110,8 @@
 
 #define WM8900_REG_CLOCKING1_BCLK_DIR   0x1
 #define WM8900_REG_CLOCKING1_MCLK_SRC   0x100
-#define WM8900_REG_CLOCKING1_BCLK_MASK  (~0x01e)
-#define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000)
+#define WM8900_REG_CLOCKING1_BCLK_MASK  0x01e
+#define WM8900_REG_CLOCKING1_OPCLK_MASK 0x7000
 
 #define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0
 #define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
@@ -135,7 +135,7 @@
 #define WM8900_REG_HPCTL1_HP_SHORT       0x08
 #define WM8900_REG_HPCTL1_HP_SHORT2      0x04
 
-#define WM8900_LRC_MASK 0xfc00
+#define WM8900_LRC_MASK 0x03ff
 
 struct wm8900_priv {
 	enum snd_soc_control_type control_type;
@@ -742,26 +742,20 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
 {
 	struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
 	struct _fll_div fll_div;
-	unsigned int reg;
 
 	if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out)
 		return 0;
 
 	/* The digital side should be disabled during any change. */
-	reg = snd_soc_read(codec, WM8900_REG_POWER1);
-	snd_soc_write(codec, WM8900_REG_POWER1,
-		     reg & (~WM8900_REG_POWER1_FLL_ENA));
+	snd_soc_update_bits(codec, WM8900_REG_POWER1,
+			    WM8900_REG_POWER1_FLL_ENA, 0);
 
 	/* Disable the FLL? */
 	if (!freq_in || !freq_out) {
-		reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
-		snd_soc_write(codec, WM8900_REG_CLOCKING1,
-			     reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
-
-		reg = snd_soc_read(codec, WM8900_REG_FLLCTL1);
-		snd_soc_write(codec, WM8900_REG_FLLCTL1,
-			     reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
-
+		snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+				    WM8900_REG_CLOCKING1_MCLK_SRC, 0);
+		snd_soc_update_bits(codec, WM8900_REG_FLLCTL1,
+				    WM8900_REG_FLLCTL1_OSC_ENA, 0);
 		wm8900->fll_in = freq_in;
 		wm8900->fll_out = freq_out;
 
@@ -796,15 +790,14 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
 	else
 		snd_soc_write(codec, WM8900_REG_FLLCTL6, 0);
 
-	reg = snd_soc_read(codec, WM8900_REG_POWER1);
-	snd_soc_write(codec, WM8900_REG_POWER1,
-		     reg | WM8900_REG_POWER1_FLL_ENA);
+	snd_soc_update_bits(codec, WM8900_REG_POWER1,
+			    WM8900_REG_POWER1_FLL_ENA,
+			    WM8900_REG_POWER1_FLL_ENA);
 
 reenable:
-	reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
-	snd_soc_write(codec, WM8900_REG_CLOCKING1,
-		     reg | WM8900_REG_CLOCKING1_MCLK_SRC);
-
+	snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+			    WM8900_REG_CLOCKING1_MCLK_SRC,
+			    WM8900_REG_CLOCKING1_MCLK_SRC);
 	return 0;
 }
 
@@ -818,43 +811,35 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 				 int div_id, int div)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
-	unsigned int reg;
 
 	switch (div_id) {
 	case WM8900_BCLK_DIV:
-		reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
-		snd_soc_write(codec, WM8900_REG_CLOCKING1,
-			     div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
+		snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+				    WM8900_REG_CLOCKING1_BCLK_MASK, div);
 		break;
 	case WM8900_OPCLK_DIV:
-		reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
-		snd_soc_write(codec, WM8900_REG_CLOCKING1,
-			     div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
+		snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+				    WM8900_REG_CLOCKING1_OPCLK_MASK, div);
 		break;
 	case WM8900_DAC_LRCLK:
-		reg = snd_soc_read(codec, WM8900_REG_AUDIO4);
-		snd_soc_write(codec, WM8900_REG_AUDIO4,
-			     div | (reg & WM8900_LRC_MASK));
+		snd_soc_update_bits(codec, WM8900_REG_AUDIO4,
+				    WM8900_LRC_MASK, div);
 		break;
 	case WM8900_ADC_LRCLK:
-		reg = snd_soc_read(codec, WM8900_REG_AUDIO3);
-		snd_soc_write(codec, WM8900_REG_AUDIO3,
-			     div | (reg & WM8900_LRC_MASK));
+		snd_soc_update_bits(codec, WM8900_REG_AUDIO3,
+				    WM8900_LRC_MASK, div);
 		break;
 	case WM8900_DAC_CLKDIV:
-		reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
-		snd_soc_write(codec, WM8900_REG_CLOCKING2,
-			     div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
+		snd_soc_update_bits(codec, WM8900_REG_CLOCKING2,
+				    WM8900_REG_CLOCKING2_DAC_CLKDIV, div);
 		break;
 	case WM8900_ADC_CLKDIV:
-		reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
-		snd_soc_write(codec, WM8900_REG_CLOCKING2,
-			     div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
+		snd_soc_update_bits(codec, WM8900_REG_CLOCKING2,
+				    WM8900_REG_CLOCKING2_ADC_CLKDIV, div);
 		break;
 	case WM8900_LRCLK_MODE:
-		reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
-		snd_soc_write(codec, WM8900_REG_DACCTRL,
-			     div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
+		snd_soc_update_bits(codec, WM8900_REG_DACCTRL,
+				    WM8900_REG_DACCTRL_AIF_LRCLKRATE, div);
 		break;
 	default:
 		return -EINVAL;
@@ -1037,12 +1022,12 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		/* Enable thermal shutdown */
-		reg = snd_soc_read(codec, WM8900_REG_GPIO);
-		snd_soc_write(codec, WM8900_REG_GPIO,
-			     reg | WM8900_REG_GPIO_TEMP_ENA);
-		reg = snd_soc_read(codec, WM8900_REG_ADDCTL);
-		snd_soc_write(codec, WM8900_REG_ADDCTL,
-			     reg | WM8900_REG_ADDCTL_TEMP_SD);
+		snd_soc_update_bits(codec, WM8900_REG_GPIO,
+				    WM8900_REG_GPIO_TEMP_ENA,
+				    WM8900_REG_GPIO_TEMP_ENA);
+		snd_soc_update_bits(codec, WM8900_REG_ADDCTL,
+				    WM8900_REG_ADDCTL_TEMP_SD,
+				    WM8900_REG_ADDCTL_TEMP_SD);
 		break;
 
 	case SND_SOC_BIAS_PREPARE:
@@ -1205,26 +1190,16 @@ static int wm8900_probe(struct snd_soc_codec *codec)
 	wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	/* Latch the volume update bits */
-	snd_soc_write(codec, WM8900_REG_LINVOL,
-		      snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
-	snd_soc_write(codec, WM8900_REG_RINVOL,
-		      snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100);
-	snd_soc_write(codec, WM8900_REG_LOUT1CTL,
-		      snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
-	snd_soc_write(codec, WM8900_REG_ROUT1CTL,
-		      snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
-	snd_soc_write(codec, WM8900_REG_LOUT2CTL,
-		      snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
-	snd_soc_write(codec, WM8900_REG_ROUT2CTL,
-		      snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
-	snd_soc_write(codec, WM8900_REG_LDAC_DV,
-		      snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100);
-	snd_soc_write(codec, WM8900_REG_RDAC_DV,
-		      snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100);
-	snd_soc_write(codec, WM8900_REG_LADC_DV,
-		      snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100);
-	snd_soc_write(codec, WM8900_REG_RADC_DV,
-		      snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_LINVOL, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_RINVOL, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_LOUT1CTL, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_ROUT1CTL, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_LOUT2CTL, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_ROUT2CTL, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_LDAC_DV, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_RDAC_DV, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_LADC_DV, 0x100, 0x100);
+	snd_soc_update_bits(codec, WM8900_REG_RADC_DV, 0x100, 0x100);
 
 	/* Set the DAC and mixer output bias */
 	snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index b085575d4aa5..9fc8f4c0a9a9 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -50,7 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
 struct wm8904_priv {
 
 	enum wm8904_type devtype;
-	void *control_data;
 
 	struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
 
@@ -2540,7 +2539,6 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
 
 	wm8904->devtype = id->driver_data;
 	i2c_set_clientdata(i2c, wm8904);
-	wm8904->control_data = i2c;
 	wm8904->pdata = i2c->dev.platform_data;
 
 	ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 056daa0010f9..dc5cb3150857 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -43,9 +43,19 @@
 struct wm8940_priv {
 	unsigned int sysclk;
 	enum snd_soc_control_type control_type;
-	void *control_data;
 };
 
+static int wm8940_volatile_register(struct snd_soc_codec *codec,
+				    unsigned int reg)
+{
+	switch (reg) {
+	case WM8940_SOFTRESET:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
 static u16 wm8940_reg_defaults[] = {
 	0x8940, /* Soft Reset */
 	0x0000, /* Power 1 */
@@ -460,6 +470,14 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
 		ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
 		break;
 	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = snd_soc_cache_sync(codec);
+			if (ret < 0) {
+				dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
+				return ret;
+			}
+		}
+
 		/* ensure bufioen and biasen */
 		pwr_reg |= (1 << 2) | (1 << 3);
 		/* set vmid to 300k for standby */
@@ -470,6 +488,8 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
 		break;
 	}
 
+	codec->dapm.bias_level = level;
+
 	return ret;
 }
 
@@ -660,30 +680,8 @@ static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8940_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	int ret;
-	u8 data[3];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware
-	 * Could use auto incremented writes to speed this up
-	 */
-	for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
-		data[0] = i;
-		data[1] = (cache[i] & 0xFF00) >> 8;
-		data[2] = cache[i] & 0x00FF;
-		ret = codec->hw_write(codec->control_data, data, 3);
-		if (ret < 0)
-			goto error_ret;
-		else if (ret != 3) {
-			ret = -EIO;
-			goto error_ret;
-		}
-	}
-	ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-error_ret:
-	return ret;
+	wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
 }
 
 static int wm8940_probe(struct snd_soc_codec *codec)
@@ -693,7 +691,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
 	int ret;
 	u16 reg;
 
-	codec->control_data = wm8940->control_data;
 	ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -744,6 +741,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
 	.reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
 	.reg_word_size = sizeof(u16),
 	.reg_cache_default = wm8940_reg_defaults,
+	.volatile_register = wm8940_volatile_register,
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -758,7 +756,6 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm8940);
-	wm8940->control_data = i2c;
 	wm8940->control_type = SND_SOC_I2C;
 
 	ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 4393394b7bc1..2df253c18568 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -72,7 +72,6 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
 
 struct wm8960_priv {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 	int (*set_bias_level)(struct snd_soc_codec *,
 			      enum snd_soc_bias_level level);
 	struct snd_soc_dapm_widget *lout1;
@@ -575,6 +574,8 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
 
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			snd_soc_cache_sync(codec);
+
 			/* Enable anti-pop features */
 			snd_soc_write(codec, WM8960_APOP1,
 				      WM8960_POBCTRL | WM8960_SOFT_ST |
@@ -677,6 +678,9 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
 					    WM8960_VREF | WM8960_VMID_MASK, 0);
 			break;
 
+		case SND_SOC_BIAS_OFF:
+			snd_soc_cache_sync(codec);
+			break;
 		default:
 			break;
 		}
@@ -902,16 +906,6 @@ static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
 static int wm8960_resume(struct snd_soc_codec *codec)
 {
 	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) {
-		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
 
 	wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	return 0;
@@ -925,7 +919,6 @@ static int wm8960_probe(struct snd_soc_codec *codec)
 	u16 reg;
 
 	wm8960->set_bias_level = wm8960_set_bias_level_out3;
-	codec->control_data = wm8960->control_data;
 
 	if (!pdata) {
 		dev_warn(codec->dev, "No platform data supplied\n");
@@ -1015,7 +1008,6 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
 
 	i2c_set_clientdata(i2c, wm8960);
 	wm8960->control_type = SND_SOC_I2C;
-	wm8960->control_data = i2c;
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8960, &wm8960_dai, 1);
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index cdee8103d09b..9568c8a49f96 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -974,7 +974,9 @@ static int wm8961_probe(struct snd_soc_codec *codec)
 	}
 
 	/* This isn't volatile - readback doesn't correspond to write */
-	reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
+	codec->cache_bypass = 1;
+	reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
+	codec->cache_bypass = 0;
 	dev_info(codec->dev, "WM8961 family %d revision %c\n",
 		 (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
 		 ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 3676b38838d8..f60dfa16545e 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2139,7 +2139,6 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
 			    struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	u16 *reg_cache = codec->reg_cache;
 	int ret;
 
 	/* Apply the update (if any) */
@@ -2148,16 +2147,19 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
 		return 0;
 
 	/* If the left PGA is enabled hit that VU bit... */
-	if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
-		return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
-				     reg_cache[WM8962_SPKOUTL_VOLUME]);
+	ret = snd_soc_read(codec, WM8962_PWR_MGMT_2);
+	if (ret & WM8962_SPKOUTL_PGA_ENA) {
+		snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
+			      snd_soc_read(codec, WM8962_SPKOUTL_VOLUME));
+		return 1;
+	}
 
 	/* ...otherwise the right.  The VU is stereo. */
-	if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
-		return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
-				     reg_cache[WM8962_SPKOUTR_VOLUME]);
+	if (ret & WM8962_SPKOUTR_PGA_ENA)
+		snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
+			      snd_soc_read(codec, WM8962_SPKOUTR_VOLUME));
 
-	return 0;
+	return 1;
 }
 
 static const char *cap_hpf_mode_text[] = {
@@ -2498,7 +2500,6 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
 			 struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	u16 *reg_cache = codec->reg_cache;
 	int reg;
 
 	switch (w->shift) {
@@ -2521,7 +2522,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
-		return snd_soc_write(codec, reg, reg_cache[reg]);
+		return snd_soc_write(codec, reg, snd_soc_read(codec, reg));
 	default:
 		BUG();
 		return -EINVAL;
@@ -2667,7 +2668,7 @@ SND_SOC_DAPM_INPUT("IN4R"),
 SND_SOC_DAPM_INPUT("Beep"),
 SND_SOC_DAPM_INPUT("DMICDAT"),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
 SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
@@ -2688,7 +2689,7 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0,
 SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0,
 		   mixinr, ARRAY_SIZE(mixinr)),
 
-SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
+SND_SOC_DAPM_AIF_IN("DMIC_ENA", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
 
 SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0),
 SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0),
@@ -2767,18 +2768,18 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
 
 	{ "MICBIAS", NULL, "SYSCLK" },
 
-	{ "DMIC", NULL, "DMICDAT" },
+	{ "DMIC_ENA", NULL, "DMICDAT" },
 
 	{ "ADCL", NULL, "SYSCLK" },
 	{ "ADCL", NULL, "TOCLK" },
 	{ "ADCL", NULL, "MIXINL" },
-	{ "ADCL", NULL, "DMIC" },
+	{ "ADCL", NULL, "DMIC_ENA" },
 	{ "ADCL", NULL, "DSP2" },
 
 	{ "ADCR", NULL, "SYSCLK" },
 	{ "ADCR", NULL, "TOCLK" },
 	{ "ADCR", NULL, "MIXINR" },
-	{ "ADCR", NULL, "DMIC" },
+	{ "ADCR", NULL, "DMIC_ENA" },
 	{ "ADCR", NULL, "DSP2" },
 
 	{ "STL", "Left", "ADCL" },
@@ -3223,9 +3224,9 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	int aif0 = 0;
 
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-	case SND_SOC_DAIFMT_DSP_A:
-		aif0 |= WM8962_LRCLK_INV;
 	case SND_SOC_DAIFMT_DSP_B:
+		aif0 |= WM8962_LRCLK_INV | 3;
+	case SND_SOC_DAIFMT_DSP_A:
 		aif0 |= 3;
 
 		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 572bb80627a4..b444b297d0b2 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -546,6 +546,9 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec,
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+			snd_soc_cache_sync(codec);
+
 		/* mute dac and set vmid to 500k, enable VREF */
 		snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
 		break;
@@ -605,20 +608,8 @@ static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8971_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
 	u16 reg;
 
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8971_reg); i++) {
-		if (i + 1 == WM8971_RESET)
-			continue;
-		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
-
 	wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	/* charge wm8971 caps */
@@ -660,25 +651,14 @@ static int wm8971_probe(struct snd_soc_codec *codec)
 		msecs_to_jiffies(1000));
 
 	/* set the update bits */
-	reg = snd_soc_read(codec, WM8971_LDAC);
-	snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8971_RDAC);
-	snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
-
-	reg = snd_soc_read(codec, WM8971_LOUT1V);
-	snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8971_ROUT1V);
-	snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
-
-	reg = snd_soc_read(codec, WM8971_LOUT2V);
-	snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8971_ROUT2V);
-	snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
-
-	reg = snd_soc_read(codec, WM8971_LINVOL);
-	snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8971_RINVOL);
-	snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
+	snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8971_LOUT1V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8971_ROUT1V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8971_LOUT2V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8971_ROUT2V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100);
 
 	snd_soc_add_controls(codec, wm8971_snd_controls,
 				ARRAY_SIZE(wm8971_snd_controls));
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index ca646a822444..9352f1e088d2 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2006-2009 Wolfson Microelectronics PLC.
  *
- * Author: Liam Girdwood <linux@wolfsonmicro.com>
+ * Author: Liam Girdwood <Liam.Girdwood@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
@@ -530,6 +530,8 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec,
 		power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
 
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			snd_soc_cache_sync(codec);
+
 			/* Initial cap charge at VMID 5k */
 			snd_soc_write(codec, WM8974_POWER1, power1 | 0x3);
 			mdelay(100);
@@ -589,18 +591,7 @@ static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8974_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) {
-		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
 	wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 85e3e630e763..41ca4d9ac20c 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -52,7 +52,6 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
 /* codec private data */
 struct wm8978_priv {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 	unsigned int f_pllout;
 	unsigned int f_mclk;
 	unsigned int f_256fs;
@@ -955,7 +954,6 @@ static int wm8978_probe(struct snd_soc_codec *codec)
 	 * default hardware setting
 	 */
 	wm8978->sysclk = WM8978_PLL;
-	codec->control_data = wm8978->control_data;
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -1016,7 +1014,6 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm8978);
-	wm8978->control_data = i2c;
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8978, &wm8978_dai, 1);
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index 17f04ec2b940..93ee28439be5 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -1007,7 +1007,7 @@ static int wm8983_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0x8983);
+	ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
 		return ret;
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index d7170f1381aa..2e9eba717d1a 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -55,7 +55,6 @@ struct wm8988_priv {
 	struct snd_pcm_hw_constraint_list *sysclk_constraints;
 };
 
-
 #define wm8988_reset(c)	snd_soc_write(c, WM8988_RESET, 0)
 
 /*
@@ -676,6 +675,8 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
 
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			snd_soc_cache_sync(codec);
+
 			/* VREF, VMID=2x5k */
 			snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
 
@@ -736,21 +737,7 @@ static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8988_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < WM8988_NUM_REG; i++) {
-		if (i == WM8988_RESET)
-			continue;
-		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
-
 	wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	return 0;
 }
 
@@ -759,7 +746,6 @@ static int wm8988_probe(struct snd_soc_codec *codec)
 	struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret = 0;
-	u16 reg;
 
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
 	if (ret < 0) {
@@ -774,16 +760,11 @@ static int wm8988_probe(struct snd_soc_codec *codec)
 	}
 
 	/* set the update bits (we always update left then right) */
-	reg = snd_soc_read(codec, WM8988_RADC);
-	snd_soc_write(codec, WM8988_RADC, reg | 0x100);
-	reg = snd_soc_read(codec, WM8988_RDAC);
-	snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8988_ROUT1V);
-	snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8988_ROUT2V);
-	snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
-	reg = snd_soc_read(codec, WM8988_RINVOL);
-	snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
+	snd_soc_update_bits(codec, WM8988_RADC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8988_RDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8988_ROUT1V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100);
 
 	wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 100aeee5ba96..d29a9622964c 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -36,10 +36,17 @@ struct wm8990_priv {
 	unsigned int pcmclk;
 };
 
-/*
- * wm8990 register cache.  Note that register 0 is not included in the
- * cache.
- */
+static int wm8990_volatile_register(struct snd_soc_codec *codec,
+				    unsigned int reg)
+{
+	switch (reg) {
+	case WM8990_RESET:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
 static const u16 wm8990_reg[] = {
 	0x8990,     /* R0  - Reset */
 	0x0000,     /* R1  - Power Management (1) */
@@ -394,7 +401,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
 		(1 << WM8990_AINRMUX_PWR_BIT))) {
 		reg |= WM8990_AINR_ENA;
 	} else {
-		reg &= ~WM8990_AINL_ENA;
+		reg &= ~WM8990_AINR_ENA;
 	}
 	snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
 
@@ -974,7 +981,6 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
 static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
 		int source, unsigned int freq_in, unsigned int freq_out)
 {
-	u16 reg;
 	struct snd_soc_codec *codec = codec_dai->codec;
 	struct _pll_div pll_div;
 
@@ -982,13 +988,12 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
 		pll_factors(&pll_div, freq_out * 4, freq_in);
 
 		/* Turn on PLL */
-		reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
-		reg |= WM8990_PLL_ENA;
-		snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+		snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+				    WM8990_PLL_ENA, WM8990_PLL_ENA);
 
 		/* sysclk comes from PLL */
-		reg = snd_soc_read(codec, WM8990_CLOCKING_2);
-		snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
+		snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+				    WM8990_SYSCLK_SRC, WM8990_SYSCLK_SRC);
 
 		/* set up N , fractional mode and pre-divisor if necessary */
 		snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
@@ -996,10 +1001,9 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
 		snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
 		snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
 	} else {
-		/* Turn on PLL */
-		reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
-		reg &= ~WM8990_PLL_ENA;
-		snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+		/* Turn off PLL */
+		snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+				    WM8990_PLL_ENA, 0);
 	}
 	return 0;
 }
@@ -1077,28 +1081,23 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 		int div_id, int div)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
-	u16 reg;
 
 	switch (div_id) {
 	case WM8990_MCLK_DIV:
-		reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
-			~WM8990_MCLK_DIV_MASK;
-		snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+		snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+				    WM8990_MCLK_DIV_MASK, div);
 		break;
 	case WM8990_DACCLK_DIV:
-		reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
-			~WM8990_DAC_CLKDIV_MASK;
-		snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+		snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+				    WM8990_DAC_CLKDIV_MASK, div);
 		break;
 	case WM8990_ADCCLK_DIV:
-		reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
-			~WM8990_ADC_CLKDIV_MASK;
-		snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+		snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+				    WM8990_ADC_CLKDIV_MASK, div);
 		break;
 	case WM8990_BCLK_DIV:
-		reg = snd_soc_read(codec, WM8990_CLOCKING_1) &
-			~WM8990_BCLK_DIV_MASK;
-		snd_soc_write(codec, WM8990_CLOCKING_1, reg | div);
+		snd_soc_update_bits(codec, WM8990_CLOCKING_1,
+				    WM8990_BCLK_DIV_MASK, div);
 		break;
 	default:
 		return -EINVAL;
@@ -1156,7 +1155,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
 static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 	enum snd_soc_bias_level level)
 {
-	u16 val;
+	int ret;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
@@ -1164,13 +1163,18 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 
 	case SND_SOC_BIAS_PREPARE:
 		/* VMID=2*50k */
-		val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
-			~WM8990_VMID_MODE_MASK;
-		snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
+		snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1,
+				    WM8990_VMID_MODE_MASK, 0x2);
 		break;
 
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = snd_soc_cache_sync(codec);
+			if (ret < 0) {
+				dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
+				return ret;
+			}
+
 			/* Enable all output discharge bits */
 			snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
 				WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
@@ -1225,9 +1229,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 		}
 
 		/* VMID=2*250k */
-		val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
-			~WM8990_VMID_MODE_MASK;
-		snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
+		snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1,
+				    WM8990_VMID_MODE_MASK, 0x4);
 		break;
 
 	case SND_SOC_BIAS_OFF:
@@ -1241,8 +1244,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 			WM8990_BUFIOEN);
 
 		/* mute DAC */
-		val = snd_soc_read(codec, WM8990_DAC_CTRL);
-		snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+		snd_soc_update_bits(codec, WM8990_DAC_CTRL,
+				    WM8990_DAC_MUTE, WM8990_DAC_MUTE);
 
 		/* Enable any disabled outputs */
 		snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
@@ -1319,19 +1322,6 @@ static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8990_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) {
-		if (i + 1 == WM8990_RESET)
-			continue;
-		data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
-	}
-
 	wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	return 0;
 }
@@ -1343,7 +1333,6 @@ static int wm8990_resume(struct snd_soc_codec *codec)
 static int wm8990_probe(struct snd_soc_codec *codec)
 {
 	int ret;
-	u16 reg;
 
 	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
 	if (ret < 0) {
@@ -1356,15 +1345,14 @@ static int wm8990_probe(struct snd_soc_codec *codec)
 	/* charge output caps */
 	wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
-	snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
+	snd_soc_update_bits(codec, WM8990_AUDIO_INTERFACE_4,
+			    WM8990_ALRCGPIO1, WM8990_ALRCGPIO1);
 
-	reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) &
-		~WM8990_GPIO1_SEL_MASK;
-	snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
+	snd_soc_update_bits(codec, WM8990_GPIO1_GPIO2,
+			    WM8990_GPIO1_SEL_MASK, 1);
 
-	reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
-	snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
+	snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+			    WM8990_OPCLK_ENA, WM8990_OPCLK_ENA);
 
 	snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
 	snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
@@ -1392,6 +1380,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
 	.reg_cache_size = ARRAY_SIZE(wm8990_reg),
 	.reg_word_size = sizeof(u16),
 	.reg_cache_default = wm8990_reg,
+	.volatile_register = wm8990_volatile_register,
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index 6af23d06870f..c9ab3ba9bced 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2007-2010 Wolfson Microelectronics PLC.
  * Author: Graeme Gregory
- *         linux@wolfsonmicro.com
+ *         Graeme.Gregory@wolfsonmicro.com
  *
  *  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
@@ -393,7 +393,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
 			 (1 << WM8991_AINRMUX_PWR_BIT)))
 		reg |= WM8991_AINR_ENA;
 	else
-		reg &= ~WM8991_AINL_ENA;
+		reg &= ~WM8991_AINR_ENA;
 
 	snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg);
 	return 0;
@@ -1264,7 +1264,6 @@ static int wm8991_probe(struct snd_soc_codec *codec)
 {
 	struct wm8991_priv *wm8991;
 	int ret;
-	unsigned int reg;
 
 	wm8991 = snd_soc_codec_get_drvdata(codec);
 
@@ -1282,19 +1281,18 @@ static int wm8991_probe(struct snd_soc_codec *codec)
 
 	wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	reg = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_4);
-	snd_soc_write(codec, WM8991_AUDIO_INTERFACE_4, reg | WM8991_ALRCGPIO1);
+	snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4,
+			    WM8991_ALRCGPIO1, WM8991_ALRCGPIO1);
 
-	reg = snd_soc_read(codec, WM8991_GPIO1_GPIO2) &
-	      ~WM8991_GPIO1_SEL_MASK;
-	snd_soc_write(codec, WM8991_GPIO1_GPIO2, reg | 1);
+	snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2,
+			    WM8991_GPIO1_SEL_MASK, 1);
 
-	reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1);
-	snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, reg | WM8991_VREF_ENA|
-		      WM8991_VMID_MODE_MASK);
+	snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1,
+			    WM8991_VREF_ENA | WM8991_VMID_MODE_MASK,
+			    WM8991_VREF_ENA | WM8991_VMID_MODE_MASK);
 
-	reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
-	snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg | WM8991_OPCLK_ENA);
+	snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2,
+			    WM8991_OPCLK_ENA, WM8991_OPCLK_ENA);
 
 	snd_soc_write(codec, WM8991_DAC_CTRL, 0);
 	snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index e5372675123d..6b73efd26991 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -208,7 +208,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
 static int configure_clock(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	int old, new;
+	int change, new;
 
 	/* Bring up the AIF clocks first */
 	configure_aif_clock(codec, 0);
@@ -229,14 +229,11 @@ static int configure_clock(struct snd_soc_codec *codec)
 	else
 		new = 0;
 
-	old = snd_soc_read(codec, WM8994_CLOCKING_1) & WM8994_SYSCLK_SRC;
-
-	/* If there's no change then we're done. */
-	if (old == new)
+	change = snd_soc_update_bits(codec, WM8994_CLOCKING_1,
+				     WM8994_SYSCLK_SRC, new);
+	if (!change)
 		return 0;
 
-	snd_soc_update_bits(codec, WM8994_CLOCKING_1, WM8994_SYSCLK_SRC, new);
-
 	snd_soc_dapm_sync(&codec->dapm);
 
 	return 0;
@@ -283,6 +280,7 @@ static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
 static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0);
 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0);
 
 #define WM8994_DRC_SWITCH(xname, reg, shift) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -703,6 +701,13 @@ SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume",
 	       7, 1, ng_tlv),
 };
 
+static const struct snd_kcontrol_new wm1811_snd_controls[] = {
+SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0,
+	       mixin_boost_tlv),
+SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
+	       mixin_boost_tlv),
+};
+
 static int clk_sys_event(struct snd_soc_dapm_widget *w,
 			 struct snd_kcontrol *kcontrol, int event)
 {
@@ -1414,7 +1419,7 @@ SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
 SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
 
 SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
 
 SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
 
@@ -2053,6 +2058,15 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
 							    WM8958_CP_DISCH);
 				}
 				break;
+
+			case WM1811:
+				if (wm8994->revision < 2) {
+					snd_soc_write(codec, 0x102, 0x3);
+					snd_soc_write(codec, 0x5d, 0x7e);
+					snd_soc_write(codec, 0x5e, 0x0);
+					snd_soc_write(codec, 0x102, 0x0);
+				}
+				break;
 			}
 
 			/* Discharge LINEOUT1 & 2 */
@@ -2168,10 +2182,18 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
 	/* The AIF2 format configuration needs to be mirrored to AIF3
 	 * on WM8958 if it's in use so just do it all the time. */
-	if (control->type == WM8958 && dai->id == 2)
-		snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
-				    WM8994_AIF1_LRCLK_INV |
-				    WM8958_AIF3_FMT_MASK, aif1);
+	switch (control->type) {
+	case WM1811:
+	case WM8958:
+		if (dai->id == 2)
+			snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
+					    WM8994_AIF1_LRCLK_INV |
+					    WM8958_AIF3_FMT_MASK, aif1);
+		break;
+
+	default:
+		break;
+	}
 
 	snd_soc_update_bits(codec, aif1_reg,
 			    WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV |
@@ -2213,7 +2235,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_soc_dai *dai)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	struct wm8994 *control = codec->control_data;
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	int aif1_reg;
 	int aif2_reg;
@@ -2256,14 +2277,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
 			dev_dbg(codec->dev, "AIF2 using split LRCLK\n");
 		}
 		break;
-	case 3:
-		switch (control->type) {
-		case WM8958:
-			aif1_reg = WM8958_AIF3_CONTROL_1;
-			break;
-		default:
-			return 0;
-		}
 	default:
 		return -EINVAL;
 	}
@@ -2384,6 +2397,7 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
 	switch (dai->id) {
 	case 3:
 		switch (control->type) {
+		case WM1811:
 		case WM8958:
 			aif1_reg = WM8958_AIF3_CONTROL_1;
 			break;
@@ -2424,7 +2438,7 @@ static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
 		rate_reg = WM8994_AIF1_RATE;
 		break;
 	case 2:
-		rate_reg = WM8994_AIF1_RATE;
+		rate_reg = WM8994_AIF2_RATE;
 		break;
 	default:
 		break;
@@ -2614,6 +2628,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
 	case WM8994:
 		snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
 		break;
+	case WM1811:
 	case WM8958:
 		snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
 				    WM8958_MICD_ENA, 0);
@@ -2682,6 +2697,7 @@ static int wm8994_resume(struct snd_soc_codec *codec)
 			snd_soc_update_bits(codec, WM8994_MICBIAS,
 					    WM8994_MICD_ENA, WM8994_MICD_ENA);
 		break;
+	case WM1811:
 	case WM8958:
 		if (wm8994->jack_cb)
 			snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
@@ -2980,8 +2996,13 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = codec->control_data;
 
-	if (control->type != WM8958)
+	switch (control->type) {
+	case WM1811:
+	case WM8958:
+		break;
+	default:
 		return -EINVAL;
+	}
 
 	if (jack) {
 		if (!cb) {
@@ -3135,6 +3156,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 		wm8994->hubs.dcs_readback_mode = 1;
 		break;
 
+	case WM1811:
+		wm8994->hubs.dcs_readback_mode = 2;
+		wm8994->hubs.no_series_update = 1;
+
+		switch (wm8994->revision) {
+		case 0:
+		case 1:
+			wm8994->hubs.dcs_codes_l = -9;
+			wm8994->hubs.dcs_codes_r = -5;
+			break;
+		default:
+			break;
+		}
+
+		snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
+				    WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
+		break;
+
 	default:
 		break;
 	}
@@ -3195,6 +3234,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 		break;
 
 	case WM8958:
+	case WM1811:
 		if (wm8994->micdet_irq) {
 			ret = request_threaded_irq(wm8994->micdet_irq, NULL,
 						   wm8958_mic_irq,
@@ -3357,6 +3397,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 						  ARRAY_SIZE(wm8994_dac_widgets));
 		}
 		break;
+
+	case WM1811:
+		snd_soc_add_controls(codec, wm8958_snd_controls,
+				     ARRAY_SIZE(wm8958_snd_controls));
+		snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
+					  ARRAY_SIZE(wm8958_dapm_widgets));
+		snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets,
+					  ARRAY_SIZE(wm8994_lateclk_widgets));
+		snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets,
+					  ARRAY_SIZE(wm8994_adc_widgets));
+		snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets,
+					  ARRAY_SIZE(wm8994_dac_widgets));
+		break;
 	}
 		
 
@@ -3393,6 +3446,12 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
 		wm8958_dsp2_init(codec);
 		break;
+	case WM1811:
+		snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon,
+					ARRAY_SIZE(wm8994_lateclk_intercon));
+		snd_soc_dapm_add_routes(dapm, wm8958_intercon,
+					ARRAY_SIZE(wm8958_intercon));
+		break;
 	}
 
 	return 0;
@@ -3448,6 +3507,7 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
 				wm8994);
 		break;
 
+	case WM1811:
 	case WM8958:
 		if (wm8994->micdet_irq)
 			free_irq(wm8994->micdet_irq, wm8994);
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 74ae5995a786..78eeb21e6696 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -485,7 +485,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
 static int configure_clock(struct snd_soc_codec *codec)
 {
 	struct wm8995_priv *wm8995;
-	int old, new;
+	int change, new;
 
 	wm8995 = snd_soc_codec_get_drvdata(codec);
 
@@ -509,15 +509,11 @@ static int configure_clock(struct snd_soc_codec *codec)
 	else
 		new = 0;
 
-	old = snd_soc_read(codec, WM8995_CLOCKING_1) & WM8995_SYSCLK_SRC;
-
-	/* If there's no change then we're done. */
-	if (old == new)
+	change = snd_soc_update_bits(codec, WM8995_CLOCKING_1,
+				     WM8995_SYSCLK_SRC_MASK, new);
+	if (!change)
 		return 0;
 
-	snd_soc_update_bits(codec, WM8995_CLOCKING_1,
-			    WM8995_SYSCLK_SRC_MASK, new);
-
 	snd_soc_dapm_sync(&codec->dapm);
 
 	return 0;
@@ -1573,9 +1569,16 @@ static int wm8995_resume(struct snd_soc_codec *codec)
 static int wm8995_remove(struct snd_soc_codec *codec)
 {
 	struct wm8995_priv *wm8995;
+	int i;
 
 	wm8995 = snd_soc_codec_get_drvdata(codec);
 	wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i)
+		regulator_unregister_notifier(wm8995->supplies[i].consumer,
+					      &wm8995->disable_nb[i]);
+
+	regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 833df74c5584..645c980d6b80 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -641,6 +641,14 @@ SOC_DOUBLE_R("Speaker ZC Switch", WM8996_LEFT_PDM_SPEAKER,
 
 SOC_SINGLE("DSP1 EQ Switch", WM8996_DSP1_RX_EQ_GAINS_1, 0, 1, 0),
 SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
+
+SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0),
+SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0),
+SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0),
+
+SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0),
+SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0),
+SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0),
 };
 
 static const struct snd_kcontrol_new wm8996_eq_controls[] = {
@@ -1105,9 +1113,9 @@ SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
 SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1,
 		    WM8996_POWER_MANAGEMENT_4, 8, 0),
 
-SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 0,
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
 		    WM8996_POWER_MANAGEMENT_6, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 1,
+SND_SOC_DAPM_AIF_OUT("AIF2TX0", "AIF2 Capture", 1,
 		    WM8996_POWER_MANAGEMENT_6, 8, 0),
 
 SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
@@ -1912,7 +1920,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
 	snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK,
 			    lrclk);
 	snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2,
-			    WM8996_DSP1_DIV_SHIFT << dsp_shift, dsp);
+			    WM8996_DSP1_DIV_MASK << dsp_shift, dsp);
 
 	return 0;
 }
@@ -2698,7 +2706,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
 	init_completion(&wm8996->fll_lock);
 
 	dapm->idle_bias_off = true;
-	dapm->bias_level = SND_SOC_BIAS_OFF;
 
 	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
 	if (ret != 0) {
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index f32ab1ee9647..3cd35a02c28c 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -157,7 +157,6 @@ static struct {
 
 struct wm9081_priv {
 	enum snd_soc_control_type control_type;
-	void *control_data;
 	int sysclk_source;
 	int mclk_rate;
 	int sysclk_rate;
@@ -174,6 +173,7 @@ static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int re
 {
 	switch (reg) {
 	case WM9081_SOFTWARE_RESET:
+	case WM9081_INTERRUPT_STATUS:
 		return 1;
 	default:
 		return 0;
@@ -820,7 +820,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
 		/* VMID 2*240k */
 		reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
 		reg &= ~WM9081_VMID_SEL_MASK;
-		reg |= 0x40;
+		reg |= 0x04;
 		snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
 		/* Standby bias current on */
@@ -1213,7 +1213,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
 	int ret;
 	u16 reg;
 
-	codec->control_data = wm9081->control_data;
 	ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -1250,8 +1249,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
 	snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
 		     reg | WM9081_SPKPGAZC);
 
-	snd_soc_add_controls(codec, wm9081_snd_controls,
-			     ARRAY_SIZE(wm9081_snd_controls));
 	if (!wm9081->pdata.num_retune_configs) {
 		dev_dbg(codec->dev,
 			"No ReTune Mobile data, using normal EQ\n");
@@ -1311,6 +1308,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
 	.reg_cache_default = wm9081_reg_defaults,
 	.volatile_register = wm9081_volatile_register,
 
+	.controls         = wm9081_snd_controls,
+	.num_controls     = ARRAY_SIZE(wm9081_snd_controls),
 	.dapm_widgets	  = wm9081_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets),
 	.dapm_routes     = wm9081_audio_paths,
@@ -1330,7 +1329,6 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
 
 	i2c_set_clientdata(i2c, wm9081);
 	wm9081->control_type = SND_SOC_I2C;
-	wm9081->control_data = i2c;
 
 	if (dev_get_platdata(&i2c->dev))
 		memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index f2f3077928da..2b5252c9e377 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -140,7 +140,6 @@ static const u16 wm9090_reg_defaults[] = {
 /* This struct is used to save the context */
 struct wm9090_priv {
 	struct wm9090_platform_data pdata;
-	void *control_data;
 };
 
 static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
@@ -549,10 +548,8 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 
 static int wm9090_probe(struct snd_soc_codec *codec)
 {
-	struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
-	codec->control_data = wm9090->control_data;
 	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -661,7 +658,6 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
 		       sizeof(wm9090->pdata));
 
 	i2c_set_clientdata(i2c, wm9090);
-	wm9090->control_data = i2c;
 
 	ret =  snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm9090,  NULL, 0);
@@ -682,6 +678,7 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
 
 static const struct i2c_device_id wm9090_id[] = {
 	{ "wm9090", 0 },
+	{ "wm9093", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, wm9090_id);
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index ca8ce03510f4..84f33d4ea2cd 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -222,7 +222,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
 	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
-	ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+	ret = snd_soc_put_volsw(kcontrol, ucontrol);
 
 	/* Updating the analogue gains invalidates the DC servo cache */
 	hubs->class_w_dcs = 0;
@@ -362,19 +362,11 @@ SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
 SOC_ENUM("Speaker Reference", speaker_ref),
 SOC_ENUM("Speaker Mode", speaker_mode),
 
-{
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume",
-	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
-		 SNDRV_CTL_ELEM_ACCESS_READWRITE,
-	.tlv.p = outpga_tlv,
-	.info = snd_soc_info_volsw_2r,
-	.get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo,
-	.private_value = (unsigned long)&(struct soc_mixer_control) {
-		.reg = WM8993_LEFT_OUTPUT_VOLUME,
-		.rreg = WM8993_RIGHT_OUTPUT_VOLUME,
-		.shift = 0, .max = 63
-	},
-},
+SOC_DOUBLE_R_EXT_TLV("Headphone Volume",
+		     WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME,
+		     0, 63, 0, snd_soc_get_volsw, wm8993_put_dc_servo,
+		     outpga_tlv),
+
 SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
 	     WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
 SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index fe7984221eb9..f78c3f0f280c 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -150,8 +150,6 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 	snd_soc_dapm_enable_pin(dapm, "Line In");
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index d0d60b8a54d4..300e12118c00 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -265,6 +265,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
 	unsigned int pcr;
 	unsigned int srgr;
+	bool inv_fs = false;
 	/* Attention srgr is updated by hw_params! */
 	srgr = DAVINCI_MCBSP_SRGR_FSGM |
 		DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
@@ -330,7 +331,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 		 * more empty bit clock slots between channels as the sample
 		 * rate is lowered.
 		 */
-		fmt ^= SND_SOC_DAIFMT_NB_IF;
+		inv_fs = true;
 	case SND_SOC_DAIFMT_DSP_A:
 		dev->mode = MOD_DSP_A;
 		break;
@@ -394,6 +395,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 	default:
 		return -EINVAL;
 	}
+	if (inv_fs == true)
+		pcr ^= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
 	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
 	dev->pcr = pcr;
 	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
index c7417c76552b..3cd6158d83e1 100644
--- a/sound/soc/ep93xx/ep93xx-ac97.c
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -335,7 +335,7 @@ static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
 	.trigger	= ep93xx_ac97_trigger,
 };
 
-struct snd_soc_dai_driver ep93xx_ac97_dai = {
+static struct snd_soc_dai_driver ep93xx_ac97_dai = {
 	.name		= "ep93xx-ac97",
 	.id		= 0,
 	.ac97_control	= 1,
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index bb699bb55a50..b133bfcc5848 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -29,7 +29,7 @@ config SND_MXC_SOC_WM1133_EV1
 config SND_SOC_MX27VIS_AIC32X4
 	tristate "SoC audio support for Visstrim M10 boards"
 	depends on MACH_IMX27_VISSTRIM_M10
-	select SND_SOC_TVL320AIC32X4
+	select SND_SOC_TLV320AIC32X4
 	select SND_MXC_SOC_MX2
 	help
 	  Say Y if you want to add support for SoC audio on Visstrim SM10
@@ -50,6 +50,7 @@ config SND_SOC_EUKREA_TLV320
 		|| MACH_EUKREA_MBIMXSD25_BASEBOARD \
 		|| MACH_EUKREA_MBIMXSD35_BASEBOARD \
 		|| MACH_EUKREA_MBIMXSD51_BASEBOARD
+	depends on I2C
 	select SND_SOC_TLV320AIC23
 	select SND_MXC_SOC_FIQ
 	help
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index c8527ead3736..8df0fae21943 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -240,7 +240,6 @@ static int ssi_irq = 0;
 
 static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_dai *dai = rtd->cpu_dai;
 	struct snd_pcm *pcm = rtd->pcm;
 	struct snd_pcm_substream *substream;
 	int ret;
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 4297cb6af42e..4c05e2b8f4d2 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -391,7 +391,6 @@ static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
 int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
-	struct snd_soc_dai *dai = rtd->cpu_dai;
 	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index 0a84cec3599e..1072dfb53e47 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -218,12 +218,6 @@ struct imx_ssi {
 	struct platform_device *soc_platform_pdev_fiq;
 };
 
-struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
-		struct imx_ssi *ssi);
-void imx_ssi_fiq_exit(struct platform_device *pdev, struct imx_ssi *ssi);
-struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev,
-		struct imx_ssi *ssi);
-
 int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
 int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
 void imx_pcm_free(struct snd_pcm *pcm);
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
index a7c9578be983..d1989cde9f14 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -299,7 +299,7 @@ static void jz4740_pcm_free(struct snd_pcm *pcm)
 
 static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
 
-int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
+static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
 	struct snd_soc_dai *dai = rtd->cpu_dai;
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index d0bcf3fcea01..715e841c0507 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -476,7 +476,7 @@ static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver kirkwood_i2s_driver = {
 	.probe  = kirkwood_i2s_dev_probe,
-	.remove = kirkwood_i2s_dev_remove,
+	.remove = __devexit_p(kirkwood_i2s_dev_remove),
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index c8d21956ab52..c772b3cf4039 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -79,8 +79,6 @@ static int t5325_dai_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
 	snd_soc_dapm_enable_pin(dapm, "Speaker");
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index 429aa1be2cff..598f48c0d8f5 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -54,9 +54,7 @@ static unsigned int	hs_switch;
 static unsigned int	lo_dac;
 
 struct mfld_mc_private {
-	struct platform_device *socdev;
 	void __iomem *int_base;
-	struct snd_soc_codec *codec;
 	u8 interrupt_status;
 };
 
@@ -235,7 +233,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
 	/* always connected */
 	snd_soc_dapm_enable_pin(dapm, "Headphones");
 	snd_soc_dapm_enable_pin(dapm, "Mic");
-	snd_soc_dapm_sync(dapm);
 
 	ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
 				ARRAY_SIZE(mfld_snd_controls));
@@ -253,7 +250,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
 	/* we dont use linein in this so set to NC */
 	snd_soc_dapm_disable_pin(dapm, "LINEINL");
 	snd_soc_dapm_disable_pin(dapm, "LINEINR");
-	snd_soc_dapm_sync(dapm);
 
 	/* Headset and button jack detection */
 	ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack",
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
index 9925d20ab0a3..7df8c58ba50a 100644
--- a/sound/soc/mid-x86/sst_platform.c
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -63,7 +63,7 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
 };
 
 /* MFLD - MSIC */
-struct snd_soc_dai_driver sst_platform_dai[] = {
+static struct snd_soc_dai_driver sst_platform_dai[] = {
 {
 	.name = "Headset-cpu-dai",
 	.id = 0,
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 401944cf4560..76dc74d24fc2 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -617,7 +617,7 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
 
 static int mxs_saif_probe(struct platform_device *pdev)
 {
-	struct resource *res;
+	struct resource *iores, *dmares;
 	struct mxs_saif *saif;
 	struct mxs_saif_platform_data *pdata;
 	int ret = 0;
@@ -655,35 +655,36 @@ static int mxs_saif_probe(struct platform_device *pdev)
 		goto failed_clk;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iores) {
 		ret = -ENODEV;
 		dev_err(&pdev->dev, "failed to get io resource: %d\n",
 			ret);
 		goto failed_get_resource;
 	}
 
-	if (!request_mem_region(res->start, resource_size(res), "mxs-saif")) {
+	if (!request_mem_region(iores->start, resource_size(iores),
+				"mxs-saif")) {
 		dev_err(&pdev->dev, "request_mem_region failed\n");
 		ret = -EBUSY;
 		goto failed_get_resource;
 	}
 
-	saif->base = ioremap(res->start, resource_size(res));
+	saif->base = ioremap(iores->start, resource_size(iores));
 	if (!saif->base) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENODEV;
 		goto failed_ioremap;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!res) {
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!dmares) {
 		ret = -ENODEV;
 		dev_err(&pdev->dev, "failed to get dma resource: %d\n",
 			ret);
 		goto failed_ioremap;
 	}
-	saif->dma_param.chan_num = res->start;
+	saif->dma_param.chan_num = dmares->start;
 
 	saif->irq = platform_get_irq(pdev, 0);
 	if (saif->irq < 0) {
@@ -742,7 +743,7 @@ failed_get_irq2:
 failed_get_irq1:
 	iounmap(saif->base);
 failed_ioremap:
-	release_mem_region(res->start, resource_size(res));
+	release_mem_region(iores->start, resource_size(iores));
 failed_get_resource:
 	clk_put(saif->clk);
 failed_clk:
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
index 865b288bd748..ae8d6806966b 100644
--- a/sound/soc/nuc900/nuc900-pcm.c
+++ b/sound/soc/nuc900/nuc900-pcm.c
@@ -227,7 +227,7 @@ static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd)
 	return ret;
 }
 
-int nuc900_dma_getposition(struct snd_pcm_substream *substream,
+static int nuc900_dma_getposition(struct snd_pcm_substream *substream,
 					dma_addr_t *src, dma_addr_t *dst)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 59e2c8d1e38d..052fd758722e 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -1,7 +1,7 @@
 # OMAP Platform Support
 snd-soc-omap-objs := omap-pcm.o
 snd-soc-omap-mcbsp-objs := omap-mcbsp.o
-snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o
+snd-soc-omap-mcpdm-objs := omap-mcpdm.o
 snd-soc-omap-hdmi-objs := omap-hdmi.o
 
 obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index 73dde4a1adc3..8da55e916451 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -43,26 +43,6 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret;
 
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_DSP_B |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_DSP_B |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return ret;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0,
 			CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -110,28 +90,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"MICIN", NULL, "Mic In"},
 };
 
-static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	/* Add am3517-evm specific widgets */
-	snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
-				  ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
-	/* Set up davinci-evm specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	/* always connected */
-	snd_soc_dapm_enable_pin(dapm, "Line Out");
-	snd_soc_dapm_enable_pin(dapm, "Line In");
-	snd_soc_dapm_enable_pin(dapm, "Mic In");
-
-	snd_soc_dapm_sync(dapm);
-
-	return 0;
-}
-
 /* Digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link am3517evm_dai = {
 	.name = "TLV320AIC23",
@@ -140,7 +98,8 @@ static struct snd_soc_dai_link am3517evm_dai = {
 	.codec_dai_name = "tlv320aic23-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "tlv320aic23-codec.2-001a",
-	.init = am3517evm_aic23_init,
+	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
 	.ops = &am3517evm_ops,
 };
 
@@ -149,6 +108,11 @@ static struct snd_soc_card snd_soc_am3517evm = {
 	.name = "am3517evm",
 	.dai_link = &am3517evm_dai,
 	.num_links = 1,
+
+	.dapm_widgets = tlv320aic23_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *am3517evm_snd_device;
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 0aa475f92efa..dcb7b689a4ea 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -569,7 +569,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_disable_pin(dapm, "Speaker");
 	snd_soc_dapm_disable_pin(dapm, "AGCIN");
 	snd_soc_dapm_disable_pin(dapm, "AGCOUT");
-	snd_soc_dapm_sync(dapm);
 
 	/* Add virtual switch */
 	ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
index 0ae34702995b..84615a7de6ad 100644
--- a/sound/soc/omap/igep0020.c
+++ b/sound/soc/omap/igep0020.c
@@ -38,29 +38,8 @@ static int igep2_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret;
 
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return ret;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
 					    SND_SOC_CLOCK_IN);
@@ -84,6 +63,8 @@ static struct snd_soc_dai_link igep2_dai = {
 	.codec_dai_name = "twl4030-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "twl4030-codec",
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
 	.ops = &igep2_ops,
 };
 
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
deleted file mode 100644
index 928f03707451..000000000000
--- a/sound/soc/omap/mcpdm.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * mcpdm.c  --	McPDM interface driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- * Copyright (C) 2009 - 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
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include "mcpdm.h"
-
-static struct omap_mcpdm *mcpdm;
-
-static inline void omap_mcpdm_write(u16 reg, u32 val)
-{
-	__raw_writel(val, mcpdm->io_base + reg);
-}
-
-static inline int omap_mcpdm_read(u16 reg)
-{
-	return __raw_readl(mcpdm->io_base + reg);
-}
-
-static void omap_mcpdm_reg_dump(void)
-{
-	dev_dbg(mcpdm->dev, "***********************\n");
-	dev_dbg(mcpdm->dev, "IRQSTATUS_RAW:  0x%04x\n",
-			omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
-	dev_dbg(mcpdm->dev, "IRQSTATUS:	0x%04x\n",
-			omap_mcpdm_read(MCPDM_IRQSTATUS));
-	dev_dbg(mcpdm->dev, "IRQENABLE_SET:  0x%04x\n",
-			omap_mcpdm_read(MCPDM_IRQENABLE_SET));
-	dev_dbg(mcpdm->dev, "IRQENABLE_CLR:  0x%04x\n",
-			omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
-	dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
-			omap_mcpdm_read(MCPDM_IRQWAKE_EN));
-	dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
-			omap_mcpdm_read(MCPDM_DMAENABLE_SET));
-	dev_dbg(mcpdm->dev, "DMAENABLE_CLR:  0x%04x\n",
-			omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
-	dev_dbg(mcpdm->dev, "DMAWAKEEN:	0x%04x\n",
-			omap_mcpdm_read(MCPDM_DMAWAKEEN));
-	dev_dbg(mcpdm->dev, "CTRL:	0x%04x\n",
-			omap_mcpdm_read(MCPDM_CTRL));
-	dev_dbg(mcpdm->dev, "DN_DATA:  0x%04x\n",
-			omap_mcpdm_read(MCPDM_DN_DATA));
-	dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
-			omap_mcpdm_read(MCPDM_UP_DATA));
-	dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
-			omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
-	dev_dbg(mcpdm->dev, "FIFO_CTRL_UP:  0x%04x\n",
-			omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
-	dev_dbg(mcpdm->dev, "DN_OFFSET:	0x%04x\n",
-			omap_mcpdm_read(MCPDM_DN_OFFSET));
-	dev_dbg(mcpdm->dev, "***********************\n");
-}
-
-/*
- * Takes the McPDM module in and out of reset state.
- * Uplink and downlink can be reset individually.
- */
-static void omap_mcpdm_reset_capture(int reset)
-{
-	int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-	if (reset)
-		ctrl |= SW_UP_RST;
-	else
-		ctrl &= ~SW_UP_RST;
-
-	omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-static void omap_mcpdm_reset_playback(int reset)
-{
-	int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-	if (reset)
-		ctrl |= SW_DN_RST;
-	else
-		ctrl &= ~SW_DN_RST;
-
-	omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Enables the transfer through the PDM interface to/from the Phoenix
- * codec by enabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_start(int stream)
-{
-	int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-	if (stream)
-		ctrl |= mcpdm->up_channels;
-	else
-		ctrl |= mcpdm->dn_channels;
-
-	omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Disables the transfer through the PDM interface to/from the Phoenix
- * codec by disabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_stop(int stream)
-{
-	int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-	if (stream)
-		ctrl &= ~mcpdm->up_channels;
-	else
-		ctrl &= ~mcpdm->dn_channels;
-
-	omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Configures McPDM uplink for audio recording.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
-{
-	int irq_mask = 0;
-	int ctrl;
-
-	if (!uplink)
-		return -EINVAL;
-
-	mcpdm->uplink = uplink;
-
-	/* Enable irq request generation */
-	irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
-	omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
-	/* Configure uplink threshold */
-	if (uplink->threshold > UP_THRES_MAX)
-		uplink->threshold = UP_THRES_MAX;
-
-	omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
-
-	/* Configure DMA controller */
-	omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
-
-	/* Set pdm out format */
-	ctrl = omap_mcpdm_read(MCPDM_CTRL);
-	ctrl &= ~PDMOUTFORMAT;
-	ctrl |= uplink->format & PDMOUTFORMAT;
-
-	/* Uplink channels */
-	mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
-
-	omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
-	return 0;
-}
-
-/*
- * Configures McPDM downlink for audio playback.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
-{
-	int irq_mask = 0;
-	int ctrl;
-
-	if (!downlink)
-		return -EINVAL;
-
-	mcpdm->downlink = downlink;
-
-	/* Enable irq request generation */
-	irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
-	omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
-	/* Configure uplink threshold */
-	if (downlink->threshold > DN_THRES_MAX)
-		downlink->threshold = DN_THRES_MAX;
-
-	omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
-
-	/* Enable DMA request generation */
-	omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
-
-	/* Set pdm out format */
-	ctrl = omap_mcpdm_read(MCPDM_CTRL);
-	ctrl &= ~PDMOUTFORMAT;
-	ctrl |= downlink->format & PDMOUTFORMAT;
-
-	/* Downlink channels */
-	mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
-
-	omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
-	return 0;
-}
-
-/*
- * Cleans McPDM uplink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
-{
-	int irq_mask = 0;
-
-	if (!uplink)
-		return -EINVAL;
-
-	/* Disable irq request generation */
-	irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
-	omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
-	/* Disable DMA request generation */
-	omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
-
-	/* Clear Downlink channels */
-	mcpdm->up_channels = 0;
-
-	mcpdm->uplink = NULL;
-
-	return 0;
-}
-
-/*
- * Cleans McPDM downlink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink)
-{
-	int irq_mask = 0;
-
-	if (!downlink)
-		return -EINVAL;
-
-	/* Disable irq request generation */
-	irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
-	omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
-	/* Disable DMA request generation */
-	omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
-
-	/* clear Downlink channels */
-	mcpdm->dn_channels = 0;
-
-	mcpdm->downlink = NULL;
-
-	return 0;
-}
-
-static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
-{
-	struct omap_mcpdm *mcpdm_irq = dev_id;
-	int irq_status;
-
-	irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
-
-	/* Acknowledge irq event */
-	omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
-
-	if (irq & MCPDM_DN_IRQ_FULL) {
-		dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
-		omap_mcpdm_reset_playback(1);
-		omap_mcpdm_playback_open(mcpdm_irq->downlink);
-		omap_mcpdm_reset_playback(0);
-	}
-
-	if (irq & MCPDM_DN_IRQ_EMPTY) {
-		dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
-		omap_mcpdm_reset_playback(1);
-		omap_mcpdm_playback_open(mcpdm_irq->downlink);
-		omap_mcpdm_reset_playback(0);
-	}
-
-	if (irq & MCPDM_DN_IRQ) {
-		dev_dbg(mcpdm_irq->dev, "DN write request\n");
-	}
-
-	if (irq & MCPDM_UP_IRQ_FULL) {
-		dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
-		omap_mcpdm_reset_capture(1);
-		omap_mcpdm_capture_open(mcpdm_irq->uplink);
-		omap_mcpdm_reset_capture(0);
-	}
-
-	if (irq & MCPDM_UP_IRQ_EMPTY) {
-		dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
-		omap_mcpdm_reset_capture(1);
-		omap_mcpdm_capture_open(mcpdm_irq->uplink);
-		omap_mcpdm_reset_capture(0);
-	}
-
-	if (irq & MCPDM_UP_IRQ) {
-		dev_dbg(mcpdm_irq->dev, "UP write request\n");
-	}
-
-	return IRQ_HANDLED;
-}
-
-int omap_mcpdm_request(void)
-{
-	int ret;
-
-	clk_enable(mcpdm->clk);
-
-	spin_lock(&mcpdm->lock);
-
-	if (!mcpdm->free) {
-		dev_err(mcpdm->dev, "McPDM interface is in use\n");
-		spin_unlock(&mcpdm->lock);
-		ret = -EBUSY;
-		goto err;
-	}
-	mcpdm->free = 0;
-
-	spin_unlock(&mcpdm->lock);
-
-	/* Disable lines while request is ongoing */
-	omap_mcpdm_write(MCPDM_CTRL, 0x00);
-
-	ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
-				0, "McPDM", (void *)mcpdm);
-	if (ret) {
-		dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
-		goto err;
-	}
-
-	return 0;
-
-err:
-	clk_disable(mcpdm->clk);
-	return ret;
-}
-
-void omap_mcpdm_free(void)
-{
-	spin_lock(&mcpdm->lock);
-	if (mcpdm->free) {
-		dev_err(mcpdm->dev, "McPDM interface is already free\n");
-		spin_unlock(&mcpdm->lock);
-		return;
-	}
-	mcpdm->free = 1;
-	spin_unlock(&mcpdm->lock);
-
-	clk_disable(mcpdm->clk);
-
-	free_irq(mcpdm->irq, (void *)mcpdm);
-}
-
-/* Enable/disable DC offset cancelation for the analog
- * headset path (PDM channels 1 and 2).
- */
-int omap_mcpdm_set_offset(int offset1, int offset2)
-{
-	int offset;
-
-	if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
-		return -EINVAL;
-
-	offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
-
-	/* offset cancellation for channel 1 */
-	if (offset1)
-		offset |= DN_OFST_RX1_EN;
-	else
-		offset &= ~DN_OFST_RX1_EN;
-
-	/* offset cancellation for channel 2 */
-	if (offset2)
-		offset |= DN_OFST_RX2_EN;
-	else
-		offset &= ~DN_OFST_RX2_EN;
-
-	omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
-
-	return 0;
-}
-
-int __devinit omap_mcpdm_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	int ret = 0;
-
-	mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
-	if (!mcpdm) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no resource\n");
-		goto err_resource;
-	}
-
-	spin_lock_init(&mcpdm->lock);
-	mcpdm->free = 1;
-	mcpdm->io_base = ioremap(res->start, resource_size(res));
-	if (!mcpdm->io_base) {
-		ret = -ENOMEM;
-		goto err_resource;
-	}
-
-	mcpdm->irq = platform_get_irq(pdev, 0);
-
-	mcpdm->clk = clk_get(&pdev->dev, "pdm_ck");
-	if (IS_ERR(mcpdm->clk)) {
-		ret = PTR_ERR(mcpdm->clk);
-		dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret);
-		goto err_clk;
-	}
-
-	mcpdm->dev = &pdev->dev;
-	platform_set_drvdata(pdev, mcpdm);
-
-	return 0;
-
-err_clk:
-	iounmap(mcpdm->io_base);
-err_resource:
-	kfree(mcpdm);
-exit:
-	return ret;
-}
-
-int __devexit omap_mcpdm_remove(struct platform_device *pdev)
-{
-	struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
-
-	platform_set_drvdata(pdev, NULL);
-
-	clk_put(mcpdm_ptr->clk);
-
-	iounmap(mcpdm_ptr->io_base);
-
-	mcpdm_ptr->clk = NULL;
-	mcpdm_ptr->free = 0;
-	mcpdm_ptr->dev = NULL;
-
-	kfree(mcpdm_ptr);
-
-	return 0;
-}
-
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h
deleted file mode 100644
index df3e16fb51f3..000000000000
--- a/sound/soc/omap/mcpdm.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * mcpdm.h -- Defines for McPDM driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-/* McPDM registers */
-
-#define MCPDM_REVISION         0x00
-#define MCPDM_SYSCONFIG                0x10
-#define MCPDM_IRQSTATUS_RAW    0x24
-#define MCPDM_IRQSTATUS                0x28
-#define MCPDM_IRQENABLE_SET    0x2C
-#define MCPDM_IRQENABLE_CLR    0x30
-#define MCPDM_IRQWAKE_EN       0x34
-#define MCPDM_DMAENABLE_SET    0x38
-#define MCPDM_DMAENABLE_CLR    0x3C
-#define MCPDM_DMAWAKEEN                0x40
-#define MCPDM_CTRL             0x44
-#define MCPDM_DN_DATA          0x48
-#define MCPDM_UP_DATA          0x4C
-#define MCPDM_FIFO_CTRL_DN     0x50
-#define MCPDM_FIFO_CTRL_UP     0x54
-#define MCPDM_DN_OFFSET                0x58
-
-/*
- * MCPDM_IRQ bit fields
- * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
- */
-
-#define MCPDM_DN_IRQ                   (1 << 0)
-#define MCPDM_DN_IRQ_EMPTY             (1 << 1)
-#define MCPDM_DN_IRQ_ALMST_EMPTY       (1 << 2)
-#define MCPDM_DN_IRQ_FULL              (1 << 3)
-
-#define MCPDM_UP_IRQ                   (1 << 8)
-#define MCPDM_UP_IRQ_EMPTY             (1 << 9)
-#define MCPDM_UP_IRQ_ALMST_FULL                (1 << 10)
-#define MCPDM_UP_IRQ_FULL              (1 << 11)
-
-#define MCPDM_DOWNLINK_IRQ_MASK                0x00F
-#define MCPDM_UPLINK_IRQ_MASK          0xF00
-
-/*
- * MCPDM_DMAENABLE bit fields
- */
-
-#define DMA_DN_ENABLE          0x1
-#define DMA_UP_ENABLE          0x2
-
-/*
- * MCPDM_CTRL bit fields
- */
-
-#define PDM_UP1_EN             0x0001
-#define PDM_UP2_EN             0x0002
-#define PDM_UP3_EN             0x0004
-#define PDM_DN1_EN             0x0008
-#define PDM_DN2_EN             0x0010
-#define PDM_DN3_EN             0x0020
-#define PDM_DN4_EN             0x0040
-#define PDM_DN5_EN             0x0080
-#define PDMOUTFORMAT           0x0100
-#define CMD_INT                        0x0200
-#define STATUS_INT             0x0400
-#define SW_UP_RST              0x0800
-#define SW_DN_RST              0x1000
-#define PDM_UP_MASK            0x007
-#define PDM_DN_MASK            0x0F8
-#define PDM_CMD_MASK           0x200
-#define PDM_STATUS_MASK                0x400
-
-
-#define PDMOUTFORMAT_LJUST     (0 << 8)
-#define PDMOUTFORMAT_RJUST     (1 << 8)
-
-/*
- * MCPDM_FIFO_CTRL bit fields
- */
-
-#define UP_THRES_MAX           0xF
-#define DN_THRES_MAX           0xF
-
-/*
- * MCPDM_DN_OFFSET bit fields
- */
-
-#define DN_OFST_RX1_EN         0x0001
-#define DN_OFST_RX2_EN         0x0100
-
-#define DN_OFST_RX1            1
-#define DN_OFST_RX2            9
-#define DN_OFST_MAX            0x1F
-
-#define MCPDM_UPLINK           1
-#define MCPDM_DOWNLINK         2
-
-struct omap_mcpdm_link {
-       int irq_mask;
-       int threshold;
-       int format;
-       int channels;
-};
-
-struct omap_mcpdm_platform_data {
-       unsigned long phys_base;
-       u16 irq;
-};
-
-struct omap_mcpdm {
-       struct device *dev;
-       unsigned long phys_base;
-       void __iomem *io_base;
-       u8 free;
-       int irq;
-
-       spinlock_t lock;
-       struct omap_mcpdm_platform_data *pdata;
-       struct clk *clk;
-       struct omap_mcpdm_link *downlink;
-       struct omap_mcpdm_link *uplink;
-       struct completion irq_completion;
-
-       int dn_channels;
-       int up_channels;
-};
-
-extern void omap_mcpdm_start(int stream);
-extern void omap_mcpdm_stop(int stream);
-extern int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_request(void);
-extern void omap_mcpdm_free(void);
-extern int omap_mcpdm_set_offset(int offset1, int offset2);
-int __devinit omap_mcpdm_probe(struct platform_device *pdev);
-int __devexit omap_mcpdm_remove(struct platform_device *pdev);
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 62e292f49313..7e3c20c965c6 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -115,25 +115,8 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int err;
 
-	/* Set codec DAI configuration */
-	err = snd_soc_dai_set_fmt(codec_dai,
-					 SND_SOC_DAIFMT_I2S |
-					 SND_SOC_DAIFMT_NB_NF |
-					 SND_SOC_DAIFMT_CBM_CFM);
-	if (err < 0)
-		return err;
-
-	/* Set cpu DAI configuration */
-	err = snd_soc_dai_set_fmt(cpu_dai,
-				       SND_SOC_DAIFMT_I2S |
-				       SND_SOC_DAIFMT_NB_NF |
-				       SND_SOC_DAIFMT_CBM_CFM);
-	if (err < 0)
-		return err;
-
 	/* Set the codec system clock for DAC and ADC */
 	err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
 					    SND_SOC_CLOCK_IN);
@@ -274,7 +257,6 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int err;
 
 	/* Not connected */
 	snd_soc_dapm_nc_pin(dapm, "MONO_LOUT");
@@ -286,21 +268,6 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "LINE2L");
 	snd_soc_dapm_nc_pin(dapm, "LINE2R");
 
-	/* Add N810 specific controls */
-	err = snd_soc_add_controls(codec, aic33_n810_controls,
-				ARRAY_SIZE(aic33_n810_controls));
-	if (err < 0)
-		return err;
-
-	/* Add N810 specific widgets */
-	snd_soc_dapm_new_controls(dapm, aic33_dapm_widgets,
-				  ARRAY_SIZE(aic33_dapm_widgets));
-
-	/* Set up N810 specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
@@ -312,6 +279,8 @@ static struct snd_soc_dai_link n810_dai = {
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "tlv320aic3x-codec.2-0018",
 	.codec_dai_name = "tlv320aic3x-hifi",
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
 	.init = n810_aic33_init,
 	.ops = &n810_ops,
 };
@@ -321,6 +290,13 @@ static struct snd_soc_card snd_soc_n810 = {
 	.name = "N810",
 	.dai_link = &n810_dai,
 	.num_links = 1,
+
+	.controls = aic33_n810_controls,
+	.num_controls = ARRAY_SIZE(aic33_n810_controls),
+	.dapm_widgets = aic33_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *n810_snd_device;
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 478d60778453..4314647e735e 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -317,6 +317,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 		return 0;
 	}
 
+	regs->rcr2	&= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7));
+	regs->xcr2	&= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
+	regs->rcr1	&= ~(RFRLEN1(0x7f) | RWDLEN1(7));
+	regs->xcr1	&= ~(XFRLEN1(0x7f) | XWDLEN1(7));
 	format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 	wpf = channels = params_channels(params);
 	if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
@@ -369,6 +373,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 		framesize = wlen * channels;
 
 	/* Set FS period and length in terms of bit clock periods */
+	regs->srgr2	&= ~FPER(0xfff);
+	regs->srgr1	&= ~FWID(0xff);
 	switch (format) {
 	case SND_SOC_DAIFMT_I2S:
 	case SND_SOC_DAIFMT_LEFT_J:
@@ -398,7 +404,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 {
 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
 	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
-	unsigned int temp_fmt = fmt;
+	bool inv_fs = false;
 
 	if (mcbsp_data->configured)
 		return 0;
@@ -430,21 +436,21 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 		regs->xcr2	|= XDATDLY(0);
 		regs->spcr1	|= RJUST(2);
 		/* Invert FS polarity configuration */
-		temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+		inv_fs = true;
 		break;
 	case SND_SOC_DAIFMT_DSP_A:
 		/* 1-bit data delay */
 		regs->rcr2      |= RDATDLY(1);
 		regs->xcr2      |= XDATDLY(1);
 		/* Invert FS polarity configuration */
-		temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+		inv_fs = true;
 		break;
 	case SND_SOC_DAIFMT_DSP_B:
 		/* 0-bit data delay */
 		regs->rcr2      |= RDATDLY(0);
 		regs->xcr2      |= XDATDLY(0);
 		/* Invert FS polarity configuration */
-		temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+		inv_fs = true;
 		break;
 	default:
 		/* Unsupported data format */
@@ -468,7 +474,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 	}
 
 	/* Set bit clock (CLKX/CLKR) and FS polarities */
-	switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 	case SND_SOC_DAIFMT_NB_NF:
 		/*
 		 * Normal BCLK + FS.
@@ -489,6 +495,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 	default:
 		return -EINVAL;
 	}
+	if (inv_fs == true)
+		regs->pcr0 ^= FSXP | FSRP;
 
 	return 0;
 }
@@ -503,6 +511,7 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
 		return -ENODEV;
 
 	mcbsp_data->clk_div = div;
+	regs->srgr1	&= ~CLKGDV(0xff);
 	regs->srgr1	|= CLKGDV(div - 1);
 
 	return 0;
@@ -516,11 +525,12 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
 	int err = 0;
 
-	if (mcbsp_data->active)
+	if (mcbsp_data->active) {
 		if (freq == mcbsp_data->in_freq)
 			return 0;
 		else
 			return -EBUSY;
+	}
 
 	/* The McBSP signal muxing functions are only available on McBSP1 */
 	if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
@@ -531,6 +541,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 			return -EINVAL;
 
 	mcbsp_data->in_freq = freq;
+	regs->srgr2	&= ~CLKSM;
+	regs->pcr0	&= ~SCLKME;
 
 	switch (clk_id) {
 	case OMAP_MCBSP_SYSCLK_CLK:
@@ -605,8 +617,7 @@ static int mcbsp_dai_probe(struct snd_soc_dai *dai)
 	return 0;
 }
 
-static struct snd_soc_dai_driver omap_mcbsp_dai =
-{
+static struct snd_soc_dai_driver omap_mcbsp_dai = {
 	.probe = mcbsp_dai_probe,
 	.playback = {
 		.channels_min = 1,
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index bed09c27e44c..41d17067cc73 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -1,11 +1,12 @@
 /*
  * omap-mcpdm.c  --  OMAP ALSA SoC DAI driver using McPDM port
  *
- * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2009 - 2011 Texas Instruments
  *
- * Author: Misael Lopez Cruz <x0052729@ti.com>
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
  * Contact: Jorge Eduardo Candelaria <x0107209@ti.com>
  *          Margarita Olaya <magi.olaya@ti.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,41 +26,42 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
-#include <sound/initval.h>
 #include <sound/soc.h>
 
 #include <plat/dma.h>
-#include <plat/mcbsp.h>
-#include "mcpdm.h"
+#include <plat/omap_hwmod.h>
+#include "omap-mcpdm.h"
 #include "omap-pcm.h"
 
-struct omap_mcpdm_data {
-	struct omap_mcpdm_link *links;
-	int active;
-};
+struct omap_mcpdm {
+	struct device *dev;
+	unsigned long phys_base;
+	void __iomem *io_base;
+	int irq;
 
-static struct omap_mcpdm_link omap_mcpdm_links[] = {
-	/* downlink */
-	{
-		.irq_mask = MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL,
-		.threshold = 1,
-		.format = PDMOUTFORMAT_LJUST,
-	},
-	/* uplink */
-	{
-		.irq_mask = MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL,
-		.threshold = 1,
-		.format = PDMOUTFORMAT_LJUST,
-	},
-};
+	struct mutex mutex;
+
+	/* channel data */
+	u32 dn_channels;
+	u32 up_channels;
+
+	/* McPDM FIFO thresholds */
+	u32 dn_threshold;
+	u32 up_threshold;
 
-static struct omap_mcpdm_data mcpdm_data = {
-	.links = omap_mcpdm_links,
-	.active = 0,
+	/* McPDM dn offsets for rx1, and 2 channels */
+	u32 dn_rx_offset;
 };
 
 /*
@@ -71,88 +73,259 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
 		.dma_req = OMAP44XX_DMA_MCPDM_DL,
 		.data_type = OMAP_DMA_DATA_TYPE_S32,
 		.sync_mode = OMAP_DMA_SYNC_PACKET,
-		.packet_size = 16,
-		.port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_DN_DATA,
+		.port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA,
 	},
 	{
 		.name = "Audio capture",
 		.dma_req = OMAP44XX_DMA_MCPDM_UP,
 		.data_type = OMAP_DMA_DATA_TYPE_S32,
 		.sync_mode = OMAP_DMA_SYNC_PACKET,
-		.packet_size = 16,
-		.port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_UP_DATA,
+		.port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA,
 	},
 };
 
-static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
-				  struct snd_soc_dai *dai)
+static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
 {
-	int err = 0;
+	__raw_writel(val, mcpdm->io_base + reg);
+}
 
-	if (!dai->active)
-		err = omap_mcpdm_request();
+static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg)
+{
+	return __raw_readl(mcpdm->io_base + reg);
+}
 
-	return err;
+#ifdef DEBUG
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm)
+{
+	dev_dbg(mcpdm->dev, "***********************\n");
+	dev_dbg(mcpdm->dev, "IRQSTATUS_RAW:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS_RAW));
+	dev_dbg(mcpdm->dev, "IRQSTATUS:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS));
+	dev_dbg(mcpdm->dev, "IRQENABLE_SET:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_SET));
+	dev_dbg(mcpdm->dev, "IRQENABLE_CLR:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_CLR));
+	dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_IRQWAKE_EN));
+	dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_SET));
+	dev_dbg(mcpdm->dev, "DMAENABLE_CLR:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_CLR));
+	dev_dbg(mcpdm->dev, "DMAWAKEEN:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_DMAWAKEEN));
+	dev_dbg(mcpdm->dev, "CTRL:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL));
+	dev_dbg(mcpdm->dev, "DN_DATA:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_DN_DATA));
+	dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_UP_DATA));
+	dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_DN));
+	dev_dbg(mcpdm->dev, "FIFO_CTRL_UP:  0x%04x\n",
+			omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_UP));
+	dev_dbg(mcpdm->dev, "***********************\n");
 }
+#else
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
+#endif
 
-static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
-				    struct snd_soc_dai *dai)
+/*
+ * Enables the transfer through the PDM interface to/from the Phoenix
+ * codec by enabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
+{
+	u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+	ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+	ctrl |= mcpdm->dn_channels | mcpdm->up_channels;
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+	ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+}
+
+/*
+ * Disables the transfer through the PDM interface to/from the Phoenix
+ * codec by disabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
+{
+	u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+	ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+	ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+	ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+}
+
+/*
+ * Is the physical McPDM interface active.
+ */
+static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
+{
+	return omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL) &
+					(MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK);
+}
+
+/*
+ * Configures McPDM uplink, and downlink for audio.
+ * This function should be called before omap_mcpdm_start.
+ */
+static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
+{
+	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET,
+			MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL |
+			MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+	/* Enable DN RX1/2 offset cancellation feature, if configured */
+	if (mcpdm->dn_rx_offset) {
+		u32 dn_offset = mcpdm->dn_rx_offset;
+
+		omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+		dn_offset |= (MCPDM_DN_OFST_RX1_EN | MCPDM_DN_OFST_RX2_EN);
+		omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+	}
+
+	omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold);
+
+	omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET,
+			MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE);
+}
+
+/*
+ * Cleans McPDM uplink, and downlink configuration.
+ * This function should be called when the stream is closed.
+ */
+static void omap_mcpdm_close_streams(struct omap_mcpdm *mcpdm)
+{
+	/* Disable irq request generation for downlink */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+			MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL);
+
+	/* Disable DMA request generation for downlink */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_DN_ENABLE);
+
+	/* Disable irq request generation for uplink */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+			MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+	/* Disable DMA request generation for uplink */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_UP_ENABLE);
+
+	/* Disable RX1/2 offset cancellation */
+	if (mcpdm->dn_rx_offset)
+		omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, 0);
+}
+
+static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
+{
+	struct omap_mcpdm *mcpdm = dev_id;
+	int irq_status;
+
+	irq_status = omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS);
+
+	/* Acknowledge irq event */
+	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQSTATUS, irq_status);
+
+	if (irq_status & MCPDM_DN_IRQ_FULL)
+		dev_dbg(mcpdm->dev, "DN (playback) FIFO Full\n");
+
+	if (irq_status & MCPDM_DN_IRQ_EMPTY)
+		dev_dbg(mcpdm->dev, "DN (playback) FIFO Empty\n");
+
+	if (irq_status & MCPDM_DN_IRQ)
+		dev_dbg(mcpdm->dev, "DN (playback) write request\n");
+
+	if (irq_status & MCPDM_UP_IRQ_FULL)
+		dev_dbg(mcpdm->dev, "UP (capture) FIFO Full\n");
+
+	if (irq_status & MCPDM_UP_IRQ_EMPTY)
+		dev_dbg(mcpdm->dev, "UP (capture) FIFO Empty\n");
+
+	if (irq_status & MCPDM_UP_IRQ)
+		dev_dbg(mcpdm->dev, "UP (capture) write request\n");
+
+	return IRQ_HANDLED;
+}
+
+static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
 {
-	if (!dai->active)
-		omap_mcpdm_free();
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	mutex_lock(&mcpdm->mutex);
+
+	if (!dai->active) {
+		pm_runtime_get_sync(mcpdm->dev);
+
+		/* Enable watch dog for ES above ES 1.0 to avoid saturation */
+		if (omap_rev() != OMAP4430_REV_ES1_0) {
+			u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+			omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL,
+					 ctrl | MCPDM_WD_EN);
+		}
+		omap_mcpdm_open_streams(mcpdm);
+	}
+
+	mutex_unlock(&mcpdm->mutex);
+
+	return 0;
 }
 
-static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
-	struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-	int stream = substream->stream;
-	int err = 0;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!mcpdm_priv->active++)
-			omap_mcpdm_start(stream);
-		break;
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (!--mcpdm_priv->active)
-			omap_mcpdm_stop(stream);
-		break;
-	default:
-		err = -EINVAL;
+	mutex_lock(&mcpdm->mutex);
+
+	if (!dai->active) {
+		if (omap_mcpdm_active(mcpdm)) {
+			omap_mcpdm_stop(mcpdm);
+			omap_mcpdm_close_streams(mcpdm);
+		}
+
+		if (!omap_mcpdm_active(mcpdm))
+			pm_runtime_put_sync(mcpdm->dev);
 	}
 
-	return err;
+	mutex_unlock(&mcpdm->mutex);
 }
 
 static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_pcm_hw_params *params,
 				    struct snd_soc_dai *dai)
 {
-	struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-	struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 	int stream = substream->stream;
-	int channels, err, link_mask = 0;
-
-	snd_soc_dai_set_dma_data(dai, substream,
-				 &omap_mcpdm_dai_dma_params[stream]);
+	struct omap_pcm_dma_data *dma_data;
+	int channels;
+	int link_mask = 0;
 
 	channels = params_channels(params);
 	switch (channels) {
+	case 5:
+		if (stream == SNDRV_PCM_STREAM_CAPTURE)
+			/* up to 3 channels for capture */
+			return -EINVAL;
+		link_mask |= 1 << 4;
 	case 4:
 		if (stream == SNDRV_PCM_STREAM_CAPTURE)
-			/* up to 2 channels for capture */
+			/* up to 3 channels for capture */
 			return -EINVAL;
 		link_mask |= 1 << 3;
 	case 3:
-		if (stream == SNDRV_PCM_STREAM_CAPTURE)
-			/* up to 2 channels for capture */
-			return -EINVAL;
 		link_mask |= 1 << 2;
 	case 2:
 		link_mask |= 1 << 1;
@@ -164,95 +337,187 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
+	dma_data = &omap_mcpdm_dai_dma_params[stream];
+
+	/* Configure McPDM channels, and DMA packet size */
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		mcpdm_links[stream].channels = link_mask << 3;
-		err = omap_mcpdm_playback_open(&mcpdm_links[stream]);
+		mcpdm->dn_channels = link_mask << 3;
+		dma_data->packet_size =
+			(MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels;
 	} else {
-		mcpdm_links[stream].channels = link_mask << 0;
-		err = omap_mcpdm_capture_open(&mcpdm_links[stream]);
+		mcpdm->up_channels = link_mask << 0;
+		dma_data->packet_size = mcpdm->up_threshold * channels;
 	}
 
-	return err;
+	snd_soc_dai_set_dma_data(dai, substream, dma_data);
+
+	return 0;
 }
 
-static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream,
+static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
-	struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-	struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
-	int stream = substream->stream;
-	int err;
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
-	if (substream->stream ==  SNDRV_PCM_STREAM_PLAYBACK)
-		err = omap_mcpdm_playback_close(&mcpdm_links[stream]);
-	else
-		err = omap_mcpdm_capture_close(&mcpdm_links[stream]);
+	if (!omap_mcpdm_active(mcpdm)) {
+		omap_mcpdm_start(mcpdm);
+		omap_mcpdm_reg_dump(mcpdm);
+	}
 
-	return err;
+	return 0;
 }
 
 static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
 	.startup	= omap_mcpdm_dai_startup,
 	.shutdown	= omap_mcpdm_dai_shutdown,
-	.trigger	= omap_mcpdm_dai_trigger,
 	.hw_params	= omap_mcpdm_dai_hw_params,
-	.hw_free	= omap_mcpdm_dai_hw_free,
+	.prepare	= omap_mcpdm_prepare,
 };
 
-#define OMAP_MCPDM_RATES	(SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-#define OMAP_MCPDM_FORMATS	(SNDRV_PCM_FMTBIT_S32_LE)
+static int omap_mcpdm_probe(struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+	int ret;
 
-static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai)
+	pm_runtime_enable(mcpdm->dev);
+
+	/* Disable lines while request is ongoing */
+	pm_runtime_get_sync(mcpdm->dev);
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
+
+	ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
+				0, "McPDM", (void *)mcpdm);
+
+	pm_runtime_put_sync(mcpdm->dev);
+
+	if (ret) {
+		dev_err(mcpdm->dev, "Request for IRQ failed\n");
+		pm_runtime_disable(mcpdm->dev);
+	}
+
+	/* Configure McPDM threshold values */
+	mcpdm->dn_threshold = 2;
+	mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3;
+	return ret;
+}
+
+static int omap_mcpdm_remove(struct snd_soc_dai *dai)
 {
-	snd_soc_dai_set_drvdata(dai, &mcpdm_data);
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	free_irq(mcpdm->irq, (void *)mcpdm);
+	pm_runtime_disable(mcpdm->dev);
+
 	return 0;
 }
 
+#define OMAP_MCPDM_RATES	(SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+#define OMAP_MCPDM_FORMATS	SNDRV_PCM_FMTBIT_S32_LE
+
 static struct snd_soc_dai_driver omap_mcpdm_dai = {
-	.probe = omap_mcpdm_dai_probe,
+	.probe = omap_mcpdm_probe,
+	.remove = omap_mcpdm_remove,
+	.probe_order = SND_SOC_COMP_ORDER_LATE,
+	.remove_order = SND_SOC_COMP_ORDER_EARLY,
 	.playback = {
 		.channels_min = 1,
-		.channels_max = 4,
+		.channels_max = 5,
 		.rates = OMAP_MCPDM_RATES,
 		.formats = OMAP_MCPDM_FORMATS,
 	},
 	.capture = {
 		.channels_min = 1,
-		.channels_max = 2,
+		.channels_max = 3,
 		.rates = OMAP_MCPDM_RATES,
 		.formats = OMAP_MCPDM_FORMATS,
 	},
 	.ops = &omap_mcpdm_dai_ops,
 };
 
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+				    u8 rx1, u8 rx2)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+	mcpdm->dn_rx_offset = MCPDM_DNOFST_RX1(rx1) | MCPDM_DNOFST_RX2(rx2);
+}
+EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets);
+
 static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
 {
-	int ret;
+	struct omap_mcpdm *mcpdm;
+	struct resource *res;
+	int ret = 0;
+
+	mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
+	if (!mcpdm)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, mcpdm);
+
+	mutex_init(&mcpdm->mutex);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no resource\n");
+		goto err_res;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res), "McPDM")) {
+		ret = -EBUSY;
+		goto err_res;
+	}
+
+	mcpdm->io_base = ioremap(res->start, resource_size(res));
+	if (!mcpdm->io_base) {
+		ret = -ENOMEM;
+		goto err_iomap;
+	}
+
+	mcpdm->irq = platform_get_irq(pdev, 0);
+	if (mcpdm->irq < 0) {
+		ret = mcpdm->irq;
+		goto err_irq;
+	}
+
+	mcpdm->dev = &pdev->dev;
 
-	ret = omap_mcpdm_probe(pdev);
-	if (ret < 0)
-		return ret;
 	ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
-	if (ret < 0)
-		omap_mcpdm_remove(pdev);
+	if (!ret)
+		return 0;
+
+err_irq:
+	iounmap(mcpdm->io_base);
+err_iomap:
+	release_mem_region(res->start, resource_size(res));
+err_res:
+	kfree(mcpdm);
 	return ret;
 }
 
 static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
 {
+	struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev);
+	struct resource *res;
+
 	snd_soc_unregister_dai(&pdev->dev);
-	omap_mcpdm_remove(pdev);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iounmap(mcpdm->io_base);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(mcpdm);
 	return 0;
 }
 
 static struct platform_driver asoc_mcpdm_driver = {
 	.driver = {
-			.name = "omap-mcpdm-dai",
-			.owner = THIS_MODULE,
+		.name	= "omap-mcpdm",
+		.owner	= THIS_MODULE,
 	},
 
-	.probe = asoc_mcpdm_probe,
-	.remove = __devexit_p(asoc_mcpdm_remove),
+	.probe	= asoc_mcpdm_probe,
+	.remove	= __devexit_p(asoc_mcpdm_remove),
 };
 
 static int __init snd_omap_mcpdm_init(void)
@@ -267,6 +532,6 @@ static void __exit snd_omap_mcpdm_exit(void)
 }
 module_exit(snd_omap_mcpdm_exit);
 
-MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
 MODULE_DESCRIPTION("OMAP PDM SoC Interface");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h
new file mode 100644
index 000000000000..de8cf26595b1
--- /dev/null
+++ b/sound/soc/omap/omap-mcpdm.h
@@ -0,0 +1,107 @@
+/*
+ * omap-mcpdm.h
+ *
+ * Copyright (C) 2009 - 2011 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <misael.lopez@ti.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_MCPDM_H__
+#define __OMAP_MCPDM_H__
+
+#define MCPDM_REG_REVISION		0x00
+#define MCPDM_REG_SYSCONFIG		0x10
+#define MCPDM_REG_IRQSTATUS_RAW		0x24
+#define MCPDM_REG_IRQSTATUS		0x28
+#define MCPDM_REG_IRQENABLE_SET		0x2C
+#define MCPDM_REG_IRQENABLE_CLR		0x30
+#define MCPDM_REG_IRQWAKE_EN		0x34
+#define MCPDM_REG_DMAENABLE_SET		0x38
+#define MCPDM_REG_DMAENABLE_CLR		0x3C
+#define MCPDM_REG_DMAWAKEEN		0x40
+#define MCPDM_REG_CTRL			0x44
+#define MCPDM_REG_DN_DATA		0x48
+#define MCPDM_REG_UP_DATA		0x4C
+#define MCPDM_REG_FIFO_CTRL_DN		0x50
+#define MCPDM_REG_FIFO_CTRL_UP		0x54
+#define MCPDM_REG_DN_OFFSET		0x58
+
+/*
+ * MCPDM_IRQ bit fields
+ * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
+ */
+
+#define MCPDM_DN_IRQ			(1 << 0)
+#define MCPDM_DN_IRQ_EMPTY		(1 << 1)
+#define MCPDM_DN_IRQ_ALMST_EMPTY	(1 << 2)
+#define MCPDM_DN_IRQ_FULL		(1 << 3)
+
+#define MCPDM_UP_IRQ			(1 << 8)
+#define MCPDM_UP_IRQ_EMPTY		(1 << 9)
+#define MCPDM_UP_IRQ_ALMST_FULL		(1 << 10)
+#define MCPDM_UP_IRQ_FULL		(1 << 11)
+
+#define MCPDM_DOWNLINK_IRQ_MASK		0x00F
+#define MCPDM_UPLINK_IRQ_MASK		0xF00
+
+/*
+ * MCPDM_DMAENABLE bit fields
+ */
+
+#define MCPDM_DMA_DN_ENABLE		(1 << 0)
+#define MCPDM_DMA_UP_ENABLE		(1 << 1)
+
+/*
+ * MCPDM_CTRL bit fields
+ */
+
+#define MCPDM_PDM_UPLINK_EN(x)		(1 << (x - 1)) /* ch1 is at bit 0 */
+#define MCPDM_PDM_DOWNLINK_EN(x)	(1 << (x + 2)) /* ch1 is at bit 3 */
+#define MCPDM_PDMOUTFORMAT		(1 << 8)
+#define MCPDM_CMD_INT			(1 << 9)
+#define MCPDM_STATUS_INT		(1 << 10)
+#define MCPDM_SW_UP_RST			(1 << 11)
+#define MCPDM_SW_DN_RST			(1 << 12)
+#define MCPDM_WD_EN			(1 << 14)
+#define MCPDM_PDM_UP_MASK		0x7
+#define MCPDM_PDM_DN_MASK		(0x1f << 3)
+
+
+#define MCPDM_PDMOUTFORMAT_LJUST	(0 << 8)
+#define MCPDM_PDMOUTFORMAT_RJUST	(1 << 8)
+
+/*
+ * MCPDM_FIFO_CTRL bit fields
+ */
+
+#define MCPDM_UP_THRES_MAX		0xF
+#define MCPDM_DN_THRES_MAX		0xF
+
+/*
+ * MCPDM_DN_OFFSET bit fields
+ */
+
+#define MCPDM_DN_OFST_RX1_EN		(1 << 0)
+#define MCPDM_DNOFST_RX1(x)		((x & 0x1f) << 1)
+#define MCPDM_DN_OFST_RX2_EN		(1 << 8)
+#define MCPDM_DNOFST_RX2(x)		((x & 0x1f) << 9)
+
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+				    u8 rx1, u8 rx2);
+
+#endif	/* End of __OMAP_MCPDM_H__ */
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 9b5c88ac35b9..5e37ec915de2 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -198,6 +198,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
 			      OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
 	else if (!substream->runtime->no_period_wakeup)
 		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+	else {
+		/*
+		 * No period wakeup:
+		 * we need to disable BLOCK_IRQ, which is enabled by the omap
+		 * dma core at request dma time.
+		 */
+		omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ);
+	}
 
 	if (!(cpu_class_is_omap1())) {
 		omap_set_dma_src_burst_mode(prtd->dma_ch,
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
index 0daa04469836..bf9ae2a6f901 100644
--- a/sound/soc/omap/omap3evm.c
+++ b/sound/soc/omap/omap3evm.c
@@ -36,29 +36,8 @@ static int omap3evm_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret;
 
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "Can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "Can't set cpu DAI configuration\n");
-		return ret;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
 				     SND_SOC_CLOCK_IN);
@@ -82,6 +61,8 @@ static struct snd_soc_dai_link omap3evm_dai = {
 	.codec_dai_name = "twl4030-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "twl4030-codec",
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
 	.ops 		= &omap3evm_ops,
 };
 
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 8047c521e318..30a75b406aea 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -48,24 +48,8 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-		  SND_SOC_DAIFMT_CBS_CFS;
 	int ret;
 
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai, fmt);
-	if (ret < 0) {
-		pr_err(PREFIX "can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
-	if (ret < 0) {
-		pr_err(PREFIX "can't set cpu DAI configuration\n");
-		return ret;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
 					    SND_SOC_CLOCK_IN);
@@ -189,10 +173,8 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
 	if (ret < 0)
 		return ret;
 
-	snd_soc_dapm_add_routes(dapm, omap3pandora_out_map,
+	return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map,
 		ARRAY_SIZE(omap3pandora_out_map));
-
-	return snd_soc_dapm_sync(dapm);
 }
 
 static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
@@ -212,10 +194,8 @@ static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
 	if (ret < 0)
 		return ret;
 
-	snd_soc_dapm_add_routes(dapm, omap3pandora_in_map,
+	return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map,
 		ARRAY_SIZE(omap3pandora_in_map));
-
-	return snd_soc_dapm_sync(dapm);
 }
 
 static struct snd_soc_ops omap3pandora_ops = {
@@ -231,6 +211,8 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
 		.codec_dai_name = "twl4030-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			   SND_SOC_DAIFMT_CBS_CFS,
 		.ops = &omap3pandora_ops,
 		.init = omap3pandora_out_init,
 	}, {
@@ -240,6 +222,8 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
 		.codec_dai_name = "twl4030-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			   SND_SOC_DAIFMT_CBS_CFS,
 		.ops = &omap3pandora_ops,
 		.init = omap3pandora_in_init,
 	}
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index 7e75e775fb4a..db91ccaf6c97 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -55,29 +55,8 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int err;
 
-	/* Set codec DAI configuration */
-	err = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_DSP_B |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (err < 0) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return err;
-	}
-
-	/* Set cpu DAI configuration */
-	err = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_DSP_B |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (err < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return err;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	err =
 	    snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -112,27 +91,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"MICIN", NULL, "Mic Jack"},
 };
 
-static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	/* Add osk5912 specific widgets */
-	snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
-				  ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
-	/* Set up osk5912 specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
-	snd_soc_dapm_enable_pin(dapm, "Line In");
-	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
-
-	snd_soc_dapm_sync(dapm);
-
-	return 0;
-}
-
 /* Digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link osk_dai = {
 	.name = "TLV320AIC23",
@@ -141,7 +99,8 @@ static struct snd_soc_dai_link osk_dai = {
 	.codec_dai_name = "tlv320aic23-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "tlv320aic23-codec",
-	.init = osk_tlv320aic23_init,
+	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
 	.ops = &osk_ops,
 };
 
@@ -150,6 +109,11 @@ static struct snd_soc_card snd_soc_card_osk = {
 	.name = "OSK5912",
 	.dai_link = &osk_dai,
 	.num_links = 1,
+
+	.dapm_widgets = tlv320aic23_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *osk_snd_device;
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index bbcf380bfb56..739efe9e327a 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -38,29 +38,8 @@ static int overo_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret;
 
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return ret;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
 					    SND_SOC_CLOCK_IN);
@@ -84,6 +63,8 @@ static struct snd_soc_dai_link overo_dai = {
 	.codec_dai_name = "twl4030-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "twl4030-codec",
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBM_CFM,
 	.ops = &overo_ops,
 };
 
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 893300a53bab..a56842380c72 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -115,24 +115,6 @@ static int rx51_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	int err;
-
-	/* Set codec DAI configuration */
-	err = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_DSP_A |
-				  SND_SOC_DAIFMT_IB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (err < 0)
-		return err;
-
-	/* Set cpu DAI configuration */
-	err = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_DSP_A |
-				  SND_SOC_DAIFMT_IB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (err < 0)
-		return err;
 
 	/* Set the codec system clock for DAC and ADC */
 	return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
@@ -335,8 +317,6 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 	if (err < 0)
 		return err;
 
-	snd_soc_dapm_sync(dapm);
-
 	/* AV jack detection */
 	err = snd_soc_jack_new(codec, "AV Jack",
 			       SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
@@ -377,6 +357,8 @@ static struct snd_soc_dai_link rx51_dai[] = {
 		.codec_dai_name = "tlv320aic3x-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "tlv320aic3x-codec.2-0018",
+		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
 		.init = rx51_aic34_init,
 		.ops = &rx51_ops,
 	},
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index 9f6a758029d1..4f1969de91a7 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -53,29 +53,8 @@ static int sdp3430_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret;
 
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return ret;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
 					    SND_SOC_CLOCK_IN);
@@ -91,49 +70,6 @@ static struct snd_soc_ops sdp3430_ops = {
 	.hw_params = sdp3430_hw_params,
 };
 
-static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	int ret;
-
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-				SND_SOC_DAIFMT_DSP_A |
-				SND_SOC_DAIFMT_IB_NF |
-				SND_SOC_DAIFMT_CBM_CFM);
-	if (ret) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				SND_SOC_DAIFMT_DSP_A |
-				SND_SOC_DAIFMT_IB_NF |
-				SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return ret;
-	}
-
-	/* Set the codec system clock for DAC and ADC */
-	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
-					    SND_SOC_CLOCK_IN);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set codec system clock\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static struct snd_soc_ops sdp3430_voice_ops = {
-	.hw_params = sdp3430_hw_voice_params,
-};
-
 /* Headset jack */
 static struct snd_soc_jack hs_jack;
 
@@ -193,15 +129,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret;
 
-	/* Add SDP3430 specific widgets */
-	ret = snd_soc_dapm_new_controls(dapm, sdp3430_twl4030_dapm_widgets,
-				ARRAY_SIZE(sdp3430_twl4030_dapm_widgets));
-	if (ret)
-		return ret;
-
-	/* Set up SDP3430 specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
 	/* SDP3430 connected pins */
 	snd_soc_dapm_enable_pin(dapm, "Ext Mic");
 	snd_soc_dapm_enable_pin(dapm, "Ext Spk");
@@ -223,10 +150,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "CARKITL");
 	snd_soc_dapm_nc_pin(dapm, "CARKITR");
 
-	ret = snd_soc_dapm_sync(dapm);
-	if (ret)
-		return ret;
-
 	/* Headset jack detection */
 	ret = snd_soc_jack_new(codec, "Headset Jack",
 				SND_JACK_HEADSET, &hs_jack);
@@ -267,6 +190,8 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
 		.codec_dai_name = "twl4030-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
 		.init = sdp3430_twl4030_init,
 		.ops = &sdp3430_ops,
 	},
@@ -277,8 +202,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
 		.codec_dai_name = "twl4030-voice",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
 		.init = sdp3430_twl4030_voice_init,
-		.ops = &sdp3430_voice_ops,
+		.ops = &sdp3430_ops,
 	},
 };
 
@@ -287,6 +214,11 @@ static struct snd_soc_card snd_soc_sdp3430 = {
 	.name = "SDP3430",
 	.dai_link = sdp3430_dai,
 	.num_links = ARRAY_SIZE(sdp3430_dai),
+
+	.dapm_widgets = sdp3430_twl4030_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(sdp3430_twl4030_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *sdp3430_snd_device;
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index b80efb02bfca..cc3d792af5ea 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -32,7 +32,7 @@
 #include <plat/hardware.h>
 #include <plat/mux.h>
 
-#include "mcpdm.h"
+#include "omap-mcpdm.h"
 #include "omap-pcm.h"
 #include "../codecs/twl6040.h"
 
@@ -88,7 +88,7 @@ static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
 	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
 	SND_SOC_DAPM_SPK("Earphone Spk", NULL),
-	SND_SOC_DAPM_INPUT("Aux/FM Stereo In"),
+	SND_SOC_DAPM_INPUT("FM Stereo In"),
 };
 
 static const struct snd_soc_dapm_route audio_map[] = {
@@ -113,36 +113,22 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"Earphone Spk", NULL, "EP"},
 
 	/* Aux/FM Stereo In: AFML, AFMR */
-	{"AFML", NULL, "Aux/FM Stereo In"},
-	{"AFMR", NULL, "Aux/FM Stereo In"},
+	{"AFML", NULL, "FM Stereo In"},
+	{"AFMR", NULL, "FM Stereo In"},
 };
 
 static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int ret;
-
-	/* Add SDP4430 specific widgets */
-	ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
-				ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
-	if (ret)
-		return ret;
-
-	/* Set up SDP4430 specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+	int ret, hs_trim;
 
-	/* SDP4430 connected pins */
-	snd_soc_dapm_enable_pin(dapm, "Ext Mic");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk");
-	snd_soc_dapm_enable_pin(dapm, "AFML");
-	snd_soc_dapm_enable_pin(dapm, "AFMR");
-	snd_soc_dapm_enable_pin(dapm, "Headset Mic");
-	snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
-
-	ret = snd_soc_dapm_sync(dapm);
-	if (ret)
-		return ret;
+	/*
+	 * Configure McPDM offset cancellation based on the HSOTRIM value from
+	 * twl6040.
+	 */
+	hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
+	omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
+					TWL6040_HSF_TRIM_RIGHT(hs_trim));
 
 	/* Headset jack detection */
 	ret = snd_soc_jack_new(codec, "Headset Jack",
@@ -165,8 +151,8 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link sdp4430_dai = {
 	.name = "TWL6040",
 	.stream_name = "TWL6040",
-	.cpu_dai_name ="omap-mcpdm-dai",
-	.codec_dai_name = "twl6040-hifi",
+	.cpu_dai_name = "omap-mcpdm",
+	.codec_dai_name = "twl6040-legacy",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "twl6040-codec",
 	.init = sdp4430_twl6040_init,
@@ -178,6 +164,11 @@ static struct snd_soc_card snd_soc_sdp4430 = {
 	.name = "SDP4430",
 	.dai_link = &sdp4430_dai,
 	.num_links = 1,
+
+	.dapm_widgets = sdp4430_twl6040_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(sdp4430_twl6040_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *sdp4430_snd_device;
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
index 9a2666ffc16c..7cf35c82368a 100644
--- a/sound/soc/omap/zoom2.c
+++ b/sound/soc/omap/zoom2.c
@@ -44,29 +44,8 @@ static int zoom2_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret;
 
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_NF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return ret;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
 					SND_SOC_CLOCK_IN);
@@ -82,49 +61,6 @@ static struct snd_soc_ops zoom2_ops = {
 	.hw_params = zoom2_hw_params,
 };
 
-static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	int ret;
-
-	/* Set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-				SND_SOC_DAIFMT_DSP_A |
-				SND_SOC_DAIFMT_IB_NF |
-				SND_SOC_DAIFMT_CBM_CFM);
-	if (ret) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return ret;
-	}
-
-	/* Set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-				SND_SOC_DAIFMT_DSP_A |
-				SND_SOC_DAIFMT_IB_NF |
-				SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return ret;
-	}
-
-	/* Set the codec system clock for DAC and ADC */
-	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
-					SND_SOC_CLOCK_IN);
-	if (ret < 0) {
-		printk(KERN_ERR "can't set codec system clock\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static struct snd_soc_ops zoom2_voice_ops = {
-	.hw_params = zoom2_hw_voice_params,
-};
-
 /* Zoom2 machine DAPM */
 static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Ext Mic", NULL),
@@ -162,23 +98,6 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int ret;
-
-	/* Add Zoom2 specific widgets */
-	ret = snd_soc_dapm_new_controls(dapm, zoom2_twl4030_dapm_widgets,
-				ARRAY_SIZE(zoom2_twl4030_dapm_widgets));
-	if (ret)
-		return ret;
-
-	/* Set up Zoom2 specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	/* Zoom2 connected pins */
-	snd_soc_dapm_enable_pin(dapm, "Ext Mic");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk");
-	snd_soc_dapm_enable_pin(dapm, "Headset Mic");
-	snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
-	snd_soc_dapm_enable_pin(dapm, "Aux In");
 
 	/* TWL4030 not connected pins */
 	snd_soc_dapm_nc_pin(dapm, "CARKITMIC");
@@ -190,9 +109,7 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "CARKITL");
 	snd_soc_dapm_nc_pin(dapm, "CARKITR");
 
-	ret = snd_soc_dapm_sync(dapm);
-
-	return ret;
+	return 0;
 }
 
 static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
@@ -217,6 +134,8 @@ static struct snd_soc_dai_link zoom2_dai[] = {
 		.codec_dai_name = "twl4030-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
 		.init = zoom2_twl4030_init,
 		.ops = &zoom2_ops,
 	},
@@ -227,8 +146,10 @@ static struct snd_soc_dai_link zoom2_dai[] = {
 		.codec_dai_name = "twl4030-voice",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
+		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+			   SND_SOC_DAIFMT_CBM_CFM,
 		.init = zoom2_twl4030_voice_init,
-		.ops = &zoom2_voice_ops,
+		.ops = &zoom2_ops,
 	},
 };
 
@@ -237,6 +158,11 @@ static struct snd_soc_card snd_soc_zoom2 = {
 	.name = "Zoom2",
 	.dai_link = zoom2_dai,
 	.num_links = ARRAY_SIZE(zoom2_dai),
+
+	.dapm_widgets = zoom2_twl4030_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(zoom2_twl4030_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *zoom2_snd_device;
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 33ebc46b45b5..ffd2242e305f 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -121,6 +121,7 @@ config SND_PXA2XX_SOC_PALM27X
 config SND_SOC_SAARB
 	tristate "SoC Audio support for Marvell Saarb"
 	depends on SND_PXA2XX_SOC && MACH_SAARB
+	select MFD_88PM860X
 	select SND_PXA_SOC_SSP
 	select SND_SOC_88PM860X
 	help
@@ -130,6 +131,7 @@ config SND_SOC_SAARB
 config SND_SOC_TAVOREVB3
 	tristate "SoC Audio support for Marvell Tavor EVB3"
 	depends on SND_PXA2XX_SOC && MACH_TAVOREVB3
+	select MFD_88PM860X
 	select SND_PXA_SOC_SSP
 	select SND_SOC_88PM860X
 	help
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 28757fb9df31..b0e2fb720910 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -299,7 +299,6 @@ static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 	/* Set up corgi specific audio path audio_map */
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	snd_soc_dapm_sync(dapm);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
index dc65650a6fa1..35ed7eb8cff2 100644
--- a/sound/soc/pxa/e740_wm9705.c
+++ b/sound/soc/pxa/e740_wm9705.c
@@ -108,8 +108,6 @@ static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd)
 
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
index 51897fcd911b..ce5f056009a7 100644
--- a/sound/soc/pxa/e750_wm9705.c
+++ b/sound/soc/pxa/e750_wm9705.c
@@ -90,8 +90,6 @@ static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd)
 
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index 053ed208e59f..6a8f38b6c379 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -80,7 +80,6 @@ static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd)
 					ARRAY_SIZE(e800_dapm_widgets));
 
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-	snd_soc_dapm_sync(dapm);
 
 	return 0;
 }
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 67dcc36cd621..e79f516c400e 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -92,11 +92,10 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	unsigned int acps, acds, width, rate;
+	unsigned int acps, acds, width;
 	unsigned int div4 = PXA_SSP_CLK_SCDB_4;
 	int ret = 0;
 
-	rate = params_rate(params);
 	width = snd_pcm_format_physical_width(params_format(params));
 
 	/*
@@ -424,7 +423,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
 	/* Set up magician specific audio path interconnects */
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	snd_soc_dapm_sync(dapm);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 38ca6759907e..0b8d1ee738a4 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -151,7 +151,6 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_enable_pin(dapm, "Front Mic");
 	snd_soc_dapm_enable_pin(dapm, "GSM Line In");
 	snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
-	snd_soc_dapm_sync(dapm);
 
 	return 0;
 }
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 504e4004f004..7edc1fb71fae 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -107,10 +107,6 @@ static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "PHONE");
 	snd_soc_dapm_nc_pin(dapm, "MIC2");
 
-	err = snd_soc_dapm_sync(dapm);
-	if (err)
-		return err;
-
 	/* Jack detection API stuff */
 	err = snd_soc_jack_new(codec, "Headphone Jack",
 				SND_JACK_HEADPHONE, &hs_jack);
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index da3ae4316cf2..4c29bc1f9cfe 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -265,7 +265,6 @@ static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 	/* Set up poodle specific audio path audio_map */
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	snd_soc_dapm_sync(dapm);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c
index 9595189fc681..d9467a2c6de0 100644
--- a/sound/soc/pxa/saarb.c
+++ b/sound/soc/pxa/saarb.c
@@ -146,10 +146,6 @@ static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
 	snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
 
-	ret = snd_soc_dapm_sync(dapm);
-	if (ret)
-		return ret;
-
 	/* Headset jack detection */
 	snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
 			| SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index ce920e3cfea1..c2d6ff9b1588 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -301,7 +301,6 @@ static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd)
 	/* Set up spitz specific audio paths */
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	snd_soc_dapm_sync(dapm);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/tavorevb3.c b/sound/soc/pxa/tavorevb3.c
index f881f65ec172..eeec892e0e04 100644
--- a/sound/soc/pxa/tavorevb3.c
+++ b/sound/soc/pxa/tavorevb3.c
@@ -146,10 +146,6 @@ static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
 	snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
 
-	ret = snd_soc_dapm_sync(dapm);
-	if (ret)
-		return ret;
-
 	/* Headset jack detection */
 	snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
 			| SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 9a2351366957..620fc69ae632 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -211,7 +211,6 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
 	/* set up tosa specific audio path audio_map */
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	snd_soc_dapm_sync(dapm);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c
index 4b81ffd87566..b311ffe04b71 100644
--- a/sound/soc/pxa/z2.c
+++ b/sound/soc/pxa/z2.c
@@ -161,10 +161,6 @@ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
 	/* Set up z2 specific audio paths */
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	ret = snd_soc_dapm_sync(dapm);
-	if (ret)
-		goto err;
-
 	/* Jack detection API stuff */
 	ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
 				&hs_jack);
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index b6445757fc54..580aae38e502 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -87,7 +87,6 @@ static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_enable_pin(dapm, "Headphone");
 	snd_soc_dapm_enable_pin(dapm, "Headset Earpiece");
 
-	snd_soc_dapm_sync(dapm);
 	return 0;
 }
 
@@ -196,20 +195,20 @@ static int zylonite_probe(struct snd_soc_card *card)
 	if (clk_pout) {
 		pout = clk_get(NULL, "CLK_POUT");
 		if (IS_ERR(pout)) {
-			dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n",
+			dev_err(card->dev, "Unable to obtain CLK_POUT: %ld\n",
 				PTR_ERR(pout));
 			return PTR_ERR(pout);
 		}
 
 		ret = clk_enable(pout);
 		if (ret != 0) {
-			dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
+			dev_err(card->dev, "Unable to enable CLK_POUT: %d\n",
 				ret);
 			clk_put(pout);
 			return ret;
 		}
 
-		dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n",
+		dev_dbg(card->dev, "MCLK enabled at %luHz\n",
 			clk_get_rate(pout));
 	}
 
@@ -241,7 +240,7 @@ static int zylonite_resume_pre(struct snd_soc_card *card)
 	if (clk_pout) {
 		ret = clk_enable(pout);
 		if (ret != 0)
-			dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
+			dev_err(card->dev, "Unable to enable CLK_POUT: %d\n",
 				ret);
 	}
 
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index dd3b3eac0805..53aaa69eda03 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -64,6 +64,8 @@ config SND_SOC_SAMSUNG_SMDK_WM8580
 config SND_SOC_SAMSUNG_SMDK_WM8994
 	tristate "SoC I2S Audio support for WM8994 on SMDK"
 	depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210 || MACH_SMDK4212)
+	depends on I2C=y && GENERIC_HARDIRQS
+	select MFD_WM8994
 	select SND_SOC_WM8994
 	select SND_SAMSUNG_I2S
 	help
@@ -150,7 +152,9 @@ config SND_SOC_SMARTQ
 config SND_SOC_GONI_AQUILA_WM8994
 	tristate "SoC I2S Audio support for AQUILA/GONI - WM8994"
 	depends on SND_SOC_SAMSUNG && (MACH_GONI || MACH_AQUILA)
+	depends on I2C=y && GENERIC_HARDIRQS
 	select SND_SAMSUNG_I2S
+	select MFD_WM8994
 	select SND_SOC_WM8994
 	help
 	  Say Y if you want to add support for SoC audio on goni or aquila
@@ -174,6 +178,8 @@ config SND_SOC_SMDK_WM8580_PCM
 config SND_SOC_SMDK_WM8994_PCM
 	tristate "SoC PCM Audio support for WM8994 on SMDK"
 	depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310 || MACH_SMDK4212)
+	depends on I2C=y && GENERIC_HARDIRQS
+	select MFD_WM8994
 	select SND_SOC_WM8994
 	select SND_SAMSUNG_PCM
 	help
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 884c8a107bf9..b5e922f469d5 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -495,7 +495,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c_ac97_driver = {
 	.probe  = s3c_ac97_probe,
-	.remove = s3c_ac97_remove,
+	.remove = __devexit_p(s3c_ac97_remove),
 	.driver = {
 		.name = "samsung-ac97",
 		.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c
index eb6d72ed55a7..4a34f608e131 100644
--- a/sound/soc/samsung/goni_wm8994.c
+++ b/sound/soc/samsung/goni_wm8994.c
@@ -99,14 +99,6 @@ static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret;
 
-	/* add goni specific widgets */
-	snd_soc_dapm_new_controls(dapm, goni_dapm_widgets,
-			ARRAY_SIZE(goni_dapm_widgets));
-
-	/* set up goni specific audio routes */
-	snd_soc_dapm_add_routes(dapm, goni_dapm_routes,
-			ARRAY_SIZE(goni_dapm_routes));
-
 	/* set endpoints to not connected */
 	snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
 	snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
@@ -120,8 +112,6 @@ static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
 		snd_soc_dapm_nc_pin(dapm, "SPKOUTRP");
 	}
 
-	snd_soc_dapm_sync(dapm);
-
 	/* Headset jack detection */
 	ret = snd_soc_jack_new(codec, "Headset Jack",
 			SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
@@ -255,6 +245,11 @@ static struct snd_soc_card goni = {
 	.name = "goni",
 	.dai_link = goni_dai,
 	.num_links = ARRAY_SIZE(goni_dai),
+
+	.dapm_widgets = goni_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(goni_dapm_widgets),
+	.dapm_routes = goni_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(goni_dapm_routes),
 };
 
 static int __init goni_init(void)
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index c6c65892294e..f75a4b60cf38 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -182,24 +182,10 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int err;
 
-	/* Add h1940 specific widgets */
-	err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
-				  ARRAY_SIZE(uda1380_dapm_widgets));
-	if (err)
-		return err;
-
-	/* Set up h1940 specific audio path audio_mapnects */
-	err = snd_soc_dapm_add_routes(dapm, audio_map,
-				      ARRAY_SIZE(audio_map));
-	if (err)
-		return err;
-
 	snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
 	snd_soc_dapm_enable_pin(dapm, "Speaker");
 	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
-	snd_soc_dapm_sync(dapm);
-
 	snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
 		&hp_jack);
 
@@ -230,6 +216,11 @@ static struct snd_soc_card h1940_asoc = {
 	.name = "h1940",
 	.dai_link = h1940_uda1380_dai,
 	.num_links = ARRAY_SIZE(h1940_uda1380_dai),
+
+	.dapm_widgets = uda1380_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static int __init h1940_init(void)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index c086b78539ee..0c9ac20d2223 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -1136,7 +1136,7 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
 
 static struct platform_driver samsung_i2s_driver = {
 	.probe  = samsung_i2s_probe,
-	.remove = samsung_i2s_remove,
+	.remove = __devexit_p(samsung_i2s_remove),
 	.driver = {
 		.name = "samsung-i2s",
 		.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c
index ed8f13a29c85..f5f7c6f822d5 100644
--- a/sound/soc/samsung/jive_wm8750.c
+++ b/sound/soc/samsung/jive_wm8750.c
@@ -110,18 +110,6 @@ static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "OUT3");
 	snd_soc_dapm_nc_pin(dapm, "MONO");
 
-	/* Add jive specific widgets */
-	err = snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
-					ARRAY_SIZE(wm8750_dapm_widgets));
-	if (err) {
-		printk(KERN_ERR "%s: failed to add widgets (%d)\n",
-		       __func__, err);
-		return err;
-	}
-
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
@@ -141,6 +129,11 @@ static struct snd_soc_card snd_soc_machine_jive = {
 	.name		= "Jive",
 	.dai_link	= &jive_dai,
 	.num_links	= 1,
+
+	.dapm_widgtets	= wm8750_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
+	.dapm_routes	= audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *jive_snd_device;
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 16152ed08648..7207189cd211 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -367,8 +367,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
 			return ret;
 	}
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
@@ -409,8 +407,6 @@ static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
 	snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
 	snd_soc_dapm_ignore_suspend(dapm, "Headphone");
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 9c7e8b48aed6..e55d7a5c4bdc 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -624,7 +624,7 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c_pcm_driver = {
 	.probe  = s3c_pcm_dev_probe,
-	.remove = s3c_pcm_dev_remove,
+	.remove = __devexit_p(s3c_pcm_dev_remove),
 	.driver = {
 		.name = "samsung-pcm",
 		.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index bc8c1676459f..aea7f1b24e6b 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -90,12 +90,6 @@ static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
 	},
 };
 
-static struct snd_soc_card rx1950_asoc = {
-	.name = "rx1950",
-	.dai_link = rx1950_uda1380_dai,
-	.num_links = ARRAY_SIZE(rx1950_uda1380_dai),
-};
-
 /* rx1950 machine dapm widgets */
 static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -117,6 +111,17 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"VINM", NULL, "Mic Jack"},
 };
 
+static struct snd_soc_card rx1950_asoc = {
+	.name = "rx1950",
+	.dai_link = rx1950_uda1380_dai,
+	.num_links = ARRAY_SIZE(rx1950_uda1380_dai),
+
+	.dapm_widgets = uda1380_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
 static struct platform_device *s3c24xx_snd_device;
 
 static int rx1950_startup(struct snd_pcm_substream *substream)
@@ -220,26 +225,10 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int err;
 
-	/* Add rx1950 specific widgets */
-	err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
-				  ARRAY_SIZE(uda1380_dapm_widgets));
-
-	if (err)
-		return err;
-
-	/* Set up rx1950 specific audio path audio_mapnects */
-	err = snd_soc_dapm_add_routes(dapm, audio_map,
-				      ARRAY_SIZE(audio_map));
-
-	if (err)
-		return err;
-
 	snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
 	snd_soc_dapm_enable_pin(dapm, "Speaker");
 	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
-	snd_soc_dapm_sync(dapm);
-
 	snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
 		&hp_jack);
 
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 52074a2b0696..7a73380b3560 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -16,6 +16,7 @@
  * option) any later version.
  */
 
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/io.h>
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 7ab8e2c29216..f26a8bfb2357 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -176,7 +176,7 @@ static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c2412_iis_driver = {
 	.probe  = s3c2412_iis_dev_probe,
-	.remove = s3c2412_iis_dev_remove,
+	.remove = __devexit_p(s3c2412_iis_dev_remove),
 	.driver = {
 		.name = "s3c2412-iis",
 		.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 21c92e2e3007..c08117e658db 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -481,7 +481,7 @@ static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c24xx_iis_driver = {
 	.probe  = s3c24xx_iis_dev_probe,
-	.remove = s3c24xx_iis_dev_remove,
+	.remove = __devexit_p(s3c24xx_iis_dev_remove),
 	.driver = {
 		.name = "s3c24xx-iis",
 		.owner = THIS_MODULE,
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
index 349566f0686b..c8d525bf6122 100644
--- a/sound/soc/samsung/s3c24xx_simtec.c
+++ b/sound/soc/samsung/s3c24xx_simtec.c
@@ -300,7 +300,7 @@ static void detach_gpio_amp(struct s3c24xx_audio_simtec_pdata *pd)
 }
 
 #ifdef CONFIG_PM
-int simtec_audio_resume(struct device *dev)
+static int simtec_audio_resume(struct device *dev)
 {
 	simtec_call_startup(pdata);
 	return 0;
diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c
index ce6aef604179..6bc5a36af1d9 100644
--- a/sound/soc/samsung/s3c24xx_simtec_hermes.c
+++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c
@@ -65,18 +65,12 @@ static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-	snd_soc_dapm_new_controls(dapm, dapm_widgets,
-				  ARRAY_SIZE(dapm_widgets));
-
-	snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map));
-
 	snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
 	snd_soc_dapm_enable_pin(dapm, "Line In");
 	snd_soc_dapm_enable_pin(dapm, "Line Out");
 	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
 	simtec_audio_init(rtd);
-	snd_soc_dapm_sync(dapm);
 
 	return 0;
 }
@@ -96,6 +90,11 @@ static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
 	.name		= "Simtec-Hermes",
 	.dai_link	= &simtec_dai_aic33,
 	.num_links	= 1,
+
+	.dapm_widgets	= dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
+	.dapm_routes	= base_map,
+	.num_dapm_routes = ARRAY_SIZE(base_map),
 };
 
 static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
index a7ef7db54687..7bdda7674008 100644
--- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
@@ -54,18 +54,12 @@ static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-	snd_soc_dapm_new_controls(dapm, dapm_widgets,
-				  ARRAY_SIZE(dapm_widgets));
-
-	snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map));
-
 	snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
 	snd_soc_dapm_enable_pin(dapm, "Line In");
 	snd_soc_dapm_enable_pin(dapm, "Line Out");
 	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
 	simtec_audio_init(rtd);
-	snd_soc_dapm_sync(dapm);
 
 	return 0;
 }
@@ -85,6 +79,11 @@ static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
 	.name		= "Simtec",
 	.dai_link	= &simtec_dai_aic23,
 	.num_links	= 1,
+
+	.dapm_widgets	= dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
+	.dapm_routes	= base_map,
+	.num_dapm_routes = ARRAY_SIZE(base_map),
 };
 
 static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c
index bbd14768ecd3..6ac6bc2bcc4e 100644
--- a/sound/soc/samsung/smartq_wm8987.c
+++ b/sound/soc/samsung/smartq_wm8987.c
@@ -153,20 +153,6 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int err = 0;
 
-	/* Add SmartQ specific widgets */
-	snd_soc_dapm_new_controls(dapm, wm8987_dapm_widgets,
-				  ARRAY_SIZE(wm8987_dapm_widgets));
-
-	/* add SmartQ specific controls */
-	err = snd_soc_add_controls(codec, wm8987_smartq_controls,
-				   ARRAY_SIZE(wm8987_smartq_controls));
-
-	if (err < 0)
-		return err;
-
-	/* setup SmartQ specific audio path */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
 	/* set endpoints to not connected */
 	snd_soc_dapm_nc_pin(dapm, "LINPUT1");
 	snd_soc_dapm_nc_pin(dapm, "RINPUT1");
@@ -178,10 +164,6 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_enable_pin(dapm, "Internal Mic");
 	snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
 
-	err = snd_soc_dapm_sync(dapm);
-	if (err)
-		return err;
-
 	/* Headphone jack detection */
 	err = snd_soc_jack_new(codec, "Headphone Jack",
 			       SND_JACK_HEADPHONE, &smartq_jack);
@@ -217,6 +199,13 @@ static struct snd_soc_card snd_soc_smartq = {
 	.name = "SmartQ",
 	.dai_link = smartq_dai,
 	.num_links = ARRAY_SIZE(smartq_dai),
+
+	.dapm_widgets = wm8987_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8987_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+	.controls = wm8987_smartq_controls,
+	.num_controls = ARRAY_SIZE(wm8987_smartq_controls),
 };
 
 static struct platform_device *smartq_snd_device;
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index 20deecf3b243..8f92ffceb5ca 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -119,30 +119,24 @@ static struct snd_soc_ops smdk_ops = {
 };
 
 /* SMDK Playback widgets */
-static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
+static const struct snd_soc_dapm_widget smdk_wm8580_dapm_widgets[] = {
 	SND_SOC_DAPM_HP("Front", NULL),
 	SND_SOC_DAPM_HP("Center+Sub", NULL),
 	SND_SOC_DAPM_HP("Rear", NULL),
-};
 
-/* SMDK Capture widgets */
-static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = {
 	SND_SOC_DAPM_MIC("MicIn", NULL),
 	SND_SOC_DAPM_LINE("LineIn", NULL),
 };
 
 /* SMDK-PAIFTX connections */
-static const struct snd_soc_dapm_route audio_map_tx[] = {
+static const struct snd_soc_dapm_route smdk_wm8580_audio_map[] = {
 	/* MicIn feeds AINL */
 	{"AINL", NULL, "MicIn"},
 
 	/* LineIn feeds AINL/R */
 	{"AINL", NULL, "LineIn"},
 	{"AINR", NULL, "LineIn"},
-};
 
-/* SMDK-PAIFRX connections */
-static const struct snd_soc_dapm_route audio_map_rx[] = {
 	/* Front Left/Right are fed VOUT1L/R */
 	{"Front", NULL, "VOUT1L"},
 	{"Front", NULL, "VOUT1R"},
@@ -161,39 +155,11 @@ static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-	/* Add smdk specific Capture widgets */
-	snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_cpt,
-				  ARRAY_SIZE(wm8580_dapm_widgets_cpt));
-
-	/* Set up PAIFTX audio path */
-	snd_soc_dapm_add_routes(dapm, audio_map_tx, ARRAY_SIZE(audio_map_tx));
-
 	/* Enabling the microphone requires the fitting of a 0R
 	 * resistor to connect the line from the microphone jack.
 	 */
 	snd_soc_dapm_disable_pin(dapm, "MicIn");
 
-	/* signal a DAPM event */
-	snd_soc_dapm_sync(dapm);
-
-	return 0;
-}
-
-static int smdk_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	/* Add smdk specific Playback widgets */
-	snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_pbk,
-				  ARRAY_SIZE(wm8580_dapm_widgets_pbk));
-
-	/* Set up PAIFRX audio path */
-	snd_soc_dapm_add_routes(dapm, audio_map_rx, ARRAY_SIZE(audio_map_rx));
-
-	/* signal a DAPM event */
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
@@ -211,7 +177,6 @@ static struct snd_soc_dai_link smdk_dai[] = {
 		.codec_dai_name = "wm8580-hifi-playback",
 		.platform_name = "samsung-audio",
 		.codec_name = "wm8580.0-001b",
-		.init = smdk_wm8580_init_paifrx,
 		.ops = &smdk_ops,
 	},
 	[PRI_CAPTURE] = { /* Primary Capture i/f */
@@ -231,7 +196,6 @@ static struct snd_soc_dai_link smdk_dai[] = {
 		.codec_dai_name = "wm8580-hifi-playback",
 		.platform_name = "samsung-audio",
 		.codec_name = "wm8580.0-001b",
-		.init = smdk_wm8580_init_paifrx,
 		.ops = &smdk_ops,
 	},
 };
@@ -240,6 +204,11 @@ static struct snd_soc_card smdk = {
 	.name = "SMDK-I2S",
 	.dai_link = smdk_dai,
 	.num_links = 2,
+
+	.dapm_widgets = smdk_wm8580_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets),
+	.dapm_routes = smdk_wm8580_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(smdk_wm8580_audio_map),
 };
 
 static struct platform_device *smdk_snd_device;
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 45fbe2b3727f..f75e43997d5b 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -117,8 +117,6 @@ static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "IN1RP");
 	snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 28c491dacf7a..3122f3154bfa 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -340,7 +340,7 @@ static struct snd_soc_dai_ops spdif_dai_ops = {
 	.shutdown	= spdif_shutdown,
 };
 
-struct snd_soc_dai_driver samsung_spdif_dai = {
+static struct snd_soc_dai_driver samsung_spdif_dai = {
 	.name = "samsung-spdif",
 	.playback = {
 		.stream_name = "S/PDIF Playback",
@@ -475,7 +475,7 @@ static __devexit int spdif_remove(struct platform_device *pdev)
 
 static struct platform_driver samsung_spdif_driver = {
 	.probe	= spdif_probe,
-	.remove	= spdif_remove,
+	.remove	= __devexit_p(spdif_remove),
 	.driver	= {
 		.name	= "samsung-spdif",
 		.owner	= THIS_MODULE,
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/speyside_wm8962.c
index 3820a6b057dc..8a082044436e 100644
--- a/sound/soc/samsung/speyside_wm8962.c
+++ b/sound/soc/samsung/speyside_wm8962.c
@@ -16,6 +16,8 @@
 
 #include "../codecs/wm8962.h"
 
+static int sample_rate = 44100;
+
 static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
 					  struct snd_soc_dapm_context *dapm,
 					  enum snd_soc_bias_level level)
@@ -31,13 +33,13 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
 		if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
 			ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
 						  WM8962_FLL_MCLK, 32768,
-						  44100 * 512);
+						  sample_rate * 512);
 			if (ret < 0)
 				pr_err("Failed to start FLL: %d\n", ret);
 
 			ret = snd_soc_dai_set_sysclk(codec_dai,
 						     WM8962_SYSCLK_FLL,
-						     44100 * 512,
+						     sample_rate * 512,
 						     SND_SOC_CLOCK_IN);
 			if (ret < 0) {
 				pr_err("Failed to set SYSCLK: %d\n", ret);
@@ -92,22 +94,7 @@ static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
 static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream,
 			      struct snd_pcm_hw_params *params)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret;
-
-	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
-					 | SND_SOC_DAIFMT_NB_NF
-					 | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
-	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
-					 | SND_SOC_DAIFMT_NB_NF
-					 | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
+	sample_rate = params_rate(params);
 
 	return 0;
 }
@@ -124,12 +111,15 @@ static struct snd_soc_dai_link speyside_wm8962_dai[] = {
 		.codec_dai_name = "wm8962",
 		.platform_name = "samsung-audio",
 		.codec_name = "wm8962.1-001a",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+				| SND_SOC_DAIFMT_CBM_CFM,
 		.ops = &speyside_wm8962_ops,
 	},
 };
 
 static const struct snd_kcontrol_new controls[] = {
 	SOC_DAPM_PIN_SWITCH("Main Speaker"),
+	SOC_DAPM_PIN_SWITCH("DMIC"),
 };
 
 static struct snd_soc_dapm_widget widgets[] = {
@@ -137,6 +127,7 @@ static struct snd_soc_dapm_widget widgets[] = {
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
 
 	SND_SOC_DAPM_MIC("DMIC", NULL),
+	SND_SOC_DAPM_MIC("AMIC", NULL),
 
 	SND_SOC_DAPM_SPK("Main Speaker", NULL),
 };
@@ -148,12 +139,16 @@ static struct snd_soc_dapm_route audio_paths[] = {
 	{ "Main Speaker", NULL, "SPKOUTL" },
 	{ "Main Speaker", NULL, "SPKOUTR" },
 
-	{ "MICBIAS", NULL, "Headset Mic" },
-	{ "IN4L", NULL, "MICBIAS" },
-	{ "IN4R", NULL, "MICBIAS" },
+	{ "Headset Mic", NULL, "MICBIAS" },
+	{ "IN4L", NULL, "Headset Mic" },
+	{ "IN4R", NULL, "Headset Mic" },
+
+	{ "AMIC", NULL, "MICBIAS" },
+	{ "IN1L", NULL, "AMIC" },
+	{ "IN1R", NULL, "AMIC" },
 
-	{ "MICBIAS", NULL, "DMIC" },
-	{ "DMICDAT", NULL, "MICBIAS" },
+	{ "DMIC", NULL, "MICBIAS" },
+	{ "DMICDAT", NULL, "DMIC" },
 };
 
 static struct snd_soc_jack speyside_wm8962_headset;
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 1493ebf4d943..a32fd16ad668 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -210,7 +210,7 @@ struct fsi_master {
  *		basic read write function
  */
 
-static void __fsi_reg_write(u32 reg, u32 data)
+static void __fsi_reg_write(u32 __iomem *reg, u32 data)
 {
 	/* valid data area is 24bit */
 	data &= 0x00ffffff;
@@ -218,12 +218,12 @@ static void __fsi_reg_write(u32 reg, u32 data)
 	__raw_writel(data, reg);
 }
 
-static u32 __fsi_reg_read(u32 reg)
+static u32 __fsi_reg_read(u32 __iomem *reg)
 {
 	return __raw_readl(reg);
 }
 
-static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
+static void __fsi_reg_mask_set(u32 __iomem *reg, u32 mask, u32 data)
 {
 	u32 val = __fsi_reg_read(reg);
 
@@ -250,7 +250,7 @@ static u32 _fsi_master_read(struct fsi_master *master, u32 reg)
 	unsigned long flags;
 
 	spin_lock_irqsave(&master->lock, flags);
-	ret = __fsi_reg_read((u32)(master->base + reg));
+	ret = __fsi_reg_read(master->base + reg);
 	spin_unlock_irqrestore(&master->lock, flags);
 
 	return ret;
@@ -264,7 +264,7 @@ static void _fsi_master_mask_set(struct fsi_master *master,
 	unsigned long flags;
 
 	spin_lock_irqsave(&master->lock, flags);
-	__fsi_reg_mask_set((u32)(master->base + reg), mask, data);
+	__fsi_reg_mask_set(master->base + reg, mask, data);
 	spin_unlock_irqrestore(&master->lock, flags);
 }
 
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c
index 917d3ceadc9d..c62ae689c4a1 100644
--- a/sound/soc/sh/sh7760-ac97.c
+++ b/sound/soc/sh/sh7760-ac97.c
@@ -20,12 +20,6 @@
 extern struct snd_soc_dai_driver sh4_hac_dai[2];
 extern struct snd_soc_platform_driver sh7760_soc_platform;
 
-static int machine_init(struct snd_soc_pcm_runtime *rtd)
-{
-	snd_soc_dapm_sync(&rtd->codec->dapm);
-	return 0;
-}
-
 static struct snd_soc_dai_link sh7760_ac97_dai = {
 	.name = "AC97",
 	.stream_name = "AC97 HiFi",
@@ -33,7 +27,6 @@ static struct snd_soc_dai_link sh7760_ac97_dai = {
 	.codec_dai_name = "ac97-hifi",
 	.platform_name = "sh7760-pcm-audio",
 	.codec_name = "ac97-codec",
-	.init = machine_init,
 	.ops = NULL,
 };
 
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index 05192d97b377..e0c621c0553b 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -342,7 +342,7 @@ static struct snd_soc_dai_ops ssi_dai_ops = {
 	.set_fmt	= ssi_set_fmt,
 };
 
-struct snd_soc_dai_driver sh4_ssi_dai[] = {
+static struct snd_soc_dai_driver sh4_ssi_dai[] = {
 {
 	.name			= "ssi-dai.0",
 	.playback = {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index bd20154e8b34..a5d3685a5d38 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1055,6 +1055,9 @@ static int soc_post_component_init(struct snd_soc_card *card,
 	}
 	rtd->card = card;
 
+	/* Make sure all DAPM widgets are instantiated */
+	snd_soc_dapm_new_widgets(&codec->dapm);
+
 	/* machine controls, routes and widgets are not prefixed */
 	temp = codec->name_prefix;
 	codec->name_prefix = NULL;
@@ -1070,9 +1073,6 @@ static int soc_post_component_init(struct snd_soc_card *card,
 	}
 	codec->name_prefix = temp;
 
-	/* Make sure all DAPM widgets are instantiated */
-	snd_soc_dapm_new_widgets(&codec->dapm);
-
 	/* register the rtd device */
 	rtd->codec = codec;
 	rtd->dev.parent = card->dev;
@@ -1317,6 +1317,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 	struct snd_soc_codec *codec;
 	struct snd_soc_codec_conf *codec_conf;
 	enum snd_soc_compress_type compress_type;
+	struct snd_soc_dai_link *dai_link;
 	int ret, i, order;
 
 	mutex_lock(&card->mutex);
@@ -1429,6 +1430,28 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 		snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
 					card->num_dapm_routes);
 
+	snd_soc_dapm_new_widgets(&card->dapm);
+
+	for (i = 0; i < card->num_links; i++) {
+		dai_link = &card->dai_link[i];
+
+		if (dai_link->dai_fmt) {
+			ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
+						  dai_link->dai_fmt);
+			if (ret != 0)
+				dev_warn(card->rtd[i].codec_dai->dev,
+					 "Failed to set DAI format: %d\n",
+					 ret);
+
+			ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
+						  dai_link->dai_fmt);
+			if (ret != 0)
+				dev_warn(card->rtd[i].cpu_dai->dev,
+					 "Failed to set DAI format: %d\n",
+					 ret);
+		}
+	}
+
 	snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
 		 "%s", card->name);
 	snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
@@ -1457,6 +1480,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 		}
 	}
 
+	snd_soc_dapm_new_widgets(&card->dapm);
+
 	ret = snd_card_register(card->snd_card);
 	if (ret < 0) {
 		printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
@@ -1477,6 +1502,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 #endif
 
 	card->instantiated = 1;
+	snd_soc_dapm_sync(&card->dapm);
 	mutex_unlock(&card->mutex);
 	return;
 
@@ -2227,7 +2253,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
  * @kcontrol: mixer control
  * @uinfo: control element information
  *
- * Callback to provide information about a single mixer control.
+ * Callback to provide information about a single mixer control, or a double
+ * mixer control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2237,8 +2264,6 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 	int platform_max;
-	unsigned int shift = mc->shift;
-	unsigned int rshift = mc->rshift;
 
 	if (!mc->platform_max)
 		mc->platform_max = mc->max;
@@ -2249,7 +2274,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
 	else
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 
-	uinfo->count = shift == rshift ? 1 : 2;
+	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = platform_max;
 	return 0;
@@ -2261,7 +2286,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
  * @kcontrol: mixer control
  * @ucontrol: control element information
  *
- * Callback to get the value of a single mixer control.
+ * Callback to get the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2272,6 +2298,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	unsigned int reg = mc->reg;
+	unsigned int reg2 = mc->rreg;
 	unsigned int shift = mc->shift;
 	unsigned int rshift = mc->rshift;
 	int max = mc->max;
@@ -2280,13 +2307,18 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
 
 	ucontrol->value.integer.value[0] =
 		(snd_soc_read(codec, reg) >> shift) & mask;
-	if (shift != rshift)
-		ucontrol->value.integer.value[1] =
-			(snd_soc_read(codec, reg) >> rshift) & mask;
-	if (invert) {
+	if (invert)
 		ucontrol->value.integer.value[0] =
 			max - ucontrol->value.integer.value[0];
-		if (shift != rshift)
+
+	if (snd_soc_volsw_is_stereo(mc)) {
+		if (reg == reg2)
+			ucontrol->value.integer.value[1] =
+				(snd_soc_read(codec, reg) >> rshift) & mask;
+		else
+			ucontrol->value.integer.value[1] =
+				(snd_soc_read(codec, reg2) >> shift) & mask;
+		if (invert)
 			ucontrol->value.integer.value[1] =
 				max - ucontrol->value.integer.value[1];
 	}
@@ -2300,7 +2332,8 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
  * @kcontrol: mixer control
  * @ucontrol: control element information
  *
- * Callback to set the value of a single mixer control.
+ * Callback to set the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2311,143 +2344,44 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	unsigned int reg = mc->reg;
+	unsigned int reg2 = mc->rreg;
 	unsigned int shift = mc->shift;
 	unsigned int rshift = mc->rshift;
 	int max = mc->max;
 	unsigned int mask = (1 << fls(max)) - 1;
 	unsigned int invert = mc->invert;
-	unsigned int val, val2, val_mask;
+	int err;
+	bool type_2r = 0;
+	unsigned int val2 = 0;
+	unsigned int val, val_mask;
 
 	val = (ucontrol->value.integer.value[0] & mask);
 	if (invert)
 		val = max - val;
 	val_mask = mask << shift;
 	val = val << shift;
-	if (shift != rshift) {
+	if (snd_soc_volsw_is_stereo(mc)) {
 		val2 = (ucontrol->value.integer.value[1] & mask);
 		if (invert)
 			val2 = max - val2;
-		val_mask |= mask << rshift;
-		val |= val2 << rshift;
-	}
-	return snd_soc_update_bits_locked(codec, reg, val_mask, val);
-}
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
-
-/**
- * snd_soc_info_volsw_2r - double mixer info callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Callback to provide information about a double mixer control that
- * spans 2 codec registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_info *uinfo)
-{
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	int platform_max;
-
-	if (!mc->platform_max)
-		mc->platform_max = mc->max;
-	platform_max = mc->platform_max;
-
-	if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
-		uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	else
-		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-
-	uinfo->count = 2;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = platform_max;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
-
-/**
- * snd_soc_get_volsw_2r - double mixer get callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to get the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	unsigned int reg = mc->reg;
-	unsigned int reg2 = mc->rreg;
-	unsigned int shift = mc->shift;
-	int max = mc->max;
-	unsigned int mask = (1 << fls(max)) - 1;
-	unsigned int invert = mc->invert;
-
-	ucontrol->value.integer.value[0] =
-		(snd_soc_read(codec, reg) >> shift) & mask;
-	ucontrol->value.integer.value[1] =
-		(snd_soc_read(codec, reg2) >> shift) & mask;
-	if (invert) {
-		ucontrol->value.integer.value[0] =
-			max - ucontrol->value.integer.value[0];
-		ucontrol->value.integer.value[1] =
-			max - ucontrol->value.integer.value[1];
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
-
-/**
- * snd_soc_put_volsw_2r - double mixer set callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to set the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	unsigned int reg = mc->reg;
-	unsigned int reg2 = mc->rreg;
-	unsigned int shift = mc->shift;
-	int max = mc->max;
-	unsigned int mask = (1 << fls(max)) - 1;
-	unsigned int invert = mc->invert;
-	int err;
-	unsigned int val, val2, val_mask;
-
-	val_mask = mask << shift;
-	val = (ucontrol->value.integer.value[0] & mask);
-	val2 = (ucontrol->value.integer.value[1] & mask);
-
-	if (invert) {
-		val = max - val;
-		val2 = max - val2;
+		if (reg == reg2) {
+			val_mask |= mask << rshift;
+			val |= val2 << rshift;
+		} else {
+			val2 = val2 << shift;
+			type_2r = 1;
+		}
 	}
-
-	val = val << shift;
-	val2 = val2 << shift;
-
 	err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
 	if (err < 0)
 		return err;
 
-	err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
+	if (type_2r)
+		err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
+
 	return err;
 }
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
+EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
 
 /**
  * snd_soc_info_volsw_s8 - signed mixer info callback
@@ -2895,6 +2829,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
 		card->rtd[i].dai_link = &card->dai_link[i];
 
 	INIT_LIST_HEAD(&card->list);
+	INIT_LIST_HEAD(&card->dapm_dirty);
 	card->instantiated = 0;
 	mutex_init(&card->mutex);
 
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 4a440b52dd7a..f42e8b9fb17d 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -48,6 +48,8 @@
 
 #include <trace/events/asoc.h>
 
+#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
+
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
 	[snd_soc_dapm_pre] = 0,
@@ -117,6 +119,21 @@ static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
 	kfree(buf);
 }
 
+static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
+{
+	return !list_empty(&w->dirty);
+}
+
+void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
+{
+	if (!dapm_dirty_widget(w)) {
+		dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
+			 w->name, reason);
+		list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
+	}
+}
+EXPORT_SYMBOL_GPL(dapm_mark_dirty);
+
 /* create a new dapm widget */
 static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
 	const struct snd_soc_dapm_widget *_widget)
@@ -316,7 +333,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 		}
 	}
 	break;
-	/* does not effect routing - always connected */
+	/* does not affect routing - always connected */
 	case snd_soc_dapm_pga:
 	case snd_soc_dapm_out_drv:
 	case snd_soc_dapm_output:
@@ -328,13 +345,13 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 	case snd_soc_dapm_supply:
 	case snd_soc_dapm_aif_in:
 	case snd_soc_dapm_aif_out:
-		p->connect = 1;
-	break;
-	/* does effect routing - dynamically connected */
 	case snd_soc_dapm_hp:
 	case snd_soc_dapm_mic:
 	case snd_soc_dapm_spk:
 	case snd_soc_dapm_line:
+		p->connect = 1;
+	break;
+	/* does affect routing - dynamically connected */
 	case snd_soc_dapm_pre:
 	case snd_soc_dapm_post:
 		p->connect = 0;
@@ -649,30 +666,45 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
 	struct snd_soc_dapm_path *path;
 	int con = 0;
 
+	if (widget->outputs >= 0)
+		return widget->outputs;
+
+	DAPM_UPDATE_STAT(widget, path_checks);
+
 	if (widget->id == snd_soc_dapm_supply)
 		return 0;
 
 	switch (widget->id) {
 	case snd_soc_dapm_adc:
 	case snd_soc_dapm_aif_out:
-		if (widget->active)
-			return snd_soc_dapm_suspend_check(widget);
+		if (widget->active) {
+			widget->outputs = snd_soc_dapm_suspend_check(widget);
+			return widget->outputs;
+		}
 	default:
 		break;
 	}
 
 	if (widget->connected) {
 		/* connected pin ? */
-		if (widget->id == snd_soc_dapm_output && !widget->ext)
-			return snd_soc_dapm_suspend_check(widget);
+		if (widget->id == snd_soc_dapm_output && !widget->ext) {
+			widget->outputs = snd_soc_dapm_suspend_check(widget);
+			return widget->outputs;
+		}
 
 		/* connected jack or spk ? */
-		if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
-		    (widget->id == snd_soc_dapm_line && !list_empty(&widget->sources)))
-			return snd_soc_dapm_suspend_check(widget);
+		if (widget->id == snd_soc_dapm_hp ||
+		    widget->id == snd_soc_dapm_spk ||
+		    (widget->id == snd_soc_dapm_line &&
+		     !list_empty(&widget->sources))) {
+			widget->outputs = snd_soc_dapm_suspend_check(widget);
+			return widget->outputs;
+		}
 	}
 
 	list_for_each_entry(path, &widget->sinks, list_source) {
+		DAPM_UPDATE_STAT(widget, neighbour_checks);
+
 		if (path->weak)
 			continue;
 
@@ -685,6 +717,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
 		}
 	}
 
+	widget->outputs = con;
+
 	return con;
 }
 
@@ -697,6 +731,11 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
 	struct snd_soc_dapm_path *path;
 	int con = 0;
 
+	if (widget->inputs >= 0)
+		return widget->inputs;
+
+	DAPM_UPDATE_STAT(widget, path_checks);
+
 	if (widget->id == snd_soc_dapm_supply)
 		return 0;
 
@@ -704,28 +743,40 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
 	switch (widget->id) {
 	case snd_soc_dapm_dac:
 	case snd_soc_dapm_aif_in:
-		if (widget->active)
-			return snd_soc_dapm_suspend_check(widget);
+		if (widget->active) {
+			widget->inputs = snd_soc_dapm_suspend_check(widget);
+			return widget->inputs;
+		}
 	default:
 		break;
 	}
 
 	if (widget->connected) {
 		/* connected pin ? */
-		if (widget->id == snd_soc_dapm_input && !widget->ext)
-			return snd_soc_dapm_suspend_check(widget);
+		if (widget->id == snd_soc_dapm_input && !widget->ext) {
+			widget->inputs = snd_soc_dapm_suspend_check(widget);
+			return widget->inputs;
+		}
 
 		/* connected VMID/Bias for lower pops */
-		if (widget->id == snd_soc_dapm_vmid)
-			return snd_soc_dapm_suspend_check(widget);
+		if (widget->id == snd_soc_dapm_vmid) {
+			widget->inputs = snd_soc_dapm_suspend_check(widget);
+			return widget->inputs;
+		}
 
 		/* connected jack ? */
 		if (widget->id == snd_soc_dapm_mic ||
-		    (widget->id == snd_soc_dapm_line && !list_empty(&widget->sinks)))
-			return snd_soc_dapm_suspend_check(widget);
+		    (widget->id == snd_soc_dapm_line &&
+		     !list_empty(&widget->sinks))) {
+			widget->inputs = snd_soc_dapm_suspend_check(widget);
+			return widget->inputs;
+		}
+
 	}
 
 	list_for_each_entry(path, &widget->sources, list_sink) {
+		DAPM_UPDATE_STAT(widget, neighbour_checks);
+
 		if (path->weak)
 			continue;
 
@@ -738,6 +789,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
 		}
 	}
 
+	widget->inputs = con;
+
 	return con;
 }
 
@@ -761,12 +814,29 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
 }
 EXPORT_SYMBOL_GPL(dapm_reg_event);
 
+static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
+{
+	if (w->power_checked)
+		return w->new_power;
+
+	if (w->force)
+		w->new_power = 1;
+	else
+		w->new_power = w->power_check(w);
+
+	w->power_checked = true;
+
+	return w->new_power;
+}
+
 /* Generic check to see if a widget should be powered.
  */
 static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
 {
 	int in, out;
 
+	DAPM_UPDATE_STAT(w, power_checks);
+
 	in = is_connected_input_ep(w);
 	dapm_clear_walk(w->dapm);
 	out = is_connected_output_ep(w);
@@ -779,6 +849,8 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
 {
 	int in;
 
+	DAPM_UPDATE_STAT(w, power_checks);
+
 	if (w->active) {
 		in = is_connected_input_ep(w);
 		dapm_clear_walk(w->dapm);
@@ -793,6 +865,8 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
 {
 	int out;
 
+	DAPM_UPDATE_STAT(w, power_checks);
+
 	if (w->active) {
 		out = is_connected_output_ep(w);
 		dapm_clear_walk(w->dapm);
@@ -806,10 +880,13 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
 static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
 {
 	struct snd_soc_dapm_path *path;
-	int power = 0;
+
+	DAPM_UPDATE_STAT(w, power_checks);
 
 	/* Check if one of our outputs is connected */
 	list_for_each_entry(path, &w->sinks, list_source) {
+		DAPM_UPDATE_STAT(w, neighbour_checks);
+
 		if (path->weak)
 			continue;
 
@@ -820,21 +897,18 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
 		if (!path->sink)
 			continue;
 
-		if (path->sink->force) {
-			power = 1;
-			break;
-		}
-
-		if (path->sink->power_check &&
-		    path->sink->power_check(path->sink)) {
-			power = 1;
-			break;
-		}
+		if (dapm_widget_power_check(path->sink))
+			return 1;
 	}
 
 	dapm_clear_walk(w->dapm);
 
-	return power;
+	return 0;
+}
+
+static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)
+{
+	return 1;
 }
 
 static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
@@ -1177,6 +1251,85 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
 	}
 }
 
+static void dapm_widget_set_peer_power(struct snd_soc_dapm_widget *peer,
+				       bool power, bool connect)
+{
+	/* If a connection is being made or broken then that update
+	 * will have marked the peer dirty, otherwise the widgets are
+	 * not connected and this update has no impact. */
+	if (!connect)
+		return;
+
+	/* If the peer is already in the state we're moving to then we
+	 * won't have an impact on it. */
+	if (power != peer->power)
+		dapm_mark_dirty(peer, "peer state change");
+}
+
+static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
+				  struct list_head *up_list,
+				  struct list_head *down_list)
+{
+	struct snd_soc_dapm_path *path;
+
+	if (w->power == power)
+		return;
+
+	trace_snd_soc_dapm_widget_power(w, power);
+
+	/* If we changed our power state perhaps our neigbours changed
+	 * also.
+	 */
+	list_for_each_entry(path, &w->sources, list_sink) {
+		if (path->source) {
+			dapm_widget_set_peer_power(path->source, power,
+						   path->connect);
+		}
+	}
+	switch (w->id) {
+	case snd_soc_dapm_supply:
+		/* Supplies can't affect their outputs, only their inputs */
+		break;
+	default:
+		list_for_each_entry(path, &w->sinks, list_source) {
+			if (path->sink) {
+				dapm_widget_set_peer_power(path->sink, power,
+							   path->connect);
+			}
+		}
+		break;
+	}
+
+	if (power)
+		dapm_seq_insert(w, up_list, true);
+	else
+		dapm_seq_insert(w, down_list, false);
+
+	w->power = power;
+}
+
+static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
+				  struct list_head *up_list,
+				  struct list_head *down_list)
+{
+	int power;
+
+	switch (w->id) {
+	case snd_soc_dapm_pre:
+		dapm_seq_insert(w, down_list, false);
+		break;
+	case snd_soc_dapm_post:
+		dapm_seq_insert(w, up_list, true);
+		break;
+
+	default:
+		power = dapm_widget_power_check(w);
+
+		dapm_widget_set_power(w, power, up_list, down_list);
+		break;
+	}
+}
+
 /*
  * Scan each dapm widget for complete audio path.
  * A complete path is a route that has valid endpoints i.e.:-
@@ -1195,7 +1348,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 	LIST_HEAD(down_list);
 	LIST_HEAD(async_domain);
 	enum snd_soc_bias_level bias;
-	int power;
 
 	trace_snd_soc_dapm_start(card);
 
@@ -1208,61 +1360,47 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 		}
 	}
 
-	/* Check which widgets we need to power and store them in
-	 * lists indicating if they should be powered up or down.
-	 */
+	memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
+
 	list_for_each_entry(w, &card->widgets, list) {
-		switch (w->id) {
-		case snd_soc_dapm_pre:
-			dapm_seq_insert(w, &down_list, false);
-			break;
-		case snd_soc_dapm_post:
-			dapm_seq_insert(w, &up_list, true);
-			break;
+		w->power_checked = false;
+		w->inputs = -1;
+		w->outputs = -1;
+	}
 
-		default:
-			if (!w->power_check)
-				continue;
+	/* Check which widgets we need to power and store them in
+	 * lists indicating if they should be powered up or down.  We
+	 * only check widgets that have been flagged as dirty but note
+	 * that new widgets may be added to the dirty list while we
+	 * iterate.
+	 */
+	list_for_each_entry(w, &card->dapm_dirty, dirty) {
+		dapm_power_one_widget(w, &up_list, &down_list);
+	}
 
-			if (!w->force)
-				power = w->power_check(w);
-			else
-				power = 1;
+	list_for_each_entry(w, &card->widgets, list) {
+		list_del_init(&w->dirty);
 
-			if (power) {
-				d = w->dapm;
+		if (w->power) {
+			d = w->dapm;
 
-				/* Supplies and micbiases only bring
-				 * the context up to STANDBY as unless
-				 * something else is active and
-				 * passing audio they generally don't
-				 * require full power.
-				 */
-				switch (w->id) {
-				case snd_soc_dapm_supply:
-				case snd_soc_dapm_micbias:
-					if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
-						d->target_bias_level = SND_SOC_BIAS_STANDBY;
-					break;
-				default:
-					d->target_bias_level = SND_SOC_BIAS_ON;
-					break;
-				}
+			/* Supplies and micbiases only bring the
+			 * context up to STANDBY as unless something
+			 * else is active and passing audio they
+			 * generally don't require full power.
+			 */
+			switch (w->id) {
+			case snd_soc_dapm_supply:
+			case snd_soc_dapm_micbias:
+				if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
+					d->target_bias_level = SND_SOC_BIAS_STANDBY;
+				break;
+			default:
+				d->target_bias_level = SND_SOC_BIAS_ON;
+				break;
 			}
-
-			if (w->power == power)
-				continue;
-
-			trace_snd_soc_dapm_widget_power(w, power);
-
-			if (power)
-				dapm_seq_insert(w, &up_list, true);
-			else
-				dapm_seq_insert(w, &down_list, false);
-
-			w->power = power;
-			break;
 		}
+
 	}
 
 	/* If there are no DAPM widgets then try to figure out power from the
@@ -1291,14 +1429,18 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 		}
 	}
 
-	/* Force all contexts in the card to the same bias state */
+	/* Force all contexts in the card to the same bias state if
+	 * they're not ground referenced.
+	 */
 	bias = SND_SOC_BIAS_OFF;
 	list_for_each_entry(d, &card->dapm_list, list)
 		if (d->target_bias_level > bias)
 			bias = d->target_bias_level;
 	list_for_each_entry(d, &card->dapm_list, list)
-		d->target_bias_level = bias;
+		if (!d->idle_bias_off)
+			d->target_bias_level = bias;
 
+	trace_snd_soc_dapm_walk_done(card);
 
 	/* Run all the bias changes in parallel */
 	list_for_each_entry(d, &dapm->card->dapm_list, list)
@@ -1529,14 +1671,21 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 
 		found = 1;
 		/* we now need to match the string in the enum to the path */
-		if (!(strcmp(path->name, e->texts[mux])))
+		if (!(strcmp(path->name, e->texts[mux]))) {
 			path->connect = 1; /* new connection */
-		else
+			dapm_mark_dirty(path->source, "mux connection");
+		} else {
+			if (path->connect)
+				dapm_mark_dirty(path->source,
+						"mux disconnection");
 			path->connect = 0; /* old connection must be powered down */
+		}
 	}
 
-	if (found)
+	if (found) {
+		dapm_mark_dirty(widget, "mux change");
 		dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
+	}
 
 	return 0;
 }
@@ -1561,10 +1710,13 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
 		/* found, now check type */
 		found = 1;
 		path->connect = connect;
+		dapm_mark_dirty(path->source, "mixer connection");
 	}
 
-	if (found)
+	if (found) {
+		dapm_mark_dirty(widget, "mixer update");
 		dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
+	}
 
 	return 0;
 }
@@ -1708,6 +1860,7 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
 	w->connected = status;
 	if (status == 0)
 		w->force = 0;
+	dapm_mark_dirty(w, "pin configuration");
 
 	return 0;
 }
@@ -1723,6 +1876,13 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
  */
 int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
 {
+	/*
+	 * Suppress early reports (eg, jacks syncing their state) to avoid
+	 * silly DAPM runs during card startup.
+	 */
+	if (!dapm->card || !dapm->card->instantiated)
+		return 0;
+
 	return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
@@ -2008,42 +2168,18 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
 		case snd_soc_dapm_switch:
 		case snd_soc_dapm_mixer:
 		case snd_soc_dapm_mixer_named_ctl:
-			w->power_check = dapm_generic_check_power;
 			dapm_new_mixer(w);
 			break;
 		case snd_soc_dapm_mux:
 		case snd_soc_dapm_virt_mux:
 		case snd_soc_dapm_value_mux:
-			w->power_check = dapm_generic_check_power;
 			dapm_new_mux(w);
 			break;
-		case snd_soc_dapm_adc:
-		case snd_soc_dapm_aif_out:
-			w->power_check = dapm_adc_check_power;
-			break;
-		case snd_soc_dapm_dac:
-		case snd_soc_dapm_aif_in:
-			w->power_check = dapm_dac_check_power;
-			break;
 		case snd_soc_dapm_pga:
 		case snd_soc_dapm_out_drv:
-			w->power_check = dapm_generic_check_power;
 			dapm_new_pga(w);
 			break;
-		case snd_soc_dapm_input:
-		case snd_soc_dapm_output:
-		case snd_soc_dapm_micbias:
-		case snd_soc_dapm_spk:
-		case snd_soc_dapm_hp:
-		case snd_soc_dapm_mic:
-		case snd_soc_dapm_line:
-			w->power_check = dapm_generic_check_power;
-			break;
-		case snd_soc_dapm_supply:
-			w->power_check = dapm_supply_check_power;
-		case snd_soc_dapm_vmid:
-		case snd_soc_dapm_pre:
-		case snd_soc_dapm_post:
+		default:
 			break;
 		}
 
@@ -2060,6 +2196,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
 
 		w->new = 1;
 
+		dapm_mark_dirty(w, "new widget");
 		dapm_debugfs_add_widget(w);
 	}
 
@@ -2534,6 +2671,44 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 	else
 		snprintf(w->name, name_len, "%s", widget->name);
 
+	switch (w->id) {
+	case snd_soc_dapm_switch:
+	case snd_soc_dapm_mixer:
+	case snd_soc_dapm_mixer_named_ctl:
+		w->power_check = dapm_generic_check_power;
+		break;
+	case snd_soc_dapm_mux:
+	case snd_soc_dapm_virt_mux:
+	case snd_soc_dapm_value_mux:
+		w->power_check = dapm_generic_check_power;
+		break;
+	case snd_soc_dapm_adc:
+	case snd_soc_dapm_aif_out:
+		w->power_check = dapm_adc_check_power;
+		break;
+	case snd_soc_dapm_dac:
+	case snd_soc_dapm_aif_in:
+		w->power_check = dapm_dac_check_power;
+		break;
+	case snd_soc_dapm_pga:
+	case snd_soc_dapm_out_drv:
+	case snd_soc_dapm_input:
+	case snd_soc_dapm_output:
+	case snd_soc_dapm_micbias:
+	case snd_soc_dapm_spk:
+	case snd_soc_dapm_hp:
+	case snd_soc_dapm_mic:
+	case snd_soc_dapm_line:
+		w->power_check = dapm_generic_check_power;
+		break;
+	case snd_soc_dapm_supply:
+		w->power_check = dapm_supply_check_power;
+		break;
+	default:
+		w->power_check = dapm_always_on_check_power;
+		break;
+	}
+
 	dapm->n_widgets++;
 	w->dapm = dapm;
 	w->codec = dapm->codec;
@@ -2541,6 +2716,7 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 	INIT_LIST_HEAD(&w->sources);
 	INIT_LIST_HEAD(&w->sinks);
 	INIT_LIST_HEAD(&w->list);
+	INIT_LIST_HEAD(&w->dirty);
 	list_add(&w->list, &dapm->card->widgets);
 
 	/* machine layer set ups unconnected pins and insertions */
@@ -2591,6 +2767,7 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
 		dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
 			w->name, w->sname, stream, event);
 		if (strstr(w->sname, stream)) {
+			dapm_mark_dirty(w, "stream event");
 			switch(event) {
 			case SND_SOC_DAPM_STREAM_START:
 				w->active = 1;
@@ -2680,6 +2857,7 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 	dev_dbg(w->dapm->dev, "dapm: force enable pin %s\n", pin);
 	w->connected = 1;
 	w->force = 1;
+	dapm_mark_dirty(w, "force enable");
 
 	return 0;
 }
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 66fcccd79efe..dd89933e2c72 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -55,7 +55,7 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
 		if (ret == 0)
 			return val;
 		else
-			return ret;
+			return -1;
 	}
 
 	ret = snd_soc_cache_read(codec, reg, &val);
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index fa31d9c2abd8..52db96636290 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -188,6 +188,8 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
 		list_add(&(pins[i].list), &jack->pins);
 	}
 
+	snd_soc_dapm_new_widgets(&jack->codec->card->dapm);
+
 	/* Update to reflect the last reported status; canned jack
 	 * implementations are likely to set their state before the
 	 * card has an opportunity to associate pins.
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 1aee9fcdf650..ee15337353fa 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -27,15 +27,13 @@
 #include <sound/soc.h>
 #include <sound/initval.h>
 
-static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
+static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
+					struct snd_soc_dai *soc_dai)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	int ret;
 
-	if (!codec_dai->driver->symmetric_rates &&
-	    !cpu_dai->driver->symmetric_rates &&
+	if (!soc_dai->driver->symmetric_rates &&
 	    !rtd->dai_link->symmetric_rates)
 		return 0;
 
@@ -43,19 +41,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
 	 * the second can need to get its constraints before the first has
 	 * picked a rate.  Complain and allow the application to carry on.
 	 */
-	if (!rtd->rate) {
-		dev_warn(&rtd->dev,
+	if (!soc_dai->rate) {
+		dev_warn(soc_dai->dev,
 			 "Not enforcing symmetric_rates due to race\n");
 		return 0;
 	}
 
-	dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
+	dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
 
 	ret = snd_pcm_hw_constraint_minmax(substream->runtime,
 					   SNDRV_PCM_HW_PARAM_RATE,
-					   rtd->rate, rtd->rate);
+					   soc_dai->rate, soc_dai->rate);
 	if (ret < 0) {
-		dev_err(&rtd->dev,
+		dev_err(soc_dai->dev,
 			"Unable to apply rate symmetry constraint: %d\n", ret);
 		return ret;
 	}
@@ -185,8 +183,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	}
 
 	/* Symmetry only applies if we've already got an active stream. */
-	if (cpu_dai->active || codec_dai->active) {
-		ret = soc_pcm_apply_symmetry(substream);
+	if (cpu_dai->active) {
+		ret = soc_pcm_apply_symmetry(substream, cpu_dai);
+		if (ret != 0)
+			goto config_err;
+	}
+
+	if (codec_dai->active) {
+		ret = soc_pcm_apply_symmetry(substream, codec_dai);
 		if (ret != 0)
 			goto config_err;
 	}
@@ -288,8 +292,12 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 	codec_dai->active--;
 	codec->active--;
 
-	if (!cpu_dai->active && !codec_dai->active)
-		rtd->rate = 0;
+	/* clear the corresponding DAIs rate when inactive */
+	if (!cpu_dai->active)
+		cpu_dai->rate = 0;
+
+	if (!codec_dai->active)
+		codec_dai->rate = 0;
 
 	/* Muting the DAC suppresses artifacts caused during digital
 	 * shutdown, for example from stopping clocks.
@@ -311,10 +319,17 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 	cpu_dai->runtime = NULL;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		/* start delayed pop wq here for playback streams */
-		codec_dai->pop_wait = 1;
-		schedule_delayed_work(&rtd->delayed_work,
-			msecs_to_jiffies(rtd->pmdown_time));
+		if (unlikely(codec->ignore_pmdown_time)) {
+			/* powered down playback stream now */
+			snd_soc_dapm_stream_event(rtd,
+				codec_dai->driver->playback.stream_name,
+				SND_SOC_DAPM_STREAM_STOP);
+		} else {
+			/* start delayed pop wq here for playback streams */
+			codec_dai->pop_wait = 1;
+			schedule_delayed_work(&rtd->delayed_work,
+				msecs_to_jiffies(rtd->pmdown_time));
+		}
 	} else {
 		/* capture streams can be powered down now */
 		snd_soc_dapm_stream_event(rtd,
@@ -447,7 +462,9 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 		}
 	}
 
-	rtd->rate = params_rate(params);
+	/* store the rate for each DAIs */
+	cpu_dai->rate = params_rate(params);
+	codec_dai->rate = params_rate(params);
 
 out:
 	mutex_unlock(&rtd->pcm_mutex);
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c
index 9f24ef73f2cb..3b55a44146af 100644
--- a/sound/soc/tegra/tegra_das.c
+++ b/sound/soc/tegra/tegra_das.c
@@ -212,7 +212,7 @@ err_release:
 	release_mem_region(res->start, resource_size(res));
 err_free:
 	kfree(das);
-	das = 0;
+	das = NULL;
 exit:
 	return ret;
 }
@@ -234,7 +234,7 @@ static int __devexit tegra_das_remove(struct platform_device *pdev)
 	release_mem_region(res->start, resource_size(res));
 
 	kfree(das);
-	das = 0;
+	das = NULL;
 
 	return 0;
 }
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
index f36b9969cfec..6728fab8c411 100644
--- a/sound/soc/tegra/tegra_i2s.c
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -312,7 +312,7 @@ static struct snd_soc_dai_ops tegra_i2s_dai_ops = {
 	.trigger	= tegra_i2s_trigger,
 };
 
-struct snd_soc_dai_driver tegra_i2s_dai[] = {
+static struct snd_soc_dai_driver tegra_i2s_dai[] = {
 	{
 		.name = DRV_NAME ".0",
 		.probe = tegra_i2s_probe,
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index c7cfd96e991e..436def1dfa39 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -367,7 +367,7 @@ static void tegra_pcm_free(struct snd_pcm *pcm)
 	tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
 }
 
-struct snd_soc_platform_driver tegra_pcm_platform = {
+static struct snd_soc_platform_driver tegra_pcm_platform = {
 	.ops		= &tegra_pcm_ops,
 	.pcm_new	= tegra_pcm_new,
 	.pcm_free	= tegra_pcm_free,
diff --git a/sound/soc/tegra/tegra_spdif.c b/sound/soc/tegra/tegra_spdif.c
index abe606b0a29e..dd11d0c63474 100644
--- a/sound/soc/tegra/tegra_spdif.c
+++ b/sound/soc/tegra/tegra_spdif.c
@@ -127,7 +127,7 @@ static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
 {
 	struct device *dev = substream->pcm->card->dev;
 	struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-	int ret, srate, spdifclock;
+	int ret, spdifclock;
 
 	spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_PACK;
 	spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_BIT_MODE_MASK;
@@ -140,7 +140,6 @@ static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	srate = params_rate(params);
 	switch (params_rate(params)) {
 	case 32000:
 		spdifclock = 4096000;
@@ -232,7 +231,7 @@ static struct snd_soc_dai_ops tegra_spdif_dai_ops = {
 	.trigger	= tegra_spdif_trigger,
 };
 
-struct snd_soc_dai_driver tegra_spdif_dai = {
+static struct snd_soc_dai_driver tegra_spdif_dai = {
 	.name = DRV_NAME,
 	.probe = tegra_spdif_probe,
 	.playback = {
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index be27f1d229af..a81cf39257bf 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -339,8 +339,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
 		snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
 	}
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 8fc07e9adf2e..b3a7efa6d960 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -124,8 +124,6 @@ static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "RHPOUT");
 	snd_soc_dapm_nc_pin(dapm, "MICIN");
 
-	snd_soc_dapm_sync(dapm);
-
 	return 0;
 }
 
diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c
index 6770e7166be4..9b5e283af51c 100644
--- a/sound/soc/txx9/txx9aclc-generic.c
+++ b/sound/soc/txx9/txx9aclc-generic.c
@@ -62,7 +62,7 @@ static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver txx9aclc_generic_driver = {
-	.remove = txx9aclc_generic_remove,
+	.remove = __exit_p(txx9aclc_generic_remove),
 	.driver = {
 		.name = "txx9aclc-generic",
 		.owner = THIS_MODULE,