Merge branch 'for-3.2' into for-3.3
diff --git a/Documentation/devicetree/bindings/sound/tegra20-das.txt b/Documentation/devicetree/bindings/sound/tegra20-das.txt
new file mode 100644
index 0000000..6de3a7e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tegra20-das.txt
@@ -0,0 +1,12 @@
+NVIDIA Tegra 20 DAS (Digital Audio Switch) controller
+
+Required properties:
+- compatible : "nvidia,tegra20-das"
+- reg : Should contain DAS registers location and length
+
+Example:
+
+das@70000c00 {
+	compatible = "nvidia,tegra20-das";
+	reg = <0x70000c00 0x80>;
+};
diff --git a/Documentation/devicetree/bindings/sound/tegra20-i2s.txt b/Documentation/devicetree/bindings/sound/tegra20-i2s.txt
new file mode 100644
index 0000000..0df2b5c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tegra20-i2s.txt
@@ -0,0 +1,17 @@
+NVIDIA Tegra 20 I2S controller
+
+Required properties:
+- compatible : "nvidia,tegra20-i2s"
+- reg : Should contain I2S registers location and length
+- interrupts : Should contain I2S interrupt
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+  request selector for this I2S controller
+
+Example:
+
+i2s@70002800 {
+	compatible = "nvidia,tegra20-i2s";
+	reg = <0x70002800 0x200>;
+	interrupts = < 45 >;
+	nvidia,dma-request-selector = < &apbdma 2 >;
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index e855278..2c1b2cb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -37,4 +37,5 @@
 sirf	SiRF Technology, Inc.
 stericsson	ST-Ericsson
 ti	Texas Instruments
+wlf	Wolfson Microelectronics
 xlnx	Xilinx
diff --git a/MAINTAINERS b/MAINTAINERS
index fd7e441..6a93a93 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -542,6 +542,7 @@
 F:	sound/soc/codecs/adav*
 F:	sound/soc/codecs/ad1*
 F:	sound/soc/codecs/ssm*
+F:	sound/soc/codecs/sigmadsp.*
 
 ANALOG DEVICES INC ASOC DRIVERS
 L:	uclinux-dist-devel@blackfin.uclinux.org
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index d04b654..55c0e75 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -282,8 +282,8 @@
 	.id		= -1,
 };
 
-static struct platform_device speyside_wm8962_device = {
-	.name		= "speyside-wm8962",
+static struct platform_device tobermory_device = {
+	.name		= "tobermory",
 	.id		= -1,
 };
 
@@ -338,7 +338,7 @@
 	&crag6410_lcd_powerdev,
 	&crag6410_backlight_device,
 	&speyside_device,
-	&speyside_wm8962_device,
+	&tobermory_device,
 	&lowland_device,
 	&wallvdd_device,
 };
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index a3aa0f6..ade98c2d 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -762,9 +762,22 @@
 	},
 };
 
-static struct platform_device fsi_ak4643_device = {
-	.name		= "sh_fsi2_a_ak4643",
+static struct fsi_ak4642_info fsi2_ak4643_info = {
+	.name		= "AK4643",
+	.card		= "FSI2A-AK4643",
+	.cpu_dai	= "fsia-dai",
+	.codec		= "ak4642-codec.0-0013",
+	.platform	= "sh_fsi2",
+	.id		= FSI_PORT_A,
 };
+
+static struct platform_device fsi_ak4643_device = {
+	.name	= "fsi-ak4642-audio",
+	.dev	= {
+		.platform_data	= &fsi_info,
+	},
+};
+
 static struct sh_mobile_meram_cfg hdmi_meram_cfg = {
 	.icb[0] = {
 		.marker_icb     = 30,
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 9c5e598..a2908d4 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -990,8 +990,20 @@
 	},
 };
 
+static struct fsi_ak4642_info fsi2_ak4643_info = {
+	.name		= "AK4643",
+	.card		= "FSI2A-AK4643",
+	.cpu_dai	= "fsia-dai",
+	.codec		= "ak4642-codec.0-0013",
+	.platform	= "sh_fsi2",
+	.id		= FSI_PORT_A,
+};
+
 static struct platform_device fsi_ak4643_device = {
-	.name		= "sh_fsi2_a_ak4643",
+	.name	= "fsi-ak4642-audio",
+	.dev	= {
+		.platform_data	= &fsi2_ak4643_info,
+	},
 };
 
 /*
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index b747c0a..b49723b 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -315,8 +315,20 @@
 	},
 };
 
+static struct fsi_ak4642_info fsi_ak4642_info = {
+	.name		= "AK4642",
+	.card		= "FSIA-AK4642",
+	.cpu_dai	= "fsia-dai",
+	.codec		= "ak4642-codec.0-0012",
+	.platform	= "sh_fsi.0",
+	.id		= FSI_PORT_A,
+};
+
 static struct platform_device fsi_ak4642_device = {
-	.name		= "sh_fsi_a_ak4642",
+	.name	= "fsi-ak4642-audio",
+	.dev	= {
+		.platform_data	= &fsi_ak4642_info,
+	},
 };
 
 /* KEYSC in SoC (Needs SW33-2 set to ON) */
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 348ff02..6483e0b 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -74,6 +74,7 @@
 	struct reg_default *reg_defaults;
 	const void *reg_defaults_raw;
 	void *cache;
+	bool cache_dirty;
 };
 
 struct regcache_ops {
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 666f6f5..6ab9f03 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -241,6 +241,8 @@
 		map->cache_ops->name);
 	name = map->cache_ops->name;
 	trace_regcache_sync(map->dev, name, "start");
+	if (!map->cache_dirty)
+		goto out;
 	if (map->cache_ops->sync) {
 		ret = map->cache_ops->sync(map);
 	} else {
@@ -291,6 +293,23 @@
 EXPORT_SYMBOL_GPL(regcache_cache_only);
 
 /**
+ * regcache_mark_dirty: Mark the register cache as dirty
+ *
+ * @map: map to mark
+ *
+ * Mark the register cache as dirty, for example due to the device
+ * having been powered down for suspend.  If the cache is not marked
+ * as dirty then the cache sync will be suppressed.
+ */
+void regcache_mark_dirty(struct regmap *map)
+{
+	mutex_lock(&map->lock);
+	map->cache_dirty = true;
+	mutex_unlock(&map->lock);
+}
+EXPORT_SYMBOL_GPL(regcache_mark_dirty);
+
+/**
  * regcache_cache_bypass: Put a register map into cache bypass mode
  *
  * @map: map to configure
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index bf441db..3aca18d 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -306,8 +306,10 @@
 		ret = regcache_write(map, reg, val);
 		if (ret != 0)
 			return ret;
-		if (map->cache_only)
+		if (map->cache_only) {
+			map->cache_dirty = true;
 			return 0;
+		}
 	}
 
 	trace_regmap_reg_write(map->dev, reg, val);
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index efba163..9b00072 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -145,18 +145,6 @@
 	  detect iSCSI boot parameters dynamically during system boot, say Y.
 	  Otherwise, say N.
 
-config SIGMA
-	tristate "SigmaStudio firmware loader"
-	depends on I2C
-	select CRC32
-	default n
-	help
-	  Enable helper functions for working with Analog Devices SigmaDSP
-	  parts and binary firmwares produced by Analog Devices SigmaStudio.
-
-	  If unsure, say N here.  Drivers that need these helpers will select
-	  this option automatically.
-
 source "drivers/firmware/google/Kconfig"
 
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 47338c9..5a7e273 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -12,6 +12,5 @@
 obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
-obj-$(CONFIG_SIGMA)		+= sigma.o
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
deleted file mode 100644
index 1eedb6f..0000000
--- a/drivers/firmware/sigma.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Load Analog Devices SigmaStudio firmware files
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/sigma.h>
-
-static size_t sigma_action_size(struct sigma_action *sa)
-{
-	size_t payload = 0;
-
-	switch (sa->instr) {
-	case SIGMA_ACTION_WRITEXBYTES:
-	case SIGMA_ACTION_WRITESINGLE:
-	case SIGMA_ACTION_WRITESAFELOAD:
-		payload = sigma_action_len(sa);
-		break;
-	default:
-		break;
-	}
-
-	payload = ALIGN(payload, 2);
-
-	return payload + sizeof(struct sigma_action);
-}
-
-/*
- * Returns a negative error value in case of an error, 0 if processing of
- * the firmware should be stopped after this action, 1 otherwise.
- */
-static int
-process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
-{
-	size_t len = sigma_action_len(sa);
-	int ret;
-
-	pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
-		sa->instr, sa->addr, len);
-
-	switch (sa->instr) {
-	case SIGMA_ACTION_WRITEXBYTES:
-	case SIGMA_ACTION_WRITESINGLE:
-	case SIGMA_ACTION_WRITESAFELOAD:
-		ret = i2c_master_send(client, (void *)&sa->addr, len);
-		if (ret < 0)
-			return -EINVAL;
-		break;
-	case SIGMA_ACTION_DELAY:
-		udelay(len);
-		len = 0;
-		break;
-	case SIGMA_ACTION_END:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-
-	return 1;
-}
-
-static int
-process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
-{
-	struct sigma_action *sa;
-	size_t size;
-	int ret;
-
-	while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
-		sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
-
-		size = sigma_action_size(sa);
-		ssfw->pos += size;
-		if (ssfw->pos > ssfw->fw->size || size == 0)
-			break;
-
-		ret = process_sigma_action(client, sa);
-
-		pr_debug("%s: action returned %i\n", __func__, ret);
-
-		if (ret <= 0)
-			return ret;
-	}
-
-	if (ssfw->pos != ssfw->fw->size)
-		return -EINVAL;
-
-	return 0;
-}
-
-int process_sigma_firmware(struct i2c_client *client, const char *name)
-{
-	int ret;
-	struct sigma_firmware_header *ssfw_head;
-	struct sigma_firmware ssfw;
-	const struct firmware *fw;
-	u32 crc;
-
-	pr_debug("%s: loading firmware %s\n", __func__, name);
-
-	/* first load the blob */
-	ret = request_firmware(&fw, name, &client->dev);
-	if (ret) {
-		pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
-		return ret;
-	}
-	ssfw.fw = fw;
-
-	/* then verify the header */
-	ret = -EINVAL;
-
-	/*
-	 * Reject too small or unreasonable large files. The upper limit has been
-	 * chosen a bit arbitrarily, but it should be enough for all practical
-	 * purposes and having the limit makes it easier to avoid integer
-	 * overflows later in the loading process.
-	 */
-	if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
-		goto done;
-
-	ssfw_head = (void *)fw->data;
-	if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
-		goto done;
-
-	crc = crc32(0, fw->data + sizeof(*ssfw_head),
-			fw->size - sizeof(*ssfw_head));
-	pr_debug("%s: crc=%x\n", __func__, crc);
-	if (crc != le32_to_cpu(ssfw_head->crc))
-		goto done;
-
-	ssfw.pos = sizeof(*ssfw_head);
-
-	/* finally process all of the actions */
-	ret = process_sigma_actions(client, &ssfw);
-
- done:
-	release_firmware(fw);
-
-	pr_debug("%s: loaded %s\n", __func__, name);
-
-	return ret;
-}
-EXPORT_SYMBOL(process_sigma_firmware);
-
-MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index ea32f30..5256f1f 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -113,6 +113,23 @@
 	u16 regs[WM8958_ENH_EQ_REGS];
 };
 
+/**
+ * Microphone detection rates, used to tune response rates and power
+ * consumption for WM8958/WM1811 microphone detection.
+ *
+ * @sysclk: System clock rate to use this configuration for.
+ * @idle: True if this configuration should use when no accessory is detected,
+ *        false otherwise.
+ * @start: Value for MICD_BIAS_START_TIME register field (not shifted).
+ * @rate: Value for MICD_RATE register field (not shifted).
+ */
+struct wm8958_micd_rate {
+	int sysclk;
+	bool idle;
+	int start;
+	int rate;
+};
+
 struct wm8994_pdata {
 	int gpio_base;
 
@@ -144,6 +161,9 @@
 	int num_enh_eq_cfgs;
 	struct wm8958_enh_eq_cfg *enh_eq_cfgs;
 
+	int num_micd_rates;
+	struct wm8958_micd_rate *micd_rates;
+
         /* LINEOUT can be differential or single ended */
         unsigned int lineout1_diff:1;
         unsigned int lineout2_diff:1;
@@ -168,6 +188,9 @@
 	/* WM8958 microphone bias configuration */
 	int micbias[2];
 
+	/* WM8958 microphone detection ranges */
+	u16 micd_lvl_sel;
+
 	/* Disable the internal pull downs on the LDOs if they are
 	 * always driven (eg, connected to an always on supply or
 	 * GPIO that always drives an output.  If they float power
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h
index 83a9cae..ebfc92f 100644
--- a/include/linux/mfd/wm8994/registers.h
+++ b/include/linux/mfd/wm8994/registers.h
@@ -242,6 +242,7 @@
 #define WM8994_GPIO_4                           0x703
 #define WM8994_GPIO_5                           0x704
 #define WM8994_GPIO_6                           0x705
+#define WM1811_JACKDET_CTRL			0x705
 #define WM8994_GPIO_7                           0x706
 #define WM8994_GPIO_8                           0x707
 #define WM8994_GPIO_9                           0x708
@@ -1852,6 +1853,9 @@
 /*
  * R57 (0x39) - AntiPOP (2)
  */
+#define WM1811_JACKDET_MODE_MASK                0x0180  /* JACKDET_MODE - [8:7] */
+#define WM1811_JACKDET_MODE_SHIFT                    7  /* JACKDET_MODE - [8:7] */
+#define WM1811_JACKDET_MODE_WIDTH                    2  /* JACKDET_MODE - [8:7] */
 #define WM8994_MICB2_DISCH                      0x0100  /* MICB2_DISCH */
 #define WM8994_MICB2_DISCH_MASK                 0x0100  /* MICB2_DISCH */
 #define WM8994_MICB2_DISCH_SHIFT                     8  /* MICB2_DISCH */
@@ -4187,6 +4191,18 @@
 #define WM8994_STL_SEL_WIDTH                         1  /* STL_SEL */
 
 /*
+ * R1797 (0x705) - JACKDET Ctrl
+ */
+#define WM1811_JACKDET_DB                       0x0100  /* JACKDET_DB */
+#define WM1811_JACKDET_DB_MASK                  0x0100  /* JACKDET_DB */
+#define WM1811_JACKDET_DB_SHIFT                      8  /* JACKDET_DB */
+#define WM1811_JACKDET_DB_WIDTH                      1  /* JACKDET_DB */
+#define WM1811_JACKDET_LVL                      0x0040  /* JACKDET_LVL */
+#define WM1811_JACKDET_LVL_MASK                 0x0040  /* JACKDET_LVL */
+#define WM1811_JACKDET_LVL_SHIFT                     6  /* JACKDET_LVL */
+#define WM1811_JACKDET_LVL_WIDTH                     1  /* JACKDET_LVL */
+
+/*
  * R1824 (0x720) - Pull Control (1)
  */
 #define WM8994_DMICDAT2_PU                      0x0800  /* DMICDAT2_PU */
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 690276a..32043a9 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -143,5 +143,6 @@
 int regcache_sync(struct regmap *map);
 void regcache_cache_only(struct regmap *map, bool enable);
 void regcache_cache_bypass(struct regmap *map, bool enable);
+void regcache_mark_dirty(struct regmap *map);
 
 #endif
diff --git a/include/linux/sigma.h b/include/linux/sigma.h
deleted file mode 100644
index d0de882..0000000
--- a/include/linux/sigma.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Load firmware files from Analog Devices SigmaStudio
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef __SIGMA_FIRMWARE_H__
-#define __SIGMA_FIRMWARE_H__
-
-#include <linux/firmware.h>
-#include <linux/types.h>
-
-struct i2c_client;
-
-#define SIGMA_MAGIC "ADISIGM"
-
-struct sigma_firmware {
-	const struct firmware *fw;
-	size_t pos;
-};
-
-struct sigma_firmware_header {
-	unsigned char magic[7];
-	u8 version;
-	__le32 crc;
-};
-
-enum {
-	SIGMA_ACTION_WRITEXBYTES = 0,
-	SIGMA_ACTION_WRITESINGLE,
-	SIGMA_ACTION_WRITESAFELOAD,
-	SIGMA_ACTION_DELAY,
-	SIGMA_ACTION_PLLWAIT,
-	SIGMA_ACTION_NOOP,
-	SIGMA_ACTION_END,
-};
-
-struct sigma_action {
-	u8 instr;
-	u8 len_hi;
-	__le16 len;
-	__be16 addr;
-	unsigned char payload[];
-};
-
-static inline u32 sigma_action_len(struct sigma_action *sa)
-{
-	return (sa->len_hi << 16) | le16_to_cpu(sa->len);
-}
-
-extern int process_sigma_firmware(struct i2c_client *client, const char *name);
-
-#endif
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 9a155f9..9b1aaca 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -78,4 +78,16 @@
 	int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
 };
 
+/*
+ * for fsi-ak4642
+ */
+struct fsi_ak4642_info {
+	const char *name;
+	const char *card;
+	const char *cpu_dai;
+	const char *codec;
+	const char *platform;
+	int id;
+};
+
 #endif /* __SOUND_FSI_H */
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 17a4c17..d26a9b7 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -43,6 +43,9 @@
 	.num_kcontrols = 0}
 
 /* platform domain */
+#define SND_SOC_DAPM_SIGGEN(wname) \
+{	.id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM }
 #define SND_SOC_DAPM_INPUT(wname) \
 {	.id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \
 	.num_kcontrols = 0, .reg = SND_SOC_NOPM }
@@ -380,6 +383,7 @@
 				  const char *pin);
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
 				const char *pin);
+void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
 
 /* Mostly internal - should not normally be used */
 void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);
@@ -409,6 +413,7 @@
 	snd_soc_dapm_supply,		/* power/clock supply */
 	snd_soc_dapm_aif_in,		/* audio interface input */
 	snd_soc_dapm_aif_out,		/* audio interface output */
+	snd_soc_dapm_siggen,		/* signal generator */
 };
 
 /*
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 11cfb59..d9aa66b 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -266,7 +266,6 @@
 
 enum snd_soc_compress_type {
 	SND_SOC_FLAT_COMPRESSION = 1,
-	SND_SOC_LZO_COMPRESSION,
 	SND_SOC_RBTREE_COMPRESSION
 };
 
@@ -593,8 +592,7 @@
 	/* driver ops */
 	int (*probe)(struct snd_soc_codec *);
 	int (*remove)(struct snd_soc_codec *);
-	int (*suspend)(struct snd_soc_codec *,
-			pm_message_t state);
+	int (*suspend)(struct snd_soc_codec *);
 	int (*resume)(struct snd_soc_codec *);
 
 	/* Default control and setup, added after probe() is run */
@@ -718,6 +716,9 @@
 	/* Symmetry requirements */
 	unsigned int symmetric_rates:1;
 
+	/* pmdown_time is ignored at stop */
+	unsigned int ignore_pmdown_time:1;
+
 	/* codec/machine specific init - e.g. add machine controls */
 	int (*init)(struct snd_soc_pcm_runtime *rtd);
 
@@ -813,6 +814,7 @@
 	int num_dapm_widgets;
 	const struct snd_soc_dapm_route *dapm_routes;
 	int num_dapm_routes;
+	bool fully_routed;
 
 	struct work_struct deferred_resume_work;
 
@@ -840,7 +842,7 @@
 };
 
 /* SoC machine DAI configuration, glues a codec and cpu DAI together */
-struct snd_soc_pcm_runtime  {
+struct snd_soc_pcm_runtime {
 	struct device dev;
 	struct snd_soc_card *card;
 	struct snd_soc_dai_link *dai_link;
diff --git a/include/sound/sta32x.h b/include/sound/sta32x.h
new file mode 100644
index 0000000..8d93b03
--- /dev/null
+++ b/include/sound/sta32x.h
@@ -0,0 +1,35 @@
+/*
+ * Platform data for ST STA32x ASoC codec driver.
+ *
+ * Copyright: 2011 Raumfeld GmbH
+ * Author: Johannes Stezenbach <js@sig21.net>
+ *
+ * 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.
+ */
+#ifndef __LINUX_SND__STA32X_H
+#define __LINUX_SND__STA32X_H
+
+#define STA32X_OCFG_2CH		0
+#define STA32X_OCFG_2_1CH	1
+#define STA32X_OCFG_1CH		3
+
+#define STA32X_OM_CH1		0
+#define STA32X_OM_CH2		1
+#define STA32X_OM_CH3		2
+
+#define STA32X_THERMAL_ADJUSTMENT_ENABLE	1
+#define STA32X_THERMAL_RECOVERY_ENABLE		2
+
+struct sta32x_platform_data {
+	int output_conf;
+	int ch1_output_mapping;
+	int ch2_output_mapping;
+	int ch3_output_mapping;
+	int thermal_conf;
+	int needs_esd_watchdog;
+};
+
+#endif /* __LINUX_SND__STA32X_H */
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 1381db8..35e662d 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -22,21 +22,6 @@
 
 if SND_SOC
 
-config SND_SOC_CACHE_LZO
-	bool "Support LZO compression for register caches"
-	select LZO_COMPRESS
-	select LZO_DECOMPRESS
-	---help---
-	   Select this to enable LZO compression for register caches.
-	   This will allow machine or CODEC drivers to compress register
-	   caches in memory, reducing the memory consumption at the
-	   expense of performance.  If this is not present and is used
-	   the system will fall back to uncompressed caches.
-
-	   Usually it is safe to disable this option, where cache
-	   compression in used the rbtree option will typically perform
-	   better.
-
 config SND_SOC_AC97_BUS
 	bool
 
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index f81d4c3..60de055 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -495,17 +495,7 @@
 	.remove = __devexit_p(atmel_soc_platform_remove),
 };
 
-static int __init snd_atmel_pcm_init(void)
-{
-	return platform_driver_register(&atmel_pcm_driver);
-}
-module_init(snd_atmel_pcm_init);
-
-static void __exit snd_atmel_pcm_exit(void)
-{
-	platform_driver_unregister(&atmel_pcm_driver);
-}
-module_exit(snd_atmel_pcm_exit);
+module_platform_driver(atmel_pcm_driver);
 
 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
 MODULE_DESCRIPTION("Atmel PCM module");
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index 7122509..354341e 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -719,7 +719,7 @@
 #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_LE |\
 			  SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops atmel_ssc_dai_ops = {
+static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
 	.startup	= atmel_ssc_startup,
 	.shutdown	= atmel_ssc_shutdown,
 	.prepare	= atmel_ssc_prepare,
@@ -859,17 +859,7 @@
 }
 EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
 
-static int __init snd_atmel_ssc_init(void)
-{
-	return platform_driver_register(&asoc_ssc_driver);
-}
-module_init(snd_atmel_ssc_init);
-
-static void __exit snd_atmel_ssc_exit(void)
-{
-	platform_driver_unregister(&asoc_ssc_driver);
-}
-module_exit(snd_atmel_ssc_exit);
+module_platform_driver(asoc_ssc_driver);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
index 726bd65..7771934 100644
--- a/sound/soc/au1x/ac97c.c
+++ b/sound/soc/au1x/ac97c.c
@@ -195,7 +195,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops alchemy_ac97c_ops = {
+static const struct snd_soc_dai_ops alchemy_ac97c_ops = {
 	.startup		= alchemy_ac97c_startup,
 };
 
diff --git a/sound/soc/au1x/db1000.c b/sound/soc/au1x/db1000.c
index 127477a..094a207 100644
--- a/sound/soc/au1x/db1000.c
+++ b/sound/soc/au1x/db1000.c
@@ -57,18 +57,7 @@
 	.remove		= __devexit_p(db1000_audio_remove),
 };
 
-static int __init db1000_audio_load(void)
-{
-	return platform_driver_register(&db1000_audio_driver);
-}
-
-static void __exit db1000_audio_unload(void)
-{
-	platform_driver_unregister(&db1000_audio_driver);
-}
-
-module_init(db1000_audio_load);
-module_exit(db1000_audio_unload);
+module_platform_driver(db1000_audio_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DB1000/DB1500/DB1100 ASoC audio");
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c
index 289312c..8073333 100644
--- a/sound/soc/au1x/db1200.c
+++ b/sound/soc/au1x/db1200.c
@@ -133,18 +133,7 @@
 	.remove		= __devexit_p(db1200_audio_remove),
 };
 
-static int __init db1200_audio_load(void)
-{
-	return platform_driver_register(&db1200_audio_driver);
-}
-
-static void __exit db1200_audio_unload(void)
-{
-	platform_driver_unregister(&db1200_audio_driver);
-}
-
-module_init(db1200_audio_load);
-module_exit(db1200_audio_unload);
+module_platform_driver(db1200_audio_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DB1200 ASoC audio support");
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index d7d04e2..09699de 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -384,18 +384,7 @@
 	.remove		= __devexit_p(au1xpsc_pcm_drvremove),
 };
 
-static int __init au1xpsc_audio_dbdma_load(void)
-{
-	return platform_driver_register(&au1xpsc_pcm_driver);
-}
-
-static void __exit au1xpsc_audio_dbdma_unload(void)
-{
-	platform_driver_unregister(&au1xpsc_pcm_driver);
-}
-
-module_init(au1xpsc_audio_dbdma_load);
-module_exit(au1xpsc_audio_dbdma_unload);
+module_platform_driver(au1xpsc_pcm_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c
index 177f713..dc4dae4 100644
--- a/sound/soc/au1x/dma.c
+++ b/sound/soc/au1x/dma.c
@@ -359,18 +359,7 @@
 	.remove		= __devexit_p(alchemy_pcm_drvremove),
 };
 
-static int __init alchemy_pcmdma_load(void)
-{
-	return platform_driver_register(&alchemy_pcmdma_driver);
-}
-
-static void __exit alchemy_pcmdma_unload(void)
-{
-	platform_driver_unregister(&alchemy_pcmdma_driver);
-}
-
-module_init(alchemy_pcmdma_load);
-module_exit(alchemy_pcmdma_unload);
+module_platform_driver(alchemy_pcmdma_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au1000/Au1500/Au1100 Audio DMA driver");
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
index 6bcf48f..cb53ad8 100644
--- a/sound/soc/au1x/i2sc.c
+++ b/sound/soc/au1x/i2sc.c
@@ -331,18 +331,7 @@
 	.remove		= __devexit_p(au1xi2s_drvremove),
 };
 
-static int __init au1xi2s_load(void)
-{
-	return platform_driver_register(&au1xi2s_driver);
-}
-
-static void __exit au1xi2s_unload(void)
-{
-	platform_driver_unregister(&au1xi2s_driver);
-}
-
-module_init(au1xi2s_load);
-module_exit(au1xi2s_unload);
+module_platform_driver(au1xi2s_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au1000/1500/1100 I2S ASoC driver");
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 0c6acd5..87daf45 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -337,7 +337,7 @@
 	return au1xpsc_ac97_workdata ? 0 : -ENODEV;
 }
 
-static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
+static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
 	.startup	= au1xpsc_ac97_startup,
 	.trigger	= au1xpsc_ac97_trigger,
 	.hw_params	= au1xpsc_ac97_hw_params,
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index e03c5ce..5c1dc8a 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -265,7 +265,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
+static const struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
 	.startup	= au1xpsc_i2s_startup,
 	.trigger	= au1xpsc_i2s_trigger,
 	.hw_params	= au1xpsc_i2s_hw_params,
@@ -435,18 +435,7 @@
 	.remove		= __devexit_p(au1xpsc_i2s_drvremove),
 };
 
-static int __init au1xpsc_i2s_load(void)
-{
-	return platform_driver_register(&au1xpsc_i2s_driver);
-}
-
-static void __exit au1xpsc_i2s_unload(void)
-{
-	platform_driver_unregister(&au1xpsc_i2s_driver);
-}
-
-module_init(au1xpsc_i2s_load);
-module_exit(au1xpsc_i2s_unload);
+module_platform_driver(au1xpsc_i2s_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver");
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 56815c1..fcff583 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -475,17 +475,7 @@
 	.remove = __devexit_p(bf5xx_soc_platform_remove),
 };
 
-static int __init snd_bf5xx_pcm_init(void)
-{
-	return platform_driver_register(&bf5xx_pcm_driver);
-}
-module_init(snd_bf5xx_pcm_init);
-
-static void __exit snd_bf5xx_pcm_exit(void)
-{
-	platform_driver_unregister(&bf5xx_pcm_driver);
-}
-module_exit(snd_bf5xx_pcm_exit);
+module_platform_driver(bf5xx_pcm_driver);
 
 MODULE_AUTHOR("Cliff Cai");
 MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 6d21625..f4e9dc4 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -375,18 +375,7 @@
 	.remove = __devexit_p(asoc_bfin_ac97_remove),
 };
 
-static int __init bfin_ac97_init(void)
-{
-	return platform_driver_register(&asoc_bfin_ac97_driver);
-}
-module_init(bfin_ac97_init);
-
-static void __exit bfin_ac97_exit(void)
-{
-	platform_driver_unregister(&asoc_bfin_ac97_driver);
-}
-module_exit(bfin_ac97_exit);
-
+module_platform_driver(asoc_bfin_ac97_driver);
 
 MODULE_AUTHOR("Roy Huang");
 MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 7565e15..6ec3d41 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -314,17 +314,7 @@
 	.remove = __devexit_p(bfin_i2s_soc_platform_remove),
 };
 
-static int __init snd_bfin_i2s_pcm_init(void)
-{
-	return platform_driver_register(&bfin_i2s_pcm_driver);
-}
-module_init(snd_bfin_i2s_pcm_init);
-
-static void __exit snd_bfin_i2s_pcm_exit(void)
-{
-	platform_driver_unregister(&bfin_i2s_pcm_driver);
-}
-module_exit(snd_bfin_i2s_pcm_exit);
+module_platform_driver(bfin_i2s_pcm_driver);
 
 MODULE_AUTHOR("Cliff Cai");
 MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 00cc3e0..4dccf03 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -223,7 +223,7 @@
 	 SNDRV_PCM_FMTBIT_S24_LE | \
 	 SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
 	.shutdown	= bf5xx_i2s_shutdown,
 	.hw_params	= bf5xx_i2s_hw_params,
 	.set_fmt	= bf5xx_i2s_set_dai_fmt,
@@ -288,18 +288,7 @@
 	},
 };
 
-static int __init bfin_i2s_init(void)
-{
-	return platform_driver_register(&bfin_i2s_driver);
-}
-
-static void __exit bfin_i2s_exit(void)
-{
-	platform_driver_unregister(&bfin_i2s_driver);
-}
-
-module_init(bfin_i2s_init);
-module_exit(bfin_i2s_exit);
+module_platform_driver(bfin_i2s_driver);
 
 /* Module information */
 MODULE_AUTHOR("Cliff Cai");
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index c95cc03..4406f9a 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -339,17 +339,7 @@
 	.remove = __devexit_p(bf5xx_soc_platform_remove),
 };
 
-static int __init snd_bfin_tdm_init(void)
-{
-	return platform_driver_register(&bfin_tdm_driver);
-}
-module_init(snd_bfin_tdm_init);
-
-static void __exit snd_bfin_tdm_exit(void)
-{
-	platform_driver_unregister(&bfin_tdm_driver);
-}
-module_exit(snd_bfin_tdm_exit);
+module_platform_driver(bfin_tdm_driver);
 
 MODULE_AUTHOR("Barry Song");
 MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index a822d1e..594f882 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -226,7 +226,7 @@
 #define bf5xx_tdm_resume       NULL
 #endif
 
-static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
+static const struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
 	.hw_params      = bf5xx_tdm_hw_params,
 	.set_fmt        = bf5xx_tdm_set_dai_fmt,
 	.shutdown       = bf5xx_tdm_shutdown,
@@ -314,17 +314,7 @@
 	},
 };
 
-static int __init bfin_tdm_init(void)
-{
-	return platform_driver_register(&bfin_tdm_driver);
-}
-module_init(bfin_tdm_init);
-
-static void __exit bfin_tdm_exit(void)
-{
-	platform_driver_unregister(&bfin_tdm_driver);
-}
-module_exit(bfin_tdm_exit);
+module_platform_driver(bfin_tdm_driver);
 
 /* Module information */
 MODULE_AUTHOR("Barry Song");
diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c
index 8df2a3b..85ed39a 100644
--- a/sound/soc/blackfin/bfin-eval-adau1373.c
+++ b/sound/soc/blackfin/bfin-eval-adau1373.c
@@ -184,17 +184,7 @@
 	.remove = __devexit_p(bfin_eval_adau1373_remove),
 };
 
-static int __init bfin_eval_adau1373_init(void)
-{
-	return platform_driver_register(&bfin_eval_adau1373_driver);
-}
-module_init(bfin_eval_adau1373_init);
-
-static void __exit bfin_eval_adau1373_exit(void)
-{
-	platform_driver_unregister(&bfin_eval_adau1373_driver);
-}
-module_exit(bfin_eval_adau1373_exit);
+module_platform_driver(bfin_eval_adau1373_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ALSA SoC bfin adau1373 driver");
diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c
index e5550ac..1a88fe9 100644
--- a/sound/soc/blackfin/bfin-eval-adau1701.c
+++ b/sound/soc/blackfin/bfin-eval-adau1701.c
@@ -121,17 +121,7 @@
 	.remove = __devexit_p(bfin_eval_adau1701_remove),
 };
 
-static int __init bfin_eval_adau1701_init(void)
-{
-	return platform_driver_register(&bfin_eval_adau1701_driver);
-}
-module_init(bfin_eval_adau1701_init);
-
-static void __exit bfin_eval_adau1701_exit(void)
-{
-	platform_driver_unregister(&bfin_eval_adau1701_driver);
-}
-module_exit(bfin_eval_adau1701_exit);
+module_platform_driver(bfin_eval_adau1701_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ALSA SoC bfin ADAU1701 driver");
diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c
index 897cfa6..0bc995f 100644
--- a/sound/soc/blackfin/bfin-eval-adav80x.c
+++ b/sound/soc/blackfin/bfin-eval-adav80x.c
@@ -157,17 +157,7 @@
 	.id_table = bfin_eval_adav80x_ids,
 };
 
-static int __init bfin_eval_adav80x_init(void)
-{
-	return platform_driver_register(&bfin_eval_adav80x_driver);
-}
-module_init(bfin_eval_adav80x_init);
-
-static void __exit bfin_eval_adav80x_exit(void)
-{
-	platform_driver_unregister(&bfin_eval_adav80x_driver);
-}
-module_exit(bfin_eval_adav80x_exit);
+module_platform_driver(bfin_eval_adav80x_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ALSA SoC bfin adav80x driver");
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 5ca122e..2d39123 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -1198,14 +1198,14 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
+static const struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
 	.digital_mute	= pm860x_digital_mute,
 	.hw_params	= pm860x_pcm_hw_params,
 	.set_fmt	= pm860x_pcm_set_dai_fmt,
 	.set_sysclk	= pm860x_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
+static const struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
 	.digital_mute	= pm860x_digital_mute,
 	.hw_params	= pm860x_i2s_hw_params,
 	.set_fmt	= pm860x_i2s_set_dai_fmt,
@@ -1481,17 +1481,7 @@
 	.remove	= __devexit_p(pm860x_codec_remove),
 };
 
-static __init int pm860x_init(void)
-{
-	return platform_driver_register(&pm860x_codec_driver);
-}
-module_init(pm860x_init);
-
-static __exit void pm860x_exit(void)
-{
-	platform_driver_unregister(&pm860x_codec_driver);
-}
-module_exit(pm860x_exit);
+module_platform_driver(pm860x_codec_driver);
 
 MODULE_DESCRIPTION("ASoC 88PM860x driver");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 4584514..593174c 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -26,8 +26,10 @@
 	select SND_SOC_AK4642 if I2C
 	select SND_SOC_AK4671 if I2C
 	select SND_SOC_ALC5623 if I2C
+	select SND_SOC_ALC5632 if I2C
 	select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
 	select SND_SOC_CS42L51 if I2C
+	select SND_SOC_CS42L73 if I2C
 	select SND_SOC_CS4270 if I2C
 	select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_CX20442
@@ -139,7 +141,7 @@
 	tristate
 
 config SND_SOC_ADAU1701
-	select SIGMA
+	select SND_SOC_SIGMADSP
 	tristate
 
 config SND_SOC_ADAU1373
@@ -168,6 +170,8 @@
 
 config SND_SOC_ALC5623
        tristate
+config SND_SOC_ALC5632
+	tristate
 
 config SND_SOC_CQ0093VC
 	tristate
@@ -175,6 +179,9 @@
 config SND_SOC_CS42L51
 	tristate
 
+config SND_SOC_CS42L73
+	tristate
+
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
 	tristate
@@ -227,6 +234,10 @@
 config SND_SOC_SGTL5000
 	tristate
 
+config SND_SOC_SIGMADSP
+	tristate
+	select CRC32
+
 config SND_SOC_SN95031
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index a2c7842..fa15006 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -15,13 +15,16 @@
 snd-soc-ak4671-objs := ak4671.o
 snd-soc-cq93vc-objs := cq93vc.o
 snd-soc-cs42l51-objs := cs42l51.o
+snd-soc-cs42l73-objs := cs42l73.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-cs4271-objs := cs4271.o
 snd-soc-cx20442-objs := cx20442.o
 snd-soc-da7210-objs := da7210.o
 snd-soc-dfbmcs320-objs := dfbmcs320.o
 snd-soc-dmic-objs := dmic.o
+snd-soc-jz4740-codec-objs := jz4740.o
 snd-soc-l3-objs := l3.o
+snd-soc-lm4857-objs := lm4857.o
 snd-soc-max98088-objs := max98088.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
@@ -29,6 +32,8 @@
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
+snd-soc-alc5632-objs := alc5632.o
+snd-soc-sigmadsp-objs := sigmadsp.o
 snd-soc-sn95031-objs := sn95031.o
 snd-soc-spdif-objs := spdif_transciever.o
 snd-soc-ssm2602-objs := ssm2602.o
@@ -88,10 +93,8 @@
 snd-soc-wm9712-objs := wm9712.o
 snd-soc-wm9713-objs := wm9713.o
 snd-soc-wm-hubs-objs := wm_hubs.o
-snd-soc-jz4740-codec-objs := jz4740.o
 
 # Amp
-snd-soc-lm4857-objs := lm4857.o
 snd-soc-max9877-objs := max9877.o
 snd-soc-tpa6130a2-objs := tpa6130a2.o
 snd-soc-wm2000-objs := wm2000.o
@@ -113,8 +116,10 @@
 obj-$(CONFIG_SND_SOC_AK4642)	+= snd-soc-ak4642.o
 obj-$(CONFIG_SND_SOC_AK4671)	+= snd-soc-ak4671.o
 obj-$(CONFIG_SND_SOC_ALC5623)    += snd-soc-alc5623.o
+obj-$(CONFIG_SND_SOC_ALC5632)	+= snd-soc-alc5632.o
 obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
 obj-$(CONFIG_SND_SOC_CS42L51)	+= snd-soc-cs42l51.o
+obj-$(CONFIG_SND_SOC_CS42L73)	+= snd-soc-cs42l73.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_CS4271)	+= snd-soc-cs4271.o
 obj-$(CONFIG_SND_SOC_CX20442)	+= snd-soc-cx20442.o
@@ -122,6 +127,7 @@
 obj-$(CONFIG_SND_SOC_DFBMCS320)	+= snd-soc-dfbmcs320.o
 obj-$(CONFIG_SND_SOC_DMIC)	+= snd-soc-dmic.o
 obj-$(CONFIG_SND_SOC_L3)	+= snd-soc-l3.o
+obj-$(CONFIG_SND_SOC_LM4857)	+= snd-soc-lm4857.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
 obj-$(CONFIG_SND_SOC_MAX98088)	+= snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98095)	+= snd-soc-max98095.o
@@ -129,6 +135,7 @@
 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_SIGMADSP)	+= snd-soc-sigmadsp.o
 obj-$(CONFIG_SND_SOC_SN95031)	+=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)	+= snd-soc-spdif.o
 obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
@@ -190,7 +197,6 @@
 obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
 
 # Amp
-obj-$(CONFIG_SND_SOC_LM4857)	+= snd-soc-lm4857.o
 obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
 obj-$(CONFIG_SND_SOC_TPA6130A2)	+= snd-soc-tpa6130a2.o
 obj-$(CONFIG_SND_SOC_WM2000)	+= snd-soc-wm2000.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index e715186..1bbad4c 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -39,7 +39,7 @@
 		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
 		SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops ac97_dai_ops = {
+static const struct snd_soc_dai_ops ac97_dai_ops = {
 	.prepare	= ac97_prepare,
 };
 
@@ -99,7 +99,7 @@
 }
 
 #ifdef CONFIG_PM
-static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int ac97_soc_suspend(struct snd_soc_codec *codec)
 {
 	snd_ac97_suspend(codec->ac97);
 
@@ -148,17 +148,7 @@
 	.remove = __devexit_p(ac97_remove),
 };
 
-static int __init ac97_init(void)
-{
-	return platform_driver_register(&ac97_codec_driver);
-}
-module_init(ac97_init);
-
-static void __exit ac97_exit(void)
-{
-	platform_driver_unregister(&ac97_codec_driver);
-}
-module_exit(ac97_exit);
+module_platform_driver(ac97_codec_driver);
 
 MODULE_DESCRIPTION("Soc Generic AC97 driver");
 MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 4e5c572..919322d 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -189,7 +189,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops ad1836_dai_ops = {
+static const struct snd_soc_dai_ops ad1836_dai_ops = {
 	.hw_params = ad1836_hw_params,
 	.set_fmt = ad1836_set_dai_fmt,
 };
@@ -223,7 +223,7 @@
 };
 
 #ifdef CONFIG_PM
-static int ad1836_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ad1836_suspend(struct snd_soc_codec *codec)
 {
 	/* reset clock control mode */
 	return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index 1206021..c1b7d92 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -30,21 +30,23 @@
 /*
  * AD193X volume/mute/de-emphasis etc. controls
  */
-static const char *ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
+static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
 
 static const struct soc_enum ad193x_deemp_enum =
 	SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp);
 
+static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
+
 static const struct snd_kcontrol_new ad193x_snd_controls[] = {
 	/* DAC volume control */
-	SOC_DOUBLE_R("DAC1 Volume", AD193X_DAC_L1_VOL,
-			AD193X_DAC_R1_VOL, 0, 0xFF, 1),
-	SOC_DOUBLE_R("DAC2 Volume", AD193X_DAC_L2_VOL,
-			AD193X_DAC_R2_VOL, 0, 0xFF, 1),
-	SOC_DOUBLE_R("DAC3 Volume", AD193X_DAC_L3_VOL,
-			AD193X_DAC_R3_VOL, 0, 0xFF, 1),
-	SOC_DOUBLE_R("DAC4 Volume", AD193X_DAC_L4_VOL,
-			AD193X_DAC_R4_VOL, 0, 0xFF, 1),
+	SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL,
+			AD193X_DAC_R1_VOL, 0, 0xFF, 1, adau193x_tlv),
+	SOC_DOUBLE_R_TLV("DAC2 Volume", AD193X_DAC_L2_VOL,
+			AD193X_DAC_R2_VOL, 0, 0xFF, 1, adau193x_tlv),
+	SOC_DOUBLE_R_TLV("DAC3 Volume", AD193X_DAC_L3_VOL,
+			AD193X_DAC_R3_VOL, 0, 0xFF, 1, adau193x_tlv),
+	SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL,
+			AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv),
 
 	/* ADC switch control */
 	SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE,
@@ -75,6 +77,7 @@
 	SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0),
 	SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0),
 	SND_SOC_DAPM_OUTPUT("DAC1OUT"),
 	SND_SOC_DAPM_OUTPUT("DAC2OUT"),
 	SND_SOC_DAPM_OUTPUT("DAC3OUT"),
@@ -84,16 +87,17 @@
 };
 
 static const struct snd_soc_dapm_route audio_paths[] = {
-	{ "DAC", NULL, "PLL_PWR" },
-	{ "ADC", NULL, "PLL_PWR" },
+	{ "DAC", NULL, "SYSCLK" },
+	{ "ADC", NULL, "SYSCLK" },
 	{ "DAC", NULL, "ADC_PWR" },
 	{ "ADC", NULL, "ADC_PWR" },
-	{ "DAC1OUT", "DAC1 Switch", "DAC" },
-	{ "DAC2OUT", "DAC2 Switch", "DAC" },
-	{ "DAC3OUT", "DAC3 Switch", "DAC" },
-	{ "DAC4OUT", "DAC4 Switch", "DAC" },
-	{ "ADC", "ADC1 Switch", "ADC1IN" },
-	{ "ADC", "ADC2 Switch", "ADC2IN" },
+	{ "DAC1OUT", NULL, "DAC" },
+	{ "DAC2OUT", NULL, "DAC" },
+	{ "DAC3OUT", NULL, "DAC" },
+	{ "DAC4OUT", NULL, "DAC" },
+	{ "ADC", NULL, "ADC1IN" },
+	{ "ADC", NULL, "ADC2IN" },
+	{ "SYSCLK", NULL, "PLL_PWR" },
 };
 
 /*
@@ -102,14 +106,14 @@
 
 static int ad193x_mute(struct snd_soc_dai *dai, int mute)
 {
-	struct snd_soc_codec *codec = dai->codec;
+	struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec);
 
 	if (mute)
-		snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+		regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
 				    AD193X_DAC_MASTER_MUTE,
 				    AD193X_DAC_MASTER_MUTE);
 	else
-		snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+		regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
 				    AD193X_DAC_MASTER_MUTE, 0);
 
 	return 0;
@@ -118,36 +122,30 @@
 static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 			       unsigned int rx_mask, int slots, int width)
 {
-	struct snd_soc_codec *codec = dai->codec;
-	int dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
-	int adc_reg = snd_soc_read(codec, AD193X_ADC_CTRL2);
-
-	dac_reg &= ~AD193X_DAC_CHAN_MASK;
-	adc_reg &= ~AD193X_ADC_CHAN_MASK;
+	struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec);
+	unsigned int channels;
 
 	switch (slots) {
 	case 2:
-		dac_reg |= AD193X_DAC_2_CHANNELS << AD193X_DAC_CHAN_SHFT;
-		adc_reg |= AD193X_ADC_2_CHANNELS << AD193X_ADC_CHAN_SHFT;
+		channels = AD193X_2_CHANNELS;
 		break;
 	case 4:
-		dac_reg |= AD193X_DAC_4_CHANNELS << AD193X_DAC_CHAN_SHFT;
-		adc_reg |= AD193X_ADC_4_CHANNELS << AD193X_ADC_CHAN_SHFT;
+		channels = AD193X_4_CHANNELS;
 		break;
 	case 8:
-		dac_reg |= AD193X_DAC_8_CHANNELS << AD193X_DAC_CHAN_SHFT;
-		adc_reg |= AD193X_ADC_8_CHANNELS << AD193X_ADC_CHAN_SHFT;
+		channels = AD193X_8_CHANNELS;
 		break;
 	case 16:
-		dac_reg |= AD193X_DAC_16_CHANNELS << AD193X_DAC_CHAN_SHFT;
-		adc_reg |= AD193X_ADC_16_CHANNELS << AD193X_ADC_CHAN_SHFT;
+		channels = AD193X_16_CHANNELS;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
-	snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg);
+	regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
+		AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT);
+	regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
+		AD193X_ADC_CHAN_MASK, channels << AD193X_ADC_CHAN_SHFT);
 
 	return 0;
 }
@@ -155,24 +153,20 @@
 static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
 		unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
-	int adc_reg1, adc_reg2, dac_reg;
-
-	adc_reg1 = snd_soc_read(codec, AD193X_ADC_CTRL1);
-	adc_reg2 = snd_soc_read(codec, AD193X_ADC_CTRL2);
-	dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
+	struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec_dai->codec);
+	unsigned int adc_serfmt = 0;
+	unsigned int adc_fmt = 0;
+	unsigned int dac_fmt = 0;
 
 	/* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
 	 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
 	 */
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
-		adc_reg1 &= ~AD193X_ADC_SERFMT_MASK;
-		adc_reg1 |= AD193X_ADC_SERFMT_TDM;
+		adc_serfmt |= AD193X_ADC_SERFMT_TDM;
 		break;
 	case SND_SOC_DAIFMT_DSP_A:
-		adc_reg1 &= ~AD193X_ADC_SERFMT_MASK;
-		adc_reg1 |= AD193X_ADC_SERFMT_AUX;
+		adc_serfmt |= AD193X_ADC_SERFMT_AUX;
 		break;
 	default:
 		return -EINVAL;
@@ -180,29 +174,20 @@
 
 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 	case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
-		adc_reg2 &= ~AD193X_ADC_LEFT_HIGH;
-		adc_reg2 &= ~AD193X_ADC_BCLK_INV;
-		dac_reg &= ~AD193X_DAC_LEFT_HIGH;
-		dac_reg &= ~AD193X_DAC_BCLK_INV;
 		break;
 	case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
-		adc_reg2 |= AD193X_ADC_LEFT_HIGH;
-		adc_reg2 &= ~AD193X_ADC_BCLK_INV;
-		dac_reg |= AD193X_DAC_LEFT_HIGH;
-		dac_reg &= ~AD193X_DAC_BCLK_INV;
+		adc_fmt |= AD193X_ADC_LEFT_HIGH;
+		dac_fmt |= AD193X_DAC_LEFT_HIGH;
 		break;
 	case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
-		adc_reg2 &= ~AD193X_ADC_LEFT_HIGH;
-		adc_reg2 |= AD193X_ADC_BCLK_INV;
-		dac_reg &= ~AD193X_DAC_LEFT_HIGH;
-		dac_reg |= AD193X_DAC_BCLK_INV;
+		adc_fmt |= AD193X_ADC_BCLK_INV;
+		dac_fmt |= AD193X_DAC_BCLK_INV;
 		break;
-
 	case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
-		adc_reg2 |= AD193X_ADC_LEFT_HIGH;
-		adc_reg2 |= AD193X_ADC_BCLK_INV;
-		dac_reg |= AD193X_DAC_LEFT_HIGH;
-		dac_reg |= AD193X_DAC_BCLK_INV;
+		adc_fmt |= AD193X_ADC_LEFT_HIGH;
+		adc_fmt |= AD193X_ADC_BCLK_INV;
+		dac_fmt |= AD193X_DAC_LEFT_HIGH;
+		dac_fmt |= AD193X_DAC_BCLK_INV;
 		break;
 	default:
 		return -EINVAL;
@@ -210,36 +195,31 @@
 
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
-		adc_reg2 |= AD193X_ADC_LCR_MASTER;
-		adc_reg2 |= AD193X_ADC_BCLK_MASTER;
-		dac_reg |= AD193X_DAC_LCR_MASTER;
-		dac_reg |= AD193X_DAC_BCLK_MASTER;
+		adc_fmt |= AD193X_ADC_LCR_MASTER;
+		adc_fmt |= AD193X_ADC_BCLK_MASTER;
+		dac_fmt |= AD193X_DAC_LCR_MASTER;
+		dac_fmt |= AD193X_DAC_BCLK_MASTER;
 		break;
 	case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
-		adc_reg2 |= AD193X_ADC_LCR_MASTER;
-		adc_reg2 &= ~AD193X_ADC_BCLK_MASTER;
-		dac_reg |= AD193X_DAC_LCR_MASTER;
-		dac_reg &= ~AD193X_DAC_BCLK_MASTER;
+		adc_fmt |= AD193X_ADC_LCR_MASTER;
+		dac_fmt |= AD193X_DAC_LCR_MASTER;
 		break;
 	case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
-		adc_reg2 &= ~AD193X_ADC_LCR_MASTER;
-		adc_reg2 |= AD193X_ADC_BCLK_MASTER;
-		dac_reg &= ~AD193X_DAC_LCR_MASTER;
-		dac_reg |= AD193X_DAC_BCLK_MASTER;
+		adc_fmt |= AD193X_ADC_BCLK_MASTER;
+		dac_fmt |= AD193X_DAC_BCLK_MASTER;
 		break;
 	case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
-		adc_reg2 &= ~AD193X_ADC_LCR_MASTER;
-		adc_reg2 &= ~AD193X_ADC_BCLK_MASTER;
-		dac_reg &= ~AD193X_DAC_LCR_MASTER;
-		dac_reg &= ~AD193X_DAC_BCLK_MASTER;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	snd_soc_write(codec, AD193X_ADC_CTRL1, adc_reg1);
-	snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg2);
-	snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
+	regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
+		AD193X_ADC_SERFMT_MASK, adc_serfmt);
+	regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
+		AD193X_ADC_FMT_MASK, adc_fmt);
+	regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
+		AD193X_DAC_FMT_MASK, dac_fmt);
 
 	return 0;
 }
@@ -299,20 +279,20 @@
 		break;
 	}
 
-	snd_soc_update_bits(codec, AD193X_PLL_CLK_CTRL0,
+	regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0,
 			    AD193X_PLL_INPUT_MASK, master_rate);
 
-	snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+	regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
 			    AD193X_DAC_WORD_LEN_MASK,
 			    word_len << AD193X_DAC_WORD_LEN_SHFT);
 
-	snd_soc_update_bits(codec, AD193X_ADC_CTRL1,
+	regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
 			    AD193X_ADC_WORD_LEN_MASK, word_len);
 
 	return 0;
 }
 
-static struct snd_soc_dai_ops ad193x_dai_ops = {
+static const struct snd_soc_dai_ops ad193x_dai_ops = {
 	.hw_params = ad193x_hw_params,
 	.digital_mute = ad193x_mute,
 	.set_tdm_slot = ad193x_set_tdm_slot,
@@ -345,7 +325,6 @@
 static int ad193x_probe(struct snd_soc_codec *codec)
 {
 	struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret;
 
 	codec->control_data = ad193x->regmap;
@@ -358,32 +337,37 @@
 	/* default setting for ad193x */
 
 	/* unmute dac channels */
-	snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
+	regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0);
 	/* de-emphasis: 48kHz, powedown dac */
-	snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
+	regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A);
 	/* powerdown dac, dac in tdm mode */
-	snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
+	regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x41);
 	/* high-pass filter enable */
-	snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
+	regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3);
 	/* sata delay=1, adc aux mode */
-	snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
+	regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43);
 	/* pll input: mclki/xi */
-	snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
-	snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
-
-	snd_soc_add_controls(codec, ad193x_snd_controls,
-			     ARRAY_SIZE(ad193x_snd_controls));
-	snd_soc_dapm_new_controls(dapm, ad193x_dapm_widgets,
-				  ARRAY_SIZE(ad193x_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
+	regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
+	regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04);
 
 	return ret;
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
 	.probe = 	ad193x_probe,
+	.controls = ad193x_snd_controls,
+	.num_controls = ARRAY_SIZE(ad193x_snd_controls),
+	.dapm_widgets = ad193x_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets),
+	.dapm_routes = audio_paths,
+	.num_dapm_routes = ARRAY_SIZE(audio_paths),
 };
 
+static bool adau193x_reg_volatile(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
 #if defined(CONFIG_SPI_MASTER)
 
 static const struct regmap_config ad193x_spi_regmap_config = {
@@ -391,6 +375,9 @@
 	.reg_bits = 16,
 	.read_flag_mask = 0x09,
 	.write_flag_mask = 0x08,
+
+	.max_register = AD193X_NUM_REGS - 1,
+	.volatile_reg = adau193x_reg_volatile,
 };
 
 static int __devinit ad193x_spi_probe(struct spi_device *spi)
@@ -450,6 +437,9 @@
 static const struct regmap_config ad193x_i2c_regmap_config = {
 	.val_bits = 8,
 	.reg_bits = 8,
+
+	.max_register = AD193X_NUM_REGS - 1,
+	.volatile_reg = adau193x_reg_volatile,
 };
 
 static const struct i2c_device_id ad193x_id[] = {
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 1507eaa..4733880 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -23,16 +23,14 @@
 #define AD193X_DAC_SERFMT_STEREO	(0 << 6)
 #define AD193X_DAC_SERFMT_TDM		(1 << 6)
 #define AD193X_DAC_CTRL1        0x03
-#define AD193X_DAC_2_CHANNELS   0
-#define AD193X_DAC_4_CHANNELS   1
-#define AD193X_DAC_8_CHANNELS   2
-#define AD193X_DAC_16_CHANNELS  3
 #define AD193X_DAC_CHAN_SHFT    1
 #define AD193X_DAC_CHAN_MASK    (3 << AD193X_DAC_CHAN_SHFT)
 #define AD193X_DAC_LCR_MASTER   (1 << 4)
 #define AD193X_DAC_BCLK_MASTER  (1 << 5)
 #define AD193X_DAC_LEFT_HIGH    (1 << 3)
 #define AD193X_DAC_BCLK_INV     (1 << 7)
+#define AD193X_DAC_FMT_MASK	(AD193X_DAC_LCR_MASTER | \
+	AD193X_DAC_BCLK_MASTER | AD193X_DAC_LEFT_HIGH | AD193X_DAC_BCLK_INV)
 #define AD193X_DAC_CTRL2        0x04
 #define AD193X_DAC_WORD_LEN_SHFT        3
 #define AD193X_DAC_WORD_LEN_MASK        0x18
@@ -68,16 +66,19 @@
 #define AD193X_ADC_SERFMT_AUX		(2 << 5)
 #define AD193X_ADC_WORD_LEN_MASK	0x3
 #define AD193X_ADC_CTRL2        0x10
-#define AD193X_ADC_2_CHANNELS   0
-#define AD193X_ADC_4_CHANNELS   1
-#define AD193X_ADC_8_CHANNELS   2
-#define AD193X_ADC_16_CHANNELS  3
 #define AD193X_ADC_CHAN_SHFT    4
 #define AD193X_ADC_CHAN_MASK    (3 << AD193X_ADC_CHAN_SHFT)
 #define AD193X_ADC_LCR_MASTER   (1 << 3)
 #define AD193X_ADC_BCLK_MASTER  (1 << 6)
 #define AD193X_ADC_LEFT_HIGH    (1 << 2)
 #define AD193X_ADC_BCLK_INV     (1 << 1)
+#define AD193X_ADC_FMT_MASK	(AD193X_ADC_LCR_MASTER | \
+	AD193X_ADC_BCLK_MASTER | AD193X_ADC_LEFT_HIGH | AD193X_ADC_BCLK_INV)
+
+#define AD193X_2_CHANNELS   0
+#define AD193X_4_CHANNELS   1
+#define AD193X_8_CHANNELS   2
+#define AD193X_16_CHANNELS  3
 
 #define AD193X_NUM_REGS          17
 
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index e3931cc..9bba7f8 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -277,17 +277,7 @@
 	.remove = __devexit_p(ad1980_remove),
 };
 
-static int __init ad1980_init(void)
-{
-	return platform_driver_register(&ad1980_codec_driver);
-}
-module_init(ad1980_init);
-
-static void __exit ad1980_exit(void)
-{
-	platform_driver_unregister(&ad1980_codec_driver);
-}
-module_exit(ad1980_exit);
+module_platform_driver(ad1980_codec_driver);
 
 MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)");
 MODULE_AUTHOR("Roy Huang, Cliff Cai");
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index 8d793e9..ee7a68d 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -63,17 +63,7 @@
 	.remove = __devexit_p(ad73311_remove),
 };
 
-static int __init ad73311_init(void)
-{
-	return platform_driver_register(&ad73311_codec_driver);
-}
-module_init(ad73311_init);
-
-static void __exit ad73311_exit(void)
-{
-	platform_driver_unregister(&ad73311_codec_driver);
-}
-module_exit(ad73311_exit);
+module_platform_driver(ad73311_codec_driver);
 
 MODULE_DESCRIPTION("ASoC ad73311 driver");
 MODULE_AUTHOR("Cliff Cai ");
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 45c6302..637b114 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1321,7 +1321,7 @@
 	return 0;
 }
 
-static int adau1373_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int adau1373_suspend(struct snd_soc_codec *codec)
 {
 	return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 8b7e1c5..6a6af56 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -12,13 +12,13 @@
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
-#include <linux/sigma.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
+#include "sigmadsp.h"
 #include "adau1701.h"
 
 #define ADAU1701_DSPCTRL	0x1c
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index f9f0894..ebd7b37 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -798,7 +798,7 @@
 	return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 }
 
-static int adav80x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int adav80x_suspend(struct snd_soc_codec *codec)
 {
 	return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index 9082e0f..8103b93 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -58,17 +58,7 @@
 	.remove = __devexit_p(ads117x_remove),
 };
 
-static int __init ads117x_init(void)
-{
-	return platform_driver_register(&ads117x_codec_driver);
-}
-module_init(ads117x_init);
-
-static void __exit ads117x_exit(void)
-{
-	platform_driver_unregister(&ads117x_codec_driver);
-}
-module_exit(ads117x_exit);
+module_platform_driver(ads117x_codec_driver);
 
 MODULE_DESCRIPTION("ASoC ads117x driver");
 MODULE_AUTHOR("Graeme Gregory");
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index d3b29dc..152420c 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -170,7 +170,7 @@
 	return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val);
 }
 
-static struct snd_soc_dai_ops ak4101_dai_ops = {
+static const struct snd_soc_dai_ops ak4101_dai_ops = {
 	.hw_params = ak4104_hw_params,
 	.set_fmt = ak4104_set_dai_fmt,
 };
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 95d782d..96296fd 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -331,7 +330,7 @@
 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
 		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops ak4535_dai_ops = {
+static const struct snd_soc_dai_ops ak4535_dai_ops = {
 	.hw_params	= ak4535_hw_params,
 	.set_fmt	= ak4535_set_dai_fmt,
 	.digital_mute	= ak4535_mute,
@@ -355,7 +354,7 @@
 	.ops = &ak4535_dai_ops,
 };
 
-static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ak4535_suspend(struct snd_soc_codec *codec)
 {
 	ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 7783858..9018470 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -17,7 +17,6 @@
 #include <linux/gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -442,14 +441,14 @@
 			 SNDRV_PCM_RATE_16000)
 #define AK4641_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE)
 
-static struct snd_soc_dai_ops ak4641_i2s_dai_ops = {
+static const struct snd_soc_dai_ops ak4641_i2s_dai_ops = {
 	.hw_params    = ak4641_i2s_hw_params,
 	.set_fmt      = ak4641_i2s_set_dai_fmt,
 	.digital_mute = ak4641_mute,
 	.set_sysclk   = ak4641_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_ops ak4641_pcm_dai_ops = {
+static const struct snd_soc_dai_ops ak4641_pcm_dai_ops = {
 	.hw_params    = NULL, /* rates are controlled by BT chip */
 	.set_fmt      = ak4641_pcm_set_dai_fmt,
 	.digital_mute = ak4641_mute,
@@ -499,7 +498,7 @@
 },
 };
 
-static int ak4641_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ak4641_suspend(struct snd_soc_codec *codec)
 {
 	ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 12c1bde..9b4ee6c 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -18,21 +18,19 @@
  * This is very simple driver.
  * It can use headphone output / stereo input only
  *
- * AK4642 is not tested.
+ * AK4642 is tested.
  * AK4643 is tested.
+ * AK4648 is tested.
  */
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <sound/soc.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#define AK4642_VERSION "0.0.1"
-
 #define PW_MGMT1	0x00
 #define PW_MGMT2	0x01
 #define SG_SL1		0x02
@@ -71,8 +69,6 @@
 #define HP_MS		0x23
 #define SPK_MS		0x24
 
-#define AK4642_CACHEREGNUM 	0x25
-
 /* PW_MGMT1*/
 #define PMVCM		(1 << 6) /* VCOM Power Management */
 #define PMMIN		(1 << 5) /* MIN Input Power Management */
@@ -150,8 +146,52 @@
 
 	SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC,
 			 0, 0xFF, 1, out_tlv),
+
+	SOC_SINGLE("Headphone Switch", PW_MGMT2, 6, 1, 0),
 };
 
+static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = {
+	SOC_DAPM_SINGLE("DACH", MD_CTL4, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = {
+	SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
+
+	/* Outputs */
+	SND_SOC_DAPM_OUTPUT("HPOUTL"),
+	SND_SOC_DAPM_OUTPUT("HPOUTR"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT"),
+
+	SND_SOC_DAPM_MIXER("HPOUTL Mixer", PW_MGMT2, 5, 0,
+			   &ak4642_hpout_mixer_controls[0],
+			   ARRAY_SIZE(ak4642_hpout_mixer_controls)),
+
+	SND_SOC_DAPM_MIXER("HPOUTR Mixer", PW_MGMT2, 4, 0,
+			   &ak4642_hpout_mixer_controls[0],
+			   ARRAY_SIZE(ak4642_hpout_mixer_controls)),
+
+	SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0,
+			   &ak4642_lout_mixer_controls[0],
+			   ARRAY_SIZE(ak4642_lout_mixer_controls)),
+
+	/* DAC */
+	SND_SOC_DAPM_DAC("DAC", "HiFi Playback", PW_MGMT1, 2, 0),
+};
+
+static const struct snd_soc_dapm_route ak4642_intercon[] = {
+
+	/* Outputs */
+	{"HPOUTL", NULL, "HPOUTL Mixer"},
+	{"HPOUTR", NULL, "HPOUTR Mixer"},
+	{"LINEOUT", NULL, "LINEOUT Mixer"},
+
+	{"HPOUTL Mixer", "DACH", "DAC"},
+	{"HPOUTR Mixer", "DACH", "DAC"},
+	{"LINEOUT Mixer", "DACL", "DAC"},
+};
 
 /* codec private data */
 struct ak4642_priv {
@@ -162,7 +202,7 @@
 /*
  * ak4642 register cache
  */
-static const u8 ak4642_reg[AK4642_CACHEREGNUM] = {
+static const u8 ak4642_reg[] = {
 	0x00, 0x00, 0x01, 0x00,
 	0x02, 0x00, 0x00, 0x00,
 	0xe1, 0xe1, 0x18, 0x00,
@@ -175,6 +215,19 @@
 	0x00,
 };
 
+static const u8 ak4648_reg[] = {
+	0x00, 0x00, 0x01, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0xe1, 0xe1, 0x18, 0x00,
+	0xe1, 0x18, 0x11, 0xb8,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x88, 0x88, 0x08,
+};
+
 static int ak4642_dai_startup(struct snd_pcm_substream *substream,
 			      struct snd_soc_dai *dai)
 {
@@ -192,14 +245,8 @@
 		 * This operation came from example code of
 		 * "ASAHI KASEI AK4642" (japanese) manual p97.
 		 */
-		snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
-		snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
 		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);
-		snd_soc_update_bits(codec, PW_MGMT2, HPMTN,	HPMTN);
 	} else {
 		/*
 		 * start stereo input
@@ -217,8 +264,7 @@
 		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_MGMT1, PMADL, PMADL);
 		snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
 	}
 
@@ -232,12 +278,6 @@
 	struct snd_soc_codec *codec = dai->codec;
 
 	if (is_play) {
-		/* stop headphone output */
-		snd_soc_update_bits(codec, PW_MGMT2, HPMTN,	0);
-		snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK,	0);
-		snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, 0);
-		snd_soc_update_bits(codec, MD_CTL3, BST1, 0);
-		snd_soc_update_bits(codec, MD_CTL4, DACH, 0);
 	} else {
 		/* stop stereo input */
 		snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0);
@@ -376,7 +416,23 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops ak4642_dai_ops = {
+static int ak4642_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_OFF:
+		snd_soc_write(codec, PW_MGMT1, 0x00);
+		break;
+	default:
+		snd_soc_update_bits(codec, PW_MGMT1, PMVCM, PMVCM);
+		break;
+	}
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops ak4642_dai_ops = {
 	.startup	= ak4642_dai_startup,
 	.shutdown	= ak4642_dai_shutdown,
 	.set_sysclk	= ak4642_dai_set_sysclk,
@@ -414,8 +470,6 @@
 	struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
-	dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
-
 	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);
@@ -425,15 +479,43 @@
 	snd_soc_add_controls(codec, ak4642_snd_controls,
 			     ARRAY_SIZE(ak4642_snd_controls));
 
+	ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	return 0;
+}
+
+static int ak4642_remove(struct snd_soc_codec *codec)
+{
+	ak4642_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
 	.probe			= ak4642_probe,
+	.remove			= ak4642_remove,
 	.resume			= ak4642_resume,
-	.reg_cache_size		= ARRAY_SIZE(ak4642_reg),
+	.set_bias_level		= ak4642_set_bias_level,
+	.reg_cache_default	= ak4642_reg,			/* ak4642 reg */
+	.reg_cache_size		= ARRAY_SIZE(ak4642_reg),	/* ak4642 reg */
 	.reg_word_size		= sizeof(u8),
-	.reg_cache_default	= ak4642_reg,
+	.dapm_widgets		= ak4642_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(ak4642_dapm_widgets),
+	.dapm_routes		= ak4642_intercon,
+	.num_dapm_routes	= ARRAY_SIZE(ak4642_intercon),
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
+	.probe			= ak4642_probe,
+	.remove			= ak4642_remove,
+	.resume			= ak4642_resume,
+	.set_bias_level		= ak4642_set_bias_level,
+	.reg_cache_default	= ak4648_reg,			/* ak4648 reg */
+	.reg_cache_size		= ARRAY_SIZE(ak4648_reg),	/* ak4648 reg */
+	.reg_word_size		= sizeof(u8),
+	.dapm_widgets		= ak4642_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(ak4642_dapm_widgets),
+	.dapm_routes		= ak4642_intercon,
+	.num_dapm_routes	= ARRAY_SIZE(ak4642_intercon),
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -451,7 +533,8 @@
 	ak4642->control_type = SND_SOC_I2C;
 
 	ret =  snd_soc_register_codec(&i2c->dev,
-			&soc_codec_dev_ak4642, &ak4642_dai, 1);
+				(struct snd_soc_codec_driver *)id->driver_data,
+				&ak4642_dai, 1);
 	if (ret < 0)
 		kfree(ak4642);
 	return ret;
@@ -465,8 +548,9 @@
 }
 
 static const struct i2c_device_id ak4642_i2c_id[] = {
-	{ "ak4642", 0 },
-	{ "ak4643", 0 },
+	{ "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 },
+	{ "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 },
+	{ "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index de9ff66..4f5c69f 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -594,7 +594,7 @@
 
 #define AK4671_FORMATS		SNDRV_PCM_FMTBIT_S16_LE
 
-static struct snd_soc_dai_ops ak4671_dai_ops = {
+static const struct snd_soc_dai_ops ak4671_dai_ops = {
 	.hw_params	= ak4671_hw_params,
 	.set_sysclk	= ak4671_set_dai_sysclk,
 	.set_fmt	= ak4671_set_dai_fmt,
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index 984b14b..da97f02 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -22,7 +22,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <linux/platform_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -839,7 +838,7 @@
 			| SNDRV_PCM_FMTBIT_S24_LE \
 			| SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops alc5623_dai_ops = {
+static const struct snd_soc_dai_ops alc5623_dai_ops = {
 		.hw_params = alc5623_pcm_hw_params,
 		.digital_mute = alc5623_mute,
 		.set_fmt = alc5623_set_dai_fmt,
@@ -869,7 +868,7 @@
 	.ops = &alc5623_dai_ops,
 };
 
-static int alc5623_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int alc5623_suspend(struct snd_soc_codec *codec)
 {
 	alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
new file mode 100644
index 0000000..08613c7
--- /dev/null
+++ b/sound/soc/codecs/alc5632.c
@@ -0,0 +1,1159 @@
+/*
+* alc5632.c  --  ALC5632 ALSA SoC Audio Codec
+*
+* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+*
+* Authors:  Leon Romanovsky <leon@leon.nu>
+*           Andrey Danin <danindrey@mail.ru>
+*           Ilya Petrov <ilya.muromec@gmail.com>
+*           Marc Dietrich <marvin24@gmx.de>
+*
+* Based on alc5623.c by Arnaud Patard
+*
+* 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/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+#include "alc5632.h"
+
+/*
+ * ALC5632 register cache
+ */
+static struct reg_default  alc5632_reg_defaults[] = {
+	{   2, 0x8080 },	/* R2   - Speaker Output Volume */
+	{   4, 0x8080 },	/* R4   - Headphone Output Volume */
+	{   6, 0x8080 },	/* R6   - AUXOUT Volume */
+	{   8, 0xC800 },	/* R8   - Phone Input */
+	{  10, 0xE808 },	/* R10  - LINE_IN Volume */
+	{  12, 0x1010 },	/* R12  - STEREO DAC Input Volume */
+	{  14, 0x0808 },	/* R14  - MIC Input Volume */
+	{  16, 0xEE0F },	/* R16  - Stereo DAC and MIC Routing Control */
+	{  18, 0xCBCB },	/* R18  - ADC Record Gain */
+	{  20, 0x7F7F },	/* R20  - ADC Record Mixer Control */
+	{  24, 0xE010 },	/* R24  - Voice DAC Volume */
+	{  28, 0x8008 },	/* R28  - Output Mixer Control */
+	{  34, 0x0000 },	/* R34  - Microphone Control */
+	{  36, 0x00C0 },    /* R36  - Codec Digital MIC/Digital Boost
+						   Control */
+	{  46, 0x0000 },	/* R46  - Stereo DAC/Voice DAC/Stereo ADC
+						   Function Select */
+	{  52, 0x8000 },	/* R52  - Main Serial Data Port Control
+						   (Stereo I2S) */
+	{  54, 0x0000 },	/* R54  - Extend Serial Data Port Control
+						   (VoDAC_I2S/PCM) */
+	{  58, 0x0000 },	/* R58  - Power Management Addition 1 */
+	{  60, 0x0000 },	/* R60  - Power Management Addition 2 */
+	{  62, 0x8000 },	/* R62  - Power Management Addition 3 */
+	{  64, 0x0C0A },	/* R64  - General Purpose Control Register 1 */
+	{  66, 0x0000 },	/* R66  - General Purpose Control Register 2 */
+	{  68, 0x0000 },	/* R68  - PLL1 Control */
+	{  70, 0x0000 },	/* R70  - PLL2 Control */
+	{  76, 0xBE3E },	/* R76  - GPIO Pin Configuration */
+	{  78, 0xBE3E },	/* R78  - GPIO Pin Polarity */
+	{  80, 0x0000 },	/* R80  - GPIO Pin Sticky */
+	{  82, 0x0000 },	/* R82  - GPIO Pin Wake Up */
+	{  86, 0x0000 },	/* R86  - Pin Sharing */
+	{  90, 0x0009 },	/* R90  - Soft Volume Control Setting */
+	{  92, 0x0000 },	/* R92  - GPIO_Output Pin Control */
+	{  94, 0x3000 },	/* R94  - MISC Control */
+	{  96, 0x3075 },	/* R96  - Stereo DAC Clock Control_1 */
+	{  98, 0x1010 },	/* R98  - Stereo DAC Clock Control_2 */
+	{ 100, 0x3110 },	/* R100 - VoDAC_PCM Clock Control_1 */
+	{ 104, 0x0553 },	/* R104 - Pseudo Stereo and Spatial Effect
+						   Block Control */
+	{ 106, 0x0000 },	/* R106 - Private Register Address */
+};
+
+/* codec private data */
+struct alc5632_priv {
+	struct regmap *regmap;
+	u8 id;
+	unsigned int sysclk;
+};
+
+static bool alc5632_volatile_register(struct device *dev,
+							unsigned int reg)
+{
+	switch (reg) {
+	case ALC5632_RESET:
+	case ALC5632_PWR_DOWN_CTRL_STATUS:
+	case ALC5632_GPIO_PIN_STATUS:
+	case ALC5632_OVER_CURR_STATUS:
+	case ALC5632_HID_CTRL_DATA:
+	case ALC5632_EQ_CTRL:
+	case ALC5632_VENDOR_ID1:
+	case ALC5632_VENDOR_ID2:
+		return true;
+
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static inline int alc5632_reset(struct regmap *map)
+{
+	return regmap_write(map, ALC5632_RESET, 0x59B4);
+}
+
+static int amp_mixer_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	/* to power-on/off class-d amp generators/speaker */
+	/* need to write to 'index-46h' register :        */
+	/* so write index num (here 0x46) to reg 0x6a     */
+	/* and then 0xffff/0 to reg 0x6c                  */
+	snd_soc_write(w->codec, ALC5632_HID_CTRL_INDEX, 0x46);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0xFFFF);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0);
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * ALC5632 Controls
+ */
+
+/* -34.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);
+/* -46.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
+/* -16.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
+static const unsigned int boost_tlv[] = {
+	TLV_DB_RANGE_HEAD(3),
+	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+	1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+	2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
+};
+/* 0db min scale, 6 db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
+/* 0db min scalem 0.75db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 075, 0);
+
+static const struct snd_kcontrol_new alc5632_vol_snd_controls[] = {
+	/* left starts at bit 8, right at bit 0 */
+	/* 31 steps (5 bit), -46.5db scale */
+	SOC_DOUBLE_TLV("Speaker Playback Volume",
+			ALC5632_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+	/* bit 15 mutes left, bit 7 right */
+	SOC_DOUBLE("Speaker Playback Switch",
+			ALC5632_SPK_OUT_VOL, 15, 7, 1, 1),
+	SOC_DOUBLE_TLV("Headphone Playback Volume",
+			ALC5632_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+	SOC_DOUBLE("Headphone Playback Switch",
+			ALC5632_HP_OUT_VOL, 15, 7, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_snd_controls[] = {
+	SOC_DOUBLE_TLV("Auxout Playback Volume",
+			ALC5632_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+	SOC_DOUBLE("Auxout Playback Switch",
+			ALC5632_AUX_OUT_VOL, 15, 7, 1, 1),
+	SOC_SINGLE_TLV("Voice DAC Playback Volume",
+			ALC5632_VOICE_DAC_VOL, 0, 63, 0, vdac_tlv),
+	SOC_SINGLE_TLV("Phone Capture Volume",
+			ALC5632_PHONE_IN_VOL, 8, 31, 1, vol_tlv),
+	SOC_DOUBLE_TLV("LineIn Capture Volume",
+			ALC5632_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
+	SOC_DOUBLE_TLV("Master Playback Volume",
+			ALC5632_STEREO_DAC_IN_VOL, 8, 0, 63, 1, vdac_tlv),
+	SOC_DOUBLE("Master Playback Switch",
+			ALC5632_STEREO_DAC_IN_VOL, 15, 7, 1, 1),
+	SOC_SINGLE_TLV("Mic1 Capture Volume",
+			ALC5632_MIC_VOL, 8, 31, 1, vol_tlv),
+	SOC_SINGLE_TLV("Mic2 Capture Volume",
+			ALC5632_MIC_VOL, 0, 31, 1, vol_tlv),
+	SOC_DOUBLE_TLV("Rec Capture Volume",
+			ALC5632_ADC_REC_GAIN, 8, 0, 31, 0, adc_rec_tlv),
+	SOC_SINGLE_TLV("Mic 1 Boost Volume",
+			ALC5632_MIC_CTRL, 10, 2, 0, boost_tlv),
+	SOC_SINGLE_TLV("Mic 2 Boost Volume",
+			ALC5632_MIC_CTRL, 8, 2, 0, boost_tlv),
+	SOC_SINGLE_TLV("Digital Boost Volume",
+			ALC5632_DIGI_BOOST_CTRL, 0, 7, 0, dig_tlv),
+};
+
+/*
+ * DAPM Controls
+ */
+static const struct snd_kcontrol_new alc5632_hp_mixer_controls[] = {
+SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5632_LINE_IN_VOL, 15, 1, 1),
+SOC_DAPM_SINGLE("PHONE2HP Playback Switch", ALC5632_PHONE_IN_VOL, 15, 1, 1),
+SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 15, 1, 1),
+SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 11, 1, 1),
+SOC_DAPM_SINGLE("VOICE2HP Playback Switch", ALC5632_VOICE_DAC_VOL, 15, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_hpl_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5632_ADC_REC_GAIN, 15, 1, 1),
+SOC_DAPM_SINGLE("DACL2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 3, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_hpr_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5632_ADC_REC_GAIN, 7, 1, 1),
+SOC_DAPM_SINGLE("DACR2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 2, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5632_ADC_REC_GAIN, 14, 1, 1),
+SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5632_ADC_REC_GAIN, 6, 1, 1),
+SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5632_LINE_IN_VOL, 13, 1, 1),
+SOC_DAPM_SINGLE("MIC12MONO Playback Switch",
+					ALC5632_MIC_ROUTING_CTRL, 13, 1, 1),
+SOC_DAPM_SINGLE("MIC22MONO Playback Switch",
+					ALC5632_MIC_ROUTING_CTRL, 9, 1, 1),
+SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5632_MIC_ROUTING_CTRL, 0, 1, 1),
+SOC_DAPM_SINGLE("VOICE2MONO Playback Switch", ALC5632_VOICE_DAC_VOL, 13, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_speaker_mixer_controls[] = {
+SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5632_LINE_IN_VOL, 14, 1, 1),
+SOC_DAPM_SINGLE("PHONE2SPK Playback Switch", ALC5632_PHONE_IN_VOL, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC12SPK Playback Switch",
+					ALC5632_MIC_ROUTING_CTRL, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC22SPK Playback Switch",
+					ALC5632_MIC_ROUTING_CTRL, 10, 1, 1),
+SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5632_MIC_ROUTING_CTRL, 1, 1, 1),
+SOC_DAPM_SINGLE("VOICE2SPK Playback Switch", ALC5632_VOICE_DAC_VOL, 14, 1, 1),
+};
+
+/* Left Record Mixer */
+static const struct snd_kcontrol_new alc5632_captureL_mixer_controls[] = {
+SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
+SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
+SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
+SOC_DAPM_SINGLE("Left Phone Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
+SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
+SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
+SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
+};
+
+/* Right Record Mixer */
+static const struct snd_kcontrol_new alc5632_captureR_mixer_controls[] = {
+SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
+SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
+SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
+SOC_DAPM_SINGLE("Right Phone Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
+SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
+SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
+SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
+};
+
+static const char *alc5632_spk_n_sour_sel[] = {
+		"RN/-R", "RP/+R", "LN/-R", "Mute"};
+static const char *alc5632_hpl_out_input_sel[] = {
+		"Vmid", "HP Left Mix"};
+static const char *alc5632_hpr_out_input_sel[] = {
+		"Vmid", "HP Right Mix"};
+static const char *alc5632_spkout_input_sel[] = {
+		"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+static const char *alc5632_aux_out_input_sel[] = {
+		"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+
+/* auxout output mux */
+static const struct soc_enum alc5632_aux_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel);
+static const struct snd_kcontrol_new alc5632_auxout_mux_controls =
+SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum);
+
+/* speaker output mux */
+static const struct soc_enum alc5632_spkout_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel);
+static const struct snd_kcontrol_new alc5632_spkout_mux_controls =
+SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum);
+
+/* headphone left output mux */
+static const struct soc_enum alc5632_hpl_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel);
+static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls =
+SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum);
+
+/* headphone right output mux */
+static const struct soc_enum alc5632_hpr_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel);
+static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls =
+SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum);
+
+/* speaker output N select */
+static const struct soc_enum alc5632_spk_n_sour_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel);
+static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls =
+SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum);
+
+/* speaker amplifier */
+static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"};
+static const struct soc_enum alc5632_amp_enum =
+	SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names);
+static const struct snd_kcontrol_new alc5632_amp_mux_controls =
+	SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
+
+
+static const struct snd_soc_dapm_widget alc5632_dapm_widgets[] = {
+/* Muxes */
+SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0,
+	&alc5632_auxout_mux_controls),
+SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0,
+	&alc5632_spkout_mux_controls),
+SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
+	&alc5632_hpl_out_mux_controls),
+SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
+	&alc5632_hpr_out_mux_controls),
+SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
+	&alc5632_spkoutn_mux_controls),
+
+/* output mixers */
+SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
+	&alc5632_hp_mixer_controls[0],
+	ARRAY_SIZE(alc5632_hp_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPR Mix", ALC5632_PWR_MANAG_ADD2, 4, 0,
+	&alc5632_hpr_mixer_controls[0],
+	ARRAY_SIZE(alc5632_hpr_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPL Mix", ALC5632_PWR_MANAG_ADD2, 5, 0,
+	&alc5632_hpl_mixer_controls[0],
+	ARRAY_SIZE(alc5632_hpl_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2, 2, 0,
+	&alc5632_mono_mixer_controls[0],
+	ARRAY_SIZE(alc5632_mono_mixer_controls)),
+SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2, 3, 0,
+	&alc5632_speaker_mixer_controls[0],
+	ARRAY_SIZE(alc5632_speaker_mixer_controls)),
+
+/* input mixers */
+SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2, 1, 0,
+	&alc5632_captureL_mixer_controls[0],
+	ARRAY_SIZE(alc5632_captureL_mixer_controls)),
+SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5632_PWR_MANAG_ADD2, 0, 0,
+	&alc5632_captureR_mixer_controls[0],
+	ARRAY_SIZE(alc5632_captureR_mixer_controls)),
+
+SND_SOC_DAPM_DAC("Left DAC", "HiFi Playback",
+	ALC5632_PWR_MANAG_ADD2, 9, 0),
+SND_SOC_DAPM_DAC("Right DAC", "HiFi Playback",
+	ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_MIXER("DAC Left Channel", ALC5632_PWR_MANAG_ADD1, 15, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("DAC Right Channel",
+	ALC5632_PWR_MANAG_ADD1, 14, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("I2S Mix", ALC5632_PWR_MANAG_ADD1, 11, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Phone Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture",
+	ALC5632_PWR_MANAG_ADD2, 7, 0),
+SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture",
+	ALC5632_PWR_MANAG_ADD2, 6, 0),
+SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3, 11, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3, 10, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3, 13, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Speaker", ALC5632_PWR_MANAG_ADD3, 12, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Aux Out", ALC5632_PWR_MANAG_ADD3, 14, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Left LineIn", ALC5632_PWR_MANAG_ADD3, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right LineIn", ALC5632_PWR_MANAG_ADD3, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Phone", ALC5632_PWR_MANAG_ADD3, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Phone ADMix", ALC5632_PWR_MANAG_ADD3, 4, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC1 PGA", ALC5632_PWR_MANAG_ADD3, 3, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC2 PGA", ALC5632_PWR_MANAG_ADD3, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5632_PWR_MANAG_ADD3, 1, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5632_PWR_MANAG_ADD3, 0, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias1", ALC5632_PWR_MANAG_ADD1, 3, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias2", ALC5632_PWR_MANAG_ADD1, 2, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_E("D Amp", ALC5632_PWR_MANAG_ADD2, 14, 0, NULL, 0,
+	amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_PGA("AB Amp", ALC5632_PWR_MANAG_ADD2, 15, 0, NULL, 0),
+SND_SOC_DAPM_MUX("AB-D Amp Mux", ALC5632_PWR_MANAG_ADD1, 10, 0,
+	&alc5632_amp_mux_controls),
+
+SND_SOC_DAPM_OUTPUT("AUXOUT"),
+SND_SOC_DAPM_OUTPUT("HPL"),
+SND_SOC_DAPM_OUTPUT("HPR"),
+SND_SOC_DAPM_OUTPUT("SPKOUT"),
+SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+SND_SOC_DAPM_INPUT("LINEINL"),
+SND_SOC_DAPM_INPUT("LINEINR"),
+SND_SOC_DAPM_INPUT("PHONEP"),
+SND_SOC_DAPM_INPUT("PHONEN"),
+SND_SOC_DAPM_INPUT("MIC1"),
+SND_SOC_DAPM_INPUT("MIC2"),
+SND_SOC_DAPM_VMID("Vmid"),
+};
+
+
+static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
+	/* virtual mixer - mixes left & right channels */
+	{"I2S Mix",	NULL,	"Left DAC"},
+	{"I2S Mix",	NULL,	"Right DAC"},
+	{"Line Mix",	NULL,	"Right LineIn"},
+	{"Line Mix",	NULL,	"Left LineIn"},
+	{"Phone Mix",	NULL,	"Phone"},
+	{"Phone Mix",	NULL,	"Phone ADMix"},
+	{"AUXOUT",		NULL,	"Aux Out"},
+
+	/* DAC */
+	{"DAC Right Channel",	NULL,	"I2S Mix"},
+	{"DAC Left Channel",	NULL,   "I2S Mix"},
+
+	/* HP mixer */
+	{"HPL Mix",	"ADC2HP_L Playback Switch",	"Left Capture Mix"},
+	{"HPL Mix", NULL,					"HP Mix"},
+	{"HPR Mix", "ADC2HP_R Playback Switch",	"Right Capture Mix"},
+	{"HPR Mix", NULL,					"HP Mix"},
+	{"HP Mix",	"LI2HP Playback Switch",	"Line Mix"},
+	{"HP Mix",	"PHONE2HP Playback Switch",	"Phone Mix"},
+	{"HP Mix",	"MIC12HP Playback Switch",	"MIC1 PGA"},
+	{"HP Mix",	"MIC22HP Playback Switch",	"MIC2 PGA"},
+
+	{"HPR Mix", "DACR2HP Playback Switch",	"DAC Right Channel"},
+	{"HPL Mix", "DACL2HP Playback Switch",	"DAC Left Channel"},
+
+	/* speaker mixer */
+	{"Speaker Mix", "LI2SPK Playback Switch",	"Line Mix"},
+	{"Speaker Mix", "PHONE2SPK Playback Switch", "Phone Mix"},
+	{"Speaker Mix", "MIC12SPK Playback Switch",	"MIC1 PGA"},
+	{"Speaker Mix", "MIC22SPK Playback Switch",	"MIC2 PGA"},
+	{"Speaker Mix", "DAC2SPK Playback Switch",	"DAC Left Channel"},
+
+
+
+	/* mono mixer */
+	{"Mono Mix", "ADC2MONO_L Playback Switch",	"Left Capture Mix"},
+	{"Mono Mix", "ADC2MONO_R Playback Switch",	"Right Capture Mix"},
+	{"Mono Mix", "LI2MONO Playback Switch",		"Line Mix"},
+	{"Mono Mix", "VOICE2MONO Playback Switch",	"Phone Mix"},
+	{"Mono Mix", "MIC12MONO Playback Switch",	"MIC1 PGA"},
+	{"Mono Mix", "MIC22MONO Playback Switch",	"MIC2 PGA"},
+	{"Mono Mix", "DAC2MONO Playback Switch",	"DAC Left Channel"},
+
+	/* Left record mixer */
+	{"Left Capture Mix", "LineInL Capture Switch",	"LINEINL"},
+	{"Left Capture Mix", "Left Phone Capture Switch", "PHONEN"},
+	{"Left Capture Mix", "Mic1 Capture Switch",	"MIC1 Pre Amp"},
+	{"Left Capture Mix", "Mic2 Capture Switch",	"MIC2 Pre Amp"},
+	{"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
+	{"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
+	{"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+
+	/*Right record mixer */
+	{"Right Capture Mix", "LineInR Capture Switch",	"LINEINR"},
+	{"Right Capture Mix", "Right Phone Capture Switch",	"PHONEP"},
+	{"Right Capture Mix", "Mic1 Capture Switch",	"MIC1 Pre Amp"},
+	{"Right Capture Mix", "Mic2 Capture Switch",	"MIC2 Pre Amp"},
+	{"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
+	{"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
+	{"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+
+	/* headphone left mux */
+	{"Left Headphone Mux", "HP Left Mix",		"HPL Mix"},
+	{"Left Headphone Mux", "Vmid",			"Vmid"},
+
+	/* headphone right mux */
+	{"Right Headphone Mux", "HP Right Mix",		"HPR Mix"},
+	{"Right Headphone Mux", "Vmid",			"Vmid"},
+
+	/* speaker out mux */
+	{"SpeakerOut Mux", "Vmid",			"Vmid"},
+	{"SpeakerOut Mux", "HPOut Mix",			"HPOut Mix"},
+	{"SpeakerOut Mux", "Speaker Mix",		"Speaker Mix"},
+	{"SpeakerOut Mux", "Mono Mix",			"Mono Mix"},
+
+	/* Mono/Aux Out mux */
+	{"AuxOut Mux", "Vmid",				"Vmid"},
+	{"AuxOut Mux", "HPOut Mix",			"HPOut Mix"},
+	{"AuxOut Mux", "Speaker Mix",			"Speaker Mix"},
+	{"AuxOut Mux", "Mono Mix",			"Mono Mix"},
+
+	/* output pga */
+	{"HPL", NULL,					"Left Headphone"},
+	{"Left Headphone", NULL,			"Left Headphone Mux"},
+	{"HPR", NULL,					"Right Headphone"},
+	{"Right Headphone", NULL,			"Right Headphone Mux"},
+	{"Aux Out", NULL,				"AuxOut Mux"},
+
+	/* input pga */
+	{"Left LineIn", NULL,				"LINEINL"},
+	{"Right LineIn", NULL,				"LINEINR"},
+	{"Phone", NULL,				"PHONEP"},
+	{"MIC1 Pre Amp", NULL,				"MIC1"},
+	{"MIC2 Pre Amp", NULL,				"MIC2"},
+	{"MIC1 PGA", NULL,				"MIC1 Pre Amp"},
+	{"MIC2 PGA", NULL,				"MIC2 Pre Amp"},
+
+	/* left ADC */
+	{"Left ADC", NULL,				"Left Capture Mix"},
+
+	/* right ADC */
+	{"Right ADC", NULL,				"Right Capture Mix"},
+
+	{"SpeakerOut N Mux", "RN/-R",			"Left Speaker"},
+	{"SpeakerOut N Mux", "RP/+R",			"Left Speaker"},
+	{"SpeakerOut N Mux", "LN/-R",			"Left Speaker"},
+	{"SpeakerOut N Mux", "Mute",			"Vmid"},
+
+	{"SpeakerOut N Mux", "RN/-R",			"Right Speaker"},
+	{"SpeakerOut N Mux", "RP/+R",			"Right Speaker"},
+	{"SpeakerOut N Mux", "LN/-R",			"Right Speaker"},
+	{"SpeakerOut N Mux", "Mute",			"Vmid"},
+
+	{"AB Amp", NULL,				"SpeakerOut Mux"},
+	{"D Amp", NULL,					"SpeakerOut Mux"},
+	{"AB-D Amp Mux", "AB Amp",			"AB Amp"},
+	{"AB-D Amp Mux", "D Amp",			"D Amp"},
+	{"Left Speaker", NULL,				"AB-D Amp Mux"},
+	{"Right Speaker", NULL,				"AB-D Amp Mux"},
+
+	{"SPKOUT", NULL,				"Left Speaker"},
+	{"SPKOUT", NULL,				"Right Speaker"},
+
+	{"SPKOUTN", NULL,				"SpeakerOut N Mux"},
+
+};
+
+/* PLL divisors */
+struct _pll_div {
+	u32 pll_in;
+	u32 pll_out;
+	u16 regvalue;
+};
+
+/* Note : pll code from original alc5632 driver. Not sure of how good it is */
+/* usefull only for master mode */
+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},
+};
+
+/* FOUT = MCLK*(N+2)/((M+2)*(K+2))
+   N: bit 15:8 (div 2 .. div 257)
+   K: bit  6:4 typical 2
+   M: bit  3:0 (div 2 .. div 17)
+
+   same as for 5623 - thanks!
+*/
+
+static const struct _pll_div codec_slave_pll_div[] = {
+
+	{  1024000,  16384000,  0x3ea0},
+	{  1411200,  22579200,	0x3ea0},
+	{  1536000,  24576000,	0x3ea0},
+	{  2048000,  16384000,  0x1ea0},
+	{  2822400,  22579200,	0x1ea0},
+	{  3072000,  24576000,	0x1ea0},
+
+};
+
+static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+		int source, unsigned int freq_in, unsigned int freq_out)
+{
+	int i;
+	struct snd_soc_codec *codec = codec_dai->codec;
+	int gbl_clk = 0, pll_div = 0;
+	u16 reg;
+
+	if (pll_id < ALC5632_PLL_FR_MCLK || pll_id > ALC5632_PLL_FR_VBCLK)
+		return -EINVAL;
+
+	/* Disable PLL power */
+	snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+				ALC5632_PWR_ADD2_PLL1,
+				0);
+	snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+				ALC5632_PWR_ADD2_PLL2,
+				0);
+
+	/* pll is not used in slave mode */
+	reg = snd_soc_read(codec, ALC5632_DAI_CONTROL);
+	if (reg & ALC5632_DAI_SDP_SLAVE_MODE)
+		return 0;
+
+	if (!freq_in || !freq_out)
+		return 0;
+
+	switch (pll_id) {
+	case ALC5632_PLL_FR_MCLK:
+		for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) {
+			if (codec_master_pll_div[i].pll_in == freq_in
+			   && codec_master_pll_div[i].pll_out == freq_out) {
+				/* PLL source from MCLK */
+				pll_div  = codec_master_pll_div[i].regvalue;
+				break;
+			}
+		}
+		break;
+	case ALC5632_PLL_FR_BCLK:
+		for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
+			if (codec_slave_pll_div[i].pll_in == freq_in
+			   && codec_slave_pll_div[i].pll_out == freq_out) {
+				/* PLL source from Bitclk */
+				gbl_clk = ALC5632_PLL_FR_BCLK;
+				pll_div = codec_slave_pll_div[i].regvalue;
+				break;
+			}
+		}
+		break;
+	case ALC5632_PLL_FR_VBCLK:
+		for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
+			if (codec_slave_pll_div[i].pll_in == freq_in
+			   && codec_slave_pll_div[i].pll_out == freq_out) {
+				/* PLL source from voice clock */
+				gbl_clk = ALC5632_PLL_FR_VBCLK;
+				pll_div = codec_slave_pll_div[i].regvalue;
+				break;
+			}
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (!pll_div)
+		return -EINVAL;
+
+	/* choose MCLK/BCLK/VBCLK */
+	snd_soc_write(codec, ALC5632_GPCR2, gbl_clk);
+	/* choose PLL1 clock rate */
+	snd_soc_write(codec, ALC5632_PLL1_CTRL, pll_div);
+	/* enable PLL1 */
+	snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+				ALC5632_PWR_ADD2_PLL1,
+				ALC5632_PWR_ADD2_PLL1);
+	/* enable PLL2 */
+	snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+				ALC5632_PWR_ADD2_PLL2,
+				ALC5632_PWR_ADD2_PLL2);
+	/* use PLL1 as main SYSCLK */
+	snd_soc_update_bits(codec, ALC5632_GPCR1,
+			ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1,
+			ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1);
+
+	return 0;
+}
+
+struct _coeff_div {
+	u16 fs;
+	u16 regvalue;
+};
+
+/* codec hifi mclk (after PLL) clock divider coefficients */
+/* values inspired from column BCLK=32Fs of Appendix A table */
+static const struct _coeff_div coeff_div[] = {
+	{512*1, 0x3075},
+};
+
+static int get_coeff(struct snd_soc_codec *codec, int rate)
+{
+	struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+		if (coeff_div[i].fs * rate == alc5632->sysclk)
+			return i;
+	}
+	return -EINVAL;
+}
+
+/*
+ * Clock after PLL and dividers
+ */
+static int alc5632_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 alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+
+	switch (freq) {
+	case  8192000:
+	case 11289600:
+	case 12288000:
+	case 16384000:
+	case 16934400:
+	case 18432000:
+	case 22579200:
+	case 24576000:
+		alc5632->sysclk = freq;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int alc5632_set_dai_fmt(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 iface = 0;
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		iface = ALC5632_DAI_SDP_MASTER_MODE;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		iface = ALC5632_DAI_SDP_SLAVE_MODE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface |= ALC5632_DAI_I2S_DF_I2S;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface |= ALC5632_DAI_I2S_DF_LEFT;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		iface |= ALC5632_DAI_I2S_DF_PCM_A;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		iface |= ALC5632_DAI_I2S_DF_PCM_B;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		iface |= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		iface |= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return snd_soc_write(codec, ALC5632_DAI_CONTROL, iface);
+}
+
+static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	int coeff, rate;
+	u16 iface;
+
+	iface = snd_soc_read(codec, ALC5632_DAI_CONTROL);
+	iface &= ~ALC5632_DAI_I2S_DL_MASK;
+
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		iface |= ALC5632_DAI_I2S_DL_16;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		iface |= ALC5632_DAI_I2S_DL_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		iface |= ALC5632_DAI_I2S_DL_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set iface & srate */
+	snd_soc_write(codec, ALC5632_DAI_CONTROL, iface);
+	rate = params_rate(params);
+	coeff = get_coeff(codec, rate);
+	if (coeff < 0)
+		return -EINVAL;
+
+	coeff = coeff_div[coeff].regvalue;
+	snd_soc_write(codec, ALC5632_DAC_CLK_CTRL1, coeff);
+
+	return 0;
+}
+
+static int alc5632_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 hp_mute = ALC5632_MISC_HP_DEPOP_MUTE_L
+						|ALC5632_MISC_HP_DEPOP_MUTE_R;
+	u16 mute_reg = snd_soc_read(codec, ALC5632_MISC_CTRL) & ~hp_mute;
+
+	if (mute)
+		mute_reg |= hp_mute;
+
+	return snd_soc_write(codec, ALC5632_MISC_CTRL, mute_reg);
+}
+
+#define ALC5632_ADD2_POWER_EN (ALC5632_PWR_ADD2_VREF)
+
+#define ALC5632_ADD3_POWER_EN (ALC5632_PWR_ADD3_MIC1_BOOST_AD)
+
+#define ALC5632_ADD1_POWER_EN \
+		(ALC5632_PWR_ADD1_DAC_REF \
+		| ALC5632_PWR_ADD1_SOFTGEN_EN \
+		| ALC5632_PWR_ADD1_HP_OUT_AMP \
+		| ALC5632_PWR_ADD1_HP_OUT_ENH_AMP \
+		| ALC5632_PWR_ADD1_MAIN_BIAS)
+
+static void enable_power_depop(struct snd_soc_codec *codec)
+{
+	snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+				ALC5632_PWR_ADD1_SOFTGEN_EN,
+				ALC5632_PWR_ADD1_SOFTGEN_EN);
+
+	snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3,
+				ALC5632_ADD3_POWER_EN,
+				ALC5632_ADD3_POWER_EN);
+
+	snd_soc_update_bits(codec, ALC5632_MISC_CTRL,
+				ALC5632_MISC_HP_DEPOP_MODE2_EN,
+				ALC5632_MISC_HP_DEPOP_MODE2_EN);
+
+	/* "normal" mode: 0 @ 26 */
+	/* set all PR0-7 mixers to 0 */
+	snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS,
+				ALC5632_PWR_DOWN_CTRL_STATUS_MASK,
+				0);
+
+	msleep(500);
+
+	snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+				ALC5632_ADD2_POWER_EN,
+				ALC5632_ADD2_POWER_EN);
+
+	snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+				ALC5632_ADD1_POWER_EN,
+				ALC5632_ADD1_POWER_EN);
+
+	/* disable HP Depop2 */
+	snd_soc_update_bits(codec, ALC5632_MISC_CTRL,
+				ALC5632_MISC_HP_DEPOP_MODE2_EN,
+				0);
+
+}
+
+static int alc5632_set_bias_level(struct snd_soc_codec *codec,
+				      enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		enable_power_depop(codec);
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		/* everything off except vref/vmid, */
+		snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+				ALC5632_PWR_MANAG_ADD1_MASK,
+				ALC5632_PWR_ADD1_MAIN_BIAS);
+		snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+				ALC5632_PWR_MANAG_ADD2_MASK,
+				ALC5632_PWR_ADD2_VREF);
+		/* "normal" mode: 0 @ 26 */
+		snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS,
+				ALC5632_PWR_DOWN_CTRL_STATUS_MASK,
+				0xffff ^ (ALC5632_PWR_VREF_PR3
+				| ALC5632_PWR_VREF_PR2));
+		break;
+	case SND_SOC_BIAS_OFF:
+		/* everything off, dac mute, inactive */
+		snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+				ALC5632_PWR_MANAG_ADD2_MASK, 0);
+		snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3,
+				ALC5632_PWR_MANAG_ADD3_MASK, 0);
+		snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+				ALC5632_PWR_MANAG_ADD1_MASK, 0);
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+#define ALC5632_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE \
+			| SNDRV_PCM_FMTBIT_S24_LE \
+			| SNDRV_PCM_FMTBIT_S32_LE)
+
+static const struct snd_soc_dai_ops alc5632_dai_ops = {
+		.hw_params = alc5632_pcm_hw_params,
+		.digital_mute = alc5632_mute,
+		.set_fmt = alc5632_set_dai_fmt,
+		.set_sysclk = alc5632_set_dai_sysclk,
+		.set_pll = alc5632_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver alc5632_dai = {
+	.name = "alc5632-hifi",
+	.playback = {
+		.stream_name = "HiFi Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min =	8000,
+		.rate_max =	48000,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = ALC5632_FORMATS,},
+	.capture = {
+		.stream_name = "HiFi Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min =	8000,
+		.rate_max =	48000,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = ALC5632_FORMATS,},
+
+	.ops = &alc5632_dai_ops,
+	.symmetric_rates = 1,
+};
+
+#ifdef CONFIG_PM
+static int alc5632_suspend(struct snd_soc_codec *codec)
+{
+	alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int alc5632_resume(struct snd_soc_codec *codec)
+{
+	struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_sync(alc5632->regmap);
+
+	alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+#else
+#define	alc5632_suspend	NULL
+#define	alc5632_resume	NULL
+#endif
+
+static int alc5632_probe(struct snd_soc_codec *codec)
+{
+	struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	codec->control_data = alc5632->regmap;
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	/* power on device  */
+	alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	switch (alc5632->id) {
+	case 0x5c:
+		snd_soc_add_controls(codec, alc5632_vol_snd_controls,
+			ARRAY_SIZE(alc5632_vol_snd_controls));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/* power down chip */
+static int alc5632_remove(struct snd_soc_codec *codec)
+{
+	alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_device_alc5632 = {
+	.probe = alc5632_probe,
+	.remove = alc5632_remove,
+	.suspend = alc5632_suspend,
+	.resume = alc5632_resume,
+	.set_bias_level = alc5632_set_bias_level,
+	.controls = alc5632_snd_controls,
+	.num_controls = ARRAY_SIZE(alc5632_snd_controls),
+	.dapm_widgets = alc5632_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets),
+	.dapm_routes = alc5632_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes),
+};
+
+static struct regmap_config alc5632_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+
+	.max_register = ALC5632_MAX_REGISTER,
+	.reg_defaults = alc5632_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(alc5632_reg_defaults),
+	.volatile_reg = alc5632_volatile_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+/*
+ * alc5632 2 wire address is determined by A1 pin
+ * state during powerup.
+ *    low  = 0x1a
+ *    high = 0x1b
+ */
+static __devinit int alc5632_i2c_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct alc5632_priv *alc5632;
+	int ret, ret1, ret2;
+	unsigned int vid1, vid2;
+
+	alc5632 = devm_kzalloc(&client->dev,
+			 sizeof(struct alc5632_priv), GFP_KERNEL);
+	if (alc5632 == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, alc5632);
+
+	alc5632->regmap = regmap_init_i2c(client, &alc5632_regmap);
+	if (IS_ERR(alc5632->regmap)) {
+		ret = PTR_ERR(alc5632->regmap);
+		dev_err(&client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	ret1 = regmap_read(alc5632->regmap, ALC5632_VENDOR_ID1, &vid1);
+	ret2 = regmap_read(alc5632->regmap, ALC5632_VENDOR_ID2, &vid2);
+	if (ret1 != 0 || ret2 != 0) {
+		dev_err(&client->dev,
+		"Failed to read chip ID: ret1=%d, ret2=%d\n", ret1, ret2);
+		regmap_exit(alc5632->regmap);
+		return -EIO;
+	}
+
+	vid2 >>= 8;
+
+	if ((vid1 != 0x10EC) || (vid2 != id->driver_data)) {
+		dev_err(&client->dev,
+		"Device is not a ALC5632: VID1=0x%x, VID2=0x%x\n", vid1, vid2);
+		regmap_exit(alc5632->regmap);
+		return -EINVAL;
+	}
+
+	ret = alc5632_reset(alc5632->regmap);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to issue reset\n");
+		regmap_exit(alc5632->regmap);
+		return ret;
+	}
+
+	alc5632->id = vid2;
+	switch (alc5632->id) {
+	case 0x5c:
+		alc5632_dai.name = "alc5632-hifi";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = snd_soc_register_codec(&client->dev,
+		&soc_codec_device_alc5632, &alc5632_dai, 1);
+
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to register codec: %d\n", ret);
+		regmap_exit(alc5632->regmap);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int alc5632_i2c_remove(struct i2c_client *client)
+{
+	struct alc5632_priv *alc5632 = i2c_get_clientdata(client);
+	snd_soc_unregister_codec(&client->dev);
+	regmap_exit(alc5632->regmap);
+	return 0;
+}
+
+static const struct i2c_device_id alc5632_i2c_table[] = {
+	{"alc5632", 0x5c},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, alc5632_i2c_table);
+
+/* i2c codec control layer */
+static struct i2c_driver alc5632_i2c_driver = {
+	.driver = {
+		.name = "alc5632",
+		.owner = THIS_MODULE,
+	},
+	.probe = alc5632_i2c_probe,
+	.remove =  __devexit_p(alc5632_i2c_remove),
+	.id_table = alc5632_i2c_table,
+};
+
+static int __init alc5632_modinit(void)
+{
+	int ret;
+
+	ret = i2c_add_driver(&alc5632_i2c_driver);
+	if (ret != 0) {
+		printk(KERN_ERR "%s: can't add i2c driver", __func__);
+		return ret;
+	}
+
+	return ret;
+}
+module_init(alc5632_modinit);
+
+static void __exit alc5632_modexit(void)
+{
+	i2c_del_driver(&alc5632_i2c_driver);
+}
+module_exit(alc5632_modexit);
+
+MODULE_DESCRIPTION("ASoC ALC5632 driver");
+MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/alc5632.h b/sound/soc/codecs/alc5632.h
new file mode 100644
index 0000000..357651ec
--- /dev/null
+++ b/sound/soc/codecs/alc5632.h
@@ -0,0 +1,251 @@
+/*
+* alc5632.h  --  ALC5632 ALSA SoC Audio Codec
+*
+* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+*
+* Authors:  Leon Romanovsky <leon@leon.nu>
+*           Andrey Danin <danindrey@mail.ru>
+*           Ilya Petrov <ilya.muromec@gmail.com>
+*           Marc Dietrich <marvin24@gmx.de>
+*
+* Based on alc5623.h by Arnaud Patard
+*
+* 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 _ALC5632_H
+#define _ALC5632_H
+
+#define ALC5632_RESET				0x00
+/* speaker output vol		   2    2           */
+/* line output vol                      4    2      */
+/* HP output vol		   4    0    4      */
+#define ALC5632_SPK_OUT_VOL			0x02 /* spe out vol */
+#define ALC5632_SPK_OUT_VOL_STEP		1.5
+#define ALC5632_HP_OUT_VOL			0x04 /* hp out vol */
+#define ALC5632_AUX_OUT_VOL			0x06 /* aux out vol */
+#define ALC5632_PHONE_IN_VOL			0x08 /* phone in vol */
+#define ALC5632_LINE_IN_VOL			0x0A /* line in vol */
+#define ALC5632_STEREO_DAC_IN_VOL		0x0C /* stereo dac in vol */
+#define ALC5632_MIC_VOL				0x0E /* mic in vol */
+/* stero dac/mic routing */
+#define ALC5632_MIC_ROUTING_CTRL		0x10
+#define ALC5632_MIC_ROUTE_MONOMIX		(1 << 0)
+#define ALC5632_MIC_ROUTE_SPK			(1 << 1)
+#define ALC5632_MIC_ROUTE_HP			(1 << 2)
+
+#define ALC5632_ADC_REC_GAIN			0x12 /* rec gain */
+#define ALC5632_ADC_REC_GAIN_RANGE		0x1F1F
+#define ALC5632_ADC_REC_GAIN_BASE		(-16.5)
+#define ALC5632_ADC_REC_GAIN_STEP		1.5
+
+#define ALC5632_ADC_REC_MIXER			0x14 /* mixer control */
+#define ALC5632_ADC_REC_MIC1			(1 << 6)
+#define ALC5632_ADC_REC_MIC2			(1 << 5)
+#define ALC5632_ADC_REC_LINE_IN			(1 << 4)
+#define ALC5632_ADC_REC_AUX			(1 << 3)
+#define ALC5632_ADC_REC_HP			(1 << 2)
+#define ALC5632_ADC_REC_SPK			(1 << 1)
+#define ALC5632_ADC_REC_MONOMIX			(1 << 0)
+
+#define ALC5632_VOICE_DAC_VOL			0x18 /* voice dac vol */
+/* ALC5632_OUTPUT_MIXER_CTRL :			*/
+/* same remark as for reg 2 line vs speaker	*/
+#define ALC5632_OUTPUT_MIXER_CTRL		0x1C /* out mix ctrl */
+#define ALC5632_OUTPUT_MIXER_RP			(1 << 14)
+#define ALC5632_OUTPUT_MIXER_WEEK		(1 << 12)
+#define ALC5632_OUTPUT_MIXER_HP			(1 << 10)
+#define ALC5632_OUTPUT_MIXER_AUX_SPK		(2 <<  6)
+#define ALC5632_OUTPUT_MIXER_AUX_HP_LR          (1 << 6)
+#define ALC5632_OUTPUT_MIXER_HP_R               (1 << 8)
+#define ALC5632_OUTPUT_MIXER_HP_L               (1 << 9)
+
+#define ALC5632_MIC_CTRL			0x22 /* mic phone ctrl */
+#define ALC5632_MIC_BOOST_BYPASS		0
+#define ALC5632_MIC_BOOST_20DB			1
+#define ALC5632_MIC_BOOST_30DB			2
+#define ALC5632_MIC_BOOST_40DB			3
+
+#define ALC5632_DIGI_BOOST_CTRL			0x24 /* digi mic / bost ctl */
+#define ALC5632_MIC_BOOST_RANGE			7
+#define ALC5632_MIC_BOOST_STEP			6
+#define ALC5632_PWR_DOWN_CTRL_STATUS		0x26
+#define ALC5632_PWR_DOWN_CTRL_STATUS_MASK	0xEF00
+#define ALC5632_PWR_VREF_PR3			(1 << 11)
+#define ALC5632_PWR_VREF_PR2			(1 << 10)
+#define ALC5632_PWR_VREF_STATUS			(1 << 3)
+#define ALC5632_PWR_AMIX_STATUS			(1 << 2)
+#define ALC5632_PWR_DAC_STATUS			(1 << 1)
+#define ALC5632_PWR_ADC_STATUS			(1 << 0)
+/* stereo/voice DAC / stereo adc func ctrl */
+#define ALC5632_DAC_FUNC_SELECT			0x2E
+
+/* Main serial data port ctrl (i2s) */
+#define ALC5632_DAI_CONTROL			0x34
+
+#define ALC5632_DAI_SDP_MASTER_MODE		(0 << 15)
+#define ALC5632_DAI_SDP_SLAVE_MODE		(1 << 15)
+#define ALC5632_DAI_SADLRCK_MODE		(1 << 14)
+/* 0:voice, 1:main */
+#define ALC5632_DAI_MAIN_I2S_SYSCLK_SEL		(1 <<  8)
+#define ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL	(1 <<  7)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_MAIN_I2S_LRCK_INV		(1 <<  6)
+#define ALC5632_DAI_I2S_DL_MASK			(3 <<  2)
+#define ALC5632_DAI_I2S_DL_8			(3 <<  2)
+#define	ALC5632_DAI_I2S_DL_24			(2 <<  2)
+#define	ALC5632_DAI_I2S_DL_20			(1 <<  2)
+#define ALC5632_DAI_I2S_DL_16			(0 <<  2)
+#define ALC5632_DAI_I2S_DF_MASK			(3 <<  0)
+#define ALC5632_DAI_I2S_DF_PCM_B		(3 <<  0)
+#define	ALC5632_DAI_I2S_DF_PCM_A		(2 <<  0)
+#define ALC5632_DAI_I2S_DF_LEFT			(1 <<  0)
+#define ALC5632_DAI_I2S_DF_I2S			(0 <<  0)
+/* extend serial data port control (VoDAC_i2c/pcm) */
+#define ALC5632_DAI_CONTROL2			0x36
+/* 0:gpio func, 1:voice pcm */
+#define ALC5632_DAI_VOICE_PCM_ENABLE		(1 << 15)
+/* 0:master, 1:slave */
+#define ALC5632_DAI_VOICE_MODE_SEL		(1 << 14)
+/* 0:disable, 1:enable */
+#define ALC5632_DAI_HPF_CLK_CTRL		(1 << 13)
+/* 0:main, 1:voice */
+#define ALC5632_DAI_VOICE_I2S_SYSCLK_SEL	(1 <<  8)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_VOICE_VBCLK_SYSCLK_SEL	(1 <<  7)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_VOICE_I2S_LR_INV		(1 <<  6)
+#define ALC5632_DAI_VOICE_DL_MASK		(3 <<  2)
+#define ALC5632_DAI_VOICE_DL_16			(0 <<  2)
+#define ALC5632_DAI_VOICE_DL_20			(1 <<  2)
+#define ALC5632_DAI_VOICE_DL_24			(2 <<  2)
+#define ALC5632_DAI_VOICE_DL_8			(3 <<  2)
+#define ALC5632_DAI_VOICE_DF_MASK		(3 <<  0)
+#define ALC5632_DAI_VOICE_DF_I2S		(0 <<  0)
+#define ALC5632_DAI_VOICE_DF_LEFT		(1 <<  0)
+#define ALC5632_DAI_VOICE_DF_PCM_A		(2 <<  0)
+#define ALC5632_DAI_VOICE_DF_PCM_B		(3 <<  0)
+
+#define	ALC5632_PWR_MANAG_ADD1			0x3A
+#define	ALC5632_PWR_MANAG_ADD1_MASK		0xEFFF
+#define ALC5632_PWR_ADD1_DAC_L_EN		(1 << 15)
+#define ALC5632_PWR_ADD1_DAC_R_EN		(1 << 14)
+#define ALC5632_PWR_ADD1_ZERO_CROSS		(1 << 13)
+#define ALC5632_PWR_ADD1_MAIN_I2S_EN		(1 << 11)
+#define ALC5632_PWR_ADD1_SPK_AMP_EN		(1 << 10)
+#define ALC5632_PWR_ADD1_HP_OUT_AMP		(1 <<  9)
+#define ALC5632_PWR_ADD1_HP_OUT_ENH_AMP		(1 <<  8)
+#define ALC5632_PWR_ADD1_VOICE_DAC_MIX		(1 <<  7)
+#define	ALC5632_PWR_ADD1_SOFTGEN_EN		(1 <<  6)
+#define	ALC5632_PWR_ADD1_MIC1_SHORT_CURR	(1 <<  5)
+#define	ALC5632_PWR_ADD1_MIC2_SHORT_CURR	(1 <<  4)
+#define	ALC5632_PWR_ADD1_MIC1_EN		(1 <<  3)
+#define	ALC5632_PWR_ADD1_MIC2_EN		(1 <<  2)
+#define ALC5632_PWR_ADD1_MAIN_BIAS		(1 <<  1)
+#define ALC5632_PWR_ADD1_DAC_REF		(1 <<  0)
+
+#define ALC5632_PWR_MANAG_ADD2			0x3C
+#define ALC5632_PWR_MANAG_ADD2_MASK		0x7FFF
+#define ALC5632_PWR_ADD2_PLL1			(1 << 15)
+#define ALC5632_PWR_ADD2_PLL2			(1 << 14)
+#define ALC5632_PWR_ADD2_VREF			(1 << 13)
+#define ALC5632_PWR_ADD2_OVT_DET		(1 << 12)
+#define ALC5632_PWR_ADD2_VOICE_DAC		(1 << 10)
+#define ALC5632_PWR_ADD2_L_DAC_CLK		(1 <<  9)
+#define ALC5632_PWR_ADD2_R_DAC_CLK		(1 <<  8)
+#define ALC5632_PWR_ADD2_L_ADC_CLK_GAIN		(1 <<  7)
+#define ALC5632_PWR_ADD2_R_ADC_CLK_GAIN		(1 <<  6)
+#define ALC5632_PWR_ADD2_L_HP_MIXER		(1 <<  5)
+#define ALC5632_PWR_ADD2_R_HP_MIXER		(1 <<  4)
+#define ALC5632_PWR_ADD2_SPK_MIXER		(1 <<  3)
+#define ALC5632_PWR_ADD2_MONO_MIXER		(1 <<  2)
+#define ALC5632_PWR_ADD2_L_ADC_REC_MIXER	(1 <<  1)
+#define ALC5632_PWR_ADD2_R_ADC_REC_MIXER	(1 <<  0)
+
+#define ALC5632_PWR_MANAG_ADD3			0x3E
+#define ALC5632_PWR_MANAG_ADD3_MASK		0x7CFF
+#define ALC5632_PWR_ADD3_AUXOUT_VOL		(1 << 14)
+#define ALC5632_PWR_ADD3_SPK_L_OUT		(1 << 13)
+#define ALC5632_PWR_ADD3_SPK_R_OUT		(1 << 12)
+#define ALC5632_PWR_ADD3_HP_L_OUT_VOL		(1 << 11)
+#define ALC5632_PWR_ADD3_HP_R_OUT_VOL		(1 << 10)
+#define ALC5632_PWR_ADD3_LINEIN_L_VOL		(1 <<  7)
+#define ALC5632_PWR_ADD3_LINEIN_R_VOL		(1 <<  6)
+#define ALC5632_PWR_ADD3_AUXIN_VOL		(1 <<  5)
+#define ALC5632_PWR_ADD3_AUXIN_MIX		(1 <<  4)
+#define ALC5632_PWR_ADD3_MIC1_VOL		(1 <<  3)
+#define ALC5632_PWR_ADD3_MIC2_VOL		(1 <<  2)
+#define ALC5632_PWR_ADD3_MIC1_BOOST_AD		(1 <<  1)
+#define ALC5632_PWR_ADD3_MIC2_BOOST_AD		(1 <<  0)
+
+#define ALC5632_GPCR1				0x40
+#define ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1	(1 << 15)
+#define ALC5632_GPCR1_CLK_SYS_SRC_SEL_MCLK	(0 << 15)
+#define ALC5632_GPCR1_DAC_HI_FLT_EN		(1 << 10)
+#define ALC5632_GPCR1_SPK_AMP_CTRL		(7 <<  1)
+#define ALC5632_GPCR1_VDD_100			(5 <<  1)
+#define ALC5632_GPCR1_VDD_125			(4 <<  1)
+#define ALC5632_GPCR1_VDD_150			(3 <<  1)
+#define ALC5632_GPCR1_VDD_175			(2 <<  1)
+#define ALC5632_GPCR1_VDD_200			(1 <<  1)
+#define ALC5632_GPCR1_VDD_225			(0 <<  1)
+
+#define	ALC5632_GPCR2				0x42
+#define ALC5632_GPCR2_PLL1_SOUR_SEL		(3 << 12)
+#define ALC5632_PLL_FR_MCLK			(0 << 12)
+#define ALC5632_PLL_FR_BCLK			(2 << 12)
+#define ALC5632_PLL_FR_VBCLK			(3 << 12)
+#define ALC5632_GPCR2_CLK_PLL_PRE_DIV1		(0 <<  0)
+
+#define ALC5632_PLL1_CTRL			0x44
+#define ALC5632_PLL1_CTRL_N_VAL(n)		(((n) & 0x0f) << 8)
+#define ALC5632_PLL1_M_BYPASS			(1 <<  7)
+#define ALC5632_PLL1_CTRL_K_VAL(k)		(((k) & 0x07) << 4)
+#define ALC5632_PLL1_CTRL_M_VAL(m)		(((m) & 0x0f) << 0)
+
+#define ALC5632_PLL2_CTRL			0x46
+#define ALC5632_PLL2_EN				(1 << 15)
+#define ALC5632_PLL2_RATIO			(0 << 15)
+
+#define ALC5632_GPIO_PIN_CONFIG			0x4C
+#define ALC5632_GPIO_PIN_POLARITY		0x4E
+#define ALC5632_GPIO_PIN_STICKY			0x50
+#define ALC5632_GPIO_PIN_WAKEUP			0x52
+#define ALC5632_GPIO_PIN_STATUS			0x54
+#define ALC5632_GPIO_PIN_SHARING		0x56
+#define	ALC5632_OVER_CURR_STATUS		0x58
+#define ALC5632_SOFTVOL_CTRL			0x5A
+#define ALC5632_GPIO_OUPUT_PIN_CTRL		0x5C
+
+#define ALC5632_MISC_CTRL			0x5E
+#define ALC5632_MISC_DISABLE_FAST_VREG		(1 << 15)
+#define ALC5632_MISC_AVC_TRGT_SEL		(3 << 12)
+#define ALC5632_MISC_AVC_TRGT_RIGHT		(1 << 12)
+#define ALC5632_MISC_AVC_TRGT_LEFT		(2 << 12)
+#define ALC5632_MISC_AVC_TRGT_BOTH		(3 << 12)
+#define ALC5632_MISC_HP_DEPOP_MODE1_EN		(1 <<  9)
+#define ALC5632_MISC_HP_DEPOP_MODE2_EN		(1 <<  8)
+#define ALC5632_MISC_HP_DEPOP_MUTE_L		(1 <<  7)
+#define ALC5632_MISC_HP_DEPOP_MUTE_R		(1 <<  6)
+#define ALC5632_MISC_HP_DEPOP_MUTE		(1 <<  5)
+#define ALC5632_MISC_GPIO_WAKEUP_CTRL		(1 <<  1)
+#define ALC5632_MISC_IRQOUT_INV_CTRL		(1 <<  0)
+
+#define ALC5632_DAC_CLK_CTRL1			0x60
+#define ALC5632_DAC_CLK_CTRL2			0x62
+#define ALC5632_DAC_CLK_CTRL2_DIV1_2		(1 << 0)
+#define ALC5632_VOICE_DAC_PCM_CLK_CTRL1		0x64
+#define ALC5632_PSEUDO_SPATIAL_CTRL		0x68
+#define ALC5632_HID_CTRL_INDEX			0x6A
+#define ALC5632_HID_CTRL_DATA			0x6C
+#define ALC5632_EQ_CTRL				0x6E
+
+/* undocumented */
+#define ALC5632_VENDOR_ID1			0x7C
+#define ALC5632_VENDOR_ID2			0x7E
+
+#define ALC5632_MAX_REGISTER        0x7E
+
+#endif
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 46dbfd0..4854b47 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -122,7 +122,7 @@
 #define CQ93VC_RATES	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
 #define CQ93VC_FORMATS	(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
 
-static struct snd_soc_dai_ops cq93vc_dai_ops = {
+static const struct snd_soc_dai_ops cq93vc_dai_ops = {
 	.digital_mute	= cq93vc_mute,
 	.set_sysclk	= cq93vc_set_dai_sysclk,
 };
@@ -206,17 +206,7 @@
 	.remove = __devexit_p(cq93vc_platform_remove),
 };
 
-static int __init cq93vc_init(void)
-{
-	return platform_driver_register(&cq93vc_codec_driver);
-}
-module_init(cq93vc_init);
-
-static void __exit cq93vc_exit(void)
-{
-	platform_driver_unregister(&cq93vc_codec_driver);
-}
-module_exit(cq93vc_exit);
+module_platform_driver(cq93vc_codec_driver);
 
 MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver");
 MODULE_AUTHOR("Miguel Aguilar");
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 73f46eb..fef0f48 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -22,7 +22,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/soc.h>
@@ -447,7 +446,7 @@
 		snd_soc_get_volsw, cs4270_soc_put_mute),
 };
 
-static struct snd_soc_dai_ops cs4270_dai_ops = {
+static const struct snd_soc_dai_ops cs4270_dai_ops = {
 	.hw_params	= cs4270_hw_params,
 	.set_sysclk	= cs4270_set_dai_sysclk,
 	.set_fmt	= cs4270_set_dai_fmt,
@@ -579,7 +578,7 @@
  * and all registers are written back to the hardware when resuming.
  */
 
-static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int cs4270_soc_suspend(struct snd_soc_codec *codec)
 {
 	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
 	int reg, ret;
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 69fde15..f6fe846 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -402,7 +402,7 @@
 		7, 1, 1),
 };
 
-static struct snd_soc_dai_ops cs4271_dai_ops = {
+static const struct snd_soc_dai_ops cs4271_dai_ops = {
 	.hw_params	= cs4271_hw_params,
 	.set_sysclk	= cs4271_set_dai_sysclk,
 	.set_fmt	= cs4271_set_dai_fmt,
@@ -430,7 +430,7 @@
 };
 
 #ifdef CONFIG_PM
-static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int cs4271_soc_suspend(struct snd_soc_codec *codec)
 {
 	int ret;
 	/* Set power-down bit */
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 1ee66361..528510b 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -22,7 +22,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/soc.h>
@@ -175,21 +174,18 @@
 static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
-	unsigned long value;
-
-	value = snd_soc_read(w->codec, CS42L51_POWER_CTL1);
-	value &= ~CS42L51_POWER_CTL1_PDN;
-
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMD:
-		value |= CS42L51_POWER_CTL1_PDN;
+		snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
+				    CS42L51_POWER_CTL1_PDN,
+				    CS42L51_POWER_CTL1_PDN);
 		break;
 	default:
 	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
+				    CS42L51_POWER_CTL1_PDN, 0);
 		break;
 	}
-	snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
-		CS42L51_POWER_CTL1_PDN, value);
 
 	return 0;
 }
@@ -486,7 +482,7 @@
 	return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg);
 }
 
-static struct snd_soc_dai_ops cs42l51_dai_ops = {
+static const struct snd_soc_dai_ops cs42l51_dai_ops = {
 	.hw_params      = cs42l51_hw_params,
 	.set_sysclk     = cs42l51_set_dai_sysclk,
 	.set_fmt        = cs42l51_set_dai_fmt,
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
new file mode 100644
index 0000000..9d38db8
--- /dev/null
+++ b/sound/soc/codecs/cs42l73.c
@@ -0,0 +1,1453 @@
+/*
+ * cs42l73.c  --  CS42L73 ALSA Soc Audio driver
+ *
+ * Copyright 2011 Cirrus Logic, Inc.
+ *
+ * Authors: Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>
+ *	    Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.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/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include "cs42l73.h"
+
+struct sp_config {
+	u8 spc, mmcc, spfs;
+	u32 srate;
+};
+struct  cs42l73_private {
+	struct sp_config config[3];
+	struct regmap *regmap;
+	u32 sysclk;
+	u8 mclksel;
+	u32 mclk;
+};
+
+static const struct reg_default cs42l73_reg_defaults[] = {
+	{ 1, 0x42 },	/* r01	- Device ID A&B */
+	{ 2, 0xA7 },	/* r02	- Device ID C&D */
+	{ 3, 0x30 },	/* r03	- Device ID E */
+	{ 6, 0xF1 },	/* r06	- Power Ctl 1 */
+	{ 7, 0xDF },	/* r07	- Power Ctl 2 */
+	{ 8, 0x3F },	/* r08	- Power Ctl 3 */
+	{ 9, 0x50 },	/* r09	- Charge Pump Freq */
+	{ 10, 0x53 },	/* r0A	- Output Load MicBias Short Detect */
+	{ 11, 0x00 },	/* r0B	- DMIC Master Clock Ctl */
+	{ 12, 0x00 },	/* r0C	- Aux PCM Ctl */
+	{ 13, 0x15 },	/* r0D	- Aux PCM Master Clock Ctl */
+	{ 14, 0x00 },	/* r0E	- Audio PCM Ctl */
+	{ 15, 0x15 },	/* r0F	- Audio PCM Master Clock Ctl */
+	{ 16, 0x00 },	/* r10	- Voice PCM Ctl */
+	{ 17, 0x15 },	/* r11	- Voice PCM Master Clock Ctl */
+	{ 18, 0x00 },	/* r12	- Voice/Aux Sample Rate */
+	{ 19, 0x06 },	/* r13	- Misc I/O Path Ctl */
+	{ 20, 0x00 },	/* r14	- ADC Input Path Ctl */
+	{ 21, 0x00 },	/* r15	- MICA Preamp, PGA Volume */
+	{ 22, 0x00 },	/* r16	- MICB Preamp, PGA Volume */
+	{ 23, 0x00 },	/* r17	- Input Path A Digital Volume */
+	{ 24, 0x00 },	/* r18	- Input Path B Digital Volume */
+	{ 25, 0x00 },	/* r19	- Playback Digital Ctl */
+	{ 26, 0x00 },	/* r1A	- HP/LO Left Digital Volume */
+	{ 27, 0x00 },	/* r1B	- HP/LO Right Digital Volume */
+	{ 28, 0x00 },	/* r1C	- Speakerphone Digital Volume */
+	{ 29, 0x00 },	/* r1D	- Ear/SPKLO Digital Volume */
+	{ 30, 0x00 },	/* r1E	- HP Left Analog Volume */
+	{ 31, 0x00 },	/* r1F	- HP Right Analog Volume */
+	{ 32, 0x00 },	/* r20	- LO Left Analog Volume */
+	{ 33, 0x00 },	/* r21	- LO Right Analog Volume */
+	{ 34, 0x00 },	/* r22	- Stereo Input Path Advisory Volume */
+	{ 35, 0x00 },	/* r23	- Aux PCM Input Advisory Volume */
+	{ 36, 0x00 },	/* r24	- Audio PCM Input Advisory Volume */
+	{ 37, 0x00 },	/* r25	- Voice PCM Input Advisory Volume */
+	{ 38, 0x00 },	/* r26	- Limiter Attack Rate HP/LO */
+	{ 39, 0x7F },	/* r27	- Limter Ctl, Release Rate HP/LO */
+	{ 40, 0x00 },	/* r28	- Limter Threshold HP/LO */
+	{ 41, 0x00 },	/* r29	- Limiter Attack Rate Speakerphone */
+	{ 42, 0x3F },	/* r2A	- Limter Ctl, Release Rate Speakerphone */
+	{ 43, 0x00 },	/* r2B	- Limter Threshold Speakerphone */
+	{ 44, 0x00 },	/* r2C	- Limiter Attack Rate Ear/SPKLO */
+	{ 45, 0x3F },	/* r2D	- Limter Ctl, Release Rate Ear/SPKLO */
+	{ 46, 0x00 },	/* r2E	- Limter Threshold Ear/SPKLO */
+	{ 47, 0x00 },	/* r2F	- ALC Enable, Attack Rate Left/Right */
+	{ 48, 0x3F },	/* r30	- ALC Release Rate Left/Right */
+	{ 49, 0x00 },	/* r31	- ALC Threshold Left/Right */
+	{ 50, 0x00 },	/* r32	- Noise Gate Ctl Left/Right */
+	{ 51, 0x00 },	/* r33	- ALC/NG Misc Ctl */
+	{ 52, 0x18 },	/* r34	- Mixer Ctl */
+	{ 53, 0x3F },	/* r35	- HP/LO Left Mixer Input Path Volume */
+	{ 54, 0x3F },	/* r36	- HP/LO Right Mixer Input Path Volume */
+	{ 55, 0x3F },	/* r37	- HP/LO Left Mixer Aux PCM Volume */
+	{ 56, 0x3F },	/* r38	- HP/LO Right Mixer Aux PCM Volume */
+	{ 57, 0x3F },	/* r39	- HP/LO Left Mixer Audio PCM Volume */
+	{ 58, 0x3F },	/* r3A	- HP/LO Right Mixer Audio PCM Volume */
+	{ 59, 0x3F },	/* r3B	- HP/LO Left Mixer Voice PCM Mono Volume */
+	{ 60, 0x3F },	/* r3C	- HP/LO Right Mixer Voice PCM Mono Volume */
+	{ 61, 0x3F },	/* r3D	- Aux PCM Left Mixer Input Path Volume */
+	{ 62, 0x3F },	/* r3E	- Aux PCM Right Mixer Input Path Volume */
+	{ 63, 0x3F },	/* r3F	- Aux PCM Left Mixer Volume */
+	{ 64, 0x3F },	/* r40	- Aux PCM Left Mixer Volume */
+	{ 65, 0x3F },	/* r41	- Aux PCM Left Mixer Audio PCM L Volume */
+	{ 66, 0x3F },	/* r42	- Aux PCM Right Mixer Audio PCM R Volume */
+	{ 67, 0x3F },	/* r43	- Aux PCM Left Mixer Voice PCM Volume */
+	{ 68, 0x3F },	/* r44	- Aux PCM Right Mixer Voice PCM Volume */
+	{ 69, 0x3F },	/* r45	- Audio PCM Left Input Path Volume */
+	{ 70, 0x3F },	/* r46	- Audio PCM Right Input Path Volume */
+	{ 71, 0x3F },	/* r47	- Audio PCM Left Mixer Aux PCM L Volume */
+	{ 72, 0x3F },	/* r48	- Audio PCM Right Mixer Aux PCM R Volume */
+	{ 73, 0x3F },	/* r49	- Audio PCM Left Mixer Volume */
+	{ 74, 0x3F },	/* r4A	- Audio PCM Right Mixer Volume */
+	{ 75, 0x3F },	/* r4B	- Audio PCM Left Mixer Voice PCM Volume */
+	{ 76, 0x3F },	/* r4C	- Audio PCM Right Mixer Voice PCM Volume */
+	{ 77, 0x3F },	/* r4D	- Voice PCM Left Input Path Volume */
+	{ 78, 0x3F },	/* r4E	- Voice PCM Right Input Path Volume */
+	{ 79, 0x3F },	/* r4F	- Voice PCM Left Mixer Aux PCM L Volume */
+	{ 80, 0x3F },	/* r50	- Voice PCM Right Mixer Aux PCM R Volume */
+	{ 81, 0x3F },	/* r51	- Voice PCM Left Mixer Audio PCM L Volume */
+	{ 82, 0x3F },	/* r52	- Voice PCM Right Mixer Audio PCM R Volume */
+	{ 83, 0x3F },	/* r53	- Voice PCM Left Mixer Voice PCM Volume */
+	{ 84, 0x3F },	/* r54	- Voice PCM Right Mixer Voice PCM Volume */
+	{ 85, 0xAA },	/* r55	- Mono Mixer Ctl */
+	{ 86, 0x3F },	/* r56	- SPK Mono Mixer Input Path Volume */
+	{ 87, 0x3F },	/* r57	- SPK Mono Mixer Aux PCM Mono/L/R Volume */
+	{ 88, 0x3F },	/* r58	- SPK Mono Mixer Audio PCM Mono/L/R Volume */
+	{ 89, 0x3F },	/* r59	- SPK Mono Mixer Voice PCM Mono Volume */
+	{ 90, 0x3F },	/* r5A	- SPKLO Mono Mixer Input Path Mono Volume */
+	{ 91, 0x3F },	/* r5B	- SPKLO Mono Mixer Aux Mono/L/R Volume */
+	{ 92, 0x3F },	/* r5C	- SPKLO Mono Mixer Audio Mono/L/R Volume */
+	{ 93, 0x3F },	/* r5D	- SPKLO Mono Mixer Voice Mono Volume */
+	{ 94, 0x00 },	/* r5E	- Interrupt Mask 1 */
+	{ 95, 0x00 },	/* r5F	- Interrupt Mask 2 */
+};
+
+static bool cs42l73_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CS42L73_IS1:
+	case CS42L73_IS2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool cs42l73_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CS42L73_DEVID_AB:
+	case CS42L73_DEVID_CD:
+	case CS42L73_DEVID_E:
+	case CS42L73_REVID:
+	case CS42L73_PWRCTL1:
+	case CS42L73_PWRCTL2:
+	case CS42L73_PWRCTL3:
+	case CS42L73_CPFCHC:
+	case CS42L73_OLMBMSDC:
+	case CS42L73_DMMCC:
+	case CS42L73_XSPC:
+	case CS42L73_XSPMMCC:
+	case CS42L73_ASPC:
+	case CS42L73_ASPMMCC:
+	case CS42L73_VSPC:
+	case CS42L73_VSPMMCC:
+	case CS42L73_VXSPFS:
+	case CS42L73_MIOPC:
+	case CS42L73_ADCIPC:
+	case CS42L73_MICAPREPGAAVOL:
+	case CS42L73_MICBPREPGABVOL:
+	case CS42L73_IPADVOL:
+	case CS42L73_IPBDVOL:
+	case CS42L73_PBDC:
+	case CS42L73_HLADVOL:
+	case CS42L73_HLBDVOL:
+	case CS42L73_SPKDVOL:
+	case CS42L73_ESLDVOL:
+	case CS42L73_HPAAVOL:
+	case CS42L73_HPBAVOL:
+	case CS42L73_LOAAVOL:
+	case CS42L73_LOBAVOL:
+	case CS42L73_STRINV:
+	case CS42L73_XSPINV:
+	case CS42L73_ASPINV:
+	case CS42L73_VSPINV:
+	case CS42L73_LIMARATEHL:
+	case CS42L73_LIMRRATEHL:
+	case CS42L73_LMAXHL:
+	case CS42L73_LIMARATESPK:
+	case CS42L73_LIMRRATESPK:
+	case CS42L73_LMAXSPK:
+	case CS42L73_LIMARATEESL:
+	case CS42L73_LIMRRATEESL:
+	case CS42L73_LMAXESL:
+	case CS42L73_ALCARATE:
+	case CS42L73_ALCRRATE:
+	case CS42L73_ALCMINMAX:
+	case CS42L73_NGCAB:
+	case CS42L73_ALCNGMC:
+	case CS42L73_MIXERCTL:
+	case CS42L73_HLAIPAA:
+	case CS42L73_HLBIPBA:
+	case CS42L73_HLAXSPAA:
+	case CS42L73_HLBXSPBA:
+	case CS42L73_HLAASPAA:
+	case CS42L73_HLBASPBA:
+	case CS42L73_HLAVSPMA:
+	case CS42L73_HLBVSPMA:
+	case CS42L73_XSPAIPAA:
+	case CS42L73_XSPBIPBA:
+	case CS42L73_XSPAXSPAA:
+	case CS42L73_XSPBXSPBA:
+	case CS42L73_XSPAASPAA:
+	case CS42L73_XSPAASPBA:
+	case CS42L73_XSPAVSPMA:
+	case CS42L73_XSPBVSPMA:
+	case CS42L73_ASPAIPAA:
+	case CS42L73_ASPBIPBA:
+	case CS42L73_ASPAXSPAA:
+	case CS42L73_ASPBXSPBA:
+	case CS42L73_ASPAASPAA:
+	case CS42L73_ASPBASPBA:
+	case CS42L73_ASPAVSPMA:
+	case CS42L73_ASPBVSPMA:
+	case CS42L73_VSPAIPAA:
+	case CS42L73_VSPBIPBA:
+	case CS42L73_VSPAXSPAA:
+	case CS42L73_VSPBXSPBA:
+	case CS42L73_VSPAASPAA:
+	case CS42L73_VSPBASPBA:
+	case CS42L73_VSPAVSPMA:
+	case CS42L73_VSPBVSPMA:
+	case CS42L73_MMIXCTL:
+	case CS42L73_SPKMIPMA:
+	case CS42L73_SPKMXSPA:
+	case CS42L73_SPKMASPA:
+	case CS42L73_SPKMVSPMA:
+	case CS42L73_ESLMIPMA:
+	case CS42L73_ESLMXSPA:
+	case CS42L73_ESLMASPA:
+	case CS42L73_ESLMVSPMA:
+	case CS42L73_IM1:
+	case CS42L73_IM2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const unsigned int hpaloa_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0),
+	14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0),
+};
+
+static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0);
+
+static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0);
+
+static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
+
+static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0);
+
+static const unsigned int limiter_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
+	3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
+};
+
+static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1);
+
+static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" };
+static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" };
+
+static const struct soc_enum pgaa_enum =
+	SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3,
+		ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text);
+
+static const struct soc_enum pgab_enum =
+	SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7,
+		ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text);
+
+static const struct snd_kcontrol_new pgaa_mux =
+	SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum);
+
+static const struct snd_kcontrol_new pgab_mux =
+	SOC_DAPM_ENUM("Right Analog Input Capture Mux", pgab_enum);
+
+static const struct snd_kcontrol_new input_left_mixer[] = {
+	SOC_DAPM_SINGLE("ADC Left Input", CS42L73_PWRCTL1,
+			5, 1, 1),
+	SOC_DAPM_SINGLE("DMIC Left Input", CS42L73_PWRCTL1,
+			4, 1, 1),
+};
+
+static const struct snd_kcontrol_new input_right_mixer[] = {
+	SOC_DAPM_SINGLE("ADC Right Input", CS42L73_PWRCTL1,
+			7, 1, 1),
+	SOC_DAPM_SINGLE("DMIC Right Input", CS42L73_PWRCTL1,
+			6, 1, 1),
+};
+
+static const char * const cs42l73_ng_delay_text[] = {
+	"50ms", "100ms", "150ms", "200ms" };
+
+static const struct soc_enum ng_delay_enum =
+	SOC_ENUM_SINGLE(CS42L73_NGCAB, 0,
+		ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text);
+
+static const char * const charge_pump_freq_text[] = {
+	"0", "1", "2", "3", "4",
+	"5", "6", "7", "8", "9",
+	"10", "11", "12", "13", "14", "15" };
+
+static const struct soc_enum charge_pump_enum =
+	SOC_ENUM_SINGLE(CS42L73_CPFCHC, 4,
+		ARRAY_SIZE(charge_pump_freq_text), charge_pump_freq_text);
+
+static const char * const cs42l73_mono_mix_texts[] = {
+	"Left", "Right", "Mono Mix"};
+
+static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 };
+
+static const struct soc_enum spk_asp_enum =
+	SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1,
+			      ARRAY_SIZE(cs42l73_mono_mix_texts),
+			      cs42l73_mono_mix_texts,
+			      cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new spk_asp_mixer =
+	SOC_DAPM_ENUM("Route", spk_asp_enum);
+
+static const struct soc_enum spk_xsp_enum =
+	SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 4, 3,
+			      ARRAY_SIZE(cs42l73_mono_mix_texts),
+			      cs42l73_mono_mix_texts,
+			      cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new spk_xsp_mixer =
+	SOC_DAPM_ENUM("Route", spk_xsp_enum);
+
+static const struct soc_enum esl_asp_enum =
+	SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5,
+			      ARRAY_SIZE(cs42l73_mono_mix_texts),
+			      cs42l73_mono_mix_texts,
+			      cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new esl_asp_mixer =
+	SOC_DAPM_ENUM("Route", esl_asp_enum);
+
+static const struct soc_enum esl_xsp_enum =
+	SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7,
+			      ARRAY_SIZE(cs42l73_mono_mix_texts),
+			      cs42l73_mono_mix_texts,
+			      cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new esl_xsp_mixer =
+	SOC_DAPM_ENUM("Route", esl_xsp_enum);
+
+static const char * const cs42l73_ip_swap_text[] = {
+	"Stereo", "Mono A", "Mono B", "Swap A-B"};
+
+static const struct soc_enum ip_swap_enum =
+	SOC_ENUM_SINGLE(CS42L73_MIOPC, 6,
+		ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text);
+
+static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"};
+
+static const struct soc_enum vsp_output_mux_enum =
+	SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5,
+		ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
+
+static const struct soc_enum xsp_output_mux_enum =
+	SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4,
+		ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
+
+static const struct snd_kcontrol_new vsp_output_mux =
+	SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
+
+static const struct snd_kcontrol_new xsp_output_mux =
+	SOC_DAPM_ENUM("Route", xsp_output_mux_enum);
+
+static const struct snd_kcontrol_new hp_amp_ctl =
+	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1);
+
+static const struct snd_kcontrol_new lo_amp_ctl =
+	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 1, 1, 1);
+
+static const struct snd_kcontrol_new spk_amp_ctl =
+	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 2, 1, 1);
+
+static const struct snd_kcontrol_new spklo_amp_ctl =
+	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 4, 1, 1);
+
+static const struct snd_kcontrol_new ear_amp_ctl =
+	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 3, 1, 1);
+
+static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
+	SOC_DOUBLE_R_SX_TLV("Headphone Analog Playback Volume",
+			CS42L73_HPAAVOL, CS42L73_HPBAVOL, 7,
+			0xffffffC1, 0x0C, hpaloa_tlv),
+
+	SOC_DOUBLE_R_SX_TLV("LineOut Analog Playback Volume", CS42L73_LOAAVOL,
+			CS42L73_LOBAVOL, 7, 0xffffffC1, 0x0C, hpaloa_tlv),
+
+	SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL,
+			CS42L73_MICBPREPGABVOL, 5, 0xffffff35,
+			0x34, micpga_tlv),
+
+	SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL,
+			CS42L73_MICBPREPGABVOL, 6, 1, 1),
+
+	SOC_DOUBLE_R_SX_TLV("Input Path Digital Volume", CS42L73_IPADVOL,
+			CS42L73_IPBDVOL, 7, 0xffffffA0, 0xA0, ipd_tlv),
+
+	SOC_DOUBLE_R_SX_TLV("HL Digital Playback Volume",
+			CS42L73_HLADVOL, CS42L73_HLBDVOL, 7, 0xffffffE5,
+			0xE4, hl_tlv),
+
+	SOC_SINGLE_TLV("ADC A Boost Volume",
+			CS42L73_ADCIPC, 2, 0x01, 1, adc_boost_tlv),
+
+	SOC_SINGLE_TLV("ADC B Boost Volume",
+			CS42L73_ADCIPC, 6, 0x01, 1, adc_boost_tlv),
+
+	SOC_SINGLE_TLV("Speakerphone Digital Playback Volume",
+			CS42L73_SPKDVOL, 0, 0xE4, 1, hl_tlv),
+
+	SOC_SINGLE_TLV("Ear Speaker Digital Playback Volume",
+			CS42L73_ESLDVOL, 0, 0xE4, 1, hl_tlv),
+
+	SOC_DOUBLE_R("Headphone Analog Playback Switch", CS42L73_HPAAVOL,
+			CS42L73_HPBAVOL, 7, 1, 1),
+
+	SOC_DOUBLE_R("LineOut Analog Playback Switch", CS42L73_LOAAVOL,
+			CS42L73_LOBAVOL, 7, 1, 1),
+	SOC_DOUBLE("Input Path Digital Switch", CS42L73_ADCIPC, 0, 4, 1, 1),
+	SOC_DOUBLE("HL Digital Playback Switch", CS42L73_PBDC, 0,
+			1, 1, 1),
+	SOC_SINGLE("Speakerphone Digital Playback Switch", CS42L73_PBDC, 2, 1,
+			1),
+	SOC_SINGLE("Ear Speaker Digital Playback Switch", CS42L73_PBDC, 3, 1,
+			1),
+
+	SOC_SINGLE("PGA Soft-Ramp Switch", CS42L73_MIOPC, 3, 1, 0),
+	SOC_SINGLE("Analog Zero Cross Switch", CS42L73_MIOPC, 2, 1, 0),
+	SOC_SINGLE("Digital Soft-Ramp Switch", CS42L73_MIOPC, 1, 1, 0),
+	SOC_SINGLE("Analog Output Soft-Ramp Switch", CS42L73_MIOPC, 0, 1, 0),
+
+	SOC_DOUBLE("ADC Signal Polarity Switch", CS42L73_ADCIPC, 1, 5, 1,
+			0),
+
+	SOC_SINGLE("HL Limiter Attack Rate", CS42L73_LIMARATEHL, 0, 0x3F,
+			0),
+	SOC_SINGLE("HL Limiter Release Rate", CS42L73_LIMRRATEHL, 0,
+			0x3F, 0),
+
+
+	SOC_SINGLE("HL Limiter Switch", CS42L73_LIMRRATEHL, 7, 1, 0),
+	SOC_SINGLE("HL Limiter All Channels Switch", CS42L73_LIMRRATEHL, 6, 1,
+			0),
+
+	SOC_SINGLE_TLV("HL Limiter Max Threshold Volume", CS42L73_LMAXHL, 5, 7,
+			1, limiter_tlv),
+
+	SOC_SINGLE_TLV("HL Limiter Cushion Volume", CS42L73_LMAXHL, 2, 7, 1,
+			limiter_tlv),
+
+	SOC_SINGLE("SPK Limiter Attack Rate Volume", CS42L73_LIMARATESPK, 0,
+			0x3F, 0),
+	SOC_SINGLE("SPK Limiter Release Rate Volume", CS42L73_LIMRRATESPK, 0,
+			0x3F, 0),
+	SOC_SINGLE("SPK Limiter Switch", CS42L73_LIMRRATESPK, 7, 1, 0),
+	SOC_SINGLE("SPK Limiter All Channels Switch", CS42L73_LIMRRATESPK,
+			6, 1, 0),
+	SOC_SINGLE_TLV("SPK Limiter Max Threshold Volume", CS42L73_LMAXSPK, 5,
+			7, 1, limiter_tlv),
+
+	SOC_SINGLE_TLV("SPK Limiter Cushion Volume", CS42L73_LMAXSPK, 2, 7, 1,
+			limiter_tlv),
+
+	SOC_SINGLE("ESL Limiter Attack Rate Volume", CS42L73_LIMARATEESL, 0,
+			0x3F, 0),
+	SOC_SINGLE("ESL Limiter Release Rate Volume", CS42L73_LIMRRATEESL, 0,
+			0x3F, 0),
+	SOC_SINGLE("ESL Limiter Switch", CS42L73_LIMRRATEESL, 7, 1, 0),
+	SOC_SINGLE_TLV("ESL Limiter Max Threshold Volume", CS42L73_LMAXESL, 5,
+			7, 1, limiter_tlv),
+
+	SOC_SINGLE_TLV("ESL Limiter Cushion Volume", CS42L73_LMAXESL, 2, 7, 1,
+			limiter_tlv),
+
+	SOC_SINGLE("ALC Attack Rate Volume", CS42L73_ALCARATE, 0, 0x3F, 0),
+	SOC_SINGLE("ALC Release Rate Volume", CS42L73_ALCRRATE, 0, 0x3F, 0),
+	SOC_DOUBLE("ALC Switch", CS42L73_ALCARATE, 6, 7, 1, 0),
+	SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L73_ALCMINMAX, 5, 7, 0,
+			limiter_tlv),
+	SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L73_ALCMINMAX, 2, 7, 0,
+			limiter_tlv),
+
+	SOC_DOUBLE("NG Enable Switch", CS42L73_NGCAB, 6, 7, 1, 0),
+	SOC_SINGLE("NG Boost Switch", CS42L73_NGCAB, 5, 1, 0),
+	/*
+	    NG Threshold depends on NG_BOOTSAB, which selects
+	    between two threshold scales in decibels.
+	    Set linear values for now ..
+	*/
+	SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0),
+	SOC_ENUM("NG Delay", ng_delay_enum),
+
+	SOC_ENUM("Charge Pump Frequency", charge_pump_enum),
+
+	SOC_DOUBLE_R_TLV("XSP-IP Volume",
+			CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("XSP-XSP Volume",
+			CS42L73_XSPAXSPAA, CS42L73_XSPBXSPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("XSP-ASP Volume",
+			CS42L73_XSPAASPAA, CS42L73_XSPAASPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("XSP-VSP Volume",
+			CS42L73_XSPAVSPMA, CS42L73_XSPBVSPMA, 0, 0x3F, 1,
+			attn_tlv),
+
+	SOC_DOUBLE_R_TLV("ASP-IP Volume",
+			CS42L73_ASPAIPAA, CS42L73_ASPBIPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("ASP-XSP Volume",
+			CS42L73_ASPAXSPAA, CS42L73_ASPBXSPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("ASP-ASP Volume",
+			CS42L73_ASPAASPAA, CS42L73_ASPBASPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("ASP-VSP Volume",
+			CS42L73_ASPAVSPMA, CS42L73_ASPBVSPMA, 0, 0x3F, 1,
+			attn_tlv),
+
+	SOC_DOUBLE_R_TLV("VSP-IP Volume",
+			CS42L73_VSPAIPAA, CS42L73_VSPBIPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("VSP-XSP Volume",
+			CS42L73_VSPAXSPAA, CS42L73_VSPBXSPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("VSP-ASP Volume",
+			CS42L73_VSPAASPAA, CS42L73_VSPBASPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("VSP-VSP Volume",
+			CS42L73_VSPAVSPMA, CS42L73_VSPBVSPMA, 0, 0x3F, 1,
+			attn_tlv),
+
+	SOC_DOUBLE_R_TLV("HL-IP Volume",
+			CS42L73_HLAIPAA, CS42L73_HLBIPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("HL-XSP Volume",
+			CS42L73_HLAXSPAA, CS42L73_HLBXSPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("HL-ASP Volume",
+			CS42L73_HLAASPAA, CS42L73_HLBASPBA, 0, 0x3F, 1,
+			attn_tlv),
+	SOC_DOUBLE_R_TLV("HL-VSP Volume",
+			CS42L73_HLAVSPMA, CS42L73_HLBVSPMA, 0, 0x3F, 1,
+			attn_tlv),
+
+	SOC_SINGLE_TLV("SPK-IP Mono Volume",
+			CS42L73_SPKMIPMA, 0, 0x3E, 1, attn_tlv),
+	SOC_SINGLE_TLV("SPK-XSP Mono Volume",
+			CS42L73_SPKMXSPA, 0, 0x3E, 1, attn_tlv),
+	SOC_SINGLE_TLV("SPK-ASP Mono Volume",
+			CS42L73_SPKMASPA, 0, 0x3E, 1, attn_tlv),
+	SOC_SINGLE_TLV("SPK-VSP Mono Volume",
+			CS42L73_SPKMVSPMA, 0, 0x3E, 1, attn_tlv),
+
+	SOC_SINGLE_TLV("ESL-IP Mono Volume",
+			CS42L73_ESLMIPMA, 0, 0x3E, 1, attn_tlv),
+	SOC_SINGLE_TLV("ESL-XSP Mono Volume",
+			CS42L73_ESLMXSPA, 0, 0x3E, 1, attn_tlv),
+	SOC_SINGLE_TLV("ESL-ASP Mono Volume",
+			CS42L73_ESLMASPA, 0, 0x3E, 1, attn_tlv),
+	SOC_SINGLE_TLV("ESL-VSP Mono Volume",
+			CS42L73_ESLMVSPMA, 0, 0x3E, 1, attn_tlv),
+
+	SOC_ENUM("IP Digital Swap/Mono Select", ip_swap_enum),
+
+	SOC_ENUM("VSPOUT Mono/Stereo Select", vsp_output_mux_enum),
+	SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum),
+};
+
+static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("LINEINA"),
+	SND_SOC_DAPM_INPUT("LINEINB"),
+	SND_SOC_DAPM_INPUT("MIC1"),
+	SND_SOC_DAPM_SUPPLY("MIC1 Bias", CS42L73_PWRCTL2, 6, 1, NULL, 0),
+	SND_SOC_DAPM_INPUT("MIC2"),
+	SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS42L73_PWRCTL2, 7, 1, NULL, 0),
+
+	SND_SOC_DAPM_AIF_OUT("XSPOUTL", "XSP Capture",  0,
+			CS42L73_PWRCTL2, 1, 1),
+	SND_SOC_DAPM_AIF_OUT("XSPOUTR", "XSP Capture",  0,
+			CS42L73_PWRCTL2, 1, 1),
+	SND_SOC_DAPM_AIF_OUT("ASPOUTL", "ASP Capture",  0,
+			CS42L73_PWRCTL2, 3, 1),
+	SND_SOC_DAPM_AIF_OUT("ASPOUTR", "ASP Capture",  0,
+			CS42L73_PWRCTL2, 3, 1),
+	SND_SOC_DAPM_AIF_OUT("VSPOUTL", "VSP Capture",  0,
+			CS42L73_PWRCTL2, 4, 1),
+	SND_SOC_DAPM_AIF_OUT("VSPOUTR", "VSP Capture",  0,
+			CS42L73_PWRCTL2, 4, 1),
+
+	SND_SOC_DAPM_PGA("PGA Left", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("PGA Right", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("PGA Left Mux", SND_SOC_NOPM, 0, 0, &pgaa_mux),
+	SND_SOC_DAPM_MUX("PGA Right Mux", SND_SOC_NOPM, 0, 0, &pgab_mux),
+
+	SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L73_PWRCTL1, 7, 1),
+	SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L73_PWRCTL1, 5, 1),
+	SND_SOC_DAPM_ADC("DMIC Left", NULL, CS42L73_PWRCTL1, 6, 1),
+	SND_SOC_DAPM_ADC("DMIC Right", NULL, CS42L73_PWRCTL1, 4, 1),
+
+	SND_SOC_DAPM_MIXER_NAMED_CTL("Input Left Capture", SND_SOC_NOPM,
+			 0, 0, input_left_mixer,
+			 ARRAY_SIZE(input_left_mixer)),
+
+	SND_SOC_DAPM_MIXER_NAMED_CTL("Input Right Capture", SND_SOC_NOPM,
+			0, 0, input_right_mixer,
+			ARRAY_SIZE(input_right_mixer)),
+
+	SND_SOC_DAPM_MIXER("ASPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("ASPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("XSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("XSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("VSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("VSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_AIF_IN("XSPINL", "XSP Playback", 0,
+				CS42L73_PWRCTL2, 0, 1),
+	SND_SOC_DAPM_AIF_IN("XSPINR", "XSP Playback", 0,
+				CS42L73_PWRCTL2, 0, 1),
+	SND_SOC_DAPM_AIF_IN("XSPINM", "XSP Playback", 0,
+				CS42L73_PWRCTL2, 0, 1),
+
+	SND_SOC_DAPM_AIF_IN("ASPINL", "ASP Playback", 0,
+				CS42L73_PWRCTL2, 2, 1),
+	SND_SOC_DAPM_AIF_IN("ASPINR", "ASP Playback", 0,
+				CS42L73_PWRCTL2, 2, 1),
+	SND_SOC_DAPM_AIF_IN("ASPINM", "ASP Playback", 0,
+				CS42L73_PWRCTL2, 2, 1),
+
+	SND_SOC_DAPM_AIF_IN("VSPIN", "VSP Playback", 0,
+				CS42L73_PWRCTL2, 4, 1),
+
+	SND_SOC_DAPM_MIXER("HL Left Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("HL Right Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("ESL Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("ESL-XSP Mux", SND_SOC_NOPM,
+			 0, 0, &esl_xsp_mixer),
+
+	SND_SOC_DAPM_MUX("ESL-ASP Mux", SND_SOC_NOPM,
+			 0, 0, &esl_asp_mixer),
+
+	SND_SOC_DAPM_MUX("SPK-ASP Mux", SND_SOC_NOPM,
+			 0, 0, &spk_asp_mixer),
+
+	SND_SOC_DAPM_MUX("SPK-XSP Mux", SND_SOC_NOPM,
+			 0, 0, &spk_xsp_mixer),
+
+	SND_SOC_DAPM_PGA("HL Left DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("HL Right DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SWITCH("HP Amp", CS42L73_PWRCTL3, 0, 1,
+			    &hp_amp_ctl),
+	SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1,
+			    &lo_amp_ctl),
+	SND_SOC_DAPM_SWITCH("SPK Amp", CS42L73_PWRCTL3, 2, 1,
+			    &spk_amp_ctl),
+	SND_SOC_DAPM_SWITCH("EAR Amp", CS42L73_PWRCTL3, 3, 1,
+			    &ear_amp_ctl),
+	SND_SOC_DAPM_SWITCH("SPKLO Amp", CS42L73_PWRCTL3, 4, 1,
+			    &spklo_amp_ctl),
+
+	SND_SOC_DAPM_OUTPUT("HPOUTA"),
+	SND_SOC_DAPM_OUTPUT("HPOUTB"),
+	SND_SOC_DAPM_OUTPUT("LINEOUTA"),
+	SND_SOC_DAPM_OUTPUT("LINEOUTB"),
+	SND_SOC_DAPM_OUTPUT("EAROUT"),
+	SND_SOC_DAPM_OUTPUT("SPKOUT"),
+	SND_SOC_DAPM_OUTPUT("SPKLINEOUT"),
+};
+
+static const struct snd_soc_dapm_route cs42l73_audio_map[] = {
+
+	/* SPKLO EARSPK Paths */
+	{"EAROUT", NULL, "EAR Amp"},
+	{"SPKLINEOUT", NULL, "SPKLO Amp"},
+
+	{"EAR Amp", "Switch", "ESL DAC"},
+	{"SPKLO Amp", "Switch", "ESL DAC"},
+
+	{"ESL DAC", "ESL-ASP Mono Volume", "ESL Mixer"},
+	{"ESL DAC", "ESL-XSP Mono Volume", "ESL Mixer"},
+	{"ESL DAC", "ESL-VSP Mono Volume", "VSPIN"},
+	/* Loopback */
+	{"ESL DAC", "ESL-IP Mono Volume", "Input Left Capture"},
+	{"ESL DAC", "ESL-IP Mono Volume", "Input Right Capture"},
+
+	{"ESL Mixer", NULL, "ESL-ASP Mux"},
+	{"ESL Mixer", NULL, "ESL-XSP Mux"},
+
+	{"ESL-ASP Mux", "Left", "ASPINL"},
+	{"ESL-ASP Mux", "Right", "ASPINR"},
+	{"ESL-ASP Mux", "Mono Mix", "ASPINM"},
+
+	{"ESL-XSP Mux", "Left", "XSPINL"},
+	{"ESL-XSP Mux", "Right", "XSPINR"},
+	{"ESL-XSP Mux", "Mono Mix", "XSPINM"},
+
+	/* Speakerphone Paths */
+	{"SPKOUT", NULL, "SPK Amp"},
+	{"SPK Amp", "Switch", "SPK DAC"},
+
+	{"SPK DAC", "SPK-ASP Mono Volume", "SPK Mixer"},
+	{"SPK DAC", "SPK-XSP Mono Volume", "SPK Mixer"},
+	{"SPK DAC", "SPK-VSP Mono Volume", "VSPIN"},
+	/* Loopback */
+	{"SPK DAC", "SPK-IP Mono Volume", "Input Left Capture"},
+	{"SPK DAC", "SPK-IP Mono Volume", "Input Right Capture"},
+
+	{"SPK Mixer", NULL, "SPK-ASP Mux"},
+	{"SPK Mixer", NULL, "SPK-XSP Mux"},
+
+	{"SPK-ASP Mux", "Left", "ASPINL"},
+	{"SPK-ASP Mux", "Mono Mix", "ASPINM"},
+	{"SPK-ASP Mux", "Right", "ASPINR"},
+
+	{"SPK-XSP Mux", "Left", "XSPINL"},
+	{"SPK-XSP Mux", "Mono Mix", "XSPINM"},
+	{"SPK-XSP Mux", "Right", "XSPINR"},
+
+	/* HP LineOUT Paths */
+	{"HPOUTA", NULL, "HP Amp"},
+	{"HPOUTB", NULL, "HP Amp"},
+	{"LINEOUTA", NULL, "LO Amp"},
+	{"LINEOUTB", NULL, "LO Amp"},
+
+	{"HP Amp", "Switch", "HL Left DAC"},
+	{"HP Amp", "Switch", "HL Right DAC"},
+	{"LO Amp", "Switch", "HL Left DAC"},
+	{"LO Amp", "Switch", "HL Right DAC"},
+
+	{"HL Left DAC", "HL-XSP Volume", "HL Left Mixer"},
+	{"HL Right DAC", "HL-XSP Volume", "HL Right Mixer"},
+	{"HL Left DAC", "HL-ASP Volume", "HL Left Mixer"},
+	{"HL Right DAC", "HL-ASP Volume", "HL Right Mixer"},
+	{"HL Left DAC", "HL-VSP Volume", "HL Left Mixer"},
+	{"HL Right DAC", "HL-VSP Volume", "HL Right Mixer"},
+	/* Loopback */
+	{"HL Left DAC", "HL-IP Volume", "HL Left Mixer"},
+	{"HL Right DAC", "HL-IP Volume", "HL Right Mixer"},
+	{"HL Left Mixer", NULL, "Input Left Capture"},
+	{"HL Right Mixer", NULL, "Input Right Capture"},
+
+	{"HL Left Mixer", NULL, "ASPINL"},
+	{"HL Right Mixer", NULL, "ASPINR"},
+	{"HL Left Mixer", NULL, "XSPINL"},
+	{"HL Right Mixer", NULL, "XSPINR"},
+	{"HL Left Mixer", NULL, "VSPIN"},
+	{"HL Right Mixer", NULL, "VSPIN"},
+
+	/* Capture Paths */
+	{"MIC1", NULL, "MIC1 Bias"},
+	{"PGA Left Mux", "Mic 1", "MIC1"},
+	{"MIC2", NULL, "MIC2 Bias"},
+	{"PGA Right Mux", "Mic 2", "MIC2"},
+
+	{"PGA Left Mux", "Line A", "LINEINA"},
+	{"PGA Right Mux", "Line B", "LINEINB"},
+
+	{"PGA Left", NULL, "PGA Left Mux"},
+	{"PGA Right", NULL, "PGA Right Mux"},
+
+	{"ADC Left", NULL, "PGA Left"},
+	{"ADC Right", NULL, "PGA Right"},
+
+	{"Input Left Capture", "ADC Left Input", "ADC Left"},
+	{"Input Right Capture", "ADC Right Input", "ADC Right"},
+	{"Input Left Capture", "DMIC Left Input", "DMIC Left"},
+	{"Input Right Capture", "DMIC Right Input", "DMIC Right"},
+
+	/* Audio Capture */
+	{"ASPL Output Mixer", NULL, "Input Left Capture"},
+	{"ASPR Output Mixer", NULL, "Input Right Capture"},
+
+	{"ASPOUTL", "ASP-IP Volume", "ASPL Output Mixer"},
+	{"ASPOUTR", "ASP-IP Volume", "ASPR Output Mixer"},
+
+	/* Auxillary Capture */
+	{"XSPL Output Mixer", NULL, "Input Left Capture"},
+	{"XSPR Output Mixer", NULL, "Input Right Capture"},
+
+	{"XSPOUTL", "XSP-IP Volume", "XSPL Output Mixer"},
+	{"XSPOUTR", "XSP-IP Volume", "XSPR Output Mixer"},
+
+	{"XSPOUTL", NULL, "XSPL Output Mixer"},
+	{"XSPOUTR", NULL, "XSPR Output Mixer"},
+
+	/* Voice Capture */
+	{"VSPL Output Mixer", NULL, "Input Left Capture"},
+	{"VSPR Output Mixer", NULL, "Input Left Capture"},
+
+	{"VSPOUTL", "VSP-IP Volume", "VSPL Output Mixer"},
+	{"VSPOUTR", "VSP-IP Volume", "VSPR Output Mixer"},
+
+	{"VSPOUTL", NULL, "VSPL Output Mixer"},
+	{"VSPOUTR", NULL, "VSPR Output Mixer"},
+};
+
+struct cs42l73_mclk_div {
+	u32 mclk;
+	u32 srate;
+	u8 mmcc;
+};
+
+static struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = {
+	/* MCLK, Sample Rate, xMMCC[5:0] */
+	{5644800, 11025, 0x30},
+	{5644800, 22050, 0x20},
+	{5644800, 44100, 0x10},
+
+	{6000000,  8000, 0x39},
+	{6000000, 11025, 0x33},
+	{6000000, 12000, 0x31},
+	{6000000, 16000, 0x29},
+	{6000000, 22050, 0x23},
+	{6000000, 24000, 0x21},
+	{6000000, 32000, 0x19},
+	{6000000, 44100, 0x13},
+	{6000000, 48000, 0x11},
+
+	{6144000,  8000, 0x38},
+	{6144000, 12000, 0x30},
+	{6144000, 16000, 0x28},
+	{6144000, 24000, 0x20},
+	{6144000, 32000, 0x18},
+	{6144000, 48000, 0x10},
+
+	{6500000,  8000, 0x3C},
+	{6500000, 11025, 0x35},
+	{6500000, 12000, 0x34},
+	{6500000, 16000, 0x2C},
+	{6500000, 22050, 0x25},
+	{6500000, 24000, 0x24},
+	{6500000, 32000, 0x1C},
+	{6500000, 44100, 0x15},
+	{6500000, 48000, 0x14},
+
+	{6400000,  8000, 0x3E},
+	{6400000, 11025, 0x37},
+	{6400000, 12000, 0x36},
+	{6400000, 16000, 0x2E},
+	{6400000, 22050, 0x27},
+	{6400000, 24000, 0x26},
+	{6400000, 32000, 0x1E},
+	{6400000, 44100, 0x17},
+	{6400000, 48000, 0x16},
+};
+
+struct cs42l73_mclkx_div {
+	u32 mclkx;
+	u8 ratio;
+	u8 mclkdiv;
+};
+
+static struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = {
+	{5644800,  1, 0},	/* 5644800 */
+	{6000000,  1, 0},	/* 6000000 */
+	{6144000,  1, 0},	/* 6144000 */
+	{11289600, 2, 2},	/* 5644800 */
+	{12288000, 2, 2},	/* 6144000 */
+	{12000000, 2, 2},	/* 6000000 */
+	{13000000, 2, 2},	/* 6500000 */
+	{19200000, 3, 3},	/* 6400000 */
+	{24000000, 4, 4},	/* 6000000 */
+	{26000000, 4, 4},	/* 6500000 */
+	{38400000, 6, 5}	/* 6400000 */
+};
+
+static int cs42l73_get_mclkx_coeff(int mclkx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cs42l73_mclkx_coeffs); i++) {
+		if (cs42l73_mclkx_coeffs[i].mclkx == mclkx)
+			return i;
+	}
+	return -EINVAL;
+}
+
+static int cs42l73_get_mclk_coeff(int mclk, int srate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cs42l73_mclk_coeffs); i++) {
+		if (cs42l73_mclk_coeffs[i].mclk == mclk &&
+		    cs42l73_mclk_coeffs[i].srate == srate)
+			return i;
+	}
+	return -EINVAL;
+
+}
+
+static int cs42l73_set_mclk(struct snd_soc_dai *dai, unsigned int freq)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	int mclkx_coeff;
+	u32 mclk = 0;
+	u8 dmmcc = 0;
+
+	/* MCLKX -> MCLK */
+	mclkx_coeff = cs42l73_get_mclkx_coeff(freq);
+
+	mclk = cs42l73_mclkx_coeffs[mclkx_coeff].mclkx /
+		cs42l73_mclkx_coeffs[mclkx_coeff].ratio;
+
+	dev_dbg(codec->dev, "MCLK%u %u  <-> internal MCLK %u\n",
+		 priv->mclksel + 1, cs42l73_mclkx_coeffs[mclkx_coeff].mclkx,
+		 mclk);
+
+	dmmcc = (priv->mclksel << 4) |
+		(cs42l73_mclkx_coeffs[mclkx_coeff].mclkdiv << 1);
+
+	snd_soc_write(codec, CS42L73_DMMCC, dmmcc);
+
+	priv->sysclk = mclkx_coeff;
+	priv->mclk = mclk;
+
+	return 0;
+}
+
+static int cs42l73_set_sysclk(struct snd_soc_dai *dai,
+			      int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+
+	switch (clk_id) {
+	case CS42L73_CLKID_MCLK1:
+		break;
+	case CS42L73_CLKID_MCLK2:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if ((cs42l73_set_mclk(dai, freq)) < 0) {
+		dev_err(codec->dev, "Unable to set MCLK for dai %s\n",
+			dai->name);
+		return -EINVAL;
+	}
+
+	priv->mclksel = clk_id;
+
+	return 0;
+}
+
+static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+	u8 id = codec_dai->id;
+	unsigned int inv, format;
+	u8 spc, mmcc;
+
+	spc = snd_soc_read(codec, CS42L73_SPC(id));
+	mmcc = snd_soc_read(codec, CS42L73_MMCC(id));
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		mmcc |= MS_MASTER;
+		break;
+
+	case SND_SOC_DAIFMT_CBS_CFS:
+		mmcc &= ~MS_MASTER;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+	inv = (fmt & SND_SOC_DAIFMT_INV_MASK);
+
+	switch (format) {
+	case SND_SOC_DAIFMT_I2S:
+		spc &= ~SPDIF_PCM;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		if (mmcc & MS_MASTER) {
+			dev_err(codec->dev,
+				"PCM format in slave mode only\n");
+			return -EINVAL;
+		}
+		if (id == CS42L73_ASP) {
+			dev_err(codec->dev,
+				"PCM format is not supported on ASP port\n");
+			return -EINVAL;
+		}
+		spc |= SPDIF_PCM;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (spc & SPDIF_PCM) {
+		/* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */
+		spc &= ~(PCM_MODE_MASK | PCM_BIT_ORDER);
+		switch (format) {
+		case SND_SOC_DAIFMT_DSP_B:
+			if (inv == SND_SOC_DAIFMT_IB_IF)
+				spc |= PCM_MODE0;
+			if (inv == SND_SOC_DAIFMT_IB_NF)
+				spc |= PCM_MODE1;
+		break;
+		case SND_SOC_DAIFMT_DSP_A:
+			if (inv == SND_SOC_DAIFMT_IB_IF)
+				spc |= PCM_MODE1;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	priv->config[id].spc = spc;
+	priv->config[id].mmcc = mmcc;
+
+	return 0;
+}
+
+static u32 cs42l73_asrc_rates[] = {
+	8000, 11025, 12000, 16000, 22050,
+	24000, 32000, 44100, 48000
+};
+
+static unsigned int cs42l73_get_xspfs_coeff(u32 rate)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(cs42l73_asrc_rates); i++) {
+		if (cs42l73_asrc_rates[i] == rate)
+			return i + 1;
+	}
+	return 0;		/* 0 = Don't know */
+}
+
+static void cs42l73_update_asrc(struct snd_soc_codec *codec, int id, int srate)
+{
+	u8 spfs = 0;
+
+	if (srate > 0)
+		spfs = cs42l73_get_xspfs_coeff(srate);
+
+	switch (id) {
+	case CS42L73_XSP:
+		snd_soc_update_bits(codec, CS42L73_VXSPFS, 0x0f, spfs);
+	break;
+	case CS42L73_ASP:
+		snd_soc_update_bits(codec, CS42L73_ASPC, 0x3c, spfs << 2);
+	break;
+	case CS42L73_VSP:
+		snd_soc_update_bits(codec, CS42L73_VXSPFS, 0xf0, spfs << 4);
+	break;
+	default:
+	break;
+	}
+}
+
+static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *params,
+				 struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+	int id = dai->id;
+	int mclk_coeff;
+	int srate = params_rate(params);
+
+	if (priv->config[id].mmcc & MS_MASTER) {
+		/* CS42L73 Master */
+		/* MCLK -> srate */
+		mclk_coeff =
+		    cs42l73_get_mclk_coeff(priv->mclk, srate);
+
+		if (mclk_coeff < 0)
+			return -EINVAL;
+
+		dev_dbg(codec->dev,
+			 "DAI[%d]: MCLK %u, srate %u, MMCC[5:0] = %x\n",
+			 id, priv->mclk, srate,
+			 cs42l73_mclk_coeffs[mclk_coeff].mmcc);
+
+		priv->config[id].mmcc &= 0xC0;
+		priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
+		priv->config[id].spc &= 0xFC;
+		priv->config[id].spc &= MCK_SCLK_64FS;
+	} else {
+		/* CS42L73 Slave */
+		priv->config[id].spc &= 0xFC;
+		priv->config[id].spc |= MCK_SCLK_64FS;
+	}
+	/* Update ASRCs */
+	priv->config[id].srate = srate;
+
+	snd_soc_write(codec, CS42L73_SPC(id), priv->config[id].spc);
+	snd_soc_write(codec, CS42L73_MMCC(id), priv->config[id].mmcc);
+
+	cs42l73_update_asrc(codec, id, srate);
+
+	return 0;
+}
+
+static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 0);
+		snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 0);
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			regcache_cache_only(cs42l73->regmap, false);
+			regcache_sync(cs42l73->regmap);
+		}
+		snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
+		snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1);
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	int id = dai->id;
+
+	return snd_soc_update_bits(codec, CS42L73_SPC(id),
+					0x7F, tristate << 7);
+}
+
+static struct snd_pcm_hw_constraint_list constraints_12_24 = {
+	.count  = ARRAY_SIZE(cs42l73_asrc_rates),
+	.list   = cs42l73_asrc_rates,
+};
+
+static int cs42l73_pcm_startup(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	snd_pcm_hw_constraint_list(substream->runtime, 0,
+					SNDRV_PCM_HW_PARAM_RATE,
+					&constraints_12_24);
+	return 0;
+}
+
+/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */
+#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT)
+
+
+#define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+	SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops cs42l73_ops = {
+	.startup = cs42l73_pcm_startup,
+	.hw_params = cs42l73_pcm_hw_params,
+	.set_fmt = cs42l73_set_dai_fmt,
+	.set_sysclk = cs42l73_set_sysclk,
+	.set_tristate = cs42l73_set_tristate,
+};
+
+static struct snd_soc_dai_driver cs42l73_dai[] = {
+	{
+		.name = "cs42l73-xsp",
+		.id = CS42L73_XSP,
+		.playback = {
+			.stream_name = "XSP Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS42L73_RATES,
+			.formats = CS42L73_FORMATS,
+		},
+		.capture = {
+			.stream_name = "XSP Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS42L73_RATES,
+			.formats = CS42L73_FORMATS,
+		},
+		.ops = &cs42l73_ops,
+		.symmetric_rates = 1,
+	 },
+	{
+		.name = "cs42l73-asp",
+		.id = CS42L73_ASP,
+		.playback = {
+			.stream_name = "ASP Playback",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = CS42L73_RATES,
+			.formats = CS42L73_FORMATS,
+		},
+		.capture = {
+			.stream_name = "ASP Capture",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = CS42L73_RATES,
+			.formats = CS42L73_FORMATS,
+		},
+		.ops = &cs42l73_ops,
+		.symmetric_rates = 1,
+	 },
+	{
+		.name = "cs42l73-vsp",
+		.id = CS42L73_VSP,
+		.playback = {
+			.stream_name = "VSP Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS42L73_RATES,
+			.formats = CS42L73_FORMATS,
+		},
+		.capture = {
+			.stream_name = "VSP Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS42L73_RATES,
+			.formats = CS42L73_FORMATS,
+		},
+		.ops = &cs42l73_ops,
+		.symmetric_rates = 1,
+	 }
+};
+
+static int cs42l73_suspend(struct snd_soc_codec *codec)
+{
+	cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+static int cs42l73_resume(struct snd_soc_codec *codec)
+{
+	cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+
+static int cs42l73_probe(struct snd_soc_codec *codec)
+{
+	int ret;
+	struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
+
+	codec->control_data = cs42l73->regmap;
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	regcache_cache_only(cs42l73->regmap, true);
+
+	cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	cs42l73->mclksel = CS42L73_CLKID_MCLK1;	/* MCLK1 as master clk */
+	cs42l73->mclk = 0;
+
+	return ret;
+}
+
+static int cs42l73_remove(struct snd_soc_codec *codec)
+{
+	cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
+	.probe = cs42l73_probe,
+	.remove = cs42l73_remove,
+	.suspend = cs42l73_suspend,
+	.resume = cs42l73_resume,
+	.set_bias_level = cs42l73_set_bias_level,
+
+	.dapm_widgets = cs42l73_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets),
+	.dapm_routes = cs42l73_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map),
+
+	.controls = cs42l73_snd_controls,
+	.num_controls = ARRAY_SIZE(cs42l73_snd_controls),
+};
+
+static struct regmap_config cs42l73_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = CS42L73_MAX_REGISTER,
+	.reg_defaults = cs42l73_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(cs42l73_reg_defaults),
+	.volatile_reg = cs42l73_volatile_register,
+	.readable_reg = cs42l73_readable_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
+				       const struct i2c_device_id *id)
+{
+	struct cs42l73_private *cs42l73;
+	int ret;
+	unsigned int devid = 0;
+	unsigned int reg;
+
+	cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
+			       GFP_KERNEL);
+	if (!cs42l73) {
+		dev_err(&i2c_client->dev, "could not allocate codec\n");
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(i2c_client, cs42l73);
+
+	cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap);
+	if (IS_ERR(cs42l73->regmap)) {
+		ret = PTR_ERR(cs42l73->regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		goto err;
+	}
+	/* initialize codec */
+	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
+	devid = (reg & 0xFF) << 12;
+
+	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_CD, &reg);
+	devid |= (reg & 0xFF) << 4;
+
+	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, &reg);
+	devid |= (reg & 0xF0) >> 4;
+
+
+	if (devid != CS42L73_DEVID) {
+		ret = -ENODEV;
+		dev_err(&i2c_client->dev,
+			"CS42L73 Device ID (%X). Expected %X\n",
+			devid, CS42L73_DEVID);
+		goto err_regmap;
+	}
+
+	ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
+	if (ret < 0) {
+		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
+		goto err_regmap;
+	}
+
+	dev_info(&i2c_client->dev,
+		 "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);
+
+	regcache_cache_only(cs42l73->regmap, true);
+
+	ret =  snd_soc_register_codec(&i2c_client->dev,
+			&soc_codec_dev_cs42l73, cs42l73_dai,
+			ARRAY_SIZE(cs42l73_dai));
+	if (ret < 0)
+		goto err_regmap;
+	return 0;
+
+err_regmap:
+	regmap_exit(cs42l73->regmap);
+
+err:
+	return ret;
+}
+
+static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
+{
+	struct cs42l73_private *cs42l73 = i2c_get_clientdata(client);
+
+	snd_soc_unregister_codec(&client->dev);
+	regmap_exit(cs42l73->regmap);
+
+	return 0;
+}
+
+static const struct i2c_device_id cs42l73_id[] = {
+	{"cs42l73", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, cs42l73_id);
+
+static struct i2c_driver cs42l73_i2c_driver = {
+	.driver = {
+		   .name = "cs42l73",
+		   .owner = THIS_MODULE,
+		   },
+	.id_table = cs42l73_id,
+	.probe = cs42l73_i2c_probe,
+	.remove = __devexit_p(cs42l73_i2c_remove),
+
+};
+
+static int __init cs42l73_modinit(void)
+{
+	int ret;
+	ret = i2c_add_driver(&cs42l73_i2c_driver);
+	if (ret != 0) {
+		pr_err("Failed to register CS42L73 I2C driver: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+module_init(cs42l73_modinit);
+
+static void __exit cs42l73_exit(void)
+{
+	i2c_del_driver(&cs42l73_i2c_driver);
+}
+
+module_exit(cs42l73_exit);
+
+MODULE_DESCRIPTION("ASoC CS42L73 driver");
+MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
+MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l73.h b/sound/soc/codecs/cs42l73.h
new file mode 100644
index 0000000..f30a4c4
--- /dev/null
+++ b/sound/soc/codecs/cs42l73.h
@@ -0,0 +1,227 @@
+/*
+ * ALSA SoC CS42L73 codec driver
+ *
+ * Copyright 2011 Cirrus Logic, Inc.
+ *
+ * Author: Georgi Vlaev <joe@nucleusys.com>
+ *	   Brian Austin <brian.austin@cirrus.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 __CS42L73_H__
+#define __CS42L73_H__
+
+/* I2C Registers */
+/* I2C Address: 1001010[R/W] - 10010100 = 0x94(Write); 10010101 = 0x95(Read) */
+#define CS42L73_CHIP_ID		0x4a
+#define CS42L73_DEVID_AB	0x01	/* Device ID A & B [RO]. */
+#define CS42L73_DEVID_CD	0x02    /* Device ID C & D [RO]. */
+#define CS42L73_DEVID_E		0x03    /* Device ID E [RO]. */
+#define CS42L73_REVID		0x05    /* Revision ID [RO]. */
+#define CS42L73_PWRCTL1		0x06    /* Power Control 1. */
+#define CS42L73_PWRCTL2		0x07    /* Power Control 2. */
+#define CS42L73_PWRCTL3		0x08    /* Power Control 3. */
+#define CS42L73_CPFCHC		0x09    /* Charge Pump Freq. Class H Ctl. */
+#define CS42L73_OLMBMSDC	0x0A    /* Output Load, MIC Bias, MIC2 SDT */
+#define CS42L73_DMMCC		0x0B    /* Digital MIC & Master Clock Ctl. */
+#define CS42L73_XSPC		0x0C    /* Auxiliary Serial Port (XSP) Ctl. */
+#define CS42L73_XSPMMCC		0x0D    /* XSP Master Mode Clocking Control. */
+#define CS42L73_ASPC		0x0E    /* Audio Serial Port (ASP) Control. */
+#define CS42L73_ASPMMCC		0x0F    /* ASP Master Mode Clocking Control. */
+#define CS42L73_VSPC		0x10    /* Voice Serial Port (VSP) Control. */
+#define CS42L73_VSPMMCC		0x11    /* VSP Master Mode Clocking Control. */
+#define CS42L73_VXSPFS		0x12    /* VSP & XSP Sample Rate. */
+#define CS42L73_MIOPC		0x13    /* Misc. Input & Output Path Control. */
+#define CS42L73_ADCIPC		0x14	/* ADC/IP Control. */
+#define CS42L73_MICAPREPGAAVOL	0x15	/* MIC 1 [A] PreAmp, PGAA Vol. */
+#define CS42L73_MICBPREPGABVOL	0x16	/* MIC 2 [B] PreAmp, PGAB Vol. */
+#define CS42L73_IPADVOL		0x17	/* Input Pat7h A Digital Volume. */
+#define CS42L73_IPBDVOL		0x18	/* Input Path B Digital Volume. */
+#define CS42L73_PBDC		0x19	/* Playback Digital Control. */
+#define CS42L73_HLADVOL		0x1A	/* HP/Line A Out Digital Vol. */
+#define CS42L73_HLBDVOL		0x1B	/* HP/Line B Out Digital Vol. */
+#define CS42L73_SPKDVOL		0x1C	/* Spkphone Out [A] Digital Vol. */
+#define CS42L73_ESLDVOL		0x1D	/* Ear/Spkphone LO [B] Digital */
+#define CS42L73_HPAAVOL		0x1E	/* HP A Analog Volume. */
+#define CS42L73_HPBAVOL		0x1F	/* HP B Analog Volume. */
+#define CS42L73_LOAAVOL		0x20	/* Line Out A Analog Volume. */
+#define CS42L73_LOBAVOL		0x21	/* Line Out B Analog Volume. */
+#define CS42L73_STRINV		0x22	/* Stereo Input Path Adv. Vol. */
+#define CS42L73_XSPINV		0x23	/* Auxiliary Port Input Advisory Vol. */
+#define CS42L73_ASPINV		0x24	/* Audio Port Input Advisory Vol. */
+#define CS42L73_VSPINV		0x25	/* Voice Port Input Advisory Vol. */
+#define CS42L73_LIMARATEHL	0x26	/* Lmtr Attack Rate HP/Line. */
+#define CS42L73_LIMRRATEHL	0x27	/* Lmtr Ctl, Rel.Rate HP/Line. */
+#define CS42L73_LMAXHL		0x28	/* Lmtr Thresholds HP/Line. */
+#define CS42L73_LIMARATESPK	0x29	/* Lmtr Attack Rate Spkphone [A]. */
+#define CS42L73_LIMRRATESPK	0x2A	/* Lmtr Ctl,Release Rate Spk. [A]. */
+#define CS42L73_LMAXSPK		0x2B	/* Lmtr Thresholds Spkphone [A]. */
+#define CS42L73_LIMARATEESL	0x2C	/* Lmtr Attack Rate  */
+#define CS42L73_LIMRRATEESL	0x2D	/* Lmtr Ctl,Release Rate */
+#define CS42L73_LMAXESL		0x2E	/* Lmtr Thresholds */
+#define CS42L73_ALCARATE	0x2F	/* ALC Enable, Attack Rate AB. */
+#define CS42L73_ALCRRATE	0x30	/* ALC Release Rate AB.  */
+#define CS42L73_ALCMINMAX	0x31	/* ALC Thresholds AB. */
+#define CS42L73_NGCAB		0x32	/* Noise Gate Ctl AB. */
+#define CS42L73_ALCNGMC		0x33	/* ALC & Noise Gate Misc Ctl. */
+#define CS42L73_MIXERCTL	0x34	/* Mixer Control. */
+#define CS42L73_HLAIPAA		0x35	/* HP/LO Left Mixer: L. */
+#define CS42L73_HLBIPBA		0x36	/* HP/LO Right Mixer: R.  */
+#define CS42L73_HLAXSPAA	0x37	/* HP/LO Left Mixer: XSP L */
+#define CS42L73_HLBXSPBA	0x38	/* HP/LO Right Mixer: XSP R */
+#define CS42L73_HLAASPAA	0x39	/* HP/LO Left Mixer: ASP L */
+#define CS42L73_HLBASPBA	0x3A	/* HP/LO Right Mixer: ASP R */
+#define CS42L73_HLAVSPMA	0x3B	/* HP/LO Left Mixer: VSP. */
+#define CS42L73_HLBVSPMA	0x3C	/* HP/LO Right Mixer: VSP */
+#define CS42L73_XSPAIPAA	0x3D	/* XSP Left Mixer: Left */
+#define CS42L73_XSPBIPBA	0x3E	/* XSP Rt. Mixer: Right */
+#define CS42L73_XSPAXSPAA	0x3F	/* XSP Left Mixer: XSP L */
+#define CS42L73_XSPBXSPBA	0x40	/* XSP Rt. Mixer: XSP R */
+#define CS42L73_XSPAASPAA	0x41	/* XSP Left Mixer: ASP L */
+#define CS42L73_XSPAASPBA	0x42	/* XSP Rt. Mixer: ASP R */
+#define CS42L73_XSPAVSPMA	0x43	/* XSP Left Mixer: VSP */
+#define CS42L73_XSPBVSPMA	0x44	/* XSP Rt. Mixer: VSP */
+#define CS42L73_ASPAIPAA	0x45	/* ASP Left Mixer: Left */
+#define CS42L73_ASPBIPBA	0x46	/* ASP Rt. Mixer: Right */
+#define CS42L73_ASPAXSPAA	0x47	/* ASP Left Mixer: XSP L */
+#define CS42L73_ASPBXSPBA	0x48	/* ASP Rt. Mixer: XSP R */
+#define CS42L73_ASPAASPAA	0x49	/* ASP Left Mixer: ASP L */
+#define CS42L73_ASPBASPBA	0x4A	/* ASP Rt. Mixer: ASP R */
+#define CS42L73_ASPAVSPMA	0x4B	/* ASP Left Mixer: VSP */
+#define CS42L73_ASPBVSPMA	0x4C	/* ASP Rt. Mixer: VSP */
+#define CS42L73_VSPAIPAA	0x4D	/* VSP Left Mixer: Left */
+#define CS42L73_VSPBIPBA	0x4E	/* VSP Rt. Mixer: Right */
+#define CS42L73_VSPAXSPAA	0x4F	/* VSP Left Mixer: XSP L */
+#define CS42L73_VSPBXSPBA	0x50	/* VSP Rt. Mixer: XSP R */
+#define CS42L73_VSPAASPAA	0x51	/* VSP Left Mixer: ASP Left */
+#define CS42L73_VSPBASPBA	0x52	/* VSP Rt. Mixer: ASP Right */
+#define CS42L73_VSPAVSPMA	0x53	/* VSP Left Mixer: VSP */
+#define CS42L73_VSPBVSPMA	0x54	/* VSP Rt. Mixer: VSP */
+#define CS42L73_MMIXCTL		0x55	/* Mono Mixer Controls. */
+#define CS42L73_SPKMIPMA	0x56	/* SPK Mono Mixer: In. Path */
+#define CS42L73_SPKMXSPA	0x57	/* SPK Mono Mixer: XSP Mono/L/R Att. */
+#define CS42L73_SPKMASPA	0x58	/* SPK Mono Mixer: ASP Mono/L/R Att. */
+#define CS42L73_SPKMVSPMA	0x59	/* SPK Mono Mixer: VSP Mono Atten. */
+#define CS42L73_ESLMIPMA	0x5A	/* Ear/SpLO Mono Mixer: */
+#define CS42L73_ESLMXSPA	0x5B	/* Ear/SpLO Mono Mixer: XSP */
+#define CS42L73_ESLMASPA	0x5C	/* Ear/SpLO Mono Mixer: ASP */
+#define CS42L73_ESLMVSPMA	0x5D	/* Ear/SpLO Mono Mixer: VSP */
+#define CS42L73_IM1		0x5E	/* Interrupt Mask 1.  */
+#define CS42L73_IM2		0x5F	/* Interrupt Mask 2. */
+#define CS42L73_IS1		0x60	/* Interrupt Status 1 [RO]. */
+#define CS42L73_IS2		0x61	/* Interrupt Status 2 [RO]. */
+#define CS42L73_MAX_REGISTER	0x61	/* Total Registers */
+/* Bitfield Definitions */
+
+/* CS42L73_PWRCTL1 */
+#define PDN_ADCB		(1 << 7)
+#define PDN_DMICB		(1 << 6)
+#define PDN_ADCA		(1 << 5)
+#define PDN_DMICA		(1 << 4)
+#define PDN_LDO			(1 << 2)
+#define DISCHG_FILT		(1 << 1)
+#define PDN			(1 << 0)
+
+/* CS42L73_PWRCTL2 */
+#define PDN_MIC2_BIAS		(1 << 7)
+#define PDN_MIC1_BIAS		(1 << 6)
+#define PDN_VSP			(1 << 4)
+#define PDN_ASP_SDOUT		(1 << 3)
+#define PDN_ASP_SDIN		(1 << 2)
+#define PDN_XSP_SDOUT		(1 << 1)
+#define PDN_XSP_SDIN		(1 << 0)
+
+/* CS42L73_PWRCTL3 */
+#define PDN_THMS		(1 << 5)
+#define PDN_SPKLO		(1 << 4)
+#define PDN_EAR			(1 << 3)
+#define PDN_SPK			(1 << 2)
+#define PDN_LO			(1 << 1)
+#define PDN_HP			(1 << 0)
+
+/* Thermal Overload Detect. Requires interrupt ... */
+#define THMOVLD_150C		0
+#define THMOVLD_132C		1
+#define THMOVLD_115C		2
+#define THMOVLD_098C		3
+
+
+/* CS42L73_ASPC, CS42L73_XSPC, CS42L73_VSPC */
+#define	SP_3ST			(1 << 7)
+#define SPDIF_I2S		(0 << 6)
+#define SPDIF_PCM		(1 << 6)
+#define PCM_MODE0		(0 << 4)
+#define PCM_MODE1		(1 << 4)
+#define PCM_MODE2		(2 << 4)
+#define PCM_MODE_MASK		(3 << 4)
+#define PCM_BIT_ORDER		(1 << 3)
+#define MCK_SCLK_64FS		(0 << 0)
+#define MCK_SCLK_MCLK		(2 << 0)
+#define MCK_SCLK_PREMCLK	(3 << 0)
+
+/* CS42L73_xSPMMCC */
+#define MS_MASTER		(1 << 7)
+
+
+/* CS42L73_DMMCC */
+#define MCLKDIS			(1 << 0)
+#define MCLKSEL_MCLK2		(1 << 4)
+#define MCLKSEL_MCLK1		(0 << 4)
+
+/* CS42L73 MCLK derived from MCLK1 or MCLK2 */
+#define CS42L73_CLKID_MCLK1     0
+#define CS42L73_CLKID_MCLK2     1
+
+#define CS42L73_MCLKXDIV	0
+#define CS42L73_MMCCDIV         1
+
+#define CS42L73_XSP		0
+#define CS42L73_ASP		1
+#define CS42L73_VSP		2
+
+/* IS1, IM1 */
+#define MIC2_SDET		(1 << 6)
+#define THMOVLD			(1 << 4)
+#define DIGMIXOVFL		(1 << 3)
+#define IPBOVFL			(1 << 1)
+#define IPAOVFL			(1 << 0)
+
+/* Analog Softramp */
+#define ANLGOSFT		(1 << 0)
+
+/* HP A/B Analog Mute */
+#define HPA_MUTE		(1 << 7)
+/* LO A/B Analog Mute	*/
+#define LOA_MUTE		(1 << 7)
+/* Digital Mute */
+#define HLAD_MUTE		(1 << 0)
+#define HLBD_MUTE		(1 << 1)
+#define SPKD_MUTE		(1 << 2)
+#define ESLD_MUTE		(1 << 3)
+
+/* Misc defines for codec */
+#define CS42L73_RESET_GPIO 143
+
+#define CS42L73_DEVID		0x00042A73
+#define CS42L73_MCLKX_MIN	5644800
+#define CS42L73_MCLKX_MAX	38400000
+
+#define CS42L73_SPC(id)		(CS42L73_XSPC + (id << 1))
+#define CS42L73_MMCC(id)	(CS42L73_XSPMMCC + (id << 1))
+#define CS42L73_SPFS(id)	((id == CS42L73_ASP) ? CS42L73_ASPC : CS42L73_VXSPFS)
+
+#endif	/* __CS42L73_H__ */
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index bc7067d..ae55e31 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -391,17 +391,7 @@
 	.remove = __exit_p(cx20442_platform_remove),
 };
 
-static int __init cx20442_init(void)
-{
-	return platform_driver_register(&cx20442_platform_driver);
-}
-module_init(cx20442_init);
-
-static void __exit cx20442_exit(void)
-{
-	platform_driver_unregister(&cx20442_platform_driver);
-}
-module_exit(cx20442_exit);
+module_platform_driver(cx20442_platform_driver);
 
 MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
 MODULE_AUTHOR("Janusz Krzysztofik");
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index b545b7d..e4ca61c 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -17,7 +17,6 @@
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <sound/pcm.h>
@@ -240,7 +239,7 @@
 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[] = {
+static const char * const da7210_hpf_cutoff_txt[] = {
 	"Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi"
 };
 
@@ -251,7 +250,7 @@
 	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[] = {
+static const char * const da7210_vf_cutoff_txt[] = {
 	"2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
 };
 
@@ -761,7 +760,7 @@
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 /* DAI operations */
-static struct snd_soc_dai_ops da7210_dai_ops = {
+static const struct snd_soc_dai_ops da7210_dai_ops = {
 	.hw_params	= da7210_hw_params,
 	.set_fmt	= da7210_set_dai_fmt,
 	.digital_mute	= da7210_mute,
diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/dfbmcs320.c
index 704bbde..bfe46aa 100644
--- a/sound/soc/codecs/dfbmcs320.c
+++ b/sound/soc/codecs/dfbmcs320.c
@@ -55,17 +55,7 @@
 	.remove = __devexit_p(dfbmcs320_remove),
 };
 
-static int __init dfbmcs320_init(void)
-{
-	return platform_driver_register(&dfmcs320_driver);
-}
-module_init(dfbmcs320_init);
-
-static void __exit dfbmcs320_exit(void)
-{
-	platform_driver_unregister(&dfmcs320_driver);
-}
-module_exit(dfbmcs320_exit);
+module_platform_driver(dfmcs320_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver");
diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c
index 6fae765..3e929f0 100644
--- a/sound/soc/codecs/dmic.c
+++ b/sound/soc/codecs/dmic.c
@@ -89,17 +89,7 @@
 	.remove = __devexit_p(dmic_dev_remove),
 };
 
-static int __init dmic_init(void)
-{
-	return platform_driver_register(&dmic_driver);
-}
-module_init(dmic_init);
-
-static void __exit dmic_exit(void)
-{
-	platform_driver_unregister(&dmic_driver);
-}
-module_exit(dmic_exit);
+module_platform_driver(dmic_driver);
 
 MODULE_DESCRIPTION("Generic DMIC driver");
 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index e373f8f..517e2a5 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -206,7 +206,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
+static const struct snd_soc_dai_ops jz4740_codec_dai_ops = {
 	.hw_params = jz4740_codec_hw_params,
 };
 
@@ -311,7 +311,7 @@
 
 #ifdef CONFIG_PM_SLEEP
 
-static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int jz4740_codec_suspend(struct snd_soc_codec *codec)
 {
 	return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
@@ -424,17 +424,7 @@
 	},
 };
 
-static int __init jz4740_codec_init(void)
-{
-	return platform_driver_register(&jz4740_codec_driver);
-}
-module_init(jz4740_codec_init);
-
-static void __exit jz4740_codec_exit(void)
-{
-	platform_driver_unregister(&jz4740_codec_driver);
-}
-module_exit(jz4740_codec_exit);
+module_platform_driver(jz4740_codec_driver);
 
 MODULE_DESCRIPTION("JZ4740 SoC internal codec driver");
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index ebbf63c..ba4f6f1 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -1650,14 +1649,14 @@
 #define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
 #define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops max98088_dai1_ops = {
+static const struct snd_soc_dai_ops max98088_dai1_ops = {
        .set_sysclk = max98088_dai_set_sysclk,
        .set_fmt = max98088_dai1_set_fmt,
        .hw_params = max98088_dai1_hw_params,
        .digital_mute = max98088_dai1_digital_mute,
 };
 
-static struct snd_soc_dai_ops max98088_dai2_ops = {
+static const struct snd_soc_dai_ops max98088_dai2_ops = {
        .set_sysclk = max98088_dai_set_sysclk,
        .set_fmt = max98088_dai2_set_fmt,
        .hw_params = max98088_dai2_hw_params,
@@ -1947,7 +1946,7 @@
 }
 
 #ifdef CONFIG_PM
-static int max98088_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max98088_suspend(struct snd_soc_codec *codec)
 {
        max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 26d7b08..c69dd02 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -1782,19 +1781,19 @@
 #define MAX98095_RATES SNDRV_PCM_RATE_8000_96000
 #define MAX98095_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops max98095_dai1_ops = {
+static const struct snd_soc_dai_ops max98095_dai1_ops = {
 	.set_sysclk = max98095_dai_set_sysclk,
 	.set_fmt = max98095_dai1_set_fmt,
 	.hw_params = max98095_dai1_hw_params,
 };
 
-static struct snd_soc_dai_ops max98095_dai2_ops = {
+static const struct snd_soc_dai_ops max98095_dai2_ops = {
 	.set_sysclk = max98095_dai_set_sysclk,
 	.set_fmt = max98095_dai2_set_fmt,
 	.hw_params = max98095_dai2_hw_params,
 };
 
-static struct snd_soc_dai_ops max98095_dai3_ops = {
+static const struct snd_soc_dai_ops max98095_dai3_ops = {
 	.set_sysclk = max98095_dai_set_sysclk,
 	.set_fmt = max98095_dai3_set_fmt,
 	.hw_params = max98095_dai3_hw_params,
@@ -2175,7 +2174,7 @@
 }
 
 #ifdef CONFIG_PM
-static int max98095_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max98095_suspend(struct snd_soc_codec *codec)
 {
 	max98095_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index 208d2ee..7dfd6e8 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -254,7 +254,7 @@
 #define MAX9850_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops max9850_dai_ops = {
+static const struct snd_soc_dai_ops max9850_dai_ops = {
 	.hw_params	= max9850_hw_params,
 	.set_sysclk	= max9850_set_dai_sysclk,
 	.set_fmt	= max9850_set_dai_fmt,
@@ -273,7 +273,7 @@
 };
 
 #ifdef CONFIG_PM
-static int max9850_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max9850_suspend(struct snd_soc_codec *codec)
 {
 	max9850_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index f731651..edcaa7e 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -118,7 +118,7 @@
 }
 
 #ifdef CONFIG_PM
-static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
 {
 	struct pcm3008_setup_data *setup = codec->dev->platform_data;
 
@@ -172,17 +172,7 @@
 	},
 };
 
-static int __init pcm3008_modinit(void)
-{
-	return platform_driver_register(&pcm3008_codec_driver);
-}
-module_init(pcm3008_modinit);
-
-static void __exit pcm3008_exit(void)
-{
-	platform_driver_unregister(&pcm3008_codec_driver);
-}
-module_exit(pcm3008_exit);
+module_platform_driver(pcm3008_codec_driver);
 
 MODULE_DESCRIPTION("Soc PCM3008 driver");
 MODULE_AUTHOR("Hugo Villeneuve");
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 4646e80..f6e4f5e 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -18,7 +18,6 @@
 #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>
@@ -1642,7 +1641,7 @@
 }
 
 #ifdef CONFIG_PM
-static int rt5631_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int rt5631_suspend(struct snd_soc_codec *codec)
 {
 	rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -1664,7 +1663,7 @@
 			SNDRV_PCM_FMTBIT_S24_LE | \
 			SNDRV_PCM_FMTBIT_S8)
 
-static struct snd_soc_dai_ops rt5631_ops = {
+static const 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,
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index bbcf921..2501757 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -16,7 +16,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/clk.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
@@ -923,7 +922,7 @@
 			SNDRV_PCM_FMTBIT_S24_LE |\
 			SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops sgtl5000_ops = {
+static const struct snd_soc_dai_ops sgtl5000_ops = {
 	.hw_params = sgtl5000_pcm_hw_params,
 	.digital_mute = sgtl5000_digital_mute,
 	.set_fmt = sgtl5000_set_dai_fmt,
@@ -968,7 +967,7 @@
 }
 
 #ifdef CONFIG_SUSPEND
-static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int sgtl5000_suspend(struct snd_soc_codec *codec)
 {
 	sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
new file mode 100644
index 0000000..5be42bf
--- /dev/null
+++ b/sound/soc/codecs/sigmadsp.c
@@ -0,0 +1,246 @@
+/*
+ * Load Analog Devices SigmaStudio firmware files
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/module.h>
+
+#include "sigmadsp.h"
+
+#define SIGMA_MAGIC "ADISIGM"
+
+struct sigma_firmware_header {
+	unsigned char magic[7];
+	u8 version;
+	__le32 crc;
+} __packed;
+
+enum {
+	SIGMA_ACTION_WRITEXBYTES = 0,
+	SIGMA_ACTION_WRITESINGLE,
+	SIGMA_ACTION_WRITESAFELOAD,
+	SIGMA_ACTION_DELAY,
+	SIGMA_ACTION_PLLWAIT,
+	SIGMA_ACTION_NOOP,
+	SIGMA_ACTION_END,
+};
+
+struct sigma_action {
+	u8 instr;
+	u8 len_hi;
+	__le16 len;
+	__be16 addr;
+	unsigned char payload[];
+} __packed;
+
+struct sigma_firmware {
+	const struct firmware *fw;
+	size_t pos;
+
+	void *control_data;
+	int (*write)(void *control_data, const struct sigma_action *sa,
+			size_t len);
+};
+
+static inline u32 sigma_action_len(struct sigma_action *sa)
+{
+	return (sa->len_hi << 16) | le16_to_cpu(sa->len);
+}
+
+static size_t sigma_action_size(struct sigma_action *sa)
+{
+	size_t payload = 0;
+
+	switch (sa->instr) {
+	case SIGMA_ACTION_WRITEXBYTES:
+	case SIGMA_ACTION_WRITESINGLE:
+	case SIGMA_ACTION_WRITESAFELOAD:
+		payload = sigma_action_len(sa);
+		break;
+	default:
+		break;
+	}
+
+	payload = ALIGN(payload, 2);
+
+	return payload + sizeof(struct sigma_action);
+}
+
+/*
+ * Returns a negative error value in case of an error, 0 if processing of
+ * the firmware should be stopped after this action, 1 otherwise.
+ */
+static int
+process_sigma_action(struct sigma_firmware *ssfw, struct sigma_action *sa)
+{
+	size_t len = sigma_action_len(sa);
+	int ret;
+
+	pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
+		sa->instr, sa->addr, len);
+
+	switch (sa->instr) {
+	case SIGMA_ACTION_WRITEXBYTES:
+	case SIGMA_ACTION_WRITESINGLE:
+	case SIGMA_ACTION_WRITESAFELOAD:
+		ret = ssfw->write(ssfw->control_data, sa, len);
+		if (ret < 0)
+			return -EINVAL;
+		break;
+	case SIGMA_ACTION_DELAY:
+		udelay(len);
+		len = 0;
+		break;
+	case SIGMA_ACTION_END:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	return 1;
+}
+
+static int
+process_sigma_actions(struct sigma_firmware *ssfw)
+{
+	struct sigma_action *sa;
+	size_t size;
+	int ret;
+
+	while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
+		sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
+
+		size = sigma_action_size(sa);
+		ssfw->pos += size;
+		if (ssfw->pos > ssfw->fw->size || size == 0)
+			break;
+
+		ret = process_sigma_action(ssfw, sa);
+
+		pr_debug("%s: action returned %i\n", __func__, ret);
+
+		if (ret <= 0)
+			return ret;
+	}
+
+	if (ssfw->pos != ssfw->fw->size)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int _process_sigma_firmware(struct device *dev,
+	struct sigma_firmware *ssfw, const char *name)
+{
+	int ret;
+	struct sigma_firmware_header *ssfw_head;
+	const struct firmware *fw;
+	u32 crc;
+
+	pr_debug("%s: loading firmware %s\n", __func__, name);
+
+	/* first load the blob */
+	ret = request_firmware(&fw, name, dev);
+	if (ret) {
+		pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
+		return ret;
+	}
+	ssfw->fw = fw;
+
+	/* then verify the header */
+	ret = -EINVAL;
+
+	/*
+	 * Reject too small or unreasonable large files. The upper limit has been
+	 * chosen a bit arbitrarily, but it should be enough for all practical
+	 * purposes and having the limit makes it easier to avoid integer
+	 * overflows later in the loading process.
+	 */
+	if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) {
+		dev_err(dev, "Failed to load firmware: Invalid size\n");
+		goto done;
+	}
+
+	ssfw_head = (void *)fw->data;
+	if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) {
+		dev_err(dev, "Failed to load firmware: Invalid magic\n");
+		goto done;
+	}
+
+	crc = crc32(0, fw->data + sizeof(*ssfw_head),
+			fw->size - sizeof(*ssfw_head));
+	pr_debug("%s: crc=%x\n", __func__, crc);
+	if (crc != le32_to_cpu(ssfw_head->crc)) {
+		dev_err(dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n",
+			le32_to_cpu(ssfw_head->crc), crc);
+		goto done;
+	}
+
+	ssfw->pos = sizeof(*ssfw_head);
+
+	/* finally process all of the actions */
+	ret = process_sigma_actions(ssfw);
+
+ done:
+	release_firmware(fw);
+
+	pr_debug("%s: loaded %s\n", __func__, name);
+
+	return ret;
+}
+
+#if IS_ENABLED(CONFIG_I2C)
+
+static int sigma_action_write_i2c(void *control_data,
+	const struct sigma_action *sa, size_t len)
+{
+	return i2c_master_send(control_data, (const unsigned char *)&sa->addr,
+		len);
+}
+
+int process_sigma_firmware(struct i2c_client *client, const char *name)
+{
+	struct sigma_firmware ssfw;
+
+	ssfw.control_data = client;
+	ssfw.write = sigma_action_write_i2c;
+
+	return _process_sigma_firmware(&client->dev, &ssfw, name);
+}
+EXPORT_SYMBOL(process_sigma_firmware);
+
+#endif
+
+#if IS_ENABLED(CONFIG_REGMAP)
+
+static int sigma_action_write_regmap(void *control_data,
+	const struct sigma_action *sa, size_t len)
+{
+	return regmap_raw_write(control_data, le16_to_cpu(sa->addr),
+		sa->payload, len - 2);
+}
+
+int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap,
+	const char *name)
+{
+	struct sigma_firmware ssfw;
+
+	ssfw.control_data = regmap;
+	ssfw.write = sigma_action_write_regmap;
+
+	return _process_sigma_firmware(dev, &ssfw, name);
+}
+EXPORT_SYMBOL(process_sigma_firmware_regmap);
+
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h
new file mode 100644
index 0000000..e439cbd
--- /dev/null
+++ b/sound/soc/codecs/sigmadsp.h
@@ -0,0 +1,21 @@
+/*
+ * Load firmware files from Analog Devices SigmaStudio
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __SIGMA_FIRMWARE_H__
+#define __SIGMA_FIRMWARE_H__
+
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+struct i2c_client;
+
+extern int process_sigma_firmware(struct i2c_client *client, const char *name);
+extern int process_sigma_firmware_regmap(struct device *dev,
+		struct regmap *regmap, const char *name);
+
+#endif
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 887d618..f99baa0 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -698,21 +698,21 @@
 }
 
 /* Codec DAI section */
-static struct snd_soc_dai_ops sn95031_headset_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_headset_dai_ops = {
 	.digital_mute	= sn95031_pcm_hs_mute,
 	.hw_params	= sn95031_pcm_hw_params,
 };
 
-static struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
 	.digital_mute	= sn95031_pcm_spkr_mute,
 	.hw_params	= sn95031_pcm_hw_params,
 };
 
-static struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
 	.hw_params	= sn95031_pcm_hw_params,
 };
 
-static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
 	.hw_params	= sn95031_pcm_hw_params,
 };
 
@@ -920,19 +920,7 @@
 	.remove		= __devexit_p(sn95031_device_remove),
 };
 
-static int __init sn95031_init(void)
-{
-	pr_debug("driver init called\n");
-	return platform_driver_register(&sn95031_codec_driver);
-}
-module_init(sn95031_init);
-
-static void __exit sn95031_exit(void)
-{
-	pr_debug("driver exit called\n");
-	platform_driver_unregister(&sn95031_codec_driver);
-}
-module_exit(sn95031_exit);
+module_platform_driver(sn95031_codec_driver);
 
 MODULE_DESCRIPTION("ASoC TI SN95031 codec driver");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
index 6a1a7e7..112a49d 100644
--- a/sound/soc/codecs/spdif_transciever.c
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -61,18 +61,7 @@
 	},
 };
 
-static int __init dit_modinit(void)
-{
-	return platform_driver_register(&spdif_dit_driver);
-}
-
-static void __exit dit_exit(void)
-{
-	platform_driver_unregister(&spdif_dit_driver);
-}
-
-module_init(dit_modinit);
-module_exit(dit_exit);
+module_platform_driver(spdif_dit_driver);
 
 MODULE_AUTHOR("Steve Chen <schen@mvista.com>");
 MODULE_DESCRIPTION("SPDIF dummy codec driver");
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 3cb3271..7dfc7b0 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -33,7 +33,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -498,7 +497,7 @@
 #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 		SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops ssm2602_dai_ops = {
+static const struct snd_soc_dai_ops ssm2602_dai_ops = {
 	.startup	= ssm2602_startup,
 	.hw_params	= ssm2602_hw_params,
 	.shutdown	= ssm2602_shutdown,
@@ -524,7 +523,7 @@
 	.ops = &ssm2602_dai_ops,
 };
 
-static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ssm2602_suspend(struct snd_soc_codec *codec)
 {
 	ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index d2f3715..6648af6 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -24,9 +24,9 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -35,6 +35,7 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
+#include <sound/sta32x.h>
 #include "sta32x.h"
 
 #define STA32X_RATES (SNDRV_PCM_RATE_32000 | \
@@ -73,11 +74,14 @@
 struct sta32x_priv {
 	struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)];
 	struct snd_soc_codec *codec;
+	struct sta32x_platform_data *pdata;
 
 	unsigned int mclk;
 	unsigned int format;
 
 	u32 coef_shadow[STA32X_COEF_COUNT];
+	struct delayed_work watchdog_work;
+	int shutdown;
 };
 
 static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
@@ -260,7 +264,7 @@
 	return 0;
 }
 
-int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
+static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
 {
 	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
 	unsigned int cfud;
@@ -285,7 +289,7 @@
 	return 0;
 }
 
-int sta32x_cache_sync(struct snd_soc_codec *codec)
+static int sta32x_cache_sync(struct snd_soc_codec *codec)
 {
 	unsigned int mute;
 	int rc;
@@ -302,6 +306,46 @@
 	return rc;
 }
 
+/* work around ESD issue where sta32x resets and loses all configuration */
+static void sta32x_watchdog(struct work_struct *work)
+{
+	struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv,
+						  watchdog_work.work);
+	struct snd_soc_codec *codec = sta32x->codec;
+	unsigned int confa, confa_cached;
+
+	/* check if sta32x has reset itself */
+	confa_cached = snd_soc_read(codec, STA32X_CONFA);
+	codec->cache_bypass = 1;
+	confa = snd_soc_read(codec, STA32X_CONFA);
+	codec->cache_bypass = 0;
+	if (confa != confa_cached) {
+		codec->cache_sync = 1;
+		sta32x_cache_sync(codec);
+	}
+
+	if (!sta32x->shutdown)
+		schedule_delayed_work(&sta32x->watchdog_work,
+				      round_jiffies_relative(HZ));
+}
+
+static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
+{
+	if (sta32x->pdata->needs_esd_watchdog) {
+		sta32x->shutdown = 0;
+		schedule_delayed_work(&sta32x->watchdog_work,
+				      round_jiffies_relative(HZ));
+	}
+}
+
+static void sta32x_watchdog_stop(struct sta32x_priv *sta32x)
+{
+	if (sta32x->pdata->needs_esd_watchdog) {
+		sta32x->shutdown = 1;
+		cancel_delayed_work_sync(&sta32x->watchdog_work);
+	}
+}
+
 #define SINGLE_COEF(xname, index) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = sta32x_coefficient_info, \
@@ -712,6 +756,7 @@
 			}
 
 			sta32x_cache_sync(codec);
+			sta32x_watchdog_start(sta32x);
 		}
 
 		/* Power up to mute */
@@ -728,7 +773,7 @@
 				    STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
 				    STA32X_CONFF_PWDN);
 		msleep(300);
-
+		sta32x_watchdog_stop(sta32x);
 		regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
 				       sta32x->supplies);
 		break;
@@ -737,7 +782,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops sta32x_dai_ops = {
+static const struct snd_soc_dai_ops sta32x_dai_ops = {
 	.hw_params	= sta32x_hw_params,
 	.set_sysclk	= sta32x_set_dai_sysclk,
 	.set_fmt	= sta32x_set_dai_fmt,
@@ -756,7 +801,7 @@
 };
 
 #ifdef CONFIG_PM
-static int sta32x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int sta32x_suspend(struct snd_soc_codec *codec)
 {
 	sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -775,9 +820,10 @@
 static int sta32x_probe(struct snd_soc_codec *codec)
 {
 	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
-	int i, ret = 0;
+	int i, ret = 0, thermal = 0;
 
 	sta32x->codec = codec;
+	sta32x->pdata = dev_get_platdata(codec->dev);
 
 	/* regulators */
 	for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
@@ -820,25 +866,34 @@
 	snd_soc_cache_write(codec, STA32X_AUTO3, 0x00);
 	snd_soc_cache_write(codec, STA32X_C3CFG, 0x40);
 
-	/* FIXME enable thermal warning adjustment and recovery  */
+	/* set thermal warning adjustment and recovery */
+	if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE))
+		thermal |= STA32X_CONFA_TWAB;
+	if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE))
+		thermal |= STA32X_CONFA_TWRB;
 	snd_soc_update_bits(codec, STA32X_CONFA,
-			    STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, 0);
+			    STA32X_CONFA_TWAB | STA32X_CONFA_TWRB,
+			    thermal);
 
-	/* FIXME select 2.1 mode  */
+	/* select output configuration  */
 	snd_soc_update_bits(codec, STA32X_CONFF,
 			    STA32X_CONFF_OCFG_MASK,
-			    1 << STA32X_CONFF_OCFG_SHIFT);
+			    sta32x->pdata->output_conf
+			    << STA32X_CONFF_OCFG_SHIFT);
 
-	/* FIXME channel to output mapping */
+	/* channel to output mapping */
 	snd_soc_update_bits(codec, STA32X_C1CFG,
 			    STA32X_CxCFG_OM_MASK,
-			    0 << STA32X_CxCFG_OM_SHIFT);
+			    sta32x->pdata->ch1_output_mapping
+			    << STA32X_CxCFG_OM_SHIFT);
 	snd_soc_update_bits(codec, STA32X_C2CFG,
 			    STA32X_CxCFG_OM_MASK,
-			    1 << STA32X_CxCFG_OM_SHIFT);
+			    sta32x->pdata->ch2_output_mapping
+			    << STA32X_CxCFG_OM_SHIFT);
 	snd_soc_update_bits(codec, STA32X_C3CFG,
 			    STA32X_CxCFG_OM_MASK,
-			    2 << STA32X_CxCFG_OM_SHIFT);
+			    sta32x->pdata->ch3_output_mapping
+			    << STA32X_CxCFG_OM_SHIFT);
 
 	/* initialize coefficient shadow RAM with reset values */
 	for (i = 4; i <= 49; i += 5)
@@ -851,6 +906,9 @@
 	sta32x->coef_shadow[60] = 0x400000;
 	sta32x->coef_shadow[61] = 0x400000;
 
+	if (sta32x->pdata->needs_esd_watchdog)
+		INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog);
+
 	sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	/* Bias level configuration will have done an extra enable */
 	regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
@@ -867,6 +925,7 @@
 {
 	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
 
+	sta32x_watchdog_stop(sta32x);
 	sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
 	regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index 78b2b50..e34969c 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -256,8 +256,7 @@
 	return 0;
 }
 
-static int stac9766_codec_suspend(struct snd_soc_codec *codec,
-				  pm_message_t state)
+static int stac9766_codec_suspend(struct snd_soc_codec *codec)
 {
 	stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -286,11 +285,11 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops stac9766_dai_ops_analog = {
+static const struct snd_soc_dai_ops stac9766_dai_ops_analog = {
 	.prepare = ac97_analog_prepare,
 };
 
-static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
+static const struct snd_soc_dai_ops stac9766_dai_ops_digital = {
 	.prepare = ac97_digital_prepare,
 };
 
@@ -408,17 +407,7 @@
 	.remove = __devexit_p(stac9766_remove),
 };
 
-static int __init stac9766_init(void)
-{
-	return platform_driver_register(&stac9766_codec_driver);
-}
-module_init(stac9766_init);
-
-static void __exit stac9766_exit(void)
-{
-	platform_driver_unregister(&stac9766_codec_driver);
-}
-module_exit(stac9766_exit);
+module_platform_driver(stac9766_codec_driver);
 
 MODULE_DESCRIPTION("ASoC stac9766 driver");
 MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 336de8f..60d08ae 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -24,7 +24,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -503,7 +502,7 @@
 #define AIC23_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
+static const struct snd_soc_dai_ops tlv320aic23_dai_ops = {
 	.prepare	= tlv320aic23_pcm_prepare,
 	.hw_params	= tlv320aic23_hw_params,
 	.shutdown	= tlv320aic23_shutdown,
@@ -529,8 +528,7 @@
 	.ops = &tlv320aic23_dai_ops,
 };
 
-static int tlv320aic23_suspend(struct snd_soc_codec *codec,
-			       pm_message_t state)
+static int tlv320aic23_suspend(struct snd_soc_codec *codec)
 {
 	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 7859bdc..86d1fa3 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -275,7 +275,7 @@
 #define AIC26_FORMATS	(SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_BE |\
 			 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
 
-static struct snd_soc_dai_ops aic26_dai_ops = {
+static const struct snd_soc_dai_ops aic26_dai_ops = {
 	.hw_params	= aic26_hw_params,
 	.digital_mute	= aic26_mute,
 	.set_sysclk	= aic26_set_sysclk,
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index b21c610..81a26e1 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
 
@@ -597,7 +596,7 @@
 #define AIC32X4_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
 			 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops aic32x4_ops = {
+static const struct snd_soc_dai_ops aic32x4_ops = {
 	.hw_params = aic32x4_hw_params,
 	.digital_mute = aic32x4_mute,
 	.set_fmt = aic32x4_set_dai_fmt,
@@ -622,7 +621,7 @@
 	.symmetric_rates = 1,
 };
 
-static int aic32x4_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int aic32x4_suspend(struct snd_soc_codec *codec)
 {
 	aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 87d5ef1..6f963c5 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -40,7 +40,6 @@
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -833,7 +832,6 @@
 	int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
 	u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
 	u16 d, pll_d = 1;
-	u8 reg;
 	int clk;
 
 	/* select data word length */
@@ -869,14 +867,13 @@
 		snd_soc_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
 		snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
 		/* disable PLL if it is bypassed */
-		reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
-		snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
+		snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, PLL_ENABLE, 0);
 
 	} else {
 		snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
 		/* enable PLL when it is used */
-		reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
-		snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
+		snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+				    PLL_ENABLE, PLL_ENABLE);
 	}
 
 	/* Route Left DAC to left channel input and
@@ -1156,7 +1153,6 @@
 				enum snd_soc_bias_level level)
 {
 	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
-	u8 reg;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
@@ -1165,9 +1161,8 @@
 		if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY &&
 		    aic3x->master) {
 			/* enable pll */
-			reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
-			snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
-				      reg | PLL_ENABLE);
+			snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+					    PLL_ENABLE, PLL_ENABLE);
 		}
 		break;
 	case SND_SOC_BIAS_STANDBY:
@@ -1176,9 +1171,8 @@
 		if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE &&
 		    aic3x->master) {
 			/* disable pll */
-			reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
-			snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
-				      reg & ~PLL_ENABLE);
+			snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+					    PLL_ENABLE, 0);
 		}
 		break;
 	case SND_SOC_BIAS_OFF:
@@ -1249,7 +1243,7 @@
 #define AIC3X_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops aic3x_dai_ops = {
+static const struct snd_soc_dai_ops aic3x_dai_ops = {
 	.hw_params	= aic3x_hw_params,
 	.digital_mute	= aic3x_mute,
 	.set_sysclk	= aic3x_set_dai_sysclk,
@@ -1274,7 +1268,7 @@
 	.symmetric_rates = 1,
 };
 
-static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int aic3x_suspend(struct snd_soc_codec *codec)
 {
 	aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1295,7 +1289,6 @@
 static int aic3x_init(struct snd_soc_codec *codec)
 {
 	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
-	int reg;
 
 	snd_soc_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
 	snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
@@ -1317,20 +1310,13 @@
 	snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
 
 	/* unmute all outputs */
-	reg = snd_soc_read(codec, LLOPM_CTRL);
-	snd_soc_write(codec, LLOPM_CTRL, reg | UNMUTE);
-	reg = snd_soc_read(codec, RLOPM_CTRL);
-	snd_soc_write(codec, RLOPM_CTRL, reg | UNMUTE);
-	reg = snd_soc_read(codec, MONOLOPM_CTRL);
-	snd_soc_write(codec, MONOLOPM_CTRL, reg | UNMUTE);
-	reg = snd_soc_read(codec, HPLOUT_CTRL);
-	snd_soc_write(codec, HPLOUT_CTRL, reg | UNMUTE);
-	reg = snd_soc_read(codec, HPROUT_CTRL);
-	snd_soc_write(codec, HPROUT_CTRL, reg | UNMUTE);
-	reg = snd_soc_read(codec, HPLCOM_CTRL);
-	snd_soc_write(codec, HPLCOM_CTRL, reg | UNMUTE);
-	reg = snd_soc_read(codec, HPRCOM_CTRL);
-	snd_soc_write(codec, HPRCOM_CTRL, reg | UNMUTE);
+	snd_soc_update_bits(codec, LLOPM_CTRL, UNMUTE, UNMUTE);
+	snd_soc_update_bits(codec, RLOPM_CTRL, UNMUTE, UNMUTE);
+	snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE);
+	snd_soc_update_bits(codec, HPLOUT_CTRL, UNMUTE, UNMUTE);
+	snd_soc_update_bits(codec, HPROUT_CTRL, UNMUTE, UNMUTE);
+	snd_soc_update_bits(codec, HPLCOM_CTRL, UNMUTE, UNMUTE);
+	snd_soc_update_bits(codec, HPRCOM_CTRL, UNMUTE, UNMUTE);
 
 	/* ADC default volume and unmute */
 	snd_soc_write(codec, LADC_VOL, DEFAULT_GAIN);
@@ -1494,7 +1480,6 @@
 	.resume = aic3x_resume,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 /*
  * AIC3X 2 wire address can be up to 4 devices with device addresses
  * 0x18, 0x19, 0x1A, 0x1B
@@ -1561,27 +1546,22 @@
 	.remove = aic3x_i2c_remove,
 	.id_table = aic3x_i2c_id,
 };
-#endif
 
 static int __init aic3x_modinit(void)
 {
 	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&aic3x_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n",
 		       ret);
 	}
-#endif
 	return ret;
 }
 module_init(aic3x_modinit);
 
 static void __exit aic3x_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&aic3x_i2c_driver);
-#endif
 }
 module_exit(aic3x_exit);
 
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index dc8a2b2..c7a61fb 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
@@ -1461,7 +1460,7 @@
 	return 0;
 }
 
-static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int dac33_soc_suspend(struct snd_soc_codec *codec)
 {
 	dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1499,7 +1498,7 @@
 			 SNDRV_PCM_RATE_48000)
 #define DAC33_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops dac33_dai_ops = {
+static const struct snd_soc_dai_ops dac33_dai_ops = {
 	.startup	= dac33_startup,
 	.shutdown	= dac33_shutdown,
 	.hw_params	= dac33_hw_params,
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index f798247..18e7101 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -2149,7 +2149,7 @@
 #define TWL4030_RATES	 (SNDRV_PCM_RATE_8000_48000)
 #define TWL4030_FORMATS	 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
+static const struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
 	.startup	= twl4030_startup,
 	.shutdown	= twl4030_shutdown,
 	.hw_params	= twl4030_hw_params,
@@ -2158,7 +2158,7 @@
 	.set_tristate	= twl4030_set_tristate,
 };
 
-static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
+static const struct snd_soc_dai_ops twl4030_dai_voice_ops = {
 	.startup	= twl4030_voice_startup,
 	.shutdown	= twl4030_voice_shutdown,
 	.hw_params	= twl4030_voice_hw_params,
@@ -2202,7 +2202,7 @@
 },
 };
 
-static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int twl4030_soc_suspend(struct snd_soc_codec *codec)
 {
 	twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -2294,17 +2294,7 @@
 	},
 };
 
-static int __init twl4030_modinit(void)
-{
-	return platform_driver_register(&twl4030_codec_driver);
-}
-module_init(twl4030_modinit);
-
-static void __exit twl4030_exit(void)
-{
-	platform_driver_unregister(&twl4030_codec_driver);
-}
-module_exit(twl4030_exit);
+module_platform_driver(twl4030_codec_driver);
 
 MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
 MODULE_AUTHOR("Steve Sakoman");
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 73e11f0..3376e6f 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1397,7 +1397,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops twl6040_dai_ops = {
+static const struct snd_soc_dai_ops twl6040_dai_ops = {
 	.startup	= twl6040_startup,
 	.hw_params	= twl6040_hw_params,
 	.prepare	= twl6040_prepare,
@@ -1470,7 +1470,7 @@
 };
 
 #ifdef CONFIG_PM
-static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int twl6040_suspend(struct snd_soc_codec *codec)
 {
 	twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1620,17 +1620,7 @@
 	.remove = __devexit_p(twl6040_codec_remove),
 };
 
-static int __init twl6040_codec_init(void)
-{
-	return platform_driver_register(&twl6040_codec_driver);
-}
-module_init(twl6040_codec_init);
-
-static void __exit twl6040_codec_exit(void)
-{
-	platform_driver_unregister(&twl6040_codec_driver);
-}
-module_exit(twl6040_codec_exit);
+module_platform_driver(twl6040_codec_driver);
 
 MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
 MODULE_AUTHOR("Misael Lopez Cruz");
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index a7b8f30..8f4f469 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -452,7 +452,7 @@
 SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
 };
 
-static struct snd_soc_dai_ops uda134x_dai_ops = {
+static const struct snd_soc_dai_ops uda134x_dai_ops = {
 	.startup	= uda134x_startup,
 	.shutdown	= uda134x_shutdown,
 	.hw_params	= uda134x_hw_params,
@@ -571,8 +571,7 @@
 }
 
 #if defined(CONFIG_PM)
-static int uda134x_soc_suspend(struct snd_soc_codec *codec,
-						pm_message_t state)
+static int uda134x_soc_suspend(struct snd_soc_codec *codec)
 {
 	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -625,17 +624,7 @@
 	.remove = __devexit_p(uda134x_codec_remove),
 };
 
-static int __init uda134x_codec_init(void)
-{
-	return platform_driver_register(&uda134x_codec_driver);
-}
-module_init(uda134x_codec_init);
-
-static void __exit uda134x_codec_exit(void)
-{
-	platform_driver_unregister(&uda134x_codec_driver);
-}
-module_exit(uda134x_codec_exit);
+module_platform_driver(uda134x_codec_driver);
 
 MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
 MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index c5ca8cf..d08b91d 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -643,21 +643,21 @@
 		       SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
 		       SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops uda1380_dai_ops = {
+static const struct snd_soc_dai_ops uda1380_dai_ops = {
 	.hw_params	= uda1380_pcm_hw_params,
 	.shutdown	= uda1380_pcm_shutdown,
 	.trigger	= uda1380_trigger,
 	.set_fmt	= uda1380_set_dai_fmt_both,
 };
 
-static struct snd_soc_dai_ops uda1380_dai_ops_playback = {
+static const struct snd_soc_dai_ops uda1380_dai_ops_playback = {
 	.hw_params	= uda1380_pcm_hw_params,
 	.shutdown	= uda1380_pcm_shutdown,
 	.trigger	= uda1380_trigger,
 	.set_fmt	= uda1380_set_dai_fmt_playback,
 };
 
-static struct snd_soc_dai_ops uda1380_dai_ops_capture = {
+static const struct snd_soc_dai_ops uda1380_dai_ops_capture = {
 	.hw_params	= uda1380_pcm_hw_params,
 	.shutdown	= uda1380_pcm_shutdown,
 	.trigger	= uda1380_trigger,
@@ -705,7 +705,7 @@
 },
 };
 
-static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int uda1380_suspend(struct snd_soc_codec *codec)
 {
 	uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index a854989..44aacf9 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -386,7 +386,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops wl1273_dai_ops = {
+static const struct snd_soc_dai_ops wl1273_dai_ops = {
 	.startup	= wl1273_startup,
 	.hw_params	= wl1273_hw_params,
 };
@@ -510,17 +510,7 @@
 	.remove		= __devexit_p(wl1273_platform_remove),
 };
 
-static int __init wl1273_init(void)
-{
-	return platform_driver_register(&wl1273_platform_driver);
-}
-module_init(wl1273_init);
-
-static void __exit wl1273_exit(void)
-{
-	platform_driver_unregister(&wl1273_platform_driver);
-}
-module_exit(wl1273_exit);
+module_platform_driver(wl1273_platform_driver);
 
 MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
 MODULE_DESCRIPTION("ASoC WL1273 codec driver");
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index cd0ec0f..aefb4f8 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -116,7 +116,7 @@
 	if (!pdata)
 		return 0;
 
-	wm1250 = kzalloc(sizeof(*wm1250), GFP_KERNEL);
+	wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL);
 	if (!wm1250) {
 		dev_err(&i2c->dev, "Unable to allocate private data\n");
 		ret = -ENOMEM;
@@ -134,15 +134,13 @@
 	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;
+		goto err;
 	}
 
 	dev_set_drvdata(&i2c->dev, wm1250);
 
 	return ret;
 
-err_alloc:
-	kfree(wm1250);
 err:
 	return ret;
 }
@@ -151,10 +149,8 @@
 {
 	struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev);
 
-	if (wm1250) {
+	if (wm1250)
 		gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
-		kfree(wm1250);
-	}
 }
 
 static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index a3b9cbb..01b1abe 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <sound/core.h>
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c
index e9ce81a..9a18fae 100644
--- a/sound/soc/codecs/wm5100-tables.c
+++ b/sound/soc/codecs/wm5100-tables.c
@@ -13,7 +13,7 @@
 
 #include "wm5100.h"
 
-int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+bool wm5100_volatile_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case WM5100_SOFTWARE_RESET:
@@ -36,7 +36,7 @@
 	}
 }
 
-int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg)
+bool wm5100_readable_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case WM5100_SOFTWARE_RESET:
@@ -85,6 +85,7 @@
 	case WM5100_MIC_DETECT_1:
 	case WM5100_MIC_DETECT_2:
 	case WM5100_MIC_DETECT_3:
+	case WM5100_MISC_CONTROL:
 	case WM5100_INPUT_ENABLES:
 	case WM5100_INPUT_ENABLES_STATUS:
 	case WM5100_IN1L_CONTROL:
@@ -696,836 +697,668 @@
 	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 */
+struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT] = {
+	{ 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 */
 };
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 42d9039..a234b70 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -18,7 +18,6 @@
 #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>
@@ -51,6 +50,7 @@
 
 /* codec private data */
 struct wm5100_priv {
+	struct regmap *regmap;
 	struct snd_soc_codec *codec;
 
 	struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
@@ -204,17 +204,15 @@
 	}
 }
 
-static int wm5100_reset(struct snd_soc_codec *codec)
+static int wm5100_reset(struct wm5100_priv *wm5100)
 {
-	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);
+		return regmap_write(wm5100->regmap, WM5100_SOFTWARE_RESET, 0);
 	}
 }
 
@@ -954,7 +952,7 @@
 SND_SOC_DAPM_INPUT("IN3R"),
 SND_SOC_DAPM_INPUT("IN4L"),
 SND_SOC_DAPM_INPUT("IN4R"),
-SND_SOC_DAPM_INPUT("TONE"),
+SND_SOC_DAPM_SIGGEN("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),
@@ -1375,7 +1373,7 @@
 				msleep(2);
 			}
 
-			codec->cache_only = false;
+			regcache_cache_only(wm5100->regmap, false);
 
 			switch (wm5100->rev) {
 			case 0:
@@ -1399,7 +1397,7 @@
 				break;
 			}
 
-			snd_soc_cache_sync(codec);
+			regcache_sync(wm5100->regmap);
 		}
 		break;
 
@@ -1662,7 +1660,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops wm5100_dai_ops = {
+static const struct snd_soc_dai_ops wm5100_dai_ops = {
 	.set_fmt = wm5100_set_fmt,
 	.hw_params = wm5100_hw_params,
 };
@@ -1993,6 +1991,9 @@
 	else
 		timeout = 50;
 
+	snd_soc_update_bits(codec, WM5100_CLOCKING_3, WM5100_SYSCLK_ENA,
+			    WM5100_SYSCLK_ENA);
+
 	/* Poll for the lock; will use interrupt when we can test */
 	for (i = 0; i < timeout; i++) {
 		if (i2c->irq) {
@@ -2350,24 +2351,22 @@
 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);
+	regmap_update_bits(wm5100->regmap, 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, ret;
 
 	val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT);
 
-	ret = snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
-				  WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
-				  WM5100_GP1_LVL, val);
+	ret = regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
+				 WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
+				 WM5100_GP1_LVL, val);
 	if (ret < 0)
 		return ret;
 	else
@@ -2377,25 +2376,24 @@
 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;
+	unsigned int reg;
 	int ret;
 
-	ret = snd_soc_read(codec, WM5100_GPIO_CTRL_1 + offset);
+	ret = regmap_read(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, &reg);
 	if (ret < 0)
 		return ret;
 
-	return (ret & WM5100_GP1_LVL) != 0;
+	return (reg & 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));
+	return regmap_update_bits(wm5100->regmap, 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 = {
@@ -2408,14 +2406,14 @@
 	.can_sleep		= 1,
 };
 
-static void wm5100_init_gpio(struct snd_soc_codec *codec)
+static void wm5100_init_gpio(struct i2c_client *i2c)
 {
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
 	int ret;
 
 	wm5100->gpio_chip = wm5100_template_chip;
 	wm5100->gpio_chip.ngpio = 6;
-	wm5100->gpio_chip.dev = codec->dev;
+	wm5100->gpio_chip.dev = &i2c->dev;
 
 	if (wm5100->pdata.gpio_base)
 		wm5100->gpio_chip.base = wm5100->pdata.gpio_base;
@@ -2424,24 +2422,24 @@
 
 	ret = gpiochip_add(&wm5100->gpio_chip);
 	if (ret != 0)
-		dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+		dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret);
 }
 
-static void wm5100_free_gpio(struct snd_soc_codec *codec)
+static void wm5100_free_gpio(struct i2c_client *i2c)
 {
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
 	int ret;
 
 	ret = gpiochip_remove(&wm5100->gpio_chip);
 	if (ret != 0)
-		dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+		dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret);
 }
 #else
-static void wm5100_init_gpio(struct snd_soc_codec *codec)
+static void wm5100_init_gpio(struct i2c_client *i2c)
 {
 }
 
-static void wm5100_free_gpio(struct snd_soc_codec *codec)
+static void wm5100_free_gpio(struct i2c_client *i2c)
 {
 }
 #endif
@@ -2453,131 +2451,21 @@
 	int ret, i, irq_flags;
 
 	wm5100->codec = codec;
+	codec->control_data = wm5100->regmap;
 
-	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 	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];
+	regcache_cache_only(wm5100->regmap, true);
 
-	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);
@@ -2662,8 +2550,207 @@
 err_gpio:
 	if (i2c->irq)
 		free_irq(i2c->irq, codec);
-	wm5100_free_gpio(codec);
+
+	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);
+	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),
+};
+
+static const struct regmap_config wm5100_regmap = {
+	.reg_bits = 16,
+	.val_bits = 16,
+
+	.max_register = WM5100_MAX_REGISTER,
+	.reg_defaults = wm5100_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm5100_reg_defaults),
+	.volatile_reg = wm5100_volatile_register,
+	.readable_reg = wm5100_readable_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+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;
+	unsigned int reg;
+	int ret, i;
+
+	wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv),
+			      GFP_KERNEL);
+	if (wm5100 == NULL)
+		return -ENOMEM;
+
+	wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
+	if (IS_ERR(wm5100->regmap)) {
+		ret = PTR_ERR(wm5100->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err;
+	}
+
+	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);
+
+	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(&i2c->dev, "Failed to request core supplies: %d\n",
+			ret);
+		goto err_regmap;
+	}
+
+	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(&i2c->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 = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read ID register\n");
+		goto err_reset;
+	}
+	switch (reg) {
+	case 0x8997:
+	case 0x5100:
+		break;
+
+	default:
+		dev_err(&i2c->dev, "Device is not a WM5100, ID is %x\n", reg);
+		ret = -EINVAL;
+		goto err_reset;
+	}
+
+	ret = regmap_read(wm5100->regmap, WM5100_DEVICE_REVISION, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read revision register\n");
+		goto err_reset;
+	}
+	wm5100->rev = reg & WM5100_DEVICE_REVISION_MASK;
+
+	dev_info(&i2c->dev, "revision %c\n", wm5100->rev + 'A');
+
+	ret = wm5100_reset(wm5100);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to issue reset\n");
+		goto err_reset;
+	}
+
+	wm5100_init_gpio(i2c);
+
+	for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
+		if (!wm5100->pdata.gpio_defaults[i])
+			continue;
+
+		regmap_write(wm5100->regmap, WM5100_GPIO_CTRL_1 + i,
+			     wm5100->pdata.gpio_defaults[i]);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
+		regmap_update_bits(wm5100->regmap, 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));
+	}
+
+	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);
+		goto err_reset;
+	}
+
+	return ret;
+
 err_reset:
+	wm5100_free_gpio(i2c);
 	if (wm5100->pdata.reset) {
 		gpio_set_value_cansleep(wm5100->pdata.reset, 1);
 		gpio_free(wm5100->pdata.reset);
@@ -2685,22 +2772,18 @@
 err_core:
 	regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
 			    wm5100->core_supplies);
-
+err_regmap:
+	regmap_exit(wm5100->regmap);
+err:
 	return ret;
 }
 
-static int wm5100_remove(struct snd_soc_codec *codec)
+static __devexit int wm5100_i2c_remove(struct i2c_client *client)
 {
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-	struct i2c_client *i2c = to_i2c_client(codec->dev);
+	struct wm5100_priv *wm5100 = i2c_get_clientdata(client);
 
-	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);
+	snd_soc_unregister_codec(&client->dev);
+	wm5100_free_gpio(client);
 	if (wm5100->pdata.reset) {
 		gpio_set_value_cansleep(wm5100->pdata.reset, 1);
 		gpio_free(wm5100->pdata.reset);
@@ -2714,69 +2797,8 @@
 	regulator_put(wm5100->cpvdd);
 	regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
 			    wm5100->core_supplies);
-	return 0;
-}
+	regmap_exit(wm5100->regmap);
 
-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;
 }
 
diff --git a/sound/soc/codecs/wm5100.h b/sound/soc/codecs/wm5100.h
index 9707596..25cb601 100644
--- a/sound/soc/codecs/wm5100.h
+++ b/sound/soc/codecs/wm5100.h
@@ -15,6 +15,7 @@
 #define WM5100_ASOC_H
 
 #include <sound/soc.h>
+#include <linux/regmap.h>
 
 int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
 
@@ -5147,9 +5148,9 @@
 #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);
+bool wm5100_readable_register(struct device *dev, unsigned int reg);
+bool wm5100_volatile_register(struct device *dev, unsigned int reg);
 
-extern u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1];
+extern struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT];
 
 #endif
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 35f3ad83..f39497f 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1315,7 +1315,7 @@
 	return 0;
 }
 
-static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8350_suspend(struct snd_soc_codec *codec)
 {
 	wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -1511,7 +1511,7 @@
 			SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8350_dai_ops = {
+static const struct snd_soc_dai_ops wm8350_dai_ops = {
 	 .hw_params	= wm8350_pcm_hw_params,
 	 .digital_mute	= wm8350_mute,
 	 .trigger	= wm8350_pcm_trigger,
@@ -1711,17 +1711,7 @@
 	.remove = __devexit_p(wm8350_remove),
 };
 
-static __init int wm8350_init(void)
-{
-	return platform_driver_register(&wm8350_codec_driver);
-}
-module_init(wm8350_init);
-
-static __exit void wm8350_exit(void)
-{
-	platform_driver_unregister(&wm8350_codec_driver);
-}
-module_exit(wm8350_exit);
+module_platform_driver(wm8350_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM8350 driver");
 MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index dc13be2..56a7b72 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -766,8 +766,8 @@
 	NULL, 0),
 
 /* MICBIAS */
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8400_POWER_MANAGEMENT_1,
-	WM8400_MIC1BIAS_ENA_SHIFT, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8400_POWER_MANAGEMENT_1,
+		    WM8400_MIC1BIAS_ENA_SHIFT, 0, NULL, 0),
 
 SND_SOC_DAPM_OUTPUT("LON"),
 SND_SOC_DAPM_OUTPUT("LOP"),
@@ -1059,7 +1059,7 @@
 	wm8400_write(codec, WM8400_FLL_CONTROL_3, factors.n);
 
 	reg = wm8400_read(codec, WM8400_FLL_CONTROL_4);
-	reg &= WM8400_FLL_OUTDIV_MASK;
+	reg &= ~WM8400_FLL_OUTDIV_MASK;
 	reg |= factors.outdiv;
 	wm8400_write(codec, WM8400_FLL_CONTROL_4, reg);
 
@@ -1316,7 +1316,7 @@
 #define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8400_dai_ops = {
+static const struct snd_soc_dai_ops wm8400_dai_ops = {
 	.hw_params = wm8400_hw_params,
 	.digital_mute = wm8400_mute,
 	.set_fmt = wm8400_set_dai_fmt,
@@ -1352,7 +1352,7 @@
 	.ops = &wm8400_dai_ops,
 };
 
-static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8400_suspend(struct snd_soc_codec *codec)
 {
 	wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1477,17 +1477,7 @@
 	.remove = __devexit_p(wm8400_remove),
 };
 
-static __init int wm8400_init(void)
-{
-	return platform_driver_register(&wm8400_codec_driver);
-}
-module_init(wm8400_init);
-
-static __exit void wm8400_exit(void)
-{
-	platform_driver_unregister(&wm8400_codec_driver);
-}
-module_exit(wm8400_exit);
+module_platform_driver(wm8400_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM8400 driver");
 MODULE_AUTHOR("Mark Brown");
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 07c9cc7..5e84750 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -509,7 +508,7 @@
 #define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8510_dai_ops = {
+static const struct snd_soc_dai_ops wm8510_dai_ops = {
 	.hw_params	= wm8510_pcm_hw_params,
 	.digital_mute	= wm8510_mute,
 	.set_fmt	= wm8510_set_dai_fmt,
@@ -535,7 +534,7 @@
 	.symmetric_rates = 1,
 };
 
-static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8510_suspend(struct snd_soc_codec *codec)
 {
 	wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index db7a681..7fea2c3 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -365,7 +364,7 @@
 #define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8523_dai_ops = {
+static const struct snd_soc_dai_ops wm8523_dai_ops = {
 	.startup	= wm8523_startup,
 	.hw_params	= wm8523_hw_params,
 	.set_sysclk	= wm8523_set_dai_sysclk,
@@ -385,7 +384,7 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8523_suspend(struct snd_soc_codec *codec)
 {
 	wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 8212b3c..764b2bf 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -776,7 +775,7 @@
 #define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
+static const struct snd_soc_dai_ops wm8580_dai_ops_playback = {
 	.set_sysclk	= wm8580_set_sysclk,
 	.hw_params	= wm8580_paif_hw_params,
 	.set_fmt	= wm8580_set_paif_dai_fmt,
@@ -785,7 +784,7 @@
 	.digital_mute	= wm8580_digital_mute,
 };
 
-static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
+static const struct snd_soc_dai_ops wm8580_dai_ops_capture = {
 	.set_sysclk	= wm8580_set_sysclk,
 	.hw_params	= wm8580_paif_hw_params,
 	.set_fmt	= wm8580_set_paif_dai_fmt,
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index 076bdb9..b9b1a2f 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -318,7 +317,7 @@
 #define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8711_ops = {
+static const struct snd_soc_dai_ops wm8711_ops = {
 	.prepare = wm8711_pcm_prepare,
 	.hw_params = wm8711_hw_params,
 	.shutdown = wm8711_shutdown,
@@ -339,7 +338,7 @@
 	.ops = &wm8711_ops,
 };
 
-static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8711_suspend(struct snd_soc_codec *codec)
 {
 	snd_soc_write(codec, WM8711_ACTIVE, 0x0);
 	wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
index 7488082..fad90a3 100644
--- a/sound/soc/codecs/wm8727.c
+++ b/sound/soc/codecs/wm8727.c
@@ -67,17 +67,7 @@
 	.remove = __devexit_p(wm8727_remove),
 };
 
-static int __init wm8727_init(void)
-{
-	return platform_driver_register(&wm8727_codec_driver);
-}
-module_init(wm8727_init);
-
-static void __exit wm8727_exit(void)
-{
-	platform_driver_unregister(&wm8727_codec_driver);
-}
-module_exit(wm8727_exit);
+module_platform_driver(wm8727_codec_driver);
 
 MODULE_DESCRIPTION("ASoC wm8727 driver");
 MODULE_AUTHOR("Neil Jones");
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 04b027e..b1f01d9 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -196,7 +196,7 @@
 #define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8728_dai_ops = {
+static const struct snd_soc_dai_ops wm8728_dai_ops = {
 	.hw_params	= wm8728_hw_params,
 	.digital_mute	= wm8728_mute,
 	.set_fmt	= wm8728_set_dai_fmt,
@@ -214,7 +214,7 @@
 	.ops = &wm8728_dai_ops,
 };
 
-static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8728_suspend(struct snd_soc_codec *codec)
 {
 	wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index a7c9ae1..8821af7 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,7 +19,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/of_device.h>
@@ -465,7 +464,7 @@
 #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8731_dai_ops = {
+static const struct snd_soc_dai_ops wm8731_dai_ops = {
 	.hw_params	= wm8731_hw_params,
 	.digital_mute	= wm8731_mute,
 	.set_sysclk	= wm8731_set_dai_sysclk,
@@ -491,7 +490,7 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8731_suspend(struct snd_soc_codec *codec)
 {
 	wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -554,9 +553,6 @@
 	/* Disable bypass path by default */
 	snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0);
 
-	snd_soc_add_controls(codec, wm8731_snd_controls,
-			     ARRAY_SIZE(wm8731_snd_controls));
-
 	/* Regulators will have been enabled by bias management */
 	regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
 
@@ -596,6 +592,8 @@
 	.num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
 	.dapm_routes = wm8731_intercon,
 	.num_dapm_routes = ARRAY_SIZE(wm8731_intercon),
+	.controls =	wm8731_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8731_snd_controls),
 };
 
 static const struct of_device_id wm8731_of_match[] = {
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index f6aef58..ff95e62c 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
@@ -521,7 +520,7 @@
 #define WM8737_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8737_dai_ops = {
+static const struct snd_soc_dai_ops wm8737_dai_ops = {
 	.hw_params	= wm8737_hw_params,
 	.set_sysclk	= wm8737_set_dai_sysclk,
 	.set_fmt	= wm8737_set_dai_fmt,
@@ -540,7 +539,7 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8737_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8737_suspend(struct snd_soc_codec *codec)
 {
 	wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 57ad22a..bf471dc 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -18,7 +18,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -382,7 +381,7 @@
 #define WM8741_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8741_dai_ops = {
+static const struct snd_soc_dai_ops wm8741_dai_ops = {
 	.startup	= wm8741_startup,
 	.hw_params	= wm8741_hw_params,
 	.set_sysclk	= wm8741_set_dai_sysclk,
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index ca75a81..48cb78f 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -643,7 +642,7 @@
 #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8750_dai_ops = {
+static const struct snd_soc_dai_ops wm8750_dai_ops = {
 	.hw_params	= wm8750_pcm_hw_params,
 	.digital_mute	= wm8750_mute,
 	.set_fmt	= wm8750_set_dai_fmt,
@@ -667,7 +666,7 @@
 	.ops = &wm8750_dai_ops,
 };
 
-static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8750_suspend(struct snd_soc_codec *codec)
 {
 	wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 3a629d0..b114c19 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -39,7 +39,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/of_device.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -486,7 +485,7 @@
 SND_SOC_DAPM_VMID("VREF"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8753_dapm_routes[] = {
 	/* left mixer */
 	{"Left Mixer", "Left Playback Switch", "Left DAC"},
 	{"Left Mixer", "Voice Playback Switch", "Voice DAC"},
@@ -640,17 +639,6 @@
 	{"ACOP", NULL, "ALC Mixer"},
 };
 
-static int wm8753_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets,
-				  ARRAY_SIZE(wm8753_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	return 0;
-}
-
 /* PLL divisors */
 struct _pll_div {
 	u32 div2:1;
@@ -1326,7 +1314,7 @@
  * 3. Voice disabled - HIFI over HIFI
  * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
  */
-static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
+static const struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
 	.hw_params	= wm8753_i2s_hw_params,
 	.digital_mute	= wm8753_mute,
 	.set_fmt	= wm8753_hifi_set_dai_fmt,
@@ -1335,7 +1323,7 @@
 	.set_sysclk	= wm8753_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = {
+static const struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = {
 	.hw_params	= wm8753_pcm_hw_params,
 	.digital_mute	= wm8753_mute,
 	.set_fmt	= wm8753_voice_set_dai_fmt,
@@ -1392,7 +1380,7 @@
 	wm8753_set_bias_level(codec, dapm->bias_level);
 }
 
-static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8753_suspend(struct snd_soc_codec *codec)
 {
 	wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -1467,10 +1455,6 @@
 	snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100);
 	snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
 
-	snd_soc_add_controls(codec, wm8753_snd_controls,
-			     ARRAY_SIZE(wm8753_snd_controls));
-	wm8753_add_widgets(codec);
-
 	return 0;
 }
 
@@ -1492,6 +1476,13 @@
 	.reg_cache_size = ARRAY_SIZE(wm8753_reg),
 	.reg_word_size = sizeof(u16),
 	.reg_cache_default = wm8753_reg,
+
+	.controls = wm8753_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8753_snd_controls),
+	.dapm_widgets = wm8753_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets),
+	.dapm_routes = wm8753_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes),
 };
 
 static const struct of_device_id wm8753_of_match[] = {
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index aa05e65..8976eb5 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 #include <linux/of_device.h>
 #include <linux/pm.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -528,7 +527,7 @@
 #define WM8770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8770_dai_ops = {
+static const struct snd_soc_dai_ops wm8770_dai_ops = {
 	.digital_mute = wm8770_mute,
 	.hw_params = wm8770_hw_params,
 	.set_fmt = wm8770_set_fmt,
@@ -556,7 +555,7 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8770_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8770_suspend(struct snd_soc_codec *codec)
 {
 	wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index bfdc523..fbf80c5 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -19,7 +19,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/of_device.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -327,14 +326,14 @@
 #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8776_dac_ops = {
+static const struct snd_soc_dai_ops wm8776_dac_ops = {
 	.digital_mute	= wm8776_mute,
 	.hw_params      = wm8776_hw_params,
 	.set_fmt        = wm8776_set_fmt,
 	.set_sysclk     = wm8776_set_sysclk,
 };
 
-static struct snd_soc_dai_ops wm8776_adc_ops = {
+static const struct snd_soc_dai_ops wm8776_adc_ops = {
 	.hw_params      = wm8776_hw_params,
 	.set_fmt        = wm8776_set_fmt,
 	.set_sysclk     = wm8776_set_sysclk,
@@ -372,7 +371,7 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8776_suspend(struct snd_soc_codec *codec)
 {
 	wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -392,7 +391,6 @@
 static int wm8776_probe(struct snd_soc_codec *codec)
 {
 	struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret = 0;
 
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type);
@@ -414,12 +412,6 @@
 	snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
 	snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
 
-	snd_soc_add_controls(codec, wm8776_snd_controls,
-			     ARRAY_SIZE(wm8776_snd_controls));
-	snd_soc_dapm_new_controls(dapm, wm8776_dapm_widgets,
-				  ARRAY_SIZE(wm8776_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
-
 	return ret;
 }
 
@@ -439,6 +431,13 @@
 	.reg_cache_size = ARRAY_SIZE(wm8776_reg),
 	.reg_word_size = sizeof(u16),
 	.reg_cache_default = wm8776_reg,
+
+	.controls = wm8776_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8776_snd_controls),
+	.dapm_widgets = wm8776_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8776_dapm_widgets),
+	.dapm_routes = routes,
+	.num_dapm_routes = ARRAY_SIZE(routes),
 };
 
 static const struct of_device_id wm8776_of_match[] = {
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c
index f2ced71..3fdea98 100644
--- a/sound/soc/codecs/wm8782.c
+++ b/sound/soc/codecs/wm8782.c
@@ -63,17 +63,7 @@
 	.remove = __devexit_p(wm8782_remove),
 };
 
-static int __init wm8782_init(void)
-{
-	return platform_driver_register(&wm8782_codec_driver);
-}
-module_init(wm8782_init);
-
-static void __exit wm8782_exit(void)
-{
-	platform_driver_unregister(&wm8782_codec_driver);
-}
-module_exit(wm8782_exit);
+module_platform_driver(wm8782_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM8782 driver");
 MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>");
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 9ee072b..ae4b8fb 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -542,7 +542,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm8804_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8804_suspend(struct snd_soc_codec *codec)
 {
 	wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -670,7 +670,7 @@
 	return ret;
 }
 
-static struct snd_soc_dai_ops wm8804_dai_ops = {
+static const struct snd_soc_dai_ops wm8804_dai_ops = {
 	.hw_params = wm8804_hw_params,
 	.set_fmt = wm8804_set_fmt,
 	.set_sysclk = wm8804_set_sysclk,
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 3d0dc15..85632ff 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -24,7 +24,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -513,7 +512,7 @@
 		   wm8900_rinmix_controls,
 		   ARRAY_SIZE(wm8900_rinmix_controls)),
 
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8900_REG_POWER1, 4, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias", WM8900_REG_POWER1, 4, 0, NULL, 0),
 
 SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0),
 SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0),
@@ -987,7 +986,7 @@
 	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
 	 SNDRV_PCM_FORMAT_S24_LE)
 
-static struct snd_soc_dai_ops wm8900_dai_ops = {
+static const struct snd_soc_dai_ops wm8900_dai_ops = {
 	.hw_params	= wm8900_hw_params,
 	.set_clkdiv	= wm8900_set_dai_clkdiv,
 	.set_pll	= wm8900_set_dai_pll,
@@ -1107,7 +1106,7 @@
 	return 0;
 }
 
-static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8900_suspend(struct snd_soc_codec *codec)
 {
 	struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
 	int fll_out = wm8900->fll_out;
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 4ad8ebd..a75688b 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -23,7 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/jack.h>
@@ -38,184 +38,84 @@
 #include "wm8903.h"
 
 /* Register defaults at reset */
-static u16 wm8903_reg_defaults[] = {
-	0x8903,     /* R0   - SW Reset and ID */
-	0x0000,     /* R1   - Revision Number */
-	0x0000,     /* R2 */
-	0x0000,     /* R3 */
-	0x0018,     /* R4   - Bias Control 0 */
-	0x0000,     /* R5   - VMID Control 0 */
-	0x0000,     /* R6   - Mic Bias Control 0 */
-	0x0000,     /* R7 */
-	0x0001,     /* R8   - Analogue DAC 0 */
-	0x0000,     /* R9 */
-	0x0001,     /* R10  - Analogue ADC 0 */
-	0x0000,     /* R11 */
-	0x0000,     /* R12  - Power Management 0 */
-	0x0000,     /* R13  - Power Management 1 */
-	0x0000,     /* R14  - Power Management 2 */
-	0x0000,     /* R15  - Power Management 3 */
-	0x0000,     /* R16  - Power Management 4 */
-	0x0000,     /* R17  - Power Management 5 */
-	0x0000,     /* R18  - Power Management 6 */
-	0x0000,     /* R19 */
-	0x0400,     /* R20  - Clock Rates 0 */
-	0x0D07,     /* R21  - Clock Rates 1 */
-	0x0000,     /* R22  - Clock Rates 2 */
-	0x0000,     /* R23 */
-	0x0050,     /* R24  - Audio Interface 0 */
-	0x0242,     /* R25  - Audio Interface 1 */
-	0x0008,     /* R26  - Audio Interface 2 */
-	0x0022,     /* R27  - Audio Interface 3 */
-	0x0000,     /* R28 */
-	0x0000,     /* R29 */
-	0x00C0,     /* R30  - DAC Digital Volume Left */
-	0x00C0,     /* R31  - DAC Digital Volume Right */
-	0x0000,     /* R32  - DAC Digital 0 */
-	0x0000,     /* R33  - DAC Digital 1 */
-	0x0000,     /* R34 */
-	0x0000,     /* R35 */
-	0x00C0,     /* R36  - ADC Digital Volume Left */
-	0x00C0,     /* R37  - ADC Digital Volume Right */
-	0x0000,     /* R38  - ADC Digital 0 */
-	0x0073,     /* R39  - Digital Microphone 0 */
-	0x09BF,     /* R40  - DRC 0 */
-	0x3241,     /* R41  - DRC 1 */
-	0x0020,     /* R42  - DRC 2 */
-	0x0000,     /* R43  - DRC 3 */
-	0x0085,     /* R44  - Analogue Left Input 0 */
-	0x0085,     /* R45  - Analogue Right Input 0 */
-	0x0044,     /* R46  - Analogue Left Input 1 */
-	0x0044,     /* R47  - Analogue Right Input 1 */
-	0x0000,     /* R48 */
-	0x0000,     /* R49 */
-	0x0008,     /* R50  - Analogue Left Mix 0 */
-	0x0004,     /* R51  - Analogue Right Mix 0 */
-	0x0000,     /* R52  - Analogue Spk Mix Left 0 */
-	0x0000,     /* R53  - Analogue Spk Mix Left 1 */
-	0x0000,     /* R54  - Analogue Spk Mix Right 0 */
-	0x0000,     /* R55  - Analogue Spk Mix Right 1 */
-	0x0000,     /* R56 */
-	0x002D,     /* R57  - Analogue OUT1 Left */
-	0x002D,     /* R58  - Analogue OUT1 Right */
-	0x0039,     /* R59  - Analogue OUT2 Left */
-	0x0039,     /* R60  - Analogue OUT2 Right */
-	0x0100,     /* R61 */
-	0x0139,     /* R62  - Analogue OUT3 Left */
-	0x0139,     /* R63  - Analogue OUT3 Right */
-	0x0000,     /* R64 */
-	0x0000,     /* R65  - Analogue SPK Output Control 0 */
-	0x0000,     /* R66 */
-	0x0010,     /* R67  - DC Servo 0 */
-	0x0100,     /* R68 */
-	0x00A4,     /* R69  - DC Servo 2 */
-	0x0807,     /* R70 */
-	0x0000,     /* R71 */
-	0x0000,     /* R72 */
-	0x0000,     /* R73 */
-	0x0000,     /* R74 */
-	0x0000,     /* R75 */
-	0x0000,     /* R76 */
-	0x0000,     /* R77 */
-	0x0000,     /* R78 */
-	0x000E,     /* R79 */
-	0x0000,     /* R80 */
-	0x0000,     /* R81 */
-	0x0000,     /* R82 */
-	0x0000,     /* R83 */
-	0x0000,     /* R84 */
-	0x0000,     /* R85 */
-	0x0000,     /* R86 */
-	0x0006,     /* R87 */
-	0x0000,     /* R88 */
-	0x0000,     /* R89 */
-	0x0000,     /* R90  - Analogue HP 0 */
-	0x0060,     /* R91 */
-	0x0000,     /* R92 */
-	0x0000,     /* R93 */
-	0x0000,     /* R94  - Analogue Lineout 0 */
-	0x0060,     /* R95 */
-	0x0000,     /* R96 */
-	0x0000,     /* R97 */
-	0x0000,     /* R98  - Charge Pump 0 */
-	0x1F25,     /* R99 */
-	0x2B19,     /* R100 */
-	0x01C0,     /* R101 */
-	0x01EF,     /* R102 */
-	0x2B00,     /* R103 */
-	0x0000,     /* R104 - Class W 0 */
-	0x01C0,     /* R105 */
-	0x1C10,     /* R106 */
-	0x0000,     /* R107 */
-	0x0000,     /* R108 - Write Sequencer 0 */
-	0x0000,     /* R109 - Write Sequencer 1 */
-	0x0000,     /* R110 - Write Sequencer 2 */
-	0x0000,     /* R111 - Write Sequencer 3 */
-	0x0000,     /* R112 - Write Sequencer 4 */
-	0x0000,     /* R113 */
-	0x0000,     /* R114 - Control Interface */
-	0x0000,     /* R115 */
-	0x00A8,     /* R116 - GPIO Control 1 */
-	0x00A8,     /* R117 - GPIO Control 2 */
-	0x00A8,     /* R118 - GPIO Control 3 */
-	0x0220,     /* R119 - GPIO Control 4 */
-	0x01A0,     /* R120 - GPIO Control 5 */
-	0x0000,     /* R121 - Interrupt Status 1 */
-	0xFFFF,     /* R122 - Interrupt Status 1 Mask */
-	0x0000,     /* R123 - Interrupt Polarity 1 */
-	0x0000,     /* R124 */
-	0x0003,     /* R125 */
-	0x0000,     /* R126 - Interrupt Control */
-	0x0000,     /* R127 */
-	0x0005,     /* R128 */
-	0x0000,     /* R129 - Control Interface Test 1 */
-	0x0000,     /* R130 */
-	0x0000,     /* R131 */
-	0x0000,     /* R132 */
-	0x0000,     /* R133 */
-	0x0000,     /* R134 */
-	0x03FF,     /* R135 */
-	0x0007,     /* R136 */
-	0x0040,     /* R137 */
-	0x0000,     /* R138 */
-	0x0000,     /* R139 */
-	0x0000,     /* R140 */
-	0x0000,     /* R141 */
-	0x0000,     /* R142 */
-	0x0000,     /* R143 */
-	0x0000,     /* R144 */
-	0x0000,     /* R145 */
-	0x0000,     /* R146 */
-	0x0000,     /* R147 */
-	0x4000,     /* R148 */
-	0x6810,     /* R149 - Charge Pump Test 1 */
-	0x0004,     /* R150 */
-	0x0000,     /* R151 */
-	0x0000,     /* R152 */
-	0x0000,     /* R153 */
-	0x0000,     /* R154 */
-	0x0000,     /* R155 */
-	0x0000,     /* R156 */
-	0x0000,     /* R157 */
-	0x0000,     /* R158 */
-	0x0000,     /* R159 */
-	0x0000,     /* R160 */
-	0x0000,     /* R161 */
-	0x0000,     /* R162 */
-	0x0000,     /* R163 */
-	0x0028,     /* R164 - Clock Rate Test 4 */
-	0x0004,     /* R165 */
-	0x0000,     /* R166 */
-	0x0060,     /* R167 */
-	0x0000,     /* R168 */
-	0x0000,     /* R169 */
-	0x0000,     /* R170 */
-	0x0000,     /* R171 */
-	0x0000,     /* R172 - Analogue Output Bias 0 */
+static const struct reg_default wm8903_reg_defaults[] = {
+	{ 4,  0x0018 },     /* R4   - Bias Control 0 */
+	{ 5,  0x0000 },     /* R5   - VMID Control 0 */
+	{ 6,  0x0000 },     /* R6   - Mic Bias Control 0 */
+	{ 8,  0x0001 },     /* R8   - Analogue DAC 0 */
+	{ 10, 0x0001 },     /* R10  - Analogue ADC 0 */
+	{ 12, 0x0000 },     /* R12  - Power Management 0 */
+	{ 13, 0x0000 },     /* R13  - Power Management 1 */
+	{ 14, 0x0000 },     /* R14  - Power Management 2 */
+	{ 15, 0x0000 },     /* R15  - Power Management 3 */
+	{ 16, 0x0000 },     /* R16  - Power Management 4 */
+	{ 17, 0x0000 },     /* R17  - Power Management 5 */
+	{ 18, 0x0000 },     /* R18  - Power Management 6 */
+	{ 20, 0x0400 },     /* R20  - Clock Rates 0 */
+	{ 21, 0x0D07 },     /* R21  - Clock Rates 1 */
+	{ 22, 0x0000 },     /* R22  - Clock Rates 2 */
+	{ 24, 0x0050 },     /* R24  - Audio Interface 0 */
+	{ 25, 0x0242 },     /* R25  - Audio Interface 1 */
+	{ 26, 0x0008 },     /* R26  - Audio Interface 2 */
+	{ 27, 0x0022 },     /* R27  - Audio Interface 3 */
+	{ 30, 0x00C0 },     /* R30  - DAC Digital Volume Left */
+	{ 31, 0x00C0 },     /* R31  - DAC Digital Volume Right */
+	{ 32, 0x0000 },     /* R32  - DAC Digital 0 */
+	{ 33, 0x0000 },     /* R33  - DAC Digital 1 */
+	{ 36, 0x00C0 },     /* R36  - ADC Digital Volume Left */
+	{ 37, 0x00C0 },     /* R37  - ADC Digital Volume Right */
+	{ 38, 0x0000 },     /* R38  - ADC Digital 0 */
+	{ 39, 0x0073 },     /* R39  - Digital Microphone 0 */
+	{ 40, 0x09BF },     /* R40  - DRC 0 */
+	{ 41, 0x3241 },     /* R41  - DRC 1 */
+	{ 42, 0x0020 },     /* R42  - DRC 2 */
+	{ 43, 0x0000 },     /* R43  - DRC 3 */
+	{ 44, 0x0085 },     /* R44  - Analogue Left Input 0 */
+	{ 45, 0x0085 },     /* R45  - Analogue Right Input 0 */
+	{ 46, 0x0044 },     /* R46  - Analogue Left Input 1 */
+	{ 47, 0x0044 },     /* R47  - Analogue Right Input 1 */
+	{ 50, 0x0008 },     /* R50  - Analogue Left Mix 0 */
+	{ 51, 0x0004 },     /* R51  - Analogue Right Mix 0 */
+	{ 52, 0x0000 },     /* R52  - Analogue Spk Mix Left 0 */
+	{ 53, 0x0000 },     /* R53  - Analogue Spk Mix Left 1 */
+	{ 54, 0x0000 },     /* R54  - Analogue Spk Mix Right 0 */
+	{ 55, 0x0000 },     /* R55  - Analogue Spk Mix Right 1 */
+	{ 57, 0x002D },     /* R57  - Analogue OUT1 Left */
+	{ 58, 0x002D },     /* R58  - Analogue OUT1 Right */
+	{ 59, 0x0039 },     /* R59  - Analogue OUT2 Left */
+	{ 60, 0x0039 },     /* R60  - Analogue OUT2 Right */
+	{ 62, 0x0139 },     /* R62  - Analogue OUT3 Left */
+	{ 63, 0x0139 },     /* R63  - Analogue OUT3 Right */
+	{ 64, 0x0000 },     /* R65  - Analogue SPK Output Control 0 */
+	{ 67, 0x0010 },     /* R67  - DC Servo 0 */
+	{ 69, 0x00A4 },     /* R69  - DC Servo 2 */
+	{ 90, 0x0000 },     /* R90  - Analogue HP 0 */
+	{ 94, 0x0000 },     /* R94  - Analogue Lineout 0 */
+	{ 98, 0x0000 },     /* R98  - Charge Pump 0 */
+	{ 104, 0x0000 },    /* R104 - Class W 0 */
+	{ 108, 0x0000 },    /* R108 - Write Sequencer 0 */
+	{ 109, 0x0000 },    /* R109 - Write Sequencer 1 */
+	{ 110, 0x0000 },    /* R110 - Write Sequencer 2 */
+	{ 111, 0x0000 },    /* R111 - Write Sequencer 3 */
+	{ 112, 0x0000 },    /* R112 - Write Sequencer 4 */
+	{ 114, 0x0000 },    /* R114 - Control Interface */
+	{ 116, 0x00A8 },    /* R116 - GPIO Control 1 */
+	{ 117, 0x00A8 },    /* R117 - GPIO Control 2 */
+	{ 118, 0x00A8 },    /* R118 - GPIO Control 3 */
+	{ 119, 0x0220 },    /* R119 - GPIO Control 4 */
+	{ 120, 0x01A0 },    /* R120 - GPIO Control 5 */
+	{ 122, 0xFFFF },    /* R122 - Interrupt Status 1 Mask */
+	{ 123, 0x0000 },    /* R123 - Interrupt Polarity 1 */
+	{ 126, 0x0000 },    /* R126 - Interrupt Control */
+	{ 129, 0x0000 },    /* R129 - Control Interface Test 1 */
+	{ 149, 0x6810 },    /* R149 - Charge Pump Test 1 */
+	{ 164, 0x0028 },    /* R164 - Clock Rate Test 4 */
+	{ 172, 0x0000 },    /* R172 - Analogue Output Bias 0 */
 };
 
 struct wm8903_priv {
 	struct snd_soc_codec *codec;
+	struct regmap *regmap;
 
 	int sysclk;
 	int irq;
@@ -240,7 +140,93 @@
 #endif
 };
 
-static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8903_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM8903_SW_RESET_AND_ID:
+	case WM8903_REVISION_NUMBER:
+	case WM8903_BIAS_CONTROL_0:
+	case WM8903_VMID_CONTROL_0:
+	case WM8903_MIC_BIAS_CONTROL_0:
+	case WM8903_ANALOGUE_DAC_0:
+	case WM8903_ANALOGUE_ADC_0:
+	case WM8903_POWER_MANAGEMENT_0:
+	case WM8903_POWER_MANAGEMENT_1:
+	case WM8903_POWER_MANAGEMENT_2:
+	case WM8903_POWER_MANAGEMENT_3:
+	case WM8903_POWER_MANAGEMENT_4:
+	case WM8903_POWER_MANAGEMENT_5:
+	case WM8903_POWER_MANAGEMENT_6:
+	case WM8903_CLOCK_RATES_0:
+	case WM8903_CLOCK_RATES_1:
+	case WM8903_CLOCK_RATES_2:
+	case WM8903_AUDIO_INTERFACE_0:
+	case WM8903_AUDIO_INTERFACE_1:
+	case WM8903_AUDIO_INTERFACE_2:
+	case WM8903_AUDIO_INTERFACE_3:
+	case WM8903_DAC_DIGITAL_VOLUME_LEFT:
+	case WM8903_DAC_DIGITAL_VOLUME_RIGHT:
+	case WM8903_DAC_DIGITAL_0:
+	case WM8903_DAC_DIGITAL_1:
+	case WM8903_ADC_DIGITAL_VOLUME_LEFT:
+	case WM8903_ADC_DIGITAL_VOLUME_RIGHT:
+	case WM8903_ADC_DIGITAL_0:
+	case WM8903_DIGITAL_MICROPHONE_0:
+	case WM8903_DRC_0:
+	case WM8903_DRC_1:
+	case WM8903_DRC_2:
+	case WM8903_DRC_3:
+	case WM8903_ANALOGUE_LEFT_INPUT_0:
+	case WM8903_ANALOGUE_RIGHT_INPUT_0:
+	case WM8903_ANALOGUE_LEFT_INPUT_1:
+	case WM8903_ANALOGUE_RIGHT_INPUT_1:
+	case WM8903_ANALOGUE_LEFT_MIX_0:
+	case WM8903_ANALOGUE_RIGHT_MIX_0:
+	case WM8903_ANALOGUE_SPK_MIX_LEFT_0:
+	case WM8903_ANALOGUE_SPK_MIX_LEFT_1:
+	case WM8903_ANALOGUE_SPK_MIX_RIGHT_0:
+	case WM8903_ANALOGUE_SPK_MIX_RIGHT_1:
+	case WM8903_ANALOGUE_OUT1_LEFT:
+	case WM8903_ANALOGUE_OUT1_RIGHT:
+	case WM8903_ANALOGUE_OUT2_LEFT:
+	case WM8903_ANALOGUE_OUT2_RIGHT:
+	case WM8903_ANALOGUE_OUT3_LEFT:
+	case WM8903_ANALOGUE_OUT3_RIGHT:
+	case WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0:
+	case WM8903_DC_SERVO_0:
+	case WM8903_DC_SERVO_2:
+	case WM8903_DC_SERVO_READBACK_1:
+	case WM8903_DC_SERVO_READBACK_2:
+	case WM8903_DC_SERVO_READBACK_3:
+	case WM8903_DC_SERVO_READBACK_4:
+	case WM8903_ANALOGUE_HP_0:
+	case WM8903_ANALOGUE_LINEOUT_0:
+	case WM8903_CHARGE_PUMP_0:
+	case WM8903_CLASS_W_0:
+	case WM8903_WRITE_SEQUENCER_0:
+	case WM8903_WRITE_SEQUENCER_1:
+	case WM8903_WRITE_SEQUENCER_2:
+	case WM8903_WRITE_SEQUENCER_3:
+	case WM8903_WRITE_SEQUENCER_4:
+	case WM8903_CONTROL_INTERFACE:
+	case WM8903_GPIO_CONTROL_1:
+	case WM8903_GPIO_CONTROL_2:
+	case WM8903_GPIO_CONTROL_3:
+	case WM8903_GPIO_CONTROL_4:
+	case WM8903_GPIO_CONTROL_5:
+	case WM8903_INTERRUPT_STATUS_1:
+	case WM8903_INTERRUPT_STATUS_1_MASK:
+	case WM8903_INTERRUPT_POLARITY_1:
+	case WM8903_INTERRUPT_CONTROL:
+	case WM8903_CLOCK_RATE_TEST_4:
+	case WM8903_ANALOGUE_OUTPUT_BIAS_0:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool wm8903_volatile_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case WM8903_SW_RESET_AND_ID:
@@ -258,13 +244,6 @@
 	}
 }
 
-static void wm8903_reset(struct snd_soc_codec *codec)
-{
-	snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0);
-	memcpy(codec->reg_cache, wm8903_reg_defaults,
-	       sizeof(wm8903_reg_defaults));
-}
-
 static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
 			   struct snd_kcontrol *kcontrol, int event)
 {
@@ -839,7 +818,7 @@
 SND_SOC_DAPM_OUTPUT("ROP"),
 SND_SOC_DAPM_OUTPUT("RON"),
 
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8903_MIC_BIAS_CONTROL_0, 0, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8903_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0),
 
 SND_SOC_DAPM_MUX("Left Input Mux", SND_SOC_NOPM, 0, 0, &linput_mux),
 SND_SOC_DAPM_MUX("Left Input Inverting Mux", SND_SOC_NOPM, 0, 0,
@@ -948,7 +927,7 @@
 static const struct snd_soc_dapm_route wm8903_intercon[] = {
 
 	{ "CLK_DSP", NULL, "CLK_SYS" },
-	{ "Mic Bias", NULL, "CLK_SYS" },
+	{ "MICBIAS", NULL, "CLK_SYS" },
 	{ "HPL_DCS", NULL, "CLK_SYS" },
 	{ "HPR_DCS", NULL, "CLK_SYS" },
 	{ "LINEOUTL_DCS", NULL, "CLK_SYS" },
@@ -1732,7 +1711,7 @@
 			SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8903_dai_ops = {
+static const struct snd_soc_dai_ops wm8903_dai_ops = {
 	.hw_params	= wm8903_hw_params,
 	.digital_mute	= wm8903_digital_mute,
 	.set_fmt	= wm8903_set_dai_fmt,
@@ -1759,7 +1738,7 @@
 	.symmetric_rates = 1,
 };
 
-static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8903_suspend(struct snd_soc_codec *codec)
 {
 	wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1768,24 +1747,12 @@
 
 static int wm8903_resume(struct snd_soc_codec *codec)
 {
-	int i;
-	u16 *reg_cache = codec->reg_cache;
-	u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults),
-				 GFP_KERNEL);
+	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 
-	/* Bring the codec back up to standby first to minimise pop/clicks */
+	regcache_sync(wm8903->regmap);
+
 	wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	/* Sync back everything else */
-	if (tmp_cache) {
-		for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
-			if (tmp_cache[i] != reg_cache[i])
-				snd_soc_write(codec, i, tmp_cache[i]);
-		kfree(tmp_cache);
-	} else {
-		dev_err(codec->dev, "Failed to allocate temporary cache\n");
-	}
-
 	return 0;
 }
 
@@ -1912,36 +1879,24 @@
 	u16 val;
 
 	wm8903->codec = codec;
+	codec->control_data = wm8903->regmap;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
 	}
 
-	val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
-	if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
-		dev_err(codec->dev,
-			"Device with ID register %x is not a WM8903\n", val);
-		return -ENODEV;
-	}
-
-	val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
-	dev_info(codec->dev, "WM8903 revision %c\n",
-		 (val & WM8903_CHIP_REV_MASK) + 'A');
-
-	wm8903_reset(codec);
-
 	/* Set up GPIOs and microphone detection */
 	if (pdata) {
 		bool mic_gpio = false;
 
 		for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
-			if (pdata->gpio_cfg[i] == WM8903_GPIO_NO_CONFIG)
+			if (pdata->gpio_cfg[i] > 0x7fff)
 				continue;
 
 			snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
-				      pdata->gpio_cfg[i] & 0xffff);
+				      pdata->gpio_cfg[i] & 0x7fff);
 
 			val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
 				>> WM8903_GP1_FN_SHIFT;
@@ -2035,9 +1990,6 @@
 			    WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE,
 			    WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE);
 
-	snd_soc_add_controls(codec, wm8903_snd_controls,
-				ARRAY_SIZE(wm8903_snd_controls));
-
 	wm8903_init_gpio(codec);
 
 	return ret;
@@ -2062,42 +2014,91 @@
 	.suspend =	wm8903_suspend,
 	.resume =	wm8903_resume,
 	.set_bias_level = wm8903_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8903_reg_defaults,
-	.volatile_register = wm8903_volatile_register,
 	.seq_notifier = wm8903_seq_notifier,
+	.controls = wm8903_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8903_snd_controls),
 	.dapm_widgets = wm8903_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets),
 	.dapm_routes = wm8903_intercon,
 	.num_dapm_routes = ARRAY_SIZE(wm8903_intercon),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static const struct regmap_config wm8903_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+
+	.max_register = WM8903_MAX_REGISTER,
+	.volatile_reg = wm8903_volatile_register,
+	.readable_reg = wm8903_readable_register,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8903_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8903_reg_defaults),
+};
+
 static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8903_priv *wm8903;
+	unsigned int val;
 	int ret;
 
-	wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
+	wm8903 = devm_kzalloc(&i2c->dev,  sizeof(struct wm8903_priv),
+			      GFP_KERNEL);
 	if (wm8903 == NULL)
 		return -ENOMEM;
 
+	wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap);
+	if (IS_ERR(wm8903->regmap)) {
+		ret = PTR_ERR(wm8903->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
 	i2c_set_clientdata(i2c, wm8903);
 	wm8903->irq = i2c->irq;
 
+	ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+		goto err;
+	}
+	if (val != 0x8903) {
+		dev_err(&i2c->dev, "Device with ID %x is not a WM8903\n", val);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ret = regmap_read(wm8903->regmap, WM8903_REVISION_NUMBER, &val);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret);
+		goto err;
+	}
+	dev_info(&i2c->dev, "WM8903 revision %c\n",
+		 (val & WM8903_CHIP_REV_MASK) + 'A');
+
+	/* Reset the device */
+	regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903);
+
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8903, &wm8903_dai, 1);
-	if (ret < 0)
-		kfree(wm8903);
+	if (ret != 0)
+		goto err;
+
+	return 0;
+err:
+	regmap_exit(wm8903->regmap);
 	return ret;
 }
 
 static __devexit int wm8903_i2c_remove(struct i2c_client *client)
 {
+	struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
+
+	regmap_exit(wm8903->regmap);
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+
 	return 0;
 }
 
@@ -2116,27 +2117,22 @@
 	.remove =   __devexit_p(wm8903_i2c_remove),
 	.id_table = wm8903_i2c_id,
 };
-#endif
 
 static int __init wm8903_modinit(void)
 {
 	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&wm8903_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n",
 		       ret);
 	}
-#endif
 	return ret;
 }
 module_init(wm8903_modinit);
 
 static void __exit wm8903_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8903_i2c_driver);
-#endif
 }
 module_exit(wm8903_exit);
 
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 285ef87..f0ae01b 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -1196,7 +1195,7 @@
 SND_SOC_DAPM_INPUT("IN3L"),
 SND_SOC_DAPM_INPUT("IN3R"),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0),
 
 SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lin_mux),
 SND_SOC_DAPM_MUX("Left Capture Inverting Mux", SND_SOC_NOPM, 0, 0,
@@ -2205,7 +2204,7 @@
 #define WM8904_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8904_dai_ops = {
+static const struct snd_soc_dai_ops wm8904_dai_ops = {
 	.set_sysclk = wm8904_set_sysclk,
 	.set_fmt = wm8904_set_fmt,
 	.set_tdm_slot = wm8904_set_tdm_slot,
@@ -2235,7 +2234,7 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8904_suspend(struct snd_soc_codec *codec)
 {
 	wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index de9ec9b..0fe4545 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -28,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -629,8 +628,8 @@
 		ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
 		break;
 	case WM8940_OPCLKDIV:
-		reg = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFCF;
-		ret = snd_soc_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
+		reg = snd_soc_read(codec, WM8940_GPIO) & 0xFFCF;
+		ret = snd_soc_write(codec, WM8940_GPIO, reg | (div << 4));
 		break;
 	}
 	return ret;
@@ -644,7 +643,7 @@
 			SNDRV_PCM_FMTBIT_S24_LE |			\
 			SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8940_dai_ops = {
+static const struct snd_soc_dai_ops wm8940_dai_ops = {
 	.hw_params = wm8940_i2s_hw_params,
 	.set_sysclk = wm8940_set_dai_sysclk,
 	.digital_mute = wm8940_mute,
@@ -673,7 +672,7 @@
 	.symmetric_rates = 1,
 };
 
-static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8940_suspend(struct snd_soc_codec *codec)
 {
 	return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 3c71987..cdd5139 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -859,7 +858,7 @@
 #define WM8955_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8955_dai_ops = {
+static const struct snd_soc_dai_ops wm8955_dai_ops = {
 	.set_sysclk = wm8955_set_sysclk,
 	.set_fmt = wm8955_set_fmt,
 	.hw_params = wm8955_hw_params,
@@ -879,7 +878,7 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8955_suspend(struct snd_soc_codec *codec)
 {
 	wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 0293763..39e9557 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -55,7 +55,8 @@
 		return 0;
 
 	if (fw->size < 32) {
-		dev_err(codec->dev, "%s: firmware too short\n", name);
+		dev_err(codec->dev, "%s: firmware too short (%d bytes)\n",
+			name, fw->size);
 		goto err;
 	}
 
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 2df253c..55b9a25 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -14,7 +14,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -265,7 +264,7 @@
 SND_SOC_DAPM_INPUT("LINPUT3"),
 SND_SOC_DAPM_INPUT("RINPUT3"),
 
-SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICB", WM8960_POWER1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,
 		   wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)),
@@ -869,7 +868,7 @@
 	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8960_dai_ops = {
+static const struct snd_soc_dai_ops wm8960_dai_ops = {
 	.hw_params = wm8960_hw_params,
 	.digital_mute = wm8960_mute,
 	.set_fmt = wm8960_set_dai_fmt,
@@ -895,7 +894,7 @@
 	.symmetric_rates = 1,
 };
 
-static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8960_suspend(struct snd_soc_codec *codec)
 {
 	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 9568c8a..9bcf846 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -531,7 +530,7 @@
 SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0),
 SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8961_PWR_MGMT_1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux),
 SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux),
@@ -929,7 +928,7 @@
 	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8961_dai_ops = {
+static const struct snd_soc_dai_ops wm8961_dai_ops = {
 	.hw_params = wm8961_hw_params,
 	.set_sysclk = wm8961_set_sysclk,
 	.set_fmt = wm8961_set_fmt,
@@ -1039,7 +1038,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8961_suspend(struct snd_soc_codec *codec)
 {
 	wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 53edd9a..be35b64 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -20,7 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -50,6 +50,7 @@
 
 /* codec private data */
 struct wm8962_priv {
+	struct regmap *regmap;
 	struct snd_soc_codec *codec;
 
 	int sysclk;
@@ -95,7 +96,7 @@
 	struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
 						  disable_nb[n]); \
 	if (event & REGULATOR_EVENT_DISABLE) { \
-		wm8962->codec->cache_sync = 1; \
+		regcache_cache_only(wm8962->regmap, true);	\
 	} \
 	return 0; \
 }
@@ -109,691 +110,691 @@
 WM8962_REGULATOR_EVENT(6)
 WM8962_REGULATOR_EVENT(7)
 
-static const u16 wm8962_reg[WM8962_MAX_REGISTER + 1] = {
-	[0] = 0x009F,     /* R0     - Left Input volume */
-	[1] = 0x049F,     /* R1     - Right Input volume */
-	[2] = 0x0000,     /* R2     - HPOUTL volume */
-	[3] = 0x0000,     /* R3     - HPOUTR volume */
-	[4] = 0x0020,     /* R4     - Clocking1 */
-	[5] = 0x0018,     /* R5     - ADC & DAC Control 1 */
-	[6] = 0x2008,     /* R6     - ADC & DAC Control 2 */
-	[7] = 0x000A,     /* R7     - Audio Interface 0 */
-	[8] = 0x01E4,     /* R8     - Clocking2 */
-	[9] = 0x0300,     /* R9     - Audio Interface 1 */
-	[10] = 0x00C0,    /* R10    - Left DAC volume */
-	[11] = 0x00C0,    /* R11    - Right DAC volume */
+static struct reg_default wm8962_reg[] = {
+	{ 0, 0x009F },   /* R0     - Left Input volume */
+	{ 1, 0x049F },   /* R1     - Right Input volume */
+	{ 2, 0x0000 },   /* R2     - HPOUTL volume */
+	{ 3, 0x0000 },   /* R3     - HPOUTR volume */
+	{ 4, 0x0020 },   /* R4     - Clocking1 */
+	{ 5, 0x0018 },   /* R5     - ADC & DAC Control 1 */
+	{ 6, 0x2008 },   /* R6     - ADC & DAC Control 2 */
+	{ 7, 0x000A },   /* R7     - Audio Interface 0 */
+	{ 8, 0x01E4 },   /* R8     - Clocking2 */
+	{ 9, 0x0300 },   /* R9     - Audio Interface 1 */
+	{ 10, 0x00C0 },  /* R10    - Left DAC volume */
+	{ 11, 0x00C0 },  /* R11    - Right DAC volume */
 
-	[14] = 0x0040,     /* R14    - Audio Interface 2 */
-	[15] = 0x6243,     /* R15    - Software Reset */
+	{ 14, 0x0040 },   /* R14    - Audio Interface 2 */
+	{ 15, 0x6243 },   /* R15    - Software Reset */
 
-	[17] = 0x007B,     /* R17    - ALC1 */
-	[18] = 0x0000,     /* R18    - ALC2 */
-	[19] = 0x1C32,     /* R19    - ALC3 */
-	[20] = 0x3200,     /* R20    - Noise Gate */
-	[21] = 0x00C0,     /* R21    - Left ADC volume */
-	[22] = 0x00C0,     /* R22    - Right ADC volume */
-	[23] = 0x0160,     /* R23    - Additional control(1) */
-	[24] = 0x0000,     /* R24    - Additional control(2) */
-	[25] = 0x0000,     /* R25    - Pwr Mgmt (1) */
-	[26] = 0x0000,     /* R26    - Pwr Mgmt (2) */
-	[27] = 0x0010,     /* R27    - Additional Control (3) */
-	[28] = 0x0000,     /* R28    - Anti-pop */
+	{ 17, 0x007B },   /* R17    - ALC1 */
+	{ 18, 0x0000 },   /* R18    - ALC2 */
+	{ 19, 0x1C32 },   /* R19    - ALC3 */
+	{ 20, 0x3200 },   /* R20    - Noise Gate */
+	{ 21, 0x00C0 },   /* R21    - Left ADC volume */
+	{ 22, 0x00C0 },   /* R22    - Right ADC volume */
+	{ 23, 0x0160 },   /* R23    - Additional control(1) */
+	{ 24, 0x0000 },   /* R24    - Additional control(2) */
+	{ 25, 0x0000 },   /* R25    - Pwr Mgmt (1) */
+	{ 26, 0x0000 },   /* R26    - Pwr Mgmt (2) */
+	{ 27, 0x0010 },   /* R27    - Additional Control (3) */
+	{ 28, 0x0000 },   /* R28    - Anti-pop */
 
-	[30] = 0x005E,     /* R30    - Clocking 3 */
-	[31] = 0x0000,     /* R31    - Input mixer control (1) */
-	[32] = 0x0145,     /* R32    - Left input mixer volume */
-	[33] = 0x0145,     /* R33    - Right input mixer volume */
-	[34] = 0x0009,     /* R34    - Input mixer control (2) */
-	[35] = 0x0003,     /* R35    - Input bias control */
-	[37] = 0x0008,     /* R37    - Left input PGA control */
-	[38] = 0x0008,     /* R38    - Right input PGA control */
+	{ 30, 0x005E },   /* R30    - Clocking 3 */
+	{ 31, 0x0000 },   /* R31    - Input mixer control (1) */
+	{ 32, 0x0145 },   /* R32    - Left input mixer volume */
+	{ 33, 0x0145 },   /* R33    - Right input mixer volume */
+	{ 34, 0x0009 },   /* R34    - Input mixer control (2) */
+	{ 35, 0x0003 },   /* R35    - Input bias control */
+	{ 37, 0x0008 },   /* R37    - Left input PGA control */
+	{ 38, 0x0008 },   /* R38    - Right input PGA control */
 
-	[40] = 0x0000,     /* R40    - SPKOUTL volume */
-	[41] = 0x0000,     /* R41    - SPKOUTR volume */
+	{ 40, 0x0000 },   /* R40    - SPKOUTL volume */
+	{ 41, 0x0000 },   /* R41    - SPKOUTR volume */
 
-	[47] = 0x0000,     /* R47    - Thermal Shutdown Status */
-	[48] = 0x8027,     /* R48    - Additional Control (4) */
-	[49] = 0x0010,     /* R49    - Class D Control 1 */
+	{ 47, 0x0000 },   /* R47    - Thermal Shutdown Status */
+	{ 48, 0x8027 },   /* R48    - Additional Control (4) */
+	{ 49, 0x0010 },   /* R49    - Class D Control 1 */
 
-	[51] = 0x0003,     /* R51    - Class D Control 2 */
+	{ 51, 0x0003 },   /* R51    - Class D Control 2 */
 
-	[56] = 0x0506,     /* R56    - Clocking 4 */
-	[57] = 0x0000,     /* R57    - DAC DSP Mixing (1) */
-	[58] = 0x0000,     /* R58    - DAC DSP Mixing (2) */
+	{ 56, 0x0506 },   /* R56    - Clocking 4 */
+	{ 57, 0x0000 },   /* R57    - DAC DSP Mixing (1) */
+	{ 58, 0x0000 },   /* R58    - DAC DSP Mixing (2) */
 
-	[60] = 0x0300,     /* R60    - DC Servo 0 */
-	[61] = 0x0300,     /* R61    - DC Servo 1 */
+	{ 60, 0x0300 },   /* R60    - DC Servo 0 */
+	{ 61, 0x0300 },   /* R61    - DC Servo 1 */
 
-	[64] = 0x0810,     /* R64    - DC Servo 4 */
+	{ 64, 0x0810 },   /* R64    - DC Servo 4 */
 
-	[66] = 0x0000,     /* R66    - DC Servo 6 */
+	{ 66, 0x0000 },   /* R66    - DC Servo 6 */
 
-	[68] = 0x001B,     /* R68    - Analogue PGA Bias */
-	[69] = 0x0000,     /* R69    - Analogue HP 0 */
+	{ 68, 0x001B },   /* R68    - Analogue PGA Bias */
+	{ 69, 0x0000 },   /* R69    - Analogue HP 0 */
 
-	[71] = 0x01FB,     /* R71    - Analogue HP 2 */
-	[72] = 0x0000,     /* R72    - Charge Pump 1 */
+	{ 71, 0x01FB },   /* R71    - Analogue HP 2 */
+	{ 72, 0x0000 },   /* R72    - Charge Pump 1 */
 
-	[82] = 0x0004,     /* R82    - Charge Pump B */
+	{ 82, 0x0004 },   /* R82    - Charge Pump B */
 
-	[87] = 0x0000,     /* R87    - Write Sequencer Control 1 */
+	{ 87, 0x0000 },   /* R87    - Write Sequencer Control 1 */
 
-	[90] = 0x0000,     /* R90    - Write Sequencer Control 2 */
+	{ 90, 0x0000 },   /* R90    - Write Sequencer Control 2 */
 
-	[93] = 0x0000,     /* R93    - Write Sequencer Control 3 */
-	[94] = 0x0000,     /* R94    - Control Interface */
+	{ 93, 0x0000 },   /* R93    - Write Sequencer Control 3 */
+	{ 94, 0x0000 },   /* R94    - Control Interface */
 
-	[99] = 0x0000,     /* R99    - Mixer Enables */
-	[100] = 0x0000,     /* R100   - Headphone Mixer (1) */
-	[101] = 0x0000,     /* R101   - Headphone Mixer (2) */
-	[102] = 0x013F,     /* R102   - Headphone Mixer (3) */
-	[103] = 0x013F,     /* R103   - Headphone Mixer (4) */
+	{ 99, 0x0000 },   /* R99    - Mixer Enables */
+	{ 100, 0x0000 },   /* R100   - Headphone Mixer (1) */
+	{ 101, 0x0000 },   /* R101   - Headphone Mixer (2) */
+	{ 102, 0x013F },   /* R102   - Headphone Mixer (3) */
+	{ 103, 0x013F },   /* R103   - Headphone Mixer (4) */
 
-	[105] = 0x0000,     /* R105   - Speaker Mixer (1) */
-	[106] = 0x0000,     /* R106   - Speaker Mixer (2) */
-	[107] = 0x013F,     /* R107   - Speaker Mixer (3) */
-	[108] = 0x013F,     /* R108   - Speaker Mixer (4) */
-	[109] = 0x0003,     /* R109   - Speaker Mixer (5) */
-	[110] = 0x0002,     /* R110   - Beep Generator (1) */
+	{ 105, 0x0000 },   /* R105   - Speaker Mixer (1) */
+	{ 106, 0x0000 },   /* R106   - Speaker Mixer (2) */
+	{ 107, 0x013F },   /* R107   - Speaker Mixer (3) */
+	{ 108, 0x013F },   /* R108   - Speaker Mixer (4) */
+	{ 109, 0x0003 },   /* R109   - Speaker Mixer (5) */
+	{ 110, 0x0002 },   /* R110   - Beep Generator (1) */
 
-	[115] = 0x0006,     /* R115   - Oscillator Trim (3) */
-	[116] = 0x0026,     /* R116   - Oscillator Trim (4) */
+	{ 115, 0x0006 },   /* R115   - Oscillator Trim (3) */
+	{ 116, 0x0026 },   /* R116   - Oscillator Trim (4) */
 
-	[119] = 0x0000,     /* R119   - Oscillator Trim (7) */
+	{ 119, 0x0000 },   /* R119   - Oscillator Trim (7) */
 
-	[124] = 0x0011,     /* R124   - Analogue Clocking1 */
-	[125] = 0x004B,     /* R125   - Analogue Clocking2 */
-	[126] = 0x000D,     /* R126   - Analogue Clocking3 */
-	[127] = 0x0000,     /* R127   - PLL Software Reset */
+	{ 124, 0x0011 },   /* R124   - Analogue Clocking1 */
+	{ 125, 0x004B },   /* R125   - Analogue Clocking2 */
+	{ 126, 0x000D },   /* R126   - Analogue Clocking3 */
+	{ 127, 0x0000 },   /* R127   - PLL Software Reset */
 
-	[129] = 0x0000,     /* R129   - PLL2 */
+	{ 129, 0x0000 },   /* R129   - PLL2 */
 
-	[131] = 0x0000,     /* R131   - PLL 4 */
+	{ 131, 0x0000 },   /* R131   - PLL 4 */
 
-	[136] = 0x0067,     /* R136   - PLL 9 */
-	[137] = 0x001C,     /* R137   - PLL 10 */
-	[138] = 0x0071,     /* R138   - PLL 11 */
-	[139] = 0x00C7,     /* R139   - PLL 12 */
-	[140] = 0x0067,     /* R140   - PLL 13 */
-	[141] = 0x0048,     /* R141   - PLL 14 */
-	[142] = 0x0022,     /* R142   - PLL 15 */
-	[143] = 0x0097,     /* R143   - PLL 16 */
+	{ 136, 0x0067 },   /* R136   - PLL 9 */
+	{ 137, 0x001C },   /* R137   - PLL 10 */
+	{ 138, 0x0071 },   /* R138   - PLL 11 */
+	{ 139, 0x00C7 },   /* R139   - PLL 12 */
+	{ 140, 0x0067 },   /* R140   - PLL 13 */
+	{ 141, 0x0048 },   /* R141   - PLL 14 */
+	{ 142, 0x0022 },   /* R142   - PLL 15 */
+	{ 143, 0x0097 },   /* R143   - PLL 16 */
 
-	[155] = 0x000C,     /* R155   - FLL Control (1) */
-	[156] = 0x0039,     /* R156   - FLL Control (2) */
-	[157] = 0x0180,     /* R157   - FLL Control (3) */
+	{ 155, 0x000C },   /* R155   - FLL Control (1) */
+	{ 156, 0x0039 },   /* R156   - FLL Control (2) */
+	{ 157, 0x0180 },   /* R157   - FLL Control (3) */
 
-	[159] = 0x0032,     /* R159   - FLL Control (5) */
-	[160] = 0x0018,     /* R160   - FLL Control (6) */
-	[161] = 0x007D,     /* R161   - FLL Control (7) */
-	[162] = 0x0008,     /* R162   - FLL Control (8) */
+	{ 159, 0x0032 },   /* R159   - FLL Control (5) */
+	{ 160, 0x0018 },   /* R160   - FLL Control (6) */
+	{ 161, 0x007D },   /* R161   - FLL Control (7) */
+	{ 162, 0x0008 },   /* R162   - FLL Control (8) */
 
-	[252] = 0x0005,     /* R252   - General test 1 */
+	{ 252, 0x0005 },   /* R252   - General test 1 */
 
-	[256] = 0x0000,     /* R256   - DF1 */
-	[257] = 0x0000,     /* R257   - DF2 */
-	[258] = 0x0000,     /* R258   - DF3 */
-	[259] = 0x0000,     /* R259   - DF4 */
-	[260] = 0x0000,     /* R260   - DF5 */
-	[261] = 0x0000,     /* R261   - DF6 */
-	[262] = 0x0000,     /* R262   - DF7 */
+	{ 256, 0x0000 },   /* R256   - DF1 */
+	{ 257, 0x0000 },   /* R257   - DF2 */
+	{ 258, 0x0000 },   /* R258   - DF3 */
+	{ 259, 0x0000 },   /* R259   - DF4 */
+	{ 260, 0x0000 },   /* R260   - DF5 */
+	{ 261, 0x0000 },   /* R261   - DF6 */
+	{ 262, 0x0000 },   /* R262   - DF7 */
 
-	[264] = 0x0000,     /* R264   - LHPF1 */
-	[265] = 0x0000,     /* R265   - LHPF2 */
+	{ 264, 0x0000 },   /* R264   - LHPF1 */
+	{ 265, 0x0000 },   /* R265   - LHPF2 */
 
-	[268] = 0x0000,     /* R268   - THREED1 */
-	[269] = 0x0000,     /* R269   - THREED2 */
-	[270] = 0x0000,     /* R270   - THREED3 */
-	[271] = 0x0000,     /* R271   - THREED4 */
+	{ 268, 0x0000 },   /* R268   - THREED1 */
+	{ 269, 0x0000 },   /* R269   - THREED2 */
+	{ 270, 0x0000 },   /* R270   - THREED3 */
+	{ 271, 0x0000 },   /* R271   - THREED4 */
 
-	[276] = 0x000C,     /* R276   - DRC 1 */
-	[277] = 0x0925,     /* R277   - DRC 2 */
-	[278] = 0x0000,     /* R278   - DRC 3 */
-	[279] = 0x0000,     /* R279   - DRC 4 */
-	[280] = 0x0000,     /* R280   - DRC 5 */
+	{ 276, 0x000C },   /* R276   - DRC 1 */
+	{ 277, 0x0925 },   /* R277   - DRC 2 */
+	{ 278, 0x0000 },   /* R278   - DRC 3 */
+	{ 279, 0x0000 },   /* R279   - DRC 4 */
+	{ 280, 0x0000 },   /* R280   - DRC 5 */
 
-	[285] = 0x0000,     /* R285   - Tloopback */
+	{ 285, 0x0000 },   /* R285   - Tloopback */
 
-	[335] = 0x0004,     /* R335   - EQ1 */
-	[336] = 0x6318,     /* R336   - EQ2 */
-	[337] = 0x6300,     /* R337   - EQ3 */
-	[338] = 0x0FCA,     /* R338   - EQ4 */
-	[339] = 0x0400,     /* R339   - EQ5 */
-	[340] = 0x00D8,     /* R340   - EQ6 */
-	[341] = 0x1EB5,     /* R341   - EQ7 */
-	[342] = 0xF145,     /* R342   - EQ8 */
-	[343] = 0x0B75,     /* R343   - EQ9 */
-	[344] = 0x01C5,     /* R344   - EQ10 */
-	[345] = 0x1C58,     /* R345   - EQ11 */
-	[346] = 0xF373,     /* R346   - EQ12 */
-	[347] = 0x0A54,     /* R347   - EQ13 */
-	[348] = 0x0558,     /* R348   - EQ14 */
-	[349] = 0x168E,     /* R349   - EQ15 */
-	[350] = 0xF829,     /* R350   - EQ16 */
-	[351] = 0x07AD,     /* R351   - EQ17 */
-	[352] = 0x1103,     /* R352   - EQ18 */
-	[353] = 0x0564,     /* R353   - EQ19 */
-	[354] = 0x0559,     /* R354   - EQ20 */
-	[355] = 0x4000,     /* R355   - EQ21 */
-	[356] = 0x6318,     /* R356   - EQ22 */
-	[357] = 0x6300,     /* R357   - EQ23 */
-	[358] = 0x0FCA,     /* R358   - EQ24 */
-	[359] = 0x0400,     /* R359   - EQ25 */
-	[360] = 0x00D8,     /* R360   - EQ26 */
-	[361] = 0x1EB5,     /* R361   - EQ27 */
-	[362] = 0xF145,     /* R362   - EQ28 */
-	[363] = 0x0B75,     /* R363   - EQ29 */
-	[364] = 0x01C5,     /* R364   - EQ30 */
-	[365] = 0x1C58,     /* R365   - EQ31 */
-	[366] = 0xF373,     /* R366   - EQ32 */
-	[367] = 0x0A54,     /* R367   - EQ33 */
-	[368] = 0x0558,     /* R368   - EQ34 */
-	[369] = 0x168E,     /* R369   - EQ35 */
-	[370] = 0xF829,     /* R370   - EQ36 */
-	[371] = 0x07AD,     /* R371   - EQ37 */
-	[372] = 0x1103,     /* R372   - EQ38 */
-	[373] = 0x0564,     /* R373   - EQ39 */
-	[374] = 0x0559,     /* R374   - EQ40 */
-	[375] = 0x4000,     /* R375   - EQ41 */
+	{ 335, 0x0004 },   /* R335   - EQ1 */
+	{ 336, 0x6318 },   /* R336   - EQ2 */
+	{ 337, 0x6300 },   /* R337   - EQ3 */
+	{ 338, 0x0FCA },   /* R338   - EQ4 */
+	{ 339, 0x0400 },   /* R339   - EQ5 */
+	{ 340, 0x00D8 },   /* R340   - EQ6 */
+	{ 341, 0x1EB5 },   /* R341   - EQ7 */
+	{ 342, 0xF145 },   /* R342   - EQ8 */
+	{ 343, 0x0B75 },   /* R343   - EQ9 */
+	{ 344, 0x01C5 },   /* R344   - EQ10 */
+	{ 345, 0x1C58 },   /* R345   - EQ11 */
+	{ 346, 0xF373 },   /* R346   - EQ12 */
+	{ 347, 0x0A54 },   /* R347   - EQ13 */
+	{ 348, 0x0558 },   /* R348   - EQ14 */
+	{ 349, 0x168E },   /* R349   - EQ15 */
+	{ 350, 0xF829 },   /* R350   - EQ16 */
+	{ 351, 0x07AD },   /* R351   - EQ17 */
+	{ 352, 0x1103 },   /* R352   - EQ18 */
+	{ 353, 0x0564 },   /* R353   - EQ19 */
+	{ 354, 0x0559 },   /* R354   - EQ20 */
+	{ 355, 0x4000 },   /* R355   - EQ21 */
+	{ 356, 0x6318 },   /* R356   - EQ22 */
+	{ 357, 0x6300 },   /* R357   - EQ23 */
+	{ 358, 0x0FCA },   /* R358   - EQ24 */
+	{ 359, 0x0400 },   /* R359   - EQ25 */
+	{ 360, 0x00D8 },   /* R360   - EQ26 */
+	{ 361, 0x1EB5 },   /* R361   - EQ27 */
+	{ 362, 0xF145 },   /* R362   - EQ28 */
+	{ 363, 0x0B75 },   /* R363   - EQ29 */
+	{ 364, 0x01C5 },   /* R364   - EQ30 */
+	{ 365, 0x1C58 },   /* R365   - EQ31 */
+	{ 366, 0xF373 },   /* R366   - EQ32 */
+	{ 367, 0x0A54 },   /* R367   - EQ33 */
+	{ 368, 0x0558 },   /* R368   - EQ34 */
+	{ 369, 0x168E },   /* R369   - EQ35 */
+	{ 370, 0xF829 },   /* R370   - EQ36 */
+	{ 371, 0x07AD },   /* R371   - EQ37 */
+	{ 372, 0x1103 },   /* R372   - EQ38 */
+	{ 373, 0x0564 },   /* R373   - EQ39 */
+	{ 374, 0x0559 },   /* R374   - EQ40 */
+	{ 375, 0x4000 },   /* R375   - EQ41 */
 
-	[513] = 0x0000,     /* R513   - GPIO 2 */
-	[514] = 0x0000,     /* R514   - GPIO 3 */
+	{ 513, 0x0000 },   /* R513   - GPIO 2 */
+	{ 514, 0x0000 },   /* R514   - GPIO 3 */
 
-	[516] = 0x8100,     /* R516   - GPIO 5 */
-	[517] = 0x8100,     /* R517   - GPIO 6 */
+	{ 516, 0x8100 },   /* R516   - GPIO 5 */
+	{ 517, 0x8100 },   /* R517   - GPIO 6 */
 
-	[560] = 0x0000,     /* R560   - Interrupt Status 1 */
-	[561] = 0x0000,     /* R561   - Interrupt Status 2 */
+	{ 560, 0x0000 },   /* R560   - Interrupt Status 1 */
+	{ 561, 0x0000 },   /* R561   - Interrupt Status 2 */
 
-	[568] = 0x0030,     /* R568   - Interrupt Status 1 Mask */
-	[569] = 0xFFED,     /* R569   - Interrupt Status 2 Mask */
+	{ 568, 0x0030 },   /* R568   - Interrupt Status 1 Mask */
+	{ 569, 0xFFED },   /* R569   - Interrupt Status 2 Mask */
 
-	[576] = 0x0000,     /* R576   - Interrupt Control */
+	{ 576, 0x0000 },   /* R576   - Interrupt Control */
 
-	[584] = 0x002D,     /* R584   - IRQ Debounce */
+	{ 584, 0x002D },   /* R584   - IRQ Debounce */
 
-	[586] = 0x0000,     /* R586   -  MICINT Source Pol */
+	{ 586, 0x0000 },   /* R586   -  MICINT Source Pol */
 
-	[768] = 0x1C00,     /* R768   - DSP2 Power Management */
+	{ 768, 0x1C00 },   /* R768   - DSP2 Power Management */
 
-	[1037] = 0x0000,     /* R1037  - DSP2_ExecControl */
+	{ 1037, 0x0000 },   /* R1037  - DSP2_ExecControl */
 
-	[8192] = 0x0000,     /* R8192  - DSP2 Instruction RAM 0 */
+	{ 8192, 0x0000 },   /* R8192  - DSP2 Instruction RAM 0 */
 
-	[9216] = 0x0030,     /* R9216  - DSP2 Address RAM 2 */
-	[9217] = 0x0000,     /* R9217  - DSP2 Address RAM 1 */
-	[9218] = 0x0000,     /* R9218  - DSP2 Address RAM 0 */
+	{ 9216, 0x0030 },   /* R9216  - DSP2 Address RAM 2 */
+	{ 9217, 0x0000 },   /* R9217  - DSP2 Address RAM 1 */
+	{ 9218, 0x0000 },   /* R9218  - DSP2 Address RAM 0 */
 
-	[12288] = 0x0000,     /* R12288 - DSP2 Data1 RAM 1 */
-	[12289] = 0x0000,     /* R12289 - DSP2 Data1 RAM 0 */
+	{ 12288, 0x0000 },   /* R12288 - DSP2 Data1 RAM 1 */
+	{ 12289, 0x0000 },   /* R12289 - DSP2 Data1 RAM 0 */
 
-	[13312] = 0x0000,     /* R13312 - DSP2 Data2 RAM 1 */
-	[13313] = 0x0000,     /* R13313 - DSP2 Data2 RAM 0 */
+	{ 13312, 0x0000 },   /* R13312 - DSP2 Data2 RAM 1 */
+	{ 13313, 0x0000 },   /* R13313 - DSP2 Data2 RAM 0 */
 
-	[14336] = 0x0000,     /* R14336 - DSP2 Data3 RAM 1 */
-	[14337] = 0x0000,     /* R14337 - DSP2 Data3 RAM 0 */
+	{ 14336, 0x0000 },   /* R14336 - DSP2 Data3 RAM 1 */
+	{ 14337, 0x0000 },   /* R14337 - DSP2 Data3 RAM 0 */
 
-	[15360] = 0x000A,     /* R15360 - DSP2 Coeff RAM 0 */
+	{ 15360, 0x000A },   /* R15360 - DSP2 Coeff RAM 0 */
 
-	[16384] = 0x0000,     /* R16384 - RETUNEADC_SHARED_COEFF_1 */
-	[16385] = 0x0000,     /* R16385 - RETUNEADC_SHARED_COEFF_0 */
-	[16386] = 0x0000,     /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
-	[16387] = 0x0000,     /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
-	[16388] = 0x0000,     /* R16388 - SOUNDSTAGE_ENABLES_1 */
-	[16389] = 0x0000,     /* R16389 - SOUNDSTAGE_ENABLES_0 */
+	{ 16384, 0x0000 },   /* R16384 - RETUNEADC_SHARED_COEFF_1 */
+	{ 16385, 0x0000 },   /* R16385 - RETUNEADC_SHARED_COEFF_0 */
+	{ 16386, 0x0000 },   /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
+	{ 16387, 0x0000 },   /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
+	{ 16388, 0x0000 },   /* R16388 - SOUNDSTAGE_ENABLES_1 */
+	{ 16389, 0x0000 },   /* R16389 - SOUNDSTAGE_ENABLES_0 */
 
-	[16896] = 0x0002,     /* R16896 - HDBASS_AI_1 */
-	[16897] = 0xBD12,     /* R16897 - HDBASS_AI_0 */
-	[16898] = 0x007C,     /* R16898 - HDBASS_AR_1 */
-	[16899] = 0x586C,     /* R16899 - HDBASS_AR_0 */
-	[16900] = 0x0053,     /* R16900 - HDBASS_B_1 */
-	[16901] = 0x8121,     /* R16901 - HDBASS_B_0 */
-	[16902] = 0x003F,     /* R16902 - HDBASS_K_1 */
-	[16903] = 0x8BD8,     /* R16903 - HDBASS_K_0 */
-	[16904] = 0x0032,     /* R16904 - HDBASS_N1_1 */
-	[16905] = 0xF52D,     /* R16905 - HDBASS_N1_0 */
-	[16906] = 0x0065,     /* R16906 - HDBASS_N2_1 */
-	[16907] = 0xAC8C,     /* R16907 - HDBASS_N2_0 */
-	[16908] = 0x006B,     /* R16908 - HDBASS_N3_1 */
-	[16909] = 0xE087,     /* R16909 - HDBASS_N3_0 */
-	[16910] = 0x0072,     /* R16910 - HDBASS_N4_1 */
-	[16911] = 0x1483,     /* R16911 - HDBASS_N4_0 */
-	[16912] = 0x0072,     /* R16912 - HDBASS_N5_1 */
-	[16913] = 0x1483,     /* R16913 - HDBASS_N5_0 */
-	[16914] = 0x0043,     /* R16914 - HDBASS_X1_1 */
-	[16915] = 0x3525,     /* R16915 - HDBASS_X1_0 */
-	[16916] = 0x0006,     /* R16916 - HDBASS_X2_1 */
-	[16917] = 0x6A4A,     /* R16917 - HDBASS_X2_0 */
-	[16918] = 0x0043,     /* R16918 - HDBASS_X3_1 */
-	[16919] = 0x6079,     /* R16919 - HDBASS_X3_0 */
-	[16920] = 0x0008,     /* R16920 - HDBASS_ATK_1 */
-	[16921] = 0x0000,     /* R16921 - HDBASS_ATK_0 */
-	[16922] = 0x0001,     /* R16922 - HDBASS_DCY_1 */
-	[16923] = 0x0000,     /* R16923 - HDBASS_DCY_0 */
-	[16924] = 0x0059,     /* R16924 - HDBASS_PG_1 */
-	[16925] = 0x999A,     /* R16925 - HDBASS_PG_0 */
+	{ 16896, 0x0002 },   /* R16896 - HDBASS_AI_1 */
+	{ 16897, 0xBD12 },   /* R16897 - HDBASS_AI_0 */
+	{ 16898, 0x007C },   /* R16898 - HDBASS_AR_1 */
+	{ 16899, 0x586C },   /* R16899 - HDBASS_AR_0 */
+	{ 16900, 0x0053 },   /* R16900 - HDBASS_B_1 */
+	{ 16901, 0x8121 },   /* R16901 - HDBASS_B_0 */
+	{ 16902, 0x003F },   /* R16902 - HDBASS_K_1 */
+	{ 16903, 0x8BD8 },   /* R16903 - HDBASS_K_0 */
+	{ 16904, 0x0032 },   /* R16904 - HDBASS_N1_1 */
+	{ 16905, 0xF52D },   /* R16905 - HDBASS_N1_0 */
+	{ 16906, 0x0065 },   /* R16906 - HDBASS_N2_1 */
+	{ 16907, 0xAC8C },   /* R16907 - HDBASS_N2_0 */
+	{ 16908, 0x006B },   /* R16908 - HDBASS_N3_1 */
+	{ 16909, 0xE087 },   /* R16909 - HDBASS_N3_0 */
+	{ 16910, 0x0072 },   /* R16910 - HDBASS_N4_1 */
+	{ 16911, 0x1483 },   /* R16911 - HDBASS_N4_0 */
+	{ 16912, 0x0072 },   /* R16912 - HDBASS_N5_1 */
+	{ 16913, 0x1483 },   /* R16913 - HDBASS_N5_0 */
+	{ 16914, 0x0043 },   /* R16914 - HDBASS_X1_1 */
+	{ 16915, 0x3525 },   /* R16915 - HDBASS_X1_0 */
+	{ 16916, 0x0006 },   /* R16916 - HDBASS_X2_1 */
+	{ 16917, 0x6A4A },   /* R16917 - HDBASS_X2_0 */
+	{ 16918, 0x0043 },   /* R16918 - HDBASS_X3_1 */
+	{ 16919, 0x6079 },   /* R16919 - HDBASS_X3_0 */
+	{ 16920, 0x0008 },   /* R16920 - HDBASS_ATK_1 */
+	{ 16921, 0x0000 },   /* R16921 - HDBASS_ATK_0 */
+	{ 16922, 0x0001 },   /* R16922 - HDBASS_DCY_1 */
+	{ 16923, 0x0000 },   /* R16923 - HDBASS_DCY_0 */
+	{ 16924, 0x0059 },   /* R16924 - HDBASS_PG_1 */
+	{ 16925, 0x999A },   /* R16925 - HDBASS_PG_0 */
 
-	[17048] = 0x0083,     /* R17408 - HPF_C_1 */
-	[17049] = 0x98AD,     /* R17409 - HPF_C_0 */
+	{ 17048, 0x0083 },   /* R17408 - HPF_C_1 */
+	{ 17049, 0x98AD },   /* R17409 - HPF_C_0 */
 
-	[17920] = 0x007F,     /* R17920 - ADCL_RETUNE_C1_1 */
-	[17921] = 0xFFFF,     /* R17921 - ADCL_RETUNE_C1_0 */
-	[17922] = 0x0000,     /* R17922 - ADCL_RETUNE_C2_1 */
-	[17923] = 0x0000,     /* R17923 - ADCL_RETUNE_C2_0 */
-	[17924] = 0x0000,     /* R17924 - ADCL_RETUNE_C3_1 */
-	[17925] = 0x0000,     /* R17925 - ADCL_RETUNE_C3_0 */
-	[17926] = 0x0000,     /* R17926 - ADCL_RETUNE_C4_1 */
-	[17927] = 0x0000,     /* R17927 - ADCL_RETUNE_C4_0 */
-	[17928] = 0x0000,     /* R17928 - ADCL_RETUNE_C5_1 */
-	[17929] = 0x0000,     /* R17929 - ADCL_RETUNE_C5_0 */
-	[17930] = 0x0000,     /* R17930 - ADCL_RETUNE_C6_1 */
-	[17931] = 0x0000,     /* R17931 - ADCL_RETUNE_C6_0 */
-	[17932] = 0x0000,     /* R17932 - ADCL_RETUNE_C7_1 */
-	[17933] = 0x0000,     /* R17933 - ADCL_RETUNE_C7_0 */
-	[17934] = 0x0000,     /* R17934 - ADCL_RETUNE_C8_1 */
-	[17935] = 0x0000,     /* R17935 - ADCL_RETUNE_C8_0 */
-	[17936] = 0x0000,     /* R17936 - ADCL_RETUNE_C9_1 */
-	[17937] = 0x0000,     /* R17937 - ADCL_RETUNE_C9_0 */
-	[17938] = 0x0000,     /* R17938 - ADCL_RETUNE_C10_1 */
-	[17939] = 0x0000,     /* R17939 - ADCL_RETUNE_C10_0 */
-	[17940] = 0x0000,     /* R17940 - ADCL_RETUNE_C11_1 */
-	[17941] = 0x0000,     /* R17941 - ADCL_RETUNE_C11_0 */
-	[17942] = 0x0000,     /* R17942 - ADCL_RETUNE_C12_1 */
-	[17943] = 0x0000,     /* R17943 - ADCL_RETUNE_C12_0 */
-	[17944] = 0x0000,     /* R17944 - ADCL_RETUNE_C13_1 */
-	[17945] = 0x0000,     /* R17945 - ADCL_RETUNE_C13_0 */
-	[17946] = 0x0000,     /* R17946 - ADCL_RETUNE_C14_1 */
-	[17947] = 0x0000,     /* R17947 - ADCL_RETUNE_C14_0 */
-	[17948] = 0x0000,     /* R17948 - ADCL_RETUNE_C15_1 */
-	[17949] = 0x0000,     /* R17949 - ADCL_RETUNE_C15_0 */
-	[17950] = 0x0000,     /* R17950 - ADCL_RETUNE_C16_1 */
-	[17951] = 0x0000,     /* R17951 - ADCL_RETUNE_C16_0 */
-	[17952] = 0x0000,     /* R17952 - ADCL_RETUNE_C17_1 */
-	[17953] = 0x0000,     /* R17953 - ADCL_RETUNE_C17_0 */
-	[17954] = 0x0000,     /* R17954 - ADCL_RETUNE_C18_1 */
-	[17955] = 0x0000,     /* R17955 - ADCL_RETUNE_C18_0 */
-	[17956] = 0x0000,     /* R17956 - ADCL_RETUNE_C19_1 */
-	[17957] = 0x0000,     /* R17957 - ADCL_RETUNE_C19_0 */
-	[17958] = 0x0000,     /* R17958 - ADCL_RETUNE_C20_1 */
-	[17959] = 0x0000,     /* R17959 - ADCL_RETUNE_C20_0 */
-	[17960] = 0x0000,     /* R17960 - ADCL_RETUNE_C21_1 */
-	[17961] = 0x0000,     /* R17961 - ADCL_RETUNE_C21_0 */
-	[17962] = 0x0000,     /* R17962 - ADCL_RETUNE_C22_1 */
-	[17963] = 0x0000,     /* R17963 - ADCL_RETUNE_C22_0 */
-	[17964] = 0x0000,     /* R17964 - ADCL_RETUNE_C23_1 */
-	[17965] = 0x0000,     /* R17965 - ADCL_RETUNE_C23_0 */
-	[17966] = 0x0000,     /* R17966 - ADCL_RETUNE_C24_1 */
-	[17967] = 0x0000,     /* R17967 - ADCL_RETUNE_C24_0 */
-	[17968] = 0x0000,     /* R17968 - ADCL_RETUNE_C25_1 */
-	[17969] = 0x0000,     /* R17969 - ADCL_RETUNE_C25_0 */
-	[17970] = 0x0000,     /* R17970 - ADCL_RETUNE_C26_1 */
-	[17971] = 0x0000,     /* R17971 - ADCL_RETUNE_C26_0 */
-	[17972] = 0x0000,     /* R17972 - ADCL_RETUNE_C27_1 */
-	[17973] = 0x0000,     /* R17973 - ADCL_RETUNE_C27_0 */
-	[17974] = 0x0000,     /* R17974 - ADCL_RETUNE_C28_1 */
-	[17975] = 0x0000,     /* R17975 - ADCL_RETUNE_C28_0 */
-	[17976] = 0x0000,     /* R17976 - ADCL_RETUNE_C29_1 */
-	[17977] = 0x0000,     /* R17977 - ADCL_RETUNE_C29_0 */
-	[17978] = 0x0000,     /* R17978 - ADCL_RETUNE_C30_1 */
-	[17979] = 0x0000,     /* R17979 - ADCL_RETUNE_C30_0 */
-	[17980] = 0x0000,     /* R17980 - ADCL_RETUNE_C31_1 */
-	[17981] = 0x0000,     /* R17981 - ADCL_RETUNE_C31_0 */
-	[17982] = 0x0000,     /* R17982 - ADCL_RETUNE_C32_1 */
-	[17983] = 0x0000,     /* R17983 - ADCL_RETUNE_C32_0 */
+	{ 17920, 0x007F },   /* R17920 - ADCL_RETUNE_C1_1 */
+	{ 17921, 0xFFFF },   /* R17921 - ADCL_RETUNE_C1_0 */
+	{ 17922, 0x0000 },   /* R17922 - ADCL_RETUNE_C2_1 */
+	{ 17923, 0x0000 },   /* R17923 - ADCL_RETUNE_C2_0 */
+	{ 17924, 0x0000 },   /* R17924 - ADCL_RETUNE_C3_1 */
+	{ 17925, 0x0000 },   /* R17925 - ADCL_RETUNE_C3_0 */
+	{ 17926, 0x0000 },   /* R17926 - ADCL_RETUNE_C4_1 */
+	{ 17927, 0x0000 },   /* R17927 - ADCL_RETUNE_C4_0 */
+	{ 17928, 0x0000 },   /* R17928 - ADCL_RETUNE_C5_1 */
+	{ 17929, 0x0000 },   /* R17929 - ADCL_RETUNE_C5_0 */
+	{ 17930, 0x0000 },   /* R17930 - ADCL_RETUNE_C6_1 */
+	{ 17931, 0x0000 },   /* R17931 - ADCL_RETUNE_C6_0 */
+	{ 17932, 0x0000 },   /* R17932 - ADCL_RETUNE_C7_1 */
+	{ 17933, 0x0000 },   /* R17933 - ADCL_RETUNE_C7_0 */
+	{ 17934, 0x0000 },   /* R17934 - ADCL_RETUNE_C8_1 */
+	{ 17935, 0x0000 },   /* R17935 - ADCL_RETUNE_C8_0 */
+	{ 17936, 0x0000 },   /* R17936 - ADCL_RETUNE_C9_1 */
+	{ 17937, 0x0000 },   /* R17937 - ADCL_RETUNE_C9_0 */
+	{ 17938, 0x0000 },   /* R17938 - ADCL_RETUNE_C10_1 */
+	{ 17939, 0x0000 },   /* R17939 - ADCL_RETUNE_C10_0 */
+	{ 17940, 0x0000 },   /* R17940 - ADCL_RETUNE_C11_1 */
+	{ 17941, 0x0000 },   /* R17941 - ADCL_RETUNE_C11_0 */
+	{ 17942, 0x0000 },   /* R17942 - ADCL_RETUNE_C12_1 */
+	{ 17943, 0x0000 },   /* R17943 - ADCL_RETUNE_C12_0 */
+	{ 17944, 0x0000 },   /* R17944 - ADCL_RETUNE_C13_1 */
+	{ 17945, 0x0000 },   /* R17945 - ADCL_RETUNE_C13_0 */
+	{ 17946, 0x0000 },   /* R17946 - ADCL_RETUNE_C14_1 */
+	{ 17947, 0x0000 },   /* R17947 - ADCL_RETUNE_C14_0 */
+	{ 17948, 0x0000 },   /* R17948 - ADCL_RETUNE_C15_1 */
+	{ 17949, 0x0000 },   /* R17949 - ADCL_RETUNE_C15_0 */
+	{ 17950, 0x0000 },   /* R17950 - ADCL_RETUNE_C16_1 */
+	{ 17951, 0x0000 },   /* R17951 - ADCL_RETUNE_C16_0 */
+	{ 17952, 0x0000 },   /* R17952 - ADCL_RETUNE_C17_1 */
+	{ 17953, 0x0000 },   /* R17953 - ADCL_RETUNE_C17_0 */
+	{ 17954, 0x0000 },   /* R17954 - ADCL_RETUNE_C18_1 */
+	{ 17955, 0x0000 },   /* R17955 - ADCL_RETUNE_C18_0 */
+	{ 17956, 0x0000 },   /* R17956 - ADCL_RETUNE_C19_1 */
+	{ 17957, 0x0000 },   /* R17957 - ADCL_RETUNE_C19_0 */
+	{ 17958, 0x0000 },   /* R17958 - ADCL_RETUNE_C20_1 */
+	{ 17959, 0x0000 },   /* R17959 - ADCL_RETUNE_C20_0 */
+	{ 17960, 0x0000 },   /* R17960 - ADCL_RETUNE_C21_1 */
+	{ 17961, 0x0000 },   /* R17961 - ADCL_RETUNE_C21_0 */
+	{ 17962, 0x0000 },   /* R17962 - ADCL_RETUNE_C22_1 */
+	{ 17963, 0x0000 },   /* R17963 - ADCL_RETUNE_C22_0 */
+	{ 17964, 0x0000 },   /* R17964 - ADCL_RETUNE_C23_1 */
+	{ 17965, 0x0000 },   /* R17965 - ADCL_RETUNE_C23_0 */
+	{ 17966, 0x0000 },   /* R17966 - ADCL_RETUNE_C24_1 */
+	{ 17967, 0x0000 },   /* R17967 - ADCL_RETUNE_C24_0 */
+	{ 17968, 0x0000 },   /* R17968 - ADCL_RETUNE_C25_1 */
+	{ 17969, 0x0000 },   /* R17969 - ADCL_RETUNE_C25_0 */
+	{ 17970, 0x0000 },   /* R17970 - ADCL_RETUNE_C26_1 */
+	{ 17971, 0x0000 },   /* R17971 - ADCL_RETUNE_C26_0 */
+	{ 17972, 0x0000 },   /* R17972 - ADCL_RETUNE_C27_1 */
+	{ 17973, 0x0000 },   /* R17973 - ADCL_RETUNE_C27_0 */
+	{ 17974, 0x0000 },   /* R17974 - ADCL_RETUNE_C28_1 */
+	{ 17975, 0x0000 },   /* R17975 - ADCL_RETUNE_C28_0 */
+	{ 17976, 0x0000 },   /* R17976 - ADCL_RETUNE_C29_1 */
+	{ 17977, 0x0000 },   /* R17977 - ADCL_RETUNE_C29_0 */
+	{ 17978, 0x0000 },   /* R17978 - ADCL_RETUNE_C30_1 */
+	{ 17979, 0x0000 },   /* R17979 - ADCL_RETUNE_C30_0 */
+	{ 17980, 0x0000 },   /* R17980 - ADCL_RETUNE_C31_1 */
+	{ 17981, 0x0000 },   /* R17981 - ADCL_RETUNE_C31_0 */
+	{ 17982, 0x0000 },   /* R17982 - ADCL_RETUNE_C32_1 */
+	{ 17983, 0x0000 },   /* R17983 - ADCL_RETUNE_C32_0 */
 
-	[18432] = 0x0020,     /* R18432 - RETUNEADC_PG2_1 */
-	[18433] = 0x0000,     /* R18433 - RETUNEADC_PG2_0 */
-	[18434] = 0x0040,     /* R18434 - RETUNEADC_PG_1 */
-	[18435] = 0x0000,     /* R18435 - RETUNEADC_PG_0 */
+	{ 18432, 0x0020 },   /* R18432 - RETUNEADC_PG2_1 */
+	{ 18433, 0x0000 },   /* R18433 - RETUNEADC_PG2_0 */
+	{ 18434, 0x0040 },   /* R18434 - RETUNEADC_PG_1 */
+	{ 18435, 0x0000 },   /* R18435 - RETUNEADC_PG_0 */
 
-	[18944] = 0x007F,     /* R18944 - ADCR_RETUNE_C1_1 */
-	[18945] = 0xFFFF,     /* R18945 - ADCR_RETUNE_C1_0 */
-	[18946] = 0x0000,     /* R18946 - ADCR_RETUNE_C2_1 */
-	[18947] = 0x0000,     /* R18947 - ADCR_RETUNE_C2_0 */
-	[18948] = 0x0000,     /* R18948 - ADCR_RETUNE_C3_1 */
-	[18949] = 0x0000,     /* R18949 - ADCR_RETUNE_C3_0 */
-	[18950] = 0x0000,     /* R18950 - ADCR_RETUNE_C4_1 */
-	[18951] = 0x0000,     /* R18951 - ADCR_RETUNE_C4_0 */
-	[18952] = 0x0000,     /* R18952 - ADCR_RETUNE_C5_1 */
-	[18953] = 0x0000,     /* R18953 - ADCR_RETUNE_C5_0 */
-	[18954] = 0x0000,     /* R18954 - ADCR_RETUNE_C6_1 */
-	[18955] = 0x0000,     /* R18955 - ADCR_RETUNE_C6_0 */
-	[18956] = 0x0000,     /* R18956 - ADCR_RETUNE_C7_1 */
-	[18957] = 0x0000,     /* R18957 - ADCR_RETUNE_C7_0 */
-	[18958] = 0x0000,     /* R18958 - ADCR_RETUNE_C8_1 */
-	[18959] = 0x0000,     /* R18959 - ADCR_RETUNE_C8_0 */
-	[18960] = 0x0000,     /* R18960 - ADCR_RETUNE_C9_1 */
-	[18961] = 0x0000,     /* R18961 - ADCR_RETUNE_C9_0 */
-	[18962] = 0x0000,     /* R18962 - ADCR_RETUNE_C10_1 */
-	[18963] = 0x0000,     /* R18963 - ADCR_RETUNE_C10_0 */
-	[18964] = 0x0000,     /* R18964 - ADCR_RETUNE_C11_1 */
-	[18965] = 0x0000,     /* R18965 - ADCR_RETUNE_C11_0 */
-	[18966] = 0x0000,     /* R18966 - ADCR_RETUNE_C12_1 */
-	[18967] = 0x0000,     /* R18967 - ADCR_RETUNE_C12_0 */
-	[18968] = 0x0000,     /* R18968 - ADCR_RETUNE_C13_1 */
-	[18969] = 0x0000,     /* R18969 - ADCR_RETUNE_C13_0 */
-	[18970] = 0x0000,     /* R18970 - ADCR_RETUNE_C14_1 */
-	[18971] = 0x0000,     /* R18971 - ADCR_RETUNE_C14_0 */
-	[18972] = 0x0000,     /* R18972 - ADCR_RETUNE_C15_1 */
-	[18973] = 0x0000,     /* R18973 - ADCR_RETUNE_C15_0 */
-	[18974] = 0x0000,     /* R18974 - ADCR_RETUNE_C16_1 */
-	[18975] = 0x0000,     /* R18975 - ADCR_RETUNE_C16_0 */
-	[18976] = 0x0000,     /* R18976 - ADCR_RETUNE_C17_1 */
-	[18977] = 0x0000,     /* R18977 - ADCR_RETUNE_C17_0 */
-	[18978] = 0x0000,     /* R18978 - ADCR_RETUNE_C18_1 */
-	[18979] = 0x0000,     /* R18979 - ADCR_RETUNE_C18_0 */
-	[18980] = 0x0000,     /* R18980 - ADCR_RETUNE_C19_1 */
-	[18981] = 0x0000,     /* R18981 - ADCR_RETUNE_C19_0 */
-	[18982] = 0x0000,     /* R18982 - ADCR_RETUNE_C20_1 */
-	[18983] = 0x0000,     /* R18983 - ADCR_RETUNE_C20_0 */
-	[18984] = 0x0000,     /* R18984 - ADCR_RETUNE_C21_1 */
-	[18985] = 0x0000,     /* R18985 - ADCR_RETUNE_C21_0 */
-	[18986] = 0x0000,     /* R18986 - ADCR_RETUNE_C22_1 */
-	[18987] = 0x0000,     /* R18987 - ADCR_RETUNE_C22_0 */
-	[18988] = 0x0000,     /* R18988 - ADCR_RETUNE_C23_1 */
-	[18989] = 0x0000,     /* R18989 - ADCR_RETUNE_C23_0 */
-	[18990] = 0x0000,     /* R18990 - ADCR_RETUNE_C24_1 */
-	[18991] = 0x0000,     /* R18991 - ADCR_RETUNE_C24_0 */
-	[18992] = 0x0000,     /* R18992 - ADCR_RETUNE_C25_1 */
-	[18993] = 0x0000,     /* R18993 - ADCR_RETUNE_C25_0 */
-	[18994] = 0x0000,     /* R18994 - ADCR_RETUNE_C26_1 */
-	[18995] = 0x0000,     /* R18995 - ADCR_RETUNE_C26_0 */
-	[18996] = 0x0000,     /* R18996 - ADCR_RETUNE_C27_1 */
-	[18997] = 0x0000,     /* R18997 - ADCR_RETUNE_C27_0 */
-	[18998] = 0x0000,     /* R18998 - ADCR_RETUNE_C28_1 */
-	[18999] = 0x0000,     /* R18999 - ADCR_RETUNE_C28_0 */
-	[19000] = 0x0000,     /* R19000 - ADCR_RETUNE_C29_1 */
-	[19001] = 0x0000,     /* R19001 - ADCR_RETUNE_C29_0 */
-	[19002] = 0x0000,     /* R19002 - ADCR_RETUNE_C30_1 */
-	[19003] = 0x0000,     /* R19003 - ADCR_RETUNE_C30_0 */
-	[19004] = 0x0000,     /* R19004 - ADCR_RETUNE_C31_1 */
-	[19005] = 0x0000,     /* R19005 - ADCR_RETUNE_C31_0 */
-	[19006] = 0x0000,     /* R19006 - ADCR_RETUNE_C32_1 */
-	[19007] = 0x0000,     /* R19007 - ADCR_RETUNE_C32_0 */
+	{ 18944, 0x007F },   /* R18944 - ADCR_RETUNE_C1_1 */
+	{ 18945, 0xFFFF },   /* R18945 - ADCR_RETUNE_C1_0 */
+	{ 18946, 0x0000 },   /* R18946 - ADCR_RETUNE_C2_1 */
+	{ 18947, 0x0000 },   /* R18947 - ADCR_RETUNE_C2_0 */
+	{ 18948, 0x0000 },   /* R18948 - ADCR_RETUNE_C3_1 */
+	{ 18949, 0x0000 },   /* R18949 - ADCR_RETUNE_C3_0 */
+	{ 18950, 0x0000 },   /* R18950 - ADCR_RETUNE_C4_1 */
+	{ 18951, 0x0000 },   /* R18951 - ADCR_RETUNE_C4_0 */
+	{ 18952, 0x0000 },   /* R18952 - ADCR_RETUNE_C5_1 */
+	{ 18953, 0x0000 },   /* R18953 - ADCR_RETUNE_C5_0 */
+	{ 18954, 0x0000 },   /* R18954 - ADCR_RETUNE_C6_1 */
+	{ 18955, 0x0000 },   /* R18955 - ADCR_RETUNE_C6_0 */
+	{ 18956, 0x0000 },   /* R18956 - ADCR_RETUNE_C7_1 */
+	{ 18957, 0x0000 },   /* R18957 - ADCR_RETUNE_C7_0 */
+	{ 18958, 0x0000 },   /* R18958 - ADCR_RETUNE_C8_1 */
+	{ 18959, 0x0000 },   /* R18959 - ADCR_RETUNE_C8_0 */
+	{ 18960, 0x0000 },   /* R18960 - ADCR_RETUNE_C9_1 */
+	{ 18961, 0x0000 },   /* R18961 - ADCR_RETUNE_C9_0 */
+	{ 18962, 0x0000 },   /* R18962 - ADCR_RETUNE_C10_1 */
+	{ 18963, 0x0000 },   /* R18963 - ADCR_RETUNE_C10_0 */
+	{ 18964, 0x0000 },   /* R18964 - ADCR_RETUNE_C11_1 */
+	{ 18965, 0x0000 },   /* R18965 - ADCR_RETUNE_C11_0 */
+	{ 18966, 0x0000 },   /* R18966 - ADCR_RETUNE_C12_1 */
+	{ 18967, 0x0000 },   /* R18967 - ADCR_RETUNE_C12_0 */
+	{ 18968, 0x0000 },   /* R18968 - ADCR_RETUNE_C13_1 */
+	{ 18969, 0x0000 },   /* R18969 - ADCR_RETUNE_C13_0 */
+	{ 18970, 0x0000 },   /* R18970 - ADCR_RETUNE_C14_1 */
+	{ 18971, 0x0000 },   /* R18971 - ADCR_RETUNE_C14_0 */
+	{ 18972, 0x0000 },   /* R18972 - ADCR_RETUNE_C15_1 */
+	{ 18973, 0x0000 },   /* R18973 - ADCR_RETUNE_C15_0 */
+	{ 18974, 0x0000 },   /* R18974 - ADCR_RETUNE_C16_1 */
+	{ 18975, 0x0000 },   /* R18975 - ADCR_RETUNE_C16_0 */
+	{ 18976, 0x0000 },   /* R18976 - ADCR_RETUNE_C17_1 */
+	{ 18977, 0x0000 },   /* R18977 - ADCR_RETUNE_C17_0 */
+	{ 18978, 0x0000 },   /* R18978 - ADCR_RETUNE_C18_1 */
+	{ 18979, 0x0000 },   /* R18979 - ADCR_RETUNE_C18_0 */
+	{ 18980, 0x0000 },   /* R18980 - ADCR_RETUNE_C19_1 */
+	{ 18981, 0x0000 },   /* R18981 - ADCR_RETUNE_C19_0 */
+	{ 18982, 0x0000 },   /* R18982 - ADCR_RETUNE_C20_1 */
+	{ 18983, 0x0000 },   /* R18983 - ADCR_RETUNE_C20_0 */
+	{ 18984, 0x0000 },   /* R18984 - ADCR_RETUNE_C21_1 */
+	{ 18985, 0x0000 },   /* R18985 - ADCR_RETUNE_C21_0 */
+	{ 18986, 0x0000 },   /* R18986 - ADCR_RETUNE_C22_1 */
+	{ 18987, 0x0000 },   /* R18987 - ADCR_RETUNE_C22_0 */
+	{ 18988, 0x0000 },   /* R18988 - ADCR_RETUNE_C23_1 */
+	{ 18989, 0x0000 },   /* R18989 - ADCR_RETUNE_C23_0 */
+	{ 18990, 0x0000 },   /* R18990 - ADCR_RETUNE_C24_1 */
+	{ 18991, 0x0000 },   /* R18991 - ADCR_RETUNE_C24_0 */
+	{ 18992, 0x0000 },   /* R18992 - ADCR_RETUNE_C25_1 */
+	{ 18993, 0x0000 },   /* R18993 - ADCR_RETUNE_C25_0 */
+	{ 18994, 0x0000 },   /* R18994 - ADCR_RETUNE_C26_1 */
+	{ 18995, 0x0000 },   /* R18995 - ADCR_RETUNE_C26_0 */
+	{ 18996, 0x0000 },   /* R18996 - ADCR_RETUNE_C27_1 */
+	{ 18997, 0x0000 },   /* R18997 - ADCR_RETUNE_C27_0 */
+	{ 18998, 0x0000 },   /* R18998 - ADCR_RETUNE_C28_1 */
+	{ 18999, 0x0000 },   /* R18999 - ADCR_RETUNE_C28_0 */
+	{ 19000, 0x0000 },   /* R19000 - ADCR_RETUNE_C29_1 */
+	{ 19001, 0x0000 },   /* R19001 - ADCR_RETUNE_C29_0 */
+	{ 19002, 0x0000 },   /* R19002 - ADCR_RETUNE_C30_1 */
+	{ 19003, 0x0000 },   /* R19003 - ADCR_RETUNE_C30_0 */
+	{ 19004, 0x0000 },   /* R19004 - ADCR_RETUNE_C31_1 */
+	{ 19005, 0x0000 },   /* R19005 - ADCR_RETUNE_C31_0 */
+	{ 19006, 0x0000 },   /* R19006 - ADCR_RETUNE_C32_1 */
+	{ 19007, 0x0000 },   /* R19007 - ADCR_RETUNE_C32_0 */
 
-	[19456] = 0x007F,     /* R19456 - DACL_RETUNE_C1_1 */
-	[19457] = 0xFFFF,     /* R19457 - DACL_RETUNE_C1_0 */
-	[19458] = 0x0000,     /* R19458 - DACL_RETUNE_C2_1 */
-	[19459] = 0x0000,     /* R19459 - DACL_RETUNE_C2_0 */
-	[19460] = 0x0000,     /* R19460 - DACL_RETUNE_C3_1 */
-	[19461] = 0x0000,     /* R19461 - DACL_RETUNE_C3_0 */
-	[19462] = 0x0000,     /* R19462 - DACL_RETUNE_C4_1 */
-	[19463] = 0x0000,     /* R19463 - DACL_RETUNE_C4_0 */
-	[19464] = 0x0000,     /* R19464 - DACL_RETUNE_C5_1 */
-	[19465] = 0x0000,     /* R19465 - DACL_RETUNE_C5_0 */
-	[19466] = 0x0000,     /* R19466 - DACL_RETUNE_C6_1 */
-	[19467] = 0x0000,     /* R19467 - DACL_RETUNE_C6_0 */
-	[19468] = 0x0000,     /* R19468 - DACL_RETUNE_C7_1 */
-	[19469] = 0x0000,     /* R19469 - DACL_RETUNE_C7_0 */
-	[19470] = 0x0000,     /* R19470 - DACL_RETUNE_C8_1 */
-	[19471] = 0x0000,     /* R19471 - DACL_RETUNE_C8_0 */
-	[19472] = 0x0000,     /* R19472 - DACL_RETUNE_C9_1 */
-	[19473] = 0x0000,     /* R19473 - DACL_RETUNE_C9_0 */
-	[19474] = 0x0000,     /* R19474 - DACL_RETUNE_C10_1 */
-	[19475] = 0x0000,     /* R19475 - DACL_RETUNE_C10_0 */
-	[19476] = 0x0000,     /* R19476 - DACL_RETUNE_C11_1 */
-	[19477] = 0x0000,     /* R19477 - DACL_RETUNE_C11_0 */
-	[19478] = 0x0000,     /* R19478 - DACL_RETUNE_C12_1 */
-	[19479] = 0x0000,     /* R19479 - DACL_RETUNE_C12_0 */
-	[19480] = 0x0000,     /* R19480 - DACL_RETUNE_C13_1 */
-	[19481] = 0x0000,     /* R19481 - DACL_RETUNE_C13_0 */
-	[19482] = 0x0000,     /* R19482 - DACL_RETUNE_C14_1 */
-	[19483] = 0x0000,     /* R19483 - DACL_RETUNE_C14_0 */
-	[19484] = 0x0000,     /* R19484 - DACL_RETUNE_C15_1 */
-	[19485] = 0x0000,     /* R19485 - DACL_RETUNE_C15_0 */
-	[19486] = 0x0000,     /* R19486 - DACL_RETUNE_C16_1 */
-	[19487] = 0x0000,     /* R19487 - DACL_RETUNE_C16_0 */
-	[19488] = 0x0000,     /* R19488 - DACL_RETUNE_C17_1 */
-	[19489] = 0x0000,     /* R19489 - DACL_RETUNE_C17_0 */
-	[19490] = 0x0000,     /* R19490 - DACL_RETUNE_C18_1 */
-	[19491] = 0x0000,     /* R19491 - DACL_RETUNE_C18_0 */
-	[19492] = 0x0000,     /* R19492 - DACL_RETUNE_C19_1 */
-	[19493] = 0x0000,     /* R19493 - DACL_RETUNE_C19_0 */
-	[19494] = 0x0000,     /* R19494 - DACL_RETUNE_C20_1 */
-	[19495] = 0x0000,     /* R19495 - DACL_RETUNE_C20_0 */
-	[19496] = 0x0000,     /* R19496 - DACL_RETUNE_C21_1 */
-	[19497] = 0x0000,     /* R19497 - DACL_RETUNE_C21_0 */
-	[19498] = 0x0000,     /* R19498 - DACL_RETUNE_C22_1 */
-	[19499] = 0x0000,     /* R19499 - DACL_RETUNE_C22_0 */
-	[19500] = 0x0000,     /* R19500 - DACL_RETUNE_C23_1 */
-	[19501] = 0x0000,     /* R19501 - DACL_RETUNE_C23_0 */
-	[19502] = 0x0000,     /* R19502 - DACL_RETUNE_C24_1 */
-	[19503] = 0x0000,     /* R19503 - DACL_RETUNE_C24_0 */
-	[19504] = 0x0000,     /* R19504 - DACL_RETUNE_C25_1 */
-	[19505] = 0x0000,     /* R19505 - DACL_RETUNE_C25_0 */
-	[19506] = 0x0000,     /* R19506 - DACL_RETUNE_C26_1 */
-	[19507] = 0x0000,     /* R19507 - DACL_RETUNE_C26_0 */
-	[19508] = 0x0000,     /* R19508 - DACL_RETUNE_C27_1 */
-	[19509] = 0x0000,     /* R19509 - DACL_RETUNE_C27_0 */
-	[19510] = 0x0000,     /* R19510 - DACL_RETUNE_C28_1 */
-	[19511] = 0x0000,     /* R19511 - DACL_RETUNE_C28_0 */
-	[19512] = 0x0000,     /* R19512 - DACL_RETUNE_C29_1 */
-	[19513] = 0x0000,     /* R19513 - DACL_RETUNE_C29_0 */
-	[19514] = 0x0000,     /* R19514 - DACL_RETUNE_C30_1 */
-	[19515] = 0x0000,     /* R19515 - DACL_RETUNE_C30_0 */
-	[19516] = 0x0000,     /* R19516 - DACL_RETUNE_C31_1 */
-	[19517] = 0x0000,     /* R19517 - DACL_RETUNE_C31_0 */
-	[19518] = 0x0000,     /* R19518 - DACL_RETUNE_C32_1 */
-	[19519] = 0x0000,     /* R19519 - DACL_RETUNE_C32_0 */
+	{ 19456, 0x007F },   /* R19456 - DACL_RETUNE_C1_1 */
+	{ 19457, 0xFFFF },   /* R19457 - DACL_RETUNE_C1_0 */
+	{ 19458, 0x0000 },   /* R19458 - DACL_RETUNE_C2_1 */
+	{ 19459, 0x0000 },   /* R19459 - DACL_RETUNE_C2_0 */
+	{ 19460, 0x0000 },   /* R19460 - DACL_RETUNE_C3_1 */
+	{ 19461, 0x0000 },   /* R19461 - DACL_RETUNE_C3_0 */
+	{ 19462, 0x0000 },   /* R19462 - DACL_RETUNE_C4_1 */
+	{ 19463, 0x0000 },   /* R19463 - DACL_RETUNE_C4_0 */
+	{ 19464, 0x0000 },   /* R19464 - DACL_RETUNE_C5_1 */
+	{ 19465, 0x0000 },   /* R19465 - DACL_RETUNE_C5_0 */
+	{ 19466, 0x0000 },   /* R19466 - DACL_RETUNE_C6_1 */
+	{ 19467, 0x0000 },   /* R19467 - DACL_RETUNE_C6_0 */
+	{ 19468, 0x0000 },   /* R19468 - DACL_RETUNE_C7_1 */
+	{ 19469, 0x0000 },   /* R19469 - DACL_RETUNE_C7_0 */
+	{ 19470, 0x0000 },   /* R19470 - DACL_RETUNE_C8_1 */
+	{ 19471, 0x0000 },   /* R19471 - DACL_RETUNE_C8_0 */
+	{ 19472, 0x0000 },   /* R19472 - DACL_RETUNE_C9_1 */
+	{ 19473, 0x0000 },   /* R19473 - DACL_RETUNE_C9_0 */
+	{ 19474, 0x0000 },   /* R19474 - DACL_RETUNE_C10_1 */
+	{ 19475, 0x0000 },   /* R19475 - DACL_RETUNE_C10_0 */
+	{ 19476, 0x0000 },   /* R19476 - DACL_RETUNE_C11_1 */
+	{ 19477, 0x0000 },   /* R19477 - DACL_RETUNE_C11_0 */
+	{ 19478, 0x0000 },   /* R19478 - DACL_RETUNE_C12_1 */
+	{ 19479, 0x0000 },   /* R19479 - DACL_RETUNE_C12_0 */
+	{ 19480, 0x0000 },   /* R19480 - DACL_RETUNE_C13_1 */
+	{ 19481, 0x0000 },   /* R19481 - DACL_RETUNE_C13_0 */
+	{ 19482, 0x0000 },   /* R19482 - DACL_RETUNE_C14_1 */
+	{ 19483, 0x0000 },   /* R19483 - DACL_RETUNE_C14_0 */
+	{ 19484, 0x0000 },   /* R19484 - DACL_RETUNE_C15_1 */
+	{ 19485, 0x0000 },   /* R19485 - DACL_RETUNE_C15_0 */
+	{ 19486, 0x0000 },   /* R19486 - DACL_RETUNE_C16_1 */
+	{ 19487, 0x0000 },   /* R19487 - DACL_RETUNE_C16_0 */
+	{ 19488, 0x0000 },   /* R19488 - DACL_RETUNE_C17_1 */
+	{ 19489, 0x0000 },   /* R19489 - DACL_RETUNE_C17_0 */
+	{ 19490, 0x0000 },   /* R19490 - DACL_RETUNE_C18_1 */
+	{ 19491, 0x0000 },   /* R19491 - DACL_RETUNE_C18_0 */
+	{ 19492, 0x0000 },   /* R19492 - DACL_RETUNE_C19_1 */
+	{ 19493, 0x0000 },   /* R19493 - DACL_RETUNE_C19_0 */
+	{ 19494, 0x0000 },   /* R19494 - DACL_RETUNE_C20_1 */
+	{ 19495, 0x0000 },   /* R19495 - DACL_RETUNE_C20_0 */
+	{ 19496, 0x0000 },   /* R19496 - DACL_RETUNE_C21_1 */
+	{ 19497, 0x0000 },   /* R19497 - DACL_RETUNE_C21_0 */
+	{ 19498, 0x0000 },   /* R19498 - DACL_RETUNE_C22_1 */
+	{ 19499, 0x0000 },   /* R19499 - DACL_RETUNE_C22_0 */
+	{ 19500, 0x0000 },   /* R19500 - DACL_RETUNE_C23_1 */
+	{ 19501, 0x0000 },   /* R19501 - DACL_RETUNE_C23_0 */
+	{ 19502, 0x0000 },   /* R19502 - DACL_RETUNE_C24_1 */
+	{ 19503, 0x0000 },   /* R19503 - DACL_RETUNE_C24_0 */
+	{ 19504, 0x0000 },   /* R19504 - DACL_RETUNE_C25_1 */
+	{ 19505, 0x0000 },   /* R19505 - DACL_RETUNE_C25_0 */
+	{ 19506, 0x0000 },   /* R19506 - DACL_RETUNE_C26_1 */
+	{ 19507, 0x0000 },   /* R19507 - DACL_RETUNE_C26_0 */
+	{ 19508, 0x0000 },   /* R19508 - DACL_RETUNE_C27_1 */
+	{ 19509, 0x0000 },   /* R19509 - DACL_RETUNE_C27_0 */
+	{ 19510, 0x0000 },   /* R19510 - DACL_RETUNE_C28_1 */
+	{ 19511, 0x0000 },   /* R19511 - DACL_RETUNE_C28_0 */
+	{ 19512, 0x0000 },   /* R19512 - DACL_RETUNE_C29_1 */
+	{ 19513, 0x0000 },   /* R19513 - DACL_RETUNE_C29_0 */
+	{ 19514, 0x0000 },   /* R19514 - DACL_RETUNE_C30_1 */
+	{ 19515, 0x0000 },   /* R19515 - DACL_RETUNE_C30_0 */
+	{ 19516, 0x0000 },   /* R19516 - DACL_RETUNE_C31_1 */
+	{ 19517, 0x0000 },   /* R19517 - DACL_RETUNE_C31_0 */
+	{ 19518, 0x0000 },   /* R19518 - DACL_RETUNE_C32_1 */
+	{ 19519, 0x0000 },   /* R19519 - DACL_RETUNE_C32_0 */
 
-	[19968] = 0x0020,     /* R19968 - RETUNEDAC_PG2_1 */
-	[19969] = 0x0000,     /* R19969 - RETUNEDAC_PG2_0 */
-	[19970] = 0x0040,     /* R19970 - RETUNEDAC_PG_1 */
-	[19971] = 0x0000,     /* R19971 - RETUNEDAC_PG_0 */
+	{ 19968, 0x0020 },   /* R19968 - RETUNEDAC_PG2_1 */
+	{ 19969, 0x0000 },   /* R19969 - RETUNEDAC_PG2_0 */
+	{ 19970, 0x0040 },   /* R19970 - RETUNEDAC_PG_1 */
+	{ 19971, 0x0000 },   /* R19971 - RETUNEDAC_PG_0 */
 
-	[20480] = 0x007F,     /* R20480 - DACR_RETUNE_C1_1 */
-	[20481] = 0xFFFF,     /* R20481 - DACR_RETUNE_C1_0 */
-	[20482] = 0x0000,     /* R20482 - DACR_RETUNE_C2_1 */
-	[20483] = 0x0000,     /* R20483 - DACR_RETUNE_C2_0 */
-	[20484] = 0x0000,     /* R20484 - DACR_RETUNE_C3_1 */
-	[20485] = 0x0000,     /* R20485 - DACR_RETUNE_C3_0 */
-	[20486] = 0x0000,     /* R20486 - DACR_RETUNE_C4_1 */
-	[20487] = 0x0000,     /* R20487 - DACR_RETUNE_C4_0 */
-	[20488] = 0x0000,     /* R20488 - DACR_RETUNE_C5_1 */
-	[20489] = 0x0000,     /* R20489 - DACR_RETUNE_C5_0 */
-	[20490] = 0x0000,     /* R20490 - DACR_RETUNE_C6_1 */
-	[20491] = 0x0000,     /* R20491 - DACR_RETUNE_C6_0 */
-	[20492] = 0x0000,     /* R20492 - DACR_RETUNE_C7_1 */
-	[20493] = 0x0000,     /* R20493 - DACR_RETUNE_C7_0 */
-	[20494] = 0x0000,     /* R20494 - DACR_RETUNE_C8_1 */
-	[20495] = 0x0000,     /* R20495 - DACR_RETUNE_C8_0 */
-	[20496] = 0x0000,     /* R20496 - DACR_RETUNE_C9_1 */
-	[20497] = 0x0000,     /* R20497 - DACR_RETUNE_C9_0 */
-	[20498] = 0x0000,     /* R20498 - DACR_RETUNE_C10_1 */
-	[20499] = 0x0000,     /* R20499 - DACR_RETUNE_C10_0 */
-	[20500] = 0x0000,     /* R20500 - DACR_RETUNE_C11_1 */
-	[20501] = 0x0000,     /* R20501 - DACR_RETUNE_C11_0 */
-	[20502] = 0x0000,     /* R20502 - DACR_RETUNE_C12_1 */
-	[20503] = 0x0000,     /* R20503 - DACR_RETUNE_C12_0 */
-	[20504] = 0x0000,     /* R20504 - DACR_RETUNE_C13_1 */
-	[20505] = 0x0000,     /* R20505 - DACR_RETUNE_C13_0 */
-	[20506] = 0x0000,     /* R20506 - DACR_RETUNE_C14_1 */
-	[20507] = 0x0000,     /* R20507 - DACR_RETUNE_C14_0 */
-	[20508] = 0x0000,     /* R20508 - DACR_RETUNE_C15_1 */
-	[20509] = 0x0000,     /* R20509 - DACR_RETUNE_C15_0 */
-	[20510] = 0x0000,     /* R20510 - DACR_RETUNE_C16_1 */
-	[20511] = 0x0000,     /* R20511 - DACR_RETUNE_C16_0 */
-	[20512] = 0x0000,     /* R20512 - DACR_RETUNE_C17_1 */
-	[20513] = 0x0000,     /* R20513 - DACR_RETUNE_C17_0 */
-	[20514] = 0x0000,     /* R20514 - DACR_RETUNE_C18_1 */
-	[20515] = 0x0000,     /* R20515 - DACR_RETUNE_C18_0 */
-	[20516] = 0x0000,     /* R20516 - DACR_RETUNE_C19_1 */
-	[20517] = 0x0000,     /* R20517 - DACR_RETUNE_C19_0 */
-	[20518] = 0x0000,     /* R20518 - DACR_RETUNE_C20_1 */
-	[20519] = 0x0000,     /* R20519 - DACR_RETUNE_C20_0 */
-	[20520] = 0x0000,     /* R20520 - DACR_RETUNE_C21_1 */
-	[20521] = 0x0000,     /* R20521 - DACR_RETUNE_C21_0 */
-	[20522] = 0x0000,     /* R20522 - DACR_RETUNE_C22_1 */
-	[20523] = 0x0000,     /* R20523 - DACR_RETUNE_C22_0 */
-	[20524] = 0x0000,     /* R20524 - DACR_RETUNE_C23_1 */
-	[20525] = 0x0000,     /* R20525 - DACR_RETUNE_C23_0 */
-	[20526] = 0x0000,     /* R20526 - DACR_RETUNE_C24_1 */
-	[20527] = 0x0000,     /* R20527 - DACR_RETUNE_C24_0 */
-	[20528] = 0x0000,     /* R20528 - DACR_RETUNE_C25_1 */
-	[20529] = 0x0000,     /* R20529 - DACR_RETUNE_C25_0 */
-	[20530] = 0x0000,     /* R20530 - DACR_RETUNE_C26_1 */
-	[20531] = 0x0000,     /* R20531 - DACR_RETUNE_C26_0 */
-	[20532] = 0x0000,     /* R20532 - DACR_RETUNE_C27_1 */
-	[20533] = 0x0000,     /* R20533 - DACR_RETUNE_C27_0 */
-	[20534] = 0x0000,     /* R20534 - DACR_RETUNE_C28_1 */
-	[20535] = 0x0000,     /* R20535 - DACR_RETUNE_C28_0 */
-	[20536] = 0x0000,     /* R20536 - DACR_RETUNE_C29_1 */
-	[20537] = 0x0000,     /* R20537 - DACR_RETUNE_C29_0 */
-	[20538] = 0x0000,     /* R20538 - DACR_RETUNE_C30_1 */
-	[20539] = 0x0000,     /* R20539 - DACR_RETUNE_C30_0 */
-	[20540] = 0x0000,     /* R20540 - DACR_RETUNE_C31_1 */
-	[20541] = 0x0000,     /* R20541 - DACR_RETUNE_C31_0 */
-	[20542] = 0x0000,     /* R20542 - DACR_RETUNE_C32_1 */
-	[20543] = 0x0000,     /* R20543 - DACR_RETUNE_C32_0 */
+	{ 20480, 0x007F },   /* R20480 - DACR_RETUNE_C1_1 */
+	{ 20481, 0xFFFF },   /* R20481 - DACR_RETUNE_C1_0 */
+	{ 20482, 0x0000 },   /* R20482 - DACR_RETUNE_C2_1 */
+	{ 20483, 0x0000 },   /* R20483 - DACR_RETUNE_C2_0 */
+	{ 20484, 0x0000 },   /* R20484 - DACR_RETUNE_C3_1 */
+	{ 20485, 0x0000 },   /* R20485 - DACR_RETUNE_C3_0 */
+	{ 20486, 0x0000 },   /* R20486 - DACR_RETUNE_C4_1 */
+	{ 20487, 0x0000 },   /* R20487 - DACR_RETUNE_C4_0 */
+	{ 20488, 0x0000 },   /* R20488 - DACR_RETUNE_C5_1 */
+	{ 20489, 0x0000 },   /* R20489 - DACR_RETUNE_C5_0 */
+	{ 20490, 0x0000 },   /* R20490 - DACR_RETUNE_C6_1 */
+	{ 20491, 0x0000 },   /* R20491 - DACR_RETUNE_C6_0 */
+	{ 20492, 0x0000 },   /* R20492 - DACR_RETUNE_C7_1 */
+	{ 20493, 0x0000 },   /* R20493 - DACR_RETUNE_C7_0 */
+	{ 20494, 0x0000 },   /* R20494 - DACR_RETUNE_C8_1 */
+	{ 20495, 0x0000 },   /* R20495 - DACR_RETUNE_C8_0 */
+	{ 20496, 0x0000 },   /* R20496 - DACR_RETUNE_C9_1 */
+	{ 20497, 0x0000 },   /* R20497 - DACR_RETUNE_C9_0 */
+	{ 20498, 0x0000 },   /* R20498 - DACR_RETUNE_C10_1 */
+	{ 20499, 0x0000 },   /* R20499 - DACR_RETUNE_C10_0 */
+	{ 20500, 0x0000 },   /* R20500 - DACR_RETUNE_C11_1 */
+	{ 20501, 0x0000 },   /* R20501 - DACR_RETUNE_C11_0 */
+	{ 20502, 0x0000 },   /* R20502 - DACR_RETUNE_C12_1 */
+	{ 20503, 0x0000 },   /* R20503 - DACR_RETUNE_C12_0 */
+	{ 20504, 0x0000 },   /* R20504 - DACR_RETUNE_C13_1 */
+	{ 20505, 0x0000 },   /* R20505 - DACR_RETUNE_C13_0 */
+	{ 20506, 0x0000 },   /* R20506 - DACR_RETUNE_C14_1 */
+	{ 20507, 0x0000 },   /* R20507 - DACR_RETUNE_C14_0 */
+	{ 20508, 0x0000 },   /* R20508 - DACR_RETUNE_C15_1 */
+	{ 20509, 0x0000 },   /* R20509 - DACR_RETUNE_C15_0 */
+	{ 20510, 0x0000 },   /* R20510 - DACR_RETUNE_C16_1 */
+	{ 20511, 0x0000 },   /* R20511 - DACR_RETUNE_C16_0 */
+	{ 20512, 0x0000 },   /* R20512 - DACR_RETUNE_C17_1 */
+	{ 20513, 0x0000 },   /* R20513 - DACR_RETUNE_C17_0 */
+	{ 20514, 0x0000 },   /* R20514 - DACR_RETUNE_C18_1 */
+	{ 20515, 0x0000 },   /* R20515 - DACR_RETUNE_C18_0 */
+	{ 20516, 0x0000 },   /* R20516 - DACR_RETUNE_C19_1 */
+	{ 20517, 0x0000 },   /* R20517 - DACR_RETUNE_C19_0 */
+	{ 20518, 0x0000 },   /* R20518 - DACR_RETUNE_C20_1 */
+	{ 20519, 0x0000 },   /* R20519 - DACR_RETUNE_C20_0 */
+	{ 20520, 0x0000 },   /* R20520 - DACR_RETUNE_C21_1 */
+	{ 20521, 0x0000 },   /* R20521 - DACR_RETUNE_C21_0 */
+	{ 20522, 0x0000 },   /* R20522 - DACR_RETUNE_C22_1 */
+	{ 20523, 0x0000 },   /* R20523 - DACR_RETUNE_C22_0 */
+	{ 20524, 0x0000 },   /* R20524 - DACR_RETUNE_C23_1 */
+	{ 20525, 0x0000 },   /* R20525 - DACR_RETUNE_C23_0 */
+	{ 20526, 0x0000 },   /* R20526 - DACR_RETUNE_C24_1 */
+	{ 20527, 0x0000 },   /* R20527 - DACR_RETUNE_C24_0 */
+	{ 20528, 0x0000 },   /* R20528 - DACR_RETUNE_C25_1 */
+	{ 20529, 0x0000 },   /* R20529 - DACR_RETUNE_C25_0 */
+	{ 20530, 0x0000 },   /* R20530 - DACR_RETUNE_C26_1 */
+	{ 20531, 0x0000 },   /* R20531 - DACR_RETUNE_C26_0 */
+	{ 20532, 0x0000 },   /* R20532 - DACR_RETUNE_C27_1 */
+	{ 20533, 0x0000 },   /* R20533 - DACR_RETUNE_C27_0 */
+	{ 20534, 0x0000 },   /* R20534 - DACR_RETUNE_C28_1 */
+	{ 20535, 0x0000 },   /* R20535 - DACR_RETUNE_C28_0 */
+	{ 20536, 0x0000 },   /* R20536 - DACR_RETUNE_C29_1 */
+	{ 20537, 0x0000 },   /* R20537 - DACR_RETUNE_C29_0 */
+	{ 20538, 0x0000 },   /* R20538 - DACR_RETUNE_C30_1 */
+	{ 20539, 0x0000 },   /* R20539 - DACR_RETUNE_C30_0 */
+	{ 20540, 0x0000 },   /* R20540 - DACR_RETUNE_C31_1 */
+	{ 20541, 0x0000 },   /* R20541 - DACR_RETUNE_C31_0 */
+	{ 20542, 0x0000 },   /* R20542 - DACR_RETUNE_C32_1 */
+	{ 20543, 0x0000 },   /* R20543 - DACR_RETUNE_C32_0 */
 
-	[20992] = 0x008C,     /* R20992 - VSS_XHD2_1 */
-	[20993] = 0x0200,     /* R20993 - VSS_XHD2_0 */
-	[20994] = 0x0035,     /* R20994 - VSS_XHD3_1 */
-	[20995] = 0x0700,     /* R20995 - VSS_XHD3_0 */
-	[20996] = 0x003A,     /* R20996 - VSS_XHN1_1 */
-	[20997] = 0x4100,     /* R20997 - VSS_XHN1_0 */
-	[20998] = 0x008B,     /* R20998 - VSS_XHN2_1 */
-	[20999] = 0x7D00,     /* R20999 - VSS_XHN2_0 */
-	[21000] = 0x003A,     /* R21000 - VSS_XHN3_1 */
-	[21001] = 0x4100,     /* R21001 - VSS_XHN3_0 */
-	[21002] = 0x008C,     /* R21002 - VSS_XLA_1 */
-	[21003] = 0xFEE8,     /* R21003 - VSS_XLA_0 */
-	[21004] = 0x0078,     /* R21004 - VSS_XLB_1 */
-	[21005] = 0x0000,     /* R21005 - VSS_XLB_0 */
-	[21006] = 0x003F,     /* R21006 - VSS_XLG_1 */
-	[21007] = 0xB260,     /* R21007 - VSS_XLG_0 */
-	[21008] = 0x002D,     /* R21008 - VSS_PG2_1 */
-	[21009] = 0x1818,     /* R21009 - VSS_PG2_0 */
-	[21010] = 0x0020,     /* R21010 - VSS_PG_1 */
-	[21011] = 0x0000,     /* R21011 - VSS_PG_0 */
-	[21012] = 0x00F1,     /* R21012 - VSS_XTD1_1 */
-	[21013] = 0x8340,     /* R21013 - VSS_XTD1_0 */
-	[21014] = 0x00FB,     /* R21014 - VSS_XTD2_1 */
-	[21015] = 0x8300,     /* R21015 - VSS_XTD2_0 */
-	[21016] = 0x00EE,     /* R21016 - VSS_XTD3_1 */
-	[21017] = 0xAEC0,     /* R21017 - VSS_XTD3_0 */
-	[21018] = 0x00FB,     /* R21018 - VSS_XTD4_1 */
-	[21019] = 0xAC40,     /* R21019 - VSS_XTD4_0 */
-	[21020] = 0x00F1,     /* R21020 - VSS_XTD5_1 */
-	[21021] = 0x7F80,     /* R21021 - VSS_XTD5_0 */
-	[21022] = 0x00F4,     /* R21022 - VSS_XTD6_1 */
-	[21023] = 0x3B40,     /* R21023 - VSS_XTD6_0 */
-	[21024] = 0x00F5,     /* R21024 - VSS_XTD7_1 */
-	[21025] = 0xFB00,     /* R21025 - VSS_XTD7_0 */
-	[21026] = 0x00EA,     /* R21026 - VSS_XTD8_1 */
-	[21027] = 0x10C0,     /* R21027 - VSS_XTD8_0 */
-	[21028] = 0x00FC,     /* R21028 - VSS_XTD9_1 */
-	[21029] = 0xC580,     /* R21029 - VSS_XTD9_0 */
-	[21030] = 0x00E2,     /* R21030 - VSS_XTD10_1 */
-	[21031] = 0x75C0,     /* R21031 - VSS_XTD10_0 */
-	[21032] = 0x0004,     /* R21032 - VSS_XTD11_1 */
-	[21033] = 0xB480,     /* R21033 - VSS_XTD11_0 */
-	[21034] = 0x00D4,     /* R21034 - VSS_XTD12_1 */
-	[21035] = 0xF980,     /* R21035 - VSS_XTD12_0 */
-	[21036] = 0x0004,     /* R21036 - VSS_XTD13_1 */
-	[21037] = 0x9140,     /* R21037 - VSS_XTD13_0 */
-	[21038] = 0x00D8,     /* R21038 - VSS_XTD14_1 */
-	[21039] = 0xA480,     /* R21039 - VSS_XTD14_0 */
-	[21040] = 0x0002,     /* R21040 - VSS_XTD15_1 */
-	[21041] = 0x3DC0,     /* R21041 - VSS_XTD15_0 */
-	[21042] = 0x00CF,     /* R21042 - VSS_XTD16_1 */
-	[21043] = 0x7A80,     /* R21043 - VSS_XTD16_0 */
-	[21044] = 0x00DC,     /* R21044 - VSS_XTD17_1 */
-	[21045] = 0x0600,     /* R21045 - VSS_XTD17_0 */
-	[21046] = 0x00F2,     /* R21046 - VSS_XTD18_1 */
-	[21047] = 0xDAC0,     /* R21047 - VSS_XTD18_0 */
-	[21048] = 0x00BA,     /* R21048 - VSS_XTD19_1 */
-	[21049] = 0xF340,     /* R21049 - VSS_XTD19_0 */
-	[21050] = 0x000A,     /* R21050 - VSS_XTD20_1 */
-	[21051] = 0x7940,     /* R21051 - VSS_XTD20_0 */
-	[21052] = 0x001C,     /* R21052 - VSS_XTD21_1 */
-	[21053] = 0x0680,     /* R21053 - VSS_XTD21_0 */
-	[21054] = 0x00FD,     /* R21054 - VSS_XTD22_1 */
-	[21055] = 0x2D00,     /* R21055 - VSS_XTD22_0 */
-	[21056] = 0x001C,     /* R21056 - VSS_XTD23_1 */
-	[21057] = 0xE840,     /* R21057 - VSS_XTD23_0 */
-	[21058] = 0x000D,     /* R21058 - VSS_XTD24_1 */
-	[21059] = 0xDC40,     /* R21059 - VSS_XTD24_0 */
-	[21060] = 0x00FC,     /* R21060 - VSS_XTD25_1 */
-	[21061] = 0x9D00,     /* R21061 - VSS_XTD25_0 */
-	[21062] = 0x0009,     /* R21062 - VSS_XTD26_1 */
-	[21063] = 0x5580,     /* R21063 - VSS_XTD26_0 */
-	[21064] = 0x00FE,     /* R21064 - VSS_XTD27_1 */
-	[21065] = 0x7E80,     /* R21065 - VSS_XTD27_0 */
-	[21066] = 0x000E,     /* R21066 - VSS_XTD28_1 */
-	[21067] = 0xAB40,     /* R21067 - VSS_XTD28_0 */
-	[21068] = 0x00F9,     /* R21068 - VSS_XTD29_1 */
-	[21069] = 0x9880,     /* R21069 - VSS_XTD29_0 */
-	[21070] = 0x0009,     /* R21070 - VSS_XTD30_1 */
-	[21071] = 0x87C0,     /* R21071 - VSS_XTD30_0 */
-	[21072] = 0x00FD,     /* R21072 - VSS_XTD31_1 */
-	[21073] = 0x2C40,     /* R21073 - VSS_XTD31_0 */
-	[21074] = 0x0009,     /* R21074 - VSS_XTD32_1 */
-	[21075] = 0x4800,     /* R21075 - VSS_XTD32_0 */
-	[21076] = 0x0003,     /* R21076 - VSS_XTS1_1 */
-	[21077] = 0x5F40,     /* R21077 - VSS_XTS1_0 */
-	[21078] = 0x0000,     /* R21078 - VSS_XTS2_1 */
-	[21079] = 0x8700,     /* R21079 - VSS_XTS2_0 */
-	[21080] = 0x00FA,     /* R21080 - VSS_XTS3_1 */
-	[21081] = 0xE4C0,     /* R21081 - VSS_XTS3_0 */
-	[21082] = 0x0000,     /* R21082 - VSS_XTS4_1 */
-	[21083] = 0x0B40,     /* R21083 - VSS_XTS4_0 */
-	[21084] = 0x0004,     /* R21084 - VSS_XTS5_1 */
-	[21085] = 0xE180,     /* R21085 - VSS_XTS5_0 */
-	[21086] = 0x0001,     /* R21086 - VSS_XTS6_1 */
-	[21087] = 0x1F40,     /* R21087 - VSS_XTS6_0 */
-	[21088] = 0x00F8,     /* R21088 - VSS_XTS7_1 */
-	[21089] = 0xB000,     /* R21089 - VSS_XTS7_0 */
-	[21090] = 0x00FB,     /* R21090 - VSS_XTS8_1 */
-	[21091] = 0xCBC0,     /* R21091 - VSS_XTS8_0 */
-	[21092] = 0x0004,     /* R21092 - VSS_XTS9_1 */
-	[21093] = 0xF380,     /* R21093 - VSS_XTS9_0 */
-	[21094] = 0x0007,     /* R21094 - VSS_XTS10_1 */
-	[21095] = 0xDF40,     /* R21095 - VSS_XTS10_0 */
-	[21096] = 0x00FF,     /* R21096 - VSS_XTS11_1 */
-	[21097] = 0x0700,     /* R21097 - VSS_XTS11_0 */
-	[21098] = 0x00EF,     /* R21098 - VSS_XTS12_1 */
-	[21099] = 0xD700,     /* R21099 - VSS_XTS12_0 */
-	[21100] = 0x00FB,     /* R21100 - VSS_XTS13_1 */
-	[21101] = 0xAF40,     /* R21101 - VSS_XTS13_0 */
-	[21102] = 0x0010,     /* R21102 - VSS_XTS14_1 */
-	[21103] = 0x8A80,     /* R21103 - VSS_XTS14_0 */
-	[21104] = 0x0011,     /* R21104 - VSS_XTS15_1 */
-	[21105] = 0x07C0,     /* R21105 - VSS_XTS15_0 */
-	[21106] = 0x00E0,     /* R21106 - VSS_XTS16_1 */
-	[21107] = 0x0800,     /* R21107 - VSS_XTS16_0 */
-	[21108] = 0x00D2,     /* R21108 - VSS_XTS17_1 */
-	[21109] = 0x7600,     /* R21109 - VSS_XTS17_0 */
-	[21110] = 0x0020,     /* R21110 - VSS_XTS18_1 */
-	[21111] = 0xCF40,     /* R21111 - VSS_XTS18_0 */
-	[21112] = 0x0030,     /* R21112 - VSS_XTS19_1 */
-	[21113] = 0x2340,     /* R21113 - VSS_XTS19_0 */
-	[21114] = 0x00FD,     /* R21114 - VSS_XTS20_1 */
-	[21115] = 0x69C0,     /* R21115 - VSS_XTS20_0 */
-	[21116] = 0x0028,     /* R21116 - VSS_XTS21_1 */
-	[21117] = 0x3500,     /* R21117 - VSS_XTS21_0 */
-	[21118] = 0x0006,     /* R21118 - VSS_XTS22_1 */
-	[21119] = 0x3300,     /* R21119 - VSS_XTS22_0 */
-	[21120] = 0x00D9,     /* R21120 - VSS_XTS23_1 */
-	[21121] = 0xF6C0,     /* R21121 - VSS_XTS23_0 */
-	[21122] = 0x00F3,     /* R21122 - VSS_XTS24_1 */
-	[21123] = 0x3340,     /* R21123 - VSS_XTS24_0 */
-	[21124] = 0x000F,     /* R21124 - VSS_XTS25_1 */
-	[21125] = 0x4200,     /* R21125 - VSS_XTS25_0 */
-	[21126] = 0x0004,     /* R21126 - VSS_XTS26_1 */
-	[21127] = 0x0C80,     /* R21127 - VSS_XTS26_0 */
-	[21128] = 0x00FB,     /* R21128 - VSS_XTS27_1 */
-	[21129] = 0x3F80,     /* R21129 - VSS_XTS27_0 */
-	[21130] = 0x00F7,     /* R21130 - VSS_XTS28_1 */
-	[21131] = 0x57C0,     /* R21131 - VSS_XTS28_0 */
-	[21132] = 0x0003,     /* R21132 - VSS_XTS29_1 */
-	[21133] = 0x5400,     /* R21133 - VSS_XTS29_0 */
-	[21134] = 0x0000,     /* R21134 - VSS_XTS30_1 */
-	[21135] = 0xC6C0,     /* R21135 - VSS_XTS30_0 */
-	[21136] = 0x0003,     /* R21136 - VSS_XTS31_1 */
-	[21137] = 0x12C0,     /* R21137 - VSS_XTS31_0 */
-	[21138] = 0x00FD,     /* R21138 - VSS_XTS32_1 */
-	[21139] = 0x8580,     /* R21139 - VSS_XTS32_0 */
+	{ 20992, 0x008C },   /* R20992 - VSS_XHD2_1 */
+	{ 20993, 0x0200 },   /* R20993 - VSS_XHD2_0 */
+	{ 20994, 0x0035 },   /* R20994 - VSS_XHD3_1 */
+	{ 20995, 0x0700 },   /* R20995 - VSS_XHD3_0 */
+	{ 20996, 0x003A },   /* R20996 - VSS_XHN1_1 */
+	{ 20997, 0x4100 },   /* R20997 - VSS_XHN1_0 */
+	{ 20998, 0x008B },   /* R20998 - VSS_XHN2_1 */
+	{ 20999, 0x7D00 },   /* R20999 - VSS_XHN2_0 */
+	{ 21000, 0x003A },   /* R21000 - VSS_XHN3_1 */
+	{ 21001, 0x4100 },   /* R21001 - VSS_XHN3_0 */
+	{ 21002, 0x008C },   /* R21002 - VSS_XLA_1 */
+	{ 21003, 0xFEE8 },   /* R21003 - VSS_XLA_0 */
+	{ 21004, 0x0078 },   /* R21004 - VSS_XLB_1 */
+	{ 21005, 0x0000 },   /* R21005 - VSS_XLB_0 */
+	{ 21006, 0x003F },   /* R21006 - VSS_XLG_1 */
+	{ 21007, 0xB260 },   /* R21007 - VSS_XLG_0 */
+	{ 21008, 0x002D },   /* R21008 - VSS_PG2_1 */
+	{ 21009, 0x1818 },   /* R21009 - VSS_PG2_0 */
+	{ 21010, 0x0020 },   /* R21010 - VSS_PG_1 */
+	{ 21011, 0x0000 },   /* R21011 - VSS_PG_0 */
+	{ 21012, 0x00F1 },   /* R21012 - VSS_XTD1_1 */
+	{ 21013, 0x8340 },   /* R21013 - VSS_XTD1_0 */
+	{ 21014, 0x00FB },   /* R21014 - VSS_XTD2_1 */
+	{ 21015, 0x8300 },   /* R21015 - VSS_XTD2_0 */
+	{ 21016, 0x00EE },   /* R21016 - VSS_XTD3_1 */
+	{ 21017, 0xAEC0 },   /* R21017 - VSS_XTD3_0 */
+	{ 21018, 0x00FB },   /* R21018 - VSS_XTD4_1 */
+	{ 21019, 0xAC40 },   /* R21019 - VSS_XTD4_0 */
+	{ 21020, 0x00F1 },   /* R21020 - VSS_XTD5_1 */
+	{ 21021, 0x7F80 },   /* R21021 - VSS_XTD5_0 */
+	{ 21022, 0x00F4 },   /* R21022 - VSS_XTD6_1 */
+	{ 21023, 0x3B40 },   /* R21023 - VSS_XTD6_0 */
+	{ 21024, 0x00F5 },   /* R21024 - VSS_XTD7_1 */
+	{ 21025, 0xFB00 },   /* R21025 - VSS_XTD7_0 */
+	{ 21026, 0x00EA },   /* R21026 - VSS_XTD8_1 */
+	{ 21027, 0x10C0 },   /* R21027 - VSS_XTD8_0 */
+	{ 21028, 0x00FC },   /* R21028 - VSS_XTD9_1 */
+	{ 21029, 0xC580 },   /* R21029 - VSS_XTD9_0 */
+	{ 21030, 0x00E2 },   /* R21030 - VSS_XTD10_1 */
+	{ 21031, 0x75C0 },   /* R21031 - VSS_XTD10_0 */
+	{ 21032, 0x0004 },   /* R21032 - VSS_XTD11_1 */
+	{ 21033, 0xB480 },   /* R21033 - VSS_XTD11_0 */
+	{ 21034, 0x00D4 },   /* R21034 - VSS_XTD12_1 */
+	{ 21035, 0xF980 },   /* R21035 - VSS_XTD12_0 */
+	{ 21036, 0x0004 },   /* R21036 - VSS_XTD13_1 */
+	{ 21037, 0x9140 },   /* R21037 - VSS_XTD13_0 */
+	{ 21038, 0x00D8 },   /* R21038 - VSS_XTD14_1 */
+	{ 21039, 0xA480 },   /* R21039 - VSS_XTD14_0 */
+	{ 21040, 0x0002 },   /* R21040 - VSS_XTD15_1 */
+	{ 21041, 0x3DC0 },   /* R21041 - VSS_XTD15_0 */
+	{ 21042, 0x00CF },   /* R21042 - VSS_XTD16_1 */
+	{ 21043, 0x7A80 },   /* R21043 - VSS_XTD16_0 */
+	{ 21044, 0x00DC },   /* R21044 - VSS_XTD17_1 */
+	{ 21045, 0x0600 },   /* R21045 - VSS_XTD17_0 */
+	{ 21046, 0x00F2 },   /* R21046 - VSS_XTD18_1 */
+	{ 21047, 0xDAC0 },   /* R21047 - VSS_XTD18_0 */
+	{ 21048, 0x00BA },   /* R21048 - VSS_XTD19_1 */
+	{ 21049, 0xF340 },   /* R21049 - VSS_XTD19_0 */
+	{ 21050, 0x000A },   /* R21050 - VSS_XTD20_1 */
+	{ 21051, 0x7940 },   /* R21051 - VSS_XTD20_0 */
+	{ 21052, 0x001C },   /* R21052 - VSS_XTD21_1 */
+	{ 21053, 0x0680 },   /* R21053 - VSS_XTD21_0 */
+	{ 21054, 0x00FD },   /* R21054 - VSS_XTD22_1 */
+	{ 21055, 0x2D00 },   /* R21055 - VSS_XTD22_0 */
+	{ 21056, 0x001C },   /* R21056 - VSS_XTD23_1 */
+	{ 21057, 0xE840 },   /* R21057 - VSS_XTD23_0 */
+	{ 21058, 0x000D },   /* R21058 - VSS_XTD24_1 */
+	{ 21059, 0xDC40 },   /* R21059 - VSS_XTD24_0 */
+	{ 21060, 0x00FC },   /* R21060 - VSS_XTD25_1 */
+	{ 21061, 0x9D00 },   /* R21061 - VSS_XTD25_0 */
+	{ 21062, 0x0009 },   /* R21062 - VSS_XTD26_1 */
+	{ 21063, 0x5580 },   /* R21063 - VSS_XTD26_0 */
+	{ 21064, 0x00FE },   /* R21064 - VSS_XTD27_1 */
+	{ 21065, 0x7E80 },   /* R21065 - VSS_XTD27_0 */
+	{ 21066, 0x000E },   /* R21066 - VSS_XTD28_1 */
+	{ 21067, 0xAB40 },   /* R21067 - VSS_XTD28_0 */
+	{ 21068, 0x00F9 },   /* R21068 - VSS_XTD29_1 */
+	{ 21069, 0x9880 },   /* R21069 - VSS_XTD29_0 */
+	{ 21070, 0x0009 },   /* R21070 - VSS_XTD30_1 */
+	{ 21071, 0x87C0 },   /* R21071 - VSS_XTD30_0 */
+	{ 21072, 0x00FD },   /* R21072 - VSS_XTD31_1 */
+	{ 21073, 0x2C40 },   /* R21073 - VSS_XTD31_0 */
+	{ 21074, 0x0009 },   /* R21074 - VSS_XTD32_1 */
+	{ 21075, 0x4800 },   /* R21075 - VSS_XTD32_0 */
+	{ 21076, 0x0003 },   /* R21076 - VSS_XTS1_1 */
+	{ 21077, 0x5F40 },   /* R21077 - VSS_XTS1_0 */
+	{ 21078, 0x0000 },   /* R21078 - VSS_XTS2_1 */
+	{ 21079, 0x8700 },   /* R21079 - VSS_XTS2_0 */
+	{ 21080, 0x00FA },   /* R21080 - VSS_XTS3_1 */
+	{ 21081, 0xE4C0 },   /* R21081 - VSS_XTS3_0 */
+	{ 21082, 0x0000 },   /* R21082 - VSS_XTS4_1 */
+	{ 21083, 0x0B40 },   /* R21083 - VSS_XTS4_0 */
+	{ 21084, 0x0004 },   /* R21084 - VSS_XTS5_1 */
+	{ 21085, 0xE180 },   /* R21085 - VSS_XTS5_0 */
+	{ 21086, 0x0001 },   /* R21086 - VSS_XTS6_1 */
+	{ 21087, 0x1F40 },   /* R21087 - VSS_XTS6_0 */
+	{ 21088, 0x00F8 },   /* R21088 - VSS_XTS7_1 */
+	{ 21089, 0xB000 },   /* R21089 - VSS_XTS7_0 */
+	{ 21090, 0x00FB },   /* R21090 - VSS_XTS8_1 */
+	{ 21091, 0xCBC0 },   /* R21091 - VSS_XTS8_0 */
+	{ 21092, 0x0004 },   /* R21092 - VSS_XTS9_1 */
+	{ 21093, 0xF380 },   /* R21093 - VSS_XTS9_0 */
+	{ 21094, 0x0007 },   /* R21094 - VSS_XTS10_1 */
+	{ 21095, 0xDF40 },   /* R21095 - VSS_XTS10_0 */
+	{ 21096, 0x00FF },   /* R21096 - VSS_XTS11_1 */
+	{ 21097, 0x0700 },   /* R21097 - VSS_XTS11_0 */
+	{ 21098, 0x00EF },   /* R21098 - VSS_XTS12_1 */
+	{ 21099, 0xD700 },   /* R21099 - VSS_XTS12_0 */
+	{ 21100, 0x00FB },   /* R21100 - VSS_XTS13_1 */
+	{ 21101, 0xAF40 },   /* R21101 - VSS_XTS13_0 */
+	{ 21102, 0x0010 },   /* R21102 - VSS_XTS14_1 */
+	{ 21103, 0x8A80 },   /* R21103 - VSS_XTS14_0 */
+	{ 21104, 0x0011 },   /* R21104 - VSS_XTS15_1 */
+	{ 21105, 0x07C0 },   /* R21105 - VSS_XTS15_0 */
+	{ 21106, 0x00E0 },   /* R21106 - VSS_XTS16_1 */
+	{ 21107, 0x0800 },   /* R21107 - VSS_XTS16_0 */
+	{ 21108, 0x00D2 },   /* R21108 - VSS_XTS17_1 */
+	{ 21109, 0x7600 },   /* R21109 - VSS_XTS17_0 */
+	{ 21110, 0x0020 },   /* R21110 - VSS_XTS18_1 */
+	{ 21111, 0xCF40 },   /* R21111 - VSS_XTS18_0 */
+	{ 21112, 0x0030 },   /* R21112 - VSS_XTS19_1 */
+	{ 21113, 0x2340 },   /* R21113 - VSS_XTS19_0 */
+	{ 21114, 0x00FD },   /* R21114 - VSS_XTS20_1 */
+	{ 21115, 0x69C0 },   /* R21115 - VSS_XTS20_0 */
+	{ 21116, 0x0028 },   /* R21116 - VSS_XTS21_1 */
+	{ 21117, 0x3500 },   /* R21117 - VSS_XTS21_0 */
+	{ 21118, 0x0006 },   /* R21118 - VSS_XTS22_1 */
+	{ 21119, 0x3300 },   /* R21119 - VSS_XTS22_0 */
+	{ 21120, 0x00D9 },   /* R21120 - VSS_XTS23_1 */
+	{ 21121, 0xF6C0 },   /* R21121 - VSS_XTS23_0 */
+	{ 21122, 0x00F3 },   /* R21122 - VSS_XTS24_1 */
+	{ 21123, 0x3340 },   /* R21123 - VSS_XTS24_0 */
+	{ 21124, 0x000F },   /* R21124 - VSS_XTS25_1 */
+	{ 21125, 0x4200 },   /* R21125 - VSS_XTS25_0 */
+	{ 21126, 0x0004 },   /* R21126 - VSS_XTS26_1 */
+	{ 21127, 0x0C80 },   /* R21127 - VSS_XTS26_0 */
+	{ 21128, 0x00FB },   /* R21128 - VSS_XTS27_1 */
+	{ 21129, 0x3F80 },   /* R21129 - VSS_XTS27_0 */
+	{ 21130, 0x00F7 },   /* R21130 - VSS_XTS28_1 */
+	{ 21131, 0x57C0 },   /* R21131 - VSS_XTS28_0 */
+	{ 21132, 0x0003 },   /* R21132 - VSS_XTS29_1 */
+	{ 21133, 0x5400 },   /* R21133 - VSS_XTS29_0 */
+	{ 21134, 0x0000 },   /* R21134 - VSS_XTS30_1 */
+	{ 21135, 0xC6C0 },   /* R21135 - VSS_XTS30_0 */
+	{ 21136, 0x0003 },   /* R21136 - VSS_XTS31_1 */
+	{ 21137, 0x12C0 },   /* R21137 - VSS_XTS31_0 */
+	{ 21138, 0x00FD },   /* R21138 - VSS_XTS32_1 */
+	{ 21139, 0x8580 },   /* R21139 - VSS_XTS32_0 */
 };
 
 static const struct wm8962_reg_access {
@@ -802,7 +803,7 @@
 	u16 vol;
 } wm8962_reg_access[WM8962_MAX_REGISTER + 1] = {
 	[0] = { 0x00FF, 0x01FF, 0x0000 }, /* R0     - Left Input volume */
-	[1] = { 0xFEFF, 0x01FF, 0xFFFF }, /* R1     - Right Input volume */
+	[1] = { 0xFEFF, 0x01FF, 0x0000 }, /* R1     - Right Input volume */
 	[2] = { 0x00FF, 0x01FF, 0x0000 }, /* R2     - HPOUTL volume */
 	[3] = { 0x00FF, 0x01FF, 0x0000 }, /* R3     - HPOUTR volume */
 	[4] = { 0x07FE, 0x07FE, 0xFFFF }, /* R4     - Clocking1 */
@@ -1943,7 +1944,7 @@
 	[21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
 };
 
-static int wm8962_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8962_volatile_register(struct device *dev, unsigned int reg)
 {
 	if (wm8962_reg_access[reg].vol)
 		return 1;
@@ -1951,7 +1952,7 @@
 		return 0;
 }
 
-static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8962_readable_register(struct device *dev, unsigned int reg)
 {
 	if (wm8962_reg_access[reg].read)
 		return 1;
@@ -1959,15 +1960,15 @@
 		return 0;
 }
 
-static int wm8962_reset(struct snd_soc_codec *codec)
+static int wm8962_reset(struct wm8962_priv *wm8962)
 {
 	int ret;
 
-	ret = snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243);
+	ret = regmap_write(wm8962->regmap, WM8962_SOFTWARE_RESET, 0x6243);
 	if (ret != 0)
 		return ret;
 
-	return snd_soc_write(codec, WM8962_PLL_SOFTWARE_RESET, 0);
+	return regmap_write(wm8962->regmap, WM8962_PLL_SOFTWARE_RESET, 0);
 }
 
 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
@@ -2345,6 +2346,10 @@
 	int src;
 	int fll;
 
+	/* Ignore attempts to run the event during startup */
+	if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+		return 0;
+
 	src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK;
 
 	switch (src) {
@@ -2670,7 +2675,7 @@
 SND_SOC_DAPM_INPUT("IN3R"),
 SND_SOC_DAPM_INPUT("IN4L"),
 SND_SOC_DAPM_INPUT("IN4R"),
-SND_SOC_DAPM_INPUT("Beep"),
+SND_SOC_DAPM_SIGGEN("Beep"),
 SND_SOC_DAPM_INPUT("DMICDAT"),
 
 SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
@@ -2684,6 +2689,8 @@
 SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT,
 		      WM8962_DSP2_ENA_SHIFT, 0, dsp2_event,
 		      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_SUPPLY("TEMP_HP", WM8962_ADDITIONAL_CONTROL_4, 2, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("TEMP_SPK", WM8962_ADDITIONAL_CONTROL_4, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
 		   inpgal, ARRAY_SIZE(inpgal)),
@@ -2839,6 +2846,9 @@
 
 	{ "HPOUTL", NULL, "HPOUT" },
 	{ "HPOUTR", NULL, "HPOUT" },
+
+	{ "HPOUTL", NULL, "TEMP_HP" },
+	{ "HPOUTR", NULL, "TEMP_HP" },
 };
 
 static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
@@ -2855,6 +2865,7 @@
 	{ "Speaker Output", NULL, "Speaker PGA" },
 	{ "Speaker Output", NULL, "SYSCLK" },
 	{ "Speaker Output", NULL, "TOCLK" },
+	{ "Speaker Output", NULL, "TEMP_SPK" },
 
 	{ "SPKOUT", NULL, "Speaker Output" },
 };
@@ -2883,10 +2894,12 @@
 	{ "SPKOUTL Output", NULL, "SPKOUTL PGA" },
 	{ "SPKOUTL Output", NULL, "SYSCLK" },
 	{ "SPKOUTL Output", NULL, "TOCLK" },
+	{ "SPKOUTL Output", NULL, "TEMP_SPK" },
 
 	{ "SPKOUTR Output", NULL, "SPKOUTR PGA" },
 	{ "SPKOUTR Output", NULL, "SYSCLK" },
 	{ "SPKOUTR Output", NULL, "TOCLK" },
+	{ "SPKOUTR Output", NULL, "TEMP_SPK" },
 
 	{ "SPKOUTL", NULL, "SPKOUTL Output" },
 	{ "SPKOUTR", NULL, "SPKOUTR Output" },
@@ -2931,33 +2944,6 @@
 	return 0;
 }
 
-static void wm8962_sync_cache(struct snd_soc_codec *codec)
-{
-	u16 *reg_cache = codec->reg_cache;
-	int i;
-
-	if (!codec->cache_sync)
-		return;
-
-	dev_dbg(codec->dev, "Syncing cache\n");
-
-	codec->cache_only = 0;
-
-	/* Sync back cached values if they're different from the
-	 * hardware default.
-	 */
-	for (i = 1; i < codec->driver->reg_cache_size; i++) {
-		if (i == WM8962_SOFTWARE_RESET)
-			continue;
-		if (reg_cache[i] == wm8962_reg[i])
-			continue;
-
-		snd_soc_write(codec, i, reg_cache[i]);
-	}
-
-	codec->cache_sync = 0;
-}
-
 /* -1 for reserved values */
 static const int bclk_divs[] = {
 	1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
@@ -3085,7 +3071,8 @@
 				return ret;
 			}
 
-			wm8962_sync_cache(codec);
+			regcache_cache_only(wm8962->regmap, false);
+			regcache_sync(wm8962->regmap);
 
 			snd_soc_update_bits(codec, WM8962_ANTI_POP,
 					    WM8962_STARTUP_BIAS_ENA |
@@ -3399,6 +3386,7 @@
 	unsigned long timeout;
 	int ret;
 	int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
+	int sysclk = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_ENA;
 
 	/* Any change? */
 	if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
@@ -3459,6 +3447,9 @@
 
 	try_wait_for_completion(&wm8962->fll_lock);
 
+	if (sysclk)
+		fll1 |= WM8962_FLL_ENA;
+
 	snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
 			    WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
 			    WM8962_FLL_ENA, fll1);
@@ -3511,7 +3502,7 @@
 #define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8962_dai_ops = {
+static const struct snd_soc_dai_ops wm8962_dai_ops = {
 	.hw_params = wm8962_hw_params,
 	.set_sysclk = wm8962_set_dai_sysclk,
 	.set_fmt = wm8962_set_dai_fmt,
@@ -3662,6 +3653,14 @@
 	snd_soc_jack_report(wm8962->jack, 0,
 			    SND_JACK_MICROPHONE | SND_JACK_BTN_0);
 
+	if (jack) {
+		snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
+		snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS");
+	} else {
+		snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK");
+		snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS");
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(wm8962_mic_detect);
@@ -3946,26 +3945,12 @@
 	bool dmicclk, dmicdat;
 
 	wm8962->codec = codec;
-	INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
-	init_completion(&wm8962->fll_lock);
+	codec->control_data = wm8962->regmap;
 
-	codec->cache_sync = 1;
-	codec->dapm.idle_bias_off = 1;
-
-	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-		goto err;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
-		wm8962->supplies[i].supply = wm8962_supply_names[i];
-
-	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8962->supplies),
-				 wm8962->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-		goto err;
+		return ret;
 	}
 
 	wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
@@ -3988,43 +3973,6 @@
 		}
 	}
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
-				    wm8962->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-		goto err_get;
-	}
-
-	ret = snd_soc_read(codec, WM8962_SOFTWARE_RESET);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to read ID register\n");
-		goto err_enable;
-	}
-	if (ret != wm8962_reg[WM8962_SOFTWARE_RESET]) {
-		dev_err(codec->dev, "Device is not a WM8962, ID %x != %x\n",
-			ret, wm8962_reg[WM8962_SOFTWARE_RESET]);
-		ret = -EINVAL;
-		goto err_enable;
-	}
-
-	ret = snd_soc_read(codec, WM8962_RIGHT_INPUT_VOLUME);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to read device revision: %d\n",
-			ret);
-		goto err_enable;
-	}
-	
-	dev_info(codec->dev, "customer id %x revision %c\n",
-		 (ret & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
-		 ((ret & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
-		 + 'A');
-
-	ret = wm8962_reset(codec);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to issue reset\n");
-		goto err_enable;
-	}
-
 	/* SYSCLK defaults to on; make sure it is off so we can safely
 	 * write to registers if the device is declocked.
 	 */
@@ -4039,8 +3987,6 @@
 			    WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
 			    0);
 
-	regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-
 	if (pdata) {
 		/* Apply static configuration for GPIOs */
 		for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
@@ -4091,6 +4037,12 @@
 	/* Stereo control for EQ */
 	snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0);
 
+	/* Don't debouce interrupts so we don't need SYSCLK */
+	snd_soc_update_bits(codec, WM8962_IRQ_DEBOUNCE,
+			    WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB |
+			    WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB,
+			    0);
+
 	wm8962_add_widgets(codec);
 
 	/* Save boards having to disable DMIC when not in use */
@@ -4150,13 +4102,6 @@
 	}
 
 	return 0;
-
-err_enable:
-	regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err_get:
-	regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err:
-	return ret;
 }
 
 static int wm8962_remove(struct snd_soc_codec *codec)
@@ -4174,7 +4119,6 @@
 	for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
 		regulator_unregister_notifier(wm8962->supplies[i].consumer,
 					      &wm8962->disable_nb[i]);
-	regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
 
 	return 0;
 }
@@ -4183,41 +4127,132 @@
 	.probe =	wm8962_probe,
 	.remove =	wm8962_remove,
 	.set_bias_level = wm8962_set_bias_level,
-	.reg_cache_size = WM8962_MAX_REGISTER + 1,
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8962_reg,
-	.volatile_register = wm8962_volatile_register,
-	.readable_register = wm8962_readable_register,
 	.set_pll = wm8962_set_fll,
 };
 
+static const struct regmap_config wm8962_regmap = {
+	.reg_bits = 16,
+	.val_bits = 16,
+
+	.max_register = WM8962_MAX_REGISTER,
+	.reg_defaults = wm8962_reg,
+	.num_reg_defaults = ARRAY_SIZE(wm8962_reg),
+	.volatile_reg = wm8962_volatile_register,
+	.readable_reg = wm8962_readable_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8962_priv *wm8962;
-	int ret;
+	unsigned int reg;
+	int ret, i;
 
-	wm8962 = kzalloc(sizeof(struct wm8962_priv), GFP_KERNEL);
+	wm8962 = devm_kzalloc(&i2c->dev, sizeof(struct wm8962_priv),
+			      GFP_KERNEL);
 	if (wm8962 == NULL)
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm8962);
 
+	INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
+	init_completion(&wm8962->fll_lock);
 	wm8962->irq = i2c->irq;
 
+	for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
+		wm8962->supplies[i].supply = wm8962_supply_names[i];
+
+	ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
+				 wm8962->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+		goto err;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+				    wm8962->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+		goto err_get;
+	}
+
+	wm8962->regmap = regmap_init_i2c(i2c, &wm8962_regmap);
+	if (IS_ERR(wm8962->regmap)) {
+		ret = PTR_ERR(wm8962->regmap);
+		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+		goto err_enable;
+	}
+
+	/*
+	 * We haven't marked the chip revision as volatile due to
+	 * sharing a register with the right input volume; explicitly
+	 * bypass the cache to read it.
+	 */
+	regcache_cache_bypass(wm8962->regmap, true);
+
+	ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read ID register\n");
+		goto err_regmap;
+	}
+	if (reg != 0x6243) {
+		dev_err(&i2c->dev,
+			"Device is not a WM8962, ID %x != 0x6243\n", ret);
+		ret = -EINVAL;
+		goto err_regmap;
+	}
+
+	ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read device revision: %d\n",
+			ret);
+		goto err_regmap;
+	}
+
+	dev_info(&i2c->dev, "customer id %x revision %c\n",
+		 (reg & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
+		 ((reg & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
+		 + 'A');
+
+	regcache_cache_bypass(wm8962->regmap, false);
+
+	ret = wm8962_reset(wm8962);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to issue reset\n");
+		goto err_regmap;
+	}
+
+	regcache_cache_only(wm8962->regmap, true);
+
 	ret = snd_soc_register_codec(&i2c->dev,
 				     &soc_codec_dev_wm8962, &wm8962_dai, 1);
 	if (ret < 0)
-		kfree(wm8962);
+		goto err_regmap;
 
+	/* The drivers should power up as needed */
+	regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+
+	return 0;
+
+err_regmap:
+	regmap_exit(wm8962->regmap);
+err_enable:
+	regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err_get:
+	regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err:
 	return ret;
 }
 
 static __devexit int wm8962_i2c_remove(struct i2c_client *client)
 {
+	struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev);
+
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm8962->regmap);
+	regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index b444b29..aadd14a 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -224,7 +223,7 @@
 	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8971_PWR2, 8, 0),
 	SND_SOC_DAPM_PGA("Mono Out 1", WM8971_PWR2, 2, 0, NULL, 0),
 
-	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8971_PWR1, 1, 0),
+	SND_SOC_DAPM_SUPPLY("Mic Bias", WM8971_PWR1, 1, 0, NULL, 0),
 	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8971_PWR1, 2, 0),
 	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8971_PWR1, 3, 0),
 
@@ -567,7 +566,7 @@
 #define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8971_dai_ops = {
+static const struct snd_soc_dai_ops wm8971_dai_ops = {
 	.hw_params	= wm8971_pcm_hw_params,
 	.digital_mute	= wm8971_mute,
 	.set_fmt	= wm8971_set_dai_fmt,
@@ -600,7 +599,7 @@
 	wm8971_set_bias_level(codec, codec->dapm.bias_level);
 }
 
-static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8971_suspend(struct snd_soc_codec *codec)
 {
 	wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 9352f1e..a5fd017 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -226,7 +225,7 @@
 SND_SOC_DAPM_MIXER("Boost Mixer", WM8974_POWER2, 4, 0,
 		   wm8974_boost_mixer, ARRAY_SIZE(wm8974_boost_mixer)),
 
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8974_POWER1, 4, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias", WM8974_POWER1, 4, 0, NULL, 0),
 
 SND_SOC_DAPM_INPUT("MICN"),
 SND_SOC_DAPM_INPUT("MICP"),
@@ -557,7 +556,7 @@
 #define WM8974_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8974_ops = {
+static const struct snd_soc_dai_ops wm8974_ops = {
 	.hw_params = wm8974_pcm_hw_params,
 	.digital_mute = wm8974_mute,
 	.set_fmt = wm8974_set_dai_fmt,
@@ -583,7 +582,7 @@
 	.symmetric_rates = 1,
 };
 
-static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8974_suspend(struct snd_soc_codec *codec)
 {
 	wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 41ca4d9..85d514d 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -865,7 +864,7 @@
 #define WM8978_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8978_dai_ops = {
+static const struct snd_soc_dai_ops wm8978_dai_ops = {
 	.hw_params	= wm8978_hw_params,
 	.digital_mute	= wm8978_mute,
 	.set_fmt	= wm8978_set_dai_fmt,
@@ -893,7 +892,7 @@
 	.ops = &wm8978_dai_ops,
 };
 
-static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8978_suspend(struct snd_soc_codec *codec)
 {
 	wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	/* Also switch PLL off */
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index 93ee284..cebde56 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -481,7 +481,8 @@
 	SND_SOC_DAPM_PGA("OUT4 Out", WM8983_POWER_MANAGEMENT_3,
 			 8, 0, NULL, 0),
 
-	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0),
+	SND_SOC_DAPM_SUPPLY("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0,
+			    NULL, 0),
 
 	SND_SOC_DAPM_INPUT("LIN"),
 	SND_SOC_DAPM_INPUT("LIP"),
@@ -973,7 +974,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm8983_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8983_suspend(struct snd_soc_codec *codec)
 {
 	wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -1034,7 +1035,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops wm8983_dai_ops = {
+static const struct snd_soc_dai_ops wm8983_dai_ops = {
 	.digital_mute = wm8983_dac_mute,
 	.hw_params = wm8983_hw_params,
 	.set_fmt = wm8983_set_fmt,
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index bae510a..c0c86b3 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -411,7 +411,8 @@
 	SND_SOC_DAPM_PGA("Right Speaker Out", WM8985_POWER_MANAGEMENT_3,
 		6, 0, NULL, 0),
 
-	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0),
+	SND_SOC_DAPM_SUPPLY("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0,
+			    NULL, 0),
 
 	SND_SOC_DAPM_INPUT("LIN"),
 	SND_SOC_DAPM_INPUT("LIP"),
@@ -944,7 +945,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm8985_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8985_suspend(struct snd_soc_codec *codec)
 {
 	wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -1030,7 +1031,7 @@
 	return ret;
 }
 
-static struct snd_soc_dai_ops wm8985_dai_ops = {
+static const struct snd_soc_dai_ops wm8985_dai_ops = {
 	.digital_mute = wm8985_dac_mute,
 	.hw_params = wm8985_hw_params,
 	.set_fmt = wm8985_set_fmt,
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 2e9eba7..0938847 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -18,7 +18,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -267,7 +266,7 @@
 	SOC_DAPM_ENUM("Route", monomux);
 
 static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
-	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8988_PWR1, 1, 0),
+	SND_SOC_DAPM_SUPPLY("Mic Bias", WM8988_PWR1, 1, 0, NULL, 0),
 
 	SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
 		&wm8988_diffmux_controls),
@@ -701,7 +700,7 @@
 #define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8988_ops = {
+static const struct snd_soc_dai_ops wm8988_ops = {
 	.startup = wm8988_pcm_startup,
 	.hw_params = wm8988_pcm_hw_params,
 	.set_fmt = wm8988_set_dai_fmt,
@@ -729,7 +728,7 @@
 	.symmetric_rates = 1,
 };
 
-static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8988_suspend(struct snd_soc_codec *codec)
 {
 	wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index d29a962..b417d2e 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -776,8 +775,8 @@
 	NULL, 0),
 
 /* MICBIAS */
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8990_POWER_MANAGEMENT_1,
-	WM8990_MICBIAS_ENA_BIT, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8990_POWER_MANAGEMENT_1,
+		    WM8990_MICBIAS_ENA_BIT, 0, NULL, 0),
 
 SND_SOC_DAPM_OUTPUT("LON"),
 SND_SOC_DAPM_OUTPUT("LOP"),
@@ -1287,7 +1286,7 @@
  * 1. ADC/DAC on Primary Interface
  * 2. ADC on Primary Interface/DAC on secondary
  */
-static struct snd_soc_dai_ops wm8990_dai_ops = {
+static const struct snd_soc_dai_ops wm8990_dai_ops = {
 	.hw_params	= wm8990_hw_params,
 	.digital_mute	= wm8990_mute,
 	.set_fmt	= wm8990_set_dai_fmt,
@@ -1314,7 +1313,7 @@
 	.ops = &wm8990_dai_ops,
 };
 
-static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8990_suspend(struct snd_soc_codec *codec)
 {
 	wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index c9ab3ba..7ee40da 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -770,8 +769,8 @@
 		NULL, 0),
 
 	/* MICBIAS */
-	SND_SOC_DAPM_MICBIAS("MICBIAS", WM8991_POWER_MANAGEMENT_1,
-		WM8991_MICBIAS_ENA_BIT, 0),
+	SND_SOC_DAPM_SUPPLY("MICBIAS", WM8991_POWER_MANAGEMENT_1,
+			    WM8991_MICBIAS_ENA_BIT, 0, NULL, 0),
 
 	SND_SOC_DAPM_OUTPUT("LON"),
 	SND_SOC_DAPM_OUTPUT("LOP"),
@@ -1241,7 +1240,7 @@
 	return 0;
 }
 
-static int wm8991_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8991_suspend(struct snd_soc_codec *codec)
 {
 	wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -1311,7 +1310,7 @@
 #define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8991_ops = {
+static const struct snd_soc_dai_ops wm8991_ops = {
 	.hw_params = wm8991_hw_params,
 	.digital_mute = wm8991_mute,
 	.set_fmt = wm8991_set_dai_fmt,
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index d1a142f4..0f8278b 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1394,7 +1394,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops wm8993_ops = {
+static const struct snd_soc_dai_ops wm8993_ops = {
 	.set_sysclk = wm8993_set_sysclk,
 	.set_fmt = wm8993_set_dai_fmt,
 	.hw_params = wm8993_hw_params,
@@ -1544,7 +1544,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8993_suspend(struct snd_soc_codec *codec)
 {
 	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
 	int fll_fout = wm8993->fll_fout;
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index d0c545b..02ca257 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -38,6 +38,11 @@
 #include "wm8994.h"
 #include "wm_hubs.h"
 
+#define WM1811_JACKDET_MODE_NONE  0x0000
+#define WM1811_JACKDET_MODE_JACK  0x0100
+#define WM1811_JACKDET_MODE_MIC   0x0080
+#define WM1811_JACKDET_MODE_AUDIO 0x0180
+
 #define WM8994_NUM_DRC 3
 #define WM8994_NUM_EQ  3
 
@@ -53,10 +58,75 @@
 	WM8994_AIF2_EQ_GAINS_1,
 };
 
+static void wm8958_default_micdet(u16 status, void *data);
+
+static const struct wm8958_micd_rate micdet_rates[] = {
+	{ 32768,       true,  1, 4 },
+	{ 32768,       false, 1, 1 },
+	{ 44100 * 256, true,  7, 10 },
+	{ 44100 * 256, false, 7, 10 },
+};
+
+static const struct wm8958_micd_rate jackdet_rates[] = {
+	{ 32768,       true,  0, 1 },
+	{ 32768,       false, 0, 1 },
+	{ 44100 * 256, true,  7, 10 },
+	{ 44100 * 256, false, 7, 10 },
+};
+
+static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
+{
+	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+	int best, i, sysclk, val;
+	bool idle;
+	const struct wm8958_micd_rate *rates;
+	int num_rates;
+
+	if (wm8994->jack_cb != wm8958_default_micdet)
+		return;
+
+	idle = !wm8994->jack_mic;
+
+	sysclk = snd_soc_read(codec, WM8994_CLOCKING_1);
+	if (sysclk & WM8994_SYSCLK_SRC)
+		sysclk = wm8994->aifclk[1];
+	else
+		sysclk = wm8994->aifclk[0];
+
+	if (wm8994->pdata && wm8994->pdata->micd_rates) {
+		rates = wm8994->pdata->micd_rates;
+		num_rates = wm8994->pdata->num_micd_rates;
+	} else if (wm8994->jackdet) {
+		rates = jackdet_rates;
+		num_rates = ARRAY_SIZE(jackdet_rates);
+	} else {
+		rates = micdet_rates;
+		num_rates = ARRAY_SIZE(micdet_rates);
+	}
+
+	best = 0;
+	for (i = 0; i < num_rates; i++) {
+		if (rates[i].idle != idle)
+			continue;
+		if (abs(rates[i].sysclk - sysclk) <
+		    abs(rates[best].sysclk - sysclk))
+			best = i;
+		else if (rates[best].idle != idle)
+			best = i;
+	}
+
+	val = rates[best].start << WM8958_MICD_BIAS_STARTTIME_SHIFT
+		| rates[best].rate << WM8958_MICD_RATE_SHIFT;
+
+	snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+			    WM8958_MICD_BIAS_STARTTIME_MASK |
+			    WM8958_MICD_RATE_MASK, val);
+}
+
 static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	struct wm8994 *control = codec->control_data;
+	struct wm8994 *control = wm8994->wm8994;
 
 	switch (reg) {
 	case WM8994_GPIO_1:
@@ -221,8 +291,10 @@
 	 */
 
 	/* If they're equal it doesn't matter which is used */
-	if (wm8994->aifclk[0] == wm8994->aifclk[1])
+	if (wm8994->aifclk[0] == wm8994->aifclk[1]) {
+		wm8958_micd_set_rate(codec);
 		return 0;
+	}
 
 	if (wm8994->aifclk[0] < wm8994->aifclk[1])
 		new = WM8994_SYSCLK_SRC;
@@ -231,10 +303,10 @@
 
 	change = snd_soc_update_bits(codec, WM8994_CLOCKING_1,
 				     WM8994_SYSCLK_SRC, new);
-	if (!change)
-		return 0;
+	if (change)
+		snd_soc_dapm_sync(&codec->dapm);
 
-	snd_soc_dapm_sync(&codec->dapm);
+	wm8958_micd_set_rate(codec);
 
 	return 0;
 }
@@ -708,6 +780,74 @@
 	       mixin_boost_tlv),
 };
 
+/* We run all mode setting through a function to enforce audio mode */
+static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
+{
+	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+	if (wm8994->active_refcount)
+		mode = WM1811_JACKDET_MODE_AUDIO;
+
+	snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+			    WM1811_JACKDET_MODE_MASK, mode);
+
+	if (mode == WM1811_JACKDET_MODE_MIC)
+		msleep(2);
+}
+
+static void active_reference(struct snd_soc_codec *codec)
+{
+	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+	mutex_lock(&wm8994->accdet_lock);
+
+	wm8994->active_refcount++;
+
+	dev_dbg(codec->dev, "Active refcount incremented, now %d\n",
+		wm8994->active_refcount);
+
+	if (wm8994->active_refcount == 1) {
+		/* If we're using jack detection go into audio mode */
+		if (wm8994->jackdet && wm8994->jack_cb) {
+			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+					    WM1811_JACKDET_MODE_MASK,
+					    WM1811_JACKDET_MODE_AUDIO);
+			msleep(2);
+		}
+	}
+
+	mutex_unlock(&wm8994->accdet_lock);
+}
+
+static void active_dereference(struct snd_soc_codec *codec)
+{
+	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+	u16 mode;
+
+	mutex_lock(&wm8994->accdet_lock);
+
+	wm8994->active_refcount--;
+
+	dev_dbg(codec->dev, "Active refcount decremented, now %d\n",
+		wm8994->active_refcount);
+
+	if (wm8994->active_refcount == 0) {
+		/* Go into appropriate detection only mode */
+		if (wm8994->jackdet && wm8994->jack_cb) {
+			if (wm8994->jack_mic || wm8994->mic_detecting)
+				mode = WM1811_JACKDET_MODE_MIC;
+			else
+				mode = WM1811_JACKDET_MODE_JACK;
+
+			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+					    WM1811_JACKDET_MODE_MASK,
+					    mode);
+		}
+	}
+
+	mutex_unlock(&wm8994->accdet_lock);
+}
+
 static int clk_sys_event(struct snd_soc_dapm_widget *w,
 			 struct snd_kcontrol *kcontrol, int event)
 {
@@ -1768,7 +1908,7 @@
 			  unsigned int freq_in, unsigned int freq_out)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	struct wm8994 *control = codec->control_data;
+	struct wm8994 *control = wm8994->wm8994;
 	int reg_offset, ret;
 	struct fll_div fll;
 	u16 reg, aif1, aif2;
@@ -1865,6 +2005,8 @@
 	if (freq_out) {
 		/* Enable VMID if we need it */
 		if (!was_enabled) {
+			active_reference(codec);
+
 			switch (control->type) {
 			case WM8994:
 				vmid_reference(codec);
@@ -1908,6 +2050,8 @@
 			default:
 				break;
 			}
+
+			active_dereference(codec);
 		}
 	}
 
@@ -2017,14 +2161,29 @@
 static int wm8994_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
-	struct wm8994 *control = codec->control_data;
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+	struct wm8994 *control = wm8994->wm8994;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		break;
 
 	case SND_SOC_BIAS_PREPARE:
+		/* MICBIAS into regulating mode */
+		switch (control->type) {
+		case WM8958:
+		case WM1811:
+			snd_soc_update_bits(codec, WM8958_MICBIAS1,
+					    WM8958_MICB1_MODE, 0);
+			snd_soc_update_bits(codec, WM8958_MICBIAS2,
+					    WM8958_MICB2_MODE, 0);
+			break;
+		default:
+			break;
+		}
+
+		if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+			active_reference(codec);
 		break;
 
 	case SND_SOC_BIAS_STANDBY:
@@ -2077,7 +2236,23 @@
 					    WM8994_LINEOUT2_DISCH);
 		}
 
+		if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE)
+			active_dereference(codec);
 
+		/* MICBIAS into bypass mode on newer devices */
+		switch (control->type) {
+		case WM8958:
+		case WM1811:
+			snd_soc_update_bits(codec, WM8958_MICBIAS1,
+					    WM8958_MICB1_MODE,
+					    WM8958_MICB1_MODE);
+			snd_soc_update_bits(codec, WM8958_MICBIAS2,
+					    WM8958_MICB2_MODE,
+					    WM8958_MICB2_MODE);
+			break;
+		default:
+			break;
+		}
 		break;
 
 	case SND_SOC_BIAS_OFF:
@@ -2089,13 +2264,15 @@
 		break;
 	}
 	codec->dapm.bias_level = level;
+
 	return 0;
 }
 
 static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	struct wm8994 *control = codec->control_data;
+	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+	struct wm8994 *control = wm8994->wm8994;
 	int ms_reg;
 	int aif1_reg;
 	int ms = 0;
@@ -2395,7 +2572,8 @@
 				 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);
+	struct wm8994 *control = wm8994->wm8994;
 	int aif1_reg;
 	int aif1 = 0;
 
@@ -2536,7 +2714,7 @@
 #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
 	.set_sysclk	= wm8994_set_dai_sysclk,
 	.set_fmt	= wm8994_set_dai_fmt,
 	.hw_params	= wm8994_hw_params,
@@ -2546,7 +2724,7 @@
 	.set_tristate	= wm8994_set_tristate,
 };
 
-static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
 	.set_sysclk	= wm8994_set_dai_sysclk,
 	.set_fmt	= wm8994_set_dai_fmt,
 	.hw_params	= wm8994_hw_params,
@@ -2556,7 +2734,7 @@
 	.set_tristate	= wm8994_set_tristate,
 };
 
-static struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
 	.hw_params	= wm8994_aif3_hw_params,
 	.set_tristate	= wm8994_set_tristate,
 };
@@ -2623,10 +2801,10 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8994_suspend(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	struct wm8994 *control = codec->control_data;
+	struct wm8994 *control = wm8994->wm8994;
 	int i, ret;
 
 	switch (control->type) {
@@ -2634,6 +2812,9 @@
 		snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
 		break;
 	case WM1811:
+		snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+				    WM1811_JACKDET_MODE_MASK, 0);
+		/* Fall through */
 	case WM8958:
 		snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
 				    WM8958_MICD_ENA, 0);
@@ -2657,7 +2838,7 @@
 static int wm8994_resume(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	struct wm8994 *control = codec->control_data;
+	struct wm8994 *control = wm8994->wm8994;
 	int i, ret;
 	unsigned int val, mask;
 
@@ -2703,6 +2884,13 @@
 					    WM8994_MICD_ENA, WM8994_MICD_ENA);
 		break;
 	case WM1811:
+		if (wm8994->jackdet && wm8994->jack_cb) {
+			/* Restart from idle */
+			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+					    WM1811_JACKDET_MODE_MASK,
+					    WM1811_JACKDET_MODE_JACK);
+			break;
+		}
 	case WM8958:
 		if (wm8994->jack_cb)
 			snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
@@ -2815,8 +3003,8 @@
 		};
 
 		/* We need an array of texts for the enum API */
-		wm8994->drc_texts = kmalloc(sizeof(char *)
-					    * pdata->num_drc_cfgs, GFP_KERNEL);
+		wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev,
+			    sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL);
 		if (!wm8994->drc_texts) {
 			dev_err(wm8994->codec->dev,
 				"Failed to allocate %d DRC config texts\n",
@@ -2879,7 +3067,7 @@
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994_micdet *micdet;
-	struct wm8994 *control = codec->control_data;
+	struct wm8994 *control = wm8994->wm8994;
 	int reg;
 
 	if (control->type != WM8994)
@@ -2962,21 +3150,136 @@
 {
 	struct snd_soc_codec *codec = data;
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	int report = 0;
+	int report;
 
-	/* If nothing present then clear our statuses */
-	if (!(status & WM8958_MICD_STS))
-		goto done;
+	dev_dbg(codec->dev, "MICDET %x\n", status);
 
-	report = SND_JACK_MICROPHONE;
+	/* Either nothing present or just starting detection */
+	if (!(status & WM8958_MICD_STS)) {
+		if (!wm8994->jackdet) {
+			/* If nothing present then clear our statuses */
+			dev_dbg(codec->dev, "Detected open circuit\n");
+			wm8994->jack_mic = false;
+			wm8994->mic_detecting = true;
 
-	/* Everything else is buttons; just assign slots */
-	if (status & 0x1c)
-		report |= SND_JACK_BTN_0;
+			wm8958_micd_set_rate(codec);
 
-done:
-	snd_soc_jack_report(wm8994->micdet[0].jack, report,
-			    SND_JACK_BTN_0 | SND_JACK_MICROPHONE);
+			snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+					    wm8994->btn_mask |
+					     SND_JACK_HEADSET);
+		}
+		return;
+	}
+
+	/* If the measurement is showing a high impedence we've got a
+	 * microphone.
+	 */
+	if (wm8994->mic_detecting && (status & 0x600)) {
+		dev_dbg(codec->dev, "Detected microphone\n");
+
+		wm8994->mic_detecting = false;
+		wm8994->jack_mic = true;
+
+		wm8958_micd_set_rate(codec);
+
+		snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADSET,
+				    SND_JACK_HEADSET);
+	}
+
+
+	if (wm8994->mic_detecting && status & 0x4) {
+		dev_dbg(codec->dev, "Detected headphone\n");
+		wm8994->mic_detecting = false;
+
+		wm8958_micd_set_rate(codec);
+
+		snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
+				    SND_JACK_HEADSET);
+
+		/* If we have jackdet that will detect removal */
+		if (wm8994->jackdet) {
+			snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+					    WM8958_MICD_ENA, 0);
+
+			wm1811_jackdet_set_mode(codec,
+						WM1811_JACKDET_MODE_JACK);
+		}
+	}
+
+	/* Report short circuit as a button */
+	if (wm8994->jack_mic) {
+		report = 0;
+		if (status & 0x4)
+			report |= SND_JACK_BTN_0;
+
+		if (status & 0x8)
+			report |= SND_JACK_BTN_1;
+
+		if (status & 0x10)
+			report |= SND_JACK_BTN_2;
+
+		if (status & 0x20)
+			report |= SND_JACK_BTN_3;
+
+		if (status & 0x40)
+			report |= SND_JACK_BTN_4;
+
+		if (status & 0x80)
+			report |= SND_JACK_BTN_5;
+
+		snd_soc_jack_report(wm8994->micdet[0].jack, report,
+				    wm8994->btn_mask);
+	}
+}
+
+static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
+{
+	struct wm8994_priv *wm8994 = data;
+	struct snd_soc_codec *codec = wm8994->codec;
+	int reg;
+
+	mutex_lock(&wm8994->accdet_lock);
+
+	reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
+	if (reg < 0) {
+		dev_err(codec->dev, "Failed to read jack status: %d\n", reg);
+		mutex_unlock(&wm8994->accdet_lock);
+		return IRQ_NONE;
+	}
+
+	dev_dbg(codec->dev, "JACKDET %x\n", reg);
+
+	if (reg & WM1811_JACKDET_LVL) {
+		dev_dbg(codec->dev, "Jack detected\n");
+
+		snd_soc_jack_report(wm8994->micdet[0].jack,
+				    SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
+
+		/*
+		 * Start off measument of microphone impedence to find
+		 * out what's actually there.
+		 */
+		wm8994->mic_detecting = true;
+		wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
+		snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+				    WM8958_MICD_ENA, WM8958_MICD_ENA);
+	} else {
+		dev_dbg(codec->dev, "Jack not detected\n");
+
+		snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+				    SND_JACK_MECHANICAL | SND_JACK_HEADSET |
+				    wm8994->btn_mask);
+
+		wm8994->mic_detecting = false;
+		wm8994->jack_mic = false;
+		snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+				    WM8958_MICD_ENA, 0);
+		wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK);
+	}
+
+	mutex_unlock(&wm8994->accdet_lock);
+
+	return IRQ_HANDLED;
 }
 
 /**
@@ -2999,7 +3302,8 @@
 		      wm8958_micdet_cb cb, void *cb_data)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	struct wm8994 *control = codec->control_data;
+	struct wm8994 *control = wm8994->wm8994;
+	u16 micd_lvl_sel;
 
 	switch (control->type) {
 	case WM1811:
@@ -3016,15 +3320,50 @@
 			cb_data = codec;
 		}
 
+		snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
+
 		wm8994->micdet[0].jack = jack;
 		wm8994->jack_cb = cb;
 		wm8994->jack_cb_data = cb_data;
 
-		snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
-				    WM8958_MICD_ENA, WM8958_MICD_ENA);
+		wm8994->mic_detecting = true;
+		wm8994->jack_mic = false;
+
+		wm8958_micd_set_rate(codec);
+
+		/* Detect microphones and short circuits by default */
+		if (wm8994->pdata->micd_lvl_sel)
+			micd_lvl_sel = wm8994->pdata->micd_lvl_sel;
+		else
+			micd_lvl_sel = 0x41;
+
+		wm8994->btn_mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+			SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+			SND_JACK_BTN_4 | SND_JACK_BTN_5;
+
+		snd_soc_update_bits(codec, WM8958_MIC_DETECT_2,
+				    WM8958_MICD_LVL_SEL_MASK, micd_lvl_sel);
+
+		WARN_ON(codec->dapm.bias_level > SND_SOC_BIAS_STANDBY);
+
+		/*
+		 * If we can use jack detection start off with that,
+		 * otherwise jump straight to microphone detection.
+		 */
+		if (wm8994->jackdet) {
+			snd_soc_update_bits(codec, WM8994_LDO_1,
+					    WM8994_LDO1_DISCH, 0);
+			wm1811_jackdet_set_mode(codec,
+						WM1811_JACKDET_MODE_JACK);
+		} else {
+			snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+					    WM8958_MICD_ENA, WM8958_MICD_ENA);
+		}
+
 	} else {
 		snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
 				    WM8958_MICD_ENA, 0);
+		snd_soc_dapm_disable_pin(&codec->dapm, "CLK_SYS");
 	}
 
 	return 0;
@@ -3037,6 +3376,18 @@
 	struct snd_soc_codec *codec = wm8994->codec;
 	int reg, count;
 
+	mutex_lock(&wm8994->accdet_lock);
+
+	/*
+	 * Jack detection may have detected a removal simulataneously
+	 * with an update of the MICDET status; if so it will have
+	 * stopped detection and we can ignore this interrupt.
+	 */
+	if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) {
+		mutex_unlock(&wm8994->accdet_lock);
+		return IRQ_HANDLED;
+	}
+
 	/* We may occasionally read a detection without an impedence
 	 * range being provided - if that happens loop again.
 	 */
@@ -3044,6 +3395,7 @@
 	do {
 		reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
 		if (reg < 0) {
+			mutex_unlock(&wm8994->accdet_lock);
 			dev_err(codec->dev,
 				"Failed to read mic detect status: %d\n",
 				reg);
@@ -3074,6 +3426,8 @@
 		dev_warn(codec->dev, "Accessory detection with no callback\n");
 
 out:
+	mutex_unlock(&wm8994->accdet_lock);
+
 	return IRQ_HANDLED;
 }
 
@@ -3114,14 +3468,19 @@
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
 	control = codec->control_data;
 
-	wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
+	wm8994 = devm_kzalloc(codec->dev, sizeof(struct wm8994_priv),
+			      GFP_KERNEL);
 	if (wm8994 == NULL)
 		return -ENOMEM;
 	snd_soc_codec_set_drvdata(codec, wm8994);
 
+
+	wm8994->wm8994 = dev_get_drvdata(codec->dev->parent);
 	wm8994->pdata = dev_get_platdata(codec->dev->parent);
 	wm8994->codec = codec;
 
+	mutex_init(&wm8994->accdet_lock);
+
 	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
 		init_completion(&wm8994->fll_locked[i]);
 
@@ -3200,14 +3559,14 @@
 		break;
 	}
 
-	wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
+	wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR,
 			   wm8994_fifo_error, "FIFO error", codec);
-	wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_WARN,
+	wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN,
 			   wm8994_temp_warn, "Thermal warning", codec);
-	wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT,
+	wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT,
 			   wm8994_temp_shut, "Thermal shutdown", codec);
 
-	ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+	ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
 				 wm_hubs_dcs_done, "DC servo done",
 				 &wm8994->hubs);
 	if (ret == 0)
@@ -3227,7 +3586,7 @@
 					 ret);
 		}
 
-		ret = wm8994_request_irq(codec->control_data,
+		ret = wm8994_request_irq(wm8994->wm8994,
 					 WM8994_IRQ_MIC1_SHRT,
 					 wm8994_mic_irq, "Mic 1 short",
 					 wm8994);
@@ -3236,7 +3595,7 @@
 				 "Failed to request Mic1 short IRQ: %d\n",
 				 ret);
 
-		ret = wm8994_request_irq(codec->control_data,
+		ret = wm8994_request_irq(wm8994->wm8994,
 					 WM8994_IRQ_MIC2_DET,
 					 wm8994_mic_irq, "Mic 2 detect",
 					 wm8994);
@@ -3245,7 +3604,7 @@
 				 "Failed to request Mic2 detect IRQ: %d\n",
 				 ret);
 
-		ret = wm8994_request_irq(codec->control_data,
+		ret = wm8994_request_irq(wm8994->wm8994,
 					 WM8994_IRQ_MIC2_SHRT,
 					 wm8994_mic_irq, "Mic 2 short",
 					 wm8994);
@@ -3270,9 +3629,24 @@
 		}
 	}
 
+	switch (control->type) {
+	case WM1811:
+		if (wm8994->revision > 1) {
+			ret = wm8994_request_irq(wm8994->wm8994,
+						 WM8994_IRQ_GPIO(6),
+						 wm1811_jackdet_irq, "JACKDET",
+						 wm8994);
+			if (ret == 0)
+				wm8994->jackdet = true;
+		}
+		break;
+	default:
+		break;
+	}
+
 	wm8994->fll_locked_irq = true;
 	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) {
-		ret = wm8994_request_irq(codec->control_data,
+		ret = wm8994_request_irq(wm8994->wm8994,
 					 WM8994_IRQ_FLL1_LOCK + i,
 					 wm8994_fll_locked_irq, "FLL lock",
 					 &wm8994->fll_locked[i]);
@@ -3368,6 +3742,19 @@
 		break;
 	}
 
+	/* Put MICBIAS into bypass mode by default on newer devices */
+	switch (control->type) {
+	case WM8958:
+	case WM1811:
+		snd_soc_update_bits(codec, WM8958_MICBIAS1,
+				    WM8958_MICB1_MODE, WM8958_MICB1_MODE);
+		snd_soc_update_bits(codec, WM8958_MICBIAS2,
+				    WM8958_MICB2_MODE, WM8958_MICB2_MODE);
+		break;
+	default:
+		break;
+	}
+
 	wm8994_update_class_w(codec);
 
 	wm8994_handle_pdata(wm8994);
@@ -3479,28 +3866,29 @@
 	return 0;
 
 err_irq:
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
+	if (wm8994->jackdet)
+		wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_SHRT, wm8994);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET, wm8994);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, wm8994);
 	if (wm8994->micdet_irq)
 		free_irq(wm8994->micdet_irq, wm8994);
 	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
-		wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+		wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i,
 				&wm8994->fll_locked[i]);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
 			&wm8994->hubs);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, codec);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec);
 err:
-	kfree(wm8994);
 	return ret;
 }
 
 static int  wm8994_codec_remove(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-	struct wm8994 *control = codec->control_data;
+	struct wm8994 *control = wm8994->wm8994;
 	int i;
 
 	wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -3508,24 +3896,27 @@
 	pm_runtime_disable(codec->dev);
 
 	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
-		wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+		wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i,
 				&wm8994->fll_locked[i]);
 
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
 			&wm8994->hubs);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, codec);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec);
+	wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec);
+
+	if (wm8994->jackdet)
+		wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994);
 
 	switch (control->type) {
 	case WM8994:
 		if (wm8994->micdet_irq)
 			free_irq(wm8994->micdet_irq, wm8994);
-		wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
+		wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET,
 				wm8994);
-		wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
+		wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT,
 				wm8994);
-		wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
+		wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_DET,
 				wm8994);
 		break;
 
@@ -3542,8 +3933,6 @@
 	if (wm8994->enh_eq)
 		release_firmware(wm8994->enh_eq);
 	kfree(wm8994->retune_mobile_texts);
-	kfree(wm8994->drc_texts);
-	kfree(wm8994);
 
 	return 0;
 }
@@ -3586,18 +3975,7 @@
 	.remove = __devexit_p(wm8994_remove),
 };
 
-static __init int wm8994_init(void)
-{
-	return platform_driver_register(&wm8994_codec_driver);
-}
-module_init(wm8994_init);
-
-static __exit void wm8994_exit(void)
-{
-	platform_driver_unregister(&wm8994_codec_driver);
-}
-module_exit(wm8994_exit);
-
+module_platform_driver(wm8994_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM8994 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index f4f1355..6ef3f11 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -70,10 +70,11 @@
 #define WM8994_NUM_DRC 3
 #define WM8994_NUM_EQ  3
 
+struct wm8994;
+
 struct wm8994_priv {
 	struct wm_hubs_data hubs;
-	enum snd_soc_control_type control_type;
-	void *control_data;
+	struct wm8994 *wm8994;
 	struct snd_soc_codec *codec;
 	int sysclk[2];
 	int sysclk_rate[2];
@@ -84,6 +85,7 @@
 	bool fll_locked_irq;
 
 	int vmid_refcount;
+	int active_refcount;
 
 	int dac_rates[2];
 	int lrclk_shared[2];
@@ -125,7 +127,12 @@
 	const char **enh_eq_texts;
 	struct soc_enum enh_eq_enum;
 
+	struct mutex accdet_lock;
 	struct wm8994_micdet micdet[2];
+	bool mic_detecting;
+	bool jack_mic;
+	int btn_mask;
+	bool jackdet;
 
 	wm8958_micdet_cb jack_cb;
 	void *jack_cb_data;
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 78eeb21..5863406 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -43,88 +44,331 @@
 	"MICVDD"
 };
 
-static const u16 wm8995_reg_defs[WM8995_MAX_REGISTER + 1] = {
-	[0]     = 0x8995, [5]     = 0x0100, [16]    = 0x000b, [17]    = 0x000b,
-	[24]    = 0x02c0, [25]    = 0x02c0, [26]    = 0x02c0, [27]    = 0x02c0,
-	[28]    = 0x000f, [32]    = 0x0005, [33]    = 0x0005, [40]    = 0x0003,
-	[41]    = 0x0013, [48]    = 0x0004, [56]    = 0x09f8, [64]    = 0x1f25,
-	[69]    = 0x0004, [82]    = 0xaaaa, [84]    = 0x2a2a, [146]   = 0x0060,
-	[256]   = 0x0002, [257]   = 0x8004, [520]   = 0x0010, [528]   = 0x0083,
-	[529]   = 0x0083, [548]   = 0x0c80, [580]   = 0x0c80, [768]   = 0x4050,
-	[769]   = 0x4000, [771]   = 0x0040, [772]   = 0x0040, [773]   = 0x0040,
-	[774]   = 0x0004, [775]   = 0x0100, [784]   = 0x4050, [785]   = 0x4000,
-	[787]   = 0x0040, [788]   = 0x0040, [789]   = 0x0040, [1024]  = 0x00c0,
-	[1025]  = 0x00c0, [1026]  = 0x00c0, [1027]  = 0x00c0, [1028]  = 0x00c0,
-	[1029]  = 0x00c0, [1030]  = 0x00c0, [1031]  = 0x00c0, [1056]  = 0x0200,
-	[1057]  = 0x0010, [1058]  = 0x0200, [1059]  = 0x0010, [1088]  = 0x0098,
-	[1089]  = 0x0845, [1104]  = 0x0098, [1105]  = 0x0845, [1152]  = 0x6318,
-	[1153]  = 0x6300, [1154]  = 0x0fca, [1155]  = 0x0400, [1156]  = 0x00d8,
-	[1157]  = 0x1eb5, [1158]  = 0xf145, [1159]  = 0x0b75, [1160]  = 0x01c5,
-	[1161]  = 0x1c58, [1162]  = 0xf373, [1163]  = 0x0a54, [1164]  = 0x0558,
-	[1165]  = 0x168e, [1166]  = 0xf829, [1167]  = 0x07ad, [1168]  = 0x1103,
-	[1169]  = 0x0564, [1170]  = 0x0559, [1171]  = 0x4000, [1184]  = 0x6318,
-	[1185]  = 0x6300, [1186]  = 0x0fca, [1187]  = 0x0400, [1188]  = 0x00d8,
-	[1189]  = 0x1eb5, [1190]  = 0xf145, [1191]  = 0x0b75, [1192]  = 0x01c5,
-	[1193]  = 0x1c58, [1194]  = 0xf373, [1195]  = 0x0a54, [1196]  = 0x0558,
-	[1197]  = 0x168e, [1198]  = 0xf829, [1199]  = 0x07ad, [1200]  = 0x1103,
-	[1201]  = 0x0564, [1202]  = 0x0559, [1203]  = 0x4000, [1280]  = 0x00c0,
-	[1281]  = 0x00c0, [1282]  = 0x00c0, [1283]  = 0x00c0, [1312]  = 0x0200,
-	[1313]  = 0x0010, [1344]  = 0x0098, [1345]  = 0x0845, [1408]  = 0x6318,
-	[1409]  = 0x6300, [1410]  = 0x0fca, [1411]  = 0x0400, [1412]  = 0x00d8,
-	[1413]  = 0x1eb5, [1414]  = 0xf145, [1415]  = 0x0b75, [1416]  = 0x01c5,
-	[1417]  = 0x1c58, [1418]  = 0xf373, [1419]  = 0x0a54, [1420]  = 0x0558,
-	[1421]  = 0x168e, [1422]  = 0xf829, [1423]  = 0x07ad, [1424]  = 0x1103,
-	[1425]  = 0x0564, [1426]  = 0x0559, [1427]  = 0x4000, [1568]  = 0x0002,
-	[1792]  = 0xa100, [1793]  = 0xa101, [1794]  = 0xa101, [1795]  = 0xa101,
-	[1796]  = 0xa101, [1797]  = 0xa101, [1798]  = 0xa101, [1799]  = 0xa101,
-	[1800]  = 0xa101, [1801]  = 0xa101, [1802]  = 0xa101, [1803]  = 0xa101,
-	[1804]  = 0xa101, [1805]  = 0xa101, [1825]  = 0x0055, [1848]  = 0x3fff,
-	[1849]  = 0x1fff, [2049]  = 0x0001, [2050]  = 0x0069, [2056]  = 0x0002,
-	[2057]  = 0x0003, [2058]  = 0x0069, [12288] = 0x0001, [12289] = 0x0001,
-	[12291] = 0x0006, [12292] = 0x0040, [12293] = 0x0001, [12294] = 0x000f,
-	[12295] = 0x0006, [12296] = 0x0001, [12297] = 0x0003, [12298] = 0x0104,
-	[12300] = 0x0060, [12301] = 0x0011, [12302] = 0x0401, [12304] = 0x0050,
-	[12305] = 0x0003, [12306] = 0x0100, [12308] = 0x0051, [12309] = 0x0003,
-	[12310] = 0x0104, [12311] = 0x000a, [12312] = 0x0060, [12313] = 0x003b,
-	[12314] = 0x0502, [12315] = 0x0100, [12316] = 0x2fff, [12320] = 0x2fff,
-	[12324] = 0x2fff, [12328] = 0x2fff, [12332] = 0x2fff, [12336] = 0x2fff,
-	[12340] = 0x2fff, [12344] = 0x2fff, [12348] = 0x2fff, [12352] = 0x0001,
-	[12353] = 0x0001, [12355] = 0x0006, [12356] = 0x0040, [12357] = 0x0001,
-	[12358] = 0x000f, [12359] = 0x0006, [12360] = 0x0001, [12361] = 0x0003,
-	[12362] = 0x0104, [12364] = 0x0060, [12365] = 0x0011, [12366] = 0x0401,
-	[12368] = 0x0050, [12369] = 0x0003, [12370] = 0x0100, [12372] = 0x0060,
-	[12373] = 0x003b, [12374] = 0x0502, [12375] = 0x0100, [12376] = 0x2fff,
-	[12380] = 0x2fff, [12384] = 0x2fff, [12388] = 0x2fff, [12392] = 0x2fff,
-	[12396] = 0x2fff, [12400] = 0x2fff, [12404] = 0x2fff, [12408] = 0x2fff,
-	[12412] = 0x2fff, [12416] = 0x0001, [12417] = 0x0001, [12419] = 0x0006,
-	[12420] = 0x0040, [12421] = 0x0001, [12422] = 0x000f, [12423] = 0x0006,
-	[12424] = 0x0001, [12425] = 0x0003, [12426] = 0x0106, [12428] = 0x0061,
-	[12429] = 0x0011, [12430] = 0x0401, [12432] = 0x0050, [12433] = 0x0003,
-	[12434] = 0x0102, [12436] = 0x0051, [12437] = 0x0003, [12438] = 0x0106,
-	[12439] = 0x000a, [12440] = 0x0061, [12441] = 0x003b, [12442] = 0x0502,
-	[12443] = 0x0100, [12444] = 0x2fff, [12448] = 0x2fff, [12452] = 0x2fff,
-	[12456] = 0x2fff, [12460] = 0x2fff, [12464] = 0x2fff, [12468] = 0x2fff,
-	[12472] = 0x2fff, [12476] = 0x2fff, [12480] = 0x0001, [12481] = 0x0001,
-	[12483] = 0x0006, [12484] = 0x0040, [12485] = 0x0001, [12486] = 0x000f,
-	[12487] = 0x0006, [12488] = 0x0001, [12489] = 0x0003, [12490] = 0x0106,
-	[12492] = 0x0061, [12493] = 0x0011, [12494] = 0x0401, [12496] = 0x0050,
-	[12497] = 0x0003, [12498] = 0x0102, [12500] = 0x0061, [12501] = 0x003b,
-	[12502] = 0x0502, [12503] = 0x0100, [12504] = 0x2fff, [12508] = 0x2fff,
-	[12512] = 0x2fff, [12516] = 0x2fff, [12520] = 0x2fff, [12524] = 0x2fff,
-	[12528] = 0x2fff, [12532] = 0x2fff, [12536] = 0x2fff, [12540] = 0x2fff,
-	[12544] = 0x0060, [12546] = 0x0601, [12548] = 0x0050, [12550] = 0x0100,
-	[12552] = 0x0001, [12554] = 0x0104, [12555] = 0x0100, [12556] = 0x2fff,
-	[12560] = 0x2fff, [12564] = 0x2fff, [12568] = 0x2fff, [12572] = 0x2fff,
-	[12576] = 0x2fff, [12580] = 0x2fff, [12584] = 0x2fff, [12588] = 0x2fff,
-	[12592] = 0x2fff, [12596] = 0x2fff, [12600] = 0x2fff, [12604] = 0x2fff,
-	[12608] = 0x0061, [12610] = 0x0601, [12612] = 0x0050, [12614] = 0x0102,
-	[12616] = 0x0001, [12618] = 0x0106, [12619] = 0x0100, [12620] = 0x2fff,
-	[12624] = 0x2fff, [12628] = 0x2fff, [12632] = 0x2fff, [12636] = 0x2fff,
-	[12640] = 0x2fff, [12644] = 0x2fff, [12648] = 0x2fff, [12652] = 0x2fff,
-	[12656] = 0x2fff, [12660] = 0x2fff, [12664] = 0x2fff, [12668] = 0x2fff,
-	[12672] = 0x0060, [12674] = 0x0601, [12676] = 0x0061, [12678] = 0x0601,
-	[12680] = 0x0050, [12682] = 0x0300, [12684] = 0x0001, [12686] = 0x0304,
-	[12688] = 0x0040, [12690] = 0x000f, [12692] = 0x0001, [12695] = 0x0100
+static struct reg_default wm8995_reg_defaults[] = {
+	{ 0, 0x8995 },
+	{ 5, 0x0100 },
+	{ 16, 0x000b },
+	{ 17, 0x000b },
+	{ 24, 0x02c0 },
+	{ 25, 0x02c0 },
+	{ 26, 0x02c0 },
+	{ 27, 0x02c0 },
+	{ 28, 0x000f },
+	{ 32, 0x0005 },
+	{ 33, 0x0005 },
+	{ 40, 0x0003 },
+	{ 41, 0x0013 },
+	{ 48, 0x0004 },
+	{ 56, 0x09f8 },
+	{ 64, 0x1f25 },
+	{ 69, 0x0004 },
+	{ 82, 0xaaaa },
+	{ 84, 0x2a2a },
+	{ 146, 0x0060 },
+	{ 256, 0x0002 },
+	{ 257, 0x8004 },
+	{ 520, 0x0010 },
+	{ 528, 0x0083 },
+	{ 529, 0x0083 },
+	{ 548, 0x0c80 },
+	{ 580, 0x0c80 },
+	{ 768, 0x4050 },
+	{ 769, 0x4000 },
+	{ 771, 0x0040 },
+	{ 772, 0x0040 },
+	{ 773, 0x0040 },
+	{ 774, 0x0004 },
+	{ 775, 0x0100 },
+	{ 784, 0x4050 },
+	{ 785, 0x4000 },
+	{ 787, 0x0040 },
+	{ 788, 0x0040 },
+	{ 789, 0x0040 },
+	{ 1024, 0x00c0 },
+	{ 1025, 0x00c0 },
+	{ 1026, 0x00c0 },
+	{ 1027, 0x00c0 },
+	{ 1028, 0x00c0 },
+	{ 1029, 0x00c0 },
+	{ 1030, 0x00c0 },
+	{ 1031, 0x00c0 },
+	{ 1056, 0x0200 },
+	{ 1057, 0x0010 },
+	{ 1058, 0x0200 },
+	{ 1059, 0x0010 },
+	{ 1088, 0x0098 },
+	{ 1089, 0x0845 },
+	{ 1104, 0x0098 },
+	{ 1105, 0x0845 },
+	{ 1152, 0x6318 },
+	{ 1153, 0x6300 },
+	{ 1154, 0x0fca },
+	{ 1155, 0x0400 },
+	{ 1156, 0x00d8 },
+	{ 1157, 0x1eb5 },
+	{ 1158, 0xf145 },
+	{ 1159, 0x0b75 },
+	{ 1160, 0x01c5 },
+	{ 1161, 0x1c58 },
+	{ 1162, 0xf373 },
+	{ 1163, 0x0a54 },
+	{ 1164, 0x0558 },
+	{ 1165, 0x168e },
+	{ 1166, 0xf829 },
+	{ 1167, 0x07ad },
+	{ 1168, 0x1103 },
+	{ 1169, 0x0564 },
+	{ 1170, 0x0559 },
+	{ 1171, 0x4000 },
+	{ 1184, 0x6318 },
+	{ 1185, 0x6300 },
+	{ 1186, 0x0fca },
+	{ 1187, 0x0400 },
+	{ 1188, 0x00d8 },
+	{ 1189, 0x1eb5 },
+	{ 1190, 0xf145 },
+	{ 1191, 0x0b75 },
+	{ 1192, 0x01c5 },
+	{ 1193, 0x1c58 },
+	{ 1194, 0xf373 },
+	{ 1195, 0x0a54 },
+	{ 1196, 0x0558 },
+	{ 1197, 0x168e },
+	{ 1198, 0xf829 },
+	{ 1199, 0x07ad },
+	{ 1200, 0x1103 },
+	{ 1201, 0x0564 },
+	{ 1202, 0x0559 },
+	{ 1203, 0x4000 },
+	{ 1280, 0x00c0 },
+	{ 1281, 0x00c0 },
+	{ 1282, 0x00c0 },
+	{ 1283, 0x00c0 },
+	{ 1312, 0x0200 },
+	{ 1313, 0x0010 },
+	{ 1344, 0x0098 },
+	{ 1345, 0x0845 },
+	{ 1408, 0x6318 },
+	{ 1409, 0x6300 },
+	{ 1410, 0x0fca },
+	{ 1411, 0x0400 },
+	{ 1412, 0x00d8 },
+	{ 1413, 0x1eb5 },
+	{ 1414, 0xf145 },
+	{ 1415, 0x0b75 },
+	{ 1416, 0x01c5 },
+	{ 1417, 0x1c58 },
+	{ 1418, 0xf373 },
+	{ 1419, 0x0a54 },
+	{ 1420, 0x0558 },
+	{ 1421, 0x168e },
+	{ 1422, 0xf829 },
+	{ 1423, 0x07ad },
+	{ 1424, 0x1103 },
+	{ 1425, 0x0564 },
+	{ 1426, 0x0559 },
+	{ 1427, 0x4000 },
+	{ 1568, 0x0002 },
+	{ 1792, 0xa100 },
+	{ 1793, 0xa101 },
+	{ 1794, 0xa101 },
+	{ 1795, 0xa101 },
+	{ 1796, 0xa101 },
+	{ 1797, 0xa101 },
+	{ 1798, 0xa101 },
+	{ 1799, 0xa101 },
+	{ 1800, 0xa101 },
+	{ 1801, 0xa101 },
+	{ 1802, 0xa101 },
+	{ 1803, 0xa101 },
+	{ 1804, 0xa101 },
+	{ 1805, 0xa101 },
+	{ 1825, 0x0055 },
+	{ 1848, 0x3fff },
+	{ 1849, 0x1fff },
+	{ 2049, 0x0001 },
+	{ 2050, 0x0069 },
+	{ 2056, 0x0002 },
+	{ 2057, 0x0003 },
+	{ 2058, 0x0069 },
+	{ 12288, 0x0001 },
+	{ 12289, 0x0001 },
+	{ 12291, 0x0006 },
+	{ 12292, 0x0040 },
+	{ 12293, 0x0001 },
+	{ 12294, 0x000f },
+	{ 12295, 0x0006 },
+	{ 12296, 0x0001 },
+	{ 12297, 0x0003 },
+	{ 12298, 0x0104 },
+	{ 12300, 0x0060 },
+	{ 12301, 0x0011 },
+	{ 12302, 0x0401 },
+	{ 12304, 0x0050 },
+	{ 12305, 0x0003 },
+	{ 12306, 0x0100 },
+	{ 12308, 0x0051 },
+	{ 12309, 0x0003 },
+	{ 12310, 0x0104 },
+	{ 12311, 0x000a },
+	{ 12312, 0x0060 },
+	{ 12313, 0x003b },
+	{ 12314, 0x0502 },
+	{ 12315, 0x0100 },
+	{ 12316, 0x2fff },
+	{ 12320, 0x2fff },
+	{ 12324, 0x2fff },
+	{ 12328, 0x2fff },
+	{ 12332, 0x2fff },
+	{ 12336, 0x2fff },
+	{ 12340, 0x2fff },
+	{ 12344, 0x2fff },
+	{ 12348, 0x2fff },
+	{ 12352, 0x0001 },
+	{ 12353, 0x0001 },
+	{ 12355, 0x0006 },
+	{ 12356, 0x0040 },
+	{ 12357, 0x0001 },
+	{ 12358, 0x000f },
+	{ 12359, 0x0006 },
+	{ 12360, 0x0001 },
+	{ 12361, 0x0003 },
+	{ 12362, 0x0104 },
+	{ 12364, 0x0060 },
+	{ 12365, 0x0011 },
+	{ 12366, 0x0401 },
+	{ 12368, 0x0050 },
+	{ 12369, 0x0003 },
+	{ 12370, 0x0100 },
+	{ 12372, 0x0060 },
+	{ 12373, 0x003b },
+	{ 12374, 0x0502 },
+	{ 12375, 0x0100 },
+	{ 12376, 0x2fff },
+	{ 12380, 0x2fff },
+	{ 12384, 0x2fff },
+	{ 12388, 0x2fff },
+	{ 12392, 0x2fff },
+	{ 12396, 0x2fff },
+	{ 12400, 0x2fff },
+	{ 12404, 0x2fff },
+	{ 12408, 0x2fff },
+	{ 12412, 0x2fff },
+	{ 12416, 0x0001 },
+	{ 12417, 0x0001 },
+	{ 12419, 0x0006 },
+	{ 12420, 0x0040 },
+	{ 12421, 0x0001 },
+	{ 12422, 0x000f },
+	{ 12423, 0x0006 },
+	{ 12424, 0x0001 },
+	{ 12425, 0x0003 },
+	{ 12426, 0x0106 },
+	{ 12428, 0x0061 },
+	{ 12429, 0x0011 },
+	{ 12430, 0x0401 },
+	{ 12432, 0x0050 },
+	{ 12433, 0x0003 },
+	{ 12434, 0x0102 },
+	{ 12436, 0x0051 },
+	{ 12437, 0x0003 },
+	{ 12438, 0x0106 },
+	{ 12439, 0x000a },
+	{ 12440, 0x0061 },
+	{ 12441, 0x003b },
+	{ 12442, 0x0502 },
+	{ 12443, 0x0100 },
+	{ 12444, 0x2fff },
+	{ 12448, 0x2fff },
+	{ 12452, 0x2fff },
+	{ 12456, 0x2fff },
+	{ 12460, 0x2fff },
+	{ 12464, 0x2fff },
+	{ 12468, 0x2fff },
+	{ 12472, 0x2fff },
+	{ 12476, 0x2fff },
+	{ 12480, 0x0001 },
+	{ 12481, 0x0001 },
+	{ 12483, 0x0006 },
+	{ 12484, 0x0040 },
+	{ 12485, 0x0001 },
+	{ 12486, 0x000f },
+	{ 12487, 0x0006 },
+	{ 12488, 0x0001 },
+	{ 12489, 0x0003 },
+	{ 12490, 0x0106 },
+	{ 12492, 0x0061 },
+	{ 12493, 0x0011 },
+	{ 12494, 0x0401 },
+	{ 12496, 0x0050 },
+	{ 12497, 0x0003 },
+	{ 12498, 0x0102 },
+	{ 12500, 0x0061 },
+	{ 12501, 0x003b },
+	{ 12502, 0x0502 },
+	{ 12503, 0x0100 },
+	{ 12504, 0x2fff },
+	{ 12508, 0x2fff },
+	{ 12512, 0x2fff },
+	{ 12516, 0x2fff },
+	{ 12520, 0x2fff },
+	{ 12524, 0x2fff },
+	{ 12528, 0x2fff },
+	{ 12532, 0x2fff },
+	{ 12536, 0x2fff },
+	{ 12540, 0x2fff },
+	{ 12544, 0x0060 },
+	{ 12546, 0x0601 },
+	{ 12548, 0x0050 },
+	{ 12550, 0x0100 },
+	{ 12552, 0x0001 },
+	{ 12554, 0x0104 },
+	{ 12555, 0x0100 },
+	{ 12556, 0x2fff },
+	{ 12560, 0x2fff },
+	{ 12564, 0x2fff },
+	{ 12568, 0x2fff },
+	{ 12572, 0x2fff },
+	{ 12576, 0x2fff },
+	{ 12580, 0x2fff },
+	{ 12584, 0x2fff },
+	{ 12588, 0x2fff },
+	{ 12592, 0x2fff },
+	{ 12596, 0x2fff },
+	{ 12600, 0x2fff },
+	{ 12604, 0x2fff },
+	{ 12608, 0x0061 },
+	{ 12610, 0x0601 },
+	{ 12612, 0x0050 },
+	{ 12614, 0x0102 },
+	{ 12616, 0x0001 },
+	{ 12618, 0x0106 },
+	{ 12619, 0x0100 },
+	{ 12620, 0x2fff },
+	{ 12624, 0x2fff },
+	{ 12628, 0x2fff },
+	{ 12632, 0x2fff },
+	{ 12636, 0x2fff },
+	{ 12640, 0x2fff },
+	{ 12644, 0x2fff },
+	{ 12648, 0x2fff },
+	{ 12652, 0x2fff },
+	{ 12656, 0x2fff },
+	{ 12660, 0x2fff },
+	{ 12664, 0x2fff },
+	{ 12668, 0x2fff },
+	{ 12672, 0x0060 },
+	{ 12674, 0x0601 },
+	{ 12676, 0x0061 },
+	{ 12678, 0x0601 },
+	{ 12680, 0x0050 },
+	{ 12682, 0x0300 },
+	{ 12684, 0x0001 },
+	{ 12686, 0x0304 },
+	{ 12688, 0x0040 },
+	{ 12690, 0x000f },
+	{ 12692, 0x0001 },
+	{ 12695, 0x0100 },
 };
 
 struct fll_config {
@@ -134,7 +378,7 @@
 };
 
 struct wm8995_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 	int sysclk[2];
 	int mclk[2];
 	int aifclk[2];
@@ -156,7 +400,7 @@
 	struct wm8995_priv *wm8995 = container_of(nb, struct wm8995_priv, \
 				     disable_nb[n]); \
 	if (event & REGULATOR_EVENT_DISABLE) { \
-		wm8995->codec->cache_sync = 1; \
+		regcache_mark_dirty(wm8995->regmap);	\
 	} \
 	return 0; \
 }
@@ -688,8 +932,10 @@
 	SND_SOC_DAPM_MIXER("IN1R PGA", SND_SOC_NOPM, 0, 0,
 		&in1r_pga, 1),
 
-	SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8995_POWER_MANAGEMENT_1, 8, 0),
-	SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8995_POWER_MANAGEMENT_1, 9, 0),
+	SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8995_POWER_MANAGEMENT_1, 8, 0,
+			    NULL, 0),
+	SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8995_POWER_MANAGEMENT_1, 9, 0,
+			    NULL, 0),
 
 	SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8995_AIF1_CLOCKING_1, 0, 0, NULL, 0),
 	SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8995_AIF2_CLOCKING_1, 0, 0, NULL, 0),
@@ -947,31 +1193,244 @@
 	{ "SPK2R", NULL, "SPK2R Driver" }
 };
 
-static int wm8995_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8995_readable(struct device *dev, unsigned int reg)
 {
-	/* out of bounds registers are generally considered
-	 * volatile to support register banks that are partially
-	 * owned by something else for e.g. a DSP
-	 */
-	if (reg > WM8995_MAX_CACHED_REGISTER)
-		return 1;
+	switch (reg) {
+	case WM8995_SOFTWARE_RESET:
+	case WM8995_POWER_MANAGEMENT_1:
+	case WM8995_POWER_MANAGEMENT_2:
+	case WM8995_POWER_MANAGEMENT_3:
+	case WM8995_POWER_MANAGEMENT_4:
+	case WM8995_POWER_MANAGEMENT_5:
+	case WM8995_LEFT_LINE_INPUT_1_VOLUME:
+	case WM8995_RIGHT_LINE_INPUT_1_VOLUME:
+	case WM8995_LEFT_LINE_INPUT_CONTROL:
+	case WM8995_DAC1_LEFT_VOLUME:
+	case WM8995_DAC1_RIGHT_VOLUME:
+	case WM8995_DAC2_LEFT_VOLUME:
+	case WM8995_DAC2_RIGHT_VOLUME:
+	case WM8995_OUTPUT_VOLUME_ZC_1:
+	case WM8995_MICBIAS_1:
+	case WM8995_MICBIAS_2:
+	case WM8995_LDO_1:
+	case WM8995_LDO_2:
+	case WM8995_ACCESSORY_DETECT_MODE1:
+	case WM8995_ACCESSORY_DETECT_MODE2:
+	case WM8995_HEADPHONE_DETECT1:
+	case WM8995_HEADPHONE_DETECT2:
+	case WM8995_MIC_DETECT_1:
+	case WM8995_MIC_DETECT_2:
+	case WM8995_CHARGE_PUMP_1:
+	case WM8995_CLASS_W_1:
+	case WM8995_DC_SERVO_1:
+	case WM8995_DC_SERVO_2:
+	case WM8995_DC_SERVO_3:
+	case WM8995_DC_SERVO_5:
+	case WM8995_DC_SERVO_6:
+	case WM8995_DC_SERVO_7:
+	case WM8995_DC_SERVO_READBACK_0:
+	case WM8995_ANALOGUE_HP_1:
+	case WM8995_ANALOGUE_HP_2:
+	case WM8995_CHIP_REVISION:
+	case WM8995_CONTROL_INTERFACE_1:
+	case WM8995_CONTROL_INTERFACE_2:
+	case WM8995_WRITE_SEQUENCER_CTRL_1:
+	case WM8995_WRITE_SEQUENCER_CTRL_2:
+	case WM8995_AIF1_CLOCKING_1:
+	case WM8995_AIF1_CLOCKING_2:
+	case WM8995_AIF2_CLOCKING_1:
+	case WM8995_AIF2_CLOCKING_2:
+	case WM8995_CLOCKING_1:
+	case WM8995_CLOCKING_2:
+	case WM8995_AIF1_RATE:
+	case WM8995_AIF2_RATE:
+	case WM8995_RATE_STATUS:
+	case WM8995_FLL1_CONTROL_1:
+	case WM8995_FLL1_CONTROL_2:
+	case WM8995_FLL1_CONTROL_3:
+	case WM8995_FLL1_CONTROL_4:
+	case WM8995_FLL1_CONTROL_5:
+	case WM8995_FLL2_CONTROL_1:
+	case WM8995_FLL2_CONTROL_2:
+	case WM8995_FLL2_CONTROL_3:
+	case WM8995_FLL2_CONTROL_4:
+	case WM8995_FLL2_CONTROL_5:
+	case WM8995_AIF1_CONTROL_1:
+	case WM8995_AIF1_CONTROL_2:
+	case WM8995_AIF1_MASTER_SLAVE:
+	case WM8995_AIF1_BCLK:
+	case WM8995_AIF1ADC_LRCLK:
+	case WM8995_AIF1DAC_LRCLK:
+	case WM8995_AIF1DAC_DATA:
+	case WM8995_AIF1ADC_DATA:
+	case WM8995_AIF2_CONTROL_1:
+	case WM8995_AIF2_CONTROL_2:
+	case WM8995_AIF2_MASTER_SLAVE:
+	case WM8995_AIF2_BCLK:
+	case WM8995_AIF2ADC_LRCLK:
+	case WM8995_AIF2DAC_LRCLK:
+	case WM8995_AIF2DAC_DATA:
+	case WM8995_AIF2ADC_DATA:
+	case WM8995_AIF1_ADC1_LEFT_VOLUME:
+	case WM8995_AIF1_ADC1_RIGHT_VOLUME:
+	case WM8995_AIF1_DAC1_LEFT_VOLUME:
+	case WM8995_AIF1_DAC1_RIGHT_VOLUME:
+	case WM8995_AIF1_ADC2_LEFT_VOLUME:
+	case WM8995_AIF1_ADC2_RIGHT_VOLUME:
+	case WM8995_AIF1_DAC2_LEFT_VOLUME:
+	case WM8995_AIF1_DAC2_RIGHT_VOLUME:
+	case WM8995_AIF1_ADC1_FILTERS:
+	case WM8995_AIF1_ADC2_FILTERS:
+	case WM8995_AIF1_DAC1_FILTERS_1:
+	case WM8995_AIF1_DAC1_FILTERS_2:
+	case WM8995_AIF1_DAC2_FILTERS_1:
+	case WM8995_AIF1_DAC2_FILTERS_2:
+	case WM8995_AIF1_DRC1_1:
+	case WM8995_AIF1_DRC1_2:
+	case WM8995_AIF1_DRC1_3:
+	case WM8995_AIF1_DRC1_4:
+	case WM8995_AIF1_DRC1_5:
+	case WM8995_AIF1_DRC2_1:
+	case WM8995_AIF1_DRC2_2:
+	case WM8995_AIF1_DRC2_3:
+	case WM8995_AIF1_DRC2_4:
+	case WM8995_AIF1_DRC2_5:
+	case WM8995_AIF1_DAC1_EQ_GAINS_1:
+	case WM8995_AIF1_DAC1_EQ_GAINS_2:
+	case WM8995_AIF1_DAC1_EQ_BAND_1_A:
+	case WM8995_AIF1_DAC1_EQ_BAND_1_B:
+	case WM8995_AIF1_DAC1_EQ_BAND_1_PG:
+	case WM8995_AIF1_DAC1_EQ_BAND_2_A:
+	case WM8995_AIF1_DAC1_EQ_BAND_2_B:
+	case WM8995_AIF1_DAC1_EQ_BAND_2_C:
+	case WM8995_AIF1_DAC1_EQ_BAND_2_PG:
+	case WM8995_AIF1_DAC1_EQ_BAND_3_A:
+	case WM8995_AIF1_DAC1_EQ_BAND_3_B:
+	case WM8995_AIF1_DAC1_EQ_BAND_3_C:
+	case WM8995_AIF1_DAC1_EQ_BAND_3_PG:
+	case WM8995_AIF1_DAC1_EQ_BAND_4_A:
+	case WM8995_AIF1_DAC1_EQ_BAND_4_B:
+	case WM8995_AIF1_DAC1_EQ_BAND_4_C:
+	case WM8995_AIF1_DAC1_EQ_BAND_4_PG:
+	case WM8995_AIF1_DAC1_EQ_BAND_5_A:
+	case WM8995_AIF1_DAC1_EQ_BAND_5_B:
+	case WM8995_AIF1_DAC1_EQ_BAND_5_PG:
+	case WM8995_AIF1_DAC2_EQ_GAINS_1:
+	case WM8995_AIF1_DAC2_EQ_GAINS_2:
+	case WM8995_AIF1_DAC2_EQ_BAND_1_A:
+	case WM8995_AIF1_DAC2_EQ_BAND_1_B:
+	case WM8995_AIF1_DAC2_EQ_BAND_1_PG:
+	case WM8995_AIF1_DAC2_EQ_BAND_2_A:
+	case WM8995_AIF1_DAC2_EQ_BAND_2_B:
+	case WM8995_AIF1_DAC2_EQ_BAND_2_C:
+	case WM8995_AIF1_DAC2_EQ_BAND_2_PG:
+	case WM8995_AIF1_DAC2_EQ_BAND_3_A:
+	case WM8995_AIF1_DAC2_EQ_BAND_3_B:
+	case WM8995_AIF1_DAC2_EQ_BAND_3_C:
+	case WM8995_AIF1_DAC2_EQ_BAND_3_PG:
+	case WM8995_AIF1_DAC2_EQ_BAND_4_A:
+	case WM8995_AIF1_DAC2_EQ_BAND_4_B:
+	case WM8995_AIF1_DAC2_EQ_BAND_4_C:
+	case WM8995_AIF1_DAC2_EQ_BAND_4_PG:
+	case WM8995_AIF1_DAC2_EQ_BAND_5_A:
+	case WM8995_AIF1_DAC2_EQ_BAND_5_B:
+	case WM8995_AIF1_DAC2_EQ_BAND_5_PG:
+	case WM8995_AIF2_ADC_LEFT_VOLUME:
+	case WM8995_AIF2_ADC_RIGHT_VOLUME:
+	case WM8995_AIF2_DAC_LEFT_VOLUME:
+	case WM8995_AIF2_DAC_RIGHT_VOLUME:
+	case WM8995_AIF2_ADC_FILTERS:
+	case WM8995_AIF2_DAC_FILTERS_1:
+	case WM8995_AIF2_DAC_FILTERS_2:
+	case WM8995_AIF2_DRC_1:
+	case WM8995_AIF2_DRC_2:
+	case WM8995_AIF2_DRC_3:
+	case WM8995_AIF2_DRC_4:
+	case WM8995_AIF2_DRC_5:
+	case WM8995_AIF2_EQ_GAINS_1:
+	case WM8995_AIF2_EQ_GAINS_2:
+	case WM8995_AIF2_EQ_BAND_1_A:
+	case WM8995_AIF2_EQ_BAND_1_B:
+	case WM8995_AIF2_EQ_BAND_1_PG:
+	case WM8995_AIF2_EQ_BAND_2_A:
+	case WM8995_AIF2_EQ_BAND_2_B:
+	case WM8995_AIF2_EQ_BAND_2_C:
+	case WM8995_AIF2_EQ_BAND_2_PG:
+	case WM8995_AIF2_EQ_BAND_3_A:
+	case WM8995_AIF2_EQ_BAND_3_B:
+	case WM8995_AIF2_EQ_BAND_3_C:
+	case WM8995_AIF2_EQ_BAND_3_PG:
+	case WM8995_AIF2_EQ_BAND_4_A:
+	case WM8995_AIF2_EQ_BAND_4_B:
+	case WM8995_AIF2_EQ_BAND_4_C:
+	case WM8995_AIF2_EQ_BAND_4_PG:
+	case WM8995_AIF2_EQ_BAND_5_A:
+	case WM8995_AIF2_EQ_BAND_5_B:
+	case WM8995_AIF2_EQ_BAND_5_PG:
+	case WM8995_DAC1_MIXER_VOLUMES:
+	case WM8995_DAC1_LEFT_MIXER_ROUTING:
+	case WM8995_DAC1_RIGHT_MIXER_ROUTING:
+	case WM8995_DAC2_MIXER_VOLUMES:
+	case WM8995_DAC2_LEFT_MIXER_ROUTING:
+	case WM8995_DAC2_RIGHT_MIXER_ROUTING:
+	case WM8995_AIF1_ADC1_LEFT_MIXER_ROUTING:
+	case WM8995_AIF1_ADC1_RIGHT_MIXER_ROUTING:
+	case WM8995_AIF1_ADC2_LEFT_MIXER_ROUTING:
+	case WM8995_AIF1_ADC2_RIGHT_MIXER_ROUTING:
+	case WM8995_DAC_SOFTMUTE:
+	case WM8995_OVERSAMPLING:
+	case WM8995_SIDETONE:
+	case WM8995_GPIO_1:
+	case WM8995_GPIO_2:
+	case WM8995_GPIO_3:
+	case WM8995_GPIO_4:
+	case WM8995_GPIO_5:
+	case WM8995_GPIO_6:
+	case WM8995_GPIO_7:
+	case WM8995_GPIO_8:
+	case WM8995_GPIO_9:
+	case WM8995_GPIO_10:
+	case WM8995_GPIO_11:
+	case WM8995_GPIO_12:
+	case WM8995_GPIO_13:
+	case WM8995_GPIO_14:
+	case WM8995_PULL_CONTROL_1:
+	case WM8995_PULL_CONTROL_2:
+	case WM8995_INTERRUPT_STATUS_1:
+	case WM8995_INTERRUPT_STATUS_2:
+	case WM8995_INTERRUPT_RAW_STATUS_2:
+	case WM8995_INTERRUPT_STATUS_1_MASK:
+	case WM8995_INTERRUPT_STATUS_2_MASK:
+	case WM8995_INTERRUPT_CONTROL:
+	case WM8995_LEFT_PDM_SPEAKER_1:
+	case WM8995_RIGHT_PDM_SPEAKER_1:
+	case WM8995_PDM_SPEAKER_1_MUTE_SEQUENCE:
+	case WM8995_LEFT_PDM_SPEAKER_2:
+	case WM8995_RIGHT_PDM_SPEAKER_2:
+	case WM8995_PDM_SPEAKER_2_MUTE_SEQUENCE:
+		return true;
+	default:
+		return false;
+	}
+}
 
+static bool wm8995_volatile(struct device *dev, unsigned int reg)
+{
 	switch (reg) {
 	case WM8995_SOFTWARE_RESET:
 	case WM8995_DC_SERVO_READBACK_0:
 	case WM8995_INTERRUPT_STATUS_1:
 	case WM8995_INTERRUPT_STATUS_2:
-	case WM8995_INTERRUPT_STATUS_1_MASK:
-	case WM8995_INTERRUPT_STATUS_2_MASK:
 	case WM8995_INTERRUPT_CONTROL:
 	case WM8995_ACCESSORY_DETECT_MODE1:
 	case WM8995_ACCESSORY_DETECT_MODE2:
 	case WM8995_HEADPHONE_DETECT1:
 	case WM8995_HEADPHONE_DETECT2:
-		return 1;
+	case WM8995_RATE_STATUS:
+		return true;
+	default:
+		return false;
 	}
-
-	return 0;
 }
 
 static int wm8995_aif_mute(struct snd_soc_dai *dai, int mute)
@@ -1526,7 +1985,7 @@
 			if (ret)
 				return ret;
 
-			ret = snd_soc_cache_sync(codec);
+			ret = regcache_sync(wm8995->regmap);
 			if (ret) {
 				dev_err(codec->dev,
 					"Failed to sync cache: %d\n", ret);
@@ -1550,7 +2009,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm8995_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8995_suspend(struct snd_soc_codec *codec)
 {
 	wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -1592,7 +2051,7 @@
 	wm8995 = snd_soc_codec_get_drvdata(codec);
 	wm8995->codec = codec;
 
-	ret = snd_soc_codec_set_cache_io(codec, 16, 16, wm8995->control_type);
+	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
 		return ret;
@@ -1696,7 +2155,7 @@
 #define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8995_aif1_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif1_dai_ops = {
 	.set_sysclk = wm8995_set_dai_sysclk,
 	.set_fmt = wm8995_set_dai_fmt,
 	.hw_params = wm8995_hw_params,
@@ -1705,7 +2164,7 @@
 	.set_tristate = wm8995_set_tristate,
 };
 
-static struct snd_soc_dai_ops wm8995_aif2_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif2_dai_ops = {
 	.set_sysclk = wm8995_set_dai_sysclk,
 	.set_fmt = wm8995_set_dai_fmt,
 	.hw_params = wm8995_hw_params,
@@ -1714,7 +2173,7 @@
 	.set_tristate = wm8995_set_tristate,
 };
 
-static struct snd_soc_dai_ops wm8995_aif3_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif3_dai_ops = {
 	.set_tristate = wm8995_set_tristate,
 };
 
@@ -1781,11 +2240,18 @@
 	.suspend = wm8995_suspend,
 	.resume = wm8995_resume,
 	.set_bias_level = wm8995_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8995_reg_defs),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8995_reg_defs,
-	.volatile_register = wm8995_volatile,
-	.compress_type = SND_SOC_RBTREE_COMPRESSION
+};
+
+static struct regmap_config wm8995_regmap = {
+	.reg_bits = 16,
+	.val_bits = 16,
+
+	.max_register = WM8995_MAX_REGISTER,
+	.reg_defaults = wm8995_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8995_reg_defaults),
+	.volatile_reg = wm8995_volatile,
+	.readable_reg = wm8995_readable,
+	.cache_type = REGCACHE_RBTREE,
 };
 
 #if defined(CONFIG_SPI_MASTER)
@@ -1798,21 +2264,37 @@
 	if (!wm8995)
 		return -ENOMEM;
 
-	wm8995->control_type = SND_SOC_SPI;
 	spi_set_drvdata(spi, wm8995);
 
+	wm8995->regmap = regmap_init_spi(spi, &wm8995_regmap);
+	if (IS_ERR(wm8995->regmap)) {
+		ret = PTR_ERR(wm8995->regmap);
+		dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
+		goto err_alloc;
+	}
+
 	ret = snd_soc_register_codec(&spi->dev,
 				     &soc_codec_dev_wm8995, wm8995_dai,
 				     ARRAY_SIZE(wm8995_dai));
 	if (ret < 0)
-		kfree(wm8995);
+		goto err_regmap;
+
+	return ret;
+
+err_regmap:
+	regmap_exit(wm8995->regmap);
+err_alloc:
+	kfree(wm8995);
+
 	return ret;
 }
 
 static int __devexit wm8995_spi_remove(struct spi_device *spi)
 {
+	struct wm8995_priv *wm8995 = spi_get_drvdata(spi);
 	snd_soc_unregister_codec(&spi->dev);
-	kfree(spi_get_drvdata(spi));
+	regmap_exit(wm8995->regmap);
+	kfree(wm8995);
 	return 0;
 }
 
@@ -1837,21 +2319,40 @@
 	if (!wm8995)
 		return -ENOMEM;
 
-	wm8995->control_type = SND_SOC_I2C;
 	i2c_set_clientdata(i2c, wm8995);
 
+	wm8995->regmap = regmap_init_i2c(i2c, &wm8995_regmap);
+	if (IS_ERR(wm8995->regmap)) {
+		ret = PTR_ERR(wm8995->regmap);
+		dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret);
+		goto err_alloc;
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev,
 				     &soc_codec_dev_wm8995, wm8995_dai,
 				     ARRAY_SIZE(wm8995_dai));
-	if (ret < 0)
-		kfree(wm8995);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+		goto err_regmap;
+	}
+
+	return ret;
+
+err_regmap:
+	regmap_exit(wm8995->regmap);
+err_alloc:
+	kfree(wm8995);
+
 	return ret;
 }
 
 static __devexit int wm8995_i2c_remove(struct i2c_client *client)
 {
+	struct wm8995_priv *wm8995 = i2c_get_clientdata(client);
+
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm8995->regmap);
+	kfree(wm8995);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 645c980..41cc9d2 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -19,6 +19,7 @@
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -49,6 +50,8 @@
 };
 
 struct wm8996_priv {
+	struct device *dev;
+	struct regmap *regmap;
 	struct snd_soc_codec *codec;
 
 	int ldo1ena;
@@ -105,7 +108,7 @@
 	struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \
 						  disable_nb[n]); \
 	if (event & REGULATOR_EVENT_DISABLE) { \
-		wm8996->codec->cache_sync = 1; \
+		regcache_cache_only(wm8996->regmap, true);	\
 	} \
 	return 0; \
 }
@@ -114,297 +117,365 @@
 WM8996_REGULATOR_EVENT(1)
 WM8996_REGULATOR_EVENT(2)
 
-static const u16 wm8996_reg[WM8996_MAX_REGISTER] = {
-	[WM8996_SOFTWARE_RESET] = 0x8996,
-	[WM8996_POWER_MANAGEMENT_7] = 0x10,
-	[WM8996_DAC1_HPOUT1_VOLUME] = 0x88,
-	[WM8996_DAC2_HPOUT2_VOLUME] = 0x88,
-	[WM8996_DAC1_LEFT_VOLUME] = 0x2c0,
-	[WM8996_DAC1_RIGHT_VOLUME] = 0x2c0,
-	[WM8996_DAC2_LEFT_VOLUME] = 0x2c0,
-	[WM8996_DAC2_RIGHT_VOLUME] = 0x2c0,
-	[WM8996_OUTPUT1_LEFT_VOLUME] = 0x80,
-	[WM8996_OUTPUT1_RIGHT_VOLUME] = 0x80,
-	[WM8996_OUTPUT2_LEFT_VOLUME] = 0x80,
-	[WM8996_OUTPUT2_RIGHT_VOLUME] = 0x80,
-	[WM8996_MICBIAS_1] = 0x39,
-	[WM8996_MICBIAS_2] = 0x39,
-	[WM8996_LDO_1] = 0x3,
-	[WM8996_LDO_2] = 0x13,
-	[WM8996_ACCESSORY_DETECT_MODE_1] = 0x4,
-	[WM8996_HEADPHONE_DETECT_1] = 0x20,
-	[WM8996_MIC_DETECT_1] = 0x7600,
-	[WM8996_MIC_DETECT_2] = 0xbf,
-	[WM8996_CHARGE_PUMP_1] = 0x1f25,
-	[WM8996_CHARGE_PUMP_2] = 0xab19,
-	[WM8996_DC_SERVO_5] = 0x2a2a,
-	[WM8996_CONTROL_INTERFACE_1] = 0x8004,
-	[WM8996_CLOCKING_1] = 0x10,
-	[WM8996_AIF_RATE] = 0x83,
-	[WM8996_FLL_CONTROL_4] = 0x5dc0,
-	[WM8996_FLL_CONTROL_5] = 0xc84,
-	[WM8996_FLL_EFS_2] = 0x2,
-	[WM8996_AIF1_TX_LRCLK_1] = 0x80,
-	[WM8996_AIF1_TX_LRCLK_2] = 0x8,
-	[WM8996_AIF1_RX_LRCLK_1] = 0x80,
-	[WM8996_AIF1TX_DATA_CONFIGURATION_1] = 0x1818,
-	[WM8996_AIF1RX_DATA_CONFIGURATION] = 0x1818,
-	[WM8996_AIF1TX_TEST] = 0x7,
-	[WM8996_AIF2_TX_LRCLK_1] = 0x80,
-	[WM8996_AIF2_TX_LRCLK_2] = 0x8,
-	[WM8996_AIF2_RX_LRCLK_1] = 0x80,
-	[WM8996_AIF2TX_DATA_CONFIGURATION_1] = 0x1818,
-	[WM8996_AIF2RX_DATA_CONFIGURATION] = 0x1818,
-	[WM8996_AIF2TX_TEST] = 0x1,
-	[WM8996_DSP1_TX_LEFT_VOLUME] = 0xc0,
-	[WM8996_DSP1_TX_RIGHT_VOLUME] = 0xc0,
-	[WM8996_DSP1_RX_LEFT_VOLUME] = 0xc0,
-	[WM8996_DSP1_RX_RIGHT_VOLUME] = 0xc0,
-	[WM8996_DSP1_TX_FILTERS] = 0x2000,
-	[WM8996_DSP1_RX_FILTERS_1] = 0x200,
-	[WM8996_DSP1_RX_FILTERS_2] = 0x10,
-	[WM8996_DSP1_DRC_1] = 0x98,
-	[WM8996_DSP1_DRC_2] = 0x845,
-	[WM8996_DSP1_RX_EQ_GAINS_1] = 0x6318,
-	[WM8996_DSP1_RX_EQ_GAINS_2] = 0x6300,
-	[WM8996_DSP1_RX_EQ_BAND_1_A] = 0xfca,
-	[WM8996_DSP1_RX_EQ_BAND_1_B] = 0x400,
-	[WM8996_DSP1_RX_EQ_BAND_1_PG] = 0xd8,
-	[WM8996_DSP1_RX_EQ_BAND_2_A] = 0x1eb5,
-	[WM8996_DSP1_RX_EQ_BAND_2_B] = 0xf145,
-	[WM8996_DSP1_RX_EQ_BAND_2_C] = 0xb75,
-	[WM8996_DSP1_RX_EQ_BAND_2_PG] = 0x1c5,
-	[WM8996_DSP1_RX_EQ_BAND_3_A] = 0x1c58,
-	[WM8996_DSP1_RX_EQ_BAND_3_B] = 0xf373,
-	[WM8996_DSP1_RX_EQ_BAND_3_C] = 0xa54,
-	[WM8996_DSP1_RX_EQ_BAND_3_PG] = 0x558,
-	[WM8996_DSP1_RX_EQ_BAND_4_A] = 0x168e,
-	[WM8996_DSP1_RX_EQ_BAND_4_B] = 0xf829,
-	[WM8996_DSP1_RX_EQ_BAND_4_C] = 0x7ad,
-	[WM8996_DSP1_RX_EQ_BAND_4_PG] = 0x1103,
-	[WM8996_DSP1_RX_EQ_BAND_5_A] = 0x564,
-	[WM8996_DSP1_RX_EQ_BAND_5_B] = 0x559,
-	[WM8996_DSP1_RX_EQ_BAND_5_PG] = 0x4000,
-	[WM8996_DSP2_TX_LEFT_VOLUME] = 0xc0,
-	[WM8996_DSP2_TX_RIGHT_VOLUME] = 0xc0,
-	[WM8996_DSP2_RX_LEFT_VOLUME] = 0xc0,
-	[WM8996_DSP2_RX_RIGHT_VOLUME] = 0xc0,
-	[WM8996_DSP2_TX_FILTERS] = 0x2000,
-	[WM8996_DSP2_RX_FILTERS_1] = 0x200,
-	[WM8996_DSP2_RX_FILTERS_2] = 0x10,
-	[WM8996_DSP2_DRC_1] = 0x98,
-	[WM8996_DSP2_DRC_2] = 0x845,
-	[WM8996_DSP2_RX_EQ_GAINS_1] = 0x6318,
-	[WM8996_DSP2_RX_EQ_GAINS_2] = 0x6300,
-	[WM8996_DSP2_RX_EQ_BAND_1_A] = 0xfca,
-	[WM8996_DSP2_RX_EQ_BAND_1_B] = 0x400,
-	[WM8996_DSP2_RX_EQ_BAND_1_PG] = 0xd8,
-	[WM8996_DSP2_RX_EQ_BAND_2_A] = 0x1eb5,
-	[WM8996_DSP2_RX_EQ_BAND_2_B] = 0xf145,
-	[WM8996_DSP2_RX_EQ_BAND_2_C] = 0xb75,
-	[WM8996_DSP2_RX_EQ_BAND_2_PG] = 0x1c5,
-	[WM8996_DSP2_RX_EQ_BAND_3_A] = 0x1c58,
-	[WM8996_DSP2_RX_EQ_BAND_3_B] = 0xf373,
-	[WM8996_DSP2_RX_EQ_BAND_3_C] = 0xa54,
-	[WM8996_DSP2_RX_EQ_BAND_3_PG] = 0x558,
-	[WM8996_DSP2_RX_EQ_BAND_4_A] = 0x168e,
-	[WM8996_DSP2_RX_EQ_BAND_4_B] = 0xf829,
-	[WM8996_DSP2_RX_EQ_BAND_4_C] = 0x7ad,
-	[WM8996_DSP2_RX_EQ_BAND_4_PG] = 0x1103,
-	[WM8996_DSP2_RX_EQ_BAND_5_A] = 0x564,
-	[WM8996_DSP2_RX_EQ_BAND_5_B] = 0x559,
-	[WM8996_DSP2_RX_EQ_BAND_5_PG] = 0x4000,
-	[WM8996_OVERSAMPLING] = 0xd,
-	[WM8996_SIDETONE] = 0x1040,
-	[WM8996_GPIO_1] = 0xa101,
-	[WM8996_GPIO_2] = 0xa101,
-	[WM8996_GPIO_3] = 0xa101,
-	[WM8996_GPIO_4] = 0xa101,
-	[WM8996_GPIO_5] = 0xa101,
-	[WM8996_PULL_CONTROL_2] = 0x140,
-	[WM8996_INTERRUPT_STATUS_1_MASK] = 0x1f,
-	[WM8996_INTERRUPT_STATUS_2_MASK] = 0x1ecf,
-	[WM8996_RIGHT_PDM_SPEAKER] = 0x1,
-	[WM8996_PDM_SPEAKER_MUTE_SEQUENCE] = 0x69,
-	[WM8996_PDM_SPEAKER_VOLUME] = 0x66,
-	[WM8996_WRITE_SEQUENCER_0] = 0x1,
-	[WM8996_WRITE_SEQUENCER_1] = 0x1,
-	[WM8996_WRITE_SEQUENCER_3] = 0x6,
-	[WM8996_WRITE_SEQUENCER_4] = 0x40,
-	[WM8996_WRITE_SEQUENCER_5] = 0x1,
-	[WM8996_WRITE_SEQUENCER_6] = 0xf,
-	[WM8996_WRITE_SEQUENCER_7] = 0x6,
-	[WM8996_WRITE_SEQUENCER_8] = 0x1,
-	[WM8996_WRITE_SEQUENCER_9] = 0x3,
-	[WM8996_WRITE_SEQUENCER_10] = 0x104,
-	[WM8996_WRITE_SEQUENCER_12] = 0x60,
-	[WM8996_WRITE_SEQUENCER_13] = 0x11,
-	[WM8996_WRITE_SEQUENCER_14] = 0x401,
-	[WM8996_WRITE_SEQUENCER_16] = 0x50,
-	[WM8996_WRITE_SEQUENCER_17] = 0x3,
-	[WM8996_WRITE_SEQUENCER_18] = 0x100,
-	[WM8996_WRITE_SEQUENCER_20] = 0x51,
-	[WM8996_WRITE_SEQUENCER_21] = 0x3,
-	[WM8996_WRITE_SEQUENCER_22] = 0x104,
-	[WM8996_WRITE_SEQUENCER_23] = 0xa,
-	[WM8996_WRITE_SEQUENCER_24] = 0x60,
-	[WM8996_WRITE_SEQUENCER_25] = 0x3b,
-	[WM8996_WRITE_SEQUENCER_26] = 0x502,
-	[WM8996_WRITE_SEQUENCER_27] = 0x100,
-	[WM8996_WRITE_SEQUENCER_28] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_32] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_36] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_40] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_44] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_48] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_52] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_56] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_60] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_64] = 0x1,
-	[WM8996_WRITE_SEQUENCER_65] = 0x1,
-	[WM8996_WRITE_SEQUENCER_67] = 0x6,
-	[WM8996_WRITE_SEQUENCER_68] = 0x40,
-	[WM8996_WRITE_SEQUENCER_69] = 0x1,
-	[WM8996_WRITE_SEQUENCER_70] = 0xf,
-	[WM8996_WRITE_SEQUENCER_71] = 0x6,
-	[WM8996_WRITE_SEQUENCER_72] = 0x1,
-	[WM8996_WRITE_SEQUENCER_73] = 0x3,
-	[WM8996_WRITE_SEQUENCER_74] = 0x104,
-	[WM8996_WRITE_SEQUENCER_76] = 0x60,
-	[WM8996_WRITE_SEQUENCER_77] = 0x11,
-	[WM8996_WRITE_SEQUENCER_78] = 0x401,
-	[WM8996_WRITE_SEQUENCER_80] = 0x50,
-	[WM8996_WRITE_SEQUENCER_81] = 0x3,
-	[WM8996_WRITE_SEQUENCER_82] = 0x100,
-	[WM8996_WRITE_SEQUENCER_84] = 0x60,
-	[WM8996_WRITE_SEQUENCER_85] = 0x3b,
-	[WM8996_WRITE_SEQUENCER_86] = 0x502,
-	[WM8996_WRITE_SEQUENCER_87] = 0x100,
-	[WM8996_WRITE_SEQUENCER_88] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_92] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_96] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_100] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_104] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_108] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_112] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_116] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_120] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_124] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_128] = 0x1,
-	[WM8996_WRITE_SEQUENCER_129] = 0x1,
-	[WM8996_WRITE_SEQUENCER_131] = 0x6,
-	[WM8996_WRITE_SEQUENCER_132] = 0x40,
-	[WM8996_WRITE_SEQUENCER_133] = 0x1,
-	[WM8996_WRITE_SEQUENCER_134] = 0xf,
-	[WM8996_WRITE_SEQUENCER_135] = 0x6,
-	[WM8996_WRITE_SEQUENCER_136] = 0x1,
-	[WM8996_WRITE_SEQUENCER_137] = 0x3,
-	[WM8996_WRITE_SEQUENCER_138] = 0x106,
-	[WM8996_WRITE_SEQUENCER_140] = 0x61,
-	[WM8996_WRITE_SEQUENCER_141] = 0x11,
-	[WM8996_WRITE_SEQUENCER_142] = 0x401,
-	[WM8996_WRITE_SEQUENCER_144] = 0x50,
-	[WM8996_WRITE_SEQUENCER_145] = 0x3,
-	[WM8996_WRITE_SEQUENCER_146] = 0x102,
-	[WM8996_WRITE_SEQUENCER_148] = 0x51,
-	[WM8996_WRITE_SEQUENCER_149] = 0x3,
-	[WM8996_WRITE_SEQUENCER_150] = 0x106,
-	[WM8996_WRITE_SEQUENCER_151] = 0xa,
-	[WM8996_WRITE_SEQUENCER_152] = 0x61,
-	[WM8996_WRITE_SEQUENCER_153] = 0x3b,
-	[WM8996_WRITE_SEQUENCER_154] = 0x502,
-	[WM8996_WRITE_SEQUENCER_155] = 0x100,
-	[WM8996_WRITE_SEQUENCER_156] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_160] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_164] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_168] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_172] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_176] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_180] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_184] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_188] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_192] = 0x1,
-	[WM8996_WRITE_SEQUENCER_193] = 0x1,
-	[WM8996_WRITE_SEQUENCER_195] = 0x6,
-	[WM8996_WRITE_SEQUENCER_196] = 0x40,
-	[WM8996_WRITE_SEQUENCER_197] = 0x1,
-	[WM8996_WRITE_SEQUENCER_198] = 0xf,
-	[WM8996_WRITE_SEQUENCER_199] = 0x6,
-	[WM8996_WRITE_SEQUENCER_200] = 0x1,
-	[WM8996_WRITE_SEQUENCER_201] = 0x3,
-	[WM8996_WRITE_SEQUENCER_202] = 0x106,
-	[WM8996_WRITE_SEQUENCER_204] = 0x61,
-	[WM8996_WRITE_SEQUENCER_205] = 0x11,
-	[WM8996_WRITE_SEQUENCER_206] = 0x401,
-	[WM8996_WRITE_SEQUENCER_208] = 0x50,
-	[WM8996_WRITE_SEQUENCER_209] = 0x3,
-	[WM8996_WRITE_SEQUENCER_210] = 0x102,
-	[WM8996_WRITE_SEQUENCER_212] = 0x61,
-	[WM8996_WRITE_SEQUENCER_213] = 0x3b,
-	[WM8996_WRITE_SEQUENCER_214] = 0x502,
-	[WM8996_WRITE_SEQUENCER_215] = 0x100,
-	[WM8996_WRITE_SEQUENCER_216] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_220] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_224] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_228] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_232] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_236] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_240] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_244] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_248] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_252] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_256] = 0x60,
-	[WM8996_WRITE_SEQUENCER_258] = 0x601,
-	[WM8996_WRITE_SEQUENCER_260] = 0x50,
-	[WM8996_WRITE_SEQUENCER_262] = 0x100,
-	[WM8996_WRITE_SEQUENCER_264] = 0x1,
-	[WM8996_WRITE_SEQUENCER_266] = 0x104,
-	[WM8996_WRITE_SEQUENCER_267] = 0x100,
-	[WM8996_WRITE_SEQUENCER_268] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_272] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_276] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_280] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_284] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_288] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_292] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_296] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_300] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_304] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_308] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_312] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_316] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_320] = 0x61,
-	[WM8996_WRITE_SEQUENCER_322] = 0x601,
-	[WM8996_WRITE_SEQUENCER_324] = 0x50,
-	[WM8996_WRITE_SEQUENCER_326] = 0x102,
-	[WM8996_WRITE_SEQUENCER_328] = 0x1,
-	[WM8996_WRITE_SEQUENCER_330] = 0x106,
-	[WM8996_WRITE_SEQUENCER_331] = 0x100,
-	[WM8996_WRITE_SEQUENCER_332] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_336] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_340] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_344] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_348] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_352] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_356] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_360] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_364] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_368] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_372] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_376] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_380] = 0x2fff,
-	[WM8996_WRITE_SEQUENCER_384] = 0x60,
-	[WM8996_WRITE_SEQUENCER_386] = 0x601,
-	[WM8996_WRITE_SEQUENCER_388] = 0x61,
-	[WM8996_WRITE_SEQUENCER_390] = 0x601,
-	[WM8996_WRITE_SEQUENCER_392] = 0x50,
-	[WM8996_WRITE_SEQUENCER_394] = 0x300,
-	[WM8996_WRITE_SEQUENCER_396] = 0x1,
-	[WM8996_WRITE_SEQUENCER_398] = 0x304,
-	[WM8996_WRITE_SEQUENCER_400] = 0x40,
-	[WM8996_WRITE_SEQUENCER_402] = 0xf,
-	[WM8996_WRITE_SEQUENCER_404] = 0x1,
-	[WM8996_WRITE_SEQUENCER_407] = 0x100,
+static struct reg_default wm8996_reg[] = {
+	{ WM8996_SOFTWARE_RESET, 0x8996 },
+	{ WM8996_POWER_MANAGEMENT_1, 0x0 },
+	{ WM8996_POWER_MANAGEMENT_2, 0x0 },
+	{ WM8996_POWER_MANAGEMENT_3, 0x0 },
+	{ WM8996_POWER_MANAGEMENT_4, 0x0 },
+	{ WM8996_POWER_MANAGEMENT_5, 0x0 },
+	{ WM8996_POWER_MANAGEMENT_6, 0x0 },
+	{ WM8996_POWER_MANAGEMENT_7, 0x10 },
+	{ WM8996_POWER_MANAGEMENT_8, 0x0 },
+	{ WM8996_LEFT_LINE_INPUT_VOLUME, 0x0 },
+	{ WM8996_RIGHT_LINE_INPUT_VOLUME, 0x0 },
+	{ WM8996_LINE_INPUT_CONTROL, 0x0 },
+	{ WM8996_DAC1_HPOUT1_VOLUME, 0x88 },
+	{ WM8996_DAC2_HPOUT2_VOLUME, 0x88 },
+	{ WM8996_DAC1_LEFT_VOLUME, 0x2c0 },
+	{ WM8996_DAC1_RIGHT_VOLUME, 0x2c0 },
+	{ WM8996_DAC2_LEFT_VOLUME, 0x2c0 },
+	{ WM8996_DAC2_RIGHT_VOLUME, 0x2c0 },
+	{ WM8996_OUTPUT1_LEFT_VOLUME, 0x80 },
+	{ WM8996_OUTPUT1_RIGHT_VOLUME, 0x80 },
+	{ WM8996_OUTPUT2_LEFT_VOLUME, 0x80 },
+	{ WM8996_OUTPUT2_RIGHT_VOLUME, 0x80 },
+	{ WM8996_MICBIAS_1, 0x39 },
+	{ WM8996_MICBIAS_2, 0x39 },
+	{ WM8996_LDO_1, 0x3 },
+	{ WM8996_LDO_2, 0x13 },
+	{ WM8996_ACCESSORY_DETECT_MODE_1, 0x4 },
+	{ WM8996_ACCESSORY_DETECT_MODE_2, 0x0 },
+	{ WM8996_HEADPHONE_DETECT_1, 0x20 },
+	{ WM8996_HEADPHONE_DETECT_2, 0x0 },
+	{ WM8996_MIC_DETECT_1, 0x7600 },
+	{ WM8996_MIC_DETECT_2, 0xbf },
+	{ WM8996_CHARGE_PUMP_1, 0x1f25 },
+	{ WM8996_CHARGE_PUMP_2, 0xab19 },
+	{ WM8996_DC_SERVO_1, 0x0 },
+	{ WM8996_DC_SERVO_2, 0x0 },
+	{ WM8996_DC_SERVO_3, 0x0 },
+	{ WM8996_DC_SERVO_5, 0x2a2a },
+	{ WM8996_DC_SERVO_6, 0x0 },
+	{ WM8996_DC_SERVO_7, 0x0 },
+	{ WM8996_ANALOGUE_HP_1, 0x0 },
+	{ WM8996_ANALOGUE_HP_2, 0x0 },
+	{ WM8996_CONTROL_INTERFACE_1, 0x8004 },
+	{ WM8996_WRITE_SEQUENCER_CTRL_1, 0x0 },
+	{ WM8996_WRITE_SEQUENCER_CTRL_2, 0x0 },
+	{ WM8996_AIF_CLOCKING_1, 0x0 },
+	{ WM8996_AIF_CLOCKING_2, 0x0 },
+	{ WM8996_CLOCKING_1, 0x10 },
+	{ WM8996_CLOCKING_2, 0x0 },
+	{ WM8996_AIF_RATE, 0x83 },
+	{ WM8996_FLL_CONTROL_1, 0x0 },
+	{ WM8996_FLL_CONTROL_2, 0x0 },
+	{ WM8996_FLL_CONTROL_3, 0x0 },
+	{ WM8996_FLL_CONTROL_4, 0x5dc0 },
+	{ WM8996_FLL_CONTROL_5, 0xc84 },
+	{ WM8996_FLL_EFS_1, 0x0 },
+	{ WM8996_FLL_EFS_2, 0x2 },
+	{ WM8996_AIF1_CONTROL, 0x0 },
+	{ WM8996_AIF1_BCLK, 0x0 },
+	{ WM8996_AIF1_TX_LRCLK_1, 0x80 },
+	{ WM8996_AIF1_TX_LRCLK_2, 0x8 },
+	{ WM8996_AIF1_RX_LRCLK_1, 0x80 },
+	{ WM8996_AIF1_RX_LRCLK_2, 0x0 },
+	{ WM8996_AIF1TX_DATA_CONFIGURATION_1, 0x1818 },
+	{ WM8996_AIF1TX_DATA_CONFIGURATION_2, 0 },
+	{ WM8996_AIF1RX_DATA_CONFIGURATION, 0x1818 },
+	{ WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1RX_MONO_CONFIGURATION, 0x0 },
+	{ WM8996_AIF1TX_TEST, 0x7 },
+	{ WM8996_AIF2_CONTROL, 0x0 },
+	{ WM8996_AIF2_BCLK, 0x0 },
+	{ WM8996_AIF2_TX_LRCLK_1, 0x80 },
+	{ WM8996_AIF2_TX_LRCLK_2, 0x8 },
+	{ WM8996_AIF2_RX_LRCLK_1, 0x80 },
+	{ WM8996_AIF2_RX_LRCLK_2, 0x0 },
+	{ WM8996_AIF2TX_DATA_CONFIGURATION_1, 0x1818 },
+	{ WM8996_AIF2RX_DATA_CONFIGURATION, 0x1818 },
+	{ WM8996_AIF2RX_DATA_CONFIGURATION, 0x0 },
+	{ WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, 0x0 },
+	{ WM8996_AIF2TX_CHANNEL_1_CONFIGURATION, 0x0 },
+	{ WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, 0x0 },
+	{ WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, 0x0 },
+	{ WM8996_AIF2RX_MONO_CONFIGURATION, 0x0 },
+	{ WM8996_AIF2TX_TEST, 0x1 },
+	{ WM8996_DSP1_TX_LEFT_VOLUME, 0xc0 },
+	{ WM8996_DSP1_TX_RIGHT_VOLUME, 0xc0 },
+	{ WM8996_DSP1_RX_LEFT_VOLUME, 0xc0 },
+	{ WM8996_DSP1_RX_RIGHT_VOLUME, 0xc0 },
+	{ WM8996_DSP1_TX_FILTERS, 0x2000 },
+	{ WM8996_DSP1_RX_FILTERS_1, 0x200 },
+	{ WM8996_DSP1_RX_FILTERS_2, 0x10 },
+	{ WM8996_DSP1_DRC_1, 0x98 },
+	{ WM8996_DSP1_DRC_2, 0x845 },
+	{ WM8996_DSP1_RX_EQ_GAINS_1, 0x6318 },
+	{ WM8996_DSP1_RX_EQ_GAINS_2, 0x6300 },
+	{ WM8996_DSP1_RX_EQ_BAND_1_A, 0xfca },
+	{ WM8996_DSP1_RX_EQ_BAND_1_B, 0x400 },
+	{ WM8996_DSP1_RX_EQ_BAND_1_PG, 0xd8 },
+	{ WM8996_DSP1_RX_EQ_BAND_2_A, 0x1eb5 },
+	{ WM8996_DSP1_RX_EQ_BAND_2_B, 0xf145 },
+	{ WM8996_DSP1_RX_EQ_BAND_2_C, 0xb75 },
+	{ WM8996_DSP1_RX_EQ_BAND_2_PG, 0x1c5 },
+	{ WM8996_DSP1_RX_EQ_BAND_3_A, 0x1c58 },
+	{ WM8996_DSP1_RX_EQ_BAND_3_B, 0xf373 },
+	{ WM8996_DSP1_RX_EQ_BAND_3_C, 0xa54 },
+	{ WM8996_DSP1_RX_EQ_BAND_3_PG, 0x558 },
+	{ WM8996_DSP1_RX_EQ_BAND_4_A, 0x168e },
+	{ WM8996_DSP1_RX_EQ_BAND_4_B, 0xf829 },
+	{ WM8996_DSP1_RX_EQ_BAND_4_C, 0x7ad },
+	{ WM8996_DSP1_RX_EQ_BAND_4_PG, 0x1103 },
+	{ WM8996_DSP1_RX_EQ_BAND_5_A, 0x564 },
+	{ WM8996_DSP1_RX_EQ_BAND_5_B, 0x559 },
+	{ WM8996_DSP1_RX_EQ_BAND_5_PG, 0x4000 },
+	{ WM8996_DSP2_TX_LEFT_VOLUME, 0xc0 },
+	{ WM8996_DSP2_TX_RIGHT_VOLUME, 0xc0 },
+	{ WM8996_DSP2_RX_LEFT_VOLUME, 0xc0 },
+	{ WM8996_DSP2_RX_RIGHT_VOLUME, 0xc0 },
+	{ WM8996_DSP2_TX_FILTERS, 0x2000 },
+	{ WM8996_DSP2_RX_FILTERS_1, 0x200 },
+	{ WM8996_DSP2_RX_FILTERS_2, 0x10 },
+	{ WM8996_DSP2_DRC_1, 0x98 },
+	{ WM8996_DSP2_DRC_2, 0x845 },
+	{ WM8996_DSP2_RX_EQ_GAINS_1, 0x6318 },
+	{ WM8996_DSP2_RX_EQ_GAINS_2, 0x6300 },
+	{ WM8996_DSP2_RX_EQ_BAND_1_A, 0xfca },
+	{ WM8996_DSP2_RX_EQ_BAND_1_B, 0x400 },
+	{ WM8996_DSP2_RX_EQ_BAND_1_PG, 0xd8 },
+	{ WM8996_DSP2_RX_EQ_BAND_2_A, 0x1eb5 },
+	{ WM8996_DSP2_RX_EQ_BAND_2_B, 0xf145 },
+	{ WM8996_DSP2_RX_EQ_BAND_2_C, 0xb75 },
+	{ WM8996_DSP2_RX_EQ_BAND_2_PG, 0x1c5 },
+	{ WM8996_DSP2_RX_EQ_BAND_3_A, 0x1c58 },
+	{ WM8996_DSP2_RX_EQ_BAND_3_B, 0xf373 },
+	{ WM8996_DSP2_RX_EQ_BAND_3_C, 0xa54 },
+	{ WM8996_DSP2_RX_EQ_BAND_3_PG, 0x558 },
+	{ WM8996_DSP2_RX_EQ_BAND_4_A, 0x168e },
+	{ WM8996_DSP2_RX_EQ_BAND_4_B, 0xf829 },
+	{ WM8996_DSP2_RX_EQ_BAND_4_C, 0x7ad },
+	{ WM8996_DSP2_RX_EQ_BAND_4_PG, 0x1103 },
+	{ WM8996_DSP2_RX_EQ_BAND_5_A, 0x564 },
+	{ WM8996_DSP2_RX_EQ_BAND_5_B, 0x559 },
+	{ WM8996_DSP2_RX_EQ_BAND_5_PG, 0x4000 },
+	{ WM8996_DAC1_MIXER_VOLUMES, 0x0 },
+	{ WM8996_DAC1_LEFT_MIXER_ROUTING, 0x0 },
+	{ WM8996_DAC1_RIGHT_MIXER_ROUTING, 0x0 },
+	{ WM8996_DAC2_MIXER_VOLUMES, 0x0 },
+	{ WM8996_DAC2_LEFT_MIXER_ROUTING, 0x0 },
+	{ WM8996_DAC2_RIGHT_MIXER_ROUTING, 0x0 },
+	{ WM8996_DSP1_TX_LEFT_MIXER_ROUTING, 0x0 },
+	{ WM8996_DSP1_TX_RIGHT_MIXER_ROUTING, 0x0 },
+	{ WM8996_DSP2_TX_LEFT_MIXER_ROUTING, 0x0 },
+	{ WM8996_DSP2_TX_RIGHT_MIXER_ROUTING, 0x0 },
+	{ WM8996_DSP_TX_MIXER_SELECT, 0x0 },
+	{ WM8996_DAC_SOFTMUTE, 0x0 },
+	{ WM8996_OVERSAMPLING, 0xd },
+	{ WM8996_SIDETONE, 0x1040 },
+	{ WM8996_GPIO_1, 0xa101 },
+	{ WM8996_GPIO_2, 0xa101 },
+	{ WM8996_GPIO_3, 0xa101 },
+	{ WM8996_GPIO_4, 0xa101 },
+	{ WM8996_GPIO_5, 0xa101 },
+	{ WM8996_PULL_CONTROL_1, 0x0 },
+	{ WM8996_PULL_CONTROL_2, 0x140 },
+	{ WM8996_INTERRUPT_STATUS_1_MASK, 0x1f },
+	{ WM8996_INTERRUPT_STATUS_2_MASK, 0x1ecf },
+	{ WM8996_LEFT_PDM_SPEAKER, 0x0 },
+	{ WM8996_RIGHT_PDM_SPEAKER, 0x1 },
+	{ WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 },
+	{ WM8996_PDM_SPEAKER_VOLUME, 0x66 },
+	{ WM8996_WRITE_SEQUENCER_0, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_1, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_3, 0x6 },
+	{ WM8996_WRITE_SEQUENCER_4, 0x40 },
+	{ WM8996_WRITE_SEQUENCER_5, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_6, 0xf },
+	{ WM8996_WRITE_SEQUENCER_7, 0x6 },
+	{ WM8996_WRITE_SEQUENCER_8, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_9, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_10, 0x104 },
+	{ WM8996_WRITE_SEQUENCER_12, 0x60 },
+	{ WM8996_WRITE_SEQUENCER_13, 0x11 },
+	{ WM8996_WRITE_SEQUENCER_14, 0x401 },
+	{ WM8996_WRITE_SEQUENCER_16, 0x50 },
+	{ WM8996_WRITE_SEQUENCER_17, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_18, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_20, 0x51 },
+	{ WM8996_WRITE_SEQUENCER_21, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_22, 0x104 },
+	{ WM8996_WRITE_SEQUENCER_23, 0xa },
+	{ WM8996_WRITE_SEQUENCER_24, 0x60 },
+	{ WM8996_WRITE_SEQUENCER_25, 0x3b },
+	{ WM8996_WRITE_SEQUENCER_26, 0x502 },
+	{ WM8996_WRITE_SEQUENCER_27, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_28, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_32, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_36, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_40, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_44, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_48, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_52, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_56, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_60, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_64, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_65, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_67, 0x6 },
+	{ WM8996_WRITE_SEQUENCER_68, 0x40 },
+	{ WM8996_WRITE_SEQUENCER_69, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_70, 0xf },
+	{ WM8996_WRITE_SEQUENCER_71, 0x6 },
+	{ WM8996_WRITE_SEQUENCER_72, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_73, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_74, 0x104 },
+	{ WM8996_WRITE_SEQUENCER_76, 0x60 },
+	{ WM8996_WRITE_SEQUENCER_77, 0x11 },
+	{ WM8996_WRITE_SEQUENCER_78, 0x401 },
+	{ WM8996_WRITE_SEQUENCER_80, 0x50 },
+	{ WM8996_WRITE_SEQUENCER_81, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_82, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_84, 0x60 },
+	{ WM8996_WRITE_SEQUENCER_85, 0x3b },
+	{ WM8996_WRITE_SEQUENCER_86, 0x502 },
+	{ WM8996_WRITE_SEQUENCER_87, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_88, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_92, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_96, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_100, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_104, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_108, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_112, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_116, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_120, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_124, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_128, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_129, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_131, 0x6 },
+	{ WM8996_WRITE_SEQUENCER_132, 0x40 },
+	{ WM8996_WRITE_SEQUENCER_133, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_134, 0xf },
+	{ WM8996_WRITE_SEQUENCER_135, 0x6 },
+	{ WM8996_WRITE_SEQUENCER_136, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_137, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_138, 0x106 },
+	{ WM8996_WRITE_SEQUENCER_140, 0x61 },
+	{ WM8996_WRITE_SEQUENCER_141, 0x11 },
+	{ WM8996_WRITE_SEQUENCER_142, 0x401 },
+	{ WM8996_WRITE_SEQUENCER_144, 0x50 },
+	{ WM8996_WRITE_SEQUENCER_145, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_146, 0x102 },
+	{ WM8996_WRITE_SEQUENCER_148, 0x51 },
+	{ WM8996_WRITE_SEQUENCER_149, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_150, 0x106 },
+	{ WM8996_WRITE_SEQUENCER_151, 0xa },
+	{ WM8996_WRITE_SEQUENCER_152, 0x61 },
+	{ WM8996_WRITE_SEQUENCER_153, 0x3b },
+	{ WM8996_WRITE_SEQUENCER_154, 0x502 },
+	{ WM8996_WRITE_SEQUENCER_155, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_156, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_160, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_164, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_168, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_172, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_176, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_180, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_184, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_188, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_192, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_193, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_195, 0x6 },
+	{ WM8996_WRITE_SEQUENCER_196, 0x40 },
+	{ WM8996_WRITE_SEQUENCER_197, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_198, 0xf },
+	{ WM8996_WRITE_SEQUENCER_199, 0x6 },
+	{ WM8996_WRITE_SEQUENCER_200, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_201, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_202, 0x106 },
+	{ WM8996_WRITE_SEQUENCER_204, 0x61 },
+	{ WM8996_WRITE_SEQUENCER_205, 0x11 },
+	{ WM8996_WRITE_SEQUENCER_206, 0x401 },
+	{ WM8996_WRITE_SEQUENCER_208, 0x50 },
+	{ WM8996_WRITE_SEQUENCER_209, 0x3 },
+	{ WM8996_WRITE_SEQUENCER_210, 0x102 },
+	{ WM8996_WRITE_SEQUENCER_212, 0x61 },
+	{ WM8996_WRITE_SEQUENCER_213, 0x3b },
+	{ WM8996_WRITE_SEQUENCER_214, 0x502 },
+	{ WM8996_WRITE_SEQUENCER_215, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_216, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_220, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_224, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_228, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_232, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_236, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_240, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_244, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_248, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_252, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_256, 0x60 },
+	{ WM8996_WRITE_SEQUENCER_258, 0x601 },
+	{ WM8996_WRITE_SEQUENCER_260, 0x50 },
+	{ WM8996_WRITE_SEQUENCER_262, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_264, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_266, 0x104 },
+	{ WM8996_WRITE_SEQUENCER_267, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_268, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_272, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_276, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_280, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_284, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_288, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_292, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_296, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_300, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_304, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_308, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_312, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_316, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_320, 0x61 },
+	{ WM8996_WRITE_SEQUENCER_322, 0x601 },
+	{ WM8996_WRITE_SEQUENCER_324, 0x50 },
+	{ WM8996_WRITE_SEQUENCER_326, 0x102 },
+	{ WM8996_WRITE_SEQUENCER_328, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_330, 0x106 },
+	{ WM8996_WRITE_SEQUENCER_331, 0x100 },
+	{ WM8996_WRITE_SEQUENCER_332, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_336, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_340, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_344, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_348, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_352, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_356, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_360, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_364, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_368, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_372, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_376, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_380, 0x2fff },
+	{ WM8996_WRITE_SEQUENCER_384, 0x60 },
+	{ WM8996_WRITE_SEQUENCER_386, 0x601 },
+	{ WM8996_WRITE_SEQUENCER_388, 0x61 },
+	{ WM8996_WRITE_SEQUENCER_390, 0x601 },
+	{ WM8996_WRITE_SEQUENCER_392, 0x50 },
+	{ WM8996_WRITE_SEQUENCER_394, 0x300 },
+	{ WM8996_WRITE_SEQUENCER_396, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_398, 0x304 },
+	{ WM8996_WRITE_SEQUENCER_400, 0x40 },
+	{ WM8996_WRITE_SEQUENCER_402, 0xf },
+	{ WM8996_WRITE_SEQUENCER_404, 0x1 },
+	{ WM8996_WRITE_SEQUENCER_407, 0x100 },
 };
 
 static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0);
@@ -1413,8 +1484,7 @@
 	{ "SPKDAT", NULL, "SPKR PGA" },
 };
 
-static int wm8996_readable_register(struct snd_soc_codec *codec,
-				    unsigned int reg)
+static bool wm8996_readable_register(struct device *dev, unsigned int reg)
 {
 	/* Due to the sparseness of the register map the compiler
 	 * output from an explicit switch statement ends up being much
@@ -1621,8 +1691,7 @@
 	}
 }
 
-static int wm8996_volatile_register(struct snd_soc_codec *codec,
-				    unsigned int reg)
+static bool wm8996_volatile_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case WM8996_SOFTWARE_RESET:
@@ -1646,9 +1715,15 @@
 	}
 }
 
-static int wm8996_reset(struct snd_soc_codec *codec)
+static int wm8996_reset(struct wm8996_priv *wm8996)
 {
-	return snd_soc_write(codec, WM8996_SOFTWARE_RESET, 0x8915);
+	if (wm8996->pdata.ldo_ena > 0) {
+		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+		return 0;
+	} else {
+		return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
+				    0x8915);
+	}
 }
 
 static const int bclk_divs[] = {
@@ -1723,13 +1798,13 @@
 				msleep(5);
 			}
 
-			codec->cache_only = false;
-			snd_soc_cache_sync(codec);
+			regcache_cache_only(codec->control_data, false);
+			regcache_sync(codec->control_data);
 		}
 		break;
 
 	case SND_SOC_BIAS_OFF:
-		codec->cache_only = true;
+		regcache_cache_only(codec->control_data, true);
 		if (wm8996->pdata.ldo_ena >= 0)
 			gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
 		regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies),
@@ -2251,48 +2326,45 @@
 static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
-	struct snd_soc_codec *codec = wm8996->codec;
 
-	snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
-			    WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT);
+	regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+			   WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT);
 }
 
 static int wm8996_gpio_direction_out(struct gpio_chip *chip,
 				     unsigned offset, int value)
 {
 	struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
-	struct snd_soc_codec *codec = wm8996->codec;
 	int val;
 
 	val = (1 << WM8996_GP1_FN_SHIFT) | (!!value << WM8996_GP1_LVL_SHIFT);
 
-	return snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
-				   WM8996_GP1_FN_MASK | WM8996_GP1_DIR |
-				   WM8996_GP1_LVL, val);
+	return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+				  WM8996_GP1_FN_MASK | WM8996_GP1_DIR |
+				  WM8996_GP1_LVL, val);
 }
 
 static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
-	struct snd_soc_codec *codec = wm8996->codec;
+	unsigned int reg;
 	int ret;
 
-	ret = snd_soc_read(codec, WM8996_GPIO_1 + offset);
+	ret = regmap_read(wm8996->regmap, WM8996_GPIO_1 + offset, &reg);
 	if (ret < 0)
 		return ret;
 
-	return (ret & WM8996_GP1_LVL) != 0;
+	return (reg & WM8996_GP1_LVL) != 0;
 }
 
 static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
 {
 	struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
-	struct snd_soc_codec *codec = wm8996->codec;
 
-	return snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
-				   WM8996_GP1_FN_MASK | WM8996_GP1_DIR,
-				   (1 << WM8996_GP1_FN_SHIFT) |
-				   (1 << WM8996_GP1_DIR_SHIFT));
+	return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+				  WM8996_GP1_FN_MASK | WM8996_GP1_DIR,
+				  (1 << WM8996_GP1_FN_SHIFT) |
+				  (1 << WM8996_GP1_DIR_SHIFT));
 }
 
 static struct gpio_chip wm8996_template_chip = {
@@ -2305,14 +2377,13 @@
 	.can_sleep		= 1,
 };
 
-static void wm8996_init_gpio(struct snd_soc_codec *codec)
+static void wm8996_init_gpio(struct wm8996_priv *wm8996)
 {
-	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
 	wm8996->gpio_chip = wm8996_template_chip;
 	wm8996->gpio_chip.ngpio = 5;
-	wm8996->gpio_chip.dev = codec->dev;
+	wm8996->gpio_chip.dev = wm8996->dev;
 
 	if (wm8996->pdata.gpio_base)
 		wm8996->gpio_chip.base = wm8996->pdata.gpio_base;
@@ -2321,24 +2392,23 @@
 
 	ret = gpiochip_add(&wm8996->gpio_chip);
 	if (ret != 0)
-		dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+		dev_err(wm8996->dev, "Failed to add GPIOs: %d\n", ret);
 }
 
-static void wm8996_free_gpio(struct snd_soc_codec *codec)
+static void wm8996_free_gpio(struct wm8996_priv *wm8996)
 {
-	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
 	ret = gpiochip_remove(&wm8996->gpio_chip);
 	if (ret != 0)
-		dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+		dev_err(wm8996->dev, "Failed to remove GPIOs: %d\n", ret);
 }
 #else
-static void wm8996_init_gpio(struct snd_soc_codec *codec)
+static void wm8996_init_gpio(struct wm8996_priv *wm8996)
 {
 }
 
-static void wm8996_free_gpio(struct snd_soc_codec *codec)
+static void wm8996_free_gpio(struct wm8996_priv *wm8996)
 {
 }
 #endif
@@ -2692,6 +2762,18 @@
 			"Failed to add ReTune Mobile controls: %d\n", ret);
 }
 
+static const struct regmap_config wm8996_regmap = {
+	.reg_bits = 16,
+	.val_bits = 16,
+
+	.max_register = WM8996_MAX_REGISTER,
+	.reg_defaults = wm8996_reg,
+	.num_reg_defaults = ARRAY_SIZE(wm8996_reg),
+	.volatile_reg = wm8996_volatile_register,
+	.readable_reg = wm8996_readable_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
 static int wm8996_probe(struct snd_soc_codec *codec)
 {
 	int ret;
@@ -2707,33 +2789,18 @@
 
 	dapm->idle_bias_off = true;
 
-	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+	codec->control_data = wm8996->regmap;
+
+	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		goto err;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
-		wm8996->supplies[i].supply = wm8996_supply_names[i];
-
-	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8996->supplies),
-				 wm8996->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-		goto err;
-	}
-
 	wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0;
 	wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
 	wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
 
-	wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD");
-	if (IS_ERR(wm8996->cpvdd)) {
-		ret = PTR_ERR(wm8996->cpvdd);
-		dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
-		goto err_get;
-	}
-
 	/* This should really be moved into the regulator core */
 	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
 		ret = regulator_register_notifier(wm8996->supplies[i].consumer,
@@ -2745,50 +2812,7 @@
 		}
 	}
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
-				    wm8996->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-		goto err_cpvdd;
-	}
-
-	if (wm8996->pdata.ldo_ena >= 0) {
-		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
-		msleep(5);
-	}
-
-	ret = snd_soc_read(codec, WM8996_SOFTWARE_RESET);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to read ID register: %d\n", ret);
-		goto err_enable;
-	}
-	if (ret != 0x8915) {
-		dev_err(codec->dev, "Device is not a WM8996, ID %x\n", ret);
-		ret = -EINVAL;
-		goto err_enable;
-	}
-
-	ret = snd_soc_read(codec, WM8996_CHIP_REVISION);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to read device revision: %d\n",
-			ret);
-		goto err_enable;
-	}
-	
-	dev_info(codec->dev, "revision %c\n",
-		 (ret & WM8996_CHIP_REV_MASK) + 'A');
-
-	if (wm8996->pdata.ldo_ena >= 0) {
-		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
-	} else {
-		ret = wm8996_reset(codec);
-		if (ret < 0) {
-			dev_err(codec->dev, "Failed to issue reset\n");
-			goto err_enable;
-		}
-	}
-
-	codec->cache_only = true;
+	regcache_cache_only(codec->control_data, true);
 
 	/* Apply platform data settings */
 	snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL,
@@ -2946,10 +2970,6 @@
 				    WM8996_AIF2TX_LRCLK_MODE,
 				    WM8996_AIF2TX_LRCLK_MODE);
 
-	regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-
-	wm8996_init_gpio(codec);
-
 	if (i2c->irq) {
 		if (wm8996->pdata.irq_flags)
 			irq_flags = wm8996->pdata.irq_flags;
@@ -2987,15 +3007,6 @@
 
 	return 0;
 
-err_enable:
-	if (wm8996->pdata.ldo_ena >= 0)
-		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
-
-	regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-err_cpvdd:
-	regulator_put(wm8996->cpvdd);
-err_get:
-	regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
 err:
 	return ret;
 }
@@ -3012,8 +3023,6 @@
 	if (i2c->irq)
 		free_irq(i2c->irq, codec);
 
-	wm8996_free_gpio(codec);
-
 	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
 		regulator_unregister_notifier(wm8996->supplies[i].consumer,
 					      &wm8996->disable_nb[i]);
@@ -3028,12 +3037,6 @@
 	.remove =	wm8996_remove,
 	.set_bias_level = wm8996_set_bias_level,
 	.seq_notifier = wm8996_seq_notifier,
-	.reg_cache_size = WM8996_MAX_REGISTER + 1,
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8996_reg,
-	.volatile_register = wm8996_volatile_register,
-	.readable_register = wm8996_readable_register,
-	.compress_type = SND_SOC_RBTREE_COMPRESSION,
 	.controls = wm8996_snd_controls,
 	.num_controls = ARRAY_SIZE(wm8996_snd_controls),
 	.dapm_widgets = wm8996_dapm_widgets,
@@ -3049,7 +3052,7 @@
 			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\
 			SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8996_dai_ops = {
+static const struct snd_soc_dai_ops wm8996_dai_ops = {
 	.set_fmt = wm8996_set_fmt,
 	.hw_params = wm8996_hw_params,
 	.set_sysclk = wm8996_set_sysclk,
@@ -3098,13 +3101,16 @@
 				      const struct i2c_device_id *id)
 {
 	struct wm8996_priv *wm8996;
-	int ret;
+	int ret, i;
+	unsigned int reg;
 
-	wm8996 = kzalloc(sizeof(struct wm8996_priv), GFP_KERNEL);
+	wm8996 = devm_kzalloc(&i2c->dev, sizeof(struct wm8996_priv),
+			      GFP_KERNEL);
 	if (wm8996 == NULL)
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm8996);
+	wm8996->dev = &i2c->dev;
 
 	if (dev_get_platdata(&i2c->dev))
 		memcpy(&wm8996->pdata, dev_get_platdata(&i2c->dev),
@@ -3120,19 +3126,97 @@
 		}
 	}
 
+	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
+		wm8996->supplies[i].supply = wm8996_supply_names[i];
+
+	ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
+				 wm8996->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+		goto err_gpio;
+	}
+
+	wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD");
+	if (IS_ERR(wm8996->cpvdd)) {
+		ret = PTR_ERR(wm8996->cpvdd);
+		dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
+		goto err_get;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
+				    wm8996->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+		goto err_cpvdd;
+	}
+
+	if (wm8996->pdata.ldo_ena > 0) {
+		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
+		msleep(5);
+	}
+
+	wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap);
+	if (IS_ERR(wm8996->regmap)) {
+		ret = PTR_ERR(wm8996->regmap);
+		dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+		goto err_enable;
+	}
+
+	ret = regmap_read(wm8996->regmap, WM8996_SOFTWARE_RESET, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+		goto err_regmap;
+	}
+	if (reg != 0x8915) {
+		dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", ret);
+		ret = -EINVAL;
+		goto err_regmap;
+	}
+
+	ret = regmap_read(wm8996->regmap, WM8996_CHIP_REVISION, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read device revision: %d\n",
+			ret);
+		goto err_regmap;
+	}
+
+	dev_info(&i2c->dev, "revision %c\n",
+		 (reg & WM8996_CHIP_REV_MASK) + 'A');
+
+	regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+
+	ret = wm8996_reset(wm8996);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to issue reset\n");
+		goto err_regmap;
+	}
+
+	wm8996_init_gpio(wm8996);
+
 	ret = snd_soc_register_codec(&i2c->dev,
 				     &soc_codec_dev_wm8996, wm8996_dai,
 				     ARRAY_SIZE(wm8996_dai));
 	if (ret < 0)
-		goto err_gpio;
+		goto err_gpiolib;
 
 	return ret;
 
+err_gpiolib:
+	wm8996_free_gpio(wm8996);
+err_regmap:
+	regmap_exit(wm8996->regmap);
+err_enable:
+	if (wm8996->pdata.ldo_ena > 0)
+		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+	regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+err_cpvdd:
+	regulator_put(wm8996->cpvdd);
+err_get:
+	regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
 err_gpio:
 	if (wm8996->pdata.ldo_ena > 0)
 		gpio_free(wm8996->pdata.ldo_ena);
 err:
-	kfree(wm8996);
 
 	return ret;
 }
@@ -3142,9 +3226,14 @@
 	struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
 
 	snd_soc_unregister_codec(&client->dev);
-	if (wm8996->pdata.ldo_ena > 0)
+	wm8996_free_gpio(wm8996);
+	regulator_put(wm8996->cpvdd);
+	regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+	regmap_exit(wm8996->regmap);
+	if (wm8996->pdata.ldo_ena > 0) {
+		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
 		gpio_free(wm8996->pdata.ldo_ena);
-	kfree(i2c_get_clientdata(client));
+	}
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 4a398c3..1f2672b 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -18,7 +18,7 @@
 #include <linux/device.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -30,69 +30,61 @@
 #include <sound/wm9081.h>
 #include "wm9081.h"
 
-static u16 wm9081_reg_defaults[] = {
-	0x0000,     /* R0  - Software Reset */
-	0x0000,     /* R1 */
-	0x00B9,     /* R2  - Analogue Lineout */
-	0x00B9,     /* R3  - Analogue Speaker PGA */
-	0x0001,     /* R4  - VMID Control */
-	0x0068,     /* R5  - Bias Control 1 */
-	0x0000,     /* R6 */
-	0x0000,     /* R7  - Analogue Mixer */
-	0x0000,     /* R8  - Anti Pop Control */
-	0x01DB,     /* R9  - Analogue Speaker 1 */
-	0x0018,     /* R10 - Analogue Speaker 2 */
-	0x0180,     /* R11 - Power Management */
-	0x0000,     /* R12 - Clock Control 1 */
-	0x0038,     /* R13 - Clock Control 2 */
-	0x4000,     /* R14 - Clock Control 3 */
-	0x0000,     /* R15 */
-	0x0000,     /* R16 - FLL Control 1 */
-	0x0200,     /* R17 - FLL Control 2 */
-	0x0000,     /* R18 - FLL Control 3 */
-	0x0204,     /* R19 - FLL Control 4 */
-	0x0000,     /* R20 - FLL Control 5 */
-	0x0000,     /* R21 */
-	0x0000,     /* R22 - Audio Interface 1 */
-	0x0002,     /* R23 - Audio Interface 2 */
-	0x0008,     /* R24 - Audio Interface 3 */
-	0x0022,     /* R25 - Audio Interface 4 */
-	0x0000,     /* R26 - Interrupt Status */
-	0x0006,     /* R27 - Interrupt Status Mask */
-	0x0000,     /* R28 - Interrupt Polarity */
-	0x0000,     /* R29 - Interrupt Control */
-	0x00C0,     /* R30 - DAC Digital 1 */
-	0x0008,     /* R31 - DAC Digital 2 */
-	0x09AF,     /* R32 - DRC 1 */
-	0x4201,     /* R33 - DRC 2 */
-	0x0000,     /* R34 - DRC 3 */
-	0x0000,     /* R35 - DRC 4 */
-	0x0000,     /* R36 */
-	0x0000,     /* R37 */
-	0x0000,     /* R38 - Write Sequencer 1 */
-	0x0000,     /* R39 - Write Sequencer 2 */
-	0x0002,     /* R40 - MW Slave 1 */
-	0x0000,     /* R41 */
-	0x0000,     /* R42 - EQ 1 */
-	0x0000,     /* R43 - EQ 2 */
-	0x0FCA,     /* R44 - EQ 3 */
-	0x0400,     /* R45 - EQ 4 */
-	0x00B8,     /* R46 - EQ 5 */
-	0x1EB5,     /* R47 - EQ 6 */
-	0xF145,     /* R48 - EQ 7 */
-	0x0B75,     /* R49 - EQ 8 */
-	0x01C5,     /* R50 - EQ 9 */
-	0x169E,     /* R51 - EQ 10 */
-	0xF829,     /* R52 - EQ 11 */
-	0x07AD,     /* R53 - EQ 12 */
-	0x1103,     /* R54 - EQ 13 */
-	0x1C58,     /* R55 - EQ 14 */
-	0xF373,     /* R56 - EQ 15 */
-	0x0A54,     /* R57 - EQ 16 */
-	0x0558,     /* R58 - EQ 17 */
-	0x0564,     /* R59 - EQ 18 */
-	0x0559,     /* R60 - EQ 19 */
-	0x4000,     /* R61 - EQ 20 */
+static struct reg_default wm9081_reg[] = {
+	{  0, 0x9081 },     /* R0  - Software Reset */
+	{  2, 0x00B9 },     /* R2  - Analogue Lineout */
+	{  3, 0x00B9 },     /* R3  - Analogue Speaker PGA */
+	{  4, 0x0001 },     /* R4  - VMID Control */
+	{  5, 0x0068 },     /* R5  - Bias Control 1 */
+	{  7, 0x0000 },     /* R7  - Analogue Mixer */
+	{  8, 0x0000 },     /* R8  - Anti Pop Control */
+	{  9, 0x01DB },     /* R9  - Analogue Speaker 1 */
+	{ 10, 0x0018 },     /* R10 - Analogue Speaker 2 */
+	{ 11, 0x0180 },     /* R11 - Power Management */
+	{ 12, 0x0000 },     /* R12 - Clock Control 1 */
+	{ 13, 0x0038 },     /* R13 - Clock Control 2 */
+	{ 14, 0x4000 },     /* R14 - Clock Control 3 */
+	{ 16, 0x0000 },     /* R16 - FLL Control 1 */
+	{ 17, 0x0200 },     /* R17 - FLL Control 2 */
+	{ 18, 0x0000 },     /* R18 - FLL Control 3 */
+	{ 19, 0x0204 },     /* R19 - FLL Control 4 */
+	{ 20, 0x0000 },     /* R20 - FLL Control 5 */
+	{ 22, 0x0000 },     /* R22 - Audio Interface 1 */
+	{ 23, 0x0002 },     /* R23 - Audio Interface 2 */
+	{ 24, 0x0008 },     /* R24 - Audio Interface 3 */
+	{ 25, 0x0022 },     /* R25 - Audio Interface 4 */
+	{ 27, 0x0006 },     /* R27 - Interrupt Status Mask */
+	{ 28, 0x0000 },     /* R28 - Interrupt Polarity */
+	{ 29, 0x0000 },     /* R29 - Interrupt Control */
+	{ 30, 0x00C0 },     /* R30 - DAC Digital 1 */
+	{ 31, 0x0008 },     /* R31 - DAC Digital 2 */
+	{ 32, 0x09AF },     /* R32 - DRC 1 */
+	{ 33, 0x4201 },     /* R33 - DRC 2 */
+	{ 34, 0x0000 },     /* R34 - DRC 3 */
+	{ 35, 0x0000 },     /* R35 - DRC 4 */
+	{ 38, 0x0000 },     /* R38 - Write Sequencer 1 */
+	{ 39, 0x0000 },     /* R39 - Write Sequencer 2 */
+	{ 40, 0x0002 },     /* R40 - MW Slave 1 */
+	{ 42, 0x0000 },     /* R42 - EQ 1 */
+	{ 43, 0x0000 },     /* R43 - EQ 2 */
+	{ 44, 0x0FCA },     /* R44 - EQ 3 */
+	{ 45, 0x0400 },     /* R45 - EQ 4 */
+	{ 46, 0x00B8 },     /* R46 - EQ 5 */
+	{ 47, 0x1EB5 },     /* R47 - EQ 6 */
+	{ 48, 0xF145 },     /* R48 - EQ 7 */
+	{ 49, 0x0B75 },     /* R49 - EQ 8 */
+	{ 50, 0x01C5 },     /* R50 - EQ 9 */
+	{ 51, 0x169E },     /* R51 - EQ 10 */
+	{ 52, 0xF829 },     /* R52 - EQ 11 */
+	{ 53, 0x07AD },     /* R53 - EQ 12 */
+	{ 54, 0x1103 },     /* R54 - EQ 13 */
+	{ 55, 0x1C58 },     /* R55 - EQ 14 */
+	{ 56, 0xF373 },     /* R56 - EQ 15 */
+	{ 57, 0x0A54 },     /* R57 - EQ 16 */
+	{ 58, 0x0558 },     /* R58 - EQ 17 */
+	{ 59, 0x0564 },     /* R59 - EQ 18 */
+	{ 60, 0x0559 },     /* R60 - EQ 19 */
+	{ 61, 0x4000 },     /* R61 - EQ 20 */
 };
 
 static struct {
@@ -156,7 +148,7 @@
 };
 
 struct wm9081_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 	int sysclk_source;
 	int mclk_rate;
 	int sysclk_rate;
@@ -169,20 +161,84 @@
 	struct wm9081_pdata pdata;
 };
 
-static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm9081_volatile_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case WM9081_SOFTWARE_RESET:
 	case WM9081_INTERRUPT_STATUS:
-		return 1;
+		return true;
 	default:
-		return 0;
+		return false;
 	}
 }
 
-static int wm9081_reset(struct snd_soc_codec *codec)
+static bool wm9081_readable_register(struct device *dev, unsigned int reg)
 {
-	return snd_soc_write(codec, WM9081_SOFTWARE_RESET, 0);
+	switch (reg) {
+	case WM9081_SOFTWARE_RESET:
+	case WM9081_ANALOGUE_LINEOUT:
+	case WM9081_ANALOGUE_SPEAKER_PGA:
+	case WM9081_VMID_CONTROL:
+	case WM9081_BIAS_CONTROL_1:
+	case WM9081_ANALOGUE_MIXER:
+	case WM9081_ANTI_POP_CONTROL:
+	case WM9081_ANALOGUE_SPEAKER_1:
+	case WM9081_ANALOGUE_SPEAKER_2:
+	case WM9081_POWER_MANAGEMENT:
+	case WM9081_CLOCK_CONTROL_1:
+	case WM9081_CLOCK_CONTROL_2:
+	case WM9081_CLOCK_CONTROL_3:
+	case WM9081_FLL_CONTROL_1:
+	case WM9081_FLL_CONTROL_2:
+	case WM9081_FLL_CONTROL_3:
+	case WM9081_FLL_CONTROL_4:
+	case WM9081_FLL_CONTROL_5:
+	case WM9081_AUDIO_INTERFACE_1:
+	case WM9081_AUDIO_INTERFACE_2:
+	case WM9081_AUDIO_INTERFACE_3:
+	case WM9081_AUDIO_INTERFACE_4:
+	case WM9081_INTERRUPT_STATUS:
+	case WM9081_INTERRUPT_STATUS_MASK:
+	case WM9081_INTERRUPT_POLARITY:
+	case WM9081_INTERRUPT_CONTROL:
+	case WM9081_DAC_DIGITAL_1:
+	case WM9081_DAC_DIGITAL_2:
+	case WM9081_DRC_1:
+	case WM9081_DRC_2:
+	case WM9081_DRC_3:
+	case WM9081_DRC_4:
+	case WM9081_WRITE_SEQUENCER_1:
+	case WM9081_WRITE_SEQUENCER_2:
+	case WM9081_MW_SLAVE_1:
+	case WM9081_EQ_1:
+	case WM9081_EQ_2:
+	case WM9081_EQ_3:
+	case WM9081_EQ_4:
+	case WM9081_EQ_5:
+	case WM9081_EQ_6:
+	case WM9081_EQ_7:
+	case WM9081_EQ_8:
+	case WM9081_EQ_9:
+	case WM9081_EQ_10:
+	case WM9081_EQ_11:
+	case WM9081_EQ_12:
+	case WM9081_EQ_13:
+	case WM9081_EQ_14:
+	case WM9081_EQ_15:
+	case WM9081_EQ_16:
+	case WM9081_EQ_17:
+	case WM9081_EQ_18:
+	case WM9081_EQ_19:
+	case WM9081_EQ_20:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int wm9081_reset(struct regmap *map)
+{
+	return regmap_write(map, WM9081_SOFTWARE_RESET, 0x9081);
 }
 
 static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
@@ -737,6 +793,7 @@
 		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("TSENSE", WM9081_POWER_MANAGEMENT, 7, 0, NULL, 0),
 };
 
 
@@ -759,6 +816,7 @@
 	{ "Speaker PGA", NULL, "CLK_SYS" },
 
 	{ "Speaker", NULL, "Speaker PGA" },
+	{ "Speaker", NULL, "TSENSE" },
 
 	{ "SPKN", NULL, "Speaker" },
 	{ "SPKP", NULL, "Speaker" },
@@ -767,84 +825,74 @@
 static int wm9081_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
-	u16 reg;
-
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		break;
 
 	case SND_SOC_BIAS_PREPARE:
 		/* VMID=2*40k */
-		reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
-		reg &= ~WM9081_VMID_SEL_MASK;
-		reg |= 0x2;
-		snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+		snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+				    WM9081_VMID_SEL_MASK, 0x2);
 
 		/* Normal bias current */
-		reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-		reg &= ~WM9081_STBY_BIAS_ENA;
-		snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+		snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+				    WM9081_STBY_BIAS_ENA, 0);
 		break;
 
 	case SND_SOC_BIAS_STANDBY:
 		/* Initial cold start */
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
 			/* Disable LINEOUT discharge */
-			reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
-			reg &= ~WM9081_LINEOUT_DISCH;
-			snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
+			snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
+					    WM9081_LINEOUT_DISCH, 0);
 
 			/* Select startup bias source */
-			reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-			reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
-			snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+			snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+					    WM9081_BIAS_SRC | WM9081_BIAS_ENA,
+					    WM9081_BIAS_SRC | WM9081_BIAS_ENA);
 
 			/* VMID 2*4k; Soft VMID ramp enable */
-			reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
-			reg |= WM9081_VMID_RAMP | 0x6;
-			snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+			snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+					    WM9081_VMID_RAMP |
+					    WM9081_VMID_SEL_MASK,
+					    WM9081_VMID_RAMP | 0x6);
 
 			mdelay(100);
 
 			/* Normal bias enable & soft start off */
-			reg &= ~WM9081_VMID_RAMP;
-			snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+			snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+					    WM9081_VMID_RAMP, 0);
 
 			/* Standard bias source */
-			reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-			reg &= ~WM9081_BIAS_SRC;
-			snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+			snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+					    WM9081_BIAS_SRC, 0);
 		}
 
 		/* VMID 2*240k */
-		reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
-		reg &= ~WM9081_VMID_SEL_MASK;
-		reg |= 0x04;
-		snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+		snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+				    WM9081_VMID_SEL_MASK, 0x04);
 
 		/* Standby bias current on */
-		reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-		reg |= WM9081_STBY_BIAS_ENA;
-		snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+		snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+				    WM9081_STBY_BIAS_ENA,
+				    WM9081_STBY_BIAS_ENA);
 		break;
 
 	case SND_SOC_BIAS_OFF:
 		/* Startup bias source and disable bias */
-		reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-		reg |= WM9081_BIAS_SRC;
-		reg &= ~WM9081_BIAS_ENA;
-		snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+		snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+				    WM9081_BIAS_SRC | WM9081_BIAS_ENA,
+				    WM9081_BIAS_SRC);
 
 		/* Disable VMID with soft ramping */
-		reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
-		reg &= ~WM9081_VMID_SEL_MASK;
-		reg |= WM9081_VMID_RAMP;
-		snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+		snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+				    WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK,
+				    WM9081_VMID_RAMP);
 
 		/* Actively discharge LINEOUT */
-		reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
-		reg |= WM9081_LINEOUT_DISCH;
-		snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
+		snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
+				    WM9081_LINEOUT_DISCH,
+				    WM9081_LINEOUT_DISCH);
 		break;
 	}
 
@@ -1185,7 +1233,7 @@
 	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 	 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm9081_dai_ops = {
+static const struct snd_soc_dai_ops wm9081_dai_ops = {
 	.hw_params = wm9081_hw_params,
 	.set_fmt = wm9081_set_dai_fmt,
 	.digital_mute = wm9081_digital_mute,
@@ -1213,25 +1261,14 @@
 	int ret;
 	u16 reg;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
+	codec->control_data = wm9081->regmap;
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
 	}
 
-	reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
-	if (reg != 0x9081) {
-		dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
-		ret = -EINVAL;
-		return ret;
-	}
-
-	ret = wm9081_reset(codec);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to issue reset\n");
-		return ret;
-	}
-
 	reg = 0;
 	if (wm9081->pdata.irq_high)
 		reg |= WM9081_IRQ_POL;
@@ -1243,11 +1280,10 @@
 	wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	/* Enable zero cross by default */
-	reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
-	snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
-	reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
-	snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
-		     reg | WM9081_SPKPGAZC);
+	snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
+			    WM9081_LINEOUTZC, WM9081_LINEOUTZC);
+	snd_soc_update_bits(codec, WM9081_ANALOGUE_SPEAKER_PGA,
+			    WM9081_SPKPGAZC, WM9081_SPKPGAZC);
 
 	if (!wm9081->pdata.num_retune_configs) {
 		dev_dbg(codec->dev,
@@ -1266,7 +1302,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm9081_suspend(struct snd_soc_codec *codec)
 {
 	wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1275,15 +1311,9 @@
 
 static int wm9081_resume(struct snd_soc_codec *codec)
 {
-	u16 *reg_cache = codec->reg_cache;
-	int i;
+	struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
 
-	for (i = 0; i < codec->driver->reg_cache_size; i++) {
-		if (i == WM9081_SOFTWARE_RESET)
-			continue;
-
-		snd_soc_write(codec, i, reg_cache[i]);
-	}
+	regcache_sync(wm9081->regmap);
 
 	wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -1303,11 +1333,6 @@
 	.set_sysclk = wm9081_set_sysclk,
 	.set_bias_level = wm9081_set_bias_level,
 
-	.reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults),
-	.reg_word_size = sizeof(u16),
-	.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,
@@ -1316,19 +1341,56 @@
 	.num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths),
 };
 
+static const struct regmap_config wm9081_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+
+	.max_register = WM9081_MAX_REGISTER,
+	.reg_defaults = wm9081_reg,
+	.num_reg_defaults = ARRAY_SIZE(wm9081_reg),
+	.volatile_reg = wm9081_volatile_register,
+	.readable_reg = wm9081_readable_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm9081_priv *wm9081;
+	unsigned int reg;
 	int ret;
 
-	wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
+	wm9081 = devm_kzalloc(&i2c->dev, sizeof(struct wm9081_priv),
+			      GFP_KERNEL);
 	if (wm9081 == NULL)
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm9081);
-	wm9081->control_type = SND_SOC_I2C;
+
+	wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap);
+	if (IS_ERR(wm9081->regmap)) {
+		ret = PTR_ERR(wm9081->regmap);
+		dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, &reg);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+		goto err_regmap;
+	}
+	if (reg != 0x9081) {
+		dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg);
+		ret = -EINVAL;
+		goto err_regmap;
+	}
+
+	ret = wm9081_reset(wm9081->regmap);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to issue reset\n");
+		goto err_regmap;
+	}
 
 	if (dev_get_platdata(&i2c->dev))
 		memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
@@ -1337,14 +1399,23 @@
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm9081, &wm9081_dai, 1);
 	if (ret < 0)
-		kfree(wm9081);
+		goto err_regmap;
+
+	return 0;
+
+err_regmap:
+	regmap_exit(wm9081->regmap);
+err:
+
 	return ret;
 }
 
 static __devexit int wm9081_i2c_remove(struct i2c_client *client)
 {
+	struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
+
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm9081->regmap);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index f94c060..5cb8759 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -604,7 +604,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm9090_suspend(struct snd_soc_codec *codec)
 {
 	wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 646b58d..40c92ea 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -258,7 +258,7 @@
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
 			SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops wm9705_dai_ops = {
+static const struct snd_soc_dai_ops wm9705_dai_ops = {
 	.prepare	= ac97_prepare,
 };
 
@@ -306,7 +306,7 @@
 }
 
 #ifdef CONFIG_PM
-static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int wm9705_soc_suspend(struct snd_soc_codec *codec)
 {
 	soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
 
@@ -406,17 +406,7 @@
 	.remove = __devexit_p(wm9705_remove),
 };
 
-static int __init wm9705_init(void)
-{
-	return platform_driver_register(&wm9705_codec_driver);
-}
-module_init(wm9705_init);
-
-static void __exit wm9705_exit(void)
-{
-	platform_driver_unregister(&wm9705_codec_driver);
-}
-module_exit(wm9705_exit);
+module_platform_driver(wm9705_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM9705 driver");
 MODULE_AUTHOR("Ian Molton");
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 90117f8..b7b31f8 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -505,11 +505,11 @@
 		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
 		SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops wm9712_dai_ops_hifi = {
+static const struct snd_soc_dai_ops wm9712_dai_ops_hifi = {
 	.prepare	= ac97_prepare,
 };
 
-static struct snd_soc_dai_ops wm9712_dai_ops_aux = {
+static const struct snd_soc_dai_ops wm9712_dai_ops_aux = {
 	.prepare	= ac97_aux_prepare,
 };
 
@@ -583,8 +583,7 @@
 	return -EIO;
 }
 
-static int wm9712_soc_suspend(struct snd_soc_codec *codec,
-	pm_message_t state)
+static int wm9712_soc_suspend(struct snd_soc_codec *codec)
 {
 	wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
@@ -694,17 +693,7 @@
 	.remove = __devexit_p(wm9712_remove),
 };
 
-static int __init wm9712_init(void)
-{
-	return platform_driver_register(&wm9712_codec_driver);
-}
-module_init(wm9712_init);
-
-static void __exit wm9712_exit(void)
-{
-	platform_driver_unregister(&wm9712_codec_driver);
-}
-module_exit(wm9712_exit);
+module_platform_driver(wm9712_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
 MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 7167cb6..2b8479b 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1026,19 +1026,19 @@
 	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
 	 SNDRV_PCM_FORMAT_S24_LE)
 
-static struct snd_soc_dai_ops wm9713_dai_ops_hifi = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_hifi = {
 	.prepare	= ac97_hifi_prepare,
 	.set_clkdiv	= wm9713_set_dai_clkdiv,
 	.set_pll	= wm9713_set_dai_pll,
 };
 
-static struct snd_soc_dai_ops wm9713_dai_ops_aux = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_aux = {
 	.prepare	= ac97_aux_prepare,
 	.set_clkdiv	= wm9713_set_dai_clkdiv,
 	.set_pll	= wm9713_set_dai_pll,
 };
 
-static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_voice = {
 	.hw_params	= wm9713_pcm_hw_params,
 	.set_clkdiv	= wm9713_set_dai_clkdiv,
 	.set_pll	= wm9713_set_dai_pll,
@@ -1140,8 +1140,7 @@
 	return 0;
 }
 
-static int wm9713_soc_suspend(struct snd_soc_codec *codec,
-	pm_message_t state)
+static int wm9713_soc_suspend(struct snd_soc_codec *codec)
 {
 	u16 reg;
 
@@ -1277,17 +1276,7 @@
 	.remove = __devexit_p(wm9713_remove),
 };
 
-static int __init wm9713_init(void)
-{
-	return platform_driver_register(&wm9713_codec_driver);
-}
-module_init(wm9713_init);
-
-static void __exit wm9713_exit(void)
-{
-	platform_driver_unregister(&wm9713_codec_driver);
-}
-module_exit(wm9713_exit);
+module_platform_driver(wm9713_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
 MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 48e61e9..2a61094 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/mfd/wm8994/registers.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -611,8 +610,8 @@
 SND_SOC_DAPM_INPUT("IN2RN"),
 SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
-SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
 
 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
 		   in1l_pga, ARRAY_SIZE(in1l_pga)),
@@ -654,6 +653,7 @@
 SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
 		   right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
 
+SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0),
 SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
 		 NULL, 0),
 SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
@@ -789,10 +789,12 @@
 	{ "SPKL Driver", NULL, "VMID" },
 	{ "SPKL Driver", NULL, "SPKL Boost" },
 	{ "SPKL Driver", NULL, "CLK_SYS" },
+	{ "SPKL Driver", NULL, "TSHUT" },
 
 	{ "SPKR Driver", NULL, "VMID" },
 	{ "SPKR Driver", NULL, "SPKR Boost" },
 	{ "SPKR Driver", NULL, "CLK_SYS" },
+	{ "SPKR Driver", NULL, "TSHUT" },
 
 	{ "SPKOUTLP", NULL, "SPKL Driver" },
 	{ "SPKOUTLN", NULL, "SPKL Driver" },
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 300e121..ec18710 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -620,7 +620,7 @@
 
 #define DAVINCI_I2S_RATES	SNDRV_PCM_RATE_8000_96000
 
-static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
+static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
 	.startup	= davinci_i2s_startup,
 	.shutdown	= davinci_i2s_shutdown,
 	.prepare	= davinci_i2s_prepare,
@@ -774,17 +774,7 @@
 	},
 };
 
-static int __init davinci_i2s_init(void)
-{
-	return platform_driver_register(&davinci_mcbsp_driver);
-}
-module_init(davinci_i2s_init);
-
-static void __exit davinci_i2s_exit(void)
-{
-	platform_driver_unregister(&davinci_mcbsp_driver);
-}
-module_exit(davinci_i2s_exit);
+module_platform_driver(davinci_mcbsp_driver);
 
 MODULE_AUTHOR("Vladimir Barinov");
 MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 7173df2..2152ff5 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -813,7 +813,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
+static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
 	.startup	= davinci_mcasp_startup,
 	.trigger	= davinci_mcasp_trigger,
 	.hw_params	= davinci_mcasp_hw_params,
@@ -991,17 +991,7 @@
 	},
 };
 
-static int __init davinci_mcasp_init(void)
-{
-	return platform_driver_register(&davinci_mcasp_driver);
-}
-module_init(davinci_mcasp_init);
-
-static void __exit davinci_mcasp_exit(void)
-{
-	platform_driver_unregister(&davinci_mcasp_driver);
-}
-module_exit(davinci_mcasp_exit);
+module_platform_driver(davinci_mcasp_driver);
 
 MODULE_AUTHOR("Steve Chen");
 MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index d5fe08c..65bff3d 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -886,17 +886,7 @@
 	.remove = __devexit_p(davinci_soc_platform_remove),
 };
 
-static int __init snd_davinci_pcm_init(void)
-{
-	return platform_driver_register(&davinci_pcm_driver);
-}
-module_init(snd_davinci_pcm_init);
-
-static void __exit snd_davinci_pcm_exit(void)
-{
-	platform_driver_unregister(&davinci_pcm_driver);
-}
-module_exit(snd_davinci_pcm_exit);
+module_platform_driver(davinci_pcm_driver);
 
 MODULE_AUTHOR("Vladimir Barinov");
 MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 1f11525..70ce10c 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -183,7 +183,7 @@
 
 #define DAVINCI_VCIF_RATES	SNDRV_PCM_RATE_8000_48000
 
-static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
+static const struct snd_soc_dai_ops davinci_vcif_dai_ops = {
 	.startup	= davinci_vcif_startup,
 	.trigger	= davinci_vcif_trigger,
 	.hw_params	= davinci_vcif_hw_params,
@@ -265,17 +265,7 @@
 	},
 };
 
-static int __init davinci_vcif_init(void)
-{
-	return platform_driver_probe(&davinci_vcif_driver, davinci_vcif_probe);
-}
-module_init(davinci_vcif_init);
-
-static void __exit davinci_vcif_exit(void)
-{
-	platform_driver_unregister(&davinci_vcif_driver);
-}
-module_exit(davinci_vcif_exit);
+module_platform_driver(davinci_vcif_driver);
 
 MODULE_AUTHOR("Miguel Aguilar");
 MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC Voice Codec Interface");
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c
index 51930b6..6b90c75 100644
--- a/sound/soc/ep93xx/edb93xx.c
+++ b/sound/soc/ep93xx/edb93xx.c
@@ -131,17 +131,7 @@
 	.remove		= __devexit_p(edb93xx_remove),
 };
 
-static int __init edb93xx_init(void)
-{
-	return platform_driver_register(&edb93xx_driver);
-}
-module_init(edb93xx_init);
-
-static void __exit edb93xx_exit(void)
-{
-	platform_driver_unregister(&edb93xx_driver);
-}
-module_exit(edb93xx_exit);
+module_platform_driver(edb93xx_driver);
 
 MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
 MODULE_DESCRIPTION("ALSA SoC EDB93xx");
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
index 3cd6158..0678637 100644
--- a/sound/soc/ep93xx/ep93xx-ac97.c
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -330,7 +330,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
+static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
 	.startup	= ep93xx_ac97_startup,
 	.trigger	= ep93xx_ac97_trigger,
 };
@@ -449,17 +449,7 @@
 	},
 };
 
-static int __init ep93xx_ac97_init(void)
-{
-	return platform_driver_register(&ep93xx_ac97_driver);
-}
-module_init(ep93xx_ac97_init);
-
-static void __exit ep93xx_ac97_exit(void)
-{
-	platform_driver_unregister(&ep93xx_ac97_driver);
-}
-module_exit(ep93xx_ac97_exit);
+module_platform_driver(ep93xx_ac97_driver);
 
 MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index 099614e..f7a6234 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -338,7 +338,7 @@
 #define ep93xx_i2s_resume	NULL
 #endif
 
-static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
 	.startup	= ep93xx_i2s_startup,
 	.shutdown	= ep93xx_i2s_shutdown,
 	.hw_params	= ep93xx_i2s_hw_params,
@@ -464,18 +464,7 @@
 	},
 };
 
-static int __init ep93xx_i2s_init(void)
-{
-	return platform_driver_register(&ep93xx_i2s_driver);
-}
-
-static void __exit ep93xx_i2s_exit(void)
-{
-	platform_driver_unregister(&ep93xx_i2s_driver);
-}
-
-module_init(ep93xx_i2s_init);
-module_exit(ep93xx_i2s_exit);
+module_platform_driver(ep93xx_i2s_driver);
 
 MODULE_ALIAS("platform:ep93xx-i2s");
 MODULE_AUTHOR("Ryan Mallon");
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index d00230a..a2de9c4 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -339,18 +339,7 @@
 	.remove = __devexit_p(ep93xx_soc_platform_remove),
 };
 
-static int __init ep93xx_soc_platform_init(void)
-{
-	return platform_driver_register(&ep93xx_pcm_driver);
-}
-
-static void __exit ep93xx_soc_platform_exit(void)
-{
-	platform_driver_unregister(&ep93xx_pcm_driver);
-}
-
-module_init(ep93xx_soc_platform_init);
-module_exit(ep93xx_soc_platform_exit);
+module_platform_driver(ep93xx_pcm_driver);
 
 MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/ep93xx/simone.c
index 968cb31..1e00b33 100644
--- a/sound/soc/ep93xx/simone.c
+++ b/sound/soc/ep93xx/simone.c
@@ -81,17 +81,7 @@
 	.remove		= __devexit_p(simone_remove),
 };
 
-static int __init simone_init(void)
-{
-	return platform_driver_register(&simone_driver);
-}
-module_init(simone_init);
-
-static void __exit simone_exit(void)
-{
-	platform_driver_unregister(&simone_driver);
-}
-module_exit(simone_exit);
+module_platform_driver(simone_driver);
 
 MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index 2cde433..33901d6 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -147,18 +147,7 @@
 	.remove		= __devexit_p(snappercl15_remove),
 };
 
-static int __init snappercl15_init(void)
-{
-	return platform_driver_register(&snappercl15_driver);
-}
-
-static void __exit snappercl15_exit(void)
-{
-	platform_driver_unregister(&snappercl15_driver);
-}
-
-module_init(snappercl15_init);
-module_exit(snappercl15_exit);
+module_platform_driver(snappercl15_driver);
 
 MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("ALSA SoC Snapper CL15");
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index ef15402..4f59bba 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -992,20 +992,7 @@
 	.remove = __devexit_p(fsl_soc_dma_remove),
 };
 
-static int __init fsl_soc_dma_init(void)
-{
-	pr_info("Freescale Elo DMA ASoC PCM Driver\n");
-
-	return platform_driver_register(&fsl_soc_dma_driver);
-}
-
-static void __exit fsl_soc_dma_exit(void)
-{
-	platform_driver_unregister(&fsl_soc_dma_driver);
-}
-
-module_init(fsl_soc_dma_init);
-module_exit(fsl_soc_dma_exit);
+module_platform_driver(fsl_soc_dma_driver);
 
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
 MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver");
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 83c4bd5..3e06696 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -514,7 +514,7 @@
 	}
 }
 
-static struct snd_soc_dai_ops fsl_ssi_dai_ops = {
+static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
 	.startup	= fsl_ssi_startup,
 	.hw_params	= fsl_ssi_hw_params,
 	.shutdown	= fsl_ssi_shutdown,
@@ -793,20 +793,7 @@
 	.remove = fsl_ssi_remove,
 };
 
-static int __init fsl_ssi_init(void)
-{
-	printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
-
-	return platform_driver_register(&fsl_ssi_driver);
-}
-
-static void __exit fsl_ssi_exit(void)
-{
-	platform_driver_unregister(&fsl_ssi_driver);
-}
-
-module_init(fsl_ssi_init);
-module_exit(fsl_ssi_exit);
+module_platform_driver(fsl_ssi_driver);
 
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
 MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 5c6c245..e7803d3 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -526,17 +526,7 @@
 	}
 };
 
-static int __init mpc5200_hpcd_init(void)
-{
-	return platform_driver_register(&mpc5200_hpcd_of_driver);
-}
-module_init(mpc5200_hpcd_init);
-
-static void __exit mpc5200_hpcd_exit(void)
-{
-	platform_driver_unregister(&mpc5200_hpcd_of_driver);
-}
-module_exit(mpc5200_hpcd_exit);
+module_platform_driver(mpc5200_hpcd_of_driver);
 
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index ad36b09..ffa00a2 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -226,12 +226,12 @@
 /**
  * psc_ac97_dai_template: template CPU Digital Audio Interface
  */
-static struct snd_soc_dai_ops psc_ac97_analog_ops = {
+static const struct snd_soc_dai_ops psc_ac97_analog_ops = {
 	.hw_params	= psc_ac97_hw_analog_params,
 	.trigger	= psc_ac97_trigger,
 };
 
-static struct snd_soc_dai_ops psc_ac97_digital_ops = {
+static const struct snd_soc_dai_ops psc_ac97_digital_ops = {
 	.hw_params	= psc_ac97_hw_digital_params,
 };
 
@@ -325,21 +325,7 @@
 	},
 };
 
-/* ---------------------------------------------------------------------
- * Module setup and teardown; simply register the of_platform driver
- * for the PSC in AC97 mode.
- */
-static int __init psc_ac97_init(void)
-{
-	return platform_driver_register(&psc_ac97_driver);
-}
-module_init(psc_ac97_init);
-
-static void __exit psc_ac97_exit(void)
-{
-	platform_driver_unregister(&psc_ac97_driver);
-}
-module_exit(psc_ac97_exit);
+module_platform_driver(psc_ac97_driver);
 
 MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
 MODULE_DESCRIPTION("mpc5200 AC97 module");
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 87cf2a5..7b53032 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -123,7 +123,7 @@
 /**
  * psc_i2s_dai_template: template CPU Digital Audio Interface
  */
-static struct snd_soc_dai_ops psc_i2s_dai_ops = {
+static const struct snd_soc_dai_ops psc_i2s_dai_ops = {
 	.hw_params	= psc_i2s_hw_params,
 	.set_sysclk	= psc_i2s_set_sysclk,
 	.set_fmt	= psc_i2s_set_fmt,
@@ -222,21 +222,7 @@
 	},
 };
 
-/* ---------------------------------------------------------------------
- * Module setup and teardown; simply register the of_platform driver
- * for the PSC in I2S mode.
- */
-static int __init psc_i2s_init(void)
-{
-	return platform_driver_register(&psc_i2s_driver);
-}
-module_init(psc_i2s_init);
-
-static void __exit psc_i2s_exit(void)
-{
-	platform_driver_unregister(&psc_i2s_driver);
-}
-module_exit(psc_i2s_exit);
+module_platform_driver(psc_i2s_driver);
 
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver");
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index ae49f1c..0ea4a5a 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
+#include <linux/of_i2c.h>
 #include <sound/soc.h>
 #include <asm/fsl_guts.h>
 
@@ -249,8 +250,9 @@
 static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 {
 	const u32 *iprop;
-	int bus, addr;
+	int addr;
 	char temp[DAI_NAME_SIZE];
+	struct i2c_client *i2c;
 
 	of_modalias_node(np, temp, DAI_NAME_SIZE);
 
@@ -260,11 +262,12 @@
 
 	addr = be32_to_cpup(iprop);
 
-	bus = get_parent_cell_index(np);
-	if (bus < 0)
-		return bus;
+	/* We need the adapter number */
+	i2c = of_find_i2c_device_by_node(np);
+	if (!i2c)
+		return -ENODEV;
 
-	snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
+	snprintf(buf, len, "%s-codec.%u-%04x", temp, i2c->adapter->nr, addr);
 
 	return 0;
 }
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 2c064a9..a5d4e80 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
+#include <linux/of_i2c.h>
 #include <sound/soc.h>
 #include <asm/fsl_guts.h>
 
@@ -252,8 +253,9 @@
 static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 {
 	const u32 *iprop;
-	int bus, addr;
+	int addr;
 	char temp[DAI_NAME_SIZE];
+	struct i2c_client *i2c;
 
 	of_modalias_node(np, temp, DAI_NAME_SIZE);
 
@@ -263,11 +265,12 @@
 
 	addr = be32_to_cpup(iprop);
 
-	bus = get_parent_cell_index(np);
-	if (bus < 0)
-		return bus;
+	/* We need the adapter number */
+	i2c = of_find_i2c_device_by_node(np);
+	if (!i2c)
+		return -ENODEV;
 
-	snprintf(buf, len, "%s.%u-%04x", temp, bus, addr);
+	snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
 
 	return 0;
 }
@@ -540,12 +543,6 @@
 	.probe = p1022_ds_probe,
 	.remove = __devexit_p(p1022_ds_remove),
 	.driver = {
-		/* The name must match the 'model' property in the device tree,
-		 * in lowercase letters, but only the part after that last
-		 * comma.  This is because some model properties have a "fsl,"
-		 * prefix.
-		 */
-		.name = "snd-soc-p1022",
 		.owner = THIS_MODULE,
 	},
 };
@@ -559,13 +556,39 @@
 {
 	struct device_node *guts_np;
 	struct resource res;
+	const char *sprop;
 
-	pr_info("Freescale P1022 DS ALSA SoC machine driver\n");
+	/*
+	 * Check if we're actually running on a P1022DS.  Older device trees
+	 * have a model of "fsl,P1022" and newer ones use "fsl,P1022DS", so we
+	 * need to support both.  The SSI driver uses that property to link to
+	 * the machine driver, so have to match it.
+	 */
+	sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
+	if (!sprop) {
+		pr_err("snd-soc-p1022ds: missing /model node");
+		return -ENODEV;
+	}
+
+	pr_debug("snd-soc-p1022ds: board model name is %s\n", sprop);
+
+	/*
+	 * The name of this board, taken from the device tree.  Normally, this is a*
+	 * fixed string, but some P1022DS device trees have a /model property of
+	 * "fsl,P1022", and others have "fsl,P1022DS".
+	 */
+	if (strcasecmp(sprop, "fsl,p1022ds") == 0)
+		p1022_ds_driver.driver.name = "snd-soc-p1022ds";
+	else if (strcasecmp(sprop, "fsl,p1022") == 0)
+		p1022_ds_driver.driver.name = "snd-soc-p1022";
+	else
+		return -ENODEV;
 
 	/* Get the physical address of the global utilities registers */
 	guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
 	if (of_address_to_resource(guts_np, 0, &res)) {
-		pr_err("p1022-ds: missing/invalid global utilities node\n");
+		pr_err("snd-soc-p1022ds: missing/invalid global utils node\n");
+		of_node_put(guts_np);
 		return -EINVAL;
 	}
 	guts_phys = res.start;
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 43fdc24f..1cf2fe8 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -326,16 +326,6 @@
 	.remove = __devexit_p(imx_soc_platform_remove),
 };
 
-static int __init snd_imx_pcm_init(void)
-{
-	return platform_driver_register(&imx_pcm_driver);
-}
-module_init(snd_imx_pcm_init);
-
-static void __exit snd_imx_pcm_exit(void)
-{
-	platform_driver_unregister(&imx_pcm_driver);
-}
-module_exit(snd_imx_pcm_exit);
+module_platform_driver(imx_pcm_driver);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:imx-pcm-audio");
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index 8df0fae2..d7ea0b3 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -331,14 +331,4 @@
 	.remove = __devexit_p(imx_soc_platform_remove),
 };
 
-static int __init snd_imx_pcm_init(void)
-{
-	return platform_driver_register(&imx_pcm_driver);
-}
-module_init(snd_imx_pcm_init);
-
-static void __exit snd_imx_pcm_exit(void)
-{
-	platform_driver_unregister(&imx_pcm_driver);
-}
-module_exit(snd_imx_pcm_exit);
+module_platform_driver(imx_pcm_driver);
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 4c05e2b..01d1f74 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -342,7 +342,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
+static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
 	.hw_params	= imx_ssi_hw_params,
 	.set_fmt	= imx_ssi_set_dai_fmt,
 	.set_clkdiv	= imx_ssi_set_dai_clkdiv,
@@ -757,18 +757,7 @@
 	},
 };
 
-static int __init imx_ssi_init(void)
-{
-	return platform_driver_register(&imx_ssi_driver);
-}
-
-static void __exit imx_ssi_exit(void)
-{
-	platform_driver_unregister(&imx_ssi_driver);
-}
-
-module_init(imx_ssi_init);
-module_exit(imx_ssi_exit);
+module_platform_driver(imx_ssi_driver);
 
 /* Module information */
 MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index cd22a54..a5af7c4 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -392,7 +392,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
+static const struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
 	.startup = jz4740_i2s_startup,
 	.shutdown = jz4740_i2s_shutdown,
 	.trigger = jz4740_i2s_trigger,
@@ -519,17 +519,7 @@
 	},
 };
 
-static int __init jz4740_i2s_init(void)
-{
-	return platform_driver_register(&jz4740_i2s_driver);
-}
-module_init(jz4740_i2s_init);
-
-static void __exit jz4740_i2s_exit(void)
-{
-	platform_driver_unregister(&jz4740_i2s_driver);
-}
-module_exit(jz4740_i2s_exit);
+module_platform_driver(jz4740_i2s_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>");
 MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver");
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
index d1989cd..50cda9e 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -356,17 +356,7 @@
 	},
 };
 
-static int __init jz4740_soc_platform_init(void)
-{
-	return platform_driver_register(&jz4740_pcm_driver);
-}
-module_init(jz4740_soc_platform_init);
-
-static void __exit jz4740_soc_platform_exit(void)
-{
-	return platform_driver_unregister(&jz4740_pcm_driver);
-}
-module_exit(jz4740_soc_platform_exit);
+module_platform_driver(jz4740_pcm_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index cd33de1..2104382 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -388,17 +388,7 @@
 	.remove = __devexit_p(kirkwood_soc_platform_remove),
 };
 
-static int __init kirkwood_pcm_init(void)
-{
-	return platform_driver_register(&kirkwood_pcm_driver);
-}
-module_init(kirkwood_pcm_init);
-
-static void __exit kirkwood_pcm_exit(void)
-{
-	platform_driver_unregister(&kirkwood_pcm_driver);
-}
-module_exit(kirkwood_pcm_exit);
+module_platform_driver(kirkwood_pcm_driver);
 
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module");
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 715e841..f6bb211 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -373,7 +373,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
+static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
 	.startup	= kirkwood_i2s_startup,
 	.trigger	= kirkwood_i2s_trigger,
 	.hw_params      = kirkwood_i2s_hw_params,
@@ -483,17 +483,7 @@
 	},
 };
 
-static int __init kirkwood_i2s_init(void)
-{
-	return platform_driver_register(&kirkwood_i2s_driver);
-}
-module_init(kirkwood_i2s_init);
-
-static void __exit kirkwood_i2s_exit(void)
-{
-	platform_driver_unregister(&kirkwood_i2s_driver);
-}
-module_exit(kirkwood_i2s_exit);
+module_platform_driver(kirkwood_i2s_driver);
 
 /* Module information */
 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index cca693a..e53f8e4 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -428,19 +428,7 @@
 	.remove = __devexit_p(snd_mfld_mc_remove),
 };
 
-static int __init snd_mfld_driver_init(void)
-{
-	pr_debug("snd_mfld_driver_init called\n");
-	return platform_driver_register(&snd_mfld_mc_driver);
-}
-module_init(snd_mfld_driver_init);
-
-static void __exit snd_mfld_driver_exit(void)
-{
-	pr_debug("snd_mfld_driver_exit called\n");
-	platform_driver_unregister(&snd_mfld_mc_driver);
-}
-module_exit(snd_mfld_driver_exit);
+module_platform_driver(snd_mfld_mc_driver);
 
 MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
index 2305702..94f70b3 100644
--- a/sound/soc/mid-x86/sst_platform.c
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -472,19 +472,7 @@
 	.remove		= sst_platform_remove,
 };
 
-static int __init sst_soc_platform_init(void)
-{
-	pr_debug("sst_soc_platform_init called\n");
-	return platform_driver_register(&sst_platform_driver);
-}
-module_init(sst_soc_platform_init);
-
-static void __exit sst_soc_platform_exit(void)
-{
-	platform_driver_unregister(&sst_platform_driver);
-	pr_debug("sst_soc_platform_exit success\n");
-}
-module_exit(sst_soc_platform_exit);
+module_platform_driver(sst_platform_driver);
 
 MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index dea5aa4..612ad3d 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -346,14 +346,4 @@
 	.remove = __devexit_p(mxs_soc_platform_remove),
 };
 
-static int __init snd_mxs_pcm_init(void)
-{
-	return platform_driver_register(&mxs_pcm_driver);
-}
-module_init(snd_mxs_pcm_init);
-
-static void __exit snd_mxs_pcm_exit(void)
-{
-	platform_driver_unregister(&mxs_pcm_driver);
-}
-module_exit(snd_mxs_pcm_exit);
+module_platform_driver(mxs_pcm_driver);
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 76dc74d..1a13ab8 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -550,7 +550,7 @@
 	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 	SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops mxs_saif_dai_ops = {
+static const struct snd_soc_dai_ops mxs_saif_dai_ops = {
 	.startup = mxs_saif_startup,
 	.trigger = mxs_saif_trigger,
 	.prepare = mxs_saif_prepare,
@@ -781,18 +781,8 @@
 	},
 };
 
-static int __init mxs_saif_init(void)
-{
-	return platform_driver_register(&mxs_saif_driver);
-}
+module_platform_driver(mxs_saif_driver);
 
-static void __exit mxs_saif_exit(void)
-{
-	platform_driver_unregister(&mxs_saif_driver);
-}
-
-module_init(mxs_saif_init);
-module_exit(mxs_saif_exit);
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ASoC SAIF driver");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 7fbeaec..200a928 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -156,17 +156,7 @@
 	.remove = __devexit_p(mxs_sgtl5000_remove),
 };
 
-static int __init mxs_sgtl5000_init(void)
-{
-	return platform_driver_register(&mxs_sgtl5000_audio_driver);
-}
-module_init(mxs_sgtl5000_init);
-
-static void __exit mxs_sgtl5000_exit(void)
-{
-	platform_driver_unregister(&mxs_sgtl5000_audio_driver);
-}
-module_exit(mxs_sgtl5000_exit);
+module_platform_driver(mxs_sgtl5000_audio_driver);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ALSA SoC Machine driver");
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index 9c0edad..f0c7904 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -291,7 +291,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
+static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
 	.trigger	= nuc900_ac97_trigger,
 };
 
@@ -405,18 +405,7 @@
 	.remove		= __devexit_p(nuc900_ac97_drvremove),
 };
 
-static int __init nuc900_ac97_init(void)
-{
-	return platform_driver_register(&nuc900_ac97_driver);
-}
-
-static void __exit nuc900_ac97_exit(void)
-{
-	platform_driver_unregister(&nuc900_ac97_driver);
-}
-
-module_init(nuc900_ac97_init);
-module_exit(nuc900_ac97_exit);
+module_platform_driver(nuc900_ac97_driver);
 
 MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
 MODULE_DESCRIPTION("NUC900 AC97 SoC driver!");
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
index ae8d680..37585b4 100644
--- a/sound/soc/nuc900/nuc900-pcm.c
+++ b/sound/soc/nuc900/nuc900-pcm.c
@@ -358,17 +358,7 @@
 	.remove = __devexit_p(nuc900_soc_platform_remove),
 };
 
-static int __init nuc900_pcm_init(void)
-{
-	return platform_driver_register(&nuc900_pcm_driver);
-}
-module_init(nuc900_pcm_init);
-
-static void __exit nuc900_pcm_exit(void)
-{
-	platform_driver_unregister(&nuc900_pcm_driver);
-}
-module_exit(nuc900_pcm_exit);
+module_platform_driver(nuc900_pcm_driver);
 
 MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>");
 MODULE_DESCRIPTION("nuc900 Audio DMA module");
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index fe83d0d..fb1bf258 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -2,6 +2,9 @@
 	tristate "SoC Audio for the Texas Instruments OMAP chips"
 	depends on ARCH_OMAP
 
+config SND_OMAP_SOC_DMIC
+	tristate
+
 config SND_OMAP_SOC_MCBSP
 	tristate
 	select OMAP_MCBSP
@@ -97,8 +100,10 @@
 config SND_OMAP_SOC_SDP4430
 	tristate "SoC Audio support for Texas Instruments SDP4430"
 	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_4430SDP
+	select SND_OMAP_SOC_DMIC
 	select SND_OMAP_SOC_MCPDM
 	select SND_SOC_TWL6040
+	select SND_SOC_DMIC
 	help
 	  Say Y if you want to add support for SoC audio on Texas Instruments
 	  SDP4430.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 052fd75..1fd723f 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -1,10 +1,12 @@
 # OMAP Platform Support
 snd-soc-omap-objs := omap-pcm.o
+snd-soc-omap-dmic-objs := omap-dmic.o
 snd-soc-omap-mcbsp-objs := omap-mcbsp.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
+obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o
 obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
 obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
 obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index ccb8a6a..a04a433 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -474,7 +474,7 @@
 }
 
 /* Our codec DAI probably doesn't have its own .ops structure */
-static struct snd_soc_dai_ops ams_delta_dai_ops = {
+static const struct snd_soc_dai_ops ams_delta_dai_ops = {
 	.digital_mute = ams_delta_digital_mute,
 };
 
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
new file mode 100644
index 0000000..9c73c0c
--- /dev/null
+++ b/sound/soc/omap/omap-dmic.c
@@ -0,0 +1,549 @@
+/*
+ * omap-dmic.c  --  OMAP ASoC DMIC DAI driver
+ *
+ * Copyright (C) 2010 - 2011 Texas Instruments
+ *
+ * Author: David Lambert <dlambert@ti.com>
+ *	   Misael Lopez Cruz <misael.lopez@ti.com>
+ *	   Liam Girdwood <lrg@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
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <plat/dma.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "omap-pcm.h"
+#include "omap-dmic.h"
+
+struct omap_dmic {
+	struct device *dev;
+	void __iomem *io_base;
+	struct clk *fclk;
+	int fclk_freq;
+	int out_freq;
+	int clk_div;
+	int sysclk;
+	int threshold;
+	u32 ch_enabled;
+	bool active;
+	struct mutex mutex;
+};
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
+	.name		= "DMIC capture",
+	.data_type	= OMAP_DMA_DATA_TYPE_S32,
+	.sync_mode	= OMAP_DMA_SYNC_PACKET,
+};
+
+static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
+{
+	__raw_writel(val, dmic->io_base + reg);
+}
+
+static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
+{
+	return __raw_readl(dmic->io_base + reg);
+}
+
+static inline void omap_dmic_start(struct omap_dmic *dmic)
+{
+	u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+
+	/* Configure DMA controller */
+	omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG,
+			OMAP_DMIC_DMA_ENABLE);
+
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled);
+}
+
+static inline void omap_dmic_stop(struct omap_dmic *dmic)
+{
+	u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
+			ctrl & ~OMAP_DMIC_UP_ENABLE_MASK);
+
+	/* Disable DMA request generation */
+	omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG,
+			OMAP_DMIC_DMA_ENABLE);
+
+}
+
+static inline int dmic_is_enabled(struct omap_dmic *dmic)
+{
+	return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) &
+						OMAP_DMIC_UP_ENABLE_MASK;
+}
+
+static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+	int ret = 0;
+
+	mutex_lock(&dmic->mutex);
+
+	if (!dai->active) {
+		pm_runtime_get_sync(dmic->dev);
+		snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
+		dmic->active = 1;
+	} else {
+		ret = -EBUSY;
+	}
+
+	mutex_unlock(&dmic->mutex);
+
+	return ret;
+}
+
+static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	mutex_lock(&dmic->mutex);
+
+	if (!dai->active) {
+		pm_runtime_put_sync(dmic->dev);
+		dmic->active = 0;
+	}
+
+	mutex_unlock(&dmic->mutex);
+}
+
+static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate)
+{
+	int divider = -EINVAL;
+
+	/*
+	 * 192KHz rate is only supported with 19.2MHz/3.84MHz clock
+	 * configuration.
+	 */
+	if (sample_rate == 192000) {
+		if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000)
+			divider = 0x6; /* Divider: 5 (192KHz sampling rate) */
+		else
+			dev_err(dmic->dev,
+				"invalid clock configuration for 192KHz\n");
+
+		return divider;
+	}
+
+	switch (dmic->out_freq) {
+	case 1536000:
+		if (dmic->fclk_freq != 24576000)
+			goto div_err;
+		divider = 0x4; /* Divider: 16 */
+		break;
+	case 2400000:
+		switch (dmic->fclk_freq) {
+		case 12000000:
+			divider = 0x5; /* Divider: 5 */
+			break;
+		case 19200000:
+			divider = 0x0; /* Divider: 8 */
+			break;
+		case 24000000:
+			divider = 0x2; /* Divider: 10 */
+			break;
+		default:
+			goto div_err;
+		}
+		break;
+	case 3072000:
+		if (dmic->fclk_freq != 24576000)
+			goto div_err;
+		divider = 0x3; /* Divider: 8 */
+		break;
+	case 3840000:
+		if (dmic->fclk_freq != 19200000)
+			goto div_err;
+		divider = 0x1; /* Divider: 5 (96KHz sampling rate) */
+		break;
+	default:
+		dev_err(dmic->dev, "invalid out frequency: %dHz\n",
+			dmic->out_freq);
+		break;
+	}
+
+	return divider;
+
+div_err:
+	dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n",
+		dmic->out_freq, dmic->fclk_freq);
+	return -EINVAL;
+}
+
+static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params,
+				    struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+	int channels;
+
+	dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
+	if (dmic->clk_div < 0) {
+		dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n",
+			dmic->out_freq, dmic->fclk_freq);
+		return -EINVAL;
+	}
+
+	dmic->ch_enabled = 0;
+	channels = params_channels(params);
+	switch (channels) {
+	case 6:
+		dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE;
+	case 4:
+		dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE;
+	case 2:
+		dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE;
+		break;
+	default:
+		dev_err(dmic->dev, "invalid number of legacy channels\n");
+		return -EINVAL;
+	}
+
+	/* packet size is threshold * channels */
+	omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels;
+	snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params);
+
+	return 0;
+}
+
+static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+	u32 ctrl;
+
+	/* Configure uplink threshold */
+	omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
+
+	ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+
+	/* Set dmic out format */
+	ctrl &= ~(OMAP_DMIC_FORMAT | OMAP_DMIC_POLAR_MASK);
+	ctrl |= (OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
+		 OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
+
+	/* Configure dmic clock divider */
+	ctrl &= ~OMAP_DMIC_CLK_DIV_MASK;
+	ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div);
+
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl);
+
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
+			ctrl | OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
+			OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
+
+	return 0;
+}
+
+static int omap_dmic_dai_trigger(struct snd_pcm_substream *substream,
+				  int cmd, struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		omap_dmic_start(dmic);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		omap_dmic_stop(dmic);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
+				 unsigned int freq)
+{
+	struct clk *parent_clk;
+	char *parent_clk_name;
+	int ret = 0;
+
+	switch (freq) {
+	case 12000000:
+	case 19200000:
+	case 24000000:
+	case 24576000:
+		break;
+	default:
+		dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq);
+		dmic->fclk_freq = 0;
+		return -EINVAL;
+	}
+
+	if (dmic->sysclk == clk_id) {
+		dmic->fclk_freq = freq;
+		return 0;
+	}
+
+	/* re-parent not allowed if a stream is ongoing */
+	if (dmic->active && dmic_is_enabled(dmic)) {
+		dev_err(dmic->dev, "can't re-parent when DMIC active\n");
+		return -EBUSY;
+	}
+
+	switch (clk_id) {
+	case OMAP_DMIC_SYSCLK_PAD_CLKS:
+		parent_clk_name = "pad_clks_ck";
+		break;
+	case OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS:
+		parent_clk_name = "slimbus_clk";
+		break;
+	case OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS:
+		parent_clk_name = "dmic_sync_mux_ck";
+		break;
+	default:
+		dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id);
+		return -EINVAL;
+	}
+
+	parent_clk = clk_get(dmic->dev, parent_clk_name);
+	if (IS_ERR(parent_clk)) {
+		dev_err(dmic->dev, "can't get %s\n", parent_clk_name);
+		return -ENODEV;
+	}
+
+	mutex_lock(&dmic->mutex);
+	if (dmic->active) {
+		/* disable clock while reparenting */
+		pm_runtime_put_sync(dmic->dev);
+		ret = clk_set_parent(dmic->fclk, parent_clk);
+		pm_runtime_get_sync(dmic->dev);
+	} else {
+		ret = clk_set_parent(dmic->fclk, parent_clk);
+	}
+	mutex_unlock(&dmic->mutex);
+
+	if (ret < 0) {
+		dev_err(dmic->dev, "re-parent failed\n");
+		goto err_busy;
+	}
+
+	dmic->sysclk = clk_id;
+	dmic->fclk_freq = freq;
+
+err_busy:
+	clk_put(parent_clk);
+
+	return ret;
+}
+
+static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id,
+				    unsigned int freq)
+{
+	int ret = 0;
+
+	if (clk_id != OMAP_DMIC_ABE_DMIC_CLK) {
+		dev_err(dmic->dev, "output clk_id (%d) not supported\n",
+			clk_id);
+		return -EINVAL;
+	}
+
+	switch (freq) {
+	case 1536000:
+	case 2400000:
+	case 3072000:
+	case 3840000:
+		dmic->out_freq = freq;
+		break;
+	default:
+		dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq);
+		dmic->out_freq = 0;
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int omap_dmic_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+				    unsigned int freq, int dir)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	if (dir == SND_SOC_CLOCK_IN)
+		return omap_dmic_select_fclk(dmic, clk_id, freq);
+	else if (dir == SND_SOC_CLOCK_OUT)
+		return omap_dmic_select_outclk(dmic, clk_id, freq);
+
+	dev_err(dmic->dev, "invalid clock direction (%d)\n", dir);
+	return -EINVAL;
+}
+
+static const struct snd_soc_dai_ops omap_dmic_dai_ops = {
+	.startup	= omap_dmic_dai_startup,
+	.shutdown	= omap_dmic_dai_shutdown,
+	.hw_params	= omap_dmic_dai_hw_params,
+	.prepare	= omap_dmic_dai_prepare,
+	.trigger	= omap_dmic_dai_trigger,
+	.set_sysclk	= omap_dmic_set_dai_sysclk,
+};
+
+static int omap_dmic_probe(struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	pm_runtime_enable(dmic->dev);
+
+	/* Disable lines while request is ongoing */
+	pm_runtime_get_sync(dmic->dev);
+	omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00);
+	pm_runtime_put_sync(dmic->dev);
+
+	/* Configure DMIC threshold value */
+	dmic->threshold = OMAP_DMIC_THRES_MAX - 3;
+	return 0;
+}
+
+static int omap_dmic_remove(struct snd_soc_dai *dai)
+{
+	struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+	pm_runtime_disable(dmic->dev);
+
+	return 0;
+}
+
+static struct snd_soc_dai_driver omap_dmic_dai = {
+	.name = "omap-dmic",
+	.probe = omap_dmic_probe,
+	.remove = omap_dmic_remove,
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 6,
+		.rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+	},
+	.ops = &omap_dmic_dai_ops,
+};
+
+static __devinit int asoc_dmic_probe(struct platform_device *pdev)
+{
+	struct omap_dmic *dmic;
+	struct resource *res;
+	int ret;
+
+	dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL);
+	if (!dmic)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, dmic);
+	dmic->dev = &pdev->dev;
+	dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS;
+
+	mutex_init(&dmic->mutex);
+
+	dmic->fclk = clk_get(dmic->dev, "dmic_fck");
+	if (IS_ERR(dmic->fclk)) {
+		dev_err(dmic->dev, "cant get dmic_fck\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+	if (!res) {
+		dev_err(dmic->dev, "invalid dma memory resource\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+	omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG;
+
+	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!res) {
+		dev_err(dmic->dev, "invalid dma resource\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+	omap_dmic_dai_dma_params.dma_req = res->start;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+	if (!res) {
+		dev_err(dmic->dev, "invalid memory resource\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res), pdev->name)) {
+		dev_err(dmic->dev, "memory region already claimed\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+
+	dmic->io_base = devm_ioremap(&pdev->dev, res->start,
+				     resource_size(res));
+	if (!dmic->io_base) {
+		ret = -ENOMEM;
+		goto err_put_clk;
+	}
+
+	ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai);
+	if (ret)
+		goto err_put_clk;
+
+	return 0;
+
+err_put_clk:
+	clk_put(dmic->fclk);
+	return ret;
+}
+
+static int __devexit asoc_dmic_remove(struct platform_device *pdev)
+{
+	struct omap_dmic *dmic = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_dai(&pdev->dev);
+	clk_put(dmic->fclk);
+
+	return 0;
+}
+
+static struct platform_driver asoc_dmic_driver = {
+	.driver = {
+		.name = "omap-dmic",
+		.owner = THIS_MODULE,
+	},
+	.probe = asoc_dmic_probe,
+	.remove = __devexit_p(asoc_dmic_remove),
+};
+
+module_platform_driver(asoc_dmic_driver);
+
+MODULE_ALIAS("platform:omap-dmic");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_DESCRIPTION("OMAP DMIC ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-dmic.h b/sound/soc/omap/omap-dmic.h
new file mode 100644
index 0000000..231e728
--- /dev/null
+++ b/sound/soc/omap/omap-dmic.h
@@ -0,0 +1,69 @@
+/*
+ * omap-dmic.h  --  OMAP Digital Microphone Controller
+ *
+ * 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 _OMAP_DMIC_H
+#define _OMAP_DMIC_H
+
+#define OMAP_DMIC_REVISION_REG		0x00
+#define OMAP_DMIC_SYSCONFIG_REG		0x10
+#define OMAP_DMIC_IRQSTATUS_RAW_REG	0x24
+#define OMAP_DMIC_IRQSTATUS_REG		0x28
+#define OMAP_DMIC_IRQENABLE_SET_REG	0x2C
+#define OMAP_DMIC_IRQENABLE_CLR_REG	0x30
+#define OMAP_DMIC_IRQWAKE_EN_REG	0x34
+#define OMAP_DMIC_DMAENABLE_SET_REG	0x38
+#define OMAP_DMIC_DMAENABLE_CLR_REG	0x3C
+#define OMAP_DMIC_DMAWAKEEN_REG		0x40
+#define OMAP_DMIC_CTRL_REG		0x44
+#define OMAP_DMIC_DATA_REG		0x48
+#define OMAP_DMIC_FIFO_CTRL_REG		0x4C
+#define OMAP_DMIC_FIFO_DMIC1R_DATA_REG	0x50
+#define OMAP_DMIC_FIFO_DMIC1L_DATA_REG	0x54
+#define OMAP_DMIC_FIFO_DMIC2R_DATA_REG	0x58
+#define OMAP_DMIC_FIFO_DMIC2L_DATA_REG	0x5C
+#define OMAP_DMIC_FIFO_DMIC3R_DATA_REG	0x60
+#define OMAP_DMIC_FIFO_DMIC3L_DATA_REG	0x64
+
+/* IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR bit fields */
+#define OMAP_DMIC_IRQ			(1 << 0)
+#define OMAP_DMIC_IRQ_FULL		(1 << 1)
+#define OMAP_DMIC_IRQ_ALMST_EMPTY	(1 << 2)
+#define OMAP_DMIC_IRQ_EMPTY		(1 << 3)
+#define OMAP_DMIC_IRQ_MASK		0x07
+
+/* DMIC_DMAENABLE bit fields */
+#define OMAP_DMIC_DMA_ENABLE		0x1
+
+/* DMIC_CTRL bit fields */
+#define OMAP_DMIC_UP1_ENABLE		(1 << 0)
+#define OMAP_DMIC_UP2_ENABLE		(1 << 1)
+#define OMAP_DMIC_UP3_ENABLE		(1 << 2)
+#define OMAP_DMIC_UP_ENABLE_MASK	0x7
+#define OMAP_DMIC_FORMAT		(1 << 3)
+#define OMAP_DMIC_POLAR1		(1 << 4)
+#define OMAP_DMIC_POLAR2		(1 << 5)
+#define OMAP_DMIC_POLAR3		(1 << 6)
+#define OMAP_DMIC_POLAR_MASK		(0x7 << 4)
+#define OMAP_DMIC_CLK_DIV(x)		(((x) & 0x7) << 7)
+#define OMAP_DMIC_CLK_DIV_MASK		(0x7 << 7)
+#define	OMAP_DMIC_RESET			(1 << 10)
+
+#define OMAP_DMICOUTFORMAT_LJUST	(0 << 3)
+#define OMAP_DMICOUTFORMAT_RJUST	(1 << 3)
+
+/* DMIC_FIFO_CTRL bit fields */
+#define OMAP_DMIC_THRES_MAX		0xF
+
+enum omap_dmic_clk {
+	OMAP_DMIC_SYSCLK_PAD_CLKS,		/* PAD_CLKS */
+	OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS,		/* SLIMBUS_CLK */
+	OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS,		/* DMIC_SYNC_MUX_CLK */
+	OMAP_DMIC_ABE_DMIC_CLK,			/* abe_dmic_clk */
+};
+
+#endif
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index 36c6eae..38e0def 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -83,7 +83,7 @@
 	return err;
 }
 
-static struct snd_soc_dai_ops omap_hdmi_dai_ops = {
+static const struct snd_soc_dai_ops omap_hdmi_dai_ops = {
 	.startup	= omap_hdmi_dai_startup,
 	.hw_params	= omap_hdmi_dai_hw_params,
 };
@@ -139,17 +139,7 @@
 	.remove = __devexit_p(omap_hdmi_remove),
 };
 
-static int __init hdmi_dai_init(void)
-{
-	return platform_driver_register(&hdmi_dai_driver);
-}
-module_init(hdmi_dai_init);
-
-static void __exit hdmi_dai_exit(void)
-{
-	platform_driver_unregister(&hdmi_dai_driver);
-}
-module_exit(hdmi_dai_exit);
+module_platform_driver(hdmi_dai_driver);
 
 MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
 MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 4314647..bd11d25 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -599,7 +599,7 @@
 	return err;
 }
 
-static struct snd_soc_dai_ops mcbsp_dai_ops = {
+static const struct snd_soc_dai_ops mcbsp_dai_ops = {
 	.startup	= omap_mcbsp_dai_startup,
 	.shutdown	= omap_mcbsp_dai_shutdown,
 	.trigger	= omap_mcbsp_dai_trigger,
@@ -785,17 +785,7 @@
 	.remove = __devexit_p(asoc_mcbsp_remove),
 };
 
-static int __init snd_omap_mcbsp_init(void)
-{
-	return platform_driver_register(&asoc_mcbsp_driver);
-}
-module_init(snd_omap_mcbsp_init);
-
-static void __exit snd_omap_mcbsp_exit(void)
-{
-	platform_driver_unregister(&asoc_mcbsp_driver);
-}
-module_exit(snd_omap_mcbsp_exit);
+module_platform_driver(asoc_mcbsp_driver);
 
 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("OMAP I2S SoC Interface");
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 41d1706..b50ac60 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -367,7 +367,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
+static const struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
 	.startup	= omap_mcpdm_dai_startup,
 	.shutdown	= omap_mcpdm_dai_shutdown,
 	.hw_params	= omap_mcpdm_dai_hw_params,
@@ -520,17 +520,7 @@
 	.remove	= __devexit_p(asoc_mcpdm_remove),
 };
 
-static int __init snd_omap_mcpdm_init(void)
-{
-	return platform_driver_register(&asoc_mcpdm_driver);
-}
-module_init(snd_omap_mcpdm_init);
-
-static void __exit snd_omap_mcpdm_exit(void)
-{
-	platform_driver_unregister(&asoc_mcpdm_driver);
-}
-module_exit(snd_omap_mcpdm_exit);
+module_platform_driver(asoc_mcpdm_driver);
 
 MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
 MODULE_DESCRIPTION("OMAP PDM SoC Interface");
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 6ede7dc..52a0f63 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -433,17 +433,7 @@
 	.remove = __devexit_p(omap_pcm_remove),
 };
 
-static int __init snd_omap_pcm_init(void)
-{
-	return platform_driver_register(&omap_pcm_driver);
-}
-module_init(snd_omap_pcm_init);
-
-static void __exit snd_omap_pcm_exit(void)
-{
-	platform_driver_unregister(&omap_pcm_driver);
-}
-module_exit(snd_omap_pcm_exit);
+module_platform_driver(omap_pcm_driver);
 
 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("OMAP PCM DMA module");
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c
index 8671261..52d471c 100644
--- a/sound/soc/omap/omap4-hdmi-card.c
+++ b/sound/soc/omap/omap4-hdmi-card.c
@@ -112,17 +112,7 @@
 	.remove = __devexit_p(omap4_hdmi_remove),
 };
 
-static int __init omap4_hdmi_init(void)
-{
-	return platform_driver_register(&omap4_hdmi_driver);
-}
-module_init(omap4_hdmi_init);
-
-static void __exit omap4_hdmi_exit(void)
-{
-	platform_driver_unregister(&omap4_hdmi_driver);
-}
-module_exit(omap4_hdmi_exit);
+module_platform_driver(omap4_hdmi_driver);
 
 MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
 MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver");
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index 03d9fa4..2735fa03 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -33,6 +33,7 @@
 #include <plat/hardware.h>
 #include <plat/mux.h>
 
+#include "omap-dmic.h"
 #include "omap-mcpdm.h"
 #include "omap-pcm.h"
 #include "../codecs/twl6040.h"
@@ -67,6 +68,32 @@
 	.hw_params = sdp4430_hw_params,
 };
 
+static int sdp4430_dmic_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;
+	int ret = 0;
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS,
+				     19200000, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set DMIC cpu system clock\n");
+		return ret;
+	}
+	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_ABE_DMIC_CLK, 2400000,
+				     SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		printk(KERN_ERR "can't set DMIC output clock\n");
+		return ret;
+	}
+	return 0;
+}
+
+static struct snd_soc_ops sdp4430_dmic_ops = {
+	.hw_params = sdp4430_dmic_hw_params,
+};
+
 /* Headset jack */
 static struct snd_soc_jack hs_jack;
 
@@ -148,23 +175,59 @@
 	return ret;
 }
 
+static const struct snd_soc_dapm_widget sdp4430_dmic_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Digital Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route dmic_audio_map[] = {
+	{"DMic", NULL, "Digital Mic1 Bias"},
+	{"Digital Mic1 Bias", NULL, "Digital Mic"},
+};
+
+static int sdp4430_dmic_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret;
+
+	ret = snd_soc_dapm_new_controls(dapm, sdp4430_dmic_dapm_widgets,
+				ARRAY_SIZE(sdp4430_dmic_dapm_widgets));
+	if (ret)
+		return ret;
+
+	return snd_soc_dapm_add_routes(dapm, dmic_audio_map,
+				ARRAY_SIZE(dmic_audio_map));
+}
+
 /* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link sdp4430_dai = {
-	.name = "TWL6040",
-	.stream_name = "TWL6040",
-	.cpu_dai_name = "omap-mcpdm",
-	.codec_dai_name = "twl6040-legacy",
-	.platform_name = "omap-pcm-audio",
-	.codec_name = "twl6040-codec",
-	.init = sdp4430_twl6040_init,
-	.ops = &sdp4430_ops,
+static struct snd_soc_dai_link sdp4430_dai[] = {
+	{
+		.name = "TWL6040",
+		.stream_name = "TWL6040",
+		.cpu_dai_name = "omap-mcpdm",
+		.codec_dai_name = "twl6040-legacy",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "twl6040-codec",
+		.init = sdp4430_twl6040_init,
+		.ops = &sdp4430_ops,
+	},
+	{
+		.name = "DMIC",
+		.stream_name = "DMIC Capture",
+		.cpu_dai_name = "omap-dmic",
+		.codec_dai_name = "dmic-hifi",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "dmic-codec",
+		.init = sdp4430_dmic_init,
+		.ops = &sdp4430_dmic_ops,
+	},
 };
 
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_sdp4430 = {
 	.name = "SDP4430",
-	.dai_link = &sdp4430_dai,
-	.num_links = 1,
+	.dai_link = sdp4430_dai,
+	.num_links = ARRAY_SIZE(sdp4430_dai),
 
 	.dapm_widgets = sdp4430_twl6040_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(sdp4430_twl6040_dapm_widgets),
diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c
index 65c1248..e32afaf 100644
--- a/sound/soc/pxa/hx4700.c
+++ b/sound/soc/pxa/hx4700.c
@@ -236,18 +236,7 @@
 	.remove	= __devexit_p(hx4700_audio_remove),
 };
 
-static int __init hx4700_modinit(void)
-{
-	return platform_driver_register(&hx4700_audio_driver);
-}
-module_init(hx4700_modinit);
-
-static void __exit hx4700_modexit(void)
-{
-	platform_driver_unregister(&hx4700_audio_driver);
-}
-
-module_exit(hx4700_modexit);
+module_platform_driver(hx4700_audio_driver);
 
 MODULE_AUTHOR("Philipp Zabel");
 MODULE_DESCRIPTION("ALSA SoC iPAQ hx4700");
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 0b8d1ee..0e73a7f 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -227,18 +227,7 @@
 	},
 };
 
-static int __init mioa701_asoc_init(void)
-{
-	return platform_driver_register(&mioa701_wm9713_driver);
-}
-
-static void __exit mioa701_asoc_exit(void)
-{
-	platform_driver_unregister(&mioa701_wm9713_driver);
-}
-
-module_init(mioa701_asoc_init);
-module_exit(mioa701_asoc_exit);
+module_platform_driver(mioa701_wm9713_driver);
 
 /* Module information */
 MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)");
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 7edc1fb..f313eca 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -201,18 +201,7 @@
 	},
 };
 
-static int __init palm27x_asoc_init(void)
-{
-	return platform_driver_register(&palm27x_wm9712_driver);
-}
-
-static void __exit palm27x_asoc_exit(void)
-{
-	platform_driver_unregister(&palm27x_wm9712_driver);
-}
-
-module_init(palm27x_asoc_init);
-module_exit(palm27x_asoc_exit);
+module_platform_driver(palm27x_wm9712_driver);
 
 /* Module information */
 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 8ad93ee..a57cfbc 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -771,7 +771,7 @@
 			    SNDRV_PCM_FMTBIT_S24_LE |	\
 			    SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ssp_dai_ops = {
 	.startup	= pxa_ssp_startup,
 	.shutdown	= pxa_ssp_shutdown,
 	.trigger	= pxa_ssp_trigger,
@@ -825,17 +825,7 @@
 	.remove = __devexit_p(asoc_ssp_remove),
 };
 
-static int __init pxa_ssp_init(void)
-{
-	return platform_driver_register(&asoc_ssp_driver);
-}
-module_init(pxa_ssp_init);
-
-static void __exit pxa_ssp_exit(void)
-{
-	platform_driver_unregister(&asoc_ssp_driver);
-}
-module_exit(pxa_ssp_exit);
+module_platform_driver(asoc_ssp_driver);
 
 /* Module information */
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index ac51c6d..837ff34 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -163,15 +163,15 @@
 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
 		SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = {
 	.hw_params	= pxa2xx_ac97_hw_params,
 };
 
-static struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = {
 	.hw_params	= pxa2xx_ac97_hw_aux_params,
 };
 
-static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
 	.hw_params	= pxa2xx_ac97_hw_mic_params,
 };
 
@@ -263,17 +263,7 @@
 	},
 };
 
-static int __init pxa_ac97_init(void)
-{
-	return platform_driver_register(&pxa2xx_ac97_driver);
-}
-module_init(pxa_ac97_init);
-
-static void __exit pxa_ac97_exit(void)
-{
-	platform_driver_unregister(&pxa2xx_ac97_driver);
-}
-module_exit(pxa_ac97_exit);
+module_platform_driver(pxa2xx_ac97_driver);
 
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 11be595..609abd5 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -331,7 +331,7 @@
 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
 		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
 
-static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
+static const struct snd_soc_dai_ops pxa_i2s_dai_ops = {
 	.startup	= pxa2xx_i2s_startup,
 	.shutdown	= pxa2xx_i2s_shutdown,
 	.trigger	= pxa2xx_i2s_trigger,
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 600676f..fdd6bed 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -141,17 +141,7 @@
 	.remove = __devexit_p(pxa2xx_soc_platform_remove),
 };
 
-static int __init snd_pxa_pcm_init(void)
-{
-	return platform_driver_register(&pxa_pcm_driver);
-}
-module_init(snd_pxa_pcm_init);
-
-static void __exit snd_pxa_pcm_exit(void)
-{
-	platform_driver_unregister(&pxa_pcm_driver);
-}
-module_exit(snd_pxa_pcm_exit);
+module_platform_driver(pxa_pcm_driver);
 
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index 3052f64..aaabdba 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -409,7 +409,7 @@
 			 SNDRV_PCM_RATE_8000_192000)
 #define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops s6000_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s6000_i2s_dai_ops = {
 	.set_fmt = s6000_i2s_set_dai_fmt,
 	.set_clkdiv = s6000_i2s_set_clkdiv,
 	.hw_params = s6000_i2s_hw_params,
@@ -604,17 +604,7 @@
 	},
 };
 
-static int __init s6000_i2s_init(void)
-{
-	return platform_driver_register(&s6000_i2s_driver);
-}
-module_init(s6000_i2s_init);
-
-static void __exit s6000_i2s_exit(void)
-{
-	platform_driver_unregister(&s6000_i2s_driver);
-}
-module_exit(s6000_i2s_exit);
+module_platform_driver(s6000_i2s_driver);
 
 MODULE_AUTHOR("Daniel Gloeckner");
 MODULE_DESCRIPTION("Stretch s6000 family I2S SoC Interface");
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 55efc2b..43c014f 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -520,17 +520,7 @@
 	.remove = __devexit_p(s6000_soc_platform_remove),
 };
 
-static int __init snd_s6000_pcm_init(void)
-{
-	return platform_driver_register(&s6000_pcm_driver);
-}
-module_init(snd_s6000_pcm_init);
-
-static void __exit snd_s6000_pcm_exit(void)
-{
-	platform_driver_unregister(&s6000_pcm_driver);
-}
-module_exit(snd_s6000_pcm_exit);
+module_platform_driver(s6000_pcm_driver);
 
 MODULE_AUTHOR("Daniel Gloeckner");
 MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 53aaa69..09d636c 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -193,8 +193,21 @@
 	select SND_SOC_WM9081
 	select SND_SOC_WM1250_EV1
 
-config SND_SOC_SPEYSIDE_WM8962
-	tristate "Audio support for Wolfson Speyside with WM8962"
+config SND_SOC_TOBERMORY
+	tristate "Audio support for Wolfson Tobermory"
 	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
 	select SND_SAMSUNG_I2S
 	select SND_SOC_WM8962
+
+config SND_SOC_LOWLAND
+	tristate "Audio support for Wolfson Lowland"
+	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+	select SND_SAMSUNG_I2S
+	select SND_SOC_WM5100
+	select SND_SOC_WM9081
+
+config SND_SOC_LITTLEMILL
+	tristate "Audio support for Wolfson Littlemill"
+	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+	select SND_SAMSUNG_I2S
+	select SND_SOC_WM8994
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 8509d3c..9d03beb 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -39,7 +39,9 @@
 snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o
 snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o
 snd-soc-speyside-objs := speyside.o
-snd-soc-speyside-wm8962-objs := speyside_wm8962.o
+snd-soc-tobermory-objs := tobermory.o
+snd-soc-lowland-objs := lowland.o
+snd-soc-littlemill-objs := littlemill.o
 
 obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -60,4 +62,6 @@
 obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o
 obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o
 obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o
-obj-$(CONFIG_SND_SOC_SPEYSIDE_WM8962) += snd-soc-speyside-wm8962.o
+obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o
+obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
+obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 16521e3..7b9bf93 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -329,12 +329,12 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops s3c_ac97_dai_ops = {
+static const struct snd_soc_dai_ops s3c_ac97_dai_ops = {
 	.hw_params	= s3c_ac97_hw_params,
 	.trigger	= s3c_ac97_trigger,
 };
 
-static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
+static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
 	.hw_params	= s3c_ac97_hw_mic_params,
 	.trigger	= s3c_ac97_mic_trigger,
 };
@@ -509,17 +509,7 @@
 	},
 };
 
-static int __init s3c_ac97_init(void)
-{
-	return platform_driver_register(&s3c_ac97_driver);
-}
-module_init(s3c_ac97_init);
-
-static void __exit s3c_ac97_exit(void)
-{
-	platform_driver_unregister(&s3c_ac97_driver);
-}
-module_exit(s3c_ac97_exit);
+module_platform_driver(s3c_ac97_driver);
 
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
 MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index a68b264..797c3d5 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -458,17 +458,7 @@
 	.remove = __devexit_p(samsung_asoc_platform_remove),
 };
 
-static int __init samsung_asoc_init(void)
-{
-	return platform_driver_register(&asoc_dma_driver);
-}
-module_init(samsung_asoc_init);
-
-static void __exit samsung_asoc_exit(void)
-{
-	platform_driver_unregister(&asoc_dma_driver);
-}
-module_exit(samsung_asoc_exit);
+module_platform_driver(asoc_dma_driver);
 
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index bff42bf..5de500c 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -881,7 +881,7 @@
 		writel(CON_RSTCLR, i2s->addr + I2SCON);
 
 	if (i2s->quirks & QUIRK_SEC_DAI)
-		idma_reg_addr_init((void *)i2s->addr,
+		idma_reg_addr_init(i2s->addr,
 					i2s->sec_dai->idma_playback.dma_addr);
 
 probe_exit:
@@ -923,7 +923,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops samsung_i2s_dai_ops = {
+static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
 	.trigger = i2s_trigger,
 	.hw_params = i2s_hw_params,
 	.set_fmt = i2s_set_fmt,
@@ -1144,17 +1144,7 @@
 	},
 };
 
-static int __init samsung_i2s_init(void)
-{
-	return platform_driver_register(&samsung_i2s_driver);
-}
-module_init(samsung_i2s_init);
-
-static void __exit samsung_i2s_exit(void)
-{
-	platform_driver_unregister(&samsung_i2s_driver);
-}
-module_exit(samsung_i2s_exit);
+module_platform_driver(samsung_i2s_driver);
 
 /* Module information */
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index c41178e..baf97eb 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -403,7 +403,7 @@
 	return ret;
 }
 
-void idma_reg_addr_init(void *regs, dma_addr_t addr)
+void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
 {
 	spin_lock_init(&idma.lock);
 	idma.regs = regs;
@@ -437,17 +437,7 @@
 	.remove = __devexit_p(asoc_idma_platform_remove),
 };
 
-static int __init asoc_idma_init(void)
-{
-	return platform_driver_register(&asoc_idma_driver);
-}
-module_init(asoc_idma_init);
-
-static void __exit asoc_idma_exit(void)
-{
-	platform_driver_unregister(&asoc_idma_driver);
-}
-module_exit(asoc_idma_exit);
+module_platform_driver(asoc_idma_driver);
 
 MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
 MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h
index 4827321..8644946 100644
--- a/sound/soc/samsung/idma.h
+++ b/sound/soc/samsung/idma.h
@@ -14,7 +14,7 @@
 #ifndef __SND_SOC_SAMSUNG_IDMA_H_
 #define __SND_SOC_SAMSUNG_IDMA_H_
 
-extern void idma_reg_addr_init(void *regs, dma_addr_t addr);
+extern void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr);
 
 /* dma_state */
 #define LPAM_DMA_STOP	0
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
new file mode 100644
index 0000000..5cea59b
--- /dev/null
+++ b/sound/soc/samsung/littlemill.c
@@ -0,0 +1,252 @@
+/*
+ * Littlemill audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * 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.
+ */
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include "../codecs/wm8994.h"
+
+static int sample_rate = 44100;
+
+static int littlemill_set_bias_level(struct snd_soc_card *card,
+					  struct snd_soc_dapm_context *dapm,
+					  enum snd_soc_bias_level level)
+{
+	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+	int ret;
+
+	if (dapm->dev != codec_dai->dev)
+		return 0;
+
+	switch (level) {
+	case SND_SOC_BIAS_PREPARE:
+		/*
+		 * If we've not already clocked things via hw_params()
+		 * then do so now, otherwise these are noops.
+		 */
+		if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
+			ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+						  WM8994_FLL_SRC_MCLK2, 32768,
+						  sample_rate * 512);
+			if (ret < 0) {
+				pr_err("Failed to start FLL: %d\n", ret);
+				return ret;
+			}
+
+			ret = snd_soc_dai_set_sysclk(codec_dai,
+						     WM8994_SYSCLK_FLL1,
+						     sample_rate * 512,
+						     SND_SOC_CLOCK_IN);
+			if (ret < 0) {
+				pr_err("Failed to set SYSCLK: %d\n", ret);
+				return ret;
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int littlemill_set_bias_level_post(struct snd_soc_card *card,
+					       struct snd_soc_dapm_context *dapm,
+					       enum snd_soc_bias_level level)
+{
+	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+	int ret;
+
+	if (dapm->dev != codec_dai->dev)
+		return 0;
+
+	switch (level) {
+	case SND_SOC_BIAS_STANDBY:
+		ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK2,
+					     32768, SND_SOC_CLOCK_IN);
+		if (ret < 0) {
+			pr_err("Failed to switch away from FLL: %d\n", ret);
+			return ret;
+		}
+
+		ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+					  0, 0, 0);
+		if (ret < 0) {
+			pr_err("Failed to stop FLL: %d\n", ret);
+			return ret;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	dapm->bias_level = level;
+
+	return 0;
+}
+
+static int littlemill_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 *codec_dai = rtd->codec_dai;
+	int ret;
+
+	sample_rate = params_rate(params);
+
+	ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+				  WM8994_FLL_SRC_MCLK2, 32768,
+				  sample_rate * 512);
+	if (ret < 0) {
+		pr_err("Failed to start FLL: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai,
+				     WM8994_SYSCLK_FLL1,
+				     sample_rate * 512,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		pr_err("Failed to set SYSCLK: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops littlemill_ops = {
+	.hw_params = littlemill_hw_params,
+};
+
+static struct snd_soc_dai_link littlemill_dai[] = {
+	{
+		.name = "CPU",
+		.stream_name = "CPU",
+		.cpu_dai_name = "samsung-i2s.0",
+		.codec_dai_name = "wm8994-aif1",
+		.platform_name = "samsung-audio",
+		.codec_name = "wm8994-codec",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+				| SND_SOC_DAIFMT_CBM_CFM,
+		.ops = &littlemill_ops,
+	},
+};
+
+static struct snd_soc_dapm_widget widgets[] = {
+	SND_SOC_DAPM_HP("Headphone", NULL),
+
+	SND_SOC_DAPM_MIC("AMIC", NULL),
+	SND_SOC_DAPM_MIC("DMIC", NULL),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+	{ "Headphone", NULL, "HPOUT1L" },
+	{ "Headphone", NULL, "HPOUT1R" },
+
+	{ "AMIC", NULL, "MICBIAS1" },   /* Default for AMICBIAS jumper */
+	{ "IN1LN", NULL, "AMIC" },
+
+	{ "DMIC", NULL, "MICBIAS2" },   /* Default for DMICBIAS jumper */
+	{ "DMIC1DAT", NULL, "DMIC" },
+	{ "DMIC2DAT", NULL, "DMIC" },
+};
+
+static struct snd_soc_jack littlemill_headset;
+
+static int littlemill_late_probe(struct snd_soc_card *card)
+{
+	struct snd_soc_codec *codec = card->rtd[0].codec;
+	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK2,
+				     32768, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_jack_new(codec, "Headset",
+			       SND_JACK_HEADSET | SND_JACK_MECHANICAL |
+			       SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+			       SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+			       SND_JACK_BTN_4 | SND_JACK_BTN_5,
+			       &littlemill_headset);
+	if (ret)
+		return ret;
+
+	/* This will check device compatibility itself */
+	wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
+
+	return 0;
+}
+
+static struct snd_soc_card littlemill = {
+	.name = "Littlemill",
+	.dai_link = littlemill_dai,
+	.num_links = ARRAY_SIZE(littlemill_dai),
+
+	.set_bias_level = littlemill_set_bias_level,
+	.set_bias_level_post = littlemill_set_bias_level_post,
+
+	.dapm_widgets = widgets,
+	.num_dapm_widgets = ARRAY_SIZE(widgets),
+	.dapm_routes = audio_paths,
+	.num_dapm_routes = ARRAY_SIZE(audio_paths),
+
+	.late_probe = littlemill_late_probe,
+};
+
+static __devinit int littlemill_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &littlemill;
+	int ret;
+
+	card->dev = &pdev->dev;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devexit littlemill_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static struct platform_driver littlemill_driver = {
+	.driver = {
+		.name = "littlemill",
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = littlemill_probe,
+	.remove = __devexit_p(littlemill_remove),
+};
+
+module_platform_driver(littlemill_driver);
+
+MODULE_DESCRIPTION("Littlemill audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:littlemill");
diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
new file mode 100644
index 0000000..4216a06
--- /dev/null
+++ b/sound/soc/samsung/lowland.c
@@ -0,0 +1,236 @@
+/*
+ * Lowland audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * 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.
+ */
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include "../codecs/wm5100.h"
+#include "../codecs/wm9081.h"
+
+#define MCLK1_RATE (44100 * 512)
+#define CLKOUT_RATE (44100 * 256)
+
+static int lowland_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;
+
+	return 0;
+}
+
+static struct snd_soc_ops lowland_ops = {
+	.hw_params = lowland_hw_params,
+};
+
+static struct snd_soc_jack lowland_headset;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin lowland_headset_pins[] = {
+	{
+		.pin = "Headphone",
+		.mask = SND_JACK_HEADPHONE | SND_JACK_LINEOUT,
+	},
+	{
+		.pin = "Headset Mic",
+		.mask = SND_JACK_MICROPHONE,
+	},
+};
+
+static int lowland_wm5100_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	int ret;
+
+	ret = snd_soc_codec_set_sysclk(codec, WM5100_CLK_SYSCLK,
+				       WM5100_CLKSRC_MCLK1, MCLK1_RATE,
+				       SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		pr_err("Failed to set SYSCLK clock source: %d\n", ret);
+		return ret;
+	}
+
+	/* Clock OPCLK, used by the other audio components. */
+	ret = snd_soc_codec_set_sysclk(codec, WM5100_CLK_OPCLK, 0,
+				       CLKOUT_RATE, 0);
+	if (ret < 0) {
+		pr_err("Failed to set OPCLK rate: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_jack_new(codec, "Headset",
+			       SND_JACK_LINEOUT | SND_JACK_HEADSET |
+			       SND_JACK_BTN_0,
+			       &lowland_headset);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_jack_add_pins(&lowland_headset,
+				    ARRAY_SIZE(lowland_headset_pins),
+				    lowland_headset_pins);
+	if (ret)
+		return ret;
+
+	wm5100_detect(codec, &lowland_headset);
+
+	return 0;
+}
+
+static struct snd_soc_dai_link lowland_dai[] = {
+	{
+		.name = "CPU",
+		.stream_name = "CPU",
+		.cpu_dai_name = "samsung-i2s.0",
+		.codec_dai_name = "wm5100-aif1",
+		.platform_name = "samsung-audio",
+		.codec_name = "wm5100.1-001a",
+		.ops = &lowland_ops,
+		.init = lowland_wm5100_init,
+	},
+	{
+		.name = "Baseband",
+		.stream_name = "Baseband",
+		.cpu_dai_name = "wm5100-aif2",
+		.codec_dai_name = "wm1250-ev1",
+		.codec_name = "wm1250-ev1.1-0027",
+		.ops = &lowland_ops,
+		.ignore_suspend = 1,
+	},
+};
+
+static int lowland_wm9081_init(struct snd_soc_dapm_context *dapm)
+{
+	snd_soc_dapm_nc_pin(dapm, "LINEOUT");
+
+	/* At any time the WM9081 is active it will have this clock */
+	return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0,
+					CLKOUT_RATE, 0);
+}
+
+static struct snd_soc_aux_dev lowland_aux_dev[] = {
+	{
+		.name = "wm9081",
+		.codec_name = "wm9081.1-006c",
+		.init = lowland_wm9081_init,
+	},
+};
+
+static struct snd_soc_codec_conf lowland_codec_conf[] = {
+	{
+		.dev_name = "wm9081.1-006c",
+		.name_prefix = "Sub",
+	},
+};
+
+static const struct snd_kcontrol_new controls[] = {
+	SOC_DAPM_PIN_SWITCH("Main Speaker"),
+	SOC_DAPM_PIN_SWITCH("Main DMIC"),
+	SOC_DAPM_PIN_SWITCH("Main AMIC"),
+	SOC_DAPM_PIN_SWITCH("WM1250 Input"),
+	SOC_DAPM_PIN_SWITCH("WM1250 Output"),
+	SOC_DAPM_PIN_SWITCH("Headphone"),
+};
+
+static struct snd_soc_dapm_widget widgets[] = {
+	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+
+	SND_SOC_DAPM_SPK("Main Speaker", NULL),
+
+	SND_SOC_DAPM_MIC("Main AMIC", NULL),
+	SND_SOC_DAPM_MIC("Main DMIC", NULL),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+	{ "Sub IN1", NULL, "HPOUT2L" },
+	{ "Sub IN2", NULL, "HPOUT2R" },
+
+	{ "Main Speaker", NULL, "Sub SPKN" },
+	{ "Main Speaker", NULL, "Sub SPKP" },
+	{ "Main Speaker", NULL, "SPKDAT1" },
+};
+
+static struct snd_soc_card lowland = {
+	.name = "Lowland",
+	.dai_link = lowland_dai,
+	.num_links = ARRAY_SIZE(lowland_dai),
+	.aux_dev = lowland_aux_dev,
+	.num_aux_devs = ARRAY_SIZE(lowland_aux_dev),
+	.codec_conf = lowland_codec_conf,
+	.num_configs = ARRAY_SIZE(lowland_codec_conf),
+
+	.controls = controls,
+	.num_controls = ARRAY_SIZE(controls),
+	.dapm_widgets = widgets,
+	.num_dapm_widgets = ARRAY_SIZE(widgets),
+	.dapm_routes = audio_paths,
+	.num_dapm_routes = ARRAY_SIZE(audio_paths),
+};
+
+static __devinit int lowland_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &lowland;
+	int ret;
+
+	card->dev = &pdev->dev;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devexit lowland_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static struct platform_driver lowland_driver = {
+	.driver = {
+		.name = "lowland",
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = lowland_probe,
+	.remove = __devexit_p(lowland_remove),
+};
+
+module_platform_driver(lowland_driver);
+
+MODULE_DESCRIPTION("Lowland audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lowland");
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 05a47cf..beef63f 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -452,7 +452,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
+static const struct snd_soc_dai_ops s3c_pcm_dai_ops = {
 	.set_sysclk	= s3c_pcm_set_sysclk,
 	.set_clkdiv	= s3c_pcm_set_clkdiv,
 	.trigger	= s3c_pcm_trigger,
@@ -632,17 +632,7 @@
 	},
 };
 
-static int __init s3c_pcm_init(void)
-{
-	return platform_driver_register(&s3c_pcm_driver);
-}
-module_init(s3c_pcm_init);
-
-static void __exit s3c_pcm_exit(void)
-{
-	platform_driver_unregister(&s3c_pcm_driver);
-}
-module_exit(s3c_pcm_exit);
+module_platform_driver(s3c_pcm_driver);
 
 /* Module information */
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 7bbec25..7218507 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -142,7 +142,7 @@
 	SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
 	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
-static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
 	.hw_params	= s3c2412_i2s_hw_params,
 };
 
@@ -184,17 +184,7 @@
 	},
 };
 
-static int __init s3c2412_i2s_init(void)
-{
-	return platform_driver_register(&s3c2412_iis_driver);
-}
-module_init(s3c2412_i2s_init);
-
-static void __exit s3c2412_i2s_exit(void)
-{
-	platform_driver_unregister(&s3c2412_iis_driver);
-}
-module_exit(s3c2412_i2s_exit);
+module_platform_driver(s3c2412_iis_driver);
 
 /* Module information */
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 558c64b..c4aa4d4 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -444,7 +444,7 @@
 	SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
 	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
-static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
 	.trigger	= s3c24xx_i2s_trigger,
 	.hw_params	= s3c24xx_i2s_hw_params,
 	.set_fmt	= s3c24xx_i2s_set_fmt,
@@ -489,17 +489,7 @@
 	},
 };
 
-static int __init s3c24xx_i2s_init(void)
-{
-	return platform_driver_register(&s3c24xx_iis_driver);
-}
-module_init(s3c24xx_i2s_init);
-
-static void __exit s3c24xx_i2s_exit(void)
-{
-	platform_driver_unregister(&s3c24xx_iis_driver);
-}
-module_exit(s3c24xx_i2s_exit);
+module_platform_driver(s3c24xx_iis_driver);
 
 /* Module information */
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c
index d125e79..5027981 100644
--- a/sound/soc/samsung/s3c24xx_simtec_hermes.c
+++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c
@@ -114,21 +114,9 @@
 	.remove	= __devexit_p(simtec_audio_remove),
 };
 
+module_platform_driver(simtec_audio_hermes_platdrv);
+
 MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
-
-static int __init simtec_hermes_modinit(void)
-{
-	return platform_driver_register(&simtec_audio_hermes_platdrv);
-}
-
-static void __exit simtec_hermes_modexit(void)
-{
-	platform_driver_unregister(&simtec_audio_hermes_platdrv);
-}
-
-module_init(simtec_hermes_modinit);
-module_exit(simtec_hermes_modexit);
-
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
index 5e4fd46..7324609 100644
--- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
@@ -102,21 +102,9 @@
 	.remove	= __devexit_p(simtec_audio_remove),
 };
 
+module_platform_driver(simtec_audio_tlv320aic32_driver);
+
 MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
-
-static int __init simtec_tlv320aic23_modinit(void)
-{
-	return platform_driver_register(&simtec_audio_tlv320aic23_platdrv);
-}
-
-static void __exit simtec_tlv320aic23_modexit(void)
-{
-	platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv);
-}
-
-module_init(simtec_tlv320aic23_modinit);
-module_exit(simtec_tlv320aic23_modexit);
-
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c
index 548c6ac..62b69fb 100644
--- a/sound/soc/samsung/s3c24xx_uda134x.c
+++ b/sound/soc/samsung/s3c24xx_uda134x.c
@@ -343,19 +343,7 @@
 	},
 };
 
-static int __init s3c24xx_uda134x_init(void)
-{
-	return platform_driver_register(&s3c24xx_uda134x_driver);
-}
-
-static void __exit s3c24xx_uda134x_exit(void)
-{
-	platform_driver_unregister(&s3c24xx_uda134x_driver);
-}
-
-
-module_init(s3c24xx_uda134x_init);
-module_exit(s3c24xx_uda134x_exit);
+module_platform_driver(s3c24xx_uda134x_driver);
 
 MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
 MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c
index 0677473..49dfafb 100644
--- a/sound/soc/samsung/smdk_wm8580pcm.c
+++ b/sound/soc/samsung/smdk_wm8580pcm.c
@@ -188,19 +188,7 @@
 	.remove = __devexit_p(snd_smdk_remove),
 };
 
-static int __init smdk_audio_init(void)
-{
-	return platform_driver_register(&snd_smdk_driver);
-}
-
-module_init(smdk_audio_init);
-
-static void __exit smdk_audio_exit(void)
-{
-	platform_driver_unregister(&snd_smdk_driver);
-}
-
-module_exit(smdk_audio_exit);
+module_platform_driver(snd_smdk_driver);
 
 MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
 MODULE_DESCRIPTION("ALSA SoC SMDK WM8580 for PCM");
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c
index da9c2a2..23c7fb7 100644
--- a/sound/soc/samsung/smdk_wm8994pcm.c
+++ b/sound/soc/samsung/smdk_wm8994pcm.c
@@ -158,19 +158,7 @@
 	.remove = __devexit_p(snd_smdk_remove),
 };
 
-static int __init smdk_audio_init(void)
-{
-	return platform_driver_register(&snd_smdk_driver);
-}
-
-module_init(smdk_audio_init);
-
-static void __exit smdk_audio_exit(void)
-{
-	platform_driver_unregister(&snd_smdk_driver);
-}
-
-module_exit(smdk_audio_exit);
+module_platform_driver(snd_smdk_driver);
 
 MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
 MODULE_DESCRIPTION("ALSA SoC SMDK WM8994 for PCM");
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 468cff1..a5a56a1 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -334,7 +334,7 @@
 #define spdif_resume NULL
 #endif
 
-static struct snd_soc_dai_ops spdif_dai_ops = {
+static const struct snd_soc_dai_ops spdif_dai_ops = {
 	.set_sysclk	= spdif_set_sysclk,
 	.trigger	= spdif_trigger,
 	.hw_params	= spdif_hw_params,
@@ -483,17 +483,7 @@
 	},
 };
 
-static int __init spdif_init(void)
-{
-	return platform_driver_register(&samsung_spdif_driver);
-}
-module_init(spdif_init);
-
-static void __exit spdif_exit(void)
-{
-	platform_driver_unregister(&samsung_spdif_driver);
-}
-module_exit(spdif_exit);
+module_platform_driver(samsung_spdif_driver);
 
 MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
 MODULE_DESCRIPTION("Samsung S/PDIF Controller Driver");
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index 4b8e354..18e6356 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -222,8 +222,6 @@
 
 static int speyside_wm9081_init(struct snd_soc_dapm_context *dapm)
 {
-	snd_soc_dapm_nc_pin(dapm, "LINEOUT");
-
 	/* At any time the WM9081 is active it will have this clock */
 	return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0,
 					48000 * 256, 0);
@@ -308,6 +306,7 @@
 	.num_dapm_widgets = ARRAY_SIZE(widgets),
 	.dapm_routes = audio_paths,
 	.num_dapm_routes = ARRAY_SIZE(audio_paths),
+	.fully_routed = true,
 
 	.late_probe = speyside_late_probe,
 };
@@ -348,17 +347,7 @@
 	.remove = __devexit_p(speyside_remove),
 };
 
-static int __init speyside_audio_init(void)
-{
-	return platform_driver_register(&speyside_driver);
-}
-module_init(speyside_audio_init);
-
-static void __exit speyside_audio_exit(void)
-{
-	platform_driver_unregister(&speyside_driver);
-}
-module_exit(speyside_audio_exit);
+module_platform_driver(speyside_driver);
 
 MODULE_DESCRIPTION("Speyside audio support");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/tobermory.c
similarity index 69%
rename from sound/soc/samsung/speyside_wm8962.c
rename to sound/soc/samsung/tobermory.c
index e3e2716..6f91c65 100644
--- a/sound/soc/samsung/speyside_wm8962.c
+++ b/sound/soc/samsung/tobermory.c
@@ -1,5 +1,5 @@
 /*
- * Speyside with WM8962 audio support
+ * Tobermory audio support
  *
  * Copyright 2011 Wolfson Microelectronics
  *
@@ -19,7 +19,7 @@
 
 static int sample_rate = 44100;
 
-static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
+static int tobermory_set_bias_level(struct snd_soc_card *card,
 					  struct snd_soc_dapm_context *dapm,
 					  enum snd_soc_bias_level level)
 {
@@ -56,7 +56,7 @@
 	return 0;
 }
 
-static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
+static int tobermory_set_bias_level_post(struct snd_soc_card *card,
 					       struct snd_soc_dapm_context *dapm,
 					       enum snd_soc_bias_level level)
 {
@@ -92,7 +92,7 @@
 	return 0;
 }
 
-static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream,
+static int tobermory_hw_params(struct snd_pcm_substream *substream,
 			      struct snd_pcm_hw_params *params)
 {
 	sample_rate = params_rate(params);
@@ -100,11 +100,11 @@
 	return 0;
 }
 
-static struct snd_soc_ops speyside_wm8962_ops = {
-	.hw_params = speyside_wm8962_hw_params,
+static struct snd_soc_ops tobermory_ops = {
+	.hw_params = tobermory_hw_params,
 };
 
-static struct snd_soc_dai_link speyside_wm8962_dai[] = {
+static struct snd_soc_dai_link tobermory_dai[] = {
 	{
 		.name = "CPU",
 		.stream_name = "CPU",
@@ -114,7 +114,7 @@
 		.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,
+		.ops = &tobermory_ops,
 	},
 };
 
@@ -152,10 +152,10 @@
 	{ "DMICDAT", NULL, "DMIC" },
 };
 
-static struct snd_soc_jack speyside_wm8962_headset;
+static struct snd_soc_jack tobermory_headset;
 
 /* Headset jack detection DAPM pins */
-static struct snd_soc_jack_pin speyside_wm8962_headset_pins[] = {
+static struct snd_soc_jack_pin tobermory_headset_pins[] = {
 	{
 		.pin = "Headset Mic",
 		.mask = SND_JACK_MICROPHONE,
@@ -166,7 +166,7 @@
 	},
 };
 
-static int speyside_wm8962_late_probe(struct snd_soc_card *card)
+static int tobermory_late_probe(struct snd_soc_card *card)
 {
 	struct snd_soc_codec *codec = card->rtd[0].codec;
 	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
@@ -179,28 +179,28 @@
 
 	ret = snd_soc_jack_new(codec, "Headset",
 			       SND_JACK_HEADSET | SND_JACK_BTN_0,
-			       &speyside_wm8962_headset);
+			       &tobermory_headset);
 	if (ret)
 		return ret;
 
-	ret = snd_soc_jack_add_pins(&speyside_wm8962_headset,
-				    ARRAY_SIZE(speyside_wm8962_headset_pins),
-				    speyside_wm8962_headset_pins);
+	ret = snd_soc_jack_add_pins(&tobermory_headset,
+				    ARRAY_SIZE(tobermory_headset_pins),
+				    tobermory_headset_pins);
 	if (ret)
 		return ret;
 
-	wm8962_mic_detect(codec, &speyside_wm8962_headset);
+	wm8962_mic_detect(codec, &tobermory_headset);
 
 	return 0;
 }
 
-static struct snd_soc_card speyside_wm8962 = {
-	.name = "Speyside WM8962",
-	.dai_link = speyside_wm8962_dai,
-	.num_links = ARRAY_SIZE(speyside_wm8962_dai),
+static struct snd_soc_card tobermory = {
+	.name = "Tobermory",
+	.dai_link = tobermory_dai,
+	.num_links = ARRAY_SIZE(tobermory_dai),
 
-	.set_bias_level = speyside_wm8962_set_bias_level,
-	.set_bias_level_post = speyside_wm8962_set_bias_level_post,
+	.set_bias_level = tobermory_set_bias_level,
+	.set_bias_level_post = tobermory_set_bias_level_post,
 
 	.controls = controls,
 	.num_controls = ARRAY_SIZE(controls),
@@ -208,13 +208,14 @@
 	.num_dapm_widgets = ARRAY_SIZE(widgets),
 	.dapm_routes = audio_paths,
 	.num_dapm_routes = ARRAY_SIZE(audio_paths),
+	.fully_routed = true,
 
-	.late_probe = speyside_wm8962_late_probe,
+	.late_probe = tobermory_late_probe,
 };
 
-static __devinit int speyside_wm8962_probe(struct platform_device *pdev)
+static __devinit int tobermory_probe(struct platform_device *pdev)
 {
-	struct snd_soc_card *card = &speyside_wm8962;
+	struct snd_soc_card *card = &tobermory;
 	int ret;
 
 	card->dev = &pdev->dev;
@@ -229,7 +230,7 @@
 	return 0;
 }
 
-static int __devexit speyside_wm8962_remove(struct platform_device *pdev)
+static int __devexit tobermory_remove(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
 
@@ -238,29 +239,19 @@
 	return 0;
 }
 
-static struct platform_driver speyside_wm8962_driver = {
+static struct platform_driver tobermory_driver = {
 	.driver = {
-		.name = "speyside-wm8962",
+		.name = "tobermory",
 		.owner = THIS_MODULE,
 		.pm = &snd_soc_pm_ops,
 	},
-	.probe = speyside_wm8962_probe,
-	.remove = __devexit_p(speyside_wm8962_remove),
+	.probe = tobermory_probe,
+	.remove = __devexit_p(tobermory_remove),
 };
 
-static int __init speyside_wm8962_audio_init(void)
-{
-	return platform_driver_register(&speyside_wm8962_driver);
-}
-module_init(speyside_wm8962_audio_init);
+module_platform_driver(tobermory_driver);
 
-static void __exit speyside_wm8962_audio_exit(void)
-{
-	platform_driver_unregister(&speyside_wm8962_driver);
-}
-module_exit(speyside_wm8962_audio_exit);
-
-MODULE_DESCRIPTION("Speyside WM8962 audio support");
+MODULE_DESCRIPTION("Tobermory audio support");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:speyside-wm8962");
+MODULE_ALIAS("platform:tobermory");
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index db74005..7da2018 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -369,17 +369,7 @@
 	.remove = __devexit_p(sh7760_soc_platform_remove),
 };
 
-static int __init snd_sh7760_pcm_init(void)
-{
-	return platform_driver_register(&sh7760_pcm_driver);
-}
-module_init(snd_sh7760_pcm_init);
-
-static void __exit snd_sh7760_pcm_exit(void)
-{
-	platform_driver_unregister(&sh7760_pcm_driver);
-}
-module_exit(snd_sh7760_pcm_exit);
+module_platform_driver(sh7760_pcm_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index dff64b9..eb52778 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -58,27 +58,23 @@
 static int fsi_ak4642_probe(struct platform_device *pdev)
 {
 	int ret = -ENOMEM;
-	const struct platform_device_id	*id_entry;
-	struct fsi_ak4642_data *pdata;
+	struct fsi_ak4642_info *pinfo = pdev->dev.platform_data;
 
-	id_entry = pdev->id_entry;
-	if (!id_entry) {
-		dev_err(&pdev->dev, "unknown fsi ak4642\n");
-		return -ENODEV;
+	if (!pinfo) {
+		dev_err(&pdev->dev, "no info for fsi ak4642\n");
+		goto out;
 	}
 
-	pdata = (struct fsi_ak4642_data *)id_entry->driver_data;
-
-	fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
+	fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id);
 	if (!fsi_snd_device)
 		goto out;
 
-	fsi_dai_link.name		= pdata->name;
-	fsi_dai_link.stream_name	= pdata->name;
-	fsi_dai_link.cpu_dai_name	= pdata->cpu_dai;
-	fsi_dai_link.platform_name	= pdata->platform;
-	fsi_dai_link.codec_name		= pdata->codec;
-	fsi_soc_card.name		= pdata->card;
+	fsi_dai_link.name		= pinfo->name;
+	fsi_dai_link.stream_name	= pinfo->name;
+	fsi_dai_link.cpu_dai_name	= pinfo->cpu_dai;
+	fsi_dai_link.platform_name	= pinfo->platform;
+	fsi_dai_link.codec_name		= pinfo->codec;
+	fsi_soc_card.name		= pinfo->card;
 
 	platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
 	ret = platform_device_add(fsi_snd_device);
@@ -96,114 +92,15 @@
 	return 0;
 }
 
-static struct fsi_ak4642_data fsi_a_ak4642 = {
-	.name		= "AK4642",
-	.card		= "FSIA-AK4642",
-	.cpu_dai	= "fsia-dai",
-	.codec		= "ak4642-codec.0-0012",
-	.platform	= "sh_fsi.0",
-	.id		= FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi_b_ak4642 = {
-	.name		= "AK4642",
-	.card		= "FSIB-AK4642",
-	.cpu_dai	= "fsib-dai",
-	.codec		= "ak4642-codec.0-0012",
-	.platform	= "sh_fsi.0",
-	.id		= FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi_a_ak4643 = {
-	.name		= "AK4643",
-	.card		= "FSIA-AK4643",
-	.cpu_dai	= "fsia-dai",
-	.codec		= "ak4642-codec.0-0013",
-	.platform	= "sh_fsi.0",
-	.id		= FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi_b_ak4643 = {
-	.name		= "AK4643",
-	.card		= "FSIB-AK4643",
-	.cpu_dai	= "fsib-dai",
-	.codec		= "ak4642-codec.0-0013",
-	.platform	= "sh_fsi.0",
-	.id		= FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi2_a_ak4642 = {
-	.name		= "AK4642",
-	.card		= "FSI2A-AK4642",
-	.cpu_dai	= "fsia-dai",
-	.codec		= "ak4642-codec.0-0012",
-	.platform	= "sh_fsi2",
-	.id		= FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi2_b_ak4642 = {
-	.name		= "AK4642",
-	.card		= "FSI2B-AK4642",
-	.cpu_dai	= "fsib-dai",
-	.codec		= "ak4642-codec.0-0012",
-	.platform	= "sh_fsi2",
-	.id		= FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi2_a_ak4643 = {
-	.name		= "AK4643",
-	.card		= "FSI2A-AK4643",
-	.cpu_dai	= "fsia-dai",
-	.codec		= "ak4642-codec.0-0013",
-	.platform	= "sh_fsi2",
-	.id		= FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi2_b_ak4643 = {
-	.name		= "AK4643",
-	.card		= "FSI2B-AK4643",
-	.cpu_dai	= "fsib-dai",
-	.codec		= "ak4642-codec.0-0013",
-	.platform	= "sh_fsi2",
-	.id		= FSI_PORT_B,
-};
-
-static struct platform_device_id fsi_id_table[] = {
-	/* FSI */
-	{ "sh_fsi_a_ak4642",	(kernel_ulong_t)&fsi_a_ak4642 },
-	{ "sh_fsi_b_ak4642",	(kernel_ulong_t)&fsi_b_ak4642 },
-	{ "sh_fsi_a_ak4643",	(kernel_ulong_t)&fsi_a_ak4643 },
-	{ "sh_fsi_b_ak4643",	(kernel_ulong_t)&fsi_b_ak4643 },
-
-	/* FSI 2 */
-	{ "sh_fsi2_a_ak4642",	(kernel_ulong_t)&fsi2_a_ak4642 },
-	{ "sh_fsi2_b_ak4642",	(kernel_ulong_t)&fsi2_b_ak4642 },
-	{ "sh_fsi2_a_ak4643",	(kernel_ulong_t)&fsi2_a_ak4643 },
-	{ "sh_fsi2_b_ak4643",	(kernel_ulong_t)&fsi2_b_ak4643 },
-	{},
-};
-
 static struct platform_driver fsi_ak4642 = {
 	.driver = {
 		.name	= "fsi-ak4642-audio",
 	},
 	.probe		= fsi_ak4642_probe,
 	.remove		= fsi_ak4642_remove,
-	.id_table	= fsi_id_table,
 };
 
-static int __init fsi_ak4642_init(void)
-{
-	return platform_driver_register(&fsi_ak4642);
-}
-
-static void __exit fsi_ak4642_exit(void)
-{
-	platform_driver_unregister(&fsi_ak4642);
-}
-
-module_init(fsi_ak4642_init);
-module_exit(fsi_ak4642_exit);
+module_platform_driver(fsi_ak4642);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
index 3ebebe7..621aea1 100644
--- a/sound/soc/sh/fsi-hdmi.c
+++ b/sound/soc/sh/fsi-hdmi.c
@@ -110,18 +110,7 @@
 	.id_table	= fsi_id_table,
 };
 
-static int __init fsi_hdmi_init(void)
-{
-	return platform_driver_register(&fsi_hdmi);
-}
-
-static void __exit fsi_hdmi_exit(void)
-{
-	platform_driver_unregister(&fsi_hdmi);
-}
-
-module_init(fsi_hdmi_init);
-module_exit(fsi_hdmi_exit);
+module_platform_driver(fsi_hdmi);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 3d7016e..a27c306 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -32,7 +32,9 @@
 #define REG_DIDT	0x0020
 #define REG_DODT	0x0024
 #define REG_MUTE_ST	0x0028
+#define REG_OUT_DMAC	0x002C
 #define REG_OUT_SEL	0x0030
+#define REG_IN_DMAC	0x0038
 
 /* master register */
 #define MST_CLK_RST	0x0210
@@ -235,13 +237,13 @@
 }
 
 #define fsi_reg_write(p, r, d)\
-	__fsi_reg_write((u32)(p->base + REG_##r), d)
+	__fsi_reg_write((p->base + REG_##r), d)
 
 #define fsi_reg_read(p, r)\
-	__fsi_reg_read((u32)(p->base + REG_##r))
+	__fsi_reg_read((p->base + REG_##r))
 
 #define fsi_reg_mask_set(p, r, m, d)\
-	__fsi_reg_mask_set((u32)(p->base + REG_##r), m, d)
+	__fsi_reg_mask_set((p->base + REG_##r), m, d)
 
 #define fsi_master_read(p, r) _fsi_master_read(p, MST_##r)
 #define fsi_core_read(p, r)   _fsi_master_read(p, p->core->r)
@@ -886,6 +888,8 @@
 			  int is_play,
 			  struct device *dev)
 {
+	struct fsi_master *master = fsi_get_master(fsi);
+	int fsi_ver = master->core->ver;
 	u32 flags = fsi_get_info_flags(fsi);
 	u32 data = 0;
 
@@ -920,6 +924,17 @@
 		fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
 	}
 
+	/*
+	 * FIXME
+	 *
+	 * FSI driver assumed that data package is in-back.
+	 * FSI2 chip can select it.
+	 */
+	if (fsi_ver >= 2) {
+		fsi_reg_write(fsi, OUT_DMAC,	(1 << 4));
+		fsi_reg_write(fsi, IN_DMAC,	(1 << 4));
+	}
+
 	/* irq clear */
 	fsi_irq_disable(fsi, is_play);
 	fsi_irq_clear_status(fsi);
@@ -1081,7 +1096,7 @@
 	return ret;
 }
 
-static struct snd_soc_dai_ops fsi_dai_ops = {
+static const struct snd_soc_dai_ops fsi_dai_ops = {
 	.startup	= fsi_dai_startup,
 	.shutdown	= fsi_dai_shutdown,
 	.trigger	= fsi_dai_trigger,
@@ -1453,18 +1468,7 @@
 	.id_table	= fsi_id_table,
 };
 
-static int __init fsi_mobile_init(void)
-{
-	return platform_driver_register(&fsi_driver);
-}
-
-static void __exit fsi_mobile_exit(void)
-{
-	platform_driver_unregister(&fsi_driver);
-}
-
-module_init(fsi_mobile_init);
-module_exit(fsi_mobile_exit);
+module_platform_driver(fsi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip FSI audio driver");
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index c87e3ff..3474d7b 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -266,7 +266,7 @@
 #define AC97_FMTS	\
 	SNDRV_PCM_FMTBIT_S16_LE
 
-static struct snd_soc_dai_ops hac_dai_ops = {
+static const struct snd_soc_dai_ops hac_dai_ops = {
 	.hw_params	= hac_hw_params,
 };
 
@@ -332,17 +332,7 @@
 	.remove = __devexit_p(hac_soc_platform_remove),
 };
 
-static int __init sh4_hac_pcm_init(void)
-{
-	return platform_driver_register(&hac_pcm_driver);
-}
-module_init(sh4_hac_pcm_init);
-
-static void __exit sh4_hac_pcm_exit(void)
-{
-	platform_driver_unregister(&hac_pcm_driver);
-}
-module_exit(sh4_hac_pcm_exit);
+module_platform_driver(hac_pcm_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index edacfeb..11c6085 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -707,7 +707,7 @@
 	return ret;
 }
 
-static struct snd_soc_dai_ops siu_dai_ops = {
+static const struct snd_soc_dai_ops siu_dai_ops = {
 	.startup	= siu_dai_startup,
 	.shutdown	= siu_dai_shutdown,
 	.prepare	= siu_dai_prepare,
@@ -852,18 +852,7 @@
 	.remove		= __devexit_p(siu_remove),
 };
 
-static int __init siu_init(void)
-{
-	return platform_driver_register(&siu_driver);
-}
-
-static void __exit siu_exit(void)
-{
-	platform_driver_unregister(&siu_driver);
-}
-
-module_init(siu_init)
-module_exit(siu_exit)
+module_platform_driver(siu_driver);
 
 MODULE_AUTHOR("Carlos Munoz <carlos@kenati.com>");
 MODULE_DESCRIPTION("ALSA SoC SH7722 SIU driver");
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index e0c621c..ff82b56 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -332,7 +332,7 @@
 	 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE |	\
 	 SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_U32_LE)
 
-static struct snd_soc_dai_ops ssi_dai_ops = {
+static const struct snd_soc_dai_ops ssi_dai_ops = {
 	.startup	= ssi_startup,
 	.shutdown	= ssi_shutdown,
 	.trigger	= ssi_trigger,
@@ -401,17 +401,7 @@
 	.remove = __devexit_p(sh4_soc_dai_remove),
 };
 
-static int __init snd_sh4_ssi_init(void)
-{
-	return platform_driver_register(&sh4_ssi_driver);
-}
-module_init(snd_sh4_ssi_init);
-
-static void __exit snd_sh4_ssi_exit(void)
-{
-	platform_driver_unregister(&sh4_ssi_driver);
-}
-module_exit(snd_sh4_ssi_exit);
+module_platform_driver(sh4_ssi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 9077aa4..18bb6b3 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -14,7 +14,6 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <sound/soc.h>
-#include <linux/lzo.h>
 #include <linux/bitmap.h>
 #include <linux/rbtree.h>
 #include <linux/export.h>
@@ -439,378 +438,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_SND_SOC_CACHE_LZO
-struct snd_soc_lzo_ctx {
-	void *wmem;
-	void *dst;
-	const void *src;
-	size_t src_len;
-	size_t dst_len;
-	size_t decompressed_size;
-	unsigned long *sync_bmp;
-	int sync_bmp_nbits;
-};
-
-#define LZO_BLOCK_NUM 8
-static int snd_soc_lzo_block_count(void)
-{
-	return LZO_BLOCK_NUM;
-}
-
-static int snd_soc_lzo_prepare(struct snd_soc_lzo_ctx *lzo_ctx)
-{
-	lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
-	if (!lzo_ctx->wmem)
-		return -ENOMEM;
-	return 0;
-}
-
-static int snd_soc_lzo_compress(struct snd_soc_lzo_ctx *lzo_ctx)
-{
-	size_t compress_size;
-	int ret;
-
-	ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
-			       lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
-	if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
-		return -EINVAL;
-	lzo_ctx->dst_len = compress_size;
-	return 0;
-}
-
-static int snd_soc_lzo_decompress(struct snd_soc_lzo_ctx *lzo_ctx)
-{
-	size_t dst_len;
-	int ret;
-
-	dst_len = lzo_ctx->dst_len;
-	ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
-				    lzo_ctx->dst, &dst_len);
-	if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
-		return -EINVAL;
-	return 0;
-}
-
-static int snd_soc_lzo_compress_cache_block(struct snd_soc_codec *codec,
-		struct snd_soc_lzo_ctx *lzo_ctx)
-{
-	int ret;
-
-	lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
-	lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
-	if (!lzo_ctx->dst) {
-		lzo_ctx->dst_len = 0;
-		return -ENOMEM;
-	}
-
-	ret = snd_soc_lzo_compress(lzo_ctx);
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-static int snd_soc_lzo_decompress_cache_block(struct snd_soc_codec *codec,
-		struct snd_soc_lzo_ctx *lzo_ctx)
-{
-	int ret;
-
-	lzo_ctx->dst_len = lzo_ctx->decompressed_size;
-	lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
-	if (!lzo_ctx->dst) {
-		lzo_ctx->dst_len = 0;
-		return -ENOMEM;
-	}
-
-	ret = snd_soc_lzo_decompress(lzo_ctx);
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
-		unsigned int reg)
-{
-	const struct snd_soc_codec_driver *codec_drv;
-
-	codec_drv = codec->driver;
-	return (reg * codec_drv->reg_word_size) /
-	       DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
-}
-
-static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
-		unsigned int reg)
-{
-	const struct snd_soc_codec_driver *codec_drv;
-
-	codec_drv = codec->driver;
-	return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
-		      codec_drv->reg_word_size);
-}
-
-static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
-{
-	return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
-}
-
-static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
-{
-	struct snd_soc_lzo_ctx **lzo_blocks;
-	unsigned int val;
-	int i;
-	int ret;
-
-	lzo_blocks = codec->reg_cache;
-	for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
-		WARN_ON(!snd_soc_codec_writable_register(codec, i));
-		ret = snd_soc_cache_read(codec, i, &val);
-		if (ret)
-			return ret;
-		codec->cache_bypass = 1;
-		ret = snd_soc_write(codec, i, val);
-		codec->cache_bypass = 0;
-		if (ret)
-			return ret;
-		dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
-			i, val);
-	}
-
-	return 0;
-}
-
-static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
-				   unsigned int reg, unsigned int value)
-{
-	struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
-	int ret, blkindex, blkpos;
-	size_t blksize, tmp_dst_len;
-	void *tmp_dst;
-
-	/* index of the compressed lzo block */
-	blkindex = snd_soc_lzo_get_blkindex(codec, reg);
-	/* register index within the decompressed block */
-	blkpos = snd_soc_lzo_get_blkpos(codec, reg);
-	/* size of the compressed block */
-	blksize = snd_soc_lzo_get_blksize(codec);
-	lzo_blocks = codec->reg_cache;
-	lzo_block = lzo_blocks[blkindex];
-
-	/* save the pointer and length of the compressed block */
-	tmp_dst = lzo_block->dst;
-	tmp_dst_len = lzo_block->dst_len;
-
-	/* prepare the source to be the compressed block */
-	lzo_block->src = lzo_block->dst;
-	lzo_block->src_len = lzo_block->dst_len;
-
-	/* decompress the block */
-	ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
-	if (ret < 0) {
-		kfree(lzo_block->dst);
-		goto out;
-	}
-
-	/* write the new value to the cache */
-	if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
-				  codec->driver->reg_word_size)) {
-		kfree(lzo_block->dst);
-		goto out;
-	}
-
-	/* prepare the source to be the decompressed block */
-	lzo_block->src = lzo_block->dst;
-	lzo_block->src_len = lzo_block->dst_len;
-
-	/* compress the block */
-	ret = snd_soc_lzo_compress_cache_block(codec, lzo_block);
-	if (ret < 0) {
-		kfree(lzo_block->dst);
-		kfree(lzo_block->src);
-		goto out;
-	}
-
-	/* set the bit so we know we have to sync this register */
-	set_bit(reg, lzo_block->sync_bmp);
-	kfree(tmp_dst);
-	kfree(lzo_block->src);
-	return 0;
-out:
-	lzo_block->dst = tmp_dst;
-	lzo_block->dst_len = tmp_dst_len;
-	return ret;
-}
-
-static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
-				  unsigned int reg, unsigned int *value)
-{
-	struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
-	int ret, blkindex, blkpos;
-	size_t blksize, tmp_dst_len;
-	void *tmp_dst;
-
-	*value = 0;
-	/* index of the compressed lzo block */
-	blkindex = snd_soc_lzo_get_blkindex(codec, reg);
-	/* register index within the decompressed block */
-	blkpos = snd_soc_lzo_get_blkpos(codec, reg);
-	/* size of the compressed block */
-	blksize = snd_soc_lzo_get_blksize(codec);
-	lzo_blocks = codec->reg_cache;
-	lzo_block = lzo_blocks[blkindex];
-
-	/* save the pointer and length of the compressed block */
-	tmp_dst = lzo_block->dst;
-	tmp_dst_len = lzo_block->dst_len;
-
-	/* prepare the source to be the compressed block */
-	lzo_block->src = lzo_block->dst;
-	lzo_block->src_len = lzo_block->dst_len;
-
-	/* decompress the block */
-	ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
-	if (ret >= 0)
-		/* fetch the value from the cache */
-		*value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
-					       codec->driver->reg_word_size);
-
-	kfree(lzo_block->dst);
-	/* restore the pointer and length of the compressed block */
-	lzo_block->dst = tmp_dst;
-	lzo_block->dst_len = tmp_dst_len;
-	return 0;
-}
-
-static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
-{
-	struct snd_soc_lzo_ctx **lzo_blocks;
-	int i, blkcount;
-
-	lzo_blocks = codec->reg_cache;
-	if (!lzo_blocks)
-		return 0;
-
-	blkcount = snd_soc_lzo_block_count();
-	/*
-	 * the pointer to the bitmap used for syncing the cache
-	 * is shared amongst all lzo_blocks.  Ensure it is freed
-	 * only once.
-	 */
-	if (lzo_blocks[0])
-		kfree(lzo_blocks[0]->sync_bmp);
-	for (i = 0; i < blkcount; ++i) {
-		if (lzo_blocks[i]) {
-			kfree(lzo_blocks[i]->wmem);
-			kfree(lzo_blocks[i]->dst);
-		}
-		/* each lzo_block is a pointer returned by kmalloc or NULL */
-		kfree(lzo_blocks[i]);
-	}
-	kfree(lzo_blocks);
-	codec->reg_cache = NULL;
-	return 0;
-}
-
-static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
-{
-	struct snd_soc_lzo_ctx **lzo_blocks;
-	size_t bmp_size;
-	const struct snd_soc_codec_driver *codec_drv;
-	int ret, tofree, i, blksize, blkcount;
-	const char *p, *end;
-	unsigned long *sync_bmp;
-
-	ret = 0;
-	codec_drv = codec->driver;
-
-	/*
-	 * If we have not been given a default register cache
-	 * then allocate a dummy zero-ed out region, compress it
-	 * and remember to free it afterwards.
-	 */
-	tofree = 0;
-	if (!codec->reg_def_copy)
-		tofree = 1;
-
-	if (!codec->reg_def_copy) {
-		codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
-		if (!codec->reg_def_copy)
-			return -ENOMEM;
-	}
-
-	blkcount = snd_soc_lzo_block_count();
-	codec->reg_cache = kzalloc(blkcount * sizeof *lzo_blocks,
-				   GFP_KERNEL);
-	if (!codec->reg_cache) {
-		ret = -ENOMEM;
-		goto err_tofree;
-	}
-	lzo_blocks = codec->reg_cache;
-
-	/*
-	 * allocate a bitmap to be used when syncing the cache with
-	 * the hardware.  Each time a register is modified, the corresponding
-	 * bit is set in the bitmap, so we know that we have to sync
-	 * that register.
-	 */
-	bmp_size = codec_drv->reg_cache_size;
-	sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
-			   GFP_KERNEL);
-	if (!sync_bmp) {
-		ret = -ENOMEM;
-		goto err;
-	}
-	bitmap_zero(sync_bmp, bmp_size);
-
-	/* allocate the lzo blocks and initialize them */
-	for (i = 0; i < blkcount; ++i) {
-		lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
-					GFP_KERNEL);
-		if (!lzo_blocks[i]) {
-			kfree(sync_bmp);
-			ret = -ENOMEM;
-			goto err;
-		}
-		lzo_blocks[i]->sync_bmp = sync_bmp;
-		lzo_blocks[i]->sync_bmp_nbits = bmp_size;
-		/* alloc the working space for the compressed block */
-		ret = snd_soc_lzo_prepare(lzo_blocks[i]);
-		if (ret < 0)
-			goto err;
-	}
-
-	blksize = snd_soc_lzo_get_blksize(codec);
-	p = codec->reg_def_copy;
-	end = codec->reg_def_copy + codec->reg_size;
-	/* compress the register map and fill the lzo blocks */
-	for (i = 0; i < blkcount; ++i, p += blksize) {
-		lzo_blocks[i]->src = p;
-		if (p + blksize > end)
-			lzo_blocks[i]->src_len = end - p;
-		else
-			lzo_blocks[i]->src_len = blksize;
-		ret = snd_soc_lzo_compress_cache_block(codec,
-						       lzo_blocks[i]);
-		if (ret < 0)
-			goto err;
-		lzo_blocks[i]->decompressed_size =
-			lzo_blocks[i]->src_len;
-	}
-
-	if (tofree) {
-		kfree(codec->reg_def_copy);
-		codec->reg_def_copy = NULL;
-	}
-	return 0;
-err:
-	snd_soc_cache_exit(codec);
-err_tofree:
-	if (tofree) {
-		kfree(codec->reg_def_copy);
-		codec->reg_def_copy = NULL;
-	}
-	return ret;
-}
-#endif
-
 static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
 {
 	int i;
@@ -889,17 +516,6 @@
 		.write = snd_soc_flat_cache_write,
 		.sync = snd_soc_flat_cache_sync
 	},
-#ifdef CONFIG_SND_SOC_CACHE_LZO
-	{
-		.id = SND_SOC_LZO_COMPRESSION,
-		.name = "LZO",
-		.init = snd_soc_lzo_cache_init,
-		.exit = snd_soc_lzo_cache_exit,
-		.read = snd_soc_lzo_cache_read,
-		.write = snd_soc_lzo_cache_write,
-		.sync = snd_soc_lzo_cache_sync
-	},
-#endif
 	{
 		.id = SND_SOC_RBTREE_COMPRESSION,
 		.name = "rbtree",
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a25fa63..5195f06 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -572,7 +572,7 @@
 			switch (codec->dapm.bias_level) {
 			case SND_SOC_BIAS_STANDBY:
 			case SND_SOC_BIAS_OFF:
-				codec->driver->suspend(codec, PMSG_SUSPEND);
+				codec->driver->suspend(codec);
 				codec->suspended = 1;
 				codec->cache_sync = 1;
 				break;
@@ -741,7 +741,7 @@
 #define snd_soc_resume NULL
 #endif
 
-static struct snd_soc_dai_ops null_dai_ops = {
+static const struct snd_soc_dai_ops null_dai_ops = {
 };
 
 static int soc_bind_dai_link(struct snd_soc_card *card, int num)
@@ -1488,6 +1488,10 @@
 
 	snd_soc_dapm_new_widgets(&card->dapm);
 
+	if (card->fully_routed)
+		list_for_each_entry(codec, &card->codec_dev_list, card_list)
+			snd_soc_dapm_auto_nc_codec_pins(codec);
+
 	ret = snd_card_register(card->snd_card);
 	if (ret < 0) {
 		printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index f42e8b9..6bb327e 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -339,6 +339,7 @@
 	case snd_soc_dapm_output:
 	case snd_soc_dapm_adc:
 	case snd_soc_dapm_input:
+	case snd_soc_dapm_siggen:
 	case snd_soc_dapm_dac:
 	case snd_soc_dapm_micbias:
 	case snd_soc_dapm_vmid:
@@ -772,6 +773,11 @@
 			return widget->inputs;
 		}
 
+		/* signal generator */
+		if (widget->id == snd_soc_dapm_siggen) {
+			widget->inputs = snd_soc_dapm_suspend_check(widget);
+			return widget->inputs;
+		}
 	}
 
 	list_for_each_entry(path, &widget->sources, list_sink) {
@@ -1982,6 +1988,7 @@
 	case snd_soc_dapm_out_drv:
 	case snd_soc_dapm_input:
 	case snd_soc_dapm_output:
+	case snd_soc_dapm_siggen:
 	case snd_soc_dapm_micbias:
 	case snd_soc_dapm_vmid:
 	case snd_soc_dapm_pre:
@@ -2947,6 +2954,79 @@
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
 
+static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
+					      struct snd_soc_dapm_widget *w)
+{
+	struct snd_soc_dapm_path *p;
+
+	list_for_each_entry(p, &card->paths, list) {
+		if ((p->source == w) || (p->sink == w)) {
+			dev_dbg(card->dev,
+			    "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n",
+			    p->source->name, p->source->id, p->source->dapm,
+			    p->sink->name, p->sink->id, p->sink->dapm);
+
+			/* Connected to something other than the codec */
+			if (p->source->dapm != p->sink->dapm)
+				return true;
+			/*
+			 * Loopback connection from codec external pin to
+			 * codec external pin
+			 */
+			if (p->sink->id == snd_soc_dapm_input) {
+				switch (p->source->id) {
+				case snd_soc_dapm_output:
+				case snd_soc_dapm_micbias:
+					return true;
+				default:
+					break;
+				}
+			}
+		}
+	}
+
+	return false;
+}
+
+/**
+ * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins
+ * @codec: The codec whose pins should be processed
+ *
+ * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec
+ * which are unused. Pins are used if they are connected externally to the
+ * codec, whether that be to some other device, or a loop-back connection to
+ * the codec itself.
+ */
+void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
+{
+	struct snd_soc_card *card = codec->card;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_dapm_widget *w;
+
+	dev_dbg(codec->dev, "Auto NC: DAPMs: card:%p codec:%p\n",
+		&card->dapm, &codec->dapm);
+
+	list_for_each_entry(w, &card->widgets, list) {
+		if (w->dapm != dapm)
+			continue;
+		switch (w->id) {
+		case snd_soc_dapm_input:
+		case snd_soc_dapm_output:
+		case snd_soc_dapm_micbias:
+			dev_dbg(codec->dev, "Auto NC: Checking widget %s\n",
+				w->name);
+			if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
+				dev_dbg(codec->dev,
+					"... Not in map; disabling\n");
+				snd_soc_dapm_nc_pin(dapm, w->name);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 /**
  * snd_soc_dapm_free - free dapm resources
  * @dapm: DAPM context
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ee15337..49aa71e 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -319,7 +319,8 @@
 	cpu_dai->runtime = NULL;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		if (unlikely(codec->ignore_pmdown_time)) {
+		if (codec->ignore_pmdown_time ||
+		    rtd->dai_link->ignore_pmdown_time) {
 			/* powered down playback stream now */
 			snd_soc_dapm_stream_event(rtd,
 				codec_dai->driver->playback.stream_name,
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c
index 3b55a44..5b82b4e 100644
--- a/sound/soc/tegra/tegra_das.c
+++ b/sound/soc/tegra/tegra_das.c
@@ -172,11 +172,11 @@
 	if (das)
 		return -ENODEV;
 
-	das = kzalloc(sizeof(struct tegra_das), GFP_KERNEL);
+	das = devm_kzalloc(&pdev->dev, sizeof(struct tegra_das), GFP_KERNEL);
 	if (!das) {
 		dev_err(&pdev->dev, "Can't allocate tegra_das\n");
 		ret = -ENOMEM;
-		goto exit;
+		goto err;
 	}
 	das->dev = &pdev->dev;
 
@@ -184,22 +184,22 @@
 	if (!res) {
 		dev_err(&pdev->dev, "No memory resource\n");
 		ret = -ENODEV;
-		goto err_free;
+		goto err;
 	}
 
-	region = request_mem_region(res->start, resource_size(res),
-					pdev->name);
+	region = devm_request_mem_region(&pdev->dev, res->start,
+					 resource_size(res), pdev->name);
 	if (!region) {
 		dev_err(&pdev->dev, "Memory region already claimed\n");
 		ret = -EBUSY;
-		goto err_free;
+		goto err;
 	}
 
-	das->regs = ioremap(res->start, resource_size(res));
+	das->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
 	if (!das->regs) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENOMEM;
-		goto err_release;
+		goto err;
 	}
 
 	tegra_das_debug_add(das);
@@ -208,58 +208,41 @@
 
 	return 0;
 
-err_release:
-	release_mem_region(res->start, resource_size(res));
-err_free:
-	kfree(das);
+err:
 	das = NULL;
-exit:
 	return ret;
 }
 
 static int __devexit tegra_das_remove(struct platform_device *pdev)
 {
-	struct resource *res;
-
 	if (!das)
 		return -ENODEV;
 
-	platform_set_drvdata(pdev, NULL);
-
 	tegra_das_debug_remove(das);
 
-	iounmap(das->regs);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-	kfree(das);
 	das = NULL;
 
 	return 0;
 }
 
+static const struct of_device_id tegra_das_of_match[] __devinitconst = {
+	{ .compatible = "nvidia,tegra20-das", },
+	{},
+};
+
 static struct platform_driver tegra_das_driver = {
 	.probe = tegra_das_probe,
 	.remove = __devexit_p(tegra_das_remove),
 	.driver = {
 		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = tegra_das_of_match,
 	},
 };
-
-static int __init tegra_das_modinit(void)
-{
-	return platform_driver_register(&tegra_das_driver);
-}
-module_init(tegra_das_modinit);
-
-static void __exit tegra_das_modexit(void)
-{
-	platform_driver_unregister(&tegra_das_driver);
-}
-module_exit(tegra_das_modexit);
+module_platform_driver(tegra_das_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra DAS driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_das_of_match);
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
index 6728fab..33509de 100644
--- a/sound/soc/tegra/tegra_i2s.c
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -36,13 +36,13 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <mach/iomap.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
-#include "tegra_das.h"
 #include "tegra_i2s.h"
 
 #define DRV_NAME "tegra-i2s"
@@ -99,13 +99,11 @@
 	.release = single_release,
 };
 
-static void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id)
+static void tegra_i2s_debug_add(struct tegra_i2s *i2s)
 {
-	char name[] = DRV_NAME ".0";
-
-	snprintf(name, sizeof(name), DRV_NAME".%1d", id);
-	i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
-						i2s, &tegra_i2s_debug_fops);
+	i2s->debug = debugfs_create_file(i2s->dai.name, S_IRUGO,
+					 snd_soc_debugfs_root, i2s,
+					 &tegra_i2s_debug_fops);
 }
 
 static void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
@@ -306,93 +304,54 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops tegra_i2s_dai_ops = {
+static const struct snd_soc_dai_ops tegra_i2s_dai_ops = {
 	.set_fmt	= tegra_i2s_set_fmt,
 	.hw_params	= tegra_i2s_hw_params,
 	.trigger	= tegra_i2s_trigger,
 };
 
-static struct snd_soc_dai_driver tegra_i2s_dai[] = {
-	{
-		.name = DRV_NAME ".0",
-		.probe = tegra_i2s_probe,
-		.playback = {
-			.channels_min = 2,
-			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_8000_96000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
-		},
-		.capture = {
-			.channels_min = 2,
-			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_8000_96000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
-		},
-		.ops = &tegra_i2s_dai_ops,
-		.symmetric_rates = 1,
+static const struct snd_soc_dai_driver tegra_i2s_dai_template = {
+	.probe = tegra_i2s_probe,
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
-	{
-		.name = DRV_NAME ".1",
-		.probe = tegra_i2s_probe,
-		.playback = {
-			.channels_min = 2,
-			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_8000_96000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
-		},
-		.capture = {
-			.channels_min = 2,
-			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_8000_96000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
-		},
-		.ops = &tegra_i2s_dai_ops,
-		.symmetric_rates = 1,
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	},
+	.ops = &tegra_i2s_dai_ops,
+	.symmetric_rates = 1,
 };
 
 static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
 {
 	struct tegra_i2s * i2s;
 	struct resource *mem, *memregion, *dmareq;
+	u32 of_dma[2];
+	u32 dma_ch;
 	int ret;
 
-	if ((pdev->id < 0) ||
-		(pdev->id >= ARRAY_SIZE(tegra_i2s_dai))) {
-		dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
-		return -EINVAL;
-	}
-
-	/*
-	 * FIXME: Until a codec driver exists for the tegra DAS, hard-code a
-	 * 1:1 mapping between audio controllers and audio ports.
-	 */
-	ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1 + pdev->id,
-					TEGRA_DAS_DAP_SEL_DAC1 + pdev->id);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't set up DAP connection\n");
-		return ret;
-	}
-	ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1 + pdev->id,
-					TEGRA_DAS_DAC_SEL_DAP1 + pdev->id);
-	if (ret) {
-		dev_err(&pdev->dev, "Can't set up DAC connection\n");
-		return ret;
-	}
-
-	i2s = kzalloc(sizeof(struct tegra_i2s), GFP_KERNEL);
+	i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra_i2s), GFP_KERNEL);
 	if (!i2s) {
 		dev_err(&pdev->dev, "Can't allocate tegra_i2s\n");
 		ret = -ENOMEM;
-		goto exit;
+		goto err;
 	}
 	dev_set_drvdata(&pdev->dev, i2s);
 
+	i2s->dai = tegra_i2s_dai_template;
+	i2s->dai.name = dev_name(&pdev->dev);
+
 	i2s->clk_i2s = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(i2s->clk_i2s)) {
 		dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
 		ret = PTR_ERR(i2s->clk_i2s);
-		goto err_free;
+		goto err;
 	}
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -404,104 +363,93 @@
 
 	dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (!dmareq) {
-		dev_err(&pdev->dev, "No DMA resource\n");
-		ret = -ENODEV;
-		goto err_clk_put;
+		if (of_property_read_u32_array(pdev->dev.of_node,
+					"nvidia,dma-request-selector",
+					of_dma, 2) < 0) {
+			dev_err(&pdev->dev, "No DMA resource\n");
+			ret = -ENODEV;
+			goto err_clk_put;
+		}
+		dma_ch = of_dma[1];
+	} else {
+		dma_ch = dmareq->start;
 	}
 
-	memregion = request_mem_region(mem->start, resource_size(mem),
-					DRV_NAME);
+	memregion = devm_request_mem_region(&pdev->dev, mem->start,
+					    resource_size(mem), DRV_NAME);
 	if (!memregion) {
 		dev_err(&pdev->dev, "Memory region already claimed\n");
 		ret = -EBUSY;
 		goto err_clk_put;
 	}
 
-	i2s->regs = ioremap(mem->start, resource_size(mem));
+	i2s->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
 	if (!i2s->regs) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENOMEM;
-		goto err_release;
+		goto err_clk_put;
 	}
 
 	i2s->capture_dma_data.addr = mem->start + TEGRA_I2S_FIFO2;
 	i2s->capture_dma_data.wrap = 4;
 	i2s->capture_dma_data.width = 32;
-	i2s->capture_dma_data.req_sel = dmareq->start;
+	i2s->capture_dma_data.req_sel = dma_ch;
 
 	i2s->playback_dma_data.addr = mem->start + TEGRA_I2S_FIFO1;
 	i2s->playback_dma_data.wrap = 4;
 	i2s->playback_dma_data.width = 32;
-	i2s->playback_dma_data.req_sel = dmareq->start;
+	i2s->playback_dma_data.req_sel = dma_ch;
 
 	i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED;
 
-	ret = snd_soc_register_dai(&pdev->dev, &tegra_i2s_dai[pdev->id]);
+	ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
 	if (ret) {
 		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
 		ret = -ENOMEM;
-		goto err_unmap;
+		goto err_clk_put;
 	}
 
-	tegra_i2s_debug_add(i2s, pdev->id);
+	tegra_i2s_debug_add(i2s);
 
 	return 0;
 
-err_unmap:
-	iounmap(i2s->regs);
-err_release:
-	release_mem_region(mem->start, resource_size(mem));
 err_clk_put:
 	clk_put(i2s->clk_i2s);
-err_free:
-	kfree(i2s);
-exit:
+err:
 	return ret;
 }
 
 static int __devexit tegra_i2s_platform_remove(struct platform_device *pdev)
 {
 	struct tegra_i2s *i2s = dev_get_drvdata(&pdev->dev);
-	struct resource *res;
 
 	snd_soc_unregister_dai(&pdev->dev);
 
 	tegra_i2s_debug_remove(i2s);
 
-	iounmap(i2s->regs);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
 	clk_put(i2s->clk_i2s);
 
-	kfree(i2s);
-
 	return 0;
 }
 
+static const struct of_device_id tegra_i2s_of_match[] __devinitconst = {
+	{ .compatible = "nvidia,tegra20-i2s", },
+	{},
+};
+
 static struct platform_driver tegra_i2s_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
+		.of_match_table = tegra_i2s_of_match,
 	},
 	.probe = tegra_i2s_platform_probe,
 	.remove = __devexit_p(tegra_i2s_platform_remove),
 };
-
-static int __init snd_tegra_i2s_init(void)
-{
-	return platform_driver_register(&tegra_i2s_driver);
-}
-module_init(snd_tegra_i2s_init);
-
-static void __exit snd_tegra_i2s_exit(void)
-{
-	platform_driver_unregister(&tegra_i2s_driver);
-}
-module_exit(snd_tegra_i2s_exit);
+module_platform_driver(tegra_i2s_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra I2S ASoC driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_i2s_of_match);
diff --git a/sound/soc/tegra/tegra_i2s.h b/sound/soc/tegra/tegra_i2s.h
index 2b38a09..15ce1e2 100644
--- a/sound/soc/tegra/tegra_i2s.h
+++ b/sound/soc/tegra/tegra_i2s.h
@@ -153,6 +153,7 @@
 #define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS	(TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
 
 struct tegra_i2s {
+	struct snd_soc_dai_driver dai;
 	struct clk *clk_i2s;
 	int clk_refs;
 	struct tegra_pcm_dma_params capture_dma_data;
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 436def1..90345ee 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -392,18 +392,7 @@
 	.probe = tegra_pcm_platform_probe,
 	.remove = __devexit_p(tegra_pcm_platform_remove),
 };
-
-static int __init snd_tegra_pcm_init(void)
-{
-	return platform_driver_register(&tegra_pcm_driver);
-}
-module_init(snd_tegra_pcm_init);
-
-static void __exit snd_tegra_pcm_exit(void)
-{
-	platform_driver_unregister(&tegra_pcm_driver);
-}
-module_exit(snd_tegra_pcm_exit);
+module_platform_driver(tegra_pcm_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra PCM ASoC driver");
diff --git a/sound/soc/tegra/tegra_spdif.c b/sound/soc/tegra/tegra_spdif.c
index dd11d0c..475428c 100644
--- a/sound/soc/tegra/tegra_spdif.c
+++ b/sound/soc/tegra/tegra_spdif.c
@@ -226,7 +226,7 @@
 	return 0;
 }
 
-static struct snd_soc_dai_ops tegra_spdif_dai_ops = {
+static const struct snd_soc_dai_ops tegra_spdif_dai_ops = {
 	.hw_params	= tegra_spdif_hw_params,
 	.trigger	= tegra_spdif_trigger,
 };
@@ -352,17 +352,7 @@
 	.remove = __devexit_p(tegra_spdif_platform_remove),
 };
 
-static int __init snd_tegra_spdif_init(void)
-{
-	return platform_driver_register(&tegra_spdif_driver);
-}
-module_init(snd_tegra_spdif_init);
-
-static void __exit snd_tegra_spdif_exit(void)
-{
-	platform_driver_unregister(&tegra_spdif_driver);
-}
-module_exit(snd_tegra_spdif_exit);
+module_platform_driver(tegra_spdif_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra SPDIF ASoC driver");
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index a81cf39..2f5b107 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -201,8 +201,8 @@
 	{"Int Spk", NULL, "RON"},
 	{"Int Spk", NULL, "LOP"},
 	{"Int Spk", NULL, "LON"},
-	{"Mic Bias", NULL, "Mic Jack"},
-	{"IN1L", NULL, "Mic Bias"},
+	{"Mic Jack", NULL, "MICBIAS"},
+	{"IN1L", NULL, "Mic Jack"},
 };
 
 static const struct snd_soc_dapm_route seaboard_audio_map[] = {
@@ -212,8 +212,8 @@
 	{"Int Spk", NULL, "RON"},
 	{"Int Spk", NULL, "LOP"},
 	{"Int Spk", NULL, "LON"},
-	{"Mic Bias", NULL, "Mic Jack"},
-	{"IN1R", NULL, "Mic Bias"},
+	{"Mic Jack", NULL, "MICBIAS"},
+	{"IN1R", NULL, "Mic Jack"},
 };
 
 static const struct snd_soc_dapm_route kaen_audio_map[] = {
@@ -223,8 +223,8 @@
 	{"Int Spk", NULL, "RON"},
 	{"Int Spk", NULL, "LOP"},
 	{"Int Spk", NULL, "LON"},
-	{"Mic Bias", NULL, "Mic Jack"},
-	{"IN2R", NULL, "Mic Bias"},
+	{"Mic Jack", NULL, "MICBIAS"},
+	{"IN2R", NULL, "Mic Jack"},
 };
 
 static const struct snd_soc_dapm_route aebl_audio_map[] = {
@@ -232,8 +232,8 @@
 	{"Headphone Jack", NULL, "HPOUTL"},
 	{"Int Spk", NULL, "LINEOUTR"},
 	{"Int Spk", NULL, "LINEOUTL"},
-	{"Mic Bias", NULL, "Mic Jack"},
-	{"IN1R", NULL, "Mic Bias"},
+	{"Mic Jack", NULL, "MICBIAS"},
+	{"IN1R", NULL, "Mic Jack"},
 };
 
 static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
@@ -249,6 +249,19 @@
 	struct tegra_wm8903_platform_data *pdata = machine->pdata;
 	int ret;
 
+	ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1,
+					   TEGRA_DAS_DAP_SEL_DAC1);
+	if (ret) {
+		dev_err(card->dev, "Can't set up DAS DAP connection\n");
+		return ret;
+	}
+	ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1,
+					   TEGRA_DAS_DAC_SEL_DAP1);
+	if (ret) {
+		dev_err(card->dev, "Can't set up DAS DAC connection\n");
+		return ret;
+	}
+
 	if (gpio_is_valid(pdata->gpio_spkr_en)) {
 		ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
 		if (ret) {
@@ -316,28 +329,7 @@
 	wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
 				0);
 
-	snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
-
-	/* FIXME: Calculate automatically based on DAPM routes? */
-	if (!machine_is_harmony())
-		snd_soc_dapm_nc_pin(dapm, "IN1L");
-	if (!machine_is_seaboard() && !machine_is_aebl())
-		snd_soc_dapm_nc_pin(dapm, "IN1R");
-	snd_soc_dapm_nc_pin(dapm, "IN2L");
-	if (!machine_is_kaen())
-		snd_soc_dapm_nc_pin(dapm, "IN2R");
-	snd_soc_dapm_nc_pin(dapm, "IN3L");
-	snd_soc_dapm_nc_pin(dapm, "IN3R");
-
-	if (machine_is_aebl()) {
-		snd_soc_dapm_nc_pin(dapm, "LON");
-		snd_soc_dapm_nc_pin(dapm, "RON");
-		snd_soc_dapm_nc_pin(dapm, "ROP");
-		snd_soc_dapm_nc_pin(dapm, "LOP");
-	} else {
-		snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
-		snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
-	}
+	snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
 
 	return 0;
 }
@@ -362,6 +354,7 @@
 	.num_controls = ARRAY_SIZE(tegra_wm8903_controls),
 	.dapm_widgets = tegra_wm8903_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets),
+	.fully_routed = true,
 };
 
 static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
@@ -377,17 +370,19 @@
 		return -EINVAL;
 	}
 
-	machine = kzalloc(sizeof(struct tegra_wm8903), GFP_KERNEL);
+	machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8903),
+			       GFP_KERNEL);
 	if (!machine) {
 		dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err;
 	}
 
 	machine->pdata = pdata;
 
 	ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
 	if (ret)
-		goto err_free_machine;
+		goto err;
 
 	card->dev = &pdev->dev;
 	platform_set_drvdata(pdev, card);
@@ -418,8 +413,7 @@
 
 err_fini_utils:
 	tegra_asoc_utils_fini(&machine->util_data);
-err_free_machine:
-	kfree(machine);
+err:
 	return ret;
 }
 
@@ -447,8 +441,6 @@
 
 	tegra_asoc_utils_fini(&machine->util_data);
 
-	kfree(machine);
-
 	return 0;
 }
 
@@ -461,18 +453,7 @@
 	.probe = tegra_wm8903_driver_probe,
 	.remove = __devexit_p(tegra_wm8903_driver_remove),
 };
-
-static int __init tegra_wm8903_modinit(void)
-{
-	return platform_driver_register(&tegra_wm8903_driver);
-}
-module_init(tegra_wm8903_modinit);
-
-static void __exit tegra_wm8903_modexit(void)
-{
-	platform_driver_unregister(&tegra_wm8903_driver);
-}
-module_exit(tegra_wm8903_modexit);
+module_platform_driver(tegra_wm8903_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver");
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index b3a7efa..043eb7c 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -118,11 +118,21 @@
 static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_card *card = codec->card;
+	int ret;
 
-	snd_soc_dapm_nc_pin(dapm, "LHPOUT");
-	snd_soc_dapm_nc_pin(dapm, "RHPOUT");
-	snd_soc_dapm_nc_pin(dapm, "MICIN");
+	ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1,
+					   TEGRA_DAS_DAP_SEL_DAC1);
+	if (ret) {
+		dev_err(card->dev, "Can't set up DAS DAP connection\n");
+		return ret;
+	}
+	ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1,
+					   TEGRA_DAS_DAC_SEL_DAP1);
+	if (ret) {
+		dev_err(card->dev, "Can't set up DAS DAC connection\n");
+		return ret;
+	}
 
 	return 0;
 }
@@ -147,6 +157,7 @@
 	.num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets),
 	.dapm_routes = trimslice_audio_map,
 	.num_dapm_routes = ARRAY_SIZE(trimslice_audio_map),
+	.fully_routed = true,
 };
 
 static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
@@ -155,15 +166,17 @@
 	struct tegra_trimslice *trimslice;
 	int ret;
 
-	trimslice = kzalloc(sizeof(struct tegra_trimslice), GFP_KERNEL);
+	trimslice = devm_kzalloc(&pdev->dev, sizeof(struct tegra_trimslice),
+				 GFP_KERNEL);
 	if (!trimslice) {
 		dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err;
 	}
 
 	ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
 	if (ret)
-		goto err_free_trimslice;
+		goto err;
 
 	card->dev = &pdev->dev;
 	platform_set_drvdata(pdev, card);
@@ -180,8 +193,7 @@
 
 err_fini_utils:
 	tegra_asoc_utils_fini(&trimslice->util_data);
-err_free_trimslice:
-	kfree(trimslice);
+err:
 	return ret;
 }
 
@@ -194,8 +206,6 @@
 
 	tegra_asoc_utils_fini(&trimslice->util_data);
 
-	kfree(trimslice);
-
 	return 0;
 }
 
@@ -207,18 +217,7 @@
 	.probe = tegra_snd_trimslice_probe,
 	.remove = __devexit_p(tegra_snd_trimslice_remove),
 };
-
-static int __init snd_tegra_trimslice_init(void)
-{
-	return platform_driver_register(&tegra_snd_trimslice_driver);
-}
-module_init(snd_tegra_trimslice_init);
-
-static void __exit snd_tegra_trimslice_exit(void)
-{
-	platform_driver_unregister(&tegra_snd_trimslice_driver);
-}
-module_exit(snd_tegra_trimslice_exit);
+module_platform_driver(tegra_snd_trimslice_driver);
 
 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 MODULE_DESCRIPTION("Trimslice machine ASoC driver");
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index a4e3f55..28db4ca 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -223,18 +223,7 @@
 	},
 };
 
-static int __init txx9aclc_ac97_init(void)
-{
-	return platform_driver_register(&txx9aclc_ac97_driver);
-}
-
-static void __exit txx9aclc_ac97_exit(void)
-{
-	platform_driver_unregister(&txx9aclc_ac97_driver);
-}
-
-module_init(txx9aclc_ac97_init);
-module_exit(txx9aclc_ac97_exit);
+module_platform_driver(txx9aclc_ac97_driver);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 MODULE_DESCRIPTION("TXx9 ACLC AC97 driver");
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index 3de99af..93931de 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -438,17 +438,7 @@
 	.remove = __devexit_p(txx9aclc_soc_platform_remove),
 };
 
-static int __init snd_txx9aclc_pcm_init(void)
-{
-	return platform_driver_register(&txx9aclc_pcm_driver);
-}
-module_init(snd_txx9aclc_pcm_init);
-
-static void __exit snd_txx9aclc_pcm_exit(void)
-{
-	platform_driver_unregister(&txx9aclc_pcm_driver);
-}
-module_exit(snd_txx9aclc_pcm_exit);
+module_platform_driver(txx9aclc_pcm_driver);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");