diff --git a/Documentation/devicetree/bindings/sound/alc5632.txt b/Documentation/devicetree/bindings/sound/alc5632.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8608f747dcfe1869ae5061007a2fd583000ef545
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/alc5632.txt
@@ -0,0 +1,24 @@
+ALC5632 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "realtek,alc5632"
+
+  - reg : the I2C address of the device.
+
+  - gpio-controller : Indicates this device is a GPIO controller.
+
+  - #gpio-cells : Should be two. The first cell is the pin number and the
+    second cell is used to specify optional parameters (currently unused).
+
+Example:
+
+alc5632: alc5632@1e {
+	compatible = "realtek,alc5632";
+	reg = <0x1a>;
+
+	gpio-controller;
+	#gpio-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/sound/imx-audmux.txt b/Documentation/devicetree/bindings/sound/imx-audmux.txt
new file mode 100644
index 0000000000000000000000000000000000000000..215aa9817213e9ea8e469a94f19fcc251aa87352
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audmux.txt
@@ -0,0 +1,13 @@
+Freescale Digital Audio Mux (AUDMUX) device
+
+Required properties:
+- compatible : "fsl,imx21-audmux" for AUDMUX version firstly used on i.MX21,
+  or "fsl,imx31-audmux" for the version firstly used on i.MX31.
+- reg : Should contain AUDMUX registers location and length
+
+Example:
+
+audmux@021d8000 {
+	compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
+	reg = <0x021d8000 0x4000>;
+};
diff --git a/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/sgtl5000.txt
similarity index 100%
rename from Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt
rename to Documentation/devicetree/bindings/sound/sgtl5000.txt
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt b/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b77a97c9101e2bf4a3daa1367cc8ecf4cf8b3b8a
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt
@@ -0,0 +1,59 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-alc5632"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the ALC5632's pins:
+
+  ALC5632 pins:
+
+  * SPK_OUTP
+  * SPK_OUTN
+  * HP_OUT_L
+  * HP_OUT_R
+  * AUX_OUT_P
+  * AUX_OUT_N
+  * LINE_IN_L
+  * LINE_IN_R
+  * PHONE_P
+  * PHONE_N
+  * MIC1_P
+  * MIC1_N
+  * MIC2_P
+  * MIC2_N
+  * MICBIAS1
+  * DMICDAT
+
+  Board connectors:
+
+  * Headset Stereophone
+  * Int Spk
+  * Headset Mic
+  * Digital Mic
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S controller
+- nvidia,audio-codec : The phandle of the ALC5632 audio codec
+
+Example:
+
+sound {
+	compatible = "nvidia,tegra-audio-alc5632-paz00",
+				 "nvidia,tegra-audio-alc5632";
+
+	nvidia,model = "Compal PAZ00";
+
+	nvidia,audio-routing =
+				"Int Spk", "SPK_OUTP",
+				"Int Spk", "SPK_OUTN",
+				"Headset Mic","MICBIAS1",
+				"MIC1_N", "Headset Mic",
+				"MIC1_P", "Headset Mic",
+				"Headset Stereophone", "HP_OUT_R",
+				"Headset Stereophone", "HP_OUT_L";
+
+	nvidia,i2s-controller = <&tegra_i2s1>;
+	nvidia,audio-codec = <&alc5632>;
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a20008ab319a9d5acba2f57bdaff0a5338a1d547..82ac057a24a948797af5575fd97d46e8161557e4 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -34,6 +34,7 @@ picochip	Picochip Ltd
 powervr	Imagination Technologies
 qcom	Qualcomm, Inc.
 ramtron	Ramtron International
+realtek Realtek Semiconductor Corp.
 samsung	Samsung Semiconductor
 sbs	Smart Battery System
 schindler	Schindler
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 12e3a0fb9bec3f9a358f42be1cd8ce2cb8195435..6f75ba3b8a391f634de7bd77ea2cae1392763571 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -860,7 +860,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     [Multiple options for each card instance]
     model	- force the model name
-    position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
+    position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF,
+    		   3 = VIACOMBO, 4 = COMBO)
     probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
     		  When the bit 8 (0x100) is set, the lower 8 bits are used
 		  as the "fixed" codec slots; i.e. the driver probes the
@@ -925,6 +926,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	    (Usually SD_LPIB register is more accurate than the
 	    position buffer.)
 
+	    position_fix=3 is specific to VIA devices.  The position
+	    of the capture stream is checked from both LPIB and POSBUF
+	    values.  position_fix=4 is a combination mode, using LPIB
+	    for playback and POSBUF for capture.
+
     NB: If you get many "azx_get_response timeout" messages at
     loading, it's likely a problem of interrupts (e.g. ACPI irq
     routing).  Try to boot with options like "pci=noacpi".  Also, you
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index c8c54544abc5c757e27c32c322b812fabf598769..d97d992ced14f97a5d423f79f1ae9b9f230fc55e 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -8,37 +8,10 @@ ALC880
   5stack-digout	5-jack in back, 2-jack in front, a SPDIF out
   6stack	6-jack in back, 2-jack in front
   6stack-digout	6-jack with a SPDIF out
-  w810		3-jack
-  z71v		3-jack (HP shared SPDIF)
-  asus		3-jack (ASUS Mobo)
-  asus-w1v	ASUS W1V
-  asus-dig	ASUS with SPDIF out
-  asus-dig2	ASUS with SPDIF out (using GPIO2)
-  uniwill	3-jack
-  fujitsu	Fujitsu Laptops (Pi1536)
-  F1734		2-jack
-  lg		LG laptop (m1 express dual)
-  lg-lw		LG LW20/LW25 laptop
-  tcl		TCL S700
-  clevo		Clevo laptops (m520G, m665n)
-  medion	Medion Rim 2150
-  test		for testing/debugging purpose, almost all controls can be
-		adjusted.  Appearing only when compiled with
-		$CONFIG_SND_DEBUG=y
-  auto		auto-config reading BIOS (default)
 
 ALC260
 ======
-  fujitsu	Fujitsu S7020
-  acer		Acer TravelMate
-  will		Will laptops (PB V7900)
-  replacer	Replacer 672V
-  favorit100	Maxdata Favorit 100XS
-  basic		fixed pin assignment (old default model)
-  test		for testing/debugging purpose, almost all controls can
-		adjusted.  Appearing only when compiled with
-		$CONFIG_SND_DEBUG=y
-  auto		auto-config reading BIOS (default)
+  N/A
 
 ALC262
 ======
@@ -70,55 +43,7 @@ ALC680
 
 ALC882/883/885/888/889
 ======================
-  3stack-dig	3-jack with SPDIF I/O
-  6stack-dig	6-jack digital with SPDIF I/O
-  arima		Arima W820Di1
-  targa		Targa T8, MSI-1049 T8
-  asus-a7j	ASUS A7J
-  asus-a7m	ASUS A7M
-  macpro	MacPro support
-  mb5		Macbook 5,1
-  macmini3	Macmini 3,1
-  mba21		Macbook Air 2,1
-  mbp3		Macbook Pro rev3
-  imac24	iMac 24'' with jack detection
-  imac91	iMac 9,1
-  w2jc		ASUS W2JC
-  3stack-2ch-dig	3-jack with SPDIF I/O (ALC883)
-  alc883-6stack-dig	6-jack digital with SPDIF I/O (ALC883)
-  3stack-6ch    3-jack 6-channel
-  3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
-  6stack-dig-demo  6-jack digital for Intel demo board
-  acer		Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
-  acer-aspire	Acer Aspire 9810
-  acer-aspire-4930g Acer Aspire 4930G
-  acer-aspire-6530g Acer Aspire 6530G
-  acer-aspire-7730g Acer Aspire 7730G
-  acer-aspire-8930g Acer Aspire 8930G
-  medion	Medion Laptops
-  targa-dig	Targa/MSI
-  targa-2ch-dig	Targa/MSI with 2-channel
-  targa-8ch-dig Targa/MSI with 8-channel (MSI GX620)
-  laptop-eapd   3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
-  lenovo-101e	Lenovo 101E
-  lenovo-nb0763	Lenovo NB0763
-  lenovo-ms7195-dig Lenovo MS7195
-  lenovo-sky	Lenovo Sky
-  haier-w66	Haier W66
-  3stack-hp	HP machines with 3stack (Lucknow, Samba boards)
-  6stack-dell	Dell machines with 6stack (Inspiron 530)
-  mitac		Mitac 8252D
-  clevo-m540r	Clevo M540R (6ch + digital)
-  clevo-m720	Clevo M720 laptop series
-  fujitsu-pi2515 Fujitsu AMILO Pi2515
-  fujitsu-xa3530 Fujitsu AMILO XA3530
-  3stack-6ch-intel Intel DG33* boards
-  intel-alc889a	Intel IbexPeak with ALC889A
-  intel-x58	Intel DX58 with ALC889
-  asus-p5q	ASUS P5Q-EM boards
-  mb31		MacBook 3,1
-  sony-vaio-tt  Sony VAIO TT
-  auto		auto-config reading BIOS (default)
+  N/A
 
 ALC861/660
 ==========
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index 91fee3b45fb80f75ac406dfbba093f1f49a418c1..7813c06a5c71d70a353862a6fec6713d3d73da3b 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -59,7 +59,12 @@ a case, you can change the default method via `position_fix` option.
 `position_fix=1` means to use LPIB method explicitly.
 `position_fix=2` means to use the position-buffer.
 `position_fix=3` means to use a combination of both methods, needed
-for some VIA and ATI controllers.  0 is the default value for all other
+for some VIA controllers.  The capture stream position is corrected
+by comparing both LPIB and position-buffer values.
+`position_fix=4` is another combination available for all controllers,
+and uses LPIB for the playback and the position-buffer for the capture
+streams.
+0 is the default value for all other
 controllers, the automatic check and fallback to LPIB as described in
 the above.  If you get a problem of repeated sounds, this option might
 help.
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 24203f9a67967df314a6d3776d6ac581a8d22fb3..b5c1dae8327fd87ccf945913a185397142135ca5 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -817,23 +817,12 @@ void __init ep93xx_register_i2s(void)
 #define EP93XX_I2SCLKDIV_MASK		(EP93XX_SYSCON_I2SCLKDIV_ORIDE | \
 					 EP93XX_SYSCON_I2SCLKDIV_SPOL)
 
-int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
+int ep93xx_i2s_acquire(void)
 {
 	unsigned val;
 
-	/* Sanity check */
-	if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK)
-		return -EINVAL;
-	if (i2s_config & ~EP93XX_I2SCLKDIV_MASK)
-		return -EINVAL;
-
-	/* Must have only one of I2SONSSP/I2SONAC97 set */
-	if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) ==
-	    (i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97))
-		return -EINVAL;
-
-	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
-	ep93xx_devcfg_set_bits(i2s_pins);
+	ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97,
+			EP93XX_SYSCON_DEVCFG_I2S_MASK);
 
 	/*
 	 * This is potentially racy with the clock api for i2s_mclk, sclk and 
@@ -843,7 +832,7 @@ int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
 	 */
 	val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
 	val &= ~EP93XX_I2SCLKDIV_MASK;
-	val |= i2s_config;
+	val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL;
 	ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV);
 
 	return 0;
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index d4c934931f9d4cbf85c580355a0115f154ca241e..ad63d4be693fbfeca164a080a73e871118df2425 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -59,7 +59,7 @@ void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
 int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
 void ep93xx_keypad_release_gpio(struct platform_device *pdev);
 void ep93xx_register_i2s(void);
-int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config);
+int ep93xx_i2s_acquire(void);
 void ep93xx_i2s_release(void);
 void ep93xx_register_ac97(void);
 
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 4defb97bbfc866400fe57fe4c5178a778c30a91f..3919fba52ac80c30196eb1abe5bc152b7edd0f0b 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -46,7 +46,6 @@ config SOC_IMX21
 	bool
 	select MACH_MX21
 	select CPU_ARM926T
-	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
@@ -55,7 +54,6 @@ config SOC_IMX25
 	bool
 	select ARCH_MX25
 	select CPU_ARM926T
-	select ARCH_MXC_AUDMUX_V2
 	select ARCH_MXC_IOMUX_V3
 	select MXC_AVIC
 
@@ -63,7 +61,6 @@ config SOC_IMX27
 	bool
 	select MACH_MX27
 	select CPU_ARM926T
-	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
@@ -72,7 +69,6 @@ config SOC_IMX31
 	bool
 	select CPU_V6
 	select IMX_HAVE_PLATFORM_MXC_RNGA
-	select ARCH_MXC_AUDMUX_V2
 	select MXC_AVIC
 	select SMP_ON_UP if SMP
 
@@ -80,7 +76,6 @@ config SOC_IMX35
 	bool
 	select CPU_V6
 	select ARCH_MXC_IOMUX_V3
-	select ARCH_MXC_AUDMUX_V2
 	select HAVE_EPIT
 	select MXC_AVIC
 	select SMP_ON_UP if SMP
@@ -89,7 +84,6 @@ config SOC_IMX5
 	select CPU_V7
 	select MXC_TZIC
 	select ARCH_MXC_IOMUX_V3
-	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
 	select ARCH_MX5
 	bool
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 5db3e1463af7714bff06e8b17f526804148e89b0..5f2f91d1798b6470e2ef9ab5fd88ca22deadafcd 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -32,7 +32,6 @@
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
 #include <mach/hardware.h>
-#include <mach/audmux.h>
 
 #include "devices-imx27.h"
 
@@ -306,25 +305,6 @@ void __init eukrea_mbimx27_baseboard_init(void)
 	mxc_gpio_setup_multiple_pins(eukrea_mbimx27_pins,
 		ARRAY_SIZE(eukrea_mbimx27_pins), "MBIMX27");
 
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320) \
-	|| defined(CONFIG_SND_SOC_EUKREA_TLV320_MODULE)
-	/* SSI unit master I2S codec connected to SSI_PINS_4*/
-	mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
-			MXC_AUDMUX_V1_PCR_SYN |
-			MXC_AUDMUX_V1_PCR_TFSDIR |
-			MXC_AUDMUX_V1_PCR_TCLKDIR |
-			MXC_AUDMUX_V1_PCR_RFSDIR |
-			MXC_AUDMUX_V1_PCR_RCLKDIR |
-			MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
-			MXC_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
-			MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4)
-	);
-	mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4,
-			MXC_AUDMUX_V1_PCR_SYN |
-			MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
-	);
-#endif
-
 	imx27_add_imx_uart1(&uart_pdata);
 	imx27_add_imx_uart2(&uart_pdata);
 #if !defined(MACH_EUKREA_CPUIMX27_USEUART4)
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
index d817fc80b986c8231da7df66dea5231f6211f4b5..aaa592fdb9ce38b84e70985a9e1496cae0c9496b 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
@@ -37,7 +37,6 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx51.h>
-#include <mach/audmux.h>
 
 #include "devices-imx51.h"
 
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 66e8726253faa5370dd23443110b472b7671ba13..2cf603e11c4f36786f06299b00cc8ffd9e7f4125 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -31,7 +31,6 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/mx25.h>
-#include <mach/audmux.h>
 
 #include "devices-imx25.h"
 
@@ -241,22 +240,6 @@ void __init eukrea_mbimxsd25_baseboard_init(void)
 			ARRAY_SIZE(eukrea_mbimxsd_pads)))
 		printk(KERN_ERR "error setting mbimxsd pads !\n");
 
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320)
-	/* SSI unit master I2S codec connected to SSI_AUD5*/
-	mxc_audmux_v2_configure_port(0,
-			MXC_AUDMUX_V2_PTCR_SYN |
-			MXC_AUDMUX_V2_PTCR_TFSDIR |
-			MXC_AUDMUX_V2_PTCR_TFSEL(4) |
-			MXC_AUDMUX_V2_PTCR_TCLKDIR |
-			MXC_AUDMUX_V2_PTCR_TCSEL(4),
-			MXC_AUDMUX_V2_PDCR_RXDSEL(4)
-	);
-	mxc_audmux_v2_configure_port(4,
-			MXC_AUDMUX_V2_PTCR_SYN,
-			MXC_AUDMUX_V2_PDCR_RXDSEL(0)
-	);
-#endif
-
 	imx25_add_imx_uart1(&uart_pdata);
 	imx25_add_imx_fb(&eukrea_mximxsd_fb_pdata);
 	imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 0f0af02b31821528185ff69401784a76c9e0efe6..fd8bf8a425a7a49c0daa7f90bb185c22f2ba2e7c 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -38,7 +38,6 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
-#include <mach/audmux.h>
 
 #include "devices-imx35.h"
 
@@ -252,22 +251,6 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
 			ARRAY_SIZE(eukrea_mbimxsd_pads)))
 		printk(KERN_ERR "error setting mbimxsd pads !\n");
 
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320)
-	/* SSI unit master I2S codec connected to SSI_AUD4 */
-	mxc_audmux_v2_configure_port(0,
-			MXC_AUDMUX_V2_PTCR_SYN |
-			MXC_AUDMUX_V2_PTCR_TFSDIR |
-			MXC_AUDMUX_V2_PTCR_TFSEL(3) |
-			MXC_AUDMUX_V2_PTCR_TCLKDIR |
-			MXC_AUDMUX_V2_PTCR_TCSEL(3),
-			MXC_AUDMUX_V2_PDCR_RXDSEL(3)
-	);
-	mxc_audmux_v2_configure_port(3,
-			MXC_AUDMUX_V2_PTCR_SYN,
-			MXC_AUDMUX_V2_PDCR_RXDSEL(0)
-	);
-#endif
-
 	imx35_add_imx_uart1(&uart_pdata);
 	imx35_add_ipu_core(&mx3_ipu_data);
 	imx35_add_mx3_sdc_fb(&mx3fb_pdata);
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index c2766ae02b4f049f6bfa6ecf79a312226e35a909..428459fbca4b5351701be89b1a136074bf9a4db6 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -263,6 +263,7 @@ static void __init visstrim_m10_board_init(void)
 	imx27_add_fec(NULL);
 	imx_add_gpio_keys(&visstrim_gpio_keys_platform_data);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	imx_add_platform_device("mx27vis", 0, NULL, 0, NULL, 0);
 }
 
 static void __init visstrim_m10_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index d3b9c6b5edde091d56f3196be79a5cf245410137..541152e450c420bbf2cd65ca6061bee935957191 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -36,7 +36,6 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
 #include <asm/mach/time.h>
-#include <mach/audmux.h>
 #include <mach/irqs.h>
 #include <mach/ulpi.h>
 
@@ -359,18 +358,6 @@ static void __init pca100_init(void)
 
 	imx27_soc_init();
 
-	/* SSI unit */
-	mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
-				  MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
-				  MXC_AUDMUX_V1_PCR_TFCSEL(3) |
-				  MXC_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */
-				  MXC_AUDMUX_V1_PCR_RXDSEL(3));
-	mxc_audmux_v1_configure_port(3,
-				  MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
-				  MXC_AUDMUX_V1_PCR_TFCSEL(0) |
-				  MXC_AUDMUX_V1_PCR_TFSDIR |
-				  MXC_AUDMUX_V1_PCR_RXDSEL(0));
-
 	ret = mxc_gpio_setup_multiple_pins(pca100_pins,
 			ARRAY_SIZE(pca100_pins), "PCA100");
 	if (ret)
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 06dc106519aec6f8826b1589b3c765cad148bfc5..237474fcca23eb352bacc211d1173fd7f21d0ac7 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -37,7 +37,6 @@
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
 #include <mach/ulpi.h>
-#include <mach/audmux.h>
 
 #include "devices-imx35.h"
 
@@ -362,18 +361,6 @@ static void __init pcm043_init(void)
 
 	mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
 
-	mxc_audmux_v2_configure_port(3,
-			MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
-			MXC_AUDMUX_V2_PTCR_TFSEL(0) |
-			MXC_AUDMUX_V2_PTCR_TFSDIR,
-			MXC_AUDMUX_V2_PDCR_RXDSEL(0));
-
-	mxc_audmux_v2_configure_port(0,
-			MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
-			MXC_AUDMUX_V2_PTCR_TCSEL(3) |
-			MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
-			MXC_AUDMUX_V2_PDCR_RXDSEL(3));
-
 	imx35_add_fec(NULL);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 	imx35_add_imx2_wdt(NULL);
diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index 3f05dfebacc9f7c2bb7df18c0646b7a775100097..14d540edfd1e6d9817ecf0f624de8d710b6dfa4d 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -75,6 +75,10 @@ void __init mx21_init_irq(void)
 	mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
 }
 
+static const struct resource imx21_audmux_res[] __initconst = {
+	DEFINE_RES_MEM(MX21_AUDMUX_BASE_ADDR, SZ_4K),
+};
+
 void __init imx21_soc_init(void)
 {
 	mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
@@ -85,4 +89,6 @@ void __init imx21_soc_init(void)
 	mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
 
 	imx_add_imx_dma();
+	platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
+					ARRAY_SIZE(imx21_audmux_res));
 }
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index cc4d152bd9bd9342d1c0ff53e6b9cfd0a52c9a90..153b457acdc02db153b520540093860dd768df14 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -83,6 +83,10 @@ static struct sdma_platform_data imx25_sdma_pdata __initdata = {
 	.script_addrs = &imx25_sdma_script,
 };
 
+static const struct resource imx25_audmux_res[] __initconst = {
+	DEFINE_RES_MEM(MX25_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
 void __init imx25_soc_init(void)
 {
 	/* i.mx25 has the i.mx31 type gpio */
@@ -93,4 +97,7 @@ void __init imx25_soc_init(void)
 
 	/* i.mx25 has the i.mx35 type sdma */
 	imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
+	/* i.mx25 has the i.mx31 type audmux */
+	platform_device_register_simple("imx31-audmux", 0, imx25_audmux_res,
+					ARRAY_SIZE(imx25_audmux_res));
 }
diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index 96dd1f5ea7bddc32d8745b7447b56cf20402640e..8cb3f5e3e56901b04228408407f2d7ecb34bee7d 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -75,6 +75,10 @@ void __init mx27_init_irq(void)
 	mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
 }
 
+static const struct resource imx27_audmux_res[] __initconst = {
+	DEFINE_RES_MEM(MX27_AUDMUX_BASE_ADDR, SZ_4K),
+};
+
 void __init imx27_soc_init(void)
 {
 	/* i.mx27 has the i.mx21 type gpio */
@@ -86,4 +90,7 @@ void __init imx27_soc_init(void)
 	mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
 
 	imx_add_imx_dma();
+	/* imx27 has the imx21 type audmux */
+	platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
+					ARRAY_SIZE(imx27_audmux_res));
 }
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
index 31807d2a8b7bf1a65d57c8f4cb748bb9e6697934..2530c151b7b3d5aa50a1731c9ceaf1a3cc949ab8 100644
--- a/arch/arm/mach-imx/mm-imx3.c
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -158,6 +158,10 @@ static struct sdma_platform_data imx31_sdma_pdata __initdata = {
 	.script_addrs = &imx31_to2_sdma_script,
 };
 
+static const struct resource imx31_audmux_res[] __initconst = {
+	DEFINE_RES_MEM(MX31_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
 void __init imx31_soc_init(void)
 {
 	int to_version = mx31_revision() >> 4;
@@ -175,6 +179,8 @@ void __init imx31_soc_init(void)
 	}
 
 	imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+	platform_device_register_simple("imx31-audmux", 0, imx31_audmux_res,
+					ARRAY_SIZE(imx31_audmux_res));
 }
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
@@ -241,6 +247,10 @@ static struct sdma_platform_data imx35_sdma_pdata __initdata = {
 	.script_addrs = &imx35_to2_sdma_script,
 };
 
+static const struct resource imx35_audmux_res[] __initconst = {
+	DEFINE_RES_MEM(MX35_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
 void __init imx35_soc_init(void)
 {
 	int to_version = mx35_revision() >> 4;
@@ -259,5 +269,8 @@ void __init imx35_soc_init(void)
 	}
 
 	imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+	/* i.mx35 has the i.mx31 type audmux */
+	platform_device_register_simple("imx31-audmux", 0, imx35_audmux_res,
+					ARRAY_SIZE(imx35_audmux_res));
 }
 #endif /* ifdef CONFIG_SOC_IMX35 */
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index bc17dfea38170872c24216165715e8af60144feb..90d7880bb372a95a7ae5b0f57f897311215dbaf8 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -170,6 +170,18 @@ static struct sdma_platform_data imx53_sdma_pdata __initdata = {
 	.script_addrs = &imx53_sdma_script,
 };
 
+static const struct resource imx50_audmux_res[] __initconst = {
+	DEFINE_RES_MEM(MX50_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
+static const struct resource imx51_audmux_res[] __initconst = {
+	DEFINE_RES_MEM(MX51_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
+static const struct resource imx53_audmux_res[] __initconst = {
+	DEFINE_RES_MEM(MX53_AUDMUX_BASE_ADDR, SZ_16K),
+};
+
 void __init imx50_soc_init(void)
 {
 	/* i.mx50 has the i.mx31 type gpio */
@@ -179,6 +191,10 @@ void __init imx50_soc_init(void)
 	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
 	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
 	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+
+	/* i.mx50 has the i.mx31 type audmux */
+	platform_device_register_simple("imx31-audmux", 0, imx50_audmux_res,
+					ARRAY_SIZE(imx50_audmux_res));
 }
 
 void __init imx51_soc_init(void)
@@ -191,6 +207,9 @@ void __init imx51_soc_init(void)
 
 	/* i.mx51 has the i.mx35 type sdma */
 	imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+	/* i.mx51 has the i.mx31 type audmux */
+	platform_device_register_simple("imx31-audmux", 0, imx51_audmux_res,
+					ARRAY_SIZE(imx51_audmux_res));
 }
 
 void __init imx53_soc_init(void)
@@ -206,4 +225,7 @@ void __init imx53_soc_init(void)
 
 	/* i.mx53 has the i.mx35 type sdma */
 	imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
+	/* i.mx53 has the i.mx31 type audmux */
+	platform_device_register_simple("imx31-audmux", 0, imx53_audmux_res,
+					ARRAY_SIZE(imx53_audmux_res));
 }
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index 01f8c8992880450d1a69d861d718d63434133977..7e99c3f340fc5e61c85e7023afc9e345a5a130d8 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -83,6 +83,11 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
 	},
 };
 
+static struct platform_device openrd_client_audio_device = {
+	.name		= "openrd-client-audio",
+	.id		= -1,
+};
+
 static int __initdata uart1;
 
 static int __init sd_uart_selection(char *str)
@@ -172,6 +177,7 @@ static void __init openrd_init(void)
 	kirkwood_i2c_init();
 
 	if (machine_is_openrd_client() || machine_is_openrd_ultimate()) {
+		platform_device_register(&openrd_client_audio_device);
 		i2c_register_board_info(0, i2c_board_info,
 			ARRAY_SIZE(i2c_board_info));
 		kirkwood_audio_init();
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
index 966b2b3bb8136a6e0ecb4b1a41190f10f379ba19..f9d2a11b7f9649468c26a882323df785e27783a0 100644
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ b/arch/arm/mach-kirkwood/t5325-setup.c
@@ -106,6 +106,11 @@ static struct platform_device hp_t5325_button_device = {
 	}
 };
 
+static struct platform_device hp_t5325_audio_device = {
+	.name		= "t5325-audio",
+	.id		= -1,
+};
+
 static unsigned int hp_t5325_mpp_config[] __initdata = {
 	MPP0_NF_IO2,
 	MPP1_SPI_MOSI,
@@ -179,6 +184,7 @@ static void __init hp_t5325_init(void)
 	kirkwood_sata_init(&hp_t5325_sata_data);
 	kirkwood_ehci_init();
 	platform_device_register(&hp_t5325_button_device);
+	platform_device_register(&hp_t5325_audio_device);
 
 	i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info));
 	kirkwood_audio_init();
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 4f8d66f044e7b90ef64fc40e27441f063ac1afa9..922ab0dc2bcd339ef888e23c1839d5cb25efe6f2 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -37,7 +37,6 @@ comment "OMAP Board Type"
 config MACH_OMAP_INNOVATOR
 	bool "TI Innovator"
 	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
-	select OMAP_MCBSP
 	help
           TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
           have such a board.
@@ -45,7 +44,6 @@ config MACH_OMAP_INNOVATOR
 config MACH_OMAP_H2
 	bool "TI H2 Support"
 	depends on ARCH_OMAP1 && ARCH_OMAP16XX
-	select OMAP_MCBSP
     	help
 	  TI OMAP 1610/1611B H2 board support. Say Y here if you have such
 	  a board.
@@ -72,7 +70,6 @@ config MACH_HERALD
 config MACH_OMAP_OSK
 	bool "TI OSK Support"
 	depends on ARCH_OMAP1 && ARCH_OMAP16XX
-	select OMAP_MCBSP
     	help
 	  TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
           if you have such a board.
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 11c85cd2731a10115e43c6bd4d95aaf956d28198..9923f92b5450e4f74701d560a31c9ba04782748f 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -6,7 +6,9 @@
 obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
 obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
 
-obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
+ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
+obj-y += mcbsp.o
+endif
 
 obj-$(CONFIG_OMAP_32K_TIMER)	+= timer32k.o
 
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index 1d76a63c098362742773ac89298c1a8cf0980e6f..187b2fe132e98c08d0fd822532e8d7dfb2ac99c1 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -28,7 +28,6 @@
 #include <plat/mux.h>
 #include <plat/mmc.h>
 #include <plat/omap7xx.h>
-#include <plat/mcbsp.h>
 
 #include "clock.h"
 
@@ -250,16 +249,8 @@ static struct platform_device omap_pcm = {
 	.id	= -1,
 };
 
-OMAP_MCBSP_PLATFORM_DEVICE(1);
-OMAP_MCBSP_PLATFORM_DEVICE(2);
-OMAP_MCBSP_PLATFORM_DEVICE(3);
-
 static void omap_init_audio(void)
 {
-	platform_device_register(&omap_mcbsp1);
-	platform_device_register(&omap_mcbsp2);
-	if (!cpu_is_omap7xx())
-		platform_device_register(&omap_mcbsp3);
 	platform_device_register(&omap_pcm);
 }
 
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index 91f9abbd3250bf981faa1e583de43d4d1f9c3490..3e8410a999903cec5a24d11510b1cd67c7f3c303 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -419,18 +419,6 @@ static int __init omap1_mcbsp_init(void)
 	if (!cpu_class_is_omap1())
 		return -ENODEV;
 
-	if (cpu_is_omap7xx())
-		omap_mcbsp_count = OMAP7XX_MCBSP_COUNT;
-	else if (cpu_is_omap15xx())
-		omap_mcbsp_count = OMAP15XX_MCBSP_COUNT;
-	else if (cpu_is_omap16xx())
-		omap_mcbsp_count = OMAP16XX_MCBSP_COUNT;
-
-	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
-								GFP_KERNEL);
-	if (!mcbsp_ptr)
-		return -ENOMEM;
-
 	if (cpu_is_omap7xx())
 		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
 					OMAP7XX_MCBSP_RES_SZ,
@@ -449,7 +437,7 @@ static int __init omap1_mcbsp_init(void)
 					omap16xx_mcbsp_pdata,
 					OMAP16XX_MCBSP_COUNT);
 
-	return omap_mcbsp_init();
+	return 0;
 }
 
 arch_initcall(omap1_mcbsp_init);
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index bd76394ccaf8c90de32b824dc5dc65675a73fb18..06326a6e460d0bcf539977fa3f3951718d6de8a8 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -17,7 +17,9 @@ obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
 obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
 
-obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
+ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
+obj-y += mcbsp.o
+endif
 
 obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
 
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 4e9071589bfb60ac3bfb5a222eefcfebc700bd03..90c76d340fb3b6b7a4119822504279e9211b5228 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -41,6 +41,7 @@
 #include <video/omap-panel-nokia-dsi.h>
 #include <video/omap-panel-picodlp.h>
 #include <linux/wl12xx.h>
+#include <linux/platform_data/omap-abe-twl6040.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -378,12 +379,40 @@ static struct platform_device sdp4430_dmic_codec = {
 	.id	= -1,
 };
 
+static struct omap_abe_twl6040_data sdp4430_abe_audio_data = {
+	.card_name = "SDP4430",
+	.has_hs		= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+	.has_hf		= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+	.has_ep		= 1,
+	.has_aux	= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+	.has_vibra	= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+
+	.has_dmic	= 1,
+	.has_hsmic	= 1,
+	.has_mainmic	= 1,
+	.has_submic	= 1,
+	.has_afm	= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+
+	.jack_detection = 1,
+	/* MCLK input is 38.4MHz */
+	.mclk_freq	= 38400000,
+};
+
+static struct platform_device sdp4430_abe_audio = {
+	.name		= "omap-abe-twl6040",
+	.id		= -1,
+	.dev = {
+		.platform_data = &sdp4430_abe_audio_data,
+	},
+};
+
 static struct platform_device *sdp4430_devices[] __initdata = {
 	&sdp4430_gpio_keys_device,
 	&sdp4430_leds_gpio,
 	&sdp4430_leds_pwm,
 	&sdp4430_vbat,
 	&sdp4430_dmic_codec,
+	&sdp4430_abe_audio,
 };
 
 static struct omap_musb_board_data musb_board_data = {
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 28fc271f70316510b5268c2a212adcac3718fce1..e4415917693f3d04cfa096283c031d8780b56321 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -28,6 +28,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/wl12xx.h>
+#include <linux/platform_data/omap-abe-twl6040.h>
 
 #include <mach/hardware.h>
 #include <asm/hardware/gic.h>
@@ -91,9 +92,34 @@ static struct platform_device leds_gpio = {
 	},
 };
 
+static struct omap_abe_twl6040_data panda_abe_audio_data = {
+	/* Audio out */
+	.has_hs		= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+	/* HandsFree through expasion connector */
+	.has_hf		= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+	/* PandaBoard: FM TX, PandaBoardES: can be connected to audio out */
+	.has_aux	= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+	/* PandaBoard: FM RX, PandaBoardES: audio in */
+	.has_afm	= ABE_TWL6040_LEFT | ABE_TWL6040_RIGHT,
+	/* No jack detection. */
+	.jack_detection	= 0,
+	/* MCLK input is 38.4MHz */
+	.mclk_freq	= 38400000,
+
+};
+
+static struct platform_device panda_abe_audio = {
+	.name		= "omap-abe-twl6040",
+	.id		= -1,
+	.dev = {
+		.platform_data = &panda_abe_audio_data,
+	},
+};
+
 static struct platform_device *panda_devices[] __initdata = {
 	&leds_gpio,
 	&wl1271_device,
+	&panda_abe_audio,
 };
 
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
@@ -252,8 +278,25 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 	return 0;
 }
 
+static struct twl4030_codec_data twl6040_codec = {
+	/* single-step ramp for headset and handsfree */
+	.hs_left_step	= 0x0f,
+	.hs_right_step	= 0x0f,
+	.hf_left_step	= 0x1d,
+	.hf_right_step	= 0x1d,
+};
+
+static struct twl4030_audio_data twl6040_audio = {
+	.codec		= &twl6040_codec,
+	.audpwron_gpio	= 127,
+	.naudint_irq	= OMAP44XX_IRQ_SYS_2N,
+	.irq_base	= TWL6040_CODEC_IRQ_BASE,
+};
+
 /* Panda board uses the common PMIC configuration */
-static struct twl4030_platform_data omap4_panda_twldata;
+static struct twl4030_platform_data omap4_panda_twldata = {
+	.audio		= &twl6040_audio,
+};
 
 /*
  * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
@@ -485,6 +528,20 @@ void omap4_panda_display_init(void)
 	omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
 }
 
+static void omap4_panda_init_rev(void)
+{
+	if (cpu_is_omap443x()) {
+		/* PandaBoard 4430 */
+		/* ASoC audio configuration */
+		panda_abe_audio_data.card_name = "PandaBoard";
+		panda_abe_audio_data.has_hsmic = 1;
+	} else {
+		/* PandaBoard ES */
+		/* ASoC audio configuration */
+		panda_abe_audio_data.card_name = "PandaBoardES";
+	}
+}
+
 static void __init omap4_panda_init(void)
 {
 	int package = OMAP_PACKAGE_CBS;
@@ -498,6 +555,7 @@ static void __init omap4_panda_init(void)
 	if (ret)
 		pr_err("error setting wl12xx data: %d\n", ret);
 
+	omap4_panda_init_rev();
 	omap4_panda_i2c_init();
 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
 	platform_device_register(&omap_vwlan_device);
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 283d11eae693115b42d2bbcca9176f019274960c..e9fae652cd048f02ff7768367f7b3c64bbc04a8d 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -26,7 +26,6 @@
 
 #include <plat/tc.h>
 #include <plat/board.h>
-#include <plat/mcbsp.h>
 #include <plat/mmc.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
@@ -304,29 +303,8 @@ static struct platform_device omap_pcm = {
 	.id	= -1,
 };
 
-/*
- * OMAP2420 has 2 McBSP ports
- * OMAP2430 has 5 McBSP ports
- * OMAP3 has 5 McBSP ports
- * OMAP4 has 4 McBSP ports
- */
-OMAP_MCBSP_PLATFORM_DEVICE(1);
-OMAP_MCBSP_PLATFORM_DEVICE(2);
-OMAP_MCBSP_PLATFORM_DEVICE(3);
-OMAP_MCBSP_PLATFORM_DEVICE(4);
-OMAP_MCBSP_PLATFORM_DEVICE(5);
-
 static void omap_init_audio(void)
 {
-	platform_device_register(&omap_mcbsp1);
-	platform_device_register(&omap_mcbsp2);
-	if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		platform_device_register(&omap_mcbsp3);
-		platform_device_register(&omap_mcbsp4);
-	}
-	if (cpu_is_omap243x() || cpu_is_omap34xx())
-		platform_device_register(&omap_mcbsp5);
-
 	platform_device_register(&omap_pcm);
 }
 
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index fb4bcf81a183311c9a0baf95ed7a92af61ae01ff..ecc039e794db4cdc8b3f284292f0a59f1445fe8e 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -34,7 +34,7 @@
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 
-/* McBSP internal signal muxing function */
+/* McBSP1 internal signal muxing function for OMAP2/3 */
 static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
 				   const char *src)
 {
@@ -65,6 +65,42 @@ static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
 	return 0;
 }
 
+/* McBSP4 internal signal muxing function for OMAP4 */
+#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX	(1 << 31)
+#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX	(1 << 30)
+static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal,
+				   const char *src)
+{
+	u32 v;
+
+	/*
+	 * In CONTROL_MCBSPLP register only bit 30 (CLKR mux), and bit 31 (FSR
+	 * mux) is used */
+	v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP);
+
+	if (!strcmp(signal, "clkr")) {
+		if (!strcmp(src, "clkr"))
+			v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX;
+		else if (!strcmp(src, "clkx"))
+			v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX;
+		else
+			return -EINVAL;
+	} else if (!strcmp(signal, "fsr")) {
+		if (!strcmp(src, "fsr"))
+			v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX;
+		else if (!strcmp(src, "fsx"))
+			v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX;
+		else
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
+
+	omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP);
+
+	return 0;
+}
+
 /* McBSP CLKS source switching function */
 static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk,
 				   const char *src)
@@ -146,9 +182,15 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 		pdata->has_ccr = true;
 	}
 	pdata->set_clk_src = omap2_mcbsp_set_clk_src;
-	if (id == 1)
+
+	/* On OMAP2/3 the McBSP1 port has 6 pin configuration */
+	if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4)
 		pdata->mux_signal = omap2_mcbsp1_mux_rx_clk;
 
+	/* On OMAP4 the McBSP4 port has 6 pin configuration */
+	if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4)
+		pdata->mux_signal = omap4_mcbsp4_mux_rx_clk;
+
 	if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
 		if (id == 2)
 			/* The FIFO has 1024 + 256 locations */
@@ -180,7 +222,6 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 					name, oh->name);
 		return PTR_ERR(pdev);
 	}
-	omap_mcbsp_count++;
 	return 0;
 }
 
@@ -188,11 +229,6 @@ static int __init omap2_mcbsp_init(void)
 {
 	omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
 
-	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
-								GFP_KERNEL);
-	if (!mcbsp_ptr)
-		return -ENOMEM;
-
-	return omap_mcbsp_init();
+	return 0;
 }
 arch_initcall(omap2_mcbsp_init);
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
index cd3c97e2ee75045afb4a855f7adf03066bca478b..32a30f38ba0ce65d243a7d3f6cbeaa70bf08dbec 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -102,6 +102,7 @@ static struct wm8962_pdata wm8962_pdata __initdata = {
 		0x8000 | WM8962_GPIO_FN_DMICDAT,
 		WM8962_GPIO_FN_IRQ,    /* Open drain mode */
 	},
+	.in4_dc_measure = true,
 };
 
 static struct wm9081_pdata wm9081_pdata __initdata = {
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index b4718b00e827b90e73edf01b252379cca75e4bcc..8f6da7f134b35a2a1e73228c6e25b8d481116850 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -737,26 +737,18 @@ static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
 	return ret;
 }
 
-static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
-{
-	int ret;
-
-	if (is_porta)
-		ret = fsi_ak4642_set_rate(dev, rate, enable);
-	else
-		ret = fsi_hdmi_set_rate(dev, rate, enable);
-
-	return ret;
-}
-
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_BRS_INV,
-
-	.portb_flags = SH_FSI_BRS_INV |
-		       SH_FSI_BRM_INV |
-		       SH_FSI_LRS_INV |
-		       SH_FSI_FMT_SPDIF,
-	.set_rate = fsi_set_rate,
+	.port_a = {
+		.flags		= SH_FSI_BRS_INV,
+		.set_rate	= fsi_ak4642_set_rate,
+	},
+	.port_b = {
+		.flags		= SH_FSI_BRS_INV |
+				  SH_FSI_BRM_INV |
+				  SH_FSI_LRS_INV |
+				  SH_FSI_FMT_SPDIF,
+		.set_rate	= fsi_hdmi_set_rate,
+	},
 };
 
 static struct resource fsi_resources[] = {
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 7b53cda418513a63f69d34a90e903aa4d7b76f1c..d99e780dffca664e8d1b86e97a7a12cf4386526d 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -860,7 +860,7 @@ static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
 	return clk_enable(clk);
 }
 
-static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
+static int fsi_b_set_rate(struct device *dev, int rate, int enable)
 {
 	struct clk *fsib_clk;
 	struct clk *fdiv_clk = &sh7372_fsidivb_clk;
@@ -869,10 +869,6 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
 	int ackmd_bpfmd;
 	int ret;
 
-	/* FSIA is slave mode. nothing to do here */
-	if (is_porta)
-		return 0;
-
 	/* clock start */
 	switch (rate) {
 	case 44100:
@@ -916,14 +912,16 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
 }
 
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags =	SH_FSI_BRS_INV,
-
-	.portb_flags =	SH_FSI_BRS_INV	|
+	.port_a = {
+		.flags = SH_FSI_BRS_INV,
+	},
+	.port_b = {
+		.flags = SH_FSI_BRS_INV	|
 			SH_FSI_BRM_INV	|
 			SH_FSI_LRS_INV	|
 			SH_FSI_FMT_SPDIF,
-
-	.set_rate = fsi_set_rate,
+		.set_rate = fsi_b_set_rate,
+	}
 };
 
 static struct resource fsi_resources[] = {
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index dcebb1230f7fd3cd6f6e492c97507a483dcef3b8..c722f9ce691827e8924674119b75708ba7ea6428 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -88,12 +88,6 @@ config IMX_HAVE_IOMUX_V1
 config ARCH_MXC_IOMUX_V3
 	bool
 
-config ARCH_MXC_AUDMUX_V1
-	bool
-
-config ARCH_MXC_AUDMUX_V2
-	bool
-
 config IRAM_ALLOC
 	bool
 	select GENERIC_ALLOCATOR
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 076db84f3e3183a47096cded0ac90abf50aa23b4..e81290c27c655bdf4ab5f4d58a61ee41cc8013e9 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -14,8 +14,6 @@ obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
 obj-$(CONFIG_MXC_PWM)  += pwm.o
 obj-$(CONFIG_MXC_ULPI) += ulpi.o
 obj-$(CONFIG_MXC_USE_EPIT) += epit.o
-obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
-obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
 ifdef CONFIG_SND_IMX_SOC
diff --git a/arch/arm/plat-mxc/audmux-v1.c b/arch/arm/plat-mxc/audmux-v1.c
deleted file mode 100644
index 1180bef7664b3ca34359d37940a2fd20081b7017..0000000000000000000000000000000000000000
--- a/arch/arm/plat-mxc/audmux-v1.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
- *
- * Initial development of this code was funded by
- * Phytec Messtechnik GmbH, http://www.phytec.de
- *
- * 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.
- *
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <mach/audmux.h>
-#include <mach/hardware.h>
-
-static void __iomem *audmux_base;
-
-static unsigned char port_mapping[] = {
-	0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
-};
-
-int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
-{
-	if (!audmux_base) {
-		printk("%s: not configured\n", __func__);
-		return -ENOSYS;
-	}
-
-	if (port >= ARRAY_SIZE(port_mapping))
-		return -EINVAL;
-
-	writel(pcr, audmux_base + port_mapping[port]);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port);
-
-static int mxc_audmux_v1_init(void)
-{
-#ifdef CONFIG_MACH_MX21
-	if (cpu_is_mx21())
-		audmux_base = MX21_IO_ADDRESS(MX21_AUDMUX_BASE_ADDR);
-	else
-#endif
-#ifdef CONFIG_MACH_MX27
-	if (cpu_is_mx27())
-		audmux_base = MX27_IO_ADDRESS(MX27_AUDMUX_BASE_ADDR);
-	else
-#endif
-		(void)0;
-	
-	return 0;
-}
-
-postcore_initcall(mxc_audmux_v1_init);
diff --git a/arch/arm/plat-mxc/include/mach/audmux.h b/arch/arm/plat-mxc/include/mach/audmux.h
deleted file mode 100644
index 6fda788ed0e96eb01e49843e800fb546e1f43e36..0000000000000000000000000000000000000000
--- a/arch/arm/plat-mxc/include/mach/audmux.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef __MACH_AUDMUX_H
-#define __MACH_AUDMUX_H
-
-#define MX27_AUDMUX_HPCR1_SSI0		0
-#define MX27_AUDMUX_HPCR2_SSI1		1
-#define MX27_AUDMUX_HPCR3_SSI_PINS_4	2
-#define MX27_AUDMUX_PPCR1_SSI_PINS_1	3
-#define MX27_AUDMUX_PPCR2_SSI_PINS_2	4
-#define MX27_AUDMUX_PPCR3_SSI_PINS_3	5
-
-#define MX31_AUDMUX_PORT1_SSI0		0
-#define MX31_AUDMUX_PORT2_SSI1		1
-#define MX31_AUDMUX_PORT3_SSI_PINS_3	2
-#define MX31_AUDMUX_PORT4_SSI_PINS_4	3
-#define MX31_AUDMUX_PORT5_SSI_PINS_5	4
-#define MX31_AUDMUX_PORT6_SSI_PINS_6	5
-
-#define MX51_AUDMUX_PORT1_SSI0		0
-#define MX51_AUDMUX_PORT2_SSI1		1
-#define MX51_AUDMUX_PORT3		2
-#define MX51_AUDMUX_PORT4		3
-#define MX51_AUDMUX_PORT5		4
-#define MX51_AUDMUX_PORT6		5
-#define MX51_AUDMUX_PORT7		6
-
-/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
-#define MXC_AUDMUX_V1_PCR_INMMASK(x)	((x) & 0xff)
-#define MXC_AUDMUX_V1_PCR_INMEN		(1 << 8)
-#define MXC_AUDMUX_V1_PCR_TXRXEN	(1 << 10)
-#define MXC_AUDMUX_V1_PCR_SYN		(1 << 12)
-#define MXC_AUDMUX_V1_PCR_RXDSEL(x)	(((x) & 0x7) << 13)
-#define MXC_AUDMUX_V1_PCR_RFCSEL(x)	(((x) & 0xf) << 20)
-#define MXC_AUDMUX_V1_PCR_RCLKDIR	(1 << 24)
-#define MXC_AUDMUX_V1_PCR_RFSDIR	(1 << 25)
-#define MXC_AUDMUX_V1_PCR_TFCSEL(x)	(((x) & 0xf) << 26)
-#define MXC_AUDMUX_V1_PCR_TCLKDIR	(1 << 30)
-#define MXC_AUDMUX_V1_PCR_TFSDIR	(1 << 31)
-
-/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
-#define MXC_AUDMUX_V2_PTCR_TFSDIR	(1 << 31)
-#define MXC_AUDMUX_V2_PTCR_TFSEL(x)	(((x) & 0xf) << 27)
-#define MXC_AUDMUX_V2_PTCR_TCLKDIR	(1 << 26)
-#define MXC_AUDMUX_V2_PTCR_TCSEL(x)	(((x) & 0xf) << 22)
-#define MXC_AUDMUX_V2_PTCR_RFSDIR	(1 << 21)
-#define MXC_AUDMUX_V2_PTCR_RFSEL(x)	(((x) & 0xf) << 17)
-#define MXC_AUDMUX_V2_PTCR_RCLKDIR	(1 << 16)
-#define MXC_AUDMUX_V2_PTCR_RCSEL(x)	(((x) & 0xf) << 12)
-#define MXC_AUDMUX_V2_PTCR_SYN		(1 << 11)
-
-#define MXC_AUDMUX_V2_PDCR_RXDSEL(x)	(((x) & 0x7) << 13)
-#define MXC_AUDMUX_V2_PDCR_TXRXEN	(1 << 12)
-#define MXC_AUDMUX_V2_PDCR_MODE(x)	(((x) & 0x3) << 8)
-#define MXC_AUDMUX_V2_PDCR_INMMASK(x)	((x) & 0xff)
-
-int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr);
-
-int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
-		unsigned int pdcr);
-
-#endif /* __MACH_AUDMUX_H */
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index aa59f4247dc53bba585fa7f93e050c10902a0708..8f81503a4df77ee6cb1c0c9ad52d723db9aa3f89 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -110,14 +110,6 @@ config OMAP_MUX_WARNINGS
 	  to change the pin multiplexing setup.	 When there are no warnings
 	  printed, it's safe to deselect OMAP_MUX for your product.
 
-config OMAP_MCBSP
-	bool "McBSP support"
-	depends on ARCH_OMAP
-	default y
-	help
-	  Say Y here if you want support for the OMAP Multichannel
-	  Buffered Serial Port.
-
 config OMAP_MBOX_FWK
 	tristate "Mailbox framework support"
 	depends on ARCH_OMAP
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9a584614e7e66feb051ddde13f61545f94632290..c0fe2757b695e74f098edbdca4125541d842d4a1 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -17,8 +17,6 @@ obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
 obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
 obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
 
-obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
-
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
 obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
 obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 8fa74e2c9d6ec6898968774a62b1c1ac65c15bfe..18814127809aa031d3d5abc1ff64c5000ba1cd49 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -27,271 +27,10 @@
 #include <linux/spinlock.h>
 #include <linux/clk.h>
 
-/* macro for building platform_device for McBSP ports */
-#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr)		\
-static struct platform_device omap_mcbsp##port_nr = {	\
-	.name	= "omap-mcbsp-dai",			\
-	.id	= port_nr - 1,			\
-}
-
 #define MCBSP_CONFIG_TYPE2	0x2
 #define MCBSP_CONFIG_TYPE3	0x3
 #define MCBSP_CONFIG_TYPE4	0x4
 
-/* McBSP register numbers. Register address offset = num * reg_step */
-enum {
-	/* Common registers */
-	OMAP_MCBSP_REG_SPCR2 = 4,
-	OMAP_MCBSP_REG_SPCR1,
-	OMAP_MCBSP_REG_RCR2,
-	OMAP_MCBSP_REG_RCR1,
-	OMAP_MCBSP_REG_XCR2,
-	OMAP_MCBSP_REG_XCR1,
-	OMAP_MCBSP_REG_SRGR2,
-	OMAP_MCBSP_REG_SRGR1,
-	OMAP_MCBSP_REG_MCR2,
-	OMAP_MCBSP_REG_MCR1,
-	OMAP_MCBSP_REG_RCERA,
-	OMAP_MCBSP_REG_RCERB,
-	OMAP_MCBSP_REG_XCERA,
-	OMAP_MCBSP_REG_XCERB,
-	OMAP_MCBSP_REG_PCR0,
-	OMAP_MCBSP_REG_RCERC,
-	OMAP_MCBSP_REG_RCERD,
-	OMAP_MCBSP_REG_XCERC,
-	OMAP_MCBSP_REG_XCERD,
-	OMAP_MCBSP_REG_RCERE,
-	OMAP_MCBSP_REG_RCERF,
-	OMAP_MCBSP_REG_XCERE,
-	OMAP_MCBSP_REG_XCERF,
-	OMAP_MCBSP_REG_RCERG,
-	OMAP_MCBSP_REG_RCERH,
-	OMAP_MCBSP_REG_XCERG,
-	OMAP_MCBSP_REG_XCERH,
-
-	/* OMAP1-OMAP2420 registers */
-	OMAP_MCBSP_REG_DRR2 = 0,
-	OMAP_MCBSP_REG_DRR1,
-	OMAP_MCBSP_REG_DXR2,
-	OMAP_MCBSP_REG_DXR1,
-
-	/* OMAP2430 and onwards */
-	OMAP_MCBSP_REG_DRR = 0,
-	OMAP_MCBSP_REG_DXR = 2,
-	OMAP_MCBSP_REG_SYSCON =	35,
-	OMAP_MCBSP_REG_THRSH2,
-	OMAP_MCBSP_REG_THRSH1,
-	OMAP_MCBSP_REG_IRQST = 40,
-	OMAP_MCBSP_REG_IRQEN,
-	OMAP_MCBSP_REG_WAKEUPEN,
-	OMAP_MCBSP_REG_XCCR,
-	OMAP_MCBSP_REG_RCCR,
-	OMAP_MCBSP_REG_XBUFFSTAT,
-	OMAP_MCBSP_REG_RBUFFSTAT,
-	OMAP_MCBSP_REG_SSELCR,
-};
-
-/* OMAP3 sidetone control registers */
-#define OMAP_ST_REG_REV		0x00
-#define OMAP_ST_REG_SYSCONFIG	0x10
-#define OMAP_ST_REG_IRQSTATUS	0x18
-#define OMAP_ST_REG_IRQENABLE	0x1C
-#define OMAP_ST_REG_SGAINCR	0x24
-#define OMAP_ST_REG_SFIRCR	0x28
-#define OMAP_ST_REG_SSELCR	0x2C
-
-/************************** McBSP SPCR1 bit definitions ***********************/
-#define RRST			0x0001
-#define RRDY			0x0002
-#define RFULL			0x0004
-#define RSYNC_ERR		0x0008
-#define RINTM(value)		((value)<<4)	/* bits 4:5 */
-#define ABIS			0x0040
-#define DXENA			0x0080
-#define CLKSTP(value)		((value)<<11)	/* bits 11:12 */
-#define RJUST(value)		((value)<<13)	/* bits 13:14 */
-#define ALB			0x8000
-#define DLB			0x8000
-
-/************************** McBSP SPCR2 bit definitions ***********************/
-#define XRST		0x0001
-#define XRDY		0x0002
-#define XEMPTY		0x0004
-#define XSYNC_ERR	0x0008
-#define XINTM(value)	((value)<<4)		/* bits 4:5 */
-#define GRST		0x0040
-#define FRST		0x0080
-#define SOFT		0x0100
-#define FREE		0x0200
-
-/************************** McBSP PCR bit definitions *************************/
-#define CLKRP		0x0001
-#define CLKXP		0x0002
-#define FSRP		0x0004
-#define FSXP		0x0008
-#define DR_STAT		0x0010
-#define DX_STAT		0x0020
-#define CLKS_STAT	0x0040
-#define SCLKME		0x0080
-#define CLKRM		0x0100
-#define CLKXM		0x0200
-#define FSRM		0x0400
-#define FSXM		0x0800
-#define RIOEN		0x1000
-#define XIOEN		0x2000
-#define IDLE_EN		0x4000
-
-/************************** McBSP RCR1 bit definitions ************************/
-#define RWDLEN1(value)		((value)<<5)	/* Bits 5:7 */
-#define RFRLEN1(value)		((value)<<8)	/* Bits 8:14 */
-
-/************************** McBSP XCR1 bit definitions ************************/
-#define XWDLEN1(value)		((value)<<5)	/* Bits 5:7 */
-#define XFRLEN1(value)		((value)<<8)	/* Bits 8:14 */
-
-/*************************** McBSP RCR2 bit definitions ***********************/
-#define RDATDLY(value)		(value)		/* Bits 0:1 */
-#define RFIG			0x0004
-#define RCOMPAND(value)		((value)<<3)	/* Bits 3:4 */
-#define RWDLEN2(value)		((value)<<5)	/* Bits 5:7 */
-#define RFRLEN2(value)		((value)<<8)	/* Bits 8:14 */
-#define RPHASE			0x8000
-
-/*************************** McBSP XCR2 bit definitions ***********************/
-#define XDATDLY(value)		(value)		/* Bits 0:1 */
-#define XFIG			0x0004
-#define XCOMPAND(value)		((value)<<3)	/* Bits 3:4 */
-#define XWDLEN2(value)		((value)<<5)	/* Bits 5:7 */
-#define XFRLEN2(value)		((value)<<8)	/* Bits 8:14 */
-#define XPHASE			0x8000
-
-/************************* McBSP SRGR1 bit definitions ************************/
-#define CLKGDV(value)		(value)		/* Bits 0:7 */
-#define FWID(value)		((value)<<8)	/* Bits 8:15 */
-
-/************************* McBSP SRGR2 bit definitions ************************/
-#define FPER(value)		(value)		/* Bits 0:11 */
-#define FSGM			0x1000
-#define CLKSM			0x2000
-#define CLKSP			0x4000
-#define GSYNC			0x8000
-
-/************************* McBSP MCR1 bit definitions *************************/
-#define RMCM			0x0001
-#define RCBLK(value)		((value)<<2)	/* Bits 2:4 */
-#define RPABLK(value)		((value)<<5)	/* Bits 5:6 */
-#define RPBBLK(value)		((value)<<7)	/* Bits 7:8 */
-
-/************************* McBSP MCR2 bit definitions *************************/
-#define XMCM(value)		(value)		/* Bits 0:1 */
-#define XCBLK(value)		((value)<<2)	/* Bits 2:4 */
-#define XPABLK(value)		((value)<<5)	/* Bits 5:6 */
-#define XPBBLK(value)		((value)<<7)	/* Bits 7:8 */
-
-/*********************** McBSP XCCR bit definitions *************************/
-#define EXTCLKGATE		0x8000
-#define PPCONNECT		0x4000
-#define DXENDLY(value)		((value)<<12)	/* Bits 12:13 */
-#define XFULL_CYCLE		0x0800
-#define DILB			0x0020
-#define XDMAEN			0x0008
-#define XDISABLE		0x0001
-
-/********************** McBSP RCCR bit definitions *************************/
-#define RFULL_CYCLE		0x0800
-#define RDMAEN			0x0008
-#define RDISABLE		0x0001
-
-/********************** McBSP SYSCONFIG bit definitions ********************/
-#define CLOCKACTIVITY(value)	((value)<<8)
-#define SIDLEMODE(value)	((value)<<3)
-#define ENAWAKEUP		0x0004
-#define SOFTRST			0x0002
-
-/********************** McBSP SSELCR bit definitions ***********************/
-#define SIDETONEEN		0x0400
-
-/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
-#define ST_AUTOIDLE		0x0001
-
-/********************** McBSP Sidetone SGAINCR bit definitions *************/
-#define ST_CH1GAIN(value)	((value<<16))	/* Bits 16:31 */
-#define ST_CH0GAIN(value)	(value)		/* Bits 0:15 */
-
-/********************** McBSP Sidetone SFIRCR bit definitions **************/
-#define ST_FIRCOEFF(value)	(value)		/* Bits 0:15 */
-
-/********************** McBSP Sidetone SSELCR bit definitions **************/
-#define ST_COEFFWRDONE		0x0004
-#define ST_COEFFWREN		0x0002
-#define ST_SIDETONEEN		0x0001
-
-/********************** McBSP DMA operating modes **************************/
-#define MCBSP_DMA_MODE_ELEMENT		0
-#define MCBSP_DMA_MODE_THRESHOLD	1
-#define MCBSP_DMA_MODE_FRAME		2
-
-/********************** McBSP WAKEUPEN bit definitions *********************/
-#define XEMPTYEOFEN		0x4000
-#define XRDYEN			0x0400
-#define XEOFEN			0x0200
-#define XFSXEN			0x0100
-#define XSYNCERREN		0x0080
-#define RRDYEN			0x0008
-#define REOFEN			0x0004
-#define RFSREN			0x0002
-#define RSYNCERREN		0x0001
-
-/* CLKR signal muxing options */
-#define CLKR_SRC_CLKR		0
-#define CLKR_SRC_CLKX		1
-
-/* FSR signal muxing options */
-#define FSR_SRC_FSR		0
-#define FSR_SRC_FSX		1
-
-/* McBSP functional clock sources */
-#define MCBSP_CLKS_PRCM_SRC	0
-#define MCBSP_CLKS_PAD_SRC	1
-
-/* we don't do multichannel for now */
-struct omap_mcbsp_reg_cfg {
-	u16 spcr2;
-	u16 spcr1;
-	u16 rcr2;
-	u16 rcr1;
-	u16 xcr2;
-	u16 xcr1;
-	u16 srgr2;
-	u16 srgr1;
-	u16 mcr2;
-	u16 mcr1;
-	u16 pcr0;
-	u16 rcerc;
-	u16 rcerd;
-	u16 xcerc;
-	u16 xcerd;
-	u16 rcere;
-	u16 rcerf;
-	u16 xcere;
-	u16 xcerf;
-	u16 rcerg;
-	u16 rcerh;
-	u16 xcerg;
-	u16 xcerh;
-	u16 xccr;
-	u16 rccr;
-};
-
-typedef enum {
-	OMAP_MCBSP_WORD_8 = 0,
-	OMAP_MCBSP_WORD_12,
-	OMAP_MCBSP_WORD_16,
-	OMAP_MCBSP_WORD_20,
-	OMAP_MCBSP_WORD_24,
-	OMAP_MCBSP_WORD_32,
-} omap_mcbsp_word_length;
-
 /* Platform specific configuration */
 struct omap_mcbsp_ops {
 	void (*request)(unsigned int);
@@ -312,43 +51,6 @@ struct omap_mcbsp_platform_data {
 	int (*mux_signal)(struct device *dev, const char *signal, const char *src);
 };
 
-struct omap_mcbsp_st_data {
-	void __iomem *io_base_st;
-	bool running;
-	bool enabled;
-	s16 taps[128];	/* Sidetone filter coefficients */
-	int nr_taps;	/* Number of filter coefficients in use */
-	s16 ch0gain;
-	s16 ch1gain;
-};
-
-struct omap_mcbsp {
-	struct device *dev;
-	unsigned long phys_base;
-	unsigned long phys_dma_base;
-	void __iomem *io_base;
-	u8 id;
-	u8 free;
-
-	int rx_irq;
-	int tx_irq;
-
-	/* DMA stuff */
-	u8 dma_rx_sync;
-	u8 dma_tx_sync;
-
-	/* Protect the field .free, while checking if the mcbsp is in use */
-	spinlock_t lock;
-	struct omap_mcbsp_platform_data *pdata;
-	struct clk *fclk;
-	struct omap_mcbsp_st_data *st_data;
-	int dma_op_mode;
-	u16 max_tx_thres;
-	u16 max_rx_thres;
-	void *reg_cache;
-	int reg_cache_size;
-};
-
 /**
  * omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod
  * @sidetone: name of the sidetone device
@@ -357,39 +59,4 @@ struct omap_mcbsp_dev_attr {
 	const char *sidetone;
 };
 
-extern struct omap_mcbsp **mcbsp_ptr;
-extern int omap_mcbsp_count;
-
-int omap_mcbsp_init(void);
-void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
-void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
-void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
-u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
-u16 omap_mcbsp_get_max_rx_threshold(unsigned int id);
-u16 omap_mcbsp_get_fifo_size(unsigned int id);
-u16 omap_mcbsp_get_tx_delay(unsigned int id);
-u16 omap_mcbsp_get_rx_delay(unsigned int id);
-int omap_mcbsp_get_dma_op_mode(unsigned int id);
-int omap_mcbsp_request(unsigned int id);
-void omap_mcbsp_free(unsigned int id);
-void omap_mcbsp_start(unsigned int id, int tx, int rx);
-void omap_mcbsp_stop(unsigned int id, int tx, int rx);
-
-/* McBSP functional clock source changing function */
-extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
-
-/* McBSP signal muxing API */
-void omap2_mcbsp1_mux_clkr_src(u8 mux);
-void omap2_mcbsp1_mux_fsr_src(u8 mux);
-
-int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream);
-int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream);
-
-/* Sidetone specific API */
-int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
-int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain);
-int omap_st_enable(unsigned int id);
-int omap_st_disable(unsigned int id);
-int omap_st_is_enabled(unsigned int id);
-
 #endif
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 639e3ce6c264d4f8af8137efffff5fdf280992cf..9a91fe9de69675ff1d74140bc658257637356090 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -418,6 +418,11 @@ static struct platform_device qi_lb60_charger_device = {
 	},
 };
 
+/* audio */
+static struct platform_device qi_lb60_audio_device = {
+	.name = "qi-lb60-audio",
+	.id = -1,
+};
 
 static struct platform_device *jz_platform_devices[] __initdata = {
 	&jz4740_udc_device,
@@ -434,6 +439,7 @@ static struct platform_device *jz_platform_devices[] __initdata = {
 	&qi_lb60_gpio_keys,
 	&qi_lb60_pwm_beeper,
 	&qi_lb60_charger_device,
+	&qi_lb60_audio_device,
 };
 
 static void __init board_gpio_setup(void)
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index cde7c0085cedf4b239e79cddaee05d5dcc9e81b7..59daae2f29db6514b47612e840ea2d0913d8ff4b 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -769,7 +769,9 @@ static struct platform_device camera_devices[] = {
 
 /* FSI */
 static struct sh_fsi_platform_info fsi_info = {
-	.portb_flags = SH_FSI_BRS_INV,
+	.port_b = {
+		.flags = SH_FSI_BRS_INV,
+	},
 };
 
 static struct resource fsi_resources[] = {
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 2b07fc0169500aab4405b18e9e2a6f024def3f3f..59f4db829e91be6b745acd0f7cccc525d8ef60b0 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -278,7 +278,9 @@ static struct platform_device ceu1_device = {
 /* FSI */
 /* change J20, J21, J22 pin to 1-2 connection to use slave mode */
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_BRS_INV,
+	.port_a = {
+		.flags = SH_FSI_BRS_INV,
+	},
 };
 
 static struct resource fsi_resources[] = {
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 1a02b7537c8bbac9d59d21ee51c1361dd03c01c0..d141b80479b5257d9fff00b9be47e47029e0f163 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -75,6 +75,9 @@ struct regmap {
 	const void *reg_defaults_raw;
 	void *cache;
 	bool cache_dirty;
+
+	struct reg_default *patch;
+	int patch_regs;
 };
 
 struct regcache_ops {
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index d1daa5e9fadf322b4a6e4d9e7f5d60e71eea0e40..5cd2a37e7688a3d7fec59d9a9a6d9f181107a6d3 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -268,6 +268,17 @@ int regcache_sync(struct regmap *map)
 		map->cache_ops->name);
 	name = map->cache_ops->name;
 	trace_regcache_sync(map->dev, name, "start");
+
+	/* Apply any patch first */
+	for (i = 0; i < map->patch_regs; i++) {
+		ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
+		if (ret != 0) {
+			dev_err(map->dev, "Failed to write %x = %x: %d\n",
+				map->patch[i].reg, map->patch[i].def, ret);
+			goto out;
+		}
+	}
+
 	if (!map->cache_dirty)
 		goto out;
 	if (map->cache_ops->sync) {
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 65558034318f3f295abde2fe7a599c4971e7d7ec..7ac234f0b1c59a1db2e5e76772d5d934545c32c7 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -672,6 +672,79 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits_check);
 
+/**
+ * regmap_register_patch: Register and apply register updates to be applied
+ *                        on device initialistion
+ *
+ * @map: Register map to apply updates to.
+ * @regs: Values to update.
+ * @num_regs: Number of entries in regs.
+ *
+ * Register a set of register updates to be applied to the device
+ * whenever the device registers are synchronised with the cache and
+ * apply them immediately.  Typically this is used to apply
+ * corrections to be applied to the device defaults on startup, such
+ * as the updates some vendors provide to undocumented registers.
+ */
+int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
+			  int num_regs)
+{
+	int i, ret;
+	bool bypass;
+
+	/* If needed the implementation can be extended to support this */
+	if (map->patch)
+		return -EBUSY;
+
+	mutex_lock(&map->lock);
+
+	bypass = map->cache_bypass;
+
+	map->cache_bypass = true;
+
+	/* Write out first; it's useful to apply even if we fail later. */
+	for (i = 0; i < num_regs; i++) {
+		ret = _regmap_write(map, regs[i].reg, regs[i].def);
+		if (ret != 0) {
+			dev_err(map->dev, "Failed to write %x = %x: %d\n",
+				regs[i].reg, regs[i].def, ret);
+			goto out;
+		}
+	}
+
+	map->patch = kcalloc(sizeof(struct reg_default), num_regs, GFP_KERNEL);
+	if (map->patch != NULL) {
+		memcpy(map->patch, regs,
+		       num_regs * sizeof(struct reg_default));
+		map->patch_regs = num_regs;
+	} else {
+		ret = -ENOMEM;
+	}
+
+out:
+	map->cache_bypass = bypass;
+
+	mutex_unlock(&map->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_register_patch);
+
+/*
+ * regmap_get_val_bytes(): Report the size of a register value
+ *
+ * Report the size of a register value, mainly intended to for use by
+ * generic infrastructure built on top of regmap.
+ */
+int regmap_get_val_bytes(struct regmap *map)
+{
+	if (map->format.format_write)
+		return -EINVAL;
+
+	return map->format.val_bytes;
+}
+EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
+
 static int __init regmap_initcall(void)
 {
 	regmap_debugfs_initcall();
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 3fb1f407d5e6e36cf0c9cff31d222bff0258b91f..dc3e050116898457e410b4cbc0c14f2cb6c81171 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -185,6 +185,9 @@ struct wm8994_pdata {
         unsigned int jd_scthr:2;
         unsigned int jd_thr:2;
 
+	/* Configure WM1811 jack detection for use with external capacitor */
+	unsigned int jd_ext_cap:1;
+
 	/* WM8958 microphone bias configuration */
 	int micbias[2];
 
diff --git a/include/linux/platform_data/omap-abe-twl6040.h b/include/linux/platform_data/omap-abe-twl6040.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d298ac10fc2358cbe2774a521f6de0c109f1ec5
--- /dev/null
+++ b/include/linux/platform_data/omap-abe-twl6040.h
@@ -0,0 +1,49 @@
+/**
+ * omap-abe-twl6040.h - ASoC machine driver OMAP4+ devices, header.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * All rights reserved.
+ *
+ * Author: 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
+ */
+
+#ifndef _OMAP_ABE_TWL6040_H_
+#define _OMAP_ABE_TWL6040_H_
+
+/* To select if only one channel is connected in a stereo port */
+#define ABE_TWL6040_LEFT	(1 << 0)
+#define ABE_TWL6040_RIGHT	(1 << 1)
+
+struct omap_abe_twl6040_data {
+	char *card_name;
+	/* Feature flags for connected audio pins */
+	u8	has_hs;
+	u8	has_hf;
+	bool	has_ep;
+	u8	has_aux;
+	u8	has_vibra;
+	bool	has_dmic;
+	bool	has_hsmic;
+	bool	has_mainmic;
+	bool	has_submic;
+	u8	has_afm;
+	/* Other features */
+	bool	jack_detection;	/* board can detect jack events */
+	int	mclk_freq;	/* MCLK frequency speed for twl6040 */
+};
+
+#endif /* _OMAP_ABE_TWL6040_H_ */
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index eb93921cdd30252b1c960cf6872585e308c9e9fc..c47898d47c8a8993b27ccea60e57ac9e8def71c3 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -143,12 +143,16 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
 int regmap_update_bits_check(struct regmap *map, unsigned int reg,
 			     unsigned int mask, unsigned int val,
 			     bool *change);
+int regmap_get_val_bytes(struct regmap *map);
 
 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);
 
+int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
+			  int num_regs);
+
 /**
  * Description of an IRQ for the generic regmap irq_chip.
  *
diff --git a/include/sound/control.h b/include/sound/control.h
index b2796e83c7acf3d1b4dd5bfacd76966a4c3eff4e..8332e865c7592c6a3eb48406bc319195c3efd193 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -40,7 +40,7 @@ struct snd_kcontrol_new {
 	snd_ctl_elem_iface_t iface;	/* interface identifier */
 	unsigned int device;		/* device/client number */
 	unsigned int subdevice;		/* subdevice (substream) number */
-	unsigned char *name;		/* ASCII name of item */
+	const unsigned char *name;	/* ASCII name of item */
 	unsigned int index;		/* index of item */
 	unsigned int access;		/* access rights */
 	unsigned int count;		/* count of same elements */
@@ -227,6 +227,11 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
 	return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE);
 }
 
+int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
+			     void (*hook)(void *private_data, int),
+			     void *private_data);
+void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kctl);
+
 /*
  * Helper functions for jack-detection controls
  */
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
new file mode 100644
index 0000000000000000000000000000000000000000..a8fcaa6d531f7caf21fd32398e55ad4b2a140a26
--- /dev/null
+++ b/include/sound/dmaengine_pcm.h
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (C) 2012, Analog Devices Inc.
+ *	Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  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.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifndef __SOUND_DMAENGINE_PCM_H__
+#define __SOUND_DMAENGINE_PCM_H__
+
+#include <sound/pcm.h>
+#include <linux/dmaengine.h>
+
+/**
+ * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM
+ *   substream
+ * @substream: PCM substream
+ */
+static inline enum dma_transfer_direction
+snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
+{
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		return DMA_MEM_TO_DEV;
+	else
+		return DMA_DEV_TO_MEM;
+}
+
+void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data);
+void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream);
+
+int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
+	const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
+int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
+snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream);
+
+int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
+	dma_filter_fn filter_fn, void *filter_data);
+int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
+
+struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
+
+#endif
diff --git a/include/sound/jack.h b/include/sound/jack.h
index 63c790742db47be586cd995cda581bfae9c33b80..58916573db582eab1d19a6d751ebe516c194b834 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -53,6 +53,9 @@ enum snd_jack_types {
 	SND_JACK_BTN_5		= 0x0200,
 };
 
+/* Keep in sync with definitions above */
+#define SND_JACK_SWITCH_TYPES 6
+
 struct snd_jack {
 	struct input_dev *input_dev;
 	int registered;
diff --git a/include/sound/max9768.h b/include/sound/max9768.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f78b41d030ec21ab005efcf034e54dda3afa02e
--- /dev/null
+++ b/include/sound/max9768.h
@@ -0,0 +1,24 @@
+/*
+ * Platform data for MAX9768
+ * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K.
+ * same licence as the driver
+ */
+
+#ifndef __SOUND_MAX9768_PDATA_H__
+#define __SOUND_MAX9768_PDATA_H__
+
+/**
+ * struct max9768_pdata - optional platform specific MAX9768 configuration
+ * @shdn_gpio:	GPIO to SHDN pin. If not valid, pin must be hardwired HIGH
+ * @mute_gpio:	GPIO to MUTE pin. If not valid, control for mute won't be added
+ * @flags: configuration flags, e.g. set classic PWM mode (check datasheet
+ *         regarding "filterless modulation" which is default).
+ */
+struct max9768_pdata {
+	int shdn_gpio;
+	int mute_gpio;
+	unsigned flags;
+#define MAX9768_FLAG_CLASSIC_PWM	(1 << 0)
+};
+
+#endif /* __SOUND_MAX9768_PDATA_H__*/
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 0cf91b2f08caaf4f9a8a70cee07a25cacc108986..0d1112815be3be6ea96a5ec1768382bb70aea571 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -264,7 +264,7 @@ struct snd_pcm_hw_constraint_ratdens {
 
 struct snd_pcm_hw_constraint_list {
 	unsigned int count;
-	unsigned int *list;
+	const unsigned int *list;
 	unsigned int mask;
 };
 
@@ -454,6 +454,7 @@ struct snd_pcm {
 	void *private_data;
 	void (*private_free) (struct snd_pcm *pcm);
 	struct device *dev; /* actual hw device this belongs to */
+	bool internal; /* pcm is for internal use only */
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	struct snd_pcm_oss oss;
 #endif
@@ -475,6 +476,9 @@ extern const struct file_operations snd_pcm_f_ops[2];
 int snd_pcm_new(struct snd_card *card, const char *id, int device,
 		int playback_count, int capture_count,
 		struct snd_pcm **rpcm);
+int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+		int playback_count, int capture_count,
+		struct snd_pcm **rpcm);
 int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);
 
 int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
@@ -781,7 +785,8 @@ void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interva
 			  unsigned int k, struct snd_interval *c);
 void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
 			  const struct snd_interval *b, struct snd_interval *c);
-int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask);
+int snd_interval_list(struct snd_interval *i, unsigned int count,
+		      const unsigned int *list, unsigned int mask);
 int snd_interval_ratnum(struct snd_interval *i,
 			unsigned int rats_count, struct snd_ratnum *rats,
 			unsigned int *nump, unsigned int *denp);
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 9b1aacaa82fedd0fcb63365fae33237627c496c9..b457e87fbd0849efd51fd22445cb76606c8f6d70 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -72,10 +72,16 @@
 #define SH_FSI_BPFMD_32		(5 << 4)
 #define SH_FSI_BPFMD_16		(6 << 4)
 
+struct sh_fsi_port_info {
+	unsigned long flags;
+	int tx_id;
+	int rx_id;
+	int (*set_rate)(struct device *dev, int rate, int enable);
+};
+
 struct sh_fsi_platform_info {
-	unsigned long porta_flags;
-	unsigned long portb_flags;
-	int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
+	struct sh_fsi_port_info port_a;
+	struct sh_fsi_port_info port_b;
 };
 
 /*
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 2413acc54883aad471cf0256b3fc2f8fc6d7ae11..c429f248cf4e995a6a8aa20eaa1ec8af71ddfe74 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 
 struct snd_pcm_substream;
+struct snd_soc_dapm_widget;
 
 /*
  * DAI hardware audio formats.
@@ -238,6 +239,9 @@ struct snd_soc_dai {
 	unsigned char pop_wait:1;
 	unsigned char probed:1;
 
+	struct snd_soc_dapm_widget *playback_widget;
+	struct snd_soc_dapm_widget *capture_widget;
+
 	/* DAI DMA data */
 	void *playback_dma_data;
 	void *capture_dma_data;
@@ -246,10 +250,9 @@ struct snd_soc_dai {
 	unsigned int rate;
 
 	/* parent platform/codec */
-	union {
-		struct snd_soc_platform *platform;
-		struct snd_soc_codec *codec;
-	};
+	struct snd_soc_platform *platform;
+	struct snd_soc_codec *codec;
+
 	struct snd_soc_card *card;
 
 	struct list_head list;
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index d26a9b784772d797e88a529f199342f277e32390..e46107fffeb48b8c5832eea797bb7ec2b69c92a0 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -243,6 +243,10 @@
 {	.id = snd_soc_dapm_supply, .name = wname, .reg = wreg,	\
 	.shift = wshift, .invert = winvert, .event = wevent, \
 	.event_flags = wflags}
+#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay) \
+{	.id = snd_soc_dapm_regulator_supply, .name = wname, \
+	.reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
+	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
 
 /* dapm kcontrol types */
 #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
@@ -322,6 +326,8 @@ struct snd_soc_dapm_context;
 
 int dapm_reg_event(struct snd_soc_dapm_widget *w,
 		   struct snd_kcontrol *kcontrol, int event);
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol, int event);
 
 /* dapm controls */
 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
@@ -346,11 +352,12 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *uncontrol);
 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *uncontrol);
-int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
-	const struct snd_soc_dapm_widget *widget);
 int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
 	const struct snd_soc_dapm_widget *widget,
 	int num);
+int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
+				 struct snd_soc_dai *dai);
+int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
 
 /* dapm path setup */
 int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
@@ -361,10 +368,16 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
 			     const struct snd_soc_dapm_route *route, int num);
 
 /* dapm events */
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
-	const char *stream, int event);
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+			      struct snd_soc_dai *dai, int event);
 void snd_soc_dapm_shutdown(struct snd_soc_card *card);
 
+/* external DAPM widget events */
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+		struct snd_kcontrol *kcontrol, int connect);
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+				 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e);
+
 /* dapm sys fs - used by the core */
 int snd_soc_dapm_sys_add(struct device *dev);
 void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
@@ -411,9 +424,11 @@ enum snd_soc_dapm_type {
 	snd_soc_dapm_pre,			/* machine specific pre widget - exec first */
 	snd_soc_dapm_post,			/* machine specific post widget - exec last */
 	snd_soc_dapm_supply,		/* power/clock supply */
+	snd_soc_dapm_regulator_supply,	/* external regulator */
 	snd_soc_dapm_aif_in,		/* audio interface input */
 	snd_soc_dapm_aif_out,		/* audio interface output */
 	snd_soc_dapm_siggen,		/* signal generator */
+	snd_soc_dapm_dai,		/* link to DAI structure */
 };
 
 /*
@@ -434,8 +449,8 @@ struct snd_soc_dapm_route {
 
 /* dapm audio path between two widgets */
 struct snd_soc_dapm_path {
-	char *name;
-	char *long_name;
+	const char *name;
+	const char *long_name;
 
 	/* source (input) and sink (output) widgets */
 	struct snd_soc_dapm_widget *source;
@@ -458,13 +473,15 @@ struct snd_soc_dapm_path {
 /* dapm widget */
 struct snd_soc_dapm_widget {
 	enum snd_soc_dapm_type id;
-	char *name;		/* widget name */
-	char *sname;	/* stream name */
+	const char *name;		/* widget name */
+	const char *sname;	/* stream name */
 	struct snd_soc_codec *codec;
 	struct snd_soc_platform *platform;
 	struct list_head list;
 	struct snd_soc_dapm_context *dapm;
 
+	void *priv;				/* widget specific data */
+
 	/* dapm control */
 	short reg;						/* negative reg = no direct dapm */
 	unsigned char shift;			/* bits to shift */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 0992dff559593d7015fcef0e5a58dd42134539d6..2ebf7877c148ae717727269a1bb91cab8124b2e9 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -185,6 +185,20 @@
 		 .rreg = xreg_right, .shift = xshift, \
 		 .min = xmin, .max = xmax} }
 
+#define SND_SOC_BYTES(xname, xbase, xregs)		      \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,   \
+	.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
+	.put = snd_soc_bytes_put, .private_value =	      \
+		((unsigned long)&(struct soc_bytes)           \
+		{.base = xbase, .num_regs = xregs }) }
+
+#define SND_SOC_BYTES_MASK(xname, xbase, xregs, xmask)	      \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,   \
+	.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
+	.put = snd_soc_bytes_put, .private_value =	      \
+		((unsigned long)&(struct soc_bytes)           \
+		{.base = xbase, .num_regs = xregs,	      \
+		 .mask = xmask }) }
 
 /*
  * Simplified versions of above macros, declaring a struct and calculating
@@ -366,12 +380,16 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
  *Controls
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
-				  void *data, char *long_name,
+				  void *data, const char *long_name,
 				  const char *prefix);
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
 	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
 	const struct snd_kcontrol_new *controls, int num_controls);
+int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+	const struct snd_kcontrol_new *controls, int num_controls);
+int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
+	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
@@ -409,6 +427,13 @@ int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
+		       struct snd_ctl_elem_info *uinfo);
+int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol);
+int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol);
+
 
 /**
  * struct snd_soc_reg_access - Describes whether a given register is
@@ -505,6 +530,7 @@ struct snd_soc_pcm_stream {
 	unsigned int rate_max;		/* max rate */
 	unsigned int channels_min;	/* min channels */
 	unsigned int channels_max;	/* max channels */
+	unsigned int sig_bits;		/* number of bits of content */
 };
 
 /* SoC audio ops */
@@ -559,6 +585,7 @@ struct snd_soc_codec {
 	unsigned int ac97_created:1; /* Codec has been created by SoC */
 	unsigned int sysfs_registered:1; /* codec has been sysfs registered */
 	unsigned int cache_init:1; /* codec cache has been initialized */
+	unsigned int using_regmap:1; /* using regmap access */
 	u32 cache_only;  /* Suppress writes to hardware */
 	u32 cache_sync; /* Cache needs to be synced to hardware */
 
@@ -637,6 +664,8 @@ struct snd_soc_codec_driver {
 	/* codec stream completion event */
 	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
 
+	bool ignore_pmdown_time;  /* Doesn't benefit from pmdown delay */
+
 	/* probe ordering - for components with runtime dependencies */
 	int probe_order;
 	int remove_order;
@@ -689,6 +718,7 @@ struct snd_soc_platform {
 	int id;
 	struct device *dev;
 	struct snd_soc_platform_driver *driver;
+	struct mutex mutex;
 
 	unsigned int suspended:1; /* platform is suspended */
 	unsigned int probed:1;
@@ -698,6 +728,11 @@ struct snd_soc_platform {
 	struct list_head card_list;
 
 	struct snd_soc_dapm_context dapm;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_platform_root;
+	struct dentry *debugfs_dapm;
+#endif
 };
 
 struct snd_soc_dai_link {
@@ -875,6 +910,12 @@ struct soc_mixer_control {
 	unsigned int reg, rreg, shift, rshift, invert;
 };
 
+struct soc_bytes {
+	int base;
+	int num_regs;
+	u32 mask;
+};
+
 /* enumerated kcontrol */
 struct soc_enum {
 	unsigned short reg;
diff --git a/include/sound/version.h b/include/sound/version.h
index 8fc5321e1ecc739fa7bd0cdb30c7e63ac0fc1e43..cc75024c10895c651d8771f525517080de16de70 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h */
-#define CONFIG_SND_VERSION "1.0.24"
+#define CONFIG_SND_VERSION "1.0.25"
 #define CONFIG_SND_DATE ""
diff --git a/include/sound/wm2200.h b/include/sound/wm2200.h
new file mode 100644
index 0000000000000000000000000000000000000000..79bf55be7ffa844dbea9bf971e1f9832c00c1fcf
--- /dev/null
+++ b/include/sound/wm2200.h
@@ -0,0 +1,41 @@
+/*
+ * linux/sound/wm2200.h -- Platform data for WM2200
+ *
+ * Copyright 2012 Wolfson Microelectronics. PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_WM2200_H
+#define __LINUX_SND_WM2200_H
+
+#define WM2200_GPIO_SET 0x10000
+
+enum wm2200_in_mode {
+	WM2200_IN_SE = 0,
+	WM2200_IN_DIFF = 1,
+	WM2200_IN_DMIC = 2,
+};
+
+enum wm2200_dmic_sup {
+	WM2200_DMIC_SUP_MICVDD = 0,
+	WM2200_DMIC_SUP_MICBIAS1 = 1,
+	WM2200_DMIC_SUP_MICBIAS2 = 2,
+};
+
+struct wm2200_pdata {
+	int reset;      /** GPIO controlling /RESET, if any */
+	int ldo_ena;    /** GPIO controlling LODENA, if any */
+	int irq_flags;
+
+	int gpio_defaults[4];
+
+	enum wm2200_in_mode in_mode[3];
+	enum wm2200_dmic_sup dmic_sup[3];
+
+	int micbias_cfg[2];  /** Register value to configure MICBIAS */
+};
+
+#endif
diff --git a/include/sound/wm8962.h b/include/sound/wm8962.h
index 1750bed7c2f6ed66d92152c089e810e0332b1251..79e6d427b8582b3f9460c25b5fc4fe4bcc086580 100644
--- a/include/sound/wm8962.h
+++ b/include/sound/wm8962.h
@@ -49,6 +49,12 @@ struct wm8962_pdata {
 	bool irq_active_low;
 
 	bool spk_mono;   /* Speaker outputs tied together as mono */
+
+	/**
+	 * This flag should be set if one or both IN4 inputs is wired
+	 * in a DC measurement configuration.
+	 */
+	bool in4_dc_measure;
 };
 
 #endif
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index 444cd6ba0ba70645c8652089d39250e58d30f8cf..41199664666bb4a96d98b5336f6433b333ef12db 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -366,6 +366,8 @@ struct snd_ymfpci {
 #ifdef CONFIG_PM
 	u32 *saved_regs;
 	u32 saved_ydsxgr_mode;
+	u16 saved_dsxg_legacy;
+	u16 saved_dsxg_elegacy;
 #endif
 };
 
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c
index 762af68c8996fbb83a822638f76f2c29a7d63f9a..270790d384e20f06a38f369cf5aa9c980aac4ed6 100644
--- a/sound/aoa/codecs/onyx.c
+++ b/sound/aoa/codecs/onyx.c
@@ -1132,15 +1132,4 @@ static struct i2c_driver onyx_driver = {
 	.id_table = onyx_i2c_id,
 };
 
-static int __init onyx_init(void)
-{
-	return i2c_add_driver(&onyx_driver);
-}
-
-static void __exit onyx_exit(void)
-{
-	i2c_del_driver(&onyx_driver);
-}
-
-module_init(onyx_init);
-module_exit(onyx_exit);
+module_i2c_driver(onyx_driver);
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index fd2188c3df2b4c436c9a6112cbc577c309d2898e..8e63d1f35ce1228cc1f6abb76cb39e1d421ea43a 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -1026,15 +1026,4 @@ static struct i2c_driver tas_driver = {
 	.id_table = tas_i2c_id,
 };
 
-static int __init tas_init(void)
-{
-	return i2c_add_driver(&tas_driver);
-}
-
-static void __exit tas_exit(void)
-{
-	i2c_del_driver(&tas_driver);
-}
-
-module_init(tas_init);
-module_exit(tas_exit);
+module_i2c_driver(tas_driver);
diff --git a/sound/core/control.c b/sound/core/control.c
index 819a5c579a3975f129b2b35e67be0ad12d2780bd..2487a6bb1c545a3338aa19fbd244c952724f1058 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1313,7 +1313,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
 			err = -EPERM;
 			goto __kctl_end;
 		}
-		err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv); 
+		err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
 		if (err > 0) {
 			up_read(&card->controls_rwsem);
 			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
diff --git a/sound/core/init.c b/sound/core/init.c
index 3ac49b1b7cb82ac4c6c6632691efb9d3178cb09e..068cf08d3ffb82360e3e6ee4c24b78be3abde545 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -480,74 +480,104 @@ int snd_card_free(struct snd_card *card)
 
 EXPORT_SYMBOL(snd_card_free);
 
-static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
+/* retrieve the last word of shortname or longname */
+static const char *retrieve_id_from_card_name(const char *name)
 {
-	int i, len, idx_flag = 0, loops = SNDRV_CARDS;
-	const char *spos, *src;
-	char *id;
-	
-	if (nid == NULL) {
-		id = card->shortname;
-		spos = src = id;
-		while (*id != '\0') {
-			if (*id == ' ')
-				spos = id + 1;
-			id++;
-		}
-	} else {
-		spos = src = nid;
+	const char *spos = name;
+
+	while (*name) {
+		if (isspace(*name) && isalnum(name[1]))
+			spos = name + 1;
+		name++;
 	}
-	id = card->id;
-	while (*spos != '\0' && !isalnum(*spos))
-		spos++;
-	if (isdigit(*spos))
-		*id++ = isalpha(src[0]) ? src[0] : 'D';
-	while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) {
-		if (isalnum(*spos))
-			*id++ = *spos;
-		spos++;
+	return spos;
+}
+
+/* return true if the given id string doesn't conflict any other card ids */
+static bool card_id_ok(struct snd_card *card, const char *id)
+{
+	int i;
+	if (!snd_info_check_reserved_words(id))
+		return false;
+	for (i = 0; i < snd_ecards_limit; i++) {
+		if (snd_cards[i] && snd_cards[i] != card &&
+		    !strcmp(snd_cards[i]->id, id))
+			return false;
 	}
-	*id = '\0';
+	return true;
+}
 
-	id = card->id;
+/* copy to card->id only with valid letters from nid */
+static void copy_valid_id_string(struct snd_card *card, const char *src,
+				 const char *nid)
+{
+	char *id = card->id;
+
+	while (*nid && !isalnum(*nid))
+		nid++;
+	if (isdigit(*nid))
+		*id++ = isalpha(*src) ? *src : 'D';
+	while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
+		if (isalnum(*nid))
+			*id++ = *nid;
+		nid++;
+	}
+	*id = 0;
+}
+
+/* Set card->id from the given string
+ * If the string conflicts with other ids, add a suffix to make it unique.
+ */
+static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
+				    const char *nid)
+{
+	int len, loops;
+	bool with_suffix;
+	bool is_default = false;
+	char *id;
 	
-	if (*id == '\0')
+	copy_valid_id_string(card, src, nid);
+	id = card->id;
+
+ again:
+	/* use "Default" for obviously invalid strings
+	 * ("card" conflicts with proc directories)
+	 */
+	if (!*id || !strncmp(id, "card", 4)) {
 		strcpy(id, "Default");
+		is_default = true;
+	}
 
-	while (1) {
-	      	if (loops-- == 0) {
-			snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
-      			strcpy(card->id, card->proc_root->name);
-      			return;
-      		}
-	      	if (!snd_info_check_reserved_words(id))
-      			goto __change;
-		for (i = 0; i < snd_ecards_limit; i++) {
-			if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
-				goto __change;
-		}
-		break;
+	with_suffix = false;
+	for (loops = 0; loops < SNDRV_CARDS; loops++) {
+		if (card_id_ok(card, id))
+			return; /* OK */
 
-	      __change:
 		len = strlen(id);
-		if (idx_flag) {
-			if (id[len-1] != '9')
-				id[len-1]++;
-			else
-				id[len-1] = 'A';
-		} else if ((size_t)len <= sizeof(card->id) - 3) {
-			strcat(id, "_1");
-			idx_flag++;
+		if (!with_suffix) {
+			/* add the "_X" suffix */
+			char *spos = id + len;
+			if (len >  sizeof(card->id) - 3)
+				spos = id + sizeof(card->id) - 3;
+			strcpy(spos, "_1");
+			with_suffix = true;
 		} else {
-			spos = id + len - 2;
-			if ((size_t)len <= sizeof(card->id) - 2)
-				spos++;
-			*(char *)spos++ = '_';
-			*(char *)spos++ = '1';
-			*(char *)spos++ = '\0';
-			idx_flag++;
+			/* modify the existing suffix */
+			if (id[len - 1] != '9')
+				id[len - 1]++;
+			else
+				id[len - 1] = 'A';
 		}
 	}
+	/* fallback to the default id */
+	if (!is_default) {
+		*id = 0;
+		goto again;
+	}
+	/* last resort... */
+	snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
+	if (card->proc_root->name)
+		strcpy(card->id, card->proc_root->name);
 }
 
 /**
@@ -564,7 +594,7 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
 	if (card->id[0] != '\0')
 		return;
 	mutex_lock(&snd_card_mutex);
-	snd_card_set_id_no_lock(card, nid);
+	snd_card_set_id_no_lock(card, nid, nid);
 	mutex_unlock(&snd_card_mutex);
 }
 EXPORT_SYMBOL(snd_card_set_id);
@@ -596,22 +626,12 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
 	memcpy(buf1, buf, copy);
 	buf1[copy] = '\0';
 	mutex_lock(&snd_card_mutex);
-	if (!snd_info_check_reserved_words(buf1)) {
-	     __exist:
+	if (!card_id_ok(NULL, buf1)) {
 		mutex_unlock(&snd_card_mutex);
 		return -EEXIST;
 	}
-	for (idx = 0; idx < snd_ecards_limit; idx++) {
-		if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
-			if (card == snd_cards[idx])
-				goto __ok;
-			else
-				goto __exist;
-		}
-	}
 	strcpy(card->id, buf1);
 	snd_info_card_id_change(card);
-__ok:
 	mutex_unlock(&snd_card_mutex);
 
 	return count;
@@ -665,7 +685,18 @@ int snd_card_register(struct snd_card *card)
 		mutex_unlock(&snd_card_mutex);
 		return 0;
 	}
-	snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id);
+	if (*card->id) {
+		/* make a unique id name from the given string */
+		char tmpid[sizeof(card->id)];
+		memcpy(tmpid, card->id, sizeof(card->id));
+		snd_card_set_id_no_lock(card, tmpid, tmpid);
+	} else {
+		/* create an id from either shortname or longname */
+		const char *src;
+		src = *card->shortname ? card->shortname : card->longname;
+		snd_card_set_id_no_lock(card, src,
+					retrieve_id_from_card_name(src));
+	}
 	snd_cards[card->number] = card;
 	mutex_unlock(&snd_card_mutex);
 	init_info_for_card(card);
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 26edf63b265f439ba7bf5636ffa0c0928cac8db7..471e1e3b0a996da3fec0d21c82a55b87f3460469 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -25,7 +25,7 @@
 #include <sound/jack.h>
 #include <sound/core.h>
 
-static int jack_switch_types[] = {
+static int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
 	SW_HEADPHONE_INSERT,
 	SW_MICROPHONE_INSERT,
 	SW_LINEOUT_INSERT,
@@ -128,7 +128,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
 
 	jack->type = type;
 
-	for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++)
+	for (i = 0; i < SND_JACK_SWITCH_TYPES; i++)
 		if (type & (1 << i))
 			input_set_capability(jack->input_dev, EV_SW,
 					     jack_switch_types[i]);
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 465f0ce772cb594dabe34e3d835c5766ec6d873b..768167925409ecb9be45b3c2ac82c885685da9bc 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -72,7 +72,7 @@ void __snd_printk(unsigned int level, const char *path, int line,
 	char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV";
 #endif
 
-#ifdef CONFIG_SND_DEBUG	
+#ifdef CONFIG_SND_DEBUG
 	if (debug < level)
 		return;
 #endif
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8928ca871c223f17da58f086a75e3b52d1edcf11..6e4bfcc14254cda1c38eb294b9cfce564de76ada 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -650,7 +650,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 	pstr->stream = stream;
 	pstr->pcm = pcm;
 	pstr->substream_count = substream_count;
-	if (substream_count > 0) {
+	if (substream_count > 0 && !pcm->internal) {
 		err = snd_pcm_stream_proc_init(pstr);
 		if (err < 0) {
 			snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
@@ -674,15 +674,18 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 			pstr->substream = substream;
 		else
 			prev->next = substream;
-		err = snd_pcm_substream_proc_init(substream);
-		if (err < 0) {
-			snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
-			if (prev == NULL)
-				pstr->substream = NULL;
-			else
-				prev->next = NULL;
-			kfree(substream);
-			return err;
+
+		if (!pcm->internal) {
+			err = snd_pcm_substream_proc_init(substream);
+			if (err < 0) {
+				snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
+				if (prev == NULL)
+					pstr->substream = NULL;
+				else
+					prev->next = NULL;
+				kfree(substream);
+				return err;
+			}
 		}
 		substream->group = &substream->self_group;
 		spin_lock_init(&substream->self_group.lock);
@@ -696,25 +699,9 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 
 EXPORT_SYMBOL(snd_pcm_new_stream);
 
-/**
- * snd_pcm_new - create a new PCM instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index (zero based)
- * @playback_count: the number of substreams for playback
- * @capture_count: the number of substreams for capture
- * @rpcm: the pointer to store the new pcm instance
- *
- * Creates a new PCM instance.
- *
- * The pcm operators have to be set afterwards to the new instance
- * via snd_pcm_set_ops().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_new(struct snd_card *card, const char *id, int device,
-		int playback_count, int capture_count,
-	        struct snd_pcm ** rpcm)
+static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
+		int playback_count, int capture_count, bool internal,
+		struct snd_pcm **rpcm)
 {
 	struct snd_pcm *pcm;
 	int err;
@@ -735,6 +722,7 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
 	}
 	pcm->card = card;
 	pcm->device = device;
+	pcm->internal = internal;
 	if (id)
 		strlcpy(pcm->id, id, sizeof(pcm->id));
 	if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
@@ -756,8 +744,59 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
 	return 0;
 }
 
+/**
+ * snd_pcm_new - create a new PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new PCM instance.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
+		int playback_count, int capture_count, struct snd_pcm **rpcm)
+{
+	return _snd_pcm_new(card, id, device, playback_count, capture_count,
+			false, rpcm);
+}
 EXPORT_SYMBOL(snd_pcm_new);
 
+/**
+ * snd_pcm_new_internal - create a new internal PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based - shared with normal PCMs)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new internal PCM instance with no userspace device or procfs
+ * entries. This is used by ASoC Back End PCMs in order to create a PCM that
+ * will only be used internally by kernel drivers. i.e. it cannot be opened
+ * by userspace. It provides existing ASoC components drivers with a substream
+ * and access to any private data.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+	int playback_count, int capture_count,
+	struct snd_pcm **rpcm)
+{
+	return _snd_pcm_new(card, id, device, playback_count, capture_count,
+			true, rpcm);
+}
+EXPORT_SYMBOL(snd_pcm_new_internal);
+
 static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
 {
 	struct snd_pcm_substream *substream, *substream_next;
@@ -994,7 +1033,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
 	}
 	for (cidx = 0; cidx < 2; cidx++) {
 		int devtype = -1;
-		if (pcm->streams[cidx].substream == NULL)
+		if (pcm->streams[cidx].substream == NULL || pcm->internal)
 			continue;
 		switch (cidx) {
 		case SNDRV_PCM_STREAM_PLAYBACK:
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 3420bd3da5d70ffec570e058d84b20f39aab49b8..4d18941178e6e933cb0f80f969c4d705c4777caf 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1029,7 +1029,8 @@ static int snd_interval_ratden(struct snd_interval *i,
  *
  * Returns non-zero if the value is changed, zero if not changed.
  */
-int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
+int snd_interval_list(struct snd_interval *i, unsigned int count,
+		      const unsigned int *list, unsigned int mask)
 {
         unsigned int k;
 	struct snd_interval list_range;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 25ed9fe41b89ceaf245278438c7113bc89ddc0f3..3fe99e644eb838a34913f8c6870742e67c227a31 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1586,12 +1586,18 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
 	struct file *file;
 	struct snd_pcm_file *pcm_file;
 	struct snd_pcm_substream *substream1;
+	struct snd_pcm_group *group;
 
 	file = snd_pcm_file_fd(fd);
 	if (!file)
 		return -EBADFD;
 	pcm_file = file->private_data;
 	substream1 = pcm_file->substream;
+	group = kmalloc(sizeof(*group), GFP_KERNEL);
+	if (!group) {
+		res = -ENOMEM;
+		goto _nolock;
+	}
 	down_write(&snd_pcm_link_rwsem);
 	write_lock_irq(&snd_pcm_link_rwlock);
 	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
@@ -1604,11 +1610,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
 		goto _end;
 	}
 	if (!snd_pcm_stream_linked(substream)) {
-		substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC);
-		if (substream->group == NULL) {
-			res = -ENOMEM;
-			goto _end;
-		}
+		substream->group = group;
 		spin_lock_init(&substream->group->lock);
 		INIT_LIST_HEAD(&substream->group->substreams);
 		list_add_tail(&substream->link_list, &substream->group->substreams);
@@ -1620,7 +1622,10 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
  _end:
 	write_unlock_irq(&snd_pcm_link_rwlock);
 	up_write(&snd_pcm_link_rwsem);
+ _nolock:
 	fput(file);
+	if (res < 0)
+		kfree(group);
 	return res;
 }
 
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 130cfe677d60a1ef8bf996c0a61bc0dea35a9da6..14a286a7bf2b01686e450b2a3bc258df59f24e21 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -37,6 +37,8 @@ struct link_master {
 	struct link_ctl_info info;
 	int val;		/* the master value */
 	unsigned int tlv[4];
+	void (*hook)(void *private_data, int);
+	void *hook_private_data;
 };
 
 /*
@@ -126,7 +128,9 @@ static int master_init(struct link_master *master)
 		master->info.count = 1; /* always mono */
 		/* set full volume as default (= no attenuation) */
 		master->val = master->info.max_val;
-		return 0;
+		if (master->hook)
+			master->hook(master->hook_private_data, master->val);
+		return 1;
 	}
 	return -ENOENT;
 }
@@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol,
 		slave_put_val(slave, uval);
 	}
 	kfree(uval);
+	if (master->hook && !err)
+		master->hook(master->hook_private_data, master->val);
 	return 1;
 }
 
@@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 	return kctl;
 }
 EXPORT_SYMBOL(snd_ctl_make_virtual_master);
+
+/**
+ * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
+ * @kcontrol: vmaster kctl element
+ * @hook: the hook function
+ *
+ * Adds the given hook to the vmaster control element so that it's called
+ * at each time when the value is changed.
+ */
+int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
+			     void (*hook)(void *private_data, int),
+			     void *private_data)
+{
+	struct link_master *master = snd_kcontrol_chip(kcontrol);
+	master->hook = hook;
+	master->hook_private_data = private_data;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
+
+/**
+ * snd_ctl_sync_vmaster_hook - Sync the vmaster hook
+ * @kcontrol: vmaster kctl element
+ *
+ * Call the hook function to synchronize with the current value of the given
+ * vmaster element.  NOP when NULL is passed to @kcontrol or the hook doesn't
+ * exist.
+ */
+void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol)
+{
+	struct link_master *master;
+	if (!kcontrol)
+		return;
+	master = snd_kcontrol_chip(kcontrol);
+	if (master->hook)
+		master->hook(master->hook_private_data, master->val);
+}
+EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index bb938153a964811b41f471f064fbd293fb660e77..466a5c8e8354f2c7eb3b08cda3130405968db759 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -26,7 +26,7 @@
 #include <sound/mpu401.h>
 #include <sound/hwdep.h>
 #include <sound/ac97_codec.h>
-
+#include <sound/tlv.h>
 #endif
 
 #ifndef CHIP_AU8820
@@ -107,6 +107,14 @@
 #define NR_WTPB 0x20		/* WT channels per each bank. */
 #define NR_PCM	0x10
 
+struct pcm_vol {
+	struct snd_kcontrol *kctl;
+	int active;
+	int dma;
+	int mixin[4];
+	int vol[4];
+};
+
 /* Structs */
 typedef struct {
 	//int this_08;          /* Still unknown */
@@ -168,6 +176,7 @@ struct snd_vortex {
 	/* Xtalk canceler */
 	int xt_mode;		/* 1: speakers, 0:headphones. */
 #endif
+	struct pcm_vol pcm_vol[NR_PCM];
 
 	int isquad;		/* cache of extended ID codec flag. */
 
@@ -239,7 +248,7 @@ static int vortex_alsafmt_aspfmt(int alsafmt);
 /* Connection  stuff. */
 static void vortex_connect_default(vortex_t * vortex, int en);
 static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch,
-				 int dir, int type);
+				 int dir, int type, int subdev);
 static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out,
 				  int restype);
 #ifndef CHIP_AU8810
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 6933a27a5d76279e1c98b59953200dbd52b84e08..525f881f04096bd25cec390d0a2a26443a93aa0c 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2050,8 +2050,6 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype)
 }
 
 /* Default Connections  */
-static int
-vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type);
 
 static void vortex_connect_default(vortex_t * vortex, int en)
 {
@@ -2111,15 +2109,13 @@ static void vortex_connect_default(vortex_t * vortex, int en)
   Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0.
 */
 static int
-vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
+vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir,
+			int type, int subdev)
 {
 	stream_t *stream;
 	int i, en;
+	struct pcm_vol *p;
 	
-	if ((nr_ch == 3)
-	    || ((dir == SNDRV_PCM_STREAM_CAPTURE) && (nr_ch > 2)))
-		return -EBUSY;
-
 	if (dma >= 0) {
 		en = 0;
 		vortex_adb_checkinout(vortex,
@@ -2250,6 +2246,14 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
 							      MIX_DEFIGAIN);
 #endif
 			}
+			if (stream->type == VORTEX_PCM_ADB && en) {
+				p = &vortex->pcm_vol[subdev];
+				p->dma = dma;
+				for (i = 0; i < nr_ch; i++)
+					p->mixin[i] = mix[i];
+				for (i = 0; i < ch_top; i++)
+					p->vol[i] = 0;
+			}
 		}
 #ifndef CHIP_AU8820
 		else {
@@ -2473,7 +2477,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
 		hwread(vortex->mmio, VORTEX_IRQ_STAT);
 		handled = 1;
 	}
-	if (source & IRQ_MIDI) {
+	if ((source & IRQ_MIDI) && vortex->rmidi) {
 		snd_mpu401_uart_interrupt(vortex->irq,
 					  vortex->rmidi->private_data);
 		handled = 1;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 0ef2f97122080f206699a01e32b7f1f1ce7b6825..e59f120742a48e4140a54d80c63f6592c325c220 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -122,6 +122,18 @@ static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {
 	.mask = 0,
 };
 #endif
+
+static void vortex_notify_pcm_vol_change(struct snd_card *card,
+			struct snd_kcontrol *kctl, int activate)
+{
+	if (activate)
+		kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+	else
+		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+	snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
+				SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id));
+}
+
 /* open callback */
 static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
 {
@@ -230,12 +242,14 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
 		if (stream != NULL)
 			vortex_adb_allocroute(chip, stream->dma,
 					      stream->nr_ch, stream->dir,
-					      stream->type);
+					      stream->type,
+					      substream->number);
 		/* Alloc routes. */
 		dma =
 		    vortex_adb_allocroute(chip, -1,
 					  params_channels(hw_params),
-					  substream->stream, type);
+					  substream->stream, type,
+					  substream->number);
 		if (dma < 0) {
 			spin_unlock_irq(&chip->lock);
 			return dma;
@@ -246,6 +260,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
 		vortex_adbdma_setbuffers(chip, dma,
 					 params_period_bytes(hw_params),
 					 params_periods(hw_params));
+		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
+			chip->pcm_vol[substream->number].active = 1;
+			vortex_notify_pcm_vol_change(chip->card,
+				chip->pcm_vol[substream->number].kctl, 1);
+		}
 	}
 #ifndef CHIP_AU8810
 	else {
@@ -275,10 +294,18 @@ static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
 	spin_lock_irq(&chip->lock);
 	// Delete audio routes.
 	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
-		if (stream != NULL)
+		if (stream != NULL) {
+			if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
+				chip->pcm_vol[substream->number].active = 0;
+				vortex_notify_pcm_vol_change(chip->card,
+					chip->pcm_vol[substream->number].kctl,
+					0);
+			}
 			vortex_adb_allocroute(chip, stream->dma,
 					      stream->nr_ch, stream->dir,
-					      stream->type);
+					      stream->type,
+					      substream->number);
+		}
 	}
 #ifndef CHIP_AU8810
 	else {
@@ -506,6 +533,83 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
 	},
 };
 
+/* subdevice PCM Volume control */
+
+static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *uinfo)
+{
+	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+	uinfo->value.integer.min = -128;
+	uinfo->value.integer.max = 32;
+	return 0;
+}
+
+static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int i;
+	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+	int subdev = kcontrol->id.subdevice;
+	struct pcm_vol *p = &vortex->pcm_vol[subdev];
+	int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+	for (i = 0; i < max_chn; i++)
+		ucontrol->value.integer.value[i] = p->vol[i];
+	return 0;
+}
+
+static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int i;
+	int changed = 0;
+	int mixin;
+	unsigned char vol;
+	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+	int subdev = kcontrol->id.subdevice;
+	struct pcm_vol *p = &vortex->pcm_vol[subdev];
+	int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+	for (i = 0; i < max_chn; i++) {
+		if (p->vol[i] != ucontrol->value.integer.value[i]) {
+			p->vol[i] = ucontrol->value.integer.value[i];
+			if (p->active) {
+				switch (vortex->dma_adb[p->dma].nr_ch) {
+				case 1:
+					mixin = p->mixin[0];
+					break;
+				case 2:
+				default:
+					mixin = p->mixin[(i < 2) ? i : (i - 2)];
+					break;
+				case 4:
+					mixin = p->mixin[i];
+					break;
+				};
+				vol = p->vol[i];
+				vortex_mix_setinputvolumebyte(vortex,
+					vortex->mixplayb[i], mixin, vol);
+			}
+			changed = 1;
+		}
+	}
+	return changed;
+}
+
+static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
+
+static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+	.name = "PCM Playback Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+		SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+		SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+	.info = snd_vortex_pcm_vol_info,
+	.get = snd_vortex_pcm_vol_get,
+	.put = snd_vortex_pcm_vol_put,
+	.tlv = { .p = vortex_pcm_vol_db_scale },
+};
+
 /* create a pcm device */
 static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
 {
@@ -555,5 +659,20 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
 				return err;
 		}
 	}
+	if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) {
+		for (i = 0; i < NR_PCM; i++) {
+			chip->pcm_vol[i].active = 0;
+			chip->pcm_vol[i].dma = -1;
+			kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip);
+			if (!kctl)
+				return -ENOMEM;
+			chip->pcm_vol[i].kctl = kctl;
+			kctl->id.device = 0;
+			kctl->id.subdevice = i;
+			err = snd_ctl_add(chip->card, kctl);
+			if (err < 0)
+				return err;
+		}
+	}
 	return 0;
 }
diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c
index b78f3fc3c33caabd26d49a5b41ed4bfda861d39d..6109490b83e83294373f36956a5a8a01dd923e20 100644
--- a/sound/pci/ctxfi/ctvmem.c
+++ b/sound/pci/ctxfi/ctvmem.c
@@ -36,7 +36,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size)
 
 	size = CT_PAGE_ALIGN(size);
 	if (size > vm->size) {
-		printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural "
+		printk(KERN_ERR "ctxfi: Fail! No sufficient device virtual "
 				  "memory space available!\n");
 		return NULL;
 	}
diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c
deleted file mode 100644
index 3b5170b9700f03b0c49d47ef0842e17a1eef1dd7..0000000000000000000000000000000000000000
--- a/sound/pci/hda/alc260_quirks.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- * ALC260 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC260 models */
-enum {
-	ALC260_AUTO,
-	ALC260_BASIC,
-	ALC260_FUJITSU_S702X,
-	ALC260_ACER,
-	ALC260_WILL,
-	ALC260_REPLACER_672V,
-	ALC260_FAVORIT100,
-#ifdef CONFIG_SND_DEBUG
-	ALC260_TEST,
-#endif
-	ALC260_MODEL_LAST /* last tag */
-};
-
-static const hda_nid_t alc260_dac_nids[1] = {
-	/* front */
-	0x02,
-};
-
-static const hda_nid_t alc260_adc_nids[1] = {
-	/* ADC0 */
-	0x04,
-};
-
-static const hda_nid_t alc260_adc_nids_alt[1] = {
-	/* ADC1 */
-	0x05,
-};
-
-/* NIDs used when simultaneous access to both ADCs makes sense.  Note that
- * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
- */
-static const hda_nid_t alc260_dual_adc_nids[2] = {
-	/* ADC0, ADC1 */
-	0x04, 0x05
-};
-
-#define ALC260_DIGOUT_NID	0x03
-#define ALC260_DIGIN_NID	0x06
-
-static const struct hda_input_mux alc260_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
- * headphone jack and the internal CD lines since these are the only pins at
- * which audio can appear.  For flexibility, also allow the option of
- * recording the mixer output on the second ADC (ADC0 doesn't have a
- * connection to the mixer output).
- */
-static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
-	{
-		.num_items = 3,
-		.items = {
-			{ "Mic/Line", 0x0 },
-			{ "CD", 0x4 },
-			{ "Headphone", 0x2 },
-		},
-	},
-	{
-		.num_items = 4,
-		.items = {
-			{ "Mic/Line", 0x0 },
-			{ "CD", 0x4 },
-			{ "Headphone", 0x2 },
-			{ "Mixer", 0x5 },
-		},
-	},
-
-};
-
-/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
- * the Fujitsu S702x, but jacks are marked differently.
- */
-static const struct hda_input_mux alc260_acer_capture_sources[2] = {
-	{
-		.num_items = 4,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-			{ "Headphone", 0x5 },
-		},
-	},
-	{
-		.num_items = 5,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-			{ "Headphone", 0x6 },
-			{ "Mixer", 0x5 },
-		},
-	},
-};
-
-/* Maxdata Favorit 100XS */
-static const struct hda_input_mux alc260_favorit100_capture_sources[2] = {
-	{
-		.num_items = 2,
-		.items = {
-			{ "Line/Mic", 0x0 },
-			{ "CD", 0x4 },
-		},
-	},
-	{
-		.num_items = 3,
-		.items = {
-			{ "Line/Mic", 0x0 },
-			{ "CD", 0x4 },
-			{ "Mixer", 0x5 },
-		},
-	},
-};
-
-/*
- * This is just place-holder, so there's something for alc_build_pcms to look
- * at when it calculates the maximum number of channels. ALC260 has no mixer
- * element which allows changing the channel mode, so the verb list is
- * never used.
- */
-static const struct hda_channel_mode alc260_modes[1] = {
-	{ 2, NULL },
-};
-
-
-/* Mixer combinations
- *
- * basic: base_output + input + pc_beep + capture
- * fujitsu: fujitsu + capture
- * acer: acer + capture
- */
-
-static const struct snd_kcontrol_new alc260_base_output_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc260_input_mixer[] = {
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Fujitsu S702x series laptops.  ALC260 pin usage: Mic/Line jack = 0x12,
- * HP jack = 0x14, CD audio =  0x16, internal speaker = 0x10.
- */
-static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
-	ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks.  Note that current
- * versions of the ALC260 don't act on requests to enable mic bias from NID
- * 0x0f (used to drive the headphone jack in these laptops).  The ALC260
- * datasheet doesn't mention this restriction.  At this stage it's not clear
- * whether this behaviour is intentional or is a hardware bug in chip
- * revisions available in early 2006.  Therefore for now allow the
- * "Headphone Jack Mode" control to span all choices, but if it turns out
- * that the lack of mic bias for this NID is intentional we could change the
- * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
- *
- * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
- * don't appear to make the mic bias available from the "line" jack, even
- * though the NID used for this jack (0x14) can supply it.  The theory is
- * that perhaps Acer have included blocking capacitors between the ALC260
- * and the output jack.  If this turns out to be the case for all such
- * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
- * to ALC_PIN_DIR_INOUT_NOMICBIAS.
- *
- * The C20x Tablet series have a mono internal speaker which is controlled
- * via the chip's Mono sum widget and pin complex, so include the necessary
- * controls for such models.  On models without a "mono speaker" the control
- * won't do anything.
- */
-static const struct snd_kcontrol_new alc260_acer_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
-	ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
-			      HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
-			   HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
-	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	{ } /* end */
-};
-
-/* Maxdata Favorit 100XS: one output and one input (0x12) jack
- */
-static const struct snd_kcontrol_new alc260_favorit100_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
-	ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	{ } /* end */
-};
-
-/* Packard bell V7900  ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
- * Line In jack = 0x14, CD audio =  0x16, pc beep = 0x17.
- */
-static const struct snd_kcontrol_new alc260_will_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
-	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
- * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
- */
-static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
-	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	{ } /* end */
-};
-
-/*
- * initialization verbs
- */
-static const struct hda_verb alc260_init_verbs[] = {
-	/* Line In pin widget for input */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* CD pin widget for input */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	/* Mic2 (front panel) pin widget for input and vref at 80% */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	/* LINE-2 is used for line-out in rear */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* select line-out */
-	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* LINE-OUT pin */
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* enable HP */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* enable Mono */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* set connection select to line in (default select for this ADC) */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* mute capture amp left and right */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* set connection select to line in (default select for this ADC) */
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* set vol=0 Line-Out mixer amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* unmute pin widget amp left and right (no gain on this amp) */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* set vol=0 HP mixer amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* unmute pin widget amp left and right (no gain on this amp) */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* set vol=0 Mono mixer amp left and right */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* unmute pin widget amp left and right (no gain on this amp) */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* unmute LINE-2 out pin */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
-	 * Line In 2 = 0x03
-	 */
-	/* mute analog inputs */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-	/* mute Front out path */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* mute Headphone out path */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* mute Mono out path */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{ }
-};
-
-/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
- * laptops.  ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
- * audio = 0x16, internal speaker = 0x10.
- */
-static const struct hda_verb alc260_fujitsu_init_verbs[] = {
-	/* Disable all GPIOs */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0},
-	/* Internal speaker is connected to headphone pin */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Mic/Line-in jack is connected to mic1 pin, so make it an input */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Ensure all other unused pins are disabled and muted. */
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
-	/* Disable digital (SPDIF) pins */
-	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
-	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure Line1 pin widget takes its input from the OUT1 sum bus
-	 * when acting as an output.
-	 */
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute Line1 pin widget output buffer since it starts as an output.
-	 * If the pin mode is changed by the user the pin mode control will
-	 * take care of enabling the pin's input/output buffers as needed.
-	 * Therefore there's no need to enable the input buffer at this
-	 * stage.
-	 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute input buffer of pin widget used for Line-in (no equiv
-	 * mixer ctrl)
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Set ADC connection select to match default mixer setting - line
-	 * in (on mic1 pin)
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Do the same for the second ADC: mute capture input amp and
-	 * set ADC connection to line in (on mic1 pin)
-	 */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-
-/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
- * similar laptops (adapted from Fujitsu init verbs).
- */
-static const struct hda_verb alc260_acer_init_verbs[] = {
-	/* On TravelMate laptops, GPIO 0 enables the internal speaker and
-	 * the headphone jack.  Turn this on and rely on the standard mute
-	 * methods whenever the user wants to turn these outputs off.
-	 */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
-	/* Internal speaker/Headphone jack is connected to Line-out pin */
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Internal microphone/Mic jack is connected to Mic1 pin */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	/* Line In jack is connected to Line1 pin */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Ensure all other unused pins are disabled and muted. */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Disable digital (SPDIF) pins */
-	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
-	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
-	 * bus when acting as outputs.
-	 */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Unmute Line-out pin widget amp left and right
-	 * (no equiv mixer ctrl)
-	 */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute mono pin widget amp output (no equiv mixer ctrl) */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
-	 * inputs. If the pin mode is changed by the user the pin mode control
-	 * will take care of enabling the pin's input/output buffers as needed.
-	 * Therefore there's no need to enable the input buffer at this
-	 * stage.
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Set ADC connection select to match default mixer setting - mic
-	 * (on mic1 pin)
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Do similar with the second ADC: mute capture input amp and
-	 * set ADC connection to mic to match ALSA's default state.
-	 */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-
-/* Initialisation sequence for Maxdata Favorit 100XS
- * (adapted from Acer init verbs).
- */
-static const struct hda_verb alc260_favorit100_init_verbs[] = {
-	/* GPIO 0 enables the output jack.
-	 * Turn this on and rely on the standard mute
-	 * methods whenever the user wants to turn these outputs off.
-	 */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
-	/* Line/Mic input jack is connected to Mic1 pin */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	/* Ensure all other unused pins are disabled and muted. */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Disable digital (SPDIF) pins */
-	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
-	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
-	 * bus when acting as outputs.
-	 */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Unmute Line-out pin widget amp left and right
-	 * (no equiv mixer ctrl)
-	 */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
-	 * inputs. If the pin mode is changed by the user the pin mode control
-	 * will take care of enabling the pin's input/output buffers as needed.
-	 * Therefore there's no need to enable the input buffer at this
-	 * stage.
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Set ADC connection select to match default mixer setting - mic
-	 * (on mic1 pin)
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Do similar with the second ADC: mute capture input amp and
-	 * set ADC connection to mic to match ALSA's default state.
-	 */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-
-static const struct hda_verb alc260_will_verbs[] = {
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
-	{}
-};
-
-static const struct hda_verb alc260_replacer_672v_verbs[] = {
-	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
-
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-
-	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{}
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc260_replacer_672v_automute(struct hda_codec *codec)
-{
-        unsigned int present;
-
-	/* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
-	present = snd_hda_jack_detect(codec, 0x0f);
-	if (present) {
-		snd_hda_codec_write_cache(codec, 0x01, 0,
-					  AC_VERB_SET_GPIO_DATA, 1);
-		snd_hda_codec_write_cache(codec, 0x0f, 0,
-					  AC_VERB_SET_PIN_WIDGET_CONTROL,
-					  PIN_HP);
-	} else {
-		snd_hda_codec_write_cache(codec, 0x01, 0,
-					  AC_VERB_SET_GPIO_DATA, 0);
-		snd_hda_codec_write_cache(codec, 0x0f, 0,
-					  AC_VERB_SET_PIN_WIDGET_CONTROL,
-					  PIN_OUT);
-	}
-}
-
-static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
-                                       unsigned int res)
-{
-        if ((res >> 26) == ALC_HP_EVENT)
-                alc260_replacer_672v_automute(codec);
-}
-
-static const struct hda_verb alc260_hp_dc7600_verbs[] = {
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{}
-};
-
-/* Test configuration for debugging, modelled after the ALC880 test
- * configuration.
- */
-#ifdef CONFIG_SND_DEBUG
-static const hda_nid_t alc260_test_dac_nids[1] = {
-	0x02,
-};
-static const hda_nid_t alc260_test_adc_nids[2] = {
-	0x04, 0x05,
-};
-/* For testing the ALC260, each input MUX needs its own definition since
- * the signal assignments are different.  This assumes that the first ADC
- * is NID 0x04.
- */
-static const struct hda_input_mux alc260_test_capture_sources[2] = {
-	{
-		.num_items = 7,
-		.items = {
-			{ "MIC1 pin", 0x0 },
-			{ "MIC2 pin", 0x1 },
-			{ "LINE1 pin", 0x2 },
-			{ "LINE2 pin", 0x3 },
-			{ "CD pin", 0x4 },
-			{ "LINE-OUT pin", 0x5 },
-			{ "HP-OUT pin", 0x6 },
-		},
-        },
-	{
-		.num_items = 8,
-		.items = {
-			{ "MIC1 pin", 0x0 },
-			{ "MIC2 pin", 0x1 },
-			{ "LINE1 pin", 0x2 },
-			{ "LINE2 pin", 0x3 },
-			{ "CD pin", 0x4 },
-			{ "Mixer", 0x5 },
-			{ "LINE-OUT pin", 0x6 },
-			{ "HP-OUT pin", 0x7 },
-		},
-        },
-};
-static const struct snd_kcontrol_new alc260_test_mixer[] = {
-	/* Output driver widgets */
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
-
-	/* Modes for retasking pin widgets
-	 * Note: the ALC260 doesn't seem to act on requests to enable mic
-         * bias from NIDs 0x0f and 0x10.  The ALC260 datasheet doesn't
-         * mention this restriction.  At this stage it's not clear whether
-         * this behaviour is intentional or is a hardware bug in chip
-         * revisions available at least up until early 2006.  Therefore for
-         * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
-         * choices, but if it turns out that the lack of mic bias for these
-         * NIDs is intentional we could change their modes from
-         * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
-	 */
-	ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
-
-	/* Loopback mixer controls */
-	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
-	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
-
-	/* Controls for GPIO pins, assuming they are configured as outputs */
-	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-
-	/* Switches to allow the digital IO pins to be enabled.  The datasheet
-	 * is ambigious as to which NID is which; testing on laptops which
-	 * make this output available should provide clarification.
-	 */
-	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
-	ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
-
-	/* A switch allowing EAPD to be enabled.  Some laptops seem to use
-	 * this output to turn on an external amplifier.
-	 */
-	ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
-	ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
-
-	{ } /* end */
-};
-static const struct hda_verb alc260_test_init_verbs[] = {
-	/* Enable all GPIOs as outputs with an initial value of 0 */
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
-
-	/* Enable retasking pins as output, initially without power amp */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* Disable digital (SPDIF) pins initially, but users can enable
-	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
-	 * payload also sets the generation to 0, output to be in "consumer"
-	 * PCM format, copyright asserted, no pre-emphasis and no validity
-	 * control.
-	 */
-	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
-	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
-	 * OUT1 sum bus when acting as an output.
-	 */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0e, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Unmute retasking pin widget output buffers since the default
-	 * state appears to be output.  As the pin mode is changed by the
-	 * user the pin mode control will take care of enabling the pin's
-	 * input/output buffers as needed.
-	 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Also unmute the mono-out pin widget */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Set ADC connection select to match default mixer setting (mic1
-	 * pin)
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Do the same for the second ADC: mute capture input amp and
-	 * set ADC connection to mic1 pin
-	 */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-#endif
-
-/*
- * ALC260 configurations
- */
-static const char * const alc260_models[ALC260_MODEL_LAST] = {
-	[ALC260_BASIC]		= "basic",
-	[ALC260_FUJITSU_S702X]	= "fujitsu",
-	[ALC260_ACER]		= "acer",
-	[ALC260_WILL]		= "will",
-	[ALC260_REPLACER_672V]	= "replacer",
-	[ALC260_FAVORIT100]	= "favorit100",
-#ifdef CONFIG_SND_DEBUG
-	[ALC260_TEST]		= "test",
-#endif
-	[ALC260_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc260_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
-	SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
-	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
-	SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
-	SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
-	SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
-	SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
-	SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
-	SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
-	SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
-	SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
-	{}
-};
-
-static const struct alc_config_preset alc260_presets[] = {
-	[ALC260_BASIC] = {
-		.mixers = { alc260_base_output_mixer,
-			    alc260_input_mixer },
-		.init_verbs = { alc260_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_dual_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-	},
-	[ALC260_FUJITSU_S702X] = {
-		.mixers = { alc260_fujitsu_mixer },
-		.init_verbs = { alc260_fujitsu_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_dual_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
-		.input_mux = alc260_fujitsu_capture_sources,
-	},
-	[ALC260_ACER] = {
-		.mixers = { alc260_acer_mixer },
-		.init_verbs = { alc260_acer_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_dual_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
-		.input_mux = alc260_acer_capture_sources,
-	},
-	[ALC260_FAVORIT100] = {
-		.mixers = { alc260_favorit100_mixer },
-		.init_verbs = { alc260_favorit100_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_dual_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
-		.input_mux = alc260_favorit100_capture_sources,
-	},
-	[ALC260_WILL] = {
-		.mixers = { alc260_will_mixer },
-		.init_verbs = { alc260_init_verbs, alc260_will_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
-		.adc_nids = alc260_adc_nids,
-		.dig_out_nid = ALC260_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-	},
-	[ALC260_REPLACER_672V] = {
-		.mixers = { alc260_replacer_672v_mixer },
-		.init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
-		.adc_nids = alc260_adc_nids,
-		.dig_out_nid = ALC260_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-		.unsol_event = alc260_replacer_672v_unsol_event,
-		.init_hook = alc260_replacer_672v_automute,
-	},
-#ifdef CONFIG_SND_DEBUG
-	[ALC260_TEST] = {
-		.mixers = { alc260_test_mixer },
-		.init_verbs = { alc260_test_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
-		.dac_nids = alc260_test_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
-		.adc_nids = alc260_test_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
-		.input_mux = alc260_test_capture_sources,
-	},
-#endif
-};
-
diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c
deleted file mode 100644
index 501501ef36a9d0133d8635795e617d1694ea4496..0000000000000000000000000000000000000000
--- a/sound/pci/hda/alc880_quirks.c
+++ /dev/null
@@ -1,1707 +0,0 @@
-/*
- * ALC880 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC880 board config type */
-enum {
-	ALC880_AUTO,
-	ALC880_3ST,
-	ALC880_3ST_DIG,
-	ALC880_5ST,
-	ALC880_5ST_DIG,
-	ALC880_W810,
-	ALC880_Z71V,
-	ALC880_6ST,
-	ALC880_6ST_DIG,
-	ALC880_F1734,
-	ALC880_ASUS,
-	ALC880_ASUS_DIG,
-	ALC880_ASUS_W1V,
-	ALC880_ASUS_DIG2,
-	ALC880_FUJITSU,
-	ALC880_UNIWILL_DIG,
-	ALC880_UNIWILL,
-	ALC880_UNIWILL_P53,
-	ALC880_CLEVO,
-	ALC880_TCL_S700,
-	ALC880_LG,
-#ifdef CONFIG_SND_DEBUG
-	ALC880_TEST,
-#endif
-	ALC880_MODEL_LAST /* last tag */
-};
-
-/*
- * ALC880 3-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
- * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
- *                 F-Mic = 0x1b, HP = 0x19
- */
-
-static const hda_nid_t alc880_dac_nids[4] = {
-	/* front, rear, clfe, rear_surr */
-	0x02, 0x05, 0x04, 0x03
-};
-
-static const hda_nid_t alc880_adc_nids[3] = {
-	/* ADC0-2 */
-	0x07, 0x08, 0x09,
-};
-
-/* The datasheet says the node 0x07 is connected from inputs,
- * but it shows zero connection in the real implementation on some devices.
- * Note: this is a 915GAV bug, fixed on 915GLV
- */
-static const hda_nid_t alc880_adc_nids_alt[2] = {
-	/* ADC1-2 */
-	0x08, 0x09,
-};
-
-#define ALC880_DIGOUT_NID	0x06
-#define ALC880_DIGIN_NID	0x0a
-#define ALC880_PIN_CD_NID	0x1c
-
-static const struct hda_input_mux alc880_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x3 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-/* channel source setting (2/6 channel selection for 3-stack) */
-/* 2ch mode */
-static const struct hda_verb alc880_threestack_ch2_init[] = {
-	/* set line-in to input, mute it */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	/* set mic-in to input vref 80%, mute it */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/* 6ch mode */
-static const struct hda_verb alc880_threestack_ch6_init[] = {
-	/* set line-in to output, unmute it */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	/* set mic-in to output, unmute it */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc880_threestack_modes[2] = {
-	{ 2, alc880_threestack_ch2_init },
-	{ 6, alc880_threestack_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc880_three_stack_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-/*
- * ALC880 5-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
- *      Side = 0x02 (0xd)
- * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
- *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
- */
-
-/* additional mixers to alc880_three_stack_mixer */
-static const struct snd_kcontrol_new alc880_five_stack_mixer[] = {
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
-	{ } /* end */
-};
-
-/* channel source setting (6/8 channel selection for 5-stack) */
-/* 6ch mode */
-static const struct hda_verb alc880_fivestack_ch6_init[] = {
-	/* set line-in to input, mute it */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/* 8ch mode */
-static const struct hda_verb alc880_fivestack_ch8_init[] = {
-	/* set line-in to output, unmute it */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc880_fivestack_modes[2] = {
-	{ 6, alc880_fivestack_ch6_init },
-	{ 8, alc880_fivestack_ch8_init },
-};
-
-
-/*
- * ALC880 6-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
- *      Side = 0x05 (0x0f)
- * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
- *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
- */
-
-static const hda_nid_t alc880_6st_dac_nids[4] = {
-	/* front, rear, clfe, rear_surr */
-	0x02, 0x03, 0x04, 0x05
-};
-
-static const struct hda_input_mux alc880_6stack_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-/* fixed 8-channels */
-static const struct hda_channel_mode alc880_sixstack_modes[1] = {
-	{ 8, NULL },
-};
-
-static const struct snd_kcontrol_new alc880_six_stack_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-
-/*
- * ALC880 W810 model
- *
- * W810 has rear IO for:
- * Front (DAC 02)
- * Surround (DAC 03)
- * Center/LFE (DAC 04)
- * Digital out (06)
- *
- * The system also has a pair of internal speakers, and a headphone jack.
- * These are both connected to Line2 on the codec, hence to DAC 02.
- *
- * There is a variable resistor to control the speaker or headphone
- * volume. This is a hardware-only device without a software API.
- *
- * Plugging headphones in will disable the internal speakers. This is
- * implemented in hardware, not via the driver using jack sense. In
- * a similar fashion, plugging into the rear socket marked "front" will
- * disable both the speakers and headphones.
- *
- * For input, there's a microphone jack, and an "audio in" jack.
- * These may not do anything useful with this driver yet, because I
- * haven't setup any initialization verbs for these yet...
- */
-
-static const hda_nid_t alc880_w810_dac_nids[3] = {
-	/* front, rear/surround, clfe */
-	0x02, 0x03, 0x04
-};
-
-/* fixed 6 channels */
-static const struct hda_channel_mode alc880_w810_modes[1] = {
-	{ 6, NULL }
-};
-
-/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
-static const struct snd_kcontrol_new alc880_w810_base_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-
-/*
- * Z710V model
- *
- * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
- * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
- *                 Line = 0x1a
- */
-
-static const hda_nid_t alc880_z71v_dac_nids[1] = {
-	0x02
-};
-#define ALC880_Z71V_HP_DAC	0x03
-
-/* fixed 2 channels */
-static const struct hda_channel_mode alc880_2_jack_modes[1] = {
-	{ 2, NULL }
-};
-
-static const struct snd_kcontrol_new alc880_z71v_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-
-/*
- * ALC880 F1734 model
- *
- * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
- * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
- */
-
-static const hda_nid_t alc880_f1734_dac_nids[1] = {
-	0x03
-};
-#define ALC880_F1734_HP_DAC	0x02
-
-static const struct snd_kcontrol_new alc880_f1734_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_input_mux alc880_f1734_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "CD", 0x4 },
-	},
-};
-
-
-/*
- * ALC880 ASUS model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- *  Mic = 0x18, Line = 0x1a
- */
-
-#define alc880_asus_dac_nids	alc880_w810_dac_nids	/* identical with w810 */
-#define alc880_asus_modes	alc880_threestack_modes	/* 2/6 channel mode */
-
-static const struct snd_kcontrol_new alc880_asus_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-/*
- * ALC880 ASUS W1V model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
- */
-
-/* additional mixers to alc880_asus_mixer */
-static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
-	HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
-	{ } /* end */
-};
-
-/* TCL S700 */
-static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Uniwill */
-static const struct snd_kcontrol_new alc880_uniwill_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-/*
- * initialize the codec volumes, etc
- */
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc880_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front
-	 * panel mic (mic 2)
-	 */
-	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-
-	/*
-	 * Set up output mixers (0x0c - 0x0f)
-	 */
-	/* set vol=0 to output mixers */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	{ }
-};
-
-/*
- * 3-stack pin configuration:
- * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc880_pin_3stack_init_verbs[] = {
-	/*
-	 * preset connection lists of input pins
-	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
-	 */
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
-
-	/*
-	 * Set pin mode and muting
-	 */
-	/* set front pin widgets 0x14 for output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mic2 (as headphone out) for HP output */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line2 (as front mic) pin widget for input and vref at 80% */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/*
- * 5-stack pin configuration:
- * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
- * line-in/side = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc880_pin_5stack_init_verbs[] = {
-	/*
-	 * preset connection lists of input pins
-	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
-	 */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
-
-	/*
-	 * Set pin mode and muting
-	 */
-	/* set pin widgets 0x14-0x17 for output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* unmute pins for output (no gain on this amp) */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mic2 (as headphone out) for HP output */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line2 (as front mic) pin widget for input and vref at 80% */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/*
- * W810 pin configuration:
- * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
- */
-static const struct hda_verb alc880_pin_w810_init_verbs[] = {
-	/* hphone/speaker input selector: front DAC */
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{ }
-};
-
-/*
- * Z71V pin configuration:
- * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
- */
-static const struct hda_verb alc880_pin_z71v_init_verbs[] = {
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/*
- * 6-stack pin configuration:
- * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
- * f-mic = 0x19, line = 0x1a, HP = 0x1b
- */
-static const struct hda_verb alc880_pin_6stack_init_verbs[] = {
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/*
- * Uniwill pin configuration:
- * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
- * line = 0x1a
- */
-static const struct hda_verb alc880_uniwill_init_verbs[] = {
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
-	/* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
-
-	{ }
-};
-
-/*
-* Uniwill P53
-* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
- */
-static const struct hda_verb alc880_uniwill_p53_init_verbs[] = {
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_DCVOL_EVENT},
-
-	{ }
-};
-
-static const struct hda_verb alc880_beep_init_verbs[] = {
-	{ 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
-	{ }
-};
-
-static void alc880_uniwill_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x16;
-	alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-static void alc880_uniwill_init_hook(struct hda_codec *codec)
-{
-	alc_hp_automute(codec);
-	alc88x_simple_mic_automute(codec);
-}
-
-static void alc880_uniwill_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	/* Looks like the unsol event is incompatible with the standard
-	 * definition.  4bit tag is placed at 28 bit!
-	 */
-	res >>= 28;
-	switch (res) {
-	case ALC_MIC_EVENT:
-		alc88x_simple_mic_automute(codec);
-		break;
-	default:
-		alc_exec_unsol_event(codec, res);
-		break;
-	}
-}
-
-static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	alc_exec_unsol_event(codec, res >> 28);
-}
-
-static void alc880_uniwill_p53_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_codec_read(codec, 0x21, 0,
-				     AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
-	present &= HDA_AMP_VOLMASK;
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
-				 HDA_AMP_VOLMASK, present);
-	snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
-				 HDA_AMP_VOLMASK, present);
-}
-
-static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	/* Looks like the unsol event is incompatible with the standard
-	 * definition.  4bit tag is placed at 28 bit!
-	 */
-	res >>= 28;
-	if (res == ALC_DCVOL_EVENT)
-		alc880_uniwill_p53_dcvol_automute(codec);
-	else
-		alc_exec_unsol_event(codec, res);
-}
-
-/*
- * F1734 pin configuration:
- * HP = 0x14, speaker-out = 0x15, mic = 0x18
- */
-static const struct hda_verb alc880_pin_f1734_init_verbs[] = {
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_DCVOL_EVENT},
-
-	{ }
-};
-
-/*
- * ASUS pin configuration:
- * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
- */
-static const struct hda_verb alc880_pin_asus_init_verbs[] = {
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/* Enable GPIO mask and set output */
-#define alc880_gpio1_init_verbs	alc_gpio1_init_verbs
-#define alc880_gpio2_init_verbs	alc_gpio2_init_verbs
-#define alc880_gpio3_init_verbs	alc_gpio3_init_verbs
-
-/* Clevo m520g init */
-static const struct hda_verb alc880_pin_clevo_init_verbs[] = {
-	/* headphone output */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* line-out */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Line-in */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* CD */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Mic1 (rear panel) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Mic2 (front panel) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* headphone */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-        /* change to EAPD mode */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
-
-	{ }
-};
-
-static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
-	/* change to EAPD mode */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
-
-	/* Headphone output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Front output*/
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-
-	/* change to EAPD mode */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
-
-	{ }
-};
-
-/*
- * LG m1 express dual
- *
- * Pin assignment:
- *   Rear Line-In/Out (blue): 0x14
- *   Build-in Mic-In: 0x15
- *   Speaker-out: 0x17
- *   HP-Out (green): 0x1b
- *   Mic-In/Out (red): 0x19
- *   SPDIF-Out: 0x1e
- */
-
-/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
-static const hda_nid_t alc880_lg_dac_nids[3] = {
-	0x05, 0x02, 0x03
-};
-
-/* seems analog CD is not working */
-static const struct hda_input_mux alc880_lg_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Line", 0x5 },
-		{ "Internal Mic", 0x6 },
-	},
-};
-
-/* 2,4,6 channel modes */
-static const struct hda_verb alc880_lg_ch2_init[] = {
-	/* set line-in and mic-in to input */
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ }
-};
-
-static const struct hda_verb alc880_lg_ch4_init[] = {
-	/* set line-in to out and mic-in to input */
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ }
-};
-
-static const struct hda_verb alc880_lg_ch6_init[] = {
-	/* set line-in and mic-in to output */
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ }
-};
-
-static const struct hda_channel_mode alc880_lg_ch_modes[3] = {
-	{ 2, alc880_lg_ch2_init },
-	{ 4, alc880_lg_ch4_init },
-	{ 6, alc880_lg_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc880_lg_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc880_lg_init_verbs[] = {
-	/* set capture source to mic-in */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* mute all amp mixer inputs */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	/* line-in to input */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* built-in mic */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* speaker-out */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* mic-in to input */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* HP-out */
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* jack sense */
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{ }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x17;
-	alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc880_lg_loopbacks[] = {
-	{ 0x0b, HDA_INPUT, 1 },
-	{ 0x0b, HDA_INPUT, 6 },
-	{ 0x0b, HDA_INPUT, 7 },
-	{ } /* end */
-};
-#endif
-
-/*
- * Test configuration for debugging
- *
- * Almost all inputs/outputs are enabled.  I/O pins can be configured via
- * enum controls.
- */
-#ifdef CONFIG_SND_DEBUG
-static const hda_nid_t alc880_test_dac_nids[4] = {
-	0x02, 0x03, 0x04, 0x05
-};
-
-static const struct hda_input_mux alc880_test_capture_source = {
-	.num_items = 7,
-	.items = {
-		{ "In-1", 0x0 },
-		{ "In-2", 0x1 },
-		{ "In-3", 0x2 },
-		{ "In-4", 0x3 },
-		{ "CD", 0x4 },
-		{ "Front", 0x5 },
-		{ "Surround", 0x6 },
-	},
-};
-
-static const struct hda_channel_mode alc880_test_modes[4] = {
-	{ 2, NULL },
-	{ 4, NULL },
-	{ 6, NULL },
-	{ 8, NULL },
-};
-
-static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_info *uinfo)
-{
-	static const char * const texts[] = {
-		"N/A", "Line Out", "HP Out",
-		"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
-	};
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 8;
-	if (uinfo->value.enumerated.item >= 8)
-		uinfo->value.enumerated.item = 7;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
-}
-
-static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
-	unsigned int pin_ctl, item = 0;
-
-	pin_ctl = snd_hda_codec_read(codec, nid, 0,
-				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-	if (pin_ctl & AC_PINCTL_OUT_EN) {
-		if (pin_ctl & AC_PINCTL_HP_EN)
-			item = 2;
-		else
-			item = 1;
-	} else if (pin_ctl & AC_PINCTL_IN_EN) {
-		switch (pin_ctl & AC_PINCTL_VREFEN) {
-		case AC_PINCTL_VREF_HIZ: item = 3; break;
-		case AC_PINCTL_VREF_50:  item = 4; break;
-		case AC_PINCTL_VREF_GRD: item = 5; break;
-		case AC_PINCTL_VREF_80:  item = 6; break;
-		case AC_PINCTL_VREF_100: item = 7; break;
-		}
-	}
-	ucontrol->value.enumerated.item[0] = item;
-	return 0;
-}
-
-static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
-	static const unsigned int ctls[] = {
-		0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
-	};
-	unsigned int old_ctl, new_ctl;
-
-	old_ctl = snd_hda_codec_read(codec, nid, 0,
-				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-	new_ctl = ctls[ucontrol->value.enumerated.item[0]];
-	if (old_ctl != new_ctl) {
-		int val;
-		snd_hda_codec_write_cache(codec, nid, 0,
-					  AC_VERB_SET_PIN_WIDGET_CONTROL,
-					  new_ctl);
-		val = ucontrol->value.enumerated.item[0] >= 3 ?
-			HDA_AMP_MUTE : 0;
-		snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, val);
-		return 1;
-	}
-	return 0;
-}
-
-static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_info *uinfo)
-{
-	static const char * const texts[] = {
-		"Front", "Surround", "CLFE", "Side"
-	};
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 4;
-	if (uinfo->value.enumerated.item >= 4)
-		uinfo->value.enumerated.item = 3;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
-}
-
-static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
-	unsigned int sel;
-
-	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
-	ucontrol->value.enumerated.item[0] = sel & 3;
-	return 0;
-}
-
-static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
-	unsigned int sel;
-
-	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
-	if (ucontrol->value.enumerated.item[0] != sel) {
-		sel = ucontrol->value.enumerated.item[0] & 3;
-		snd_hda_codec_write_cache(codec, nid, 0,
-					  AC_VERB_SET_CONNECT_SEL, sel);
-		return 1;
-	}
-	return 0;
-}
-
-#define PIN_CTL_TEST(xname,nid) {			\
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
-			.name = xname,		       \
-			.subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-			.info = alc_test_pin_ctl_info, \
-			.get = alc_test_pin_ctl_get,   \
-			.put = alc_test_pin_ctl_put,   \
-			.private_value = nid	       \
-			}
-
-#define PIN_SRC_TEST(xname,nid) {			\
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
-			.name = xname,		       \
-			.subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-			.info = alc_test_pin_src_info, \
-			.get = alc_test_pin_src_get,   \
-			.put = alc_test_pin_src_put,   \
-			.private_value = nid	       \
-			}
-
-static const struct snd_kcontrol_new alc880_test_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	PIN_CTL_TEST("Front Pin Mode", 0x14),
-	PIN_CTL_TEST("Surround Pin Mode", 0x15),
-	PIN_CTL_TEST("CLFE Pin Mode", 0x16),
-	PIN_CTL_TEST("Side Pin Mode", 0x17),
-	PIN_CTL_TEST("In-1 Pin Mode", 0x18),
-	PIN_CTL_TEST("In-2 Pin Mode", 0x19),
-	PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
-	PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
-	PIN_SRC_TEST("In-1 Pin Source", 0x18),
-	PIN_SRC_TEST("In-2 Pin Source", 0x19),
-	PIN_SRC_TEST("In-3 Pin Source", 0x1a),
-	PIN_SRC_TEST("In-4 Pin Source", 0x1b),
-	HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc880_test_init_verbs[] = {
-	/* Unmute inputs of 0x0c - 0x0f */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Vol output for 0x0c-0x0f */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* Set output pins 0x14-0x17 */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Unmute output pins 0x14-0x17 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Set input pins 0x18-0x1c */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Mute input pins 0x18-0x1b */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* ADC set up */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Analog input/passthru */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{ }
-};
-#endif
-
-/*
- */
-
-static const char * const alc880_models[ALC880_MODEL_LAST] = {
-	[ALC880_3ST]		= "3stack",
-	[ALC880_TCL_S700]	= "tcl",
-	[ALC880_3ST_DIG]	= "3stack-digout",
-	[ALC880_CLEVO]		= "clevo",
-	[ALC880_5ST]		= "5stack",
-	[ALC880_5ST_DIG]	= "5stack-digout",
-	[ALC880_W810]		= "w810",
-	[ALC880_Z71V]		= "z71v",
-	[ALC880_6ST]		= "6stack",
-	[ALC880_6ST_DIG]	= "6stack-digout",
-	[ALC880_ASUS]		= "asus",
-	[ALC880_ASUS_W1V]	= "asus-w1v",
-	[ALC880_ASUS_DIG]	= "asus-dig",
-	[ALC880_ASUS_DIG2]	= "asus-dig2",
-	[ALC880_UNIWILL_DIG]	= "uniwill",
-	[ALC880_UNIWILL_P53]	= "uniwill-p53",
-	[ALC880_FUJITSU]	= "fujitsu",
-	[ALC880_F1734]		= "F1734",
-	[ALC880_LG]		= "lg",
-#ifdef CONFIG_SND_DEBUG
-	[ALC880_TEST]		= "test",
-#endif
-	[ALC880_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc880_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
-	SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
-	SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
-	SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
-	SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
-	/* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
-	SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
-	SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
-	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
-	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
-	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
-	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
-	SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
-	SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
-	SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
-	SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
-	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
-	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
-	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
-	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
-	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
-	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
-	SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
-	SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
-	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
-	SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
-	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
-	SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
-	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
-	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
-	SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
-	SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
-	/* default Intel */
-	SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
-	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
-	{}
-};
-
-/*
- * ALC880 codec presets
- */
-static const struct alc_config_preset alc880_presets[] = {
-	[ALC880_3ST] = {
-		.mixers = { alc880_three_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_3stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_3ST_DIG] = {
-		.mixers = { alc880_three_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_3stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_TCL_S700] = {
-		.mixers = { alc880_tcl_s700_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_tcl_S700_init_verbs,
-				alc880_gpio2_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
-		.num_adc_nids = 1, /* single ADC */
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_5ST] = {
-		.mixers = { alc880_three_stack_mixer,
-			    alc880_five_stack_mixer},
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_5stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
-		.channel_mode = alc880_fivestack_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_5ST_DIG] = {
-		.mixers = { alc880_three_stack_mixer,
-			    alc880_five_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_5stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
-		.channel_mode = alc880_fivestack_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_6ST] = {
-		.mixers = { alc880_six_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_6stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
-		.dac_nids = alc880_6st_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
-		.channel_mode = alc880_sixstack_modes,
-		.input_mux = &alc880_6stack_capture_source,
-	},
-	[ALC880_6ST_DIG] = {
-		.mixers = { alc880_six_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_6stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
-		.dac_nids = alc880_6st_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
-		.channel_mode = alc880_sixstack_modes,
-		.input_mux = &alc880_6stack_capture_source,
-	},
-	[ALC880_W810] = {
-		.mixers = { alc880_w810_base_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_w810_init_verbs,
-				alc880_gpio2_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
-		.dac_nids = alc880_w810_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
-		.channel_mode = alc880_w810_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_Z71V] = {
-		.mixers = { alc880_z71v_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_z71v_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
-		.dac_nids = alc880_z71v_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_F1734] = {
-		.mixers = { alc880_f1734_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_f1734_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
-		.dac_nids = alc880_f1734_dac_nids,
-		.hp_nid = 0x02,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_f1734_capture_source,
-		.unsol_event = alc880_uniwill_p53_unsol_event,
-		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC880_ASUS] = {
-		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_ASUS_DIG] = {
-		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_ASUS_DIG2] = {
-		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs,
-				alc880_gpio2_init_verbs }, /* use GPIO2 */
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_ASUS_W1V] = {
-		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_UNIWILL_DIG] = {
-		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_UNIWILL] = {
-		.mixers = { alc880_uniwill_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_uniwill_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-		.unsol_event = alc880_uniwill_unsol_event,
-		.setup = alc880_uniwill_setup,
-		.init_hook = alc880_uniwill_init_hook,
-	},
-	[ALC880_UNIWILL_P53] = {
-		.mixers = { alc880_uniwill_p53_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_uniwill_p53_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
-		.channel_mode = alc880_threestack_modes,
-		.input_mux = &alc880_capture_source,
-		.unsol_event = alc880_uniwill_p53_unsol_event,
-		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC880_FUJITSU] = {
-		.mixers = { alc880_fujitsu_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_uniwill_p53_init_verbs,
-	       			alc880_beep_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_capture_source,
-		.unsol_event = alc880_uniwill_p53_unsol_event,
-		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC880_CLEVO] = {
-		.mixers = { alc880_three_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_clevo_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_LG] = {
-		.mixers = { alc880_lg_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_lg_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
-		.dac_nids = alc880_lg_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
-		.channel_mode = alc880_lg_ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_lg_capture_source,
-		.unsol_event = alc880_unsol_event,
-		.setup = alc880_lg_setup,
-		.init_hook = alc_hp_automute,
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-		.loopbacks = alc880_lg_loopbacks,
-#endif
-	},
-#ifdef CONFIG_SND_DEBUG
-	[ALC880_TEST] = {
-		.mixers = { alc880_test_mixer },
-		.init_verbs = { alc880_test_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
-		.dac_nids = alc880_test_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_test_modes),
-		.channel_mode = alc880_test_modes,
-		.input_mux = &alc880_test_capture_source,
-	},
-#endif
-};
-
diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c
deleted file mode 100644
index bb364a53f546bd65154115ce0cc81bc613f38f72..0000000000000000000000000000000000000000
--- a/sound/pci/hda/alc882_quirks.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * ALC882/ALC883/ALC888/ALC889 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC882 models */
-enum {
-	ALC882_AUTO,
-	ALC885_MBA21,
-	ALC885_MBP3,
-	ALC885_MB5,
-	ALC885_MACMINI3,
-	ALC885_IMAC91,
-	ALC889A_MB31,
-	ALC882_MODEL_LAST,
-};
-
-#define ALC882_DIGOUT_NID	0x06
-#define ALC882_DIGIN_NID	0x0a
-#define ALC883_DIGOUT_NID	ALC882_DIGOUT_NID
-#define ALC883_DIGIN_NID	ALC882_DIGIN_NID
-#define ALC1200_DIGOUT_NID	0x10
-
-
-static const struct hda_channel_mode alc882_ch_modes[1] = {
-	{ 8, NULL }
-};
-
-/* DACs */
-static const hda_nid_t alc882_dac_nids[4] = {
-	/* front, rear, clfe, rear_surr */
-	0x02, 0x03, 0x04, 0x05
-};
-#define alc883_dac_nids		alc882_dac_nids
-
-/* ADCs */
-#define alc882_adc_nids		alc880_adc_nids
-#define alc882_adc_nids_alt	alc880_adc_nids_alt
-#define alc883_adc_nids		alc882_adc_nids_alt
-
-static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
-#define alc883_capsrc_nids	alc882_capsrc_nids_alt
-
-/* input MUX */
-/* FIXME: should be a matrix-type input source selection */
-
-static const struct hda_input_mux alc882_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-#define alc883_capture_source	alc882_capture_source
-
-static const struct hda_input_mux mb5_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Line", 0x7 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux macmini3_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc883_3stack_6ch_intel = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Front Mic", 0x0 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc889A_mb31_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x0 },
-		/* Front Mic (0x01) unused */
-		{ "Line", 0x2 },
-		/* Line 2 (0x03) unused */
-		/* CD (0x04) unused? */
-	},
-};
-
-static const struct hda_input_mux alc889A_imac91_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x01 },
-		{ "Line", 0x2 }, /* Not sure! */
-	},
-};
-
-/* Macbook Air 2,1 */
-
-static const struct hda_channel_mode alc885_mba21_ch_modes[1] = {
-      { 2, NULL },
-};
-
-/*
- * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
- */
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc885_mbp_ch2_init[] = {
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{ } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc885_mbp_ch4_init[] = {
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
-	{ 2, alc885_mbp_ch2_init },
-	{ 4, alc885_mbp_ch4_init },
-};
-
-/*
- * 2ch
- * Speakers/Woofer/HP = Front
- * LineIn = Input
- */
-static const struct hda_verb alc885_mb5_ch2_init[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- * Speakers/HP = Front
- * Woofer = LFE
- * LineIn = Surround
- */
-static const struct hda_verb alc885_mb5_ch6_init[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
-	{ 2, alc885_mb5_ch2_init },
-	{ 6, alc885_mb5_ch6_init },
-};
-
-#define alc885_macmini3_6ch_modes	alc885_mb5_6ch_modes
-
-/* Macbook Air 2,1 same control for HP and internal Speaker */
-
-static const struct snd_kcontrol_new alc885_mba21_mixer[] = {
-      HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-      HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
-     { }
-};
-
-
-static const struct snd_kcontrol_new alc885_mbp3_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_mb5_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_macmini3_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_imac91_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	{ } /* end */
-};
-
-
-static const struct snd_kcontrol_new alc882_chmode_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc882_base_init_verbs[] = {
-	/* Front mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Rear mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* CLFE mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Side mixer */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	/* Front Pin: output 0 (0x0c) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Rear Pin: output 1 (0x0d) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* CLFE Pin: output 2 (0x0e) */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* Side Pin: output 3 (0x0f) */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-	/* Mic (rear) pin: input vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin: input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line-2 In: Headphone output (output 0 - 0x0c) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* ADC2: mute amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* ADC3: mute amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{ }
-};
-
-#define alc883_init_verbs	alc882_base_init_verbs
-
-/* Macbook 5,1 */
-static const struct hda_verb alc885_mb5_init_verbs[] = {
-	/* DACs */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Front mixer */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Surround mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* LFE mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* HP mixer */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Front Pin (0x0c) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* LFE Pin (0x0e) */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* HP Pin (0x0f) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
-	{ }
-};
-
-/* Macmini 3,1 */
-static const struct hda_verb alc885_macmini3_init_verbs[] = {
-	/* DACs */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Front mixer */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Surround mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* LFE mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* HP mixer */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Front Pin (0x0c) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* LFE Pin (0x0e) */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* HP Pin (0x0f) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-	/* Line In pin */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{ }
-};
-
-
-static const struct hda_verb alc885_mba21_init_verbs[] = {
-	/*Internal and HP Speaker Mixer*/
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/*Internal Speaker Pin (0x0c)*/
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP Pin: output 0 (0x0e) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)},
-	/* Line in (is hp when jack connected)*/
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{ }
- };
-
-
-/* Macbook Pro rev3 */
-static const struct hda_verb alc885_mbp3_init_verbs[] = {
-	/* Front mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Rear mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* HP mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Front Pin: output 0 (0x0c) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP Pin: output 0 (0x0e) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-	/* Mic (rear) pin: input vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin: use output 1 when in LineOut mode */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* ADC1: mute amp left and right */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* ADC2: mute amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* ADC3: mute amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{ }
-};
-
-/* iMac 9,1 */
-static const struct hda_verb alc885_imac91_init_verbs[] = {
-	/* Internal Speaker Pin (0x0c) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP Pin: Rear */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)},
-	/* Line in Rear */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Rear mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{ }
-};
-
-/* Toggle speaker-output according to the hp-jack state */
-static void alc885_imac24_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x18;
-	spec->autocfg.speaker_pins[1] = 0x1a;
-	alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-#define alc885_mb5_setup	alc885_imac24_setup
-#define alc885_macmini3_setup	alc885_imac24_setup
-
-/* Macbook Air 2,1 */
-static void alc885_mba21_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x18;
-	alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-
-
-static void alc885_mbp3_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-static void alc885_imac91_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x18;
-	spec->autocfg.speaker_pins[1] = 0x1a;
-	alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
-}
-
-/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
-static const struct hda_verb alc889A_mb31_ch2_init[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},             /* HP as front */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},    /* Line as input */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Line off */
-	{ } /* end */
-};
-
-/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
-static const struct hda_verb alc889A_mb31_ch4_init[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},             /* HP as front */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},   /* Line as output */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
-	{ } /* end */
-};
-
-/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
-static const struct hda_verb alc889A_mb31_ch5_init[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},             /* HP as rear */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},    /* Line as input */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Line off */
-	{ } /* end */
-};
-
-/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
-static const struct hda_verb alc889A_mb31_ch6_init[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},             /* HP as front */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Subwoofer off */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},   /* Line as output */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
-	{ 2, alc889A_mb31_ch2_init },
-	{ 4, alc889A_mb31_ch4_init },
-	{ 5, alc889A_mb31_ch5_init },
-	{ 6, alc889A_mb31_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc889A_mb31_mixer[] = {
-	/* Output mixers */
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
-		HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
-	/* Output switches */
-	HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
-	/* Boost mixers */
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
-	/* Input mixers */
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_chmode_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc889A_mb31_verbs[] = {
-	/* Init rear pin (used as headphone output) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},    /* Apple Headphones */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},           /* Connect to front */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-	/* Init line pin (used as output in 4ch and 6ch mode) */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},           /* Connect to CLFE */
-	/* Init line 2 pin (used as headphone out by default) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},  /* Use as input */
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
-	{ } /* end */
-};
-
-/* Mute speakers according to the headphone jack state */
-static void alc889A_mb31_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	/* Mute only in 2ch or 4ch mode */
-	if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
-	    == 0x00) {
-		present = snd_hda_jack_detect(codec, 0x15);
-		snd_hda_codec_amp_stereo(codec, 0x14,  HDA_OUTPUT, 0,
-			HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
-			HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-	}
-}
-
-static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	if ((res >> 26) == ALC_HP_EVENT)
-		alc889A_mb31_automute(codec);
-}
-
-static void alc882_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	alc_exec_unsol_event(codec, res >> 26);
-}
-
-/*
- * configuration and preset
- */
-static const char * const alc882_models[ALC882_MODEL_LAST] = {
-	[ALC885_MB5]		= "mb5",
-	[ALC885_MACMINI3]	= "macmini3",
-	[ALC885_MBA21]		= "mba21",
-	[ALC885_MBP3]		= "mbp3",
-	[ALC885_IMAC91]		= "imac91",
-	[ALC889A_MB31]		= "mb31",
-	[ALC882_AUTO]		= "auto",
-};
-
-/* codec SSID table for Intel Mac */
-static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
-	SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
-	SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
-	SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
-	SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
-	SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
-	/* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
-	 * so apparently no perfect solution yet
-	 */
-	SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
-	SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
-	SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
-	{} /* terminator */
-};
-
-static const struct alc_config_preset alc882_presets[] = {
-	   [ALC885_MBA21] = {
-			.mixers = { alc885_mba21_mixer },
-			.init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
-			.num_dacs = 2,
-			.dac_nids = alc882_dac_nids,
-			.channel_mode = alc885_mba21_ch_modes,
-			.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
-			.input_mux = &alc882_capture_source,
-			.unsol_event = alc882_unsol_event,
-			.setup = alc885_mba21_setup,
-			.init_hook = alc_hp_automute,
-       },
-	[ALC885_MBP3] = {
-		.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc885_mbp3_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = 2,
-		.dac_nids = alc882_dac_nids,
-		.hp_nid = 0x04,
-		.channel_mode = alc885_mbp_4ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
-		.input_mux = &alc882_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc882_unsol_event,
-		.setup = alc885_mbp3_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC885_MB5] = {
-		.mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc885_mb5_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.channel_mode = alc885_mb5_6ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
-		.input_mux = &mb5_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc882_unsol_event,
-		.setup = alc885_mb5_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC885_MACMINI3] = {
-		.mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc885_macmini3_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.channel_mode = alc885_macmini3_6ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
-		.input_mux = &macmini3_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc882_unsol_event,
-		.setup = alc885_macmini3_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC885_IMAC91] = {
-		.mixers = {alc885_imac91_mixer},
-		.init_verbs = { alc885_imac91_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.channel_mode = alc885_mba21_ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
-		.input_mux = &alc889A_imac91_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc882_unsol_event,
-		.setup = alc885_imac91_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC889A_MB31] = {
-		.mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
-		.init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
-			alc880_gpio1_init_verbs },
-		.adc_nids = alc883_adc_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.capsrc_nids = alc883_capsrc_nids,
-		.dac_nids = alc883_dac_nids,
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.channel_mode = alc889A_mb31_6ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
-		.input_mux = &alc889A_mb31_capture_source,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.unsol_event = alc889A_mb31_unsol_event,
-		.init_hook = alc889A_mb31_automute,
-	},
-};
-
-
diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c
deleted file mode 100644
index a18952ed4311993e9a56d1a1c356b819cb6c7de7..0000000000000000000000000000000000000000
--- a/sound/pci/hda/alc_quirks.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Common codes for Realtek codec quirks
- * included by patch_realtek.c
- */
-
-/*
- * configuration template - to be copied to the spec instance
- */
-struct alc_config_preset {
-	const struct snd_kcontrol_new *mixers[5]; /* should be identical size
-					     * with spec
-					     */
-	const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
-	const struct hda_verb *init_verbs[5];
-	unsigned int num_dacs;
-	const hda_nid_t *dac_nids;
-	hda_nid_t dig_out_nid;		/* optional */
-	hda_nid_t hp_nid;		/* optional */
-	const hda_nid_t *slave_dig_outs;
-	unsigned int num_adc_nids;
-	const hda_nid_t *adc_nids;
-	const hda_nid_t *capsrc_nids;
-	hda_nid_t dig_in_nid;
-	unsigned int num_channel_mode;
-	const struct hda_channel_mode *channel_mode;
-	int need_dac_fix;
-	int const_channel_count;
-	unsigned int num_mux_defs;
-	const struct hda_input_mux *input_mux;
-	void (*unsol_event)(struct hda_codec *, unsigned int);
-	void (*setup)(struct hda_codec *);
-	void (*init_hook)(struct hda_codec *);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	const struct hda_amp_list *loopbacks;
-	void (*power_hook)(struct hda_codec *codec);
-#endif
-};
-
-/*
- * channel mode setting
- */
-static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
-				    spec->num_channel_mode);
-}
-
-static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
-				   spec->num_channel_mode,
-				   spec->ext_channel_count);
-}
-
-static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
-				      spec->num_channel_mode,
-				      &spec->ext_channel_count);
-	if (err >= 0 && !spec->const_channel_count) {
-		spec->multiout.max_channels = spec->ext_channel_count;
-		if (spec->need_dac_fix)
-			spec->multiout.num_dacs = spec->multiout.max_channels / 2;
-	}
-	return err;
-}
-
-/*
- * Control the mode of pin widget settings via the mixer.  "pc" is used
- * instead of "%" to avoid consequences of accidentally treating the % as
- * being part of a format specifier.  Maximum allowed length of a value is
- * 63 characters plus NULL terminator.
- *
- * Note: some retasking pin complexes seem to ignore requests for input
- * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
- * are requested.  Therefore order this list so that this behaviour will not
- * cause problems when mixer clients move through the enum sequentially.
- * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
- * March 2006.
- */
-static const char * const alc_pin_mode_names[] = {
-	"Mic 50pc bias", "Mic 80pc bias",
-	"Line in", "Line out", "Headphone out",
-};
-static const unsigned char alc_pin_mode_values[] = {
-	PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
-};
-/* The control can present all 5 options, or it can limit the options based
- * in the pin being assumed to be exclusively an input or an output pin.  In
- * addition, "input" pins may or may not process the mic bias option
- * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
- * accept requests for bias as of chip versions up to March 2006) and/or
- * wiring in the computer.
- */
-#define ALC_PIN_DIR_IN              0x00
-#define ALC_PIN_DIR_OUT             0x01
-#define ALC_PIN_DIR_INOUT           0x02
-#define ALC_PIN_DIR_IN_NOMICBIAS    0x03
-#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
-
-/* Info about the pin modes supported by the different pin direction modes.
- * For each direction the minimum and maximum values are given.
- */
-static const signed char alc_pin_mode_dir_info[5][2] = {
-	{ 0, 2 },    /* ALC_PIN_DIR_IN */
-	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
-	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
-	{ 2, 2 },    /* ALC_PIN_DIR_IN_NOMICBIAS */
-	{ 2, 4 },    /* ALC_PIN_DIR_INOUT_NOMICBIAS */
-};
-#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
-#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
-#define alc_pin_mode_n_items(_dir) \
-	(alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
-
-static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_info *uinfo)
-{
-	unsigned int item_num = uinfo->value.enumerated.item;
-	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
-
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
-
-	if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
-		item_num = alc_pin_mode_min(dir);
-	strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
-	return 0;
-}
-
-static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_value *ucontrol)
-{
-	unsigned int i;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
-						 AC_VERB_GET_PIN_WIDGET_CONTROL,
-						 0x00);
-
-	/* Find enumerated value for current pinctl setting */
-	i = alc_pin_mode_min(dir);
-	while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
-		i++;
-	*valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
-	return 0;
-}
-
-static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_value *ucontrol)
-{
-	signed int change;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
-						 AC_VERB_GET_PIN_WIDGET_CONTROL,
-						 0x00);
-
-	if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
-		val = alc_pin_mode_min(dir);
-
-	change = pinctl != alc_pin_mode_values[val];
-	if (change) {
-		/* Set pin mode to that requested */
-		snd_hda_codec_write_cache(codec, nid, 0,
-					  AC_VERB_SET_PIN_WIDGET_CONTROL,
-					  alc_pin_mode_values[val]);
-
-		/* Also enable the retasking pin's input/output as required
-		 * for the requested pin mode.  Enum values of 2 or less are
-		 * input modes.
-		 *
-		 * Dynamically switching the input/output buffers probably
-		 * reduces noise slightly (particularly on input) so we'll
-		 * do it.  However, having both input and output buffers
-		 * enabled simultaneously doesn't seem to be problematic if
-		 * this turns out to be necessary in the future.
-		 */
-		if (val <= 2) {
-			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-						 HDA_AMP_MUTE, HDA_AMP_MUTE);
-			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
-						 HDA_AMP_MUTE, 0);
-		} else {
-			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
-						 HDA_AMP_MUTE, HDA_AMP_MUTE);
-			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-						 HDA_AMP_MUTE, 0);
-		}
-	}
-	return change;
-}
-
-#define ALC_PIN_MODE(xname, nid, dir) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-	  .info = alc_pin_mode_info, \
-	  .get = alc_pin_mode_get, \
-	  .put = alc_pin_mode_put, \
-	  .private_value = nid | (dir<<16) }
-
-/* A switch control for ALC260 GPIO pins.  Multiple GPIOs can be ganged
- * together using a mask with more than one bit set.  This control is
- * currently used only by the ALC260 test model.  At this stage they are not
- * needed for any "production" models.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_gpio_data_info	snd_ctl_boolean_mono_info
-
-static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int val = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_GPIO_DATA, 0x00);
-
-	*valp = (val & mask) != 0;
-	return 0;
-}
-static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	signed int change;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
-						    AC_VERB_GET_GPIO_DATA,
-						    0x00);
-
-	/* Set/unset the masked GPIO bit(s) as needed */
-	change = (val == 0 ? 0 : mask) != (gpio_data & mask);
-	if (val == 0)
-		gpio_data &= ~mask;
-	else
-		gpio_data |= mask;
-	snd_hda_codec_write_cache(codec, nid, 0,
-				  AC_VERB_SET_GPIO_DATA, gpio_data);
-
-	return change;
-}
-#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-	  .info = alc_gpio_data_info, \
-	  .get = alc_gpio_data_get, \
-	  .put = alc_gpio_data_put, \
-	  .private_value = nid | (mask<<16) }
-#endif   /* CONFIG_SND_DEBUG */
-
-/* A switch control to allow the enabling of the digital IO pins on the
- * ALC260.  This is incredibly simplistic; the intention of this control is
- * to provide something in the test model allowing digital outputs to be
- * identified if present.  If models are found which can utilise these
- * outputs a more complete mixer control can be devised for those models if
- * necessary.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_spdif_ctrl_info	snd_ctl_boolean_mono_info
-
-static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int val = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_DIGI_CONVERT_1, 0x00);
-
-	*valp = (val & mask) != 0;
-	return 0;
-}
-static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	signed int change;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
-						    AC_VERB_GET_DIGI_CONVERT_1,
-						    0x00);
-
-	/* Set/unset the masked control bit(s) as needed */
-	change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
-	if (val==0)
-		ctrl_data &= ~mask;
-	else
-		ctrl_data |= mask;
-	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
-				  ctrl_data);
-
-	return change;
-}
-#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-	  .info = alc_spdif_ctrl_info, \
-	  .get = alc_spdif_ctrl_get, \
-	  .put = alc_spdif_ctrl_put, \
-	  .private_value = nid | (mask<<16) }
-#endif   /* CONFIG_SND_DEBUG */
-
-/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
- * Again, this is only used in the ALC26x test models to help identify when
- * the EAPD line must be asserted for features to work.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_eapd_ctrl_info	snd_ctl_boolean_mono_info
-
-static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int val = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_EAPD_BTLENABLE, 0x00);
-
-	*valp = (val & mask) != 0;
-	return 0;
-}
-
-static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	int change;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
-						    AC_VERB_GET_EAPD_BTLENABLE,
-						    0x00);
-
-	/* Set/unset the masked control bit(s) as needed */
-	change = (!val ? 0 : mask) != (ctrl_data & mask);
-	if (!val)
-		ctrl_data &= ~mask;
-	else
-		ctrl_data |= mask;
-	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
-				  ctrl_data);
-
-	return change;
-}
-
-#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-	  .info = alc_eapd_ctrl_info, \
-	  .get = alc_eapd_ctrl_get, \
-	  .put = alc_eapd_ctrl_put, \
-	  .private_value = nid | (mask<<16) }
-#endif   /* CONFIG_SND_DEBUG */
-
-static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-
-	if (!cfg->line_outs) {
-		while (cfg->line_outs < AUTO_CFG_MAX_OUTS &&
-		       cfg->line_out_pins[cfg->line_outs])
-			cfg->line_outs++;
-	}
-	if (!cfg->speaker_outs) {
-		while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS &&
-		       cfg->speaker_pins[cfg->speaker_outs])
-			cfg->speaker_outs++;
-	}
-	if (!cfg->hp_outs) {
-		while (cfg->hp_outs < AUTO_CFG_MAX_OUTS &&
-		       cfg->hp_pins[cfg->hp_outs])
-			cfg->hp_outs++;
-	}
-}
-
-/*
- * set up from the preset table
- */
-static void setup_preset(struct hda_codec *codec,
-			 const struct alc_config_preset *preset)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
-		add_mixer(spec, preset->mixers[i]);
-	spec->cap_mixer = preset->cap_mixer;
-	for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
-	     i++)
-		add_verb(spec, preset->init_verbs[i]);
-
-	spec->channel_mode = preset->channel_mode;
-	spec->num_channel_mode = preset->num_channel_mode;
-	spec->need_dac_fix = preset->need_dac_fix;
-	spec->const_channel_count = preset->const_channel_count;
-
-	if (preset->const_channel_count)
-		spec->multiout.max_channels = preset->const_channel_count;
-	else
-		spec->multiout.max_channels = spec->channel_mode[0].channels;
-	spec->ext_channel_count = spec->channel_mode[0].channels;
-
-	spec->multiout.num_dacs = preset->num_dacs;
-	spec->multiout.dac_nids = preset->dac_nids;
-	spec->multiout.dig_out_nid = preset->dig_out_nid;
-	spec->multiout.slave_dig_outs = preset->slave_dig_outs;
-	spec->multiout.hp_nid = preset->hp_nid;
-
-	spec->num_mux_defs = preset->num_mux_defs;
-	if (!spec->num_mux_defs)
-		spec->num_mux_defs = 1;
-	spec->input_mux = preset->input_mux;
-
-	spec->num_adc_nids = preset->num_adc_nids;
-	spec->adc_nids = preset->adc_nids;
-	spec->capsrc_nids = preset->capsrc_nids;
-	spec->dig_in_nid = preset->dig_in_nid;
-
-	spec->unsol_event = preset->unsol_event;
-	spec->init_hook = preset->init_hook;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->power_hook = preset->power_hook;
-	spec->loopback.amplist = preset->loopbacks;
-#endif
-
-	if (preset->setup)
-		preset->setup(codec);
-
-	alc_fixup_autocfg_pin_nums(codec);
-}
-
-static void alc_simple_setup_automute(struct alc_spec *spec, int mode)
-{
-	int lo_pin = spec->autocfg.line_out_pins[0];
-
-	if (lo_pin == spec->autocfg.speaker_pins[0] ||
-		lo_pin == spec->autocfg.hp_pins[0])
-		lo_pin = 0;
-	spec->automute_mode = mode;
-	spec->detect_hp = !!spec->autocfg.hp_pins[0];
-	spec->detect_lo = !!lo_pin;
-	spec->automute_lo = spec->automute_lo_possible = !!lo_pin;
-	spec->automute_speaker = spec->automute_speaker_possible = !!spec->autocfg.speaker_pins[0];
-}
-
-/* auto-toggle front mic */
-static void alc88x_simple_mic_automute(struct hda_codec *codec)
-{
- 	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x18);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
-}
-
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 684307372d73e87535323ecc2e250a2ffab21f8e..7a8fcc4c15f84acf5baab4ec9301f35f84a75049 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -19,6 +19,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -2304,7 +2305,7 @@ typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
 
 /* apply the function to all matching slave ctls in the mixer list */
 static int map_slaves(struct hda_codec *codec, const char * const *slaves,
-		      map_slave_func_t func, void *data) 
+		      const char *suffix, map_slave_func_t func, void *data) 
 {
 	struct hda_nid_item *items;
 	const char * const *s;
@@ -2317,7 +2318,14 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
 		    sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
 			continue;
 		for (s = slaves; *s; s++) {
-			if (!strcmp(sctl->id.name, *s)) {
+			char tmpname[sizeof(sctl->id.name)];
+			const char *name = *s;
+			if (suffix) {
+				snprintf(tmpname, sizeof(tmpname), "%s %s",
+					 name, suffix);
+				name = tmpname;
+			}
+			if (!strcmp(sctl->id.name, name)) {
 				err = func(data, sctl);
 				if (err)
 					return err;
@@ -2333,12 +2341,65 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl)
 	return 1;
 }
 
+/* guess the value corresponding to 0dB */
+static int get_kctl_0dB_offset(struct snd_kcontrol *kctl)
+{
+	int _tlv[4];
+	const int *tlv = NULL;
+	int val = -1;
+
+	if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+		/* FIXME: set_fs() hack for obtaining user-space TLV data */
+		mm_segment_t fs = get_fs();
+		set_fs(get_ds());
+		if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
+			tlv = _tlv;
+		set_fs(fs);
+	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
+		tlv = kctl->tlv.p;
+	if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE)
+		val = -tlv[2] / tlv[3];
+	return val;
+}
+
+/* call kctl->put with the given value(s) */
+static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
+{
+	struct snd_ctl_elem_value *ucontrol;
+	ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL);
+	if (!ucontrol)
+		return -ENOMEM;
+	ucontrol->value.integer.value[0] = val;
+	ucontrol->value.integer.value[1] = val;
+	kctl->put(kctl, ucontrol);
+	kfree(ucontrol);
+	return 0;
+}
+
+/* initialize the slave volume with 0dB */
+static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
+{
+	int offset = get_kctl_0dB_offset(slave);
+	if (offset > 0)
+		put_kctl_with_value(slave, offset);
+	return 0;
+}
+
+/* unmute the slave */
+static int init_slave_unmute(void *data, struct snd_kcontrol *slave)
+{
+	return put_kctl_with_value(slave, 1);
+}
+
 /**
  * snd_hda_add_vmaster - create a virtual master control and add slaves
  * @codec: HD-audio codec
  * @name: vmaster control name
  * @tlv: TLV data (optional)
  * @slaves: slave control names (optional)
+ * @suffix: suffix string to each slave name (optional)
+ * @init_slave_vol: initialize slaves to unmute/0dB
+ * @ctl_ret: store the vmaster kcontrol in return
  *
  * Create a virtual master control with the given name.  The TLV data
  * must be either NULL or a valid data.
@@ -2349,13 +2410,18 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl)
  *
  * This function returns zero if successful or a negative error code.
  */
-int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
-			unsigned int *tlv, const char * const *slaves)
+int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+			unsigned int *tlv, const char * const *slaves,
+			  const char *suffix, bool init_slave_vol,
+			  struct snd_kcontrol **ctl_ret)
 {
 	struct snd_kcontrol *kctl;
 	int err;
 
-	err = map_slaves(codec, slaves, check_slave_present, NULL);
+	if (ctl_ret)
+		*ctl_ret = NULL;
+
+	err = map_slaves(codec, slaves, suffix, check_slave_present, NULL);
 	if (err != 1) {
 		snd_printdd("No slave found for %s\n", name);
 		return 0;
@@ -2367,13 +2433,119 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
 	if (err < 0)
 		return err;
 
-	err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave,
-			 kctl);
+	err = map_slaves(codec, slaves, suffix,
+			 (map_slave_func_t)snd_ctl_add_slave, kctl);
 	if (err < 0)
 		return err;
+
+	/* init with master mute & zero volume */
+	put_kctl_with_value(kctl, 0);
+	if (init_slave_vol)
+		map_slaves(codec, slaves, suffix,
+			   tlv ? init_slave_0dB : init_slave_unmute, kctl);
+
+	if (ctl_ret)
+		*ctl_ret = kctl;
 	return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
+EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster);
+
+/*
+ * mute-LED control using vmaster
+ */
+static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
+{
+	static const char * const texts[] = {
+		"Off", "On", "Follow Master"
+	};
+	unsigned int index;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	index = uinfo->value.enumerated.item;
+	if (index >= 3)
+		index = 2;
+	strcpy(uinfo->value.enumerated.name, texts[index]);
+	return 0;
+}
+
+static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = hook->mute_mode;
+	return 0;
+}
+
+static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
+	unsigned int old_mode = hook->mute_mode;
+
+	hook->mute_mode = ucontrol->value.enumerated.item[0];
+	if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER)
+		hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+	if (old_mode == hook->mute_mode)
+		return 0;
+	snd_hda_sync_vmaster_hook(hook);
+	return 1;
+}
+
+static struct snd_kcontrol_new vmaster_mute_mode = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Mute-LED Mode",
+	.info = vmaster_mute_mode_info,
+	.get = vmaster_mute_mode_get,
+	.put = vmaster_mute_mode_put,
+};
+
+/*
+ * Add a mute-LED hook with the given vmaster switch kctl
+ * "Mute-LED Mode" control is automatically created and associated with
+ * the given hook.
+ */
+int snd_hda_add_vmaster_hook(struct hda_codec *codec,
+			     struct hda_vmaster_mute_hook *hook,
+			     bool expose_enum_ctl)
+{
+	struct snd_kcontrol *kctl;
+
+	if (!hook->hook || !hook->sw_kctl)
+		return 0;
+	snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec);
+	hook->codec = codec;
+	hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+	if (!expose_enum_ctl)
+		return 0;
+	kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
+	if (!kctl)
+		return -ENOMEM;
+	return snd_hda_ctl_add(codec, 0, kctl);
+}
+EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook);
+
+/*
+ * Call the hook with the current value for synchronization
+ * Should be called in init callback
+ */
+void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
+{
+	if (!hook->hook || !hook->codec)
+		return;
+	switch (hook->mute_mode) {
+	case HDA_VMUTE_FOLLOW_MASTER:
+		snd_ctl_sync_vmaster_hook(hook->sw_kctl);
+		break;
+	default:
+		hook->hook(hook->codec, hook->mute_mode);
+		break;
+	}
+}
+EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);
+
 
 /**
  * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
@@ -5272,6 +5444,10 @@ int snd_hda_suspend(struct hda_bus *bus)
 	list_for_each_entry(codec, &bus->codec_list, list) {
 		if (hda_codec_is_power_on(codec))
 			hda_call_codec_suspend(codec);
+		else /* forcibly change the power to D3 even if not used */
+			hda_set_power_state(codec,
+					    codec->afg ? codec->afg : codec->mfg,
+					    AC_PWRST_D3);
 		if (codec->patch_ops.post_suspend)
 			codec->patch_ops.post_suspend(codec);
 	}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index f0f1943a4b2c890ce4affe17425de6210e53ea89..9a9f372e1be4f50070e818116dd7786156fb089c 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -855,6 +855,7 @@ struct hda_codec {
 	unsigned int pins_shutup:1;	/* pins are shut up */
 	unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
 	unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
+	unsigned int no_jack_detect:1;	/* Machine has no jack-detection */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	unsigned int power_on :1;	/* current (global) power-state */
 	unsigned int power_transition :1; /* power-state in transition */
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index c1da422e085a5230d8b7eb837925772b11ea4328..b58b4b1687fa674243be3a167d20e64d8e90cbfe 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -385,8 +385,8 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
 static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
 {
 	static unsigned int alsa_rates[] = {
-		5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
-		96000, 176400, 192000, 384000
+		5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
+		88200, 96000, 176400, 192000, 384000
 	};
 	int i, j;
 
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 95dfb687494144e54b191e3f7f4dbe7179bcf37d..c19e71a94e1bd5a792ff100cba817134bae04b12 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -84,7 +84,7 @@ module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 module_param_array(position_fix, int, NULL, 0444);
 MODULE_PARM_DESC(position_fix, "DMA pointer read method."
-		 "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO).");
+		 "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO).");
 module_param_array(bdl_pos_adj, int, NULL, 0644);
 MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
 module_param_array(probe_mask, int, NULL, 0444);
@@ -94,7 +94,7 @@ MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
 module_param(single_cmd, bool, 0444);
 MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
 		 "(for debugging only).");
-module_param(enable_msi, int, 0444);
+module_param(enable_msi, bint, 0444);
 MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
 module_param_array(patch, charp, NULL, 0444);
@@ -121,8 +121,8 @@ module_param(power_save_controller, bool, 0644);
 MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
 #endif
 
-static bool align_buffer_size = 1;
-module_param(align_buffer_size, bool, 0644);
+static int align_buffer_size = -1;
+module_param(align_buffer_size, bint, 0644);
 MODULE_PARM_DESC(align_buffer_size,
 		"Force buffer and period sizes to be multiple of 128 bytes.");
 
@@ -148,6 +148,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
 			 "{Intel, PCH},"
 			 "{Intel, CPT},"
 			 "{Intel, PPT},"
+			 "{Intel, LPT},"
 			 "{Intel, PBG},"
 			 "{Intel, SCH},"
 			 "{ATI, SB450},"
@@ -329,6 +330,7 @@ enum {
 	POS_FIX_LPIB,
 	POS_FIX_POSBUF,
 	POS_FIX_VIACOMBO,
+	POS_FIX_COMBO,
 };
 
 /* Defines for ATI HD Audio support in SB450 south bridge */
@@ -515,6 +517,7 @@ enum {
 #define AZX_DCAPS_SYNC_WRITE	(1 << 19)	/* sync each cmd write */
 #define AZX_DCAPS_OLD_SSYNC	(1 << 20)	/* Old SSYNC reg for ICH */
 #define AZX_DCAPS_BUFSIZE	(1 << 21)	/* no buffer size alignment */
+#define AZX_DCAPS_ALIGN_BUFSIZE	(1 << 22)	/* buffer size alignment */
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -527,7 +530,8 @@ enum {
 
 /* quirks for Nvidia */
 #define AZX_DCAPS_PRESET_NVIDIA \
-	(AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI)
+	(AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\
+	 AZX_DCAPS_ALIGN_BUFSIZE)
 
 static char *driver_short_names[] __devinitdata = {
 	[AZX_DRIVER_ICH] = "HDA Intel",
@@ -2347,17 +2351,6 @@ static void azx_power_notify(struct hda_bus *bus)
  * power management
  */
 
-static int snd_hda_codecs_inuse(struct hda_bus *bus)
-{
-	struct hda_codec *codec;
-
-	list_for_each_entry(codec, &bus->codec_list, list) {
-		if (snd_hda_codec_needs_resume(codec))
-			return 1;
-	}
-	return 0;
-}
-
 static int azx_suspend(struct pci_dev *pci, pm_message_t state)
 {
 	struct snd_card *card = pci_get_drvdata(pci);
@@ -2404,8 +2397,7 @@ static int azx_resume(struct pci_dev *pci)
 		return -EIO;
 	azx_init_pci(chip);
 
-	if (snd_hda_codecs_inuse(chip->bus))
-		azx_init_chip(chip, 1);
+	azx_init_chip(chip, 1);
 
 	snd_hda_resume(chip->bus);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -2517,6 +2509,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
 	case POS_FIX_LPIB:
 	case POS_FIX_POSBUF:
 	case POS_FIX_VIACOMBO:
+	case POS_FIX_COMBO:
 		return fix;
 	}
 
@@ -2696,6 +2689,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 
 	chip->position_fix[0] = chip->position_fix[1] =
 		check_position_fix(chip, position_fix[dev]);
+	/* combo mode uses LPIB for playback */
+	if (chip->position_fix[0] == POS_FIX_COMBO) {
+		chip->position_fix[0] = POS_FIX_LPIB;
+		chip->position_fix[1] = POS_FIX_AUTO;
+	}
+
 	check_probe_mask(chip, dev);
 
 	chip->single_cmd = single_cmd;
@@ -2774,9 +2773,16 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 	}
 
 	/* disable buffer size rounding to 128-byte multiples if supported */
-	chip->align_buffer_size = align_buffer_size;
-	if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
-		chip->align_buffer_size = 0;
+	if (align_buffer_size >= 0)
+		chip->align_buffer_size = !!align_buffer_size;
+	else {
+		if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
+			chip->align_buffer_size = 0;
+		else if (chip->driver_caps & AZX_DCAPS_ALIGN_BUFSIZE)
+			chip->align_buffer_size = 1;
+		else
+			chip->align_buffer_size = 1;
+	}
 
 	/* allow 64bit DMA address if supported by H/W */
 	if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
@@ -2992,6 +2998,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
 	{ PCI_DEVICE(0x8086, 0x1e20),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
 	  AZX_DCAPS_BUFSIZE},
+	/* Lynx Point */
+	{ PCI_DEVICE(0x8086, 0x8c20),
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
+	  AZX_DCAPS_BUFSIZE},
 	/* SCH */
 	{ PCI_DEVICE(0x8086, 0x811b),
 	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 9d819c4b4923d18c67447953b02395408e923afc..d68948499fbc15d7342ba0c9a63675d769b95a92 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -19,6 +19,22 @@
 #include "hda_local.h"
 #include "hda_jack.h"
 
+bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
+{
+	if (codec->no_jack_detect)
+		return false;
+	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
+		return false;
+	if (!codec->ignore_misc_bit &&
+	    (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+	     AC_DEFCFG_MISC_NO_PRESENCE))
+		return false;
+	if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+		return false;
+	return true;
+}
+EXPORT_SYMBOL_HDA(is_jack_detectable);
+
 /* execute pin sense measurement */
 static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)
 {
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index f8f97c71c9c1a05fc8016187228f77aca71256d7..c66655cf413a1bc074f62ac91e0ed6e3907e342d 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -62,18 +62,7 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
 u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
 int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
 
-static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
-{
-	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
-		return false;
-	if (!codec->ignore_misc_bit &&
-	    (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
-	     AC_DEFCFG_MISC_NO_PRESENCE))
-		return false;
-	if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
-		return false;
-	return true;
-}
+bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
 
 int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 			  const char *name, int idx);
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index aca8d3193b9507f55080b13811936fca3a301a28..0ec9248165bca9c7f7f7d47aaffe4abc863b600c 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -139,10 +139,36 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
 			     unsigned int *tlv);
 struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
 					    const char *name);
-int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
-			unsigned int *tlv, const char * const *slaves);
+int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+			  unsigned int *tlv, const char * const *slaves,
+			  const char *suffix, bool init_slave_vol,
+			  struct snd_kcontrol **ctl_ret);
+#define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \
+	__snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL)
 int snd_hda_codec_reset(struct hda_codec *codec);
 
+enum {
+	HDA_VMUTE_OFF,
+	HDA_VMUTE_ON,
+	HDA_VMUTE_FOLLOW_MASTER,
+};
+
+struct hda_vmaster_mute_hook {
+	/* below two fields must be filled by the caller of
+	 * snd_hda_add_vmaster_hook() beforehand
+	 */
+	struct snd_kcontrol *sw_kctl;
+	void (*hook)(void *, int);
+	/* below are initialized automatically */
+	unsigned int mute_mode; /* HDA_VMUTE_XXX */
+	struct hda_codec *codec;
+};
+
+int snd_hda_add_vmaster_hook(struct hda_codec *codec,
+			     struct hda_vmaster_mute_hook *hook,
+			     bool expose_enum_ctl);
+void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook);
+
 /* amp value bits */
 #define HDA_AMP_MUTE	0x80
 #define HDA_AMP_UNMUTE	0x00
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 9cb14b42dfff48f890ee10871dea7fffb14b7054..7143393927da34ddeac2c86ce6538c669e85d16a 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -82,6 +82,7 @@ struct ad198x_spec {
 	unsigned int inv_jack_detect: 1;/* inverted jack-detection */
 	unsigned int inv_eapd: 1;	/* inverted EAPD implementation */
 	unsigned int analog_beep: 1;	/* analog beep input present */
+	unsigned int avoid_init_slave_vol:1;
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	struct hda_loopback_check loopback;
@@ -137,51 +138,17 @@ static int ad198x_init(struct hda_codec *codec)
 	return 0;
 }
 
-static const char * const ad_slave_vols[] = {
-	"Front Playback Volume",
-	"Surround Playback Volume",
-	"Center Playback Volume",
-	"LFE Playback Volume",
-	"Side Playback Volume",
-	"Headphone Playback Volume",
-	"Mono Playback Volume",
-	"Speaker Playback Volume",
-	"IEC958 Playback Volume",
+static const char * const ad_slave_pfxs[] = {
+	"Front", "Surround", "Center", "LFE", "Side",
+	"Headphone", "Mono", "Speaker", "IEC958",
 	NULL
 };
 
-static const char * const ad_slave_sws[] = {
-	"Front Playback Switch",
-	"Surround Playback Switch",
-	"Center Playback Switch",
-	"LFE Playback Switch",
-	"Side Playback Switch",
-	"Headphone Playback Switch",
-	"Mono Playback Switch",
-	"Speaker Playback Switch",
-	"IEC958 Playback Switch",
+static const char * const ad1988_6stack_fp_slave_pfxs[] = {
+	"Front", "Surround", "Center", "LFE", "Side", "IEC958",
 	NULL
 };
 
-static const char * const ad1988_6stack_fp_slave_vols[] = {
-	"Front Playback Volume",
-	"Surround Playback Volume",
-	"Center Playback Volume",
-	"LFE Playback Volume",
-	"Side Playback Volume",
-	"IEC958 Playback Volume",
-	NULL
-};
-
-static const char * const ad1988_6stack_fp_slave_sws[] = {
-	"Front Playback Switch",
-	"Surround Playback Switch",
-	"Center Playback Switch",
-	"LFE Playback Switch",
-	"Side Playback Switch",
-	"IEC958 Playback Switch",
-	NULL
-};
 static void ad198x_free_kctls(struct hda_codec *codec);
 
 #ifdef CONFIG_SND_HDA_INPUT_BEEP
@@ -257,10 +224,12 @@ static int ad198x_build_controls(struct hda_codec *codec)
 		unsigned int vmaster_tlv[4];
 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
 					HDA_OUTPUT, vmaster_tlv);
-		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+		err = __snd_hda_add_vmaster(codec, "Master Playback Volume",
 					  vmaster_tlv,
 					  (spec->slave_vols ?
-					   spec->slave_vols : ad_slave_vols));
+					   spec->slave_vols : ad_slave_pfxs),
+					  "Playback Volume",
+					  !spec->avoid_init_slave_vol, NULL);
 		if (err < 0)
 			return err;
 	}
@@ -268,7 +237,8 @@ static int ad198x_build_controls(struct hda_codec *codec)
 		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
 					  NULL,
 					  (spec->slave_sws ?
-					   spec->slave_sws : ad_slave_sws));
+					   spec->slave_sws : ad_slave_pfxs),
+					  "Playback Switch");
 		if (err < 0)
 			return err;
 	}
@@ -3385,8 +3355,8 @@ static int patch_ad1988(struct hda_codec *codec)
 
 	if (spec->autocfg.hp_pins[0]) {
 		spec->mixers[spec->num_mixers++] = ad1988_hp_mixers;
-		spec->slave_vols = ad1988_6stack_fp_slave_vols;
-		spec->slave_sws = ad1988_6stack_fp_slave_sws;
+		spec->slave_vols = ad1988_6stack_fp_slave_pfxs;
+		spec->slave_sws = ad1988_6stack_fp_slave_pfxs;
 		spec->alt_dac_nid = ad1988_alt_dac_nid;
 		spec->stream_analog_alt_playback =
 			&ad198x_pcm_analog_alt_playback;
@@ -3594,16 +3564,8 @@ static const struct hda_amp_list ad1884_loopbacks[] = {
 #endif
 
 static const char * const ad1884_slave_vols[] = {
-	"PCM Playback Volume",
-	"Mic Playback Volume",
-	"Mono Playback Volume",
-	"Front Mic Playback Volume",
-	"Mic Playback Volume",
-	"CD Playback Volume",
-	"Internal Mic Playback Volume",
-	"Docking Mic Playback Volume",
-	/* "Beep Playback Volume", */
-	"IEC958 Playback Volume",
+	"PCM", "Mic", "Mono", "Front Mic", "Mic", "CD",
+	"Internal Mic", "Docking Mic", /* "Beep", */ "IEC958",
 	NULL
 };
 
@@ -3644,6 +3606,8 @@ static int patch_ad1884(struct hda_codec *codec)
 	spec->vmaster_nid = 0x04;
 	/* we need to cover all playback volumes */
 	spec->slave_vols = ad1884_slave_vols;
+	/* slaves may contain input volumes, so we can't raise to 0dB blindly */
+	spec->avoid_init_slave_vol = 1;
 
 	codec->patch_ops = ad198x_patch_ops;
 
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index f584f6d8ffcccfe1237e8495289cec805b91b9bb..8c6523bbc797f8c3a22bbbeedc4a19194e26027e 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -70,6 +70,8 @@ struct conexant_spec {
 	const struct snd_kcontrol_new *mixers[5];
 	int num_mixers;
 	hda_nid_t vmaster_nid;
+	struct hda_vmaster_mute_hook vmaster_mute;
+	bool vmaster_mute_led;
 
 	const struct hda_verb *init_verbs[5];	/* initialization verbs
 						 * don't forget NULL
@@ -465,21 +467,8 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = {
 };
 #endif
 
-static const char * const slave_vols[] = {
-	"Headphone Playback Volume",
-	"Speaker Playback Volume",
-	"Front Playback Volume",
-	"Surround Playback Volume",
-	"CLFE Playback Volume",
-	NULL
-};
-
-static const char * const slave_sws[] = {
-	"Headphone Playback Switch",
-	"Speaker Playback Switch",
-	"Front Playback Switch",
-	"Surround Playback Switch",
-	"CLFE Playback Switch",
+static const char * const slave_pfxs[] = {
+	"Headphone", "Speaker", "Front", "Surround", "CLFE",
 	NULL
 };
 
@@ -519,14 +508,17 @@ static int conexant_build_controls(struct hda_codec *codec)
 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
 					HDA_OUTPUT, vmaster_tlv);
 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  vmaster_tlv, slave_vols);
+					  vmaster_tlv, slave_pfxs,
+					  "Playback Volume");
 		if (err < 0)
 			return err;
 	}
 	if (spec->vmaster_nid &&
 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
-		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
-					  NULL, slave_sws);
+		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+					    NULL, slave_pfxs,
+					    "Playback Switch", true,
+					    &spec->vmaster_mute.sw_kctl);
 		if (err < 0)
 			return err;
 	}
@@ -3034,7 +3026,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
 	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
 	SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO),
-	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
 	SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO),
 	{}
 };
@@ -3943,6 +3934,63 @@ static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
 		snd_hda_jack_detect_enable(codec, pins[i], action);
 }
 
+static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+{
+	int i;
+	for (i = 0; i < nums; i++)
+		if (list[i] == nid)
+			return true;
+	return false;
+}
+
+/* is the given NID found in any of autocfg items? */
+static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid)
+{
+	int i;
+
+	if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
+	    found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
+	    found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) ||
+	    found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs))
+		return true;
+	for (i = 0; i < cfg->num_inputs; i++)
+		if (cfg->inputs[i].pin == nid)
+			return true;
+	if (cfg->dig_in_pin == nid)
+		return true;
+	return false;
+}
+
+/* clear unsol-event tags on unused pins; Conexant codecs seem to leave
+ * invalid unsol tags by some reason
+ */
+static void clear_unsol_on_unused_pins(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i;
+
+	for (i = 0; i < codec->init_pins.used; i++) {
+		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+		if (!found_in_autocfg(cfg, pin->nid))
+			snd_hda_codec_write(codec, pin->nid, 0,
+					    AC_VERB_SET_UNSOLICITED_ENABLE, 0);
+	}
+}
+
+/* turn on/off EAPD according to Master switch */
+static void cx_auto_vmaster_hook(void *private_data, int enabled)
+{
+	struct hda_codec *codec = private_data;
+	struct conexant_spec *spec = codec->spec;
+
+	if (enabled && spec->pin_eapd_ctrls) {
+		cx_auto_update_speakers(codec);
+		return;
+	}
+	cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled);
+}
+
 static void cx_auto_init_output(struct hda_codec *codec)
 {
 	struct conexant_spec *spec = codec->spec;
@@ -3983,6 +4031,7 @@ static void cx_auto_init_output(struct hda_codec *codec)
 	/* turn on all EAPDs if no individual EAPD control is available */
 	if (!spec->pin_eapd_ctrls)
 		cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
+	clear_unsol_on_unused_pins(codec);
 }
 
 static void cx_auto_init_input(struct hda_codec *codec)
@@ -4046,11 +4095,13 @@ static void cx_auto_init_digital(struct hda_codec *codec)
 
 static int cx_auto_init(struct hda_codec *codec)
 {
+	struct conexant_spec *spec = codec->spec;
 	/*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/
 	cx_auto_init_output(codec);
 	cx_auto_init_input(codec);
 	cx_auto_init_digital(codec);
 	snd_hda_jack_report_sync(codec);
+	snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
 	return 0;
 }
 
@@ -4296,6 +4347,13 @@ static int cx_auto_build_controls(struct hda_codec *codec)
 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
 	if (err < 0)
 		return err;
+	if (spec->vmaster_mute.sw_kctl) {
+		spec->vmaster_mute.hook = cx_auto_vmaster_hook;
+		err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
+					       spec->vmaster_mute_led);
+		if (err < 0)
+			return err;
+	}
 	return 0;
 }
 
@@ -4320,7 +4378,6 @@ static int cx_auto_search_adcs(struct hda_codec *codec)
 	return 0;
 }
 
-
 static const struct hda_codec_ops cx_auto_patch_ops = {
 	.build_controls = cx_auto_build_controls,
 	.build_pcms = conexant_build_pcms,
@@ -4368,6 +4425,7 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
 	{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
 	{ 0x17, 0x21a11000 }, /* dock-mic */
 	{ 0x19, 0x2121103f }, /* dock-HP */
+	{ 0x1c, 0x21440100 }, /* dock SPDIF out */
 	{}
 };
 
@@ -4421,6 +4479,18 @@ static int patch_conexant_auto(struct hda_codec *codec)
 
 	apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
 
+	/* Show mute-led control only on HP laptops
+	 * This is a sort of white-list: on HP laptops, EAPD corresponds
+	 * only to the mute-LED without actualy amp function.  Meanwhile,
+	 * others may use EAPD really as an amp switch, so it might be
+	 * not good to expose it blindly.
+	 */
+	switch (codec->subsystem_id >> 16) {
+	case 0x103c:
+		spec->vmaster_mute_led = 1;
+		break;
+	}
+
 	err = cx_auto_search_adcs(codec);
 	if (err < 0)
 		return err;
@@ -4434,6 +4504,18 @@ static int patch_conexant_auto(struct hda_codec *codec)
 	codec->patch_ops = cx_auto_patch_ops;
 	if (spec->beep_amp)
 		snd_hda_attach_beep_device(codec, spec->beep_amp);
+
+	/* Some laptops with Conexant chips show stalls in S3 resume,
+	 * which falls into the single-cmd mode.
+	 * Better to make reset, then.
+	 */
+	if (!codec->bus->sync_write) {
+		snd_printd("hda_codec: "
+			   "Enable sync_write for stable communication\n");
+		codec->bus->sync_write = 1;
+		codec->bus->allow_bus_reset = 1;
+	}
+
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 1168ebd3fb5c9cfe3bc964b9e223f45f3513c471..540cd13f7f15e4fd4ecd3a0ae3a114a16683b76d 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1912,6 +1912,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
 { .id = 0x80862804, .name = "IbexPeak HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862805, .name = "CougarPoint HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
+{ .id = 0x80862880, .name = "CedarTrail HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x808629fb, .name = "Crestline HDMI",	.patch = patch_generic_hdmi },
 {} /* terminator */
 };
@@ -1958,6 +1959,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862803");
 MODULE_ALIAS("snd-hda-codec-id:80862804");
 MODULE_ALIAS("snd-hda-codec-id:80862805");
 MODULE_ALIAS("snd-hda-codec-id:80862806");
+MODULE_ALIAS("snd-hda-codec-id:80862880");
 MODULE_ALIAS("snd-hda-codec-id:808629fb");
 
 MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 22c73b78ac6f193b635ef362c026bf51b8fe1da8..8ea2fd65432718411776151a9b034a1251c46a49 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -198,8 +198,11 @@ struct alc_spec {
 
 	/* for virtual master */
 	hda_nid_t vmaster_nid;
+	struct hda_vmaster_mute_hook vmaster_mute;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	struct hda_loopback_check loopback;
+	int num_loopbacks;
+	struct hda_amp_list loopback_list[8];
 #endif
 
 	/* for PLL fix */
@@ -220,8 +223,6 @@ struct alc_spec {
 	struct snd_array bind_ctls;
 };
 
-#define ALC_MODEL_AUTO		0	/* common for all chips */
-
 static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
 			   int dir, unsigned int bits)
 {
@@ -300,6 +301,9 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
 	int i, type, num_conns;
 	hda_nid_t nid;
 
+	if (!spec->input_mux)
+		return 0;
+
 	mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
 	imux = &spec->input_mux[mux_idx];
 	if (!imux->num_items && mux_idx > 0)
@@ -651,15 +655,51 @@ static void alc_exec_unsol_event(struct hda_codec *codec, int action)
 	snd_hda_jack_report_sync(codec);
 }
 
+/* update the master volume per volume-knob's unsol event */
+static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid)
+{
+	unsigned int val;
+	struct snd_kcontrol *kctl;
+	struct snd_ctl_elem_value *uctl;
+
+	kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
+	if (!kctl)
+		return;
+	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+	if (!uctl)
+		return;
+	val = snd_hda_codec_read(codec, nid, 0,
+				 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+	val &= HDA_AMP_VOLMASK;
+	uctl->value.integer.value[0] = val;
+	uctl->value.integer.value[1] = val;
+	kctl->put(kctl, uctl);
+	kfree(uctl);
+}
+
 /* unsolicited event for HP jack sensing */
 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 {
+	int action;
+
 	if (codec->vendor_id == 0x10ec0880)
 		res >>= 28;
 	else
 		res >>= 26;
-	res = snd_hda_jack_get_action(codec, res);
-	alc_exec_unsol_event(codec, res);
+	action = snd_hda_jack_get_action(codec, res);
+	if (action == ALC_DCVOL_EVENT) {
+		/* Execute the dc-vol event here as it requires the NID
+		 * but we don't pass NID to alc_exec_unsol_event().
+		 * Once when we convert all static quirks to the auto-parser,
+		 * this can be integerated into there.
+		 */
+		struct hda_jack_tbl *jack;
+		jack = snd_hda_jack_tbl_get_from_tag(codec, res);
+		if (jack)
+			alc_update_knob_master(codec, jack->nid);
+		return;
+	}
+	alc_exec_unsol_event(codec, action);
 }
 
 /* call init functions of standard auto-mute helpers */
@@ -1033,45 +1073,6 @@ static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
 	return true;
 }
 
-/* rebuild imux for matching with the given auto-mic pins (if not yet) */
-static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct hda_input_mux *imux;
-	static char * const texts[3] = {
-		"Mic", "Internal Mic", "Dock Mic"
-	};
-	int i;
-
-	if (!spec->auto_mic)
-		return false;
-	imux = &spec->private_imux[0];
-	if (spec->input_mux == imux)
-		return true;
-	spec->imux_pins[0] = spec->ext_mic_pin;
-	spec->imux_pins[1] = spec->int_mic_pin;
-	spec->imux_pins[2] = spec->dock_mic_pin;
-	for (i = 0; i < 3; i++) {
-		strcpy(imux->items[i].label, texts[i]);
-		if (spec->imux_pins[i]) {
-			hda_nid_t pin = spec->imux_pins[i];
-			int c;
-			for (c = 0; c < spec->num_adc_nids; c++) {
-				hda_nid_t cap = get_capsrc(spec, c);
-				int idx = get_connection_index(codec, cap, pin);
-				if (idx >= 0) {
-					imux->items[i].index = idx;
-					break;
-				}
-			}
-			imux->num_items = i + 1;
-		}
-	}
-	spec->num_mux_defs = 1;
-	spec->input_mux = imux;
-	return true;
-}
-
 /* check whether all auto-mic pins are valid; setup indices if OK */
 static bool alc_auto_mic_check_imux(struct hda_codec *codec)
 {
@@ -1441,6 +1442,7 @@ enum {
 	ALC_FIXUP_ACT_PRE_PROBE,
 	ALC_FIXUP_ACT_PROBE,
 	ALC_FIXUP_ACT_INIT,
+	ALC_FIXUP_ACT_BUILD,
 };
 
 static void alc_apply_fixup(struct hda_codec *codec, int action)
@@ -1520,6 +1522,13 @@ static void alc_pick_fixup(struct hda_codec *codec,
 	int id = -1;
 	const char *name = NULL;
 
+	/* when model=nofixup is given, don't pick up any fixups */
+	if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
+		spec->fixup_list = NULL;
+		spec->fixup_id = -1;
+		return;
+	}
+
 	if (codec->modelname && models) {
 		while (models->name) {
 			if (!strcmp(codec->modelname, models->name)) {
@@ -1847,36 +1856,10 @@ DEFINE_CAPMIX_NOSRC(3);
 /*
  * slave controls for virtual master
  */
-static const char * const alc_slave_vols[] = {
-	"Front Playback Volume",
-	"Surround Playback Volume",
-	"Center Playback Volume",
-	"LFE Playback Volume",
-	"Side Playback Volume",
-	"Headphone Playback Volume",
-	"Speaker Playback Volume",
-	"Mono Playback Volume",
-	"Line Out Playback Volume",
-	"CLFE Playback Volume",
-	"Bass Speaker Playback Volume",
-	"PCM Playback Volume",
-	NULL,
-};
-
-static const char * const alc_slave_sws[] = {
-	"Front Playback Switch",
-	"Surround Playback Switch",
-	"Center Playback Switch",
-	"LFE Playback Switch",
-	"Side Playback Switch",
-	"Headphone Playback Switch",
-	"Speaker Playback Switch",
-	"Mono Playback Switch",
-	"IEC958 Playback Switch",
-	"Line Out Playback Switch",
-	"CLFE Playback Switch",
-	"Bass Speaker Playback Switch",
-	"PCM Playback Switch",
+static const char * const alc_slave_pfxs[] = {
+	"Front", "Surround", "Center", "LFE", "Side",
+	"Headphone", "Speaker", "Mono", "Line Out",
+	"CLFE", "Bass Speaker", "PCM",
 	NULL,
 };
 
@@ -1967,14 +1950,17 @@ static int __alc_build_controls(struct hda_codec *codec)
 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
 					HDA_OUTPUT, vmaster_tlv);
 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  vmaster_tlv, alc_slave_vols);
+					  vmaster_tlv, alc_slave_pfxs,
+					  "Playback Volume");
 		if (err < 0)
 			return err;
 	}
 	if (!spec->no_analog &&
 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
-		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
-					  NULL, alc_slave_sws);
+		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+					    NULL, alc_slave_pfxs,
+					    "Playback Switch",
+					    true, &spec->vmaster_mute.sw_kctl);
 		if (err < 0)
 			return err;
 	}
@@ -2059,7 +2045,11 @@ static int alc_build_controls(struct hda_codec *codec)
 	int err = __alc_build_controls(codec);
 	if (err < 0)
 		return err;
-	return snd_hda_jack_add_kctls(codec, &spec->autocfg);
+	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD);
+	return 0;
 }
 
 
@@ -2068,15 +2058,15 @@ static int alc_build_controls(struct hda_codec *codec)
  */
 
 static void alc_init_special_input_src(struct hda_codec *codec);
-static int alc269_fill_coef(struct hda_codec *codec);
+static void alc_auto_init_std(struct hda_codec *codec);
 
 static int alc_init(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	unsigned int i;
 
-	if (codec->vendor_id == 0x10ec0269)
-		alc269_fill_coef(codec);
+	if (spec->init_hook)
+		spec->init_hook(codec);
 
 	alc_fix_pll(codec);
 	alc_auto_init_amp(codec, spec->init_amp);
@@ -2084,9 +2074,7 @@ static int alc_init(struct hda_codec *codec)
 	for (i = 0; i < spec->num_init_verbs; i++)
 		snd_hda_sequence_write(codec, spec->init_verbs[i]);
 	alc_init_special_input_src(codec);
-
-	if (spec->init_hook)
-		spec->init_hook(codec);
+	alc_auto_init_std(codec);
 
 	alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
 
@@ -2675,6 +2663,25 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
 	return channel_name[ch];
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+/* add the powersave loopback-list entry */
+static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx)
+{
+	struct hda_amp_list *list;
+
+	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
+		return;
+	list = spec->loopback_list + spec->num_loopbacks;
+	list->nid = mix;
+	list->dir = HDA_INPUT;
+	list->idx = idx;
+	spec->num_loopbacks++;
+	spec->loopback.amplist = spec->loopback_list;
+}
+#else
+#define add_loopback_list(spec, mix, idx) /* NOP */
+#endif
+
 /* create input playback/capture controls for the given pin */
 static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
 			    const char *ctlname, int ctlidx,
@@ -2690,6 +2697,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
 			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
 	if (err < 0)
 		return err;
+	add_loopback_list(spec, mix_nid, idx);
 	return 0;
 }
 
@@ -2954,10 +2962,27 @@ static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
 	return 0;
 }
 
+static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+	if (found_in_nid_list(nid, spec->multiout.dac_nids,
+			      ARRAY_SIZE(spec->private_dac_nids)) ||
+	    found_in_nid_list(nid, spec->multiout.hp_out_nid,
+			      ARRAY_SIZE(spec->multiout.hp_out_nid)) ||
+	    found_in_nid_list(nid, spec->multiout.extra_out_nid,
+			      ARRAY_SIZE(spec->multiout.extra_out_nid)))
+		return true;
+	for (i = 0; i < spec->multi_ios; i++) {
+		if (spec->multi_io[i].dac == nid)
+			return true;
+	}
+	return false;
+}
+
 /* look for an empty DAC slot */
 static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
 {
-	struct alc_spec *spec = codec->spec;
 	hda_nid_t srcs[5];
 	int i, num;
 
@@ -2967,16 +2992,8 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
 		hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
 		if (!nid)
 			continue;
-		if (found_in_nid_list(nid, spec->multiout.dac_nids,
-				      ARRAY_SIZE(spec->private_dac_nids)))
-			continue;
-		if (found_in_nid_list(nid, spec->multiout.hp_out_nid,
-				      ARRAY_SIZE(spec->multiout.hp_out_nid)))
-		    continue;
-		if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
-				      ARRAY_SIZE(spec->multiout.extra_out_nid)))
-		    continue;
-		return nid;
+		if (!alc_is_dac_already_used(codec, nid))
+			return nid;
 	}
 	return 0;
 }
@@ -2988,6 +3005,8 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
 	hda_nid_t srcs[5];
 	int i, num;
 
+	if (!pin || !dac)
+		return false;
 	pin = alc_go_down_to_selector(codec, pin);
 	num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
 	for (i = 0; i < num; i++) {
@@ -3000,83 +3019,260 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
 
 static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
 {
+	struct alc_spec *spec = codec->spec;
 	hda_nid_t sel = alc_go_down_to_selector(codec, pin);
-	if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
+	hda_nid_t nid, nid_found, srcs[5];
+	int i, num = snd_hda_get_connections(codec, sel, srcs,
+					  ARRAY_SIZE(srcs));
+	if (num == 1)
 		return alc_auto_look_for_dac(codec, pin);
-	return 0;
+	nid_found = 0;
+	for (i = 0; i < num; i++) {
+		if (srcs[i] == spec->mixer_nid)
+			continue;
+		nid = alc_auto_mix_to_dac(codec, srcs[i]);
+		if (nid && !alc_is_dac_already_used(codec, nid)) {
+			if (nid_found)
+				return 0;
+			nid_found = nid;
+		}
+	}
+	return nid_found;
 }
 
-/* return 0 if no possible DAC is found, 1 if one or more found */
-static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
-				    const hda_nid_t *pins, hda_nid_t *dacs)
+/* mark up volume and mute control NIDs: used during badness parsing and
+ * at creating actual controls
+ */
+static inline unsigned int get_ctl_pos(unsigned int data)
 {
-	int i;
+	hda_nid_t nid = get_amp_nid_(data);
+	unsigned int dir;
+	if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
+		return 0;
+	dir = get_amp_direction_(data);
+	return (nid << 1) | dir;
+}
 
-	if (num_outs && !dacs[0]) {
-		dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
-		if (!dacs[0])
-			return 0;
-	}
+#define is_ctl_used(bits, data) \
+	test_bit(get_ctl_pos(data), bits)
+#define mark_ctl_usage(bits, data) \
+	set_bit(get_ctl_pos(data), bits)
 
-	for (i = 1; i < num_outs; i++)
-		dacs[i] = get_dac_if_single(codec, pins[i]);
-	for (i = 1; i < num_outs; i++) {
+static void clear_vol_marks(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls));
+	memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls));
+}
+
+/* badness definition */
+enum {
+	/* No primary DAC is found for the main output */
+	BAD_NO_PRIMARY_DAC = 0x10000,
+	/* No DAC is found for the extra output */
+	BAD_NO_DAC = 0x4000,
+	/* No possible multi-ios */
+	BAD_MULTI_IO = 0x103,
+	/* No individual DAC for extra output */
+	BAD_NO_EXTRA_DAC = 0x102,
+	/* No individual DAC for extra surrounds */
+	BAD_NO_EXTRA_SURR_DAC = 0x101,
+	/* Primary DAC shared with main surrounds */
+	BAD_SHARED_SURROUND = 0x100,
+	/* Primary DAC shared with main CLFE */
+	BAD_SHARED_CLFE = 0x10,
+	/* Primary DAC shared with extra surrounds */
+	BAD_SHARED_EXTRA_SURROUND = 0x10,
+	/* Volume widget is shared */
+	BAD_SHARED_VOL = 0x10,
+};
+
+static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
+					   hda_nid_t pin, hda_nid_t dac);
+static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
+					  hda_nid_t pin, hda_nid_t dac);
+
+static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
+				   hda_nid_t dac)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t nid;
+	unsigned int val;
+	int badness = 0;
+
+	nid = alc_look_for_out_vol_nid(codec, pin, dac);
+	if (nid) {
+		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+		if (is_ctl_used(spec->vol_ctls, nid))
+			badness += BAD_SHARED_VOL;
+		else
+			mark_ctl_usage(spec->vol_ctls, val);
+	} else
+		badness += BAD_SHARED_VOL;
+	nid = alc_look_for_out_mute_nid(codec, pin, dac);
+	if (nid) {
+		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
+		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT)
+			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+		else
+			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
+		if (is_ctl_used(spec->sw_ctls, val))
+			badness += BAD_SHARED_VOL;
+		else
+			mark_ctl_usage(spec->sw_ctls, val);
+	} else
+		badness += BAD_SHARED_VOL;
+	return badness;
+}
+
+struct badness_table {
+	int no_primary_dac;	/* no primary DAC */
+	int no_dac;		/* no secondary DACs */
+	int shared_primary;	/* primary DAC is shared with main output */
+	int shared_surr;	/* secondary DAC shared with main or primary */
+	int shared_clfe;	/* third DAC shared with main or primary */
+	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
+};
+
+static struct badness_table main_out_badness = {
+	.no_primary_dac = BAD_NO_PRIMARY_DAC,
+	.no_dac = BAD_NO_DAC,
+	.shared_primary = BAD_NO_PRIMARY_DAC,
+	.shared_surr = BAD_SHARED_SURROUND,
+	.shared_clfe = BAD_SHARED_CLFE,
+	.shared_surr_main = BAD_SHARED_SURROUND,
+};
+
+static struct badness_table extra_out_badness = {
+	.no_primary_dac = BAD_NO_DAC,
+	.no_dac = BAD_NO_DAC,
+	.shared_primary = BAD_NO_EXTRA_DAC,
+	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
+	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
+	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
+};
+
+/* try to assign DACs to pins and return the resultant badness */
+static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs,
+			      const hda_nid_t *pins, hda_nid_t *dacs,
+			      const struct badness_table *bad)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i, j;
+	int badness = 0;
+	hda_nid_t dac;
+
+	if (!num_outs)
+		return 0;
+
+	for (i = 0; i < num_outs; i++) {
+		hda_nid_t pin = pins[i];
 		if (!dacs[i])
-			dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
+			dacs[i] = alc_auto_look_for_dac(codec, pin);
+		if (!dacs[i] && !i) {
+			for (j = 1; j < num_outs; j++) {
+				if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) {
+					dacs[0] = dacs[j];
+					dacs[j] = 0;
+					break;
+				}
+			}
+		}
+		dac = dacs[i];
+		if (!dac) {
+			if (alc_auto_is_dac_reachable(codec, pin, dacs[0]))
+				dac = dacs[0];
+			else if (cfg->line_outs > i &&
+				 alc_auto_is_dac_reachable(codec, pin,
+					spec->private_dac_nids[i]))
+				dac = spec->private_dac_nids[i];
+			if (dac) {
+				if (!i)
+					badness += bad->shared_primary;
+				else if (i == 1)
+					badness += bad->shared_surr;
+				else
+					badness += bad->shared_clfe;
+			} else if (alc_auto_is_dac_reachable(codec, pin,
+					spec->private_dac_nids[0])) {
+				dac = spec->private_dac_nids[0];
+				badness += bad->shared_surr_main;
+			} else if (!i)
+				badness += bad->no_primary_dac;
+			else
+				badness += bad->no_dac;
+		}
+		if (dac)
+			badness += eval_shared_vol_badness(codec, pin, dac);
 	}
-	return 1;
+
+	return badness;
 }
 
 static int alc_auto_fill_multi_ios(struct hda_codec *codec,
-				   unsigned int location, int offset);
-static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
-					  hda_nid_t pin, hda_nid_t dac);
+				   hda_nid_t reference_pin,
+				   bool hardwired, int offset);
+
+static bool alc_map_singles(struct hda_codec *codec, int outs,
+			    const hda_nid_t *pins, hda_nid_t *dacs)
+{
+	int i;
+	bool found = false;
+	for (i = 0; i < outs; i++) {
+		if (dacs[i])
+			continue;
+		dacs[i] = get_dac_if_single(codec, pins[i]);
+		if (dacs[i])
+			found = true;
+	}
+	return found;
+}
 
 /* fill in the dac_nids table from the parsed pin configuration */
-static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+static int fill_and_eval_dacs(struct hda_codec *codec,
+			      bool fill_hardwired,
+			      bool fill_mio_first)
 {
 	struct alc_spec *spec = codec->spec;
 	struct auto_pin_cfg *cfg = &spec->autocfg;
-	unsigned int location, defcfg;
-	int num_pins;
-	bool redone = false;
-	int i;
+	int i, err, badness;
 
- again:
 	/* set num_dacs once to full for alc_auto_look_for_dac() */
 	spec->multiout.num_dacs = cfg->line_outs;
-	spec->multiout.hp_out_nid[0] = 0;
-	spec->multiout.extra_out_nid[0] = 0;
-	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
 	spec->multiout.dac_nids = spec->private_dac_nids;
+	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
+	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
+	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
 	spec->multi_ios = 0;
+	clear_vol_marks(codec);
+	badness = 0;
 
 	/* fill hard-wired DACs first */
-	if (!redone) {
-		for (i = 0; i < cfg->line_outs; i++)
-			spec->private_dac_nids[i] =
-				get_dac_if_single(codec, cfg->line_out_pins[i]);
-		if (cfg->hp_outs)
-			spec->multiout.hp_out_nid[0] =
-				get_dac_if_single(codec, cfg->hp_pins[0]);
-		if (cfg->speaker_outs)
-			spec->multiout.extra_out_nid[0] =
-				get_dac_if_single(codec, cfg->speaker_pins[0]);
+	if (fill_hardwired) {
+		bool mapped;
+		do {
+			mapped = alc_map_singles(codec, cfg->line_outs,
+						 cfg->line_out_pins,
+						 spec->private_dac_nids);
+			mapped |= alc_map_singles(codec, cfg->hp_outs,
+						  cfg->hp_pins,
+						  spec->multiout.hp_out_nid);
+			mapped |= alc_map_singles(codec, cfg->speaker_outs,
+						  cfg->speaker_pins,
+						  spec->multiout.extra_out_nid);
+			if (fill_mio_first && cfg->line_outs == 1 &&
+			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+				err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], true, 0);
+				if (!err)
+					mapped = true;
+			}
+		} while (mapped);
 	}
 
-	for (i = 0; i < cfg->line_outs; i++) {
-		hda_nid_t pin = cfg->line_out_pins[i];
-		if (spec->private_dac_nids[i])
-			continue;
-		spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
-		if (!spec->private_dac_nids[i] && !redone) {
-			/* if we can't find primary DACs, re-probe without
-			 * checking the hard-wired DACs
-			 */
-			redone = true;
-			goto again;
-		}
-	}
+	badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins,
+				      spec->private_dac_nids,
+				      &main_out_badness);
 
 	/* re-count num_dacs and squash invalid entries */
 	spec->multiout.num_dacs = 0;
@@ -3091,30 +3287,144 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
 		}
 	}
 
-	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+	if (fill_mio_first &&
+	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
 		/* try to fill multi-io first */
-		defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
-		location = get_defcfg_location(defcfg);
-
-		num_pins = alc_auto_fill_multi_ios(codec, location, 0);
-		if (num_pins > 0) {
-			spec->multi_ios = num_pins;
-			spec->ext_channel_count = 2;
-			spec->multiout.num_dacs = num_pins + 1;
-		}
+		err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
+		if (err < 0)
+			return err;
+		/* we don't count badness at this stage yet */
 	}
 
-	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
-		alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins,
-				 spec->multiout.hp_out_nid);
+	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
+		err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins,
+					 spec->multiout.hp_out_nid,
+					 &extra_out_badness);
+		if (err < 0)
+			return err;
+		badness += err;
+	}
 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
-		int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
-					cfg->speaker_pins,
-					spec->multiout.extra_out_nid);
-		/* if no speaker volume is assigned, try again as the primary
-		 * output
-		 */
-		if (!err && cfg->speaker_outs > 0 &&
+		err = alc_auto_fill_dacs(codec, cfg->speaker_outs,
+					 cfg->speaker_pins,
+					 spec->multiout.extra_out_nid,
+					 &extra_out_badness);
+		if (err < 0)
+			return err;
+		badness += err;
+	}
+	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+		err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
+		if (err < 0)
+			return err;
+		badness += err;
+	}
+	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
+		/* try multi-ios with HP + inputs */
+		int offset = 0;
+		if (cfg->line_outs >= 3)
+			offset = 1;
+		err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false,
+					      offset);
+		if (err < 0)
+			return err;
+		badness += err;
+	}
+
+	if (spec->multi_ios == 2) {
+		for (i = 0; i < 2; i++)
+			spec->private_dac_nids[spec->multiout.num_dacs++] =
+				spec->multi_io[i].dac;
+		spec->ext_channel_count = 2;
+	} else if (spec->multi_ios) {
+		spec->multi_ios = 0;
+		badness += BAD_MULTI_IO;
+	}
+
+	return badness;
+}
+
+#define DEBUG_BADNESS
+
+#ifdef DEBUG_BADNESS
+#define debug_badness	snd_printdd
+#else
+#define debug_badness(...)
+#endif
+
+static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg)
+{
+	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+		      cfg->line_out_pins[0], cfg->line_out_pins[1],
+		      cfg->line_out_pins[2], cfg->line_out_pins[2],
+		      spec->multiout.dac_nids[0],
+		      spec->multiout.dac_nids[1],
+		      spec->multiout.dac_nids[2],
+		      spec->multiout.dac_nids[3]);
+	if (spec->multi_ios > 0)
+		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
+			      spec->multi_ios,
+			      spec->multi_io[0].pin, spec->multi_io[1].pin,
+			      spec->multi_io[0].dac, spec->multi_io[1].dac);
+	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+		      cfg->hp_pins[0], cfg->hp_pins[1],
+		      cfg->hp_pins[2], cfg->hp_pins[2],
+		      spec->multiout.hp_out_nid[0],
+		      spec->multiout.hp_out_nid[1],
+		      spec->multiout.hp_out_nid[2],
+		      spec->multiout.hp_out_nid[3]);
+	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+		      cfg->speaker_pins[0], cfg->speaker_pins[1],
+		      cfg->speaker_pins[2], cfg->speaker_pins[3],
+		      spec->multiout.extra_out_nid[0],
+		      spec->multiout.extra_out_nid[1],
+		      spec->multiout.extra_out_nid[2],
+		      spec->multiout.extra_out_nid[3]);
+}
+
+static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	struct auto_pin_cfg *best_cfg;
+	int best_badness = INT_MAX;
+	int badness;
+	bool fill_hardwired = true, fill_mio_first = true;
+	bool best_wired = true, best_mio = true;
+	bool hp_spk_swapped = false;
+
+	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
+	if (!best_cfg)
+		return -ENOMEM;
+	*best_cfg = *cfg;
+
+	for (;;) {
+		badness = fill_and_eval_dacs(codec, fill_hardwired,
+					     fill_mio_first);
+		if (badness < 0)
+			return badness;
+		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
+			      cfg->line_out_type, fill_hardwired, fill_mio_first,
+			      badness);
+		debug_show_configs(spec, cfg);
+		if (badness < best_badness) {
+			best_badness = badness;
+			*best_cfg = *cfg;
+			best_wired = fill_hardwired;
+			best_mio = fill_mio_first;
+		}
+		if (!badness)
+			break;
+		fill_mio_first = !fill_mio_first;
+		if (!fill_mio_first)
+			continue;
+		fill_hardwired = !fill_hardwired;
+		if (!fill_hardwired)
+			continue;
+		if (hp_spk_swapped)
+			break;
+		hp_spk_swapped = true;
+		if (cfg->speaker_outs > 0 &&
 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
 			cfg->hp_outs = cfg->line_outs;
 			memcpy(cfg->hp_pins, cfg->line_out_pins,
@@ -3125,48 +3435,45 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
 			cfg->speaker_outs = 0;
 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
-			redone = false;
-			goto again;
-		}
+			fill_hardwired = true;
+			continue;
+		} 
+		if (cfg->hp_outs > 0 &&
+		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
+			cfg->speaker_outs = cfg->line_outs;
+			memcpy(cfg->speaker_pins, cfg->line_out_pins,
+			       sizeof(cfg->speaker_pins));
+			cfg->line_outs = cfg->hp_outs;
+			memcpy(cfg->line_out_pins, cfg->hp_pins,
+			       sizeof(cfg->hp_pins));
+			cfg->hp_outs = 0;
+			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+			cfg->line_out_type = AUTO_PIN_HP_OUT;
+			fill_hardwired = true;
+			continue;
+		} 
+		break;
 	}
 
-	if (!spec->multi_ios &&
-	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
-	    cfg->hp_outs) {
-		/* try multi-ios with HP + inputs */
-		defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]);
-		location = get_defcfg_location(defcfg);
-
-		num_pins = alc_auto_fill_multi_ios(codec, location, 1);
-		if (num_pins > 0) {
-			spec->multi_ios = num_pins;
-			spec->ext_channel_count = 2;
-			spec->multiout.num_dacs = num_pins + 1;
-		}
+	if (badness) {
+		*cfg = *best_cfg;
+		fill_and_eval_dacs(codec, best_wired, best_mio);
 	}
+	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
+		      cfg->line_out_type, best_wired, best_mio);
+	debug_show_configs(spec, cfg);
 
 	if (cfg->line_out_pins[0])
 		spec->vmaster_nid =
 			alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0],
 						 spec->multiout.dac_nids[0]);
-	return 0;
-}
 
-static inline unsigned int get_ctl_pos(unsigned int data)
-{
-	hda_nid_t nid = get_amp_nid_(data);
-	unsigned int dir;
-	if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
-		return 0;
-	dir = get_amp_direction_(data);
-	return (nid << 1) | dir;
+	/* clear the bitmap flags for creating controls */
+	clear_vol_marks(codec);
+	kfree(best_cfg);
+	return 0;
 }
 
-#define is_ctl_used(bits, data) \
-	test_bit(get_ctl_pos(data), bits)
-#define mark_ctl_usage(bits, data) \
-	set_bit(get_ctl_pos(data), bits)
-
 static int alc_auto_add_vol_ctl(struct hda_codec *codec,
 			      const char *pfx, int cidx,
 			      hda_nid_t nid, unsigned int chs)
@@ -3278,14 +3585,17 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
 		dac = spec->multiout.dac_nids[i];
 		if (!dac)
 			continue;
-		if (i >= cfg->line_outs)
+		if (i >= cfg->line_outs) {
 			pin = spec->multi_io[i - 1].pin;
-		else
+			index = 0;
+			name = channel_name[i];
+		} else {
 			pin = cfg->line_out_pins[i];
+			name = alc_get_line_out_pfx(spec, i, true, &index);
+		}
 
 		sw = alc_look_for_out_mute_nid(codec, pin, dac);
 		vol = alc_look_for_out_vol_nid(codec, pin, dac);
-		name = alc_get_line_out_pfx(spec, i, true, &index);
 		if (!name || !strcmp(name, "CLFE")) {
 			/* Center/LFE */
 			err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
@@ -3382,41 +3692,31 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
 		return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0);
 	}
 
-	if (dacs[num_pins - 1]) {
-		/* OK, we have a multi-output system with individual volumes */
-		for (i = 0; i < num_pins; i++) {
-			if (num_pins >= 3) {
-				snprintf(name, sizeof(name), "%s %s",
-					 pfx, channel_name[i]);
-				err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
-								name, 0);
-			} else {
-				err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
-								pfx, i);
-			}
-			if (err < 0)
-				return err;
-		}
-		return 0;
-	}
-
-	/* Let's create a bind-controls */
-	ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw);
-	if (!ctl)
-		return -ENOMEM;
-	n = 0;
 	for (i = 0; i < num_pins; i++) {
-		if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP)
-			ctl->values[n++] =
-				HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT);
-	}
-	if (n) {
-		snprintf(name, sizeof(name), "%s Playback Switch", pfx);
-		err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl);
+		hda_nid_t dac;
+		if (dacs[num_pins - 1])
+			dac = dacs[i]; /* with individual volumes */
+		else
+			dac = 0;
+		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) {
+			err = alc_auto_create_extra_out(codec, pins[i], dac,
+							"Bass Speaker", 0);
+		} else if (num_pins >= 3) {
+			snprintf(name, sizeof(name), "%s %s",
+				 pfx, channel_name[i]);
+			err = alc_auto_create_extra_out(codec, pins[i], dac,
+							name, 0);
+		} else {
+			err = alc_auto_create_extra_out(codec, pins[i], dac,
+							pfx, i);
+		}
 		if (err < 0)
 			return err;
 	}
+	if (dacs[num_pins - 1])
+		return 0;
 
+	/* Let's create a bind-controls for volumes */
 	ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
 	if (!ctl)
 		return -ENOMEM;
@@ -3552,58 +3852,111 @@ static void alc_auto_init_extra_out(struct hda_codec *codec)
 	}
 }
 
+/* check whether the given pin can be a multi-io pin */
+static bool can_be_multiio_pin(struct hda_codec *codec,
+			       unsigned int location, hda_nid_t nid)
+{
+	unsigned int defcfg, caps;
+
+	defcfg = snd_hda_codec_get_pincfg(codec, nid);
+	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+		return false;
+	if (location && get_defcfg_location(defcfg) != location)
+		return false;
+	caps = snd_hda_query_pin_caps(codec, nid);
+	if (!(caps & AC_PINCAP_OUT))
+		return false;
+	return true;
+}
+
 /*
  * multi-io helper
+ *
+ * When hardwired is set, try to fill ony hardwired pins, and returns
+ * zero if any pins are filled, non-zero if nothing found.
+ * When hardwired is off, try to fill possible input pins, and returns
+ * the badness value.
  */
 static int alc_auto_fill_multi_ios(struct hda_codec *codec,
-				   unsigned int location,
-				   int offset)
+				   hda_nid_t reference_pin,
+				   bool hardwired, int offset)
 {
 	struct alc_spec *spec = codec->spec;
 	struct auto_pin_cfg *cfg = &spec->autocfg;
-	hda_nid_t prime_dac = spec->private_dac_nids[0];
-	int type, i, dacs, num_pins = 0;
+	int type, i, j, dacs, num_pins, old_pins;
+	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
+	unsigned int location = get_defcfg_location(defcfg);
+	int badness = 0;
 
-	dacs = spec->multiout.num_dacs;
+	old_pins = spec->multi_ios;
+	if (old_pins >= 2)
+		goto end_fill;
+
+	num_pins = 0;
 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
 		for (i = 0; i < cfg->num_inputs; i++) {
-			hda_nid_t nid = cfg->inputs[i].pin;
-			hda_nid_t dac = 0;
-			unsigned int defcfg, caps;
 			if (cfg->inputs[i].type != type)
 				continue;
-			defcfg = snd_hda_codec_get_pincfg(codec, nid);
-			if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+			if (can_be_multiio_pin(codec, location,
+					       cfg->inputs[i].pin))
+				num_pins++;
+		}
+	}
+	if (num_pins < 2)
+		goto end_fill;
+
+	dacs = spec->multiout.num_dacs;
+	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
+		for (i = 0; i < cfg->num_inputs; i++) {
+			hda_nid_t nid = cfg->inputs[i].pin;
+			hda_nid_t dac = 0;
+
+			if (cfg->inputs[i].type != type)
 				continue;
-			if (location && get_defcfg_location(defcfg) != location)
+			if (!can_be_multiio_pin(codec, location, nid))
 				continue;
-			caps = snd_hda_query_pin_caps(codec, nid);
-			if (!(caps & AC_PINCAP_OUT))
+			for (j = 0; j < spec->multi_ios; j++) {
+				if (nid == spec->multi_io[j].pin)
+					break;
+			}
+			if (j < spec->multi_ios)
 				continue;
-			if (offset && offset + num_pins < dacs) {
-				dac = spec->private_dac_nids[offset + num_pins];
+
+			if (offset && offset + spec->multi_ios < dacs) {
+				dac = spec->private_dac_nids[offset + spec->multi_ios];
 				if (!alc_auto_is_dac_reachable(codec, nid, dac))
 					dac = 0;
 			}
-			if (!dac)
+			if (hardwired)
+				dac = get_dac_if_single(codec, nid);
+			else if (!dac)
 				dac = alc_auto_look_for_dac(codec, nid);
-			if (!dac)
+			if (!dac) {
+				badness++;
 				continue;
-			spec->multi_io[num_pins].pin = nid;
-			spec->multi_io[num_pins].dac = dac;
-			num_pins++;
-			spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+			}
+			spec->multi_io[spec->multi_ios].pin = nid;
+			spec->multi_io[spec->multi_ios].dac = dac;
+			spec->multi_ios++;
+			if (spec->multi_ios >= 2)
+				break;
 		}
 	}
-	spec->multiout.num_dacs = dacs;
-	if (num_pins < 2) {
-		/* clear up again */
-		memset(spec->private_dac_nids + dacs, 0,
-		       sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs));
-		spec->private_dac_nids[0] = prime_dac;
-		return 0;
+ end_fill:
+	if (badness)
+		badness = BAD_MULTI_IO;
+	if (old_pins == spec->multi_ios) {
+		if (hardwired)
+			return 1; /* nothing found */
+		else
+			return badness; /* no badness if nothing found */
+	}
+	if (!hardwired && spec->multi_ios < 2) {
+		spec->multi_ios = old_pins;
+		return badness;
 	}
-	return num_pins;
+
+	return 0;
 }
 
 static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
@@ -3958,6 +4311,7 @@ static const struct snd_pci_quirk beep_white_list[] = {
 	SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
 	SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
 	SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
+	SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
 	SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
 	{}
 };
@@ -4057,6 +4411,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
 	if (spec->kctls.list)
 		add_mixer(spec, spec->kctls.list);
 
+	if (!spec->no_analog && !spec->cap_mixer)
+		set_capture_mixer(codec);
+
 	return 1;
 }
 
@@ -4067,26 +4424,47 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
 	return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc880_loopbacks[] = {
-	{ 0x0b, HDA_INPUT, 0 },
-	{ 0x0b, HDA_INPUT, 1 },
-	{ 0x0b, HDA_INPUT, 2 },
-	{ 0x0b, HDA_INPUT, 3 },
-	{ 0x0b, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 /*
  * ALC880 fix-ups
  */
 enum {
+	ALC880_FIXUP_GPIO1,
 	ALC880_FIXUP_GPIO2,
 	ALC880_FIXUP_MEDION_RIM,
+	ALC880_FIXUP_LG,
+	ALC880_FIXUP_W810,
+	ALC880_FIXUP_EAPD_COEF,
+	ALC880_FIXUP_TCL_S700,
+	ALC880_FIXUP_VOL_KNOB,
+	ALC880_FIXUP_FUJITSU,
+	ALC880_FIXUP_F1734,
+	ALC880_FIXUP_UNIWILL,
+	ALC880_FIXUP_UNIWILL_DIG,
+	ALC880_FIXUP_Z71V,
+	ALC880_FIXUP_3ST_BASE,
+	ALC880_FIXUP_3ST,
+	ALC880_FIXUP_3ST_DIG,
+	ALC880_FIXUP_5ST_BASE,
+	ALC880_FIXUP_5ST,
+	ALC880_FIXUP_5ST_DIG,
+	ALC880_FIXUP_6ST_BASE,
+	ALC880_FIXUP_6ST,
+	ALC880_FIXUP_6ST_DIG,
 };
 
+/* enable the volume-knob widget support on NID 0x21 */
+static void alc880_fixup_vol_knob(struct hda_codec *codec,
+				  const struct alc_fixup *fix, int action)
+{
+	if (action == ALC_FIXUP_ACT_PROBE)
+		snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT);
+}
+
 static const struct alc_fixup alc880_fixups[] = {
+	[ALC880_FIXUP_GPIO1] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = alc_gpio1_init_verbs,
+	},
 	[ALC880_FIXUP_GPIO2] = {
 		.type = ALC_FIXUP_VERBS,
 		.v.verbs = alc_gpio2_init_verbs,
@@ -4101,40 +4479,323 @@ static const struct alc_fixup alc880_fixups[] = {
 		.chained = true,
 		.chain_id = ALC880_FIXUP_GPIO2,
 	},
+	[ALC880_FIXUP_LG] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			/* disable bogus unused pins */
+			{ 0x16, 0x411111f0 },
+			{ 0x18, 0x411111f0 },
+			{ 0x1a, 0x411111f0 },
+			{ }
+		}
+	},
+	[ALC880_FIXUP_W810] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			/* disable bogus unused pins */
+			{ 0x17, 0x411111f0 },
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_GPIO2,
+	},
+	[ALC880_FIXUP_EAPD_COEF] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			/* change to EAPD mode */
+			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+			{ 0x20, AC_VERB_SET_PROC_COEF,  0x3060 },
+			{}
+		},
+	},
+	[ALC880_FIXUP_TCL_S700] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			/* change to EAPD mode */
+			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+			{ 0x20, AC_VERB_SET_PROC_COEF,  0x3070 },
+			{}
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_GPIO2,
+	},
+	[ALC880_FIXUP_VOL_KNOB] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc880_fixup_vol_knob,
+	},
+	[ALC880_FIXUP_FUJITSU] = {
+		/* override all pins as BIOS on old Amilo is broken */
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x14, 0x0121411f }, /* HP */
+			{ 0x15, 0x99030120 }, /* speaker */
+			{ 0x16, 0x99030130 }, /* bass speaker */
+			{ 0x17, 0x411111f0 }, /* N/A */
+			{ 0x18, 0x411111f0 }, /* N/A */
+			{ 0x19, 0x01a19950 }, /* mic-in */
+			{ 0x1a, 0x411111f0 }, /* N/A */
+			{ 0x1b, 0x411111f0 }, /* N/A */
+			{ 0x1c, 0x411111f0 }, /* N/A */
+			{ 0x1d, 0x411111f0 }, /* N/A */
+			{ 0x1e, 0x01454140 }, /* SPDIF out */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_VOL_KNOB,
+	},
+	[ALC880_FIXUP_F1734] = {
+		/* almost compatible with FUJITSU, but no bass and SPDIF */
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x14, 0x0121411f }, /* HP */
+			{ 0x15, 0x99030120 }, /* speaker */
+			{ 0x16, 0x411111f0 }, /* N/A */
+			{ 0x17, 0x411111f0 }, /* N/A */
+			{ 0x18, 0x411111f0 }, /* N/A */
+			{ 0x19, 0x01a19950 }, /* mic-in */
+			{ 0x1a, 0x411111f0 }, /* N/A */
+			{ 0x1b, 0x411111f0 }, /* N/A */
+			{ 0x1c, 0x411111f0 }, /* N/A */
+			{ 0x1d, 0x411111f0 }, /* N/A */
+			{ 0x1e, 0x411111f0 }, /* N/A */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_VOL_KNOB,
+	},
+	[ALC880_FIXUP_UNIWILL] = {
+		/* need to fix HP and speaker pins to be parsed correctly */
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x14, 0x0121411f }, /* HP */
+			{ 0x15, 0x99030120 }, /* speaker */
+			{ 0x16, 0x99030130 }, /* bass speaker */
+			{ }
+		},
+	},
+	[ALC880_FIXUP_UNIWILL_DIG] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			/* disable bogus unused pins */
+			{ 0x17, 0x411111f0 },
+			{ 0x19, 0x411111f0 },
+			{ 0x1b, 0x411111f0 },
+			{ 0x1f, 0x411111f0 },
+			{ }
+		}
+	},
+	[ALC880_FIXUP_Z71V] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			/* set up the whole pins as BIOS is utterly broken */
+			{ 0x14, 0x99030120 }, /* speaker */
+			{ 0x15, 0x0121411f }, /* HP */
+			{ 0x16, 0x411111f0 }, /* N/A */
+			{ 0x17, 0x411111f0 }, /* N/A */
+			{ 0x18, 0x01a19950 }, /* mic-in */
+			{ 0x19, 0x411111f0 }, /* N/A */
+			{ 0x1a, 0x01813031 }, /* line-in */
+			{ 0x1b, 0x411111f0 }, /* N/A */
+			{ 0x1c, 0x411111f0 }, /* N/A */
+			{ 0x1d, 0x411111f0 }, /* N/A */
+			{ 0x1e, 0x0144111e }, /* SPDIF */
+			{ }
+		}
+	},
+	[ALC880_FIXUP_3ST_BASE] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x14, 0x01014010 }, /* line-out */
+			{ 0x15, 0x411111f0 }, /* N/A */
+			{ 0x16, 0x411111f0 }, /* N/A */
+			{ 0x17, 0x411111f0 }, /* N/A */
+			{ 0x18, 0x01a19c30 }, /* mic-in */
+			{ 0x19, 0x0121411f }, /* HP */
+			{ 0x1a, 0x01813031 }, /* line-in */
+			{ 0x1b, 0x02a19c40 }, /* front-mic */
+			{ 0x1c, 0x411111f0 }, /* N/A */
+			{ 0x1d, 0x411111f0 }, /* N/A */
+			/* 0x1e is filled in below */
+			{ 0x1f, 0x411111f0 }, /* N/A */
+			{ }
+		}
+	},
+	[ALC880_FIXUP_3ST] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x1e, 0x411111f0 }, /* N/A */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_3ST_BASE,
+	},
+	[ALC880_FIXUP_3ST_DIG] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x1e, 0x0144111e }, /* SPDIF */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_3ST_BASE,
+	},
+	[ALC880_FIXUP_5ST_BASE] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x14, 0x01014010 }, /* front */
+			{ 0x15, 0x411111f0 }, /* N/A */
+			{ 0x16, 0x01011411 }, /* CLFE */
+			{ 0x17, 0x01016412 }, /* surr */
+			{ 0x18, 0x01a19c30 }, /* mic-in */
+			{ 0x19, 0x0121411f }, /* HP */
+			{ 0x1a, 0x01813031 }, /* line-in */
+			{ 0x1b, 0x02a19c40 }, /* front-mic */
+			{ 0x1c, 0x411111f0 }, /* N/A */
+			{ 0x1d, 0x411111f0 }, /* N/A */
+			/* 0x1e is filled in below */
+			{ 0x1f, 0x411111f0 }, /* N/A */
+			{ }
+		}
+	},
+	[ALC880_FIXUP_5ST] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x1e, 0x411111f0 }, /* N/A */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_5ST_BASE,
+	},
+	[ALC880_FIXUP_5ST_DIG] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x1e, 0x0144111e }, /* SPDIF */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_5ST_BASE,
+	},
+	[ALC880_FIXUP_6ST_BASE] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x14, 0x01014010 }, /* front */
+			{ 0x15, 0x01016412 }, /* surr */
+			{ 0x16, 0x01011411 }, /* CLFE */
+			{ 0x17, 0x01012414 }, /* side */
+			{ 0x18, 0x01a19c30 }, /* mic-in */
+			{ 0x19, 0x02a19c40 }, /* front-mic */
+			{ 0x1a, 0x01813031 }, /* line-in */
+			{ 0x1b, 0x0121411f }, /* HP */
+			{ 0x1c, 0x411111f0 }, /* N/A */
+			{ 0x1d, 0x411111f0 }, /* N/A */
+			/* 0x1e is filled in below */
+			{ 0x1f, 0x411111f0 }, /* N/A */
+			{ }
+		}
+	},
+	[ALC880_FIXUP_6ST] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x1e, 0x411111f0 }, /* N/A */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_6ST_BASE,
+	},
+	[ALC880_FIXUP_6ST_DIG] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x1e, 0x0144111e }, /* SPDIF */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_6ST_BASE,
+	},
 };
 
 static const struct snd_pci_quirk alc880_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
+	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
+	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
+	SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
+	SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
+	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
+	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
+	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
+	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
+	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
 	SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
+	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734),
+	SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
+	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
+	SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
+	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
+	SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
+	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
+	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
+
+	/* Below is the copied entries from alc880_quirks.c.
+	 * It's not quite sure whether BIOS sets the correct pin-config table
+	 * on these machines, thus they are kept to be compatible with
+	 * the old static quirks.  Once when it's confirmed to work without
+	 * these overrides, it'd be better to remove.
+	 */
+	SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
+	SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
+	SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
+	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
+	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
+	SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
+	SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
+	SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
+	SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+	/* default Intel */
+	SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
+	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
+	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
 	{}
 };
 
+static const struct alc_model_fixup alc880_fixup_models[] = {
+	{.id = ALC880_FIXUP_3ST, .name = "3stack"},
+	{.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
+	{.id = ALC880_FIXUP_5ST, .name = "5stack"},
+	{.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
+	{.id = ALC880_FIXUP_6ST, .name = "6stack"},
+	{.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
+	{}
+};
 
-/*
- * board setups
- */
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#define alc_board_config \
-	snd_hda_check_board_config
-#define alc_board_codec_sid_config \
-	snd_hda_check_board_codec_sid_config
-#include "alc_quirks.c"
-#else
-#define alc_board_config(codec, nums, models, tbl)	-1
-#define alc_board_codec_sid_config(codec, nums, models, tbl)	-1
-#define setup_preset(codec, x)	/* NOP */
-#endif
 
 /*
  * OK, here we have finally the patch for ALC880
  */
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc880_quirks.c"
-#endif
-
 static int patch_alc880(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
-	int board_config;
 	int err;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -4146,47 +4807,14 @@ static int patch_alc880(struct hda_codec *codec)
 	spec->mixer_nid = 0x0b;
 	spec->need_dac_fix = 1;
 
-	board_config = alc_board_config(codec, ALC880_MODEL_LAST,
-					alc880_models, alc880_cfg_tbl);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = ALC_MODEL_AUTO;
-	}
-
-	if (board_config == ALC_MODEL_AUTO) {
-		alc_pick_fixup(codec, NULL, alc880_fixup_tbl, alc880_fixups);
-		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-	}
-
-	if (board_config == ALC_MODEL_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc880_parse_auto_config(codec);
-		if (err < 0)
-			goto error;
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-		else if (!err) {
-			printk(KERN_INFO
-			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using 3-stack mode...\n");
-			board_config = ALC880_3ST;
-		}
-#endif
-	}
-
-	if (board_config != ALC_MODEL_AUTO) {
-		spec->vmaster_nid = 0x0c;
-		setup_preset(codec, &alc880_presets[board_config]);
-	}
-
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
+	alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
+		       alc880_fixups);
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
+	/* automatic parse from the BIOS config */
+	err = alc880_parse_auto_config(codec);
+	if (err < 0)
+		goto error;
 
 	if (!spec->no_analog) {
 		err = snd_hda_attach_beep_device(codec, 0x1);
@@ -4195,17 +4823,9 @@ static int patch_alc880(struct hda_codec *codec)
 		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
 	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC_MODEL_AUTO)
-		spec->init_hook = alc_auto_init_std;
-	else
-		codec->patch_ops.build_controls = __alc_build_controls;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc880_loopbacks;
-#endif
+
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
 	return 0;
 
@@ -4225,49 +4845,115 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
 	return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc260_loopbacks[] = {
-	{ 0x07, HDA_INPUT, 0 },
-	{ 0x07, HDA_INPUT, 1 },
-	{ 0x07, HDA_INPUT, 2 },
-	{ 0x07, HDA_INPUT, 3 },
-	{ 0x07, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 /*
  * Pin config fixes
  */
 enum {
-	PINFIX_HP_DC5750,
+	ALC260_FIXUP_HP_DC5750,
+	ALC260_FIXUP_HP_PIN_0F,
+	ALC260_FIXUP_COEF,
+	ALC260_FIXUP_GPIO1,
+	ALC260_FIXUP_GPIO1_TOGGLE,
+	ALC260_FIXUP_REPLACER,
+	ALC260_FIXUP_HP_B1900,
 };
 
+static void alc260_gpio1_automute(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+			    spec->hp_jack_present);
+}
+
+static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
+				      const struct alc_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	if (action == ALC_FIXUP_ACT_PROBE) {
+		/* although the machine has only one output pin, we need to
+		 * toggle GPIO1 according to the jack state
+		 */
+		spec->automute_hook = alc260_gpio1_automute;
+		spec->detect_hp = 1;
+		spec->automute_speaker = 1;
+		spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
+		snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
+		spec->unsol_event = alc_sku_unsol_event;
+		add_verb(codec->spec, alc_gpio1_init_verbs);
+	}
+}
+
 static const struct alc_fixup alc260_fixups[] = {
-	[PINFIX_HP_DC5750] = {
+	[ALC260_FIXUP_HP_DC5750] = {
 		.type = ALC_FIXUP_PINS,
 		.v.pins = (const struct alc_pincfg[]) {
 			{ 0x11, 0x90130110 }, /* speaker */
 			{ }
 		}
 	},
+	[ALC260_FIXUP_HP_PIN_0F] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x0f, 0x01214000 }, /* HP */
+			{ }
+		}
+	},
+	[ALC260_FIXUP_COEF] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+			{ 0x20, AC_VERB_SET_PROC_COEF,  0x3040 },
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC260_FIXUP_HP_PIN_0F,
+	},
+	[ALC260_FIXUP_GPIO1] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = alc_gpio1_init_verbs,
+	},
+	[ALC260_FIXUP_GPIO1_TOGGLE] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc260_fixup_gpio1_toggle,
+		.chained = true,
+		.chain_id = ALC260_FIXUP_HP_PIN_0F,
+	},
+	[ALC260_FIXUP_REPLACER] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+			{ 0x20, AC_VERB_SET_PROC_COEF,  0x3050 },
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
+	},
+	[ALC260_FIXUP_HP_B1900] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc260_fixup_gpio1_toggle,
+		.chained = true,
+		.chain_id = ALC260_FIXUP_COEF,
+	}
 };
 
 static const struct snd_pci_quirk alc260_fixup_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
+	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
+	SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
+	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
+	SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
+	SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
+	SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
+	SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
+	SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
 	{}
 };
 
 /*
  */
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc260_quirks.c"
-#endif
-
 static int patch_alc260(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
-	int err, board_config;
+	int err;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -4277,47 +4963,13 @@ static int patch_alc260(struct hda_codec *codec)
 
 	spec->mixer_nid = 0x07;
 
-	board_config = alc_board_config(codec, ALC260_MODEL_LAST,
-					alc260_models, alc260_cfg_tbl);
-	if (board_config < 0) {
-		snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-			   codec->chip_name);
-		board_config = ALC_MODEL_AUTO;
-	}
-
-	if (board_config == ALC_MODEL_AUTO) {
-		alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
-		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-	}
-
-	if (board_config == ALC_MODEL_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc260_parse_auto_config(codec);
-		if (err < 0)
-			goto error;
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-		else if (!err) {
-			printk(KERN_INFO
-			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using base mode...\n");
-			board_config = ALC260_BASIC;
-		}
-#endif
-	}
-
-	if (board_config != ALC_MODEL_AUTO) {
-		setup_preset(codec, &alc260_presets[board_config]);
-		spec->vmaster_nid = 0x08;
-	}
-
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
+	alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
+	/* automatic parse from the BIOS config */
+	err = alc260_parse_auto_config(codec);
+	if (err < 0)
+		goto error;
 
 	if (!spec->no_analog) {
 		err = snd_hda_attach_beep_device(codec, 0x1);
@@ -4326,18 +4978,10 @@ static int patch_alc260(struct hda_codec *codec)
 		set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
 	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
 	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC_MODEL_AUTO)
-		spec->init_hook = alc_auto_init_std;
-	else
-		codec->patch_ops.build_controls = __alc_build_controls;
 	spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc260_loopbacks;
-#endif
+
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
 	return 0;
 
@@ -4358,9 +5002,6 @@ static int patch_alc260(struct hda_codec *codec)
  * In addition, an independent DAC for the multi-playback (not used in this
  * driver yet).
  */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc882_loopbacks	alc880_loopbacks
-#endif
 
 /*
  * Pin config fixes
@@ -4377,6 +5018,8 @@ enum {
 	ALC882_FIXUP_EAPD,
 	ALC883_FIXUP_EAPD,
 	ALC883_FIXUP_ACER_EAPD,
+	ALC882_FIXUP_GPIO1,
+	ALC882_FIXUP_GPIO2,
 	ALC882_FIXUP_GPIO3,
 	ALC889_FIXUP_COEF,
 	ALC882_FIXUP_ASUS_W2JC,
@@ -4385,6 +5028,8 @@ enum {
 	ALC882_FIXUP_ASPIRE_8930G_VERBS,
 	ALC885_FIXUP_MACPRO_GPIO,
 	ALC889_FIXUP_DAC_ROUTE,
+	ALC889_FIXUP_MBP_VREF,
+	ALC889_FIXUP_IMAC91_VREF,
 };
 
 static void alc889_fixup_coef(struct hda_codec *codec,
@@ -4463,6 +5108,51 @@ static void alc889_fixup_dac_route(struct hda_codec *codec,
 	}
 }
 
+/* Set VREF on HP pin */
+static void alc889_fixup_mbp_vref(struct hda_codec *codec,
+				  const struct alc_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	static hda_nid_t nids[2] = { 0x14, 0x15 };
+	int i;
+
+	if (action != ALC_FIXUP_ACT_INIT)
+		return;
+	for (i = 0; i < ARRAY_SIZE(nids); i++) {
+		unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
+		if (get_defcfg_device(val) != AC_JACK_HP_OUT)
+			continue;
+		val = snd_hda_codec_read(codec, nids[i], 0,
+					 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+		val |= AC_PINCTL_VREF_80;
+		snd_hda_codec_write(codec, nids[i], 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+		spec->keep_vref_in_automute = 1;
+		break;
+	}
+}
+
+/* Set VREF on speaker pins on imac91 */
+static void alc889_fixup_imac91_vref(struct hda_codec *codec,
+				     const struct alc_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	static hda_nid_t nids[2] = { 0x18, 0x1a };
+	int i;
+
+	if (action != ALC_FIXUP_ACT_INIT)
+		return;
+	for (i = 0; i < ARRAY_SIZE(nids); i++) {
+		unsigned int val;
+		val = snd_hda_codec_read(codec, nids[i], 0,
+					 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+		val |= AC_PINCTL_VREF_50;
+		snd_hda_codec_write(codec, nids[i], 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+	}
+	spec->keep_vref_in_automute = 1;
+}
+
 static const struct alc_fixup alc882_fixups[] = {
 	[ALC882_FIXUP_ABIT_AW9D_MAX] = {
 		.type = ALC_FIXUP_PINS,
@@ -4548,6 +5238,14 @@ static const struct alc_fixup alc882_fixups[] = {
 			{ }
 		}
 	},
+	[ALC882_FIXUP_GPIO1] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = alc_gpio1_init_verbs,
+	},
+	[ALC882_FIXUP_GPIO2] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = alc_gpio2_init_verbs,
+	},
 	[ALC882_FIXUP_GPIO3] = {
 		.type = ALC_FIXUP_VERBS,
 		.v.verbs = alc_gpio3_init_verbs,
@@ -4621,6 +5319,18 @@ static const struct alc_fixup alc882_fixups[] = {
 		.type = ALC_FIXUP_FUNC,
 		.v.func = alc889_fixup_dac_route,
 	},
+	[ALC889_FIXUP_MBP_VREF] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc889_fixup_mbp_vref,
+		.chained = true,
+		.chain_id = ALC882_FIXUP_GPIO1,
+	},
+	[ALC889_FIXUP_IMAC91_VREF] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc889_fixup_imac91_vref,
+		.chained = true,
+		.chain_id = ALC882_FIXUP_GPIO1,
+	},
 };
 
 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -4654,11 +5364,26 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
 
 	/* All Apple entries are in codec SSIDs */
+	SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
+	SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
+	SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
 	SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
 	SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
 	SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
+	SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
+	SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
 	SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
+	SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
+	SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF),
+	SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
+	SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
 	SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
+	SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
+	SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
+	SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
+	SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
+	SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
+	SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
 
 	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
 	SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
@@ -4684,14 +5409,10 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
 
 /*
  */
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc882_quirks.c"
-#endif
-
 static int patch_alc882(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
-	int err, board_config;
+	int err;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -4715,45 +5436,15 @@ static int patch_alc882(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	board_config = alc_board_config(codec, ALC882_MODEL_LAST,
-					alc882_models, NULL);
-	if (board_config < 0)
-		board_config = alc_board_codec_sid_config(codec,
-			ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
-
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = ALC_MODEL_AUTO;
-	}
-
-	if (board_config == ALC_MODEL_AUTO) {
-		alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
-		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-	}
+	alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
 	alc_auto_parse_customize_define(codec);
 
-	if (board_config == ALC_MODEL_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc882_parse_auto_config(codec);
-		if (err < 0)
-			goto error;
-	}
-
-	if (board_config != ALC_MODEL_AUTO) {
-		setup_preset(codec, &alc882_presets[board_config]);
-		spec->vmaster_nid = 0x0c;
-	}
-
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
-
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
+	/* automatic parse from the BIOS config */
+	err = alc882_parse_auto_config(codec);
+	if (err < 0)
+		goto error;
 
 	if (!spec->no_analog && has_cdefine_beep(codec)) {
 		err = snd_hda_attach_beep_device(codec, 0x1);
@@ -4762,18 +5453,9 @@ static int patch_alc882(struct hda_codec *codec)
 		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
 	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC_MODEL_AUTO)
-		spec->init_hook = alc_auto_init_std;
-	else
-		codec->patch_ops.build_controls = __alc_build_controls;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc882_loopbacks;
-#endif
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
 	return 0;
 
@@ -4869,10 +5551,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
 };
 
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc262_loopbacks	alc880_loopbacks
-#endif
-
 /*
  */
 static int patch_alc262(struct hda_codec *codec)
@@ -4912,15 +5590,6 @@ static int patch_alc262(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
-
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
-
 	if (!spec->no_analog && has_cdefine_beep(codec)) {
 		err = snd_hda_attach_beep_device(codec, 0x1);
 		if (err < 0)
@@ -4928,16 +5597,10 @@ static int patch_alc262(struct hda_codec *codec)
 		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
 	codec->patch_ops = alc_patch_ops;
-	spec->init_hook = alc_auto_init_std;
 	spec->shutup = alc_eapd_shutup;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc262_loopbacks;
-#endif
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
 	return 0;
 
@@ -5031,17 +5694,7 @@ static int patch_alc268(struct hda_codec *codec)
 					  (0 << AC_AMPCAP_MUTE_SHIFT));
 	}
 
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
-
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
-
 	codec->patch_ops = alc_patch_ops;
-	spec->init_hook = alc_auto_init_std;
 	spec->shutup = alc_eapd_shutup;
 
 	return 0;
@@ -5054,10 +5707,6 @@ static int patch_alc268(struct hda_codec *codec)
 /*
  * ALC269
  */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc269_loopbacks	alc880_loopbacks
-#endif
-
 static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
 	.substreams = 1,
 	.channels_min = 2,
@@ -5079,35 +5728,6 @@ static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
 	/* NID is set in alc_build_pcms */
 };
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc269_mic2_for_mute_led(struct hda_codec *codec)
-{
-	switch (codec->subsystem_id) {
-	case 0x103c1586:
-		return 1;
-	}
-	return 0;
-}
-
-static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
-{
-	/* update mute-LED according to the speaker mute state */
-	if (nid == 0x01 || nid == 0x14) {
-		int pinval;
-		if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
-		    HDA_AMP_MUTE)
-			pinval = 0x24;
-		else
-			pinval = 0x20;
-		/* mic2 vref pin is used for mute LED control */
-		snd_hda_codec_update_cache(codec, 0x19, 0,
-					   AC_VERB_SET_PIN_WIDGET_CONTROL,
-					   pinval);
-	}
-	return alc_check_power_status(codec, nid);
-}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
-
 /* different alc269-variants */
 enum {
 	ALC269_TYPE_ALC269VA,
@@ -5258,6 +5878,31 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec,
 	spec->automute_hook = alc269_quanta_automute;
 }
 
+/* update mute-LED according to the speaker mute state via mic2 VREF pin */
+static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled)
+{
+	struct hda_codec *codec = private_data;
+	unsigned int pinval = enabled ? 0x20 : 0x24;
+	snd_hda_codec_update_cache(codec, 0x19, 0,
+				   AC_VERB_SET_PIN_WIDGET_CONTROL,
+				   pinval);
+}
+
+static void alc269_fixup_mic2_mute(struct hda_codec *codec,
+				   const struct alc_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	switch (action) {
+	case ALC_FIXUP_ACT_BUILD:
+		spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook;
+		snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true);
+		/* fallthru */
+	case ALC_FIXUP_ACT_INIT:
+		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
+		break;
+	}
+}
+
 enum {
 	ALC269_FIXUP_SONY_VAIO,
 	ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -5275,6 +5920,7 @@ enum {
 	ALC269_FIXUP_DMIC,
 	ALC269VB_FIXUP_AMIC,
 	ALC269VB_FIXUP_DMIC,
+	ALC269_FIXUP_MIC2_MUTE_LED,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -5395,9 +6041,14 @@ static const struct alc_fixup alc269_fixups[] = {
 			{ }
 		},
 	},
+	[ALC269_FIXUP_MIC2_MUTE_LED] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc269_fixup_mic2_mute,
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
 	SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
 	SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
 	SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
@@ -5420,7 +6071,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
 	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
 
-#if 1
+#if 0
 	/* Below is a quirk table taken from the old code.
 	 * Basically the device should work as is without the fixup table.
 	 * If BIOS doesn't give a proper info, enable the corresponding
@@ -5478,13 +6129,13 @@ static const struct alc_model_fixup alc269_fixup_models[] = {
 };
 
 
-static int alc269_fill_coef(struct hda_codec *codec)
+static void alc269_fill_coef(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	int val;
 
 	if (spec->codec_variant != ALC269_TYPE_ALC269VB)
-		return 0;
+		return;
 
 	if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
 		alc_write_coef_idx(codec, 0xf, 0x960b);
@@ -5520,8 +6171,6 @@ static int alc269_fill_coef(struct hda_codec *codec)
 
 	val = alc_read_coef_idx(codec, 0x4); /* HP */
 	alc_write_coef_idx(codec, 0x4, val | (1<<11));
-
-	return 0;
 }
 
 /*
@@ -5565,6 +6214,7 @@ static int patch_alc269(struct hda_codec *codec)
 		}
 		if (err < 0)
 			goto error;
+		spec->init_hook = alc269_fill_coef;
 		alc269_fill_coef(codec);
 	}
 
@@ -5577,15 +6227,6 @@ static int patch_alc269(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
-
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
-
 	if (!spec->no_analog && has_cdefine_beep(codec)) {
 		err = snd_hda_attach_beep_device(codec, 0x1);
 		if (err < 0)
@@ -5593,21 +6234,13 @@ static int patch_alc269(struct hda_codec *codec)
 		set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
 	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
 	codec->patch_ops = alc_patch_ops;
 #ifdef CONFIG_PM
 	codec->patch_ops.resume = alc269_resume;
 #endif
-	spec->init_hook = alc_auto_init_std;
 	spec->shutup = alc269_shutup;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc269_loopbacks;
-	if (alc269_mic2_for_mute_led(codec))
-		codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
-#endif
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
 	return 0;
 
@@ -5627,21 +6260,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
 	return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc861_loopbacks[] = {
-	{ 0x15, HDA_INPUT, 0 },
-	{ 0x15, HDA_INPUT, 1 },
-	{ 0x15, HDA_INPUT, 2 },
-	{ 0x15, HDA_INPUT, 3 },
-	{ } /* end */
-};
-#endif
-
-
 /* Pin config fixes */
 enum {
-	PINFIX_FSC_AMILO_PI1505,
-	PINFIX_ASUS_A6RP,
+	ALC861_FIXUP_FSC_AMILO_PI1505,
+	ALC861_FIXUP_AMP_VREF_0F,
+	ALC861_FIXUP_NO_JACK_DETECT,
+	ALC861_FIXUP_ASUS_A6RP,
 };
 
 /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
@@ -5663,8 +6287,16 @@ static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
 	spec->keep_vref_in_automute = 1;
 }
 
+/* suppress the jack-detection */
+static void alc_fixup_no_jack_detect(struct hda_codec *codec,
+				     const struct alc_fixup *fix, int action)
+{
+	if (action == ALC_FIXUP_ACT_PRE_PROBE)
+		codec->no_jack_detect = 1;
+}	
+
 static const struct alc_fixup alc861_fixups[] = {
-	[PINFIX_FSC_AMILO_PI1505] = {
+	[ALC861_FIXUP_FSC_AMILO_PI1505] = {
 		.type = ALC_FIXUP_PINS,
 		.v.pins = (const struct alc_pincfg[]) {
 			{ 0x0b, 0x0221101f }, /* HP */
@@ -5672,17 +6304,29 @@ static const struct alc_fixup alc861_fixups[] = {
 			{ }
 		}
 	},
-	[PINFIX_ASUS_A6RP] = {
+	[ALC861_FIXUP_AMP_VREF_0F] = {
 		.type = ALC_FIXUP_FUNC,
 		.v.func = alc861_fixup_asus_amp_vref_0f,
 	},
+	[ALC861_FIXUP_NO_JACK_DETECT] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc_fixup_no_jack_detect,
+	},
+	[ALC861_FIXUP_ASUS_A6RP] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc861_fixup_asus_amp_vref_0f,
+		.chained = true,
+		.chain_id = ALC861_FIXUP_NO_JACK_DETECT,
+	}
 };
 
 static const struct snd_pci_quirk alc861_fixup_tbl[] = {
-	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP),
-	SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP),	
-	SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
-	SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
+	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
+	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
+	SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
+	SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
+	SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
+	SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
 	{}
 };
 
@@ -5709,15 +6353,6 @@ static int patch_alc861(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
-
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
-
 	if (!spec->no_analog) {
 		err = snd_hda_attach_beep_device(codec, 0x23);
 		if (err < 0)
@@ -5725,16 +6360,13 @@ static int patch_alc861(struct hda_codec *codec)
 		set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
 	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
 	codec->patch_ops = alc_patch_ops;
-	spec->init_hook = alc_auto_init_std;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	spec->power_hook = alc_power_eapd;
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc861_loopbacks;
 #endif
 
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
+
 	return 0;
 
  error:
@@ -5749,10 +6381,6 @@ static int patch_alc861(struct hda_codec *codec)
  *
  * In addition, an independent DAC
  */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc861vd_loopbacks	alc880_loopbacks
-#endif
-
 static int alc861vd_parse_auto_config(struct hda_codec *codec)
 {
 	static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
@@ -5833,15 +6461,6 @@ static int patch_alc861vd(struct hda_codec *codec)
 		add_verb(spec, alc660vd_eapd_verbs);
 	}
 
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
-
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
-
 	if (!spec->no_analog) {
 		err = snd_hda_attach_beep_device(codec, 0x23);
 		if (err < 0)
@@ -5849,16 +6468,11 @@ static int patch_alc861vd(struct hda_codec *codec)
 		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
 	codec->patch_ops = alc_patch_ops;
 
-	spec->init_hook = alc_auto_init_std;
 	spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc861vd_loopbacks;
-#endif
+
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
 	return 0;
 
@@ -5878,9 +6492,6 @@ static int patch_alc861vd(struct hda_codec *codec)
  * In addition, an independent DAC for the multi-playback (not used in this
  * driver yet).
  */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc662_loopbacks	alc880_loopbacks
-#endif
 
 /*
  * BIOS auto configuration
@@ -5930,6 +6541,7 @@ enum {
 	ALC662_FIXUP_ASUS_MODE6,
 	ALC662_FIXUP_ASUS_MODE7,
 	ALC662_FIXUP_ASUS_MODE8,
+	ALC662_FIXUP_NO_JACK_DETECT,
 };
 
 static const struct alc_fixup alc662_fixups[] = {
@@ -6075,6 +6687,10 @@ static const struct alc_fixup alc662_fixups[] = {
 		.chained = true,
 		.chain_id = ALC662_FIXUP_SKU_IGNORE
 	},
+	[ALC662_FIXUP_NO_JACK_DETECT] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc_fixup_no_jack_detect,
+	},
 };
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -6083,6 +6699,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
 	SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+	SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
 	SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
 	SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
 	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
@@ -6204,15 +6821,6 @@ static int patch_alc662(struct hda_codec *codec)
 	if (err < 0)
 		goto error;
 
-	if (!spec->no_analog && !spec->adc_nids) {
-		alc_auto_fill_adc_caps(codec);
-		alc_rebuild_imux_for_auto_mic(codec);
-		alc_remove_invalid_adc_nids(codec);
-	}
-
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
-
 	if (!spec->no_analog && has_cdefine_beep(codec)) {
 		err = snd_hda_attach_beep_device(codec, 0x1);
 		if (err < 0)
@@ -6232,16 +6840,10 @@ static int patch_alc662(struct hda_codec *codec)
 		}
 	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
 	codec->patch_ops = alc_patch_ops;
-	spec->init_hook = alc_auto_init_std;
 	spec->shutup = alc_eapd_shutup;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc662_loopbacks;
-#endif
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
 	return 0;
 
@@ -6281,11 +6883,7 @@ static int patch_alc680(struct hda_codec *codec)
 		return err;
 	}
 
-	if (!spec->no_analog && !spec->cap_mixer)
-		set_capture_mixer(codec);
-
 	codec->patch_ops = alc_patch_ops;
-	spec->init_hook = alc_auto_init_std;
 
 	return 0;
 }
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 9dbb5735d778692c81f0010311b2958309a9fa43..33a9946b492cb333184b1a9405c11f553fc55566 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -99,6 +99,7 @@ enum {
 	STAC_DELL_VOSTRO_3500,
 	STAC_92HD83XXX_HP_cNB11_INTQUAD,
 	STAC_HP_DV7_4000,
+	STAC_HP_ZEPHYR,
 	STAC_92HD83XXX_MODELS
 };
 
@@ -309,6 +310,8 @@ struct sigmatel_spec {
 	unsigned long auto_capvols[MAX_ADCS_NUM];
 	unsigned auto_dmic_cnt;
 	hda_nid_t auto_dmic_nids[MAX_DMICS_NUM];
+
+	struct hda_vmaster_mute_hook vmaster_mute;
 };
 
 static const hda_nid_t stac9200_adc_nids[1] = {
@@ -662,7 +665,6 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
 static int stac_vrefout_set(struct hda_codec *codec,
 					hda_nid_t nid, unsigned int new_vref)
 {
@@ -686,7 +688,6 @@ static int stac_vrefout_set(struct hda_codec *codec,
 
 	return 1;
 }
-#endif
 
 static unsigned int stac92xx_vref_set(struct hda_codec *codec,
 					hda_nid_t nid, unsigned int new_vref)
@@ -894,6 +895,13 @@ static const struct hda_verb stac92hd83xxx_core_init[] = {
 	{}
 };
 
+static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = {
+	{ 0x22, 0x785, 0x43 },
+	{ 0x22, 0x782, 0xe0 },
+	{ 0x22, 0x795, 0x00 },
+	{}
+};
+
 static const struct hda_verb stac92hd71bxx_core_init[] = {
 	/* set master volume and direct control */
 	{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
@@ -999,8 +1007,8 @@ static const struct hda_verb stac9205_core_init[] = {
 	}
 
 static const struct snd_kcontrol_new stac9200_mixer[] = {
-	HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
 	{ } /* end */
@@ -1027,8 +1035,8 @@ static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
 };
 
 static const struct snd_kcontrol_new stac925x_mixer[] = {
-	HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT),
 	{ } /* end */
 };
 
@@ -1060,34 +1068,25 @@ static struct snd_kcontrol_new stac_smux_mixer = {
 	.put = stac92xx_smux_enum_put,
 };
 
-static const char * const slave_vols[] = {
-	"Front Playback Volume",
-	"Surround Playback Volume",
-	"Center Playback Volume",
-	"LFE Playback Volume",
-	"Side Playback Volume",
-	"Headphone Playback Volume",
-	"Speaker Playback Volume",
+static const char * const slave_pfxs[] = {
+	"Front", "Surround", "Center", "LFE", "Side",
+	"Headphone", "Speaker", "IEC958",
 	NULL
 };
 
-static const char * const slave_sws[] = {
-	"Front Playback Switch",
-	"Surround Playback Switch",
-	"Center Playback Switch",
-	"LFE Playback Switch",
-	"Side Playback Switch",
-	"Headphone Playback Switch",
-	"Speaker Playback Switch",
-	"IEC958 Playback Switch",
-	NULL
-};
+static void stac92xx_update_led_status(struct hda_codec *codec, int enabled);
+
+static void stac92xx_vmaster_hook(void *private_data, int val)
+{
+	stac92xx_update_led_status(private_data, val);
+}
 
 static void stac92xx_free_kctls(struct hda_codec *codec);
 
 static int stac92xx_build_controls(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
+	unsigned int vmaster_tlv[4];
 	int err;
 	int i;
 
@@ -1144,22 +1143,28 @@ static int stac92xx_build_controls(struct hda_codec *codec)
 	}
 
 	/* if we have no master control, let's create it */
-	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
-		unsigned int vmaster_tlv[4];
-		snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
-					HDA_OUTPUT, vmaster_tlv);
-		/* correct volume offset */
-		vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
-		/* minimum value is actually mute */
-		vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
-		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  vmaster_tlv, slave_vols);
-		if (err < 0)
-			return err;
-	}
-	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
-		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
-					  NULL, slave_sws);
+	snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
+				HDA_OUTPUT, vmaster_tlv);
+	/* correct volume offset */
+	vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
+	/* minimum value is actually mute */
+	vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
+	err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+				  vmaster_tlv, slave_pfxs,
+				  "Playback Volume");
+	if (err < 0)
+		return err;
+
+	err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+				    NULL, slave_pfxs,
+				    "Playback Switch", true,
+				    &spec->vmaster_mute.sw_kctl);
+	if (err < 0)
+		return err;
+
+	if (spec->gpio_led) {
+		spec->vmaster_mute.hook = stac92xx_vmaster_hook;
+		err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true);
 		if (err < 0)
 			return err;
 	}
@@ -1636,6 +1641,12 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = {
 	0x40f000f0, 0x40f000f0,
 };
 
+static const unsigned int hp_zephyr_pin_configs[10] = {
+	0x01813050, 0x0421201f, 0x04a1205e, 0x96130310,
+	0x96130310, 0x0101401f, 0x1111611f, 0xd5a30130,
+	0, 0,
+};
+
 static const unsigned int hp_cNB11_intquad_pin_configs[10] = {
 	0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110,
 	0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130,
@@ -1649,6 +1660,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
 	[STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs,
 	[STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs,
 	[STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs,
+	[STAC_HP_ZEPHYR] = hp_zephyr_pin_configs,
 };
 
 static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
@@ -1659,6 +1671,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
 	[STAC_DELL_VOSTRO_3500] = "dell-vostro-3500",
 	[STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad",
 	[STAC_HP_DV7_4000] = "hp-dv7-4000",
+	[STAC_HP_ZEPHYR] = "hp-zephyr",
 };
 
 static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
@@ -1711,6 +1724,14 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
 			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593,
 			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561,
+			  "HP", STAC_HP_ZEPHYR),
+	{} /* terminator */
+};
+
+static const struct snd_pci_quirk stac92hd83xxx_codec_id_cfg_tbl[] = {
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561,
+			  "HP", STAC_HP_ZEPHYR),
 	{} /* terminator */
 };
 
@@ -4410,8 +4431,7 @@ static int stac92xx_init(struct hda_codec *codec)
 	snd_hda_jack_report_sync(codec);
 
 	/* sync mute LED */
-	if (spec->gpio_led)
-		hda_call_check_power_status(codec, 0x01);
+	snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
 	if (spec->dac_list)
 		stac92xx_power_down(codec);
 	return 0;
@@ -4989,7 +5009,6 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
 	return 0;
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
 static int stac92xx_pre_resume(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -5024,82 +5043,40 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
 			afg_power_state);
 	snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
 }
+#else
+#define stac92xx_suspend	NULL
+#define stac92xx_resume		NULL
+#define stac92xx_pre_resume	NULL
+#define stac92xx_set_power_state NULL
+#endif /* CONFIG_PM */
 
-/*
- * For this feature CONFIG_SND_HDA_POWER_SAVE is needed
- * as mute LED state is updated in check_power_status hook
- */
-static int stac92xx_update_led_status(struct hda_codec *codec)
+/* update mute-LED accoring to the master switch */
+static void stac92xx_update_led_status(struct hda_codec *codec, int enabled)
 {
 	struct sigmatel_spec *spec = codec->spec;
-	int i, num_ext_dacs, muted = 1;
-	unsigned int muted_lvl, notmtd_lvl;
-	hda_nid_t nid;
+	int muted = !enabled;
 
 	if (!spec->gpio_led)
-		return 0;
+		return;
+
+	/* LED state is inverted on these systems */
+	if (spec->gpio_led_polarity)
+		muted = !muted;
 
-	for (i = 0; i < spec->multiout.num_dacs; i++) {
-		nid = spec->multiout.dac_nids[i];
-		if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
-		      HDA_AMP_MUTE)) {
-			muted = 0; /* something heard */
-			break;
-		}
-	}
-	if (muted && spec->multiout.hp_nid)
-		if (!(snd_hda_codec_amp_read(codec,
-				spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) &
-					HDA_AMP_MUTE)) {
-			muted = 0; /* HP is not muted */
-		}
-	num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid);
-	for (i = 0; muted && i < num_ext_dacs; i++) {
-		nid = spec->multiout.extra_out_nid[i];
-		if (nid == 0)
-			break;
-		if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
-		      HDA_AMP_MUTE)) {
-			muted = 0; /* extra output is not muted */
-		}
-	}
 	/*polarity defines *not* muted state level*/
 	if (!spec->vref_mute_led_nid) {
 		if (muted)
 			spec->gpio_data &= ~spec->gpio_led; /* orange */
 		else
 			spec->gpio_data |= spec->gpio_led; /* white */
-
-		if (!spec->gpio_led_polarity) {
-			/* LED state is inverted on these systems */
-			spec->gpio_data ^= spec->gpio_led;
-		}
 		stac_gpio_set(codec, spec->gpio_mask,
 				spec->gpio_dir, spec->gpio_data);
 	} else {
-		notmtd_lvl = spec->gpio_led_polarity ?
-				AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;
-		muted_lvl = spec->gpio_led_polarity ?
-				AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_50;
-		spec->vref_led = muted ? muted_lvl : notmtd_lvl;
+		spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;
 		stac_vrefout_set(codec,	spec->vref_mute_led_nid,
 				 spec->vref_led);
 	}
-	return 0;
-}
-
-/*
- * use power check for controlling mute led of HP notebooks
- */
-static int stac92xx_check_power_status(struct hda_codec *codec,
-					      hda_nid_t nid)
-{
-	stac92xx_update_led_status(codec);
-
-	return 0;
 }
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
-#endif /* CONFIG_PM */
 
 static const struct hda_codec_ops stac92xx_patch_ops = {
 	.build_controls = stac92xx_build_controls,
@@ -5580,6 +5557,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
 							STAC_92HD83XXX_MODELS,
 							stac92hd83xxx_models,
 							stac92hd83xxx_cfg_tbl);
+	/* check codec subsystem id if not found */
+	if (spec->board_config < 0)
+		spec->board_config =
+			snd_hda_check_board_codec_sid_config(codec,
+				STAC_92HD83XXX_MODELS, stac92hd83xxx_models,
+				stac92hd83xxx_codec_id_cfg_tbl);
 again:
 	if (spec->board_config < 0)
 		snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
@@ -5590,12 +5573,17 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
 
 	codec->patch_ops = stac92xx_patch_ops;
 
+	switch (spec->board_config) {
+	case STAC_HP_ZEPHYR:
+		spec->init = stac92hd83xxx_hp_zephyr_init;
+		break;
+	}
+
 	if (find_mute_led_cfg(codec, -1/*no default cfg*/))
 		snd_printd("mute LED gpio %d polarity %d\n",
 				spec->gpio_led,
 				spec->gpio_led_polarity);
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (spec->gpio_led) {
 		if (!spec->vref_mute_led_nid) {
 			spec->gpio_mask |= spec->gpio_led;
@@ -5605,11 +5593,10 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
 			codec->patch_ops.set_power_state =
 					stac92xx_set_power_state;
 		}
+#ifdef CONFIG_PM
 		codec->patch_ops.pre_resume = stac92xx_pre_resume;
-		codec->patch_ops.check_power_status =
-			stac92xx_check_power_status;
+#endif
 	}
-#endif	
 
 	err = stac92xx_parse_auto_config(codec);
 	if (!err) {
@@ -5906,7 +5893,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
 				spec->gpio_led,
 				spec->gpio_led_polarity);
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (spec->gpio_led) {
 		if (!spec->vref_mute_led_nid) {
 			spec->gpio_mask |= spec->gpio_led;
@@ -5916,11 +5902,10 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
 			codec->patch_ops.set_power_state =
 					stac92xx_set_power_state;
 		}
+#ifdef CONFIG_PM
 		codec->patch_ops.pre_resume = stac92xx_pre_resume;
-		codec->patch_ops.check_power_status =
-			stac92xx_check_power_status;
+#endif
 	}
-#endif	
 
 	spec->multiout.dac_nids = spec->dac_nids;
 
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index dff9a00ee8fbf136101243c031d3cd3222cff291..06214fdc9486d2c5d1d6c59eca22325330c5c3f3 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -550,7 +550,10 @@ static void via_auto_init_output(struct hda_codec *codec,
 	pin = path->path[path->depth - 1];
 
 	init_output_pin(codec, pin, pin_type);
-	caps = query_amp_caps(codec, pin, HDA_OUTPUT);
+	if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
+		caps = query_amp_caps(codec, pin, HDA_OUTPUT);
+	else
+		caps = 0;
 	if (caps & AC_AMPCAP_MUTE) {
 		unsigned int val;
 		val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
@@ -645,6 +648,10 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
 
 	/* init ADCs */
 	for (i = 0; i < spec->num_adc_nids; i++) {
+		hda_nid_t nid = spec->adc_nids[i];
+		if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP) ||
+		    !(query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE))
+			continue;
 		snd_hda_codec_write(codec, spec->adc_nids[i], 0,
 				    AC_VERB_SET_AMP_GAIN_MUTE,
 				    AMP_IN_UNMUTE(0));
@@ -1445,25 +1452,9 @@ static const struct hda_pcm_stream via_pcm_digital_capture = {
 /*
  * slave controls for virtual master
  */
-static const char * const via_slave_vols[] = {
-	"Front Playback Volume",
-	"Surround Playback Volume",
-	"Center Playback Volume",
-	"LFE Playback Volume",
-	"Side Playback Volume",
-	"Headphone Playback Volume",
-	"Speaker Playback Volume",
-	NULL,
-};
-
-static const char * const via_slave_sws[] = {
-	"Front Playback Switch",
-	"Surround Playback Switch",
-	"Center Playback Switch",
-	"LFE Playback Switch",
-	"Side Playback Switch",
-	"Headphone Playback Switch",
-	"Speaker Playback Switch",
+static const char * const via_slave_pfxs[] = {
+	"Front", "Surround", "Center", "LFE", "Side",
+	"Headphone", "Speaker",
 	NULL,
 };
 
@@ -1508,13 +1499,15 @@ static int via_build_controls(struct hda_codec *codec)
 		snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
 					HDA_OUTPUT, vmaster_tlv);
 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  vmaster_tlv, via_slave_vols);
+					  vmaster_tlv, via_slave_pfxs,
+					  "Playback Volume");
 		if (err < 0)
 			return err;
 	}
 	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
 		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
-					  NULL, via_slave_sws);
+					  NULL, via_slave_pfxs,
+					  "Playback Switch");
 		if (err < 0)
 			return err;
 	}
@@ -1522,6 +1515,8 @@ static int via_build_controls(struct hda_codec *codec)
 	/* assign Capture Source enums to NID */
 	kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
 	for (i = 0; kctl && i < kctl->count; i++) {
+		if (!spec->mux_nids[i])
+			continue;
 		err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]);
 		if (err < 0)
 			return err;
@@ -2488,6 +2483,8 @@ static int create_mic_boost_ctls(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
 	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	const char *prev_label = NULL;
+	int type_idx = 0;
 	int i, err;
 
 	for (i = 0; i < cfg->num_inputs; i++) {
@@ -2502,8 +2499,13 @@ static int create_mic_boost_ctls(struct hda_codec *codec)
 		if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS))
 			continue;
 		label = hda_get_autocfg_input_label(codec, cfg, i);
+		if (prev_label && !strcmp(label, prev_label))
+			type_idx++;
+		else
+			type_idx = 0;
+		prev_label = label;
 		snprintf(name, sizeof(name), "%s Boost Volume", label);
-		err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+		err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx,
 			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT));
 		if (err < 0)
 			return err;
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 92362973764dbbfebeab03085a669f36d2f21bf9..812d10e43ae0aa270517b9204be80a2c64200ff6 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -1013,6 +1013,25 @@ static int set_rate_constraints(struct snd_ice1712 *ice,
 					  ice->hw_rates);
 }
 
+/* if the card has the internal rate locked (is_pro_locked), limit runtime
+   hw rates to the current internal rate only.
+*/
+static void constrain_rate_if_locked(struct snd_pcm_substream *substream)
+{
+	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned int rate;
+	if (is_pro_rate_locked(ice)) {
+		rate = ice->get_rate(ice);
+		if (rate >= runtime->hw.rate_min
+		    && rate <= runtime->hw.rate_max) {
+			runtime->hw.rate_min = rate;
+			runtime->hw.rate_max = rate;
+		}
+	}
+}
+
+
 /* multi-channel playback needs alignment 8x32bit regardless of the channels
  * actually used
  */
@@ -1046,6 +1065,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream)
 				   VT1724_BUFFER_ALIGN);
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   VT1724_BUFFER_ALIGN);
+	constrain_rate_if_locked(substream);
 	if (ice->pro_open)
 		ice->pro_open(ice, substream);
 	return 0;
@@ -1066,6 +1086,7 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream)
 				   VT1724_BUFFER_ALIGN);
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   VT1724_BUFFER_ALIGN);
+	constrain_rate_if_locked(substream);
 	if (ice->pro_open)
 		ice->pro_open(ice, substream);
 	return 0;
@@ -1215,6 +1236,7 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
 				   VT1724_BUFFER_ALIGN);
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   VT1724_BUFFER_ALIGN);
+	constrain_rate_if_locked(substream);
 	if (ice->spdif.ops.open)
 		ice->spdif.ops.open(ice, substream);
 	return 0;
@@ -1251,6 +1273,7 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
 				   VT1724_BUFFER_ALIGN);
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   VT1724_BUFFER_ALIGN);
+	constrain_rate_if_locked(substream);
 	if (ice->spdif.ops.open)
 		ice->spdif.ops.open(ice, substream);
 	return 0;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 12a9a2b0338719c556446c2c716d5ff4a8742196..a8159b81e9c438ea42b63bb79e9bdcd65e521d8d 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2317,6 +2317,10 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state)
 	for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++)
 		chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]);
 	chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE);
+	pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY,
+			     &chip->saved_dsxg_legacy);
+	pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY,
+			     &chip->saved_dsxg_elegacy);
 	snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
 	snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
 	snd_ymfpci_disable_dsp(chip);
@@ -2351,6 +2355,11 @@ int snd_ymfpci_resume(struct pci_dev *pci)
 
 	snd_ac97_resume(chip->ac97);
 
+	pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY,
+			      chip->saved_dsxg_legacy);
+	pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY,
+			      chip->saved_dsxg_elegacy);
+
 	/* start hw again */
 	if (chip->start_count > 0) {
 		spin_lock_irq(&chip->reg_lock);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 35e662d270e6141338669051a784c06a3fe9fbea..91c985599d32c782c9b42029ccb409bb9afec429 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -25,6 +25,9 @@ if SND_SOC
 config SND_SOC_AC97_BUS
 	bool
 
+config SND_SOC_DMAENGINE_PCM
+	bool
+
 # All the supported SoCs
 source "sound/soc/atmel/Kconfig"
 source "sound/soc/au1x/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 9ea8ac827adc37327d955acd30a7639b571030d3..2feaf376e94b2fc4ab06ca821e4ac328d3d423bb 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,6 +1,9 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
 snd-soc-core-objs += soc-pcm.o soc-io.o
 
+snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o
+obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o
+
 obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
 obj-$(CONFIG_SND_SOC)	+= codecs/
 obj-$(CONFIG_SND_SOC)	+= atmel/
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index a21ff459e5d3e0d53a6d50264c3f150dbaf6b0c9..9b84f985770ee4e09ca1d7a8ab04cbe410fda037 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -362,7 +362,7 @@ static struct snd_pcm_ops atmel_pcm_ops = {
 /*--------------------------------------------------------------------------*\
  * ASoC platform driver
 \*--------------------------------------------------------------------------*/
-static u64 atmel_pcm_dmamask = 0xffffffff;
+static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
 
 static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
@@ -373,7 +373,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &atmel_pcm_dmamask;
 	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = 0xffffffff;
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
 	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
 		ret = atmel_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c
index 4ca667d477f9f332e77a9ab60b0ce3805f4418ce..f65f08beac31487248139e594f16d5f51381e08b 100644
--- a/sound/soc/atmel/snd-soc-afeb9260.c
+++ b/sound/soc/atmel/snd-soc-afeb9260.c
@@ -46,29 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int err;
 
-	/* Set codec DAI configuration */
-	err = snd_soc_dai_set_fmt(codec_dai,
-				  SND_SOC_DAIFMT_I2S|
-				  SND_SOC_DAIFMT_NB_IF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (err < 0) {
-		printk(KERN_ERR "can't set codec DAI configuration\n");
-		return err;
-	}
-
-	/* Set cpu DAI configuration */
-	err = snd_soc_dai_set_fmt(cpu_dai,
-				  SND_SOC_DAIFMT_I2S |
-				  SND_SOC_DAIFMT_NB_IF |
-				  SND_SOC_DAIFMT_CBM_CFM);
-	if (err < 0) {
-		printk(KERN_ERR "can't set cpu DAI configuration\n");
-		return err;
-	}
-
 	/* Set the codec system clock for DAC and ADC */
 	err =
 	    snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -91,7 +70,7 @@ static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Mic Jack", NULL),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route afeb9260_audio_map[] = {
 	{"Headphone Jack", NULL, "LHPOUT"},
 	{"Headphone Jack", NULL, "RHPOUT"},
 
@@ -106,13 +85,6 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-	/* Add afeb9260 specific widgets */
-	snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
-				  ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
-	/* Set up afeb9260 specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
 	snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
 	snd_soc_dapm_enable_pin(dapm, "Line In");
 	snd_soc_dapm_enable_pin(dapm, "Mic Jack");
@@ -129,6 +101,8 @@ static struct snd_soc_dai_link afeb9260_dai = {
 	.platform_name = "atmel_pcm-audio",
 	.codec_name = "tlv320aic23-codec.0-001a",
 	.init = afeb9260_tlv320aic23_init,
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+		   SND_SOC_DAIFMT_CBM_CFM,
 	.ops = &afeb9260_ops,
 };
 
@@ -138,6 +112,11 @@ static struct snd_soc_card snd_soc_machine_afeb9260 = {
 	.owner = THIS_MODULE,
 	.dai_link = &afeb9260_dai,
 	.num_links = 1,
+
+	.dapm_widgets = tlv320aic23_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+	.dapm_routes = afeb9260_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(afeb9260_audio_map),
 };
 
 static struct platform_device *afeb9260_snd_device;
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index 60962ce6cd4d06c96536ca9ee124a8ac66e10467..d542d4063771a4daaec9048ad0b6aa0e4d640afb 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -40,20 +40,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
 {
 	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;
 	unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
 	int ret = 0;
-	/* set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
-		SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
-	/* set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
-		SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
 
 	/* set cpu DAI channel mapping */
 	ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
@@ -68,6 +56,9 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {
 	.hw_params = bf5xx_ad1836_hw_params,
 };
 
+#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+				SND_SOC_DAIFMT_CBM_CFM)
+
 static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
 	{
 		.name = "ad1836",
@@ -77,6 +68,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
 		.platform_name = "bfin-tdm-pcm-audio",
 		.codec_name = "spi0.4",
 		.ops = &bf5xx_ad1836_ops,
+		.dai_fmt = BF5XX_AD1836_DAIFMT,
 	},
 	{
 		.name = "ad1836",
@@ -86,6 +78,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
 		.platform_name = "bfin-tdm-pcm-audio",
 		.codec_name = "spi0.4",
 		.ops = &bf5xx_ad1836_ops,
+		.dai_fmt = BF5XX_AD1836_DAIFMT,
 	},
 };
 
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c
index 2d8d82dbc159ef6326b553e8ce2916fd0c1e771f..0e55e9f2a514df69473365a7222d93908ea1bdcd 100644
--- a/sound/soc/blackfin/bf5xx-ad193x.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -60,18 +60,6 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	/* set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
-		SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
-	/* set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
-		SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
 	/* set the codec system clock for DAC and ADC */
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
 		SND_SOC_CLOCK_IN);
@@ -92,6 +80,9 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+				SND_SOC_DAIFMT_CBM_CFM)
+
 static struct snd_soc_ops bf5xx_ad193x_ops = {
 	.hw_params = bf5xx_ad193x_hw_params,
 };
@@ -105,6 +96,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
 		.platform_name = "bfin-tdm-pcm-audio",
 		.codec_name = "spi0.5",
 		.ops = &bf5xx_ad193x_ops,
+		.dai_fmt = BF5XX_AD193X_DAIFMT,
 	},
 	{
 		.name = "ad193x",
@@ -114,6 +106,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
 		.platform_name = "bfin-tdm-pcm-audio",
 		.codec_name = "spi0.5",
 		.ops = &bf5xx_ad193x_ops,
+		.dai_fmt = BF5XX_AD193X_DAIFMT,
 	},
 };
 
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 8e49508596dad59911ab3ac3c4ae1baa006cc678..61cc91d4a028f8916d9c48adf0d14df2406368e2 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -145,29 +145,8 @@ static int bf5xx_probe(struct snd_soc_card *card)
 	return 0;
 }
 
-static int bf5xx_ad73311_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;
-
-	pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
-		params_format(params));
-
-	/* set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
-		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-
-static struct snd_soc_ops bf5xx_ad73311_ops = {
-	.hw_params = bf5xx_ad73311_hw_params,
-};
+#define BF5XX_AD7311_DAI_FMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | \
+				SND_SOC_DAIFMT_CBM_CFM)
 
 static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
 	{
@@ -177,7 +156,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
 		.codec_dai_name = "ad73311-hifi",
 		.platform_name = "bfin-i2s-pcm-audio",
 		.codec_name = "ad73311",
-		.ops = &bf5xx_ad73311_ops,
+		.dai_fmt = BF5XX_AD7311_DAI_FMT,
 	},
 	{
 		.name = "ad73311",
@@ -186,7 +165,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
 		.codec_dai_name = "ad73311-hifi",
 		.platform_name = "bfin-i2s-pcm-audio",
 		.codec_name = "ad73311",
-		.ops = &bf5xx_ad73311_ops,
+		.dai_fmt = BF5XX_AD7311_DAI_FMT,
 	},
 };
 
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index 0303032380420eb7bd12d198ca4be3f5ea684149..df3ac73f8778288d6666e29728e6136b44630827 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -49,7 +49,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	unsigned int clk = 0;
 	int ret = 0;
 
@@ -75,21 +74,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	/*
-	 * CODEC is master for BCLK and LRC in this configuration.
-	 */
-
-	/* set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-	/* set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
 	ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
 		SND_SOC_CLOCK_IN);
 	if (ret < 0)
@@ -102,6 +86,10 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {
 	.hw_params = bf5xx_ssm2602_hw_params,
 };
 
+/* CODEC is master for BCLK and LRC in this configuration. */
+#define BF5XX_SSM2602_DAIFMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
+				SND_SOC_DAIFMT_CBM_CFM)
+
 static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = {
 	{
 		.name = "ssm2602",
diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c
index 26b271c62efa392825f95c64c627fc7fc63d1a68..f3adbdbdd5e1a0a96f93caf305c6ba0a74619e2d 100644
--- a/sound/soc/blackfin/bfin-eval-adau1373.c
+++ b/sound/soc/blackfin/bfin-eval-adau1373.c
@@ -67,21 +67,10 @@ static int bfin_eval_adau1373_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;
 	int pll_rate;
 
-	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret)
-		return 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)
-		return ret;
-
 	switch (params_rate(params)) {
 	case 48000:
 	case 8000:
@@ -143,6 +132,8 @@ static struct snd_soc_dai_link bfin_eval_adau1373_dai = {
 	.codec_name = "adau1373.0-001a",
 	.ops = &bfin_eval_adau1373_ops,
 	.init = bfin_eval_adau1373_codec_init,
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBM_CFM,
 };
 
 static struct snd_soc_card bfin_eval_adau1373 = {
diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c
index c0064fa1dca653c7395062b5ee0076b5f24fbce2..b0531fc9d814058409b5cf585e99eaf0e3f7352d 100644
--- a/sound/soc/blackfin/bfin-eval-adau1701.c
+++ b/sound/soc/blackfin/bfin-eval-adau1701.c
@@ -37,20 +37,9 @@ static int bfin_eval_adau1701_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(cpu_dai, SND_SOC_DAIFMT_I2S |
-			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret)
-		return 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)
-		return ret;
-
 	ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1701_CLK_SRC_OSC, 12288000,
 			SND_SOC_CLOCK_IN);
 
@@ -61,6 +50,9 @@ static struct snd_soc_ops bfin_eval_adau1701_ops = {
 	.hw_params = bfin_eval_adau1701_hw_params,
 };
 
+#define BFIN_EVAL_ADAU1701_DAI_FMT (SND_SOC_DAIFMT_I2S | \
+				SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM)
+
 static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
 	{
 		.name = "adau1701",
@@ -70,6 +62,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
 		.platform_name = "bfin-i2s-pcm-audio",
 		.codec_name = "adau1701.0-0034",
 		.ops = &bfin_eval_adau1701_ops,
+		.dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
 	},
 	{
 		.name = "adau1701",
@@ -79,6 +72,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
 		.platform_name = "bfin-i2s-pcm-audio",
 		.codec_name = "adau1701.0-0034",
 		.ops = &bfin_eval_adau1701_ops,
+		.dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
 	},
 };
 
diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c
index 4ef079f95e2ede670a97f782fad67e573a516eed..84b09987b7f319cbaf01e2cb05be11c666404280 100644
--- a/sound/soc/blackfin/bfin-eval-adav80x.c
+++ b/sound/soc/blackfin/bfin-eval-adav80x.c
@@ -34,20 +34,9 @@ static int bfin_eval_adav80x_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(cpu_dai, SND_SOC_DAIFMT_I2S |
-			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-	if (ret)
-		return 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)
-		return ret;
-
 	ret = snd_soc_dai_set_pll(codec_dai, ADAV80X_PLL1, ADAV80X_PLL_SRC_XTAL,
 			27000000, params_rate(params) * 256);
 	if (ret)
@@ -88,6 +77,8 @@ static struct snd_soc_dai_link bfin_eval_adav80x_dais[] = {
 		.platform_name = "bfin-i2s-pcm-audio",
 		.init = bfin_eval_adav80x_codec_init,
 		.ops = &bfin_eval_adav80x_ops,
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+				SND_SOC_DAIFMT_CBM_CFM,
 	},
 };
 
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7c205e77d83aa8af2439955b56cecc9fc1e7419b..6508e8b790bb16076d3539261db7df43032438e4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX98088 if I2C
 	select SND_SOC_MAX98095 if I2C
 	select SND_SOC_MAX9850 if I2C
+	select SND_SOC_MAX9768 if I2C
 	select SND_SOC_MAX9877 if I2C
 	select SND_SOC_PCM3008
 	select SND_SOC_RT5631 if I2C
@@ -62,6 +63,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_WL1273 if MFD_WL1273_CORE
 	select SND_SOC_WM1250_EV1 if I2C
 	select SND_SOC_WM2000 if I2C
+	select SND_SOC_WM2200 if I2C
 	select SND_SOC_WM5100 if I2C
 	select SND_SOC_WM8350 if MFD_WM8350
 	select SND_SOC_WM8400 if MFD_WM8400
@@ -292,6 +294,9 @@ config SND_SOC_WM1250_EV1
 config SND_SOC_WM2000
 	tristate
 
+config SND_SOC_WM2200
+	tristate
+
 config SND_SOC_WM5100
 	tristate
 
@@ -425,6 +430,9 @@ config SND_SOC_WM9713
 config SND_SOC_LM4857
 	tristate
 
+config SND_SOC_MAX9768
+	tristate
+
 config SND_SOC_MAX9877
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index de8078178f86be523f75071207a776c6ff2b4657..6662eb0cdcc0724f2364760a15730346278267ab 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -25,6 +25,7 @@ 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-max9768-objs := max9768.o
 snd-soc-max98088-objs := max98088.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
@@ -51,6 +52,7 @@ snd-soc-uda1380-objs := uda1380.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm2000-objs := wm2000.o
+snd-soc-wm2200-objs := wm2200.o
 snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
@@ -129,6 +131,7 @@ 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_MAX9768)	+= snd-soc-max9768.o
 obj-$(CONFIG_SND_SOC_MAX98088)	+= snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98095)	+= snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
@@ -153,6 +156,7 @@ obj-$(CONFIG_SND_SOC_UDA1380)	+= snd-soc-uda1380.o
 obj-$(CONFIG_SND_SOC_WL1273)	+= snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
 obj-$(CONFIG_SND_SOC_WM2000)	+= snd-soc-wm2000.o
+obj-$(CONFIG_SND_SOC_WM2200)	+= snd-soc-wm2200.o
 obj-$(CONFIG_SND_SOC_WM5100)	+= snd-soc-wm5100.o
 obj-$(CONFIG_SND_SOC_WM8350)	+= snd-soc-wm8350.o
 obj-$(CONFIG_SND_SOC_WM8400)	+= snd-soc-wm8400.o
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 982d201c2e8699589ab049544e517d2f69db3678..12e3b4118557388b5cbb1a62fc0dea3264ba082f 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -277,7 +277,7 @@ static int ad1836_probe(struct snd_soc_codec *codec)
 	if (ad1836->type == AD1836) {
 		/* left/right diff:PGA/MUX */
 		snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
-		ret = snd_soc_add_controls(codec, ad1836_controls,
+		ret = snd_soc_add_codec_controls(codec, ad1836_controls,
 				ARRAY_SIZE(ad1836_controls));
 		if (ret)
 			return ret;
@@ -285,11 +285,11 @@ static int ad1836_probe(struct snd_soc_codec *codec)
 		snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00);
 	}
 
-	ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2);
+	ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2);
 	if (ret)
 		return ret;
 
-	ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs);
+	ret = snd_soc_add_codec_controls(codec, ad183x_adc_controls, num_adcs);
 	if (ret)
 		return ret;
 
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 9bba7f849464391778e5c33f0076c0e20b3ea44f..8c39dddd7d0063d90adcf587c5e6dc19c37f73ad 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -228,7 +228,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
 	ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
 	ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
 
-	snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
+	snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls,
 				ARRAY_SIZE(ad1980_snd_ac97_controls));
 
 	return 0;
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 971ba45291717d9c9c87dc662b07b23deb2b55a2..44f59064d8de11247187a8d124661361e7913e65 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1244,8 +1244,6 @@ static int adau1373_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	codec->dapm.idle_bias_off = true;
-
 	if (pdata) {
 		if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting))
 			return -EINVAL;
@@ -1259,7 +1257,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
 				pdata->drc_setting[i]);
 		}
 
-		snd_soc_add_controls(codec, adau1373_drc_controls,
+		snd_soc_add_codec_controls(codec, adau1373_drc_controls,
 			pdata->num_drc);
 
 		val = 0;
@@ -1284,7 +1282,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
 	}
 
 	if (!lineout_differential) {
-		snd_soc_add_controls(codec, adau1373_lineout2_controls,
+		snd_soc_add_codec_controls(codec, adau1373_lineout2_controls,
 			ARRAY_SIZE(adau1373_lineout2_controls));
 	}
 
@@ -1340,6 +1338,7 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
 	.suspend =	adau1373_suspend,
 	.resume =	adau1373_resume,
 	.set_bias_level = adau1373_set_bias_level,
+	.idle_bias_off = true,
 	.reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
 	.reg_cache_default = adau1373_default_regs,
 	.reg_word_size = sizeof(uint8_t),
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 6b325ea03869f4758247cec758c96ed71ab60b7e..78e9ce48bb99e6402987a0083d124219bd3400f7 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -457,7 +457,6 @@ static int adau1701_probe(struct snd_soc_codec *codec)
 {
 	int ret;
 
-	codec->dapm.idle_bias_off = 1;
 	codec->control_data = to_i2c_client(codec->dev);
 
 	ret = adau1701_load_firmware(codec);
@@ -473,6 +472,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
 static struct snd_soc_codec_driver adau1701_codec_drv = {
 	.probe			= adau1701_probe,
 	.set_bias_level		= adau1701_set_bias_level,
+	.idle_bias_off		= true,
 
 	.reg_cache_size		= ADAU1701_NUM_REGS,
 	.reg_word_size		= sizeof(u16),
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index d27b5e4cce99b58339300b860bc4bad1b924b87d..ceb96ecf5588994f1d8c3797a7d4ed9048f83417 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -46,75 +46,15 @@
 #define DRV_NAME "ak4104-codec"
 
 struct ak4104_private {
-	enum snd_soc_control_type control_type;
-	void *control_data;
+	struct regmap *regmap;
 };
 
-static int ak4104_fill_cache(struct snd_soc_codec *codec)
-{
-	int i;
-	u8 *reg_cache = codec->reg_cache;
-	struct spi_device *spi = codec->control_data;
-
-	for (i = 0; i < codec->driver->reg_cache_size; i++) {
-		int ret = spi_w8r8(spi, i | AK4104_READ);
-		if (ret < 0) {
-			dev_err(&spi->dev, "SPI write failure\n");
-			return ret;
-		}
-
-		reg_cache[i] = ret;
-	}
-
-	return 0;
-}
-
-static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
-					  unsigned int reg)
-{
-	u8 *reg_cache = codec->reg_cache;
-
-	if (reg >= codec->driver->reg_cache_size)
-		return -EINVAL;
-
-	return reg_cache[reg];
-}
-
-static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
-			    unsigned int value)
-{
-	u8 *cache = codec->reg_cache;
-	struct spi_device *spi = codec->control_data;
-
-	if (reg >= codec->driver->reg_cache_size)
-		return -EINVAL;
-
-	/* only write to the hardware if value has changed */
-	if (cache[reg] != value) {
-		u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value };
-
-		if (spi_write(spi, tmp, sizeof(tmp))) {
-			dev_err(&spi->dev, "SPI write failed\n");
-			return -EIO;
-		}
-
-		cache[reg] = value;
-	}
-
-	return 0;
-}
-
 static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
 			      unsigned int format)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
 	int val = 0;
-
-	val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
-	if (val < 0)
-		return val;
-
-	val &= ~(AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1);
+	int ret;
 
 	/* set DAI format */
 	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -135,7 +75,13 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
 		return -EINVAL;
 
-	return ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+	ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+				  AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
+				  val);
+	if (ret < 0)
+		return ret;
+
+	return 0;
 }
 
 static int ak4104_hw_params(struct snd_pcm_substream *substream,
@@ -148,7 +94,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
 
 	/* set the IEC958 bits: consumer mode, no copyright bit */
 	val |= IEC958_AES0_CON_NOT_COPYRIGHT;
-	ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(0), val);
+	snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val);
 
 	val = 0;
 
@@ -167,7 +113,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val);
+	return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val);
 }
 
 static const struct snd_soc_dai_ops ak4101_dai_ops = {
@@ -192,67 +138,57 @@ static struct snd_soc_dai_driver ak4104_dai = {
 static int ak4104_probe(struct snd_soc_codec *codec)
 {
 	struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
-	int ret, val;
-
-	codec->control_data = ak4104->control_data;
+	int ret;
 
-	/* read all regs and fill the cache */
-	ret = ak4104_fill_cache(codec);
-	if (ret < 0) {
-		dev_err(codec->dev, "failed to fill register cache\n");
+	codec->control_data = ak4104->regmap;
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+	if (ret != 0)
 		return ret;
-	}
-
-	/* read the 'reserved' register - according to the datasheet, it
-	 * should contain 0x5b. Not a good way to verify the presence of
-	 * the device, but there is no hardware ID register. */
-	if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
-					 AK4104_RESERVED_VAL)
-		return -ENODEV;
 
 	/* set power-up and non-reset bits */
-	val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
-	val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN;
-	ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+	ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+				  AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
+				  AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
 	if (ret < 0)
 		return ret;
 
 	/* enable transmitter */
-	val = ak4104_read_reg_cache(codec, AK4104_REG_TX);
-	val |= AK4104_TX_TXE;
-	ret = ak4104_spi_write(codec, AK4104_REG_TX, val);
+	ret = snd_soc_update_bits(codec, AK4104_REG_TX,
+				  AK4104_TX_TXE, AK4104_TX_TXE);
 	if (ret < 0)
 		return ret;
 
-	dev_info(codec->dev, "SPI device initialized\n");
 	return 0;
 }
 
 static int ak4104_remove(struct snd_soc_codec *codec)
 {
-	int val, ret;
-
-	val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
-	if (val < 0)
-		return val;
-
-	/* clear power-up and non-reset bits */
-	val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
-	ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+	snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+			    AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
 
-	return ret;
+	return 0;
 }
 
 static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
 	.probe =	ak4104_probe,
 	.remove =	ak4104_remove,
-	.reg_cache_size = AK4104_NUM_REGS,
-	.reg_word_size = sizeof(u8),
+};
+
+static const struct regmap_config ak4104_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = AK4104_NUM_REGS - 1,
+	.read_flag_mask = AK4104_READ,
+	.write_flag_mask = AK4104_WRITE,
+
+	.cache_type = REGCACHE_RBTREE,
 };
 
 static int ak4104_spi_probe(struct spi_device *spi)
 {
 	struct ak4104_private *ak4104;
+	unsigned int val;
 	int ret;
 
 	spi->bits_per_word = 8;
@@ -266,17 +202,41 @@ static int ak4104_spi_probe(struct spi_device *spi)
 	if (ak4104 == NULL)
 		return -ENOMEM;
 
-	ak4104->control_data = spi;
-	ak4104->control_type = SND_SOC_SPI;
+	ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap);
+	if (IS_ERR(ak4104->regmap)) {
+		ret = PTR_ERR(ak4104->regmap);
+		return ret;
+	}
+
+	/* read the 'reserved' register - according to the datasheet, it
+	 * should contain 0x5b. Not a good way to verify the presence of
+	 * the device, but there is no hardware ID register. */
+	ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
+	if (ret != 0)
+		goto err;
+	if (val != AK4104_RESERVED_VAL) {
+		ret = -ENODEV;
+		goto err;
+	}
+
 	spi_set_drvdata(spi, ak4104);
 
 	ret = snd_soc_register_codec(&spi->dev,
 			&soc_codec_device_ak4104, &ak4104_dai, 1);
+	if (ret != 0)
+		goto err;
+
+	return 0;
+
+err:
+	regmap_exit(ak4104->regmap);
 	return ret;
 }
 
 static int __devexit ak4104_spi_remove(struct spi_device *spi)
 {
+	struct ak4104_private *ak4101 = spi_get_drvdata(spi);
+	regmap_exit(ak4101->regmap);
 	snd_soc_unregister_codec(&spi->dev);
 	return 0;
 }
@@ -290,17 +250,7 @@ static struct spi_driver ak4104_spi_driver = {
 	.remove = __devexit_p(ak4104_spi_remove),
 };
 
-static int __init ak4104_init(void)
-{
-	return spi_register_driver(&ak4104_spi_driver);
-}
-module_init(ak4104_init);
-
-static void __exit ak4104_exit(void)
-{
-	spi_unregister_driver(&ak4104_spi_driver);
-}
-module_exit(ak4104_exit);
+module_spi_driver(ak4104_spi_driver);
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
 MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver");
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 9e809e05d06644aa52fb11bf4ad96867c5c63aef..838ae8b22b500f8461f2baa151f4164d303ec85d 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -18,6 +18,7 @@
 #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>
@@ -27,24 +28,43 @@
 
 #include "ak4535.h"
 
-#define AK4535_VERSION "0.3"
-
 /* codec private data */
 struct ak4535_priv {
+	struct regmap *regmap;
 	unsigned int sysclk;
-	enum snd_soc_control_type control_type;
 };
 
 /*
  * ak4535 register cache
  */
-static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
-	0x00, 0x80, 0x00, 0x03,
-	0x02, 0x00, 0x11, 0x01,
-	0x00, 0x40, 0x36, 0x10,
-	0x00, 0x00, 0x57, 0x00,
+static const struct reg_default ak4535_reg_defaults[] = {
+	{ 0, 0x00 },
+	{ 1, 0x80 },
+	{ 2, 0x00 },
+	{ 3, 0x03 },
+	{ 4, 0x02 },
+	{ 5, 0x00 },
+	{ 6, 0x11 },
+	{ 7, 0x01 },
+	{ 8, 0x00 },
+	{ 9, 0x40 },
+	{ 10, 0x36 },
+	{ 11, 0x10 },
+	{ 12, 0x00 },
+	{ 13, 0x00 },
+	{ 14, 0x57 },
 };
 
+static bool ak4535_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AK4535_STATUS:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
 static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"};
 static const char *ak4535_hp_out[] = {"Stereo", "Mono"};
@@ -372,9 +392,8 @@ static int ak4535_probe(struct snd_soc_codec *codec)
 	struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
-	printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
-
-	ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4535->control_type);
+	codec->control_data = ak4535->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;
@@ -382,7 +401,7 @@ static int ak4535_probe(struct snd_soc_codec *codec)
 	/* power on device */
 	ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	snd_soc_add_controls(codec, ak4535_snd_controls,
+	snd_soc_add_codec_controls(codec, ak4535_snd_controls,
 				ARRAY_SIZE(ak4535_snd_controls));
 	return 0;
 }
@@ -394,22 +413,30 @@ static int ak4535_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
+static const struct regmap_config ak4535_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = AK4535_STATUS,
+	.volatile_reg = ak4535_volatile,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = ak4535_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(ak4535_reg_defaults),
+};
+
 static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
 	.probe =	ak4535_probe,
 	.remove =	ak4535_remove,
 	.suspend =	ak4535_suspend,
 	.resume =	ak4535_resume,
 	.set_bias_level = ak4535_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(ak4535_reg),
-	.reg_word_size = sizeof(u8),
-	.reg_cache_default = ak4535_reg,
 	.dapm_widgets = ak4535_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets),
 	.dapm_routes = ak4535_audio_map,
 	.num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
@@ -421,17 +448,29 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
 	if (ak4535 == NULL)
 		return -ENOMEM;
 
+	ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+	if (IS_ERR(ak4535->regmap)) {
+		ret = PTR_ERR(ak4535->regmap);
+		dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+		return ret;
+	}
+
 	i2c_set_clientdata(i2c, ak4535);
-	ak4535->control_type = SND_SOC_I2C;
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_ak4535, &ak4535_dai, 1);
+	if (ret != 0)
+		regmap_exit(ak4535->regmap);
+
 	return ret;
 }
 
 static __devexit int ak4535_i2c_remove(struct i2c_client *client)
 {
+	struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
+
 	snd_soc_unregister_codec(&client->dev);
+	regmap_exit(ak4535->regmap);
 	return 0;
 }
 
@@ -443,36 +482,15 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
 
 static struct i2c_driver ak4535_i2c_driver = {
 	.driver = {
-		.name = "ak4535-codec",
+		.name = "ak4535",
 		.owner = THIS_MODULE,
 	},
 	.probe =    ak4535_i2c_probe,
 	.remove =   __devexit_p(ak4535_i2c_remove),
 	.id_table = ak4535_i2c_id,
 };
-#endif
 
-static int __init ak4535_modinit(void)
-{
-	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	ret = i2c_add_driver(&ak4535_i2c_driver);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
-		       ret);
-	}
-#endif
-	return ret;
-}
-module_init(ak4535_modinit);
-
-static void __exit ak4535_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	i2c_del_driver(&ak4535_i2c_driver);
-#endif
-}
-module_exit(ak4535_exit);
+module_i2c_driver(ak4535_i2c_driver);
 
 MODULE_DESCRIPTION("Soc AK4535 driver");
 MODULE_AUTHOR("Richard Purdie");
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
index 0431e5f634a2440c8ef9f0206fe1c0959a6cd553..402de1d274bf8ac426b07c84fe2dde4d8f06250f 100644
--- a/sound/soc/codecs/ak4535.h
+++ b/sound/soc/codecs/ak4535.h
@@ -34,6 +34,4 @@
 #define AK4535_VOL		0xe
 #define AK4535_STATUS		0xf
 
-#define AK4535_CACHEREGNUM 	0x10
-
 #endif
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 278c0a0575f5596b5fe4249759c34202a3b02be5..f8e10ced244a6d4f36b6ab964bf39f54579da91e 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -477,7 +477,7 @@ static int ak4642_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	snd_soc_add_controls(codec, ak4642_snd_controls,
+	snd_soc_add_codec_controls(codec, ak4642_snd_controls,
 			     ARRAY_SIZE(ak4642_snd_controls));
 
 	ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index a53b152e6a07a529fc4e1298fc33bc4ccb3abdb2..5fb7c2a80e6daa5e8e68948a09b95a852fba778e 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -628,7 +628,7 @@ static int ak4671_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	snd_soc_add_controls(codec, ak4671_snd_controls,
+	snd_soc_add_codec_controls(codec, ak4671_snd_controls,
 			     ARRAY_SIZE(ak4671_snd_controls));
 
 	ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index 3feee569ceea1bacab11ac78ad6b83bbf01bab7b..d47b62ddb210dbf68b5eeb4b4e0dc4abadc5556d 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -925,22 +925,22 @@ static int alc5623_probe(struct snd_soc_codec *codec)
 
 	switch (alc5623->id) {
 	case 0x21:
-		snd_soc_add_controls(codec, alc5621_vol_snd_controls,
+		snd_soc_add_codec_controls(codec, alc5621_vol_snd_controls,
 			ARRAY_SIZE(alc5621_vol_snd_controls));
 		break;
 	case 0x22:
-		snd_soc_add_controls(codec, alc5622_vol_snd_controls,
+		snd_soc_add_codec_controls(codec, alc5622_vol_snd_controls,
 			ARRAY_SIZE(alc5622_vol_snd_controls));
 		break;
 	case 0x23:
-		snd_soc_add_controls(codec, alc5623_vol_snd_controls,
+		snd_soc_add_codec_controls(codec, alc5623_vol_snd_controls,
 			ARRAY_SIZE(alc5623_vol_snd_controls));
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	snd_soc_add_controls(codec, alc5623_snd_controls,
+	snd_soc_add_codec_controls(codec, alc5623_snd_controls,
 			ARRAY_SIZE(alc5623_snd_controls));
 
 	snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,
@@ -992,7 +992,7 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
  *    low  = 0x1a
  *    high = 0x1b
  */
-static int alc5623_i2c_probe(struct i2c_client *client,
+static __devinit int alc5623_i2c_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct alc5623_platform_data *pdata;
@@ -1059,7 +1059,7 @@ static int alc5623_i2c_probe(struct i2c_client *client,
 	return ret;
 }
 
-static int alc5623_i2c_remove(struct i2c_client *client)
+static __devexit int alc5623_i2c_remove(struct i2c_client *client)
 {
 	snd_soc_unregister_codec(&client->dev);
 	return 0;
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index 390e437d7c5e08ef75a8406b5572f245d90eaaeb..e2111e0ccad7eedad086e5bc791d690f86388a15 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -145,15 +145,14 @@ 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),
+	TLV_DB_RANGE_HEAD(2),
+	0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+	1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 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 DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 75, 0);
 
 static const struct snd_kcontrol_new alc5632_vol_snd_controls[] = {
 	/* left starts at bit 8, right at bit 0 */
@@ -176,26 +175,32 @@ static const struct snd_kcontrol_new alc5632_snd_controls[] = {
 			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",
+	SOC_SINGLE("Voice DAC Playback Switch",
+			ALC5632_VOICE_DAC_VOL, 12, 1, 1),
+	SOC_SINGLE_TLV("Phone Playback Volume",
 			ALC5632_PHONE_IN_VOL, 8, 31, 1, vol_tlv),
-	SOC_DOUBLE_TLV("LineIn Capture Volume",
+	SOC_DOUBLE_TLV("LineIn Playback 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",
+	SOC_SINGLE_TLV("Mic1 Playback Volume",
 			ALC5632_MIC_VOL, 8, 31, 1, vol_tlv),
-	SOC_SINGLE_TLV("Mic2 Capture Volume",
+	SOC_SINGLE_TLV("Mic2 Playback 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),
+			ALC5632_MIC_CTRL, 10, 3, 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_MIC_CTRL, 8, 3, 0, boost_tlv),
+	SOC_SINGLE_TLV("DMIC Boost Capture Volume",
 			ALC5632_DIGI_BOOST_CTRL, 0, 7, 0, dig_tlv),
+	SOC_SINGLE("DMIC En Capture Switch",
+			ALC5632_DIGI_BOOST_CTRL, 15, 1, 0),
+	SOC_SINGLE("DMIC PreFilter Capture Switch",
+			ALC5632_DIGI_BOOST_CTRL, 12, 1, 0),
 };
 
 /*
@@ -244,36 +249,48 @@ 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),
+SOC_DAPM_SINGLE("MIC12REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
+SOC_DAPM_SINGLE("LIL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
+SOC_DAPM_SINGLE("HPL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_L 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),
+SOC_DAPM_SINGLE("MIC12REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
+SOC_DAPM_SINGLE("LIR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
+SOC_DAPM_SINGLE("HPR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
 };
 
-static const char *alc5632_spk_n_sour_sel[] = {
+/* Dmic Mixer */
+static const struct snd_kcontrol_new alc5632_dmicl_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICL2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 7, 1, 1),
+};
+static const struct snd_kcontrol_new alc5632_dmicr_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICR2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 6, 1, 1),
+};
+
+static const char * const alc5632_spk_n_sour_sel[] = {
 		"RN/-R", "RP/+R", "LN/-R", "Mute"};
-static const char *alc5632_hpl_out_input_sel[] = {
+static const char * const alc5632_hpl_out_input_sel[] = {
 		"Vmid", "HP Left Mix"};
-static const char *alc5632_hpr_out_input_sel[] = {
+static const char * const alc5632_hpr_out_input_sel[] = {
 		"Vmid", "HP Right Mix"};
-static const char *alc5632_spkout_input_sel[] = {
+static const char * const alc5632_spkout_input_sel[] = {
 		"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
-static const char *alc5632_aux_out_input_sel[] = {
+static const char * const alc5632_aux_out_input_sel[] = {
 		"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+static const char * const alc5632_adcr_func_sel[] = {
+		"Stereo ADC", "Voice ADC"};
+static const char * const alc5632_i2s_out_sel[] = {
+		"ADC LR", "Voice Stereo Digital"};
 
 /* auxout output mux */
 static const struct soc_enum alc5632_aux_out_input_enum =
@@ -312,6 +329,17 @@ static const struct soc_enum alc5632_amp_enum =
 static const struct snd_kcontrol_new alc5632_amp_mux_controls =
 	SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
 
+/* ADC output select */
+static const struct soc_enum alc5632_adcr_func_enum =
+	SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel);
+static const struct snd_kcontrol_new alc5632_adcr_func_controls =
+	SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum);
+
+/* I2S out select */
+static const struct soc_enum alc5632_i2s_out_enum =
+	SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel);
+static const struct snd_kcontrol_new alc5632_i2s_out_controls =
+	SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum);
 
 static const struct snd_soc_dapm_widget alc5632_dapm_widgets[] = {
 /* Muxes */
@@ -325,6 +353,10 @@ 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),
+SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0,
+	&alc5632_adcr_func_controls),
+SND_SOC_DAPM_MUX("I2SOut Mux", ALC5632_PWR_MANAG_ADD1, 11, 0,
+	&alc5632_i2s_out_controls),
 
 /* output mixers */
 SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
@@ -343,6 +375,12 @@ SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2, 2, 0,
 SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2, 3, 0,
 	&alc5632_speaker_mixer_controls[0],
 	ARRAY_SIZE(alc5632_speaker_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICL Mix", SND_SOC_NOPM, 0, 0,
+	&alc5632_dmicl_mixer_controls[0],
+	ARRAY_SIZE(alc5632_dmicl_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICR Mix", SND_SOC_NOPM, 0, 0,
+	&alc5632_dmicr_mixer_controls[0],
+	ARRAY_SIZE(alc5632_dmicr_mixer_controls)),
 
 /* input mixers */
 SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2, 1, 0,
@@ -352,20 +390,28 @@ 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_AIF_IN("AIFRXL", "Left HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXR", "Right HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("VAIFRX", "Voice Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("VAIFTX", "Voice Capture", 0, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_DAC("Voice DAC", NULL, ALC5632_PWR_MANAG_ADD2, 10, 0),
+SND_SOC_DAPM_DAC("Left DAC", NULL, ALC5632_PWR_MANAG_ADD2, 9, 0),
+SND_SOC_DAPM_DAC("Right DAC", NULL, ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_ADC("Left ADC", NULL, ALC5632_PWR_MANAG_ADD2, 7, 0),
+SND_SOC_DAPM_ADC("Right ADC", NULL, ALC5632_PWR_MANAG_ADD2, 6, 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_MIXER("Voice Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("ADCLR", SND_SOC_NOPM, 0, 0, NULL, 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),
@@ -393,10 +439,12 @@ 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("DMICDAT"),
 SND_SOC_DAPM_INPUT("MIC1"),
 SND_SOC_DAPM_INPUT("MIC2"),
 SND_SOC_DAPM_VMID("Vmid"),
@@ -404,6 +452,10 @@ SND_SOC_DAPM_VMID("Vmid"),
 
 
 static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
+	/* Playback streams */
+	{"Left DAC", NULL, "AIFRXL"},
+	{"Right DAC", NULL, "AIFRXR"},
+
 	/* virtual mixer - mixes left & right channels */
 	{"I2S Mix",	NULL,	"Left DAC"},
 	{"I2S Mix",	NULL,	"Right DAC"},
@@ -426,9 +478,12 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
 	{"HP Mix",	"PHONE2HP Playback Switch",	"Phone Mix"},
 	{"HP Mix",	"MIC12HP Playback Switch",	"MIC1 PGA"},
 	{"HP Mix",	"MIC22HP Playback Switch",	"MIC2 PGA"},
-
+	{"HP Mix", "VOICE2HP Playback Switch",	"Voice Mix"},
 	{"HPR Mix", "DACR2HP Playback Switch",	"DAC Right Channel"},
 	{"HPL Mix", "DACL2HP Playback Switch",	"DAC Left Channel"},
+	{"HPOut Mix", NULL, "HP Mix"},
+	{"HPOut Mix", NULL, "HPR Mix"},
+	{"HPOut Mix", NULL, "HPL Mix"},
 
 	/* speaker mixer */
 	{"Speaker Mix", "LI2SPK Playback Switch",	"Line Mix"},
@@ -436,35 +491,34 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
 	{"Speaker Mix", "MIC12SPK Playback Switch",	"MIC1 PGA"},
 	{"Speaker Mix", "MIC22SPK Playback Switch",	"MIC2 PGA"},
 	{"Speaker Mix", "DAC2SPK Playback Switch",	"DAC Left Channel"},
-
-
+	{"Speaker Mix", "VOICE2SPK Playback Switch",	"Voice Mix"},
 
 	/* 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"},
+	{"Mono Mix", "VOICE2MONO Playback Switch",	"Voice Mix"},
 
 	/* 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"},
+	{"Left Capture Mix", "LIL2REC Capture Switch", "LINEINL"},
+	{"Left Capture Mix", "PH2REC_L Capture Switch", "PHONEN"},
+	{"Left Capture Mix", "MIC12REC_L Capture Switch", "MIC1 Pre Amp"},
+	{"Left Capture Mix", "MIC22REC_L Capture Switch", "MIC2 Pre Amp"},
+	{"Left Capture Mix", "HPL2REC Capture Switch", "HPL Mix"},
+	{"Left Capture Mix", "SPK2REC_L Capture Switch", "Speaker Mix"},
+	{"Left Capture Mix", "MONO2REC_L 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"},
+	{"Right Capture Mix", "LIR2REC Capture Switch", "LINEINR"},
+	{"Right Capture Mix", "PH2REC_R Capture Switch", "PHONEP"},
+	{"Right Capture Mix", "MIC12REC_R Capture Switch", "MIC1 Pre Amp"},
+	{"Right Capture Mix", "MIC22REC_R Capture Switch", "MIC2 Pre Amp"},
+	{"Right Capture Mix", "HPR2REC Capture Switch", "HPR Mix"},
+	{"Right Capture Mix", "SPK2REC_R Capture Switch", "Speaker Mix"},
+	{"Right Capture Mix", "MONO2REC_R Capture Switch", "Mono Mix"},
 
 	/* headphone left mux */
 	{"Left Headphone Mux", "HP Left Mix",		"HPL Mix"},
@@ -504,10 +558,30 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
 
 	/* left ADC */
 	{"Left ADC", NULL,				"Left Capture Mix"},
+	{"DMICL Mix", "DMICL2ADC Capture Switch", "DMICDAT"},
+	{"Left ADC", NULL,				"DMICL Mix"},
+	{"ADCLR", NULL,					"Left ADC"},
 
 	/* right ADC */
-	{"Right ADC", NULL,				"Right Capture Mix"},
-
+	{"Right ADC", NULL, "Right Capture Mix"},
+	{"DMICR Mix", "DMICR2ADC Capture Switch", "DMICDAT"},
+	{"Right ADC", NULL, "DMICR Mix"},
+	{"ADCR Mux", "Stereo ADC", "Right ADC"},
+	{"ADCR Mux", "Voice ADC", "Right ADC"},
+	{"ADCLR", NULL, "ADCR Mux"},
+	{"VAIFTX", NULL, "ADCR Mux"},
+
+	/* Digital I2S out */
+	{"I2SOut Mux", "ADC LR", "ADCLR"},
+	{"I2SOut Mux", "Voice Stereo Digital", "VAIFRX"},
+	{"AIFTXL", NULL, "I2SOut Mux"},
+	{"AIFTXR", NULL, "I2SOut Mux"},
+
+	/* Voice Mix */
+	{"Voice DAC", NULL, "VAIFRX"},
+	{"Voice Mix", NULL, "Voice DAC"},
+
+	/* Speaker Output */
 	{"SpeakerOut N Mux", "RN/-R",			"Left Speaker"},
 	{"SpeakerOut N Mux", "RP/+R",			"Left Speaker"},
 	{"SpeakerOut N Mux", "LN/-R",			"Left Speaker"},
@@ -714,6 +788,7 @@ static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
 
 	switch (freq) {
+	case  4096000:
 	case  8192000:
 	case 11289600:
 	case 12288000:
@@ -994,7 +1069,7 @@ static int alc5632_probe(struct snd_soc_codec *codec)
 
 	switch (alc5632->id) {
 	case 0x5c:
-		snd_soc_add_controls(codec, alc5632_vol_snd_controls,
+		snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls,
 			ARRAY_SIZE(alc5632_vol_snd_controls));
 		break;
 	default:
@@ -1109,7 +1184,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
 	return ret;
 }
 
-static int alc5632_i2c_remove(struct i2c_client *client)
+static __devexit int alc5632_i2c_remove(struct i2c_client *client)
 {
 	struct alc5632_priv *alc5632 = i2c_get_clientdata(client);
 	snd_soc_unregister_codec(&client->dev);
diff --git a/sound/soc/codecs/alc5632.h b/sound/soc/codecs/alc5632.h
index 357651ec074e6e2c5f0110c86f65822023b34d6b..1b5bda594ea3a33fb2b63ee704c354a57ecee57c 100644
--- a/sound/soc/codecs/alc5632.h
+++ b/sound/soc/codecs/alc5632.h
@@ -51,6 +51,7 @@
 #define ALC5632_ADC_REC_MONOMIX			(1 << 0)
 
 #define ALC5632_VOICE_DAC_VOL			0x18 /* voice dac vol */
+#define ALC5632_I2S_OUT_CTL				0x1A /* undocumented reg. found in path scheme */
 /* ALC5632_OUTPUT_MIXER_CTRL :			*/
 /* same remark as for reg 2 line vs speaker	*/
 #define ALC5632_OUTPUT_MIXER_CTRL		0x1C /* out mix ctrl */
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 4854b472d5fdb98ca5d6cae18863286a17f3b408..064cd6a935163ebf4fa0619b80f67154e1733528 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -38,8 +38,6 @@
 #include <sound/soc.h>
 #include <sound/initval.h>
 
-#include <mach/dm365.h>
-
 static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
 						unsigned int reg)
 {
@@ -159,7 +157,7 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
 	codec->control_data = davinci_vc;
 
 	/* Set controls */
-	snd_soc_add_controls(codec, cq93vc_snd_controls,
+	snd_soc_add_codec_controls(codec, cq93vc_snd_controls,
 			     ARRAY_SIZE(cq93vc_snd_controls));
 
 	/* Off, with power on */
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 055536645da917e15308cd4abb17d13f2a43bf67..1d672f528662cb162fc99a36b6946026a2dfdb09 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -521,7 +521,7 @@ static int cs4270_probe(struct snd_soc_codec *codec)
 	}
 
 	/* Add the non-DAPM controls */
-	ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+	ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls,
 				ARRAY_SIZE(cs4270_snd_controls));
 	if (ret < 0) {
 		dev_err(codec->dev, "failed to add controls\n");
@@ -715,7 +715,7 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
  */
 static struct i2c_driver cs4270_i2c_driver = {
 	.driver = {
-		.name = "cs4270-codec",
+		.name = "cs4270",
 		.owner = THIS_MODULE,
 	},
 	.id_table = cs4270_id,
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index f6fe846b6a6c3d76f8778140261c96b0ed7a65eb..bf7141280a747ab25b311c083b06b82bc8e7ad9e 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -513,7 +513,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
 	/* Power-up sequence requires 85 uS */
 	udelay(85);
 
-	return snd_soc_add_controls(codec, cs4271_snd_controls,
+	return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
 		ARRAY_SIZE(cs4271_snd_controls));
 }
 
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index ab38e93c3543220d7ea55b33c0172487d00783cd..7843711729bcd79ce0f9d8938904199d7c056dd9 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -17,6 +17,7 @@
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <sound/pcm.h>
@@ -626,41 +627,82 @@ static const struct snd_soc_dapm_route da7210_audio_map[] = {
 
 /* Codec private data */
 struct da7210_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 };
 
-/*
- * Register cache
- */
-static const u8 da7210_reg[] = {
-	0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R0  - R7  */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,	/* R8  - RF  */
-	0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x54,	/* R10 - R17 */
-	0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R18 - R1F */
-	0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00,	/* R20 - R27 */
-	0x04, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x40, 0x00,	/* R28 - R2F */
-	0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,	/* R30 - R37 */
-	0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00,	/* R38 - R3F */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R40 - R4F */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R48 - R4F */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R50 - R57 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R58 - R5F */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R60 - R67 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R68 - R6F */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R70 - R77 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x00,	/* R78 - R7F */
-	0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,	/* R80 - R87 */
-	0x00,						/* R88       */
+static struct reg_default da7210_reg_defaults[] = {
+	{ 0x01, 0x11 },
+	{ 0x03, 0x00 },
+	{ 0x04, 0x00 },
+	{ 0x05, 0x00 },
+	{ 0x06, 0x00 },
+	{ 0x07, 0x00 },
+	{ 0x08, 0x00 },
+	{ 0x09, 0x00 },
+	{ 0x0a, 0x00 },
+	{ 0x0b, 0x00 },
+	{ 0x0c, 0x00 },
+	{ 0x0d, 0x00 },
+	{ 0x0e, 0x00 },
+	{ 0x0f, 0x08 },
+	{ 0x10, 0x00 },
+	{ 0x11, 0x00 },
+	{ 0x12, 0x00 },
+	{ 0x13, 0x00 },
+	{ 0x14, 0x08 },
+	{ 0x15, 0x10 },
+	{ 0x16, 0x10 },
+	{ 0x17, 0x54 },
+	{ 0x18, 0x40 },
+	{ 0x19, 0x00 },
+	{ 0x1a, 0x00 },
+	{ 0x1b, 0x00 },
+	{ 0x1c, 0x00 },
+	{ 0x1d, 0x00 },
+	{ 0x1e, 0x00 },
+	{ 0x1f, 0x00 },
+	{ 0x20, 0x00 },
+	{ 0x21, 0x00 },
+	{ 0x22, 0x00 },
+	{ 0x23, 0x02 },
+	{ 0x24, 0x00 },
+	{ 0x25, 0x76 },
+	{ 0x26, 0x00 },
+	{ 0x27, 0x00 },
+	{ 0x28, 0x04 },
+	{ 0x29, 0x00 },
+	{ 0x2a, 0x00 },
+	{ 0x2b, 0x30 },
+	{ 0x2c, 0x2A },
+	{ 0x83, 0x00 },
+	{ 0x84, 0x00 },
+	{ 0x85, 0x00 },
+	{ 0x86, 0x00 },
+	{ 0x87, 0x00 },
+	{ 0x88, 0x00 },
 };
 
-static int da7210_volatile_register(struct snd_soc_codec *codec,
+static bool da7210_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case DA7210_A_HID_UNLOCK:
+	case DA7210_A_TEST_UNLOCK:
+	case DA7210_A_PLL1:
+	case DA7210_A_CP_MODE:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static bool da7210_volatile_register(struct device *dev,
 				    unsigned int reg)
 {
 	switch (reg) {
 	case DA7210_STATUS:
-		return 1;
+		return true;
 	default:
-		return 0;
+		return false;
 	}
 }
 
@@ -866,7 +908,8 @@ static int da7210_probe(struct snd_soc_codec *codec)
 
 	dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 8, da7210->control_type);
+	codec->control_data = da7210->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;
@@ -983,12 +1026,14 @@ static int da7210_probe(struct snd_soc_codec *codec)
 	snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
 
 	/* As suggested by Dialog */
-	snd_soc_write(codec, DA7210_A_HID_UNLOCK,	0x8B); /* unlock */
-	snd_soc_write(codec, DA7210_A_TEST_UNLOCK,	0xB4);
-	snd_soc_write(codec, DA7210_A_PLL1,		0x01);
-	snd_soc_write(codec, DA7210_A_CP_MODE,		0x7C);
-	snd_soc_write(codec, DA7210_A_HID_UNLOCK,	0x00); /* re-lock */
-	snd_soc_write(codec, DA7210_A_TEST_UNLOCK,	0x00);
+	/* unlock */
+	regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK,	0x8B);
+	regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK,	0xB4);
+	regmap_write(da7210->regmap, DA7210_A_PLL1,		0x01);
+	regmap_write(da7210->regmap, DA7210_A_CP_MODE,		0x7C);
+	/* re-lock */
+	regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK,	0x00);
+	regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK,	0x00);
 
 	/* Activate all enabled subsystem */
 	snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
@@ -1000,10 +1045,6 @@ static int da7210_probe(struct snd_soc_codec *codec)
 
 static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
 	.probe			= da7210_probe,
-	.reg_cache_size		= ARRAY_SIZE(da7210_reg),
-	.reg_word_size		= sizeof(u8),
-	.reg_cache_default	= da7210_reg,
-	.volatile_register	= da7210_volatile_register,
 
 	.controls		= da7210_snd_controls,
 	.num_controls		= ARRAY_SIZE(da7210_snd_controls),
@@ -1014,6 +1055,17 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
 	.num_dapm_routes	= ARRAY_SIZE(da7210_audio_map),
 };
 
+static struct regmap_config da7210_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.reg_defaults = da7210_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(da7210_reg_defaults),
+	.volatile_reg = da7210_volatile_register,
+	.readable_reg = da7210_readable_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
 			   	      const struct i2c_device_id *id)
@@ -1027,16 +1079,34 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, da7210);
-	da7210->control_type = SND_SOC_I2C;
+
+	da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap);
+	if (IS_ERR(da7210->regmap)) {
+		ret = PTR_ERR(da7210->regmap);
+		dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
 
 	ret =  snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_da7210, &da7210_dai, 1);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+		goto err_regmap;
+	}
+	return ret;
+
+err_regmap:
+	regmap_exit(da7210->regmap);
+
 	return ret;
 }
 
 static int __devexit da7210_i2c_remove(struct i2c_client *client)
 {
+	struct da7210_priv *da7210 = i2c_get_clientdata(client);
+
 	snd_soc_unregister_codec(&client->dev);
+	regmap_exit(da7210->regmap);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 319039240e0fafe25412110e81fc548b011df072..ba4fafb93e5624d2aff10f6e20cf81ad34066ea9 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -179,7 +179,7 @@ static int lm4857_probe(struct snd_soc_codec *codec)
 
 	codec->control_data = lm4857->i2c;
 
-	ret = snd_soc_add_controls(codec, lm4857_controls,
+	ret = snd_soc_add_codec_controls(codec, lm4857_controls,
 			ARRAY_SIZE(lm4857_controls));
 	if (ret)
 		return ret;
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
new file mode 100644
index 0000000000000000000000000000000000000000..17b3ec2d05cb1ebade50fe27eb95b4a62dfbfc20
--- /dev/null
+++ b/sound/soc/codecs/max9768.c
@@ -0,0 +1,247 @@
+/*
+ * MAX9768 AMP driver
+ *
+ * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/max9768.h>
+
+/* "Registers" */
+#define MAX9768_VOL 0
+#define MAX9768_CTRL 3
+
+/* Commands */
+#define MAX9768_CTRL_PWM 0x15
+#define MAX9768_CTRL_FILTERLESS 0x16
+
+struct max9768 {
+	struct regmap *regmap;
+	int mute_gpio;
+	int shdn_gpio;
+	u32 flags;
+};
+
+static struct reg_default max9768_default_regs[] = {
+	{ 0, 0 },
+	{ 3,  MAX9768_CTRL_FILTERLESS},
+};
+
+static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+	int val = gpio_get_value_cansleep(max9768->mute_gpio);
+
+	ucontrol->value.integer.value[0] = !val;
+
+	return 0;
+}
+
+static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+
+	gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static const unsigned int volume_tlv[] = {
+	TLV_DB_RANGE_HEAD(43),
+	0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0),
+	1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0),
+	2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0),
+	3, 3, TLV_DB_SCALE_ITEM(-8680, 0, 0),
+	4, 4, TLV_DB_SCALE_ITEM(-8430, 0, 0),
+	5, 5, TLV_DB_SCALE_ITEM(-8080, 0, 0),
+	6, 6, TLV_DB_SCALE_ITEM(-7830, 0, 0),
+	7, 7, TLV_DB_SCALE_ITEM(-7470, 0, 0),
+	8, 8, TLV_DB_SCALE_ITEM(-7220, 0, 0),
+	9, 9, TLV_DB_SCALE_ITEM(-6870, 0, 0),
+	10, 10, TLV_DB_SCALE_ITEM(-6620, 0, 0),
+	11, 11, TLV_DB_SCALE_ITEM(-6270, 0, 0),
+	12, 12, TLV_DB_SCALE_ITEM(-6020, 0, 0),
+	13, 13, TLV_DB_SCALE_ITEM(-5670, 0, 0),
+	14, 14, TLV_DB_SCALE_ITEM(-5420, 0, 0),
+	15, 17, TLV_DB_SCALE_ITEM(-5060, 250, 0),
+	18, 18, TLV_DB_SCALE_ITEM(-4370, 0, 0),
+	19, 19, TLV_DB_SCALE_ITEM(-4210, 0, 0),
+	20, 20, TLV_DB_SCALE_ITEM(-3960, 0, 0),
+	21, 21, TLV_DB_SCALE_ITEM(-3760, 0, 0),
+	22, 22, TLV_DB_SCALE_ITEM(-3600, 0, 0),
+	23, 23, TLV_DB_SCALE_ITEM(-3340, 0, 0),
+	24, 24, TLV_DB_SCALE_ITEM(-3150, 0, 0),
+	25, 25, TLV_DB_SCALE_ITEM(-2980, 0, 0),
+	26, 26, TLV_DB_SCALE_ITEM(-2720, 0, 0),
+	27, 27, TLV_DB_SCALE_ITEM(-2520, 0, 0),
+	28, 30, TLV_DB_SCALE_ITEM(-2350, 190, 0),
+	31, 31, TLV_DB_SCALE_ITEM(-1750, 0, 0),
+	32, 34, TLV_DB_SCALE_ITEM(-1640, 100, 0),
+	35, 37, TLV_DB_SCALE_ITEM(-1310, 110, 0),
+	38, 39, TLV_DB_SCALE_ITEM(-990, 100, 0),
+	40, 40, TLV_DB_SCALE_ITEM(-710, 0, 0),
+	41, 41, TLV_DB_SCALE_ITEM(-600, 0, 0),
+	42, 42, TLV_DB_SCALE_ITEM(-500, 0, 0),
+	43, 43, TLV_DB_SCALE_ITEM(-340, 0, 0),
+	44, 44, TLV_DB_SCALE_ITEM(-190, 0, 0),
+	45, 45, TLV_DB_SCALE_ITEM(-50, 0, 0),
+	46, 46, TLV_DB_SCALE_ITEM(50, 0, 0),
+	47, 50, TLV_DB_SCALE_ITEM(120, 40, 0),
+	51, 57, TLV_DB_SCALE_ITEM(290, 50, 0),
+	58, 58, TLV_DB_SCALE_ITEM(650, 0, 0),
+	59, 62, TLV_DB_SCALE_ITEM(700, 60, 0),
+	63, 63, TLV_DB_SCALE_ITEM(950, 0, 0),
+};
+
+static const struct snd_kcontrol_new max9768_volume[] = {
+	SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv),
+};
+
+static const struct snd_kcontrol_new max9768_mute[] = {
+	SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio),
+};
+
+static int max9768_probe(struct snd_soc_codec *codec)
+{
+	struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	codec->control_data = max9768->regmap;
+	ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP);
+	if (ret)
+		return ret;
+
+	if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) {
+		ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM);
+		if (ret)
+			return ret;
+	}
+
+	if (gpio_is_valid(max9768->mute_gpio)) {
+		ret = snd_soc_add_codec_controls(codec, max9768_mute,
+				ARRAY_SIZE(max9768_mute));
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver max9768_codec_driver = {
+	.probe = max9768_probe,
+	.controls = max9768_volume,
+	.num_controls = ARRAY_SIZE(max9768_volume),
+};
+
+static const struct regmap_config max9768_i2c_regmap_config = {
+	.reg_bits = 2,
+	.val_bits = 6,
+	.max_register = 3,
+	.reg_defaults = max9768_default_regs,
+	.num_reg_defaults = ARRAY_SIZE(max9768_default_regs),
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit max9768_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	struct max9768 *max9768;
+	struct max9768_pdata *pdata = client->dev.platform_data;
+	int err;
+
+	max9768 = devm_kzalloc(&client->dev, sizeof(*max9768), GFP_KERNEL);
+	if (!max9768)
+		return -ENOMEM;
+
+	if (pdata) {
+		/* Mute on powerup to avoid clicks */
+		err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute");
+		max9768->mute_gpio = err ?: pdata->mute_gpio;
+
+		/* Activate chip by releasing shutdown, enables I2C */
+		err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown");
+		max9768->shdn_gpio = err ?: pdata->shdn_gpio;
+
+		max9768->flags = pdata->flags;
+	} else {
+		max9768->shdn_gpio = -EINVAL;
+		max9768->mute_gpio = -EINVAL;
+	}
+
+	i2c_set_clientdata(client, max9768);
+
+	max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config);
+	if (IS_ERR(max9768->regmap)) {
+		err = PTR_ERR(max9768->regmap);
+		goto err_gpio_free;
+	}
+
+	err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
+	if (err)
+		goto err_regmap_free;
+
+	return 0;
+
+ err_regmap_free:
+	regmap_exit(max9768->regmap);
+ err_gpio_free:
+	if (gpio_is_valid(max9768->shdn_gpio))
+		gpio_free(max9768->shdn_gpio);
+	if (gpio_is_valid(max9768->mute_gpio))
+		gpio_free(max9768->mute_gpio);
+
+	return err;
+}
+
+static int __devexit max9768_i2c_remove(struct i2c_client *client)
+{
+	struct max9768 *max9768 = i2c_get_clientdata(client);
+
+	snd_soc_unregister_codec(&client->dev);
+	regmap_exit(max9768->regmap);
+
+	if (gpio_is_valid(max9768->shdn_gpio))
+		gpio_free(max9768->shdn_gpio);
+	if (gpio_is_valid(max9768->mute_gpio))
+		gpio_free(max9768->mute_gpio);
+
+	return 0;
+}
+
+static const struct i2c_device_id max9768_i2c_id[] = {
+	{ "max9768", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max9768_i2c_id);
+
+static struct i2c_driver max9768_i2c_driver = {
+	.driver = {
+		.name = "max9768",
+		.owner = THIS_MODULE,
+	},
+	.probe = max9768_i2c_probe,
+	.remove = __devexit_p(max9768_i2c_remove),
+	.id_table = max9768_i2c_id,
+};
+module_i2c_driver(max9768_i2c_driver);
+
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("ASoC MAX9768 amplifier driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 006efcfe6dda84b486330bb79cdb0d36b8389efe..af7324b79dd0a8c8ae900277a7bf4abf2a98995a 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -1908,7 +1908,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
        max98088->eq_enum.texts = max98088->eq_texts;
        max98088->eq_enum.max = max98088->eq_textcnt;
 
-       ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+       ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
        if (ret != 0)
                dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
 }
@@ -2030,7 +2030,7 @@ static int max98088_probe(struct snd_soc_codec *codec)
 
        max98088_handle_pdata(codec);
 
-       snd_soc_add_controls(codec, max98088_snd_controls,
+       snd_soc_add_codec_controls(codec, max98088_snd_controls,
                             ARRAY_SIZE(max98088_snd_controls));
 
 err_access:
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index fcfa7497d7b74aac4777def9e7b7d186ec7c58ef..0bb511a0388de84cfec32f1794dd0a77be63ba1d 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -1284,7 +1284,7 @@ static const struct snd_soc_dapm_route max98095_audio_map[] = {
 
 static int max98095_add_widgets(struct snd_soc_codec *codec)
 {
-	snd_soc_add_controls(codec, max98095_snd_controls,
+	snd_soc_add_codec_controls(codec, max98095_snd_controls,
 			     ARRAY_SIZE(max98095_snd_controls));
 
 	return 0;
@@ -1984,7 +1984,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
 	max98095->eq_enum.texts = max98095->eq_texts;
 	max98095->eq_enum.max = max98095->eq_textcnt;
 
-	ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+	ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
 	if (ret != 0)
 		dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
 }
@@ -2139,7 +2139,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
 	max98095->bq_enum.texts = max98095->bq_texts;
 	max98095->bq_enum.max = max98095->bq_textcnt;
 
-	ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+	ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
 	if (ret != 0)
 		dev_err(codec->dev, "Failed to add Biquad control: %d\n", ret);
 }
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index dcf6f2a1600ae5726a60d0a7e11ef6e53d57d466..3a2ba3d8fd6de13ec21f8e5b6ed67df85af77256 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -253,7 +253,7 @@ static const struct snd_kcontrol_new max9877_controls[] = {
 /* This function is called from ASoC machine driver */
 int max9877_add_controls(struct snd_soc_codec *codec)
 {
-	return snd_soc_add_controls(codec, max9877_controls,
+	return snd_soc_add_codec_controls(codec, max9877_controls,
 			ARRAY_SIZE(max9877_controls));
 }
 EXPORT_SYMBOL_GPL(max9877_add_controls);
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 7f4ba819a9f681dad3f962ae7c65c60d73b0f2a3..d1926266fe00f4ae10003d9c632a07e4dcd68862 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -227,7 +227,7 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
 };
 
 /* routes for sgtl5000 */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = {
 	{"Capture Mux", "LINE_IN", "LINE_IN"},	/* line_in --> adc_mux */
 	{"Capture Mux", "MIC_IN", "MIC_IN"},	/* mic_in --> adc_mux */
 
@@ -1248,7 +1248,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 	}
 
 	rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
-	dev_info(codec->dev, "sgtl5000 revision %d\n", rev);
+	dev_info(codec->dev, "sgtl5000 revision 0x%x\n", rev);
 
 	/*
 	 * workaround for revision 0x11 and later,
@@ -1353,15 +1353,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
 	if (ret)
 		goto err;
 
-	snd_soc_add_controls(codec, sgtl5000_snd_controls,
-			     ARRAY_SIZE(sgtl5000_snd_controls));
-
-	snd_soc_dapm_new_controls(&codec->dapm, sgtl5000_dapm_widgets,
-				  ARRAY_SIZE(sgtl5000_dapm_widgets));
-
-	snd_soc_dapm_add_routes(&codec->dapm, audio_map,
-				ARRAY_SIZE(audio_map));
-
 	snd_soc_dapm_new_widgets(&codec->dapm);
 
 	return 0;
@@ -1402,6 +1393,12 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
 	.reg_cache_step = 2,
 	.reg_cache_default = sgtl5000_regs,
 	.volatile_register = sgtl5000_volatile_register,
+	.controls = sgtl5000_snd_controls,
+	.num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
+	.dapm_widgets = sgtl5000_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets),
+	.dapm_routes = sgtl5000_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
 };
 
 static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index f99baa0b8c39133b5cbc342368b4ac98f79cb365..50dbdb9357ead627961f08a170d8430b99faca07 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -827,8 +827,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
 {
 	pr_debug("codec_probe called\n");
 
-	codec->dapm.idle_bias_off = 1;
-
 	/* PCM interface config
 	 * This sets the pcm rx slot conguration to max 6 slots
 	 * for max 4 dais (2 stereo and 2 mono)
@@ -871,7 +869,7 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
 	snd_soc_write(codec, SN95031_SSR2, 0x10);
 	snd_soc_write(codec, SN95031_SSR3, 0x40);
 
-	snd_soc_add_controls(codec, sn95031_snd_controls,
+	snd_soc_add_codec_controls(codec, sn95031_snd_controls,
 			     ARRAY_SIZE(sn95031_snd_controls));
 
 	return 0;
@@ -891,6 +889,7 @@ struct snd_soc_codec_driver sn95031_codec = {
 	.read		= sn95031_read,
 	.write		= sn95031_write,
 	.set_bias_level	= sn95031_set_vaud_bias,
+	.idle_bias_off	= true,
 	.dapm_widgets	= sn95031_dapm_widgets,
 	.num_dapm_widgets	= ARRAY_SIZE(sn95031_dapm_widgets),
 	.dapm_routes	= sn95031_audio_map,
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 333dd98af39ce538868d706a2281f2e7514152ab..de2b20544ceb01cb8ecbecaae507d6b33826e53f 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -548,7 +548,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
 	snd_soc_update_bits(codec, SSM2602_ROUT1V,
 			    ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
 
-	ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
+	ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls,
 			ARRAY_SIZE(ssm2602_snd_controls));
 	if (ret)
 		return ret;
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index cc0566c22ec12ecfcf3f67d486b6330fea448f47..982e437799a8e62aa8085a9d5b509fa4d8f8a387 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -355,7 +355,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)
 
 	stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
+	snd_soc_add_codec_controls(codec, stac9766_snd_ac97_controls,
 			     ARRAY_SIZE(stac9766_snd_ac97_controls));
 
 	return 0;
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index dfa41a96599b8c61884c04392c6a878e7e715372..16d55f91a6535e088dff5999ee9bae408999dd7e 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -593,7 +593,7 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
 
 	snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
 
-	snd_soc_add_controls(codec, tlv320aic23_snd_controls,
+	snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls,
 				ARRAY_SIZE(tlv320aic23_snd_controls));
 
 	return 0;
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index a038daec682bfba9dd6997b9acfbb4e0c4855ca2..802064b5030d0b910736ae05d5365941a9d0b74c 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -389,7 +389,7 @@ static int aic26_probe(struct snd_soc_codec *codec)
 
 	/* register controls */
 	dev_dbg(codec->dev, "Registering controls\n");
-	err = snd_soc_add_controls(codec, aic26_snd_controls,
+	err = snd_soc_add_codec_controls(codec, aic26_snd_controls,
 			ARRAY_SIZE(aic26_snd_controls));
 	WARN_ON(err < 0);
 
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 372b0b83bd9f191c104dd18dcff3a7756021f1dc..b0a73d37ed52b4dfb52fb97a367e03f37a6df291 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -671,7 +671,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
 	}
 
 	aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	snd_soc_add_controls(codec, aic32x4_snd_controls,
+	snd_soc_add_codec_controls(codec, aic32x4_snd_controls,
 			     ARRAY_SIZE(aic32x4_snd_controls));
 	aic32x4_add_widgets(codec);
 
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 492f22f8a4d7bd8ae30bbd2bb4ae6dae3488ccad..8d20f6ec20f35853b98e13735f5e540ef9c27c47 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -121,30 +121,6 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
 	0x00, 0x00, 0x02,	/* 100 */
 };
 
-/*
- * read from the aic3x register space. Only use for this function is if
- * wanting to read volatile bits from those registers that has both read-only
- * and read/write bits. All other cases should use snd_soc_read.
- */
-static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
-		      u8 *value)
-{
-	u8 *cache = codec->reg_cache;
-
-	if (codec->cache_only)
-		return -EINVAL;
-	if (reg >= AIC3X_CACHEREGNUM)
-		return -1;
-
-	codec->cache_bypass = 1;
-	*value = snd_soc_read(codec, reg);
-	codec->cache_bypass = 0;
-
-	cache[reg] = *value;
-
-	return 0;
-}
-
 #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_volsw, \
@@ -1185,25 +1161,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
 	return 0;
 }
 
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
-{
-	u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
-	u8 bit = gpio ? 3: 0;
-	u8 val = snd_soc_read(codec, reg) & ~(1 << bit);
-	snd_soc_write(codec, reg, val | (!!state << bit));
-}
-EXPORT_SYMBOL_GPL(aic3x_set_gpio);
-
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
-{
-	u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
-	u8 val = 0, bit = gpio ? 2 : 1;
-
-	aic3x_read(codec, reg, &val);
-	return (val >> bit) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_get_gpio);
-
 void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
 				 int headset_debounce, int button_debounce)
 {
@@ -1221,23 +1178,6 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
 
 	snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
 }
-EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
-
-int aic3x_headset_detected(struct snd_soc_codec *codec)
-{
-	u8 val = 0;
-	aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
-	return (val >> 4) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_headset_detected);
-
-int aic3x_button_pressed(struct snd_soc_codec *codec)
-{
-	u8 val = 0;
-	aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
-	return (val >> 5) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_button_pressed);
 
 #define AIC3X_RATES	SNDRV_PCM_RATE_8000_96000
 #define AIC3X_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
@@ -1377,7 +1317,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 
 	INIT_LIST_HEAD(&aic3x->list);
 	aic3x->codec = codec;
-	codec->dapm.idle_bias_off = 1;
 
 	ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
 	if (ret != 0) {
@@ -1426,10 +1365,10 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 			      (aic3x->setup->gpio_func[1] & 0xf) << 4);
 	}
 
-	snd_soc_add_controls(codec, aic3x_snd_controls,
+	snd_soc_add_codec_controls(codec, aic3x_snd_controls,
 			     ARRAY_SIZE(aic3x_snd_controls));
 	if (aic3x->model == AIC3X_MODEL_3007)
-		snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
+		snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
 
 	aic3x_add_widgets(codec);
 	list_add(&aic3x->list, &reset_list);
@@ -1471,6 +1410,7 @@ static int aic3x_remove(struct snd_soc_codec *codec)
 
 static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
 	.set_bias_level = aic3x_set_bias_level,
+	.idle_bias_off = true,
 	.reg_cache_size = ARRAY_SIZE(aic3x_reg),
 	.reg_word_size = sizeof(u8),
 	.reg_cache_default = aic3x_reg,
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 06a19784b162dddfd2f719d850deaf45d52dfef6..6f097fb60683e7b5605b38e373c7f1c75f4158c9 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -212,9 +212,6 @@
 /* Default input volume */
 #define DEFAULT_GAIN    0x20
 
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
-
 /* headset detection / button API */
 
 /* The AIC3x supports detection of stereo headsets (GND + left + right signal)
@@ -252,10 +249,4 @@ enum {
 #define AIC3X_BUTTON_DEBOUNCE_SHIFT 	0
 #define AIC3X_BUTTON_DEBOUNCE_MASK	3
 
-/* see the enums above for valid parameters to this function */
-void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
-				 int headset_debounce, int button_debounce);
-int aic3x_headset_detected(struct snd_soc_codec *codec);
-int aic3x_button_pressed(struct snd_soc_codec *codec);
-
 #endif /* _AIC3X_H */
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index f0aad26cdb3166ea18456cdfafec5bce35835ac5..4587ddd0fbf8c2e30fa01600dcbd17aed9545e90 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -806,8 +806,6 @@ static int dac33_startup(struct snd_pcm_substream *substream,
 	/* Stream started, save the substream pointer */
 	dac33->substream = substream;
 
-	snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
-
 	return 0;
 }
 
@@ -1397,7 +1395,6 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
 
 	codec->control_data = dac33->control_data;
 	codec->hw_write = (hw_write_t) i2c_master_send;
-	codec->dapm.idle_bias_off = 1;
 	dac33->codec = codec;
 
 	/* Read the tlv320dac33 ID registers */
@@ -1440,7 +1437,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
 
 	/* Only add the FIFO controls, if we have valid IRQ number */
 	if (dac33->irq >= 0)
-		snd_soc_add_controls(codec, dac33_mode_snd_controls,
+		snd_soc_add_codec_controls(codec, dac33_mode_snd_controls,
 				     ARRAY_SIZE(dac33_mode_snd_controls));
 
 err_power:
@@ -1478,6 +1475,7 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
 	.read = dac33_read_reg_cache,
 	.write = dac33_write_locked,
 	.set_bias_level = dac33_set_bias_level,
+	.idle_bias_off = true,
 	.reg_cache_size = ARRAY_SIZE(dac33_reg),
 	.reg_word_size = sizeof(u8),
 	.reg_cache_default = dac33_reg,
@@ -1515,7 +1513,9 @@ static struct snd_soc_dai_driver dac33_dai = {
 		.channels_min = 2,
 		.channels_max = 2,
 		.rates = DAC33_RATES,
-		.formats = DAC33_FORMATS,},
+		.formats = DAC33_FORMATS,
+		.sig_bits = 24,
+	},
 	.ops = &dac33_dai_ops,
 };
 
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 363b99dad8e9539e09cc29134e7d215243dddbc8..6fe4aa3ac54401da4210df65ead54e0a1fe537b2 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -351,10 +351,10 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
 	data = i2c_get_clientdata(tpa6130a2_client);
 
 	if (data->id == TPA6140A2)
-		return snd_soc_add_controls(codec, tpa6140a2_controls,
+		return snd_soc_add_codec_controls(codec, tpa6140a2_controls,
 						ARRAY_SIZE(tpa6140a2_controls));
 	else
-		return snd_soc_add_controls(codec, tpa6130a2_controls,
+		return snd_soc_add_codec_controls(codec, tpa6130a2_controls,
 						ARRAY_SIZE(tpa6130a2_controls));
 }
 EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 18e71014cc2e87a93d82abdca853b62d29ab8a54..170cf9a8fc796c40925c24d594ed36d20181721b 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -1002,8 +1002,8 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
 	unsigned short mask, bitmask;
 
 	if (twl4030->configured) {
-		printk(KERN_ERR "twl4030 operation mode cannot be "
-			"changed on-the-fly\n");
+		dev_err(codec->dev,
+			"operation mode cannot be changed on-the-fly\n");
 		return -EBUSY;
 	}
 
@@ -1689,7 +1689,6 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
 	struct snd_soc_codec *codec = rtd->codec;
 	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 
-	snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
 	if (twl4030->master_substream) {
 		twl4030->slave_substream = substream;
 		/* The DAI has one configuration for playback and capture, so
@@ -1801,7 +1800,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
 		mode |= TWL4030_APLL_RATE_96000;
 		break;
 	default:
-		printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
+		dev_err(codec->dev, "%s: unknown rate %d\n", __func__,
 			params_rate(params));
 		return -EINVAL;
 	}
@@ -1818,7 +1817,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
 		format |= TWL4030_DATA_WIDTH_32S_24W;
 		break;
 	default:
-		printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
+		dev_err(codec->dev, "%s: unknown format %d\n", __func__,
 			params_format(params));
 		return -EINVAL;
 	}
@@ -1868,13 +1867,13 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	case 38400000:
 		break;
 	default:
-		dev_err(codec->dev, "Unsupported APLL mclk: %u\n", freq);
+		dev_err(codec->dev, "Unsupported HFCLKIN: %u\n", freq);
 		return -EINVAL;
 	}
 
 	if ((freq / 1000) != twl4030->sysclk) {
 		dev_err(codec->dev,
-			"Mismatch in APLL mclk: %u (configured: %u)\n",
+			"Mismatch in HFCLKIN: %u (configured: %u)\n",
 			freq, twl4030->sysclk * 1000);
 		return -EINVAL;
 	}
@@ -1984,9 +1983,9 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
 	 * not available.
 	 */
 	if (twl4030->sysclk != 26000) {
-		dev_err(codec->dev, "The board is configured for %u Hz, while"
-			"the Voice interface needs 26MHz APLL mclk\n",
-			twl4030->sysclk * 1000);
+		dev_err(codec->dev,
+			"%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n",
+			__func__, twl4030->sysclk);
 		return -EINVAL;
 	}
 
@@ -1997,8 +1996,8 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
 		& TWL4030_OPT_MODE;
 
 	if (mode != TWL4030_OPTION_2) {
-		printk(KERN_ERR "TWL4030 voice startup: "
-			"the codec mode is not option2\n");
+		dev_err(codec->dev, "%s: the codec mode is not option2\n",
+			__func__);
 		return -EINVAL;
 	}
 
@@ -2039,7 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
 		mode |= TWL4030_SEL_16K;
 		break;
 	default:
-		printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
+		dev_err(codec->dev, "%s: unknown rate %d\n", __func__,
 			params_rate(params));
 		return -EINVAL;
 	}
@@ -2068,13 +2067,14 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 
 	if (freq != 26000000) {
-		dev_err(codec->dev, "Unsupported APLL mclk: %u, the Voice"
-			"interface needs 26MHz APLL mclk\n", freq);
+		dev_err(codec->dev,
+			"%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n",
+			__func__, freq / 1000);
 		return -EINVAL;
 	}
 	if ((freq / 1000) != twl4030->sysclk) {
 		dev_err(codec->dev,
-			"Mismatch in APLL mclk: %u (configured: %u)\n",
+			"Mismatch in HFCLKIN: %u (configured: %u)\n",
 			freq, twl4030->sysclk * 1000);
 		return -EINVAL;
 	}
@@ -2175,13 +2175,15 @@ static struct snd_soc_dai_driver twl4030_dai[] = {
 		.channels_min = 2,
 		.channels_max = 4,
 		.rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
-		.formats = TWL4030_FORMATS,},
+		.formats = TWL4030_FORMATS,
+		.sig_bits = 24,},
 	.capture = {
 		.stream_name = "Capture",
 		.channels_min = 2,
 		.channels_max = 4,
 		.rates = TWL4030_RATES,
-		.formats = TWL4030_FORMATS,},
+		.formats = TWL4030_FORMATS,
+		.sig_bits = 24,},
 	.ops = &twl4030_dai_hifi_ops,
 },
 {
@@ -2220,13 +2222,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
 
 	twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
 	if (twl4030 == NULL) {
-		printk("Can not allocate memroy\n");
+		dev_err(codec->dev, "Can not allocate memory\n");
 		return -ENOMEM;
 	}
 	snd_soc_codec_set_drvdata(codec, twl4030);
 	/* Set the defaults, and power up the codec */
 	twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
-	codec->dapm.idle_bias_off = 1;
 
 	twl4030_init_chip(codec);
 
@@ -2252,6 +2253,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
 	.read = twl4030_read_reg_cache,
 	.write = twl4030_write,
 	.set_bias_level = twl4030_set_bias_level,
+	.idle_bias_off = true,
 	.reg_cache_size = sizeof(twl4030_reg),
 	.reg_word_size = sizeof(u8),
 	.reg_cache_default = twl4030_reg,
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 5b9c79b6f65e104fdbbae4779452d15821752c58..2d8c6b825e57b9ecd17253c5de57432260ecdaab 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1052,6 +1052,19 @@ int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
 }
 EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
 
+int twl6040_get_hs_step_size(struct snd_soc_codec *codec)
+{
+	struct twl6040 *twl6040 = codec->control_data;
+
+	if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_2)
+		/* For ES under ES_1.3 HS step is 2 mV */
+		return 2;
+	else
+		/* For ES_1.3 HS step is 1 mV */
+		return 1;
+}
+EXPORT_SYMBOL_GPL(twl6040_get_hs_step_size);
+
 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
 	/* Capture gains */
 	SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1125,14 +1138,14 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
 			TWL6040_REG_MICRCTL, 2, 0),
 
 	/* Microphone bias */
-	SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
-			TWL6040_REG_AMICBCTL, 0, 0),
-	SND_SOC_DAPM_MICBIAS("Main Mic Bias",
-			TWL6040_REG_AMICBCTL, 4, 0),
-	SND_SOC_DAPM_MICBIAS("Digital Mic1 Bias",
-			TWL6040_REG_DMICBCTL, 0, 0),
-	SND_SOC_DAPM_MICBIAS("Digital Mic2 Bias",
-			TWL6040_REG_DMICBCTL, 4, 0),
+	SND_SOC_DAPM_SUPPLY("Headset Mic Bias",
+			    TWL6040_REG_AMICBCTL, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Main Mic Bias",
+			    TWL6040_REG_AMICBCTL, 4, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias",
+			    TWL6040_REG_DMICBCTL, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias",
+			    TWL6040_REG_DMICBCTL, 4, 0, NULL, 0),
 
 	/* DACs */
 	SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0),
@@ -1527,7 +1540,6 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
 	priv->codec = codec;
 	codec->control_data = dev_get_drvdata(codec->dev->parent);
-	codec->ignore_pmdown_time = 1;
 
 	if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
 		priv->hs_left_step = pdata->hs_left_step;
@@ -1613,6 +1625,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
 	.reg_cache_size = ARRAY_SIZE(twl6040_reg),
 	.reg_word_size = sizeof(u8),
 	.reg_cache_default = twl6040_reg,
+	.ignore_pmdown_time = true,
 
 	.controls = twl6040_snd_controls,
 	.num_controls = ARRAY_SIZE(twl6040_snd_controls),
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index ef273f1fac2f838add14ecc8b01465e4677097af..0611406ca7c0359188575df1e61020c1680e9b4e 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -39,5 +39,6 @@ void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
 			    struct snd_soc_jack *jack, int report);
 int twl6040_get_clk_id(struct snd_soc_codec *codec);
 int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim);
+int twl6040_get_hs_step_size(struct snd_soc_codec *codec);
 
 #endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 8f4f469d64115cb52ae8c58fd60fcc78d9669e50..797b0dde2c68620910a5870f7e341731aaf3380b 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -531,15 +531,15 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
 	switch (pd->model) {
 	case UDA134X_UDA1340:
 	case UDA134X_UDA1344:
-		ret = snd_soc_add_controls(codec, uda1340_snd_controls,
+		ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
 					ARRAY_SIZE(uda1340_snd_controls));
 	break;
 	case UDA134X_UDA1341:
-		ret = snd_soc_add_controls(codec, uda1341_snd_controls,
+		ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
 					ARRAY_SIZE(uda1341_snd_controls));
 	break;
 	case UDA134X_UDA1345:
-		ret = snd_soc_add_controls(codec, uda1345_snd_controls,
+		ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
 					ARRAY_SIZE(uda1345_snd_controls));
 	break;
 	default:
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 44aacf927ba99d6a533524b39859eac9d565c265..3d868dc400921cc22d21ef1ede114fb643dcd6e1 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -464,7 +464,7 @@ static int wl1273_probe(struct snd_soc_codec *codec)
 
 	snd_soc_codec_set_drvdata(codec, wl1273);
 
-	r = snd_soc_add_controls(codec, wl1273_controls,
+	r = snd_soc_add_codec_controls(codec, wl1273_controls,
 				 ARRAY_SIZE(wl1273_controls));
 	if (r)
 		kfree(wl1273);
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
new file mode 100644
index 0000000000000000000000000000000000000000..acbdc5fde9236be0e43a5767bd0135eb92450e68
--- /dev/null
+++ b/sound/soc/codecs/wm2200.c
@@ -0,0 +1,2286 @@
+/*
+ * wm2200.c  --  WM2200 ALSA SoC Audio driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm2200.h>
+
+#include "wm2200.h"
+
+/* The code assumes DCVDD is generated internally */
+#define WM2200_NUM_CORE_SUPPLIES 2
+static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = {
+	"DBVDD",
+	"LDOVDD",
+};
+
+struct wm2200_fll {
+	int fref;
+	int fout;
+	int src;
+	struct completion lock;
+};
+
+/* codec private data */
+struct wm2200_priv {
+	struct regmap *regmap;
+	struct device *dev;
+	struct snd_soc_codec *codec;
+	struct wm2200_pdata pdata;
+	struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES];
+
+	struct completion fll_lock;
+	int fll_fout;
+	int fll_fref;
+	int fll_src;
+
+	int rev;
+	int sysclk;
+};
+
+static struct reg_default wm2200_reg_defaults[] = {
+	{ 0x000B, 0x0000 },   /* R11    - Tone Generator 1 */
+	{ 0x0102, 0x0000 },   /* R258   - Clocking 3 */
+	{ 0x0103, 0x0011 },   /* R259   - Clocking 4 */
+	{ 0x0111, 0x0000 },   /* R273   - FLL Control 1 */
+	{ 0x0112, 0x0000 },   /* R274   - FLL Control 2 */
+	{ 0x0113, 0x0000 },   /* R275   - FLL Control 3 */
+	{ 0x0114, 0x0000 },   /* R276   - FLL Control 4 */
+	{ 0x0116, 0x0177 },   /* R278   - FLL Control 6 */
+	{ 0x0117, 0x0004 },   /* R279   - FLL Control 7 */
+	{ 0x0119, 0x0000 },   /* R281   - FLL EFS 1 */
+	{ 0x011A, 0x0002 },   /* R282   - FLL EFS 2 */
+	{ 0x0200, 0x0000 },   /* R512   - Mic Charge Pump 1 */
+	{ 0x0201, 0x03FF },   /* R513   - Mic Charge Pump 2 */
+	{ 0x0202, 0x9BDE },   /* R514   - DM Charge Pump 1 */
+	{ 0x020C, 0x0000 },   /* R524   - Mic Bias Ctrl 1 */
+	{ 0x020D, 0x0000 },   /* R525   - Mic Bias Ctrl 2 */
+	{ 0x020F, 0x0000 },   /* R527   - Ear Piece Ctrl 1 */
+	{ 0x0210, 0x0000 },   /* R528   - Ear Piece Ctrl 2 */
+	{ 0x0301, 0x0000 },   /* R769   - Input Enables */
+	{ 0x0302, 0x2240 },   /* R770   - IN1L Control */
+	{ 0x0303, 0x0040 },   /* R771   - IN1R Control */
+	{ 0x0304, 0x2240 },   /* R772   - IN2L Control */
+	{ 0x0305, 0x0040 },   /* R773   - IN2R Control */
+	{ 0x0306, 0x2240 },   /* R774   - IN3L Control */
+	{ 0x0307, 0x0040 },   /* R775   - IN3R Control */
+	{ 0x030A, 0x0000 },   /* R778   - RXANC_SRC */
+	{ 0x030B, 0x0022 },   /* R779   - Input Volume Ramp */
+	{ 0x030C, 0x0180 },   /* R780   - ADC Digital Volume 1L */
+	{ 0x030D, 0x0180 },   /* R781   - ADC Digital Volume 1R */
+	{ 0x030E, 0x0180 },   /* R782   - ADC Digital Volume 2L */
+	{ 0x030F, 0x0180 },   /* R783   - ADC Digital Volume 2R */
+	{ 0x0310, 0x0180 },   /* R784   - ADC Digital Volume 3L */
+	{ 0x0311, 0x0180 },   /* R785   - ADC Digital Volume 3R */
+	{ 0x0400, 0x0000 },   /* R1024  - Output Enables */
+	{ 0x0401, 0x0000 },   /* R1025  - DAC Volume Limit 1L */
+	{ 0x0402, 0x0000 },   /* R1026  - DAC Volume Limit 1R */
+	{ 0x0403, 0x0000 },   /* R1027  - DAC Volume Limit 2L */
+	{ 0x0404, 0x0000 },   /* R1028  - DAC Volume Limit 2R */
+	{ 0x0409, 0x0000 },   /* R1033  - DAC AEC Control 1 */
+	{ 0x040A, 0x0022 },   /* R1034  - Output Volume Ramp */
+	{ 0x040B, 0x0180 },   /* R1035  - DAC Digital Volume 1L */
+	{ 0x040C, 0x0180 },   /* R1036  - DAC Digital Volume 1R */
+	{ 0x040D, 0x0180 },   /* R1037  - DAC Digital Volume 2L */
+	{ 0x040E, 0x0180 },   /* R1038  - DAC Digital Volume 2R */
+	{ 0x0417, 0x0069 },   /* R1047  - PDM 1 */
+	{ 0x0418, 0x0000 },   /* R1048  - PDM 2 */
+	{ 0x0500, 0x0000 },   /* 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, 0x0001 },   /* R1285  - Audio IF 1_6 */
+	{ 0x0506, 0x0001 },   /* R1286  - Audio IF 1_7 */
+	{ 0x0507, 0x0000 },   /* R1287  - Audio IF 1_8 */
+	{ 0x0508, 0x0000 },   /* R1288  - Audio IF 1_9 */
+	{ 0x0509, 0x0000 },   /* R1289  - Audio IF 1_10 */
+	{ 0x050A, 0x0000 },   /* R1290  - Audio IF 1_11 */
+	{ 0x050B, 0x0000 },   /* R1291  - Audio IF 1_12 */
+	{ 0x050C, 0x0000 },   /* R1292  - Audio IF 1_13 */
+	{ 0x050D, 0x0000 },   /* R1293  - Audio IF 1_14 */
+	{ 0x050E, 0x0000 },   /* R1294  - Audio IF 1_15 */
+	{ 0x050F, 0x0000 },   /* R1295  - Audio IF 1_16 */
+	{ 0x0510, 0x0000 },   /* R1296  - Audio IF 1_17 */
+	{ 0x0511, 0x0000 },   /* R1297  - Audio IF 1_18 */
+	{ 0x0512, 0x0000 },   /* R1298  - Audio IF 1_19 */
+	{ 0x0513, 0x0000 },   /* R1299  - Audio IF 1_20 */
+	{ 0x0514, 0x0000 },   /* R1300  - Audio IF 1_21 */
+	{ 0x0515, 0x0001 },   /* R1301  - Audio IF 1_22 */
+	{ 0x0600, 0x0000 },   /* R1536  - OUT1LMIX Input 1 Source */
+	{ 0x0601, 0x0080 },   /* R1537  - OUT1LMIX Input 1 Volume */
+	{ 0x0602, 0x0000 },   /* R1538  - OUT1LMIX Input 2 Source */
+	{ 0x0603, 0x0080 },   /* R1539  - OUT1LMIX Input 2 Volume */
+	{ 0x0604, 0x0000 },   /* R1540  - OUT1LMIX Input 3 Source */
+	{ 0x0605, 0x0080 },   /* R1541  - OUT1LMIX Input 3 Volume */
+	{ 0x0606, 0x0000 },   /* R1542  - OUT1LMIX Input 4 Source */
+	{ 0x0607, 0x0080 },   /* R1543  - OUT1LMIX Input 4 Volume */
+	{ 0x0608, 0x0000 },   /* R1544  - OUT1RMIX Input 1 Source */
+	{ 0x0609, 0x0080 },   /* R1545  - OUT1RMIX Input 1 Volume */
+	{ 0x060A, 0x0000 },   /* R1546  - OUT1RMIX Input 2 Source */
+	{ 0x060B, 0x0080 },   /* R1547  - OUT1RMIX Input 2 Volume */
+	{ 0x060C, 0x0000 },   /* R1548  - OUT1RMIX Input 3 Source */
+	{ 0x060D, 0x0080 },   /* R1549  - OUT1RMIX Input 3 Volume */
+	{ 0x060E, 0x0000 },   /* R1550  - OUT1RMIX Input 4 Source */
+	{ 0x060F, 0x0080 },   /* R1551  - OUT1RMIX Input 4 Volume */
+	{ 0x0610, 0x0000 },   /* R1552  - OUT2LMIX Input 1 Source */
+	{ 0x0611, 0x0080 },   /* R1553  - OUT2LMIX Input 1 Volume */
+	{ 0x0612, 0x0000 },   /* R1554  - OUT2LMIX Input 2 Source */
+	{ 0x0613, 0x0080 },   /* R1555  - OUT2LMIX Input 2 Volume */
+	{ 0x0614, 0x0000 },   /* R1556  - OUT2LMIX Input 3 Source */
+	{ 0x0615, 0x0080 },   /* R1557  - OUT2LMIX Input 3 Volume */
+	{ 0x0616, 0x0000 },   /* R1558  - OUT2LMIX Input 4 Source */
+	{ 0x0617, 0x0080 },   /* R1559  - OUT2LMIX Input 4 Volume */
+	{ 0x0618, 0x0000 },   /* R1560  - OUT2RMIX Input 1 Source */
+	{ 0x0619, 0x0080 },   /* R1561  - OUT2RMIX Input 1 Volume */
+	{ 0x061A, 0x0000 },   /* R1562  - OUT2RMIX Input 2 Source */
+	{ 0x061B, 0x0080 },   /* R1563  - OUT2RMIX Input 2 Volume */
+	{ 0x061C, 0x0000 },   /* R1564  - OUT2RMIX Input 3 Source */
+	{ 0x061D, 0x0080 },   /* R1565  - OUT2RMIX Input 3 Volume */
+	{ 0x061E, 0x0000 },   /* R1566  - OUT2RMIX Input 4 Source */
+	{ 0x061F, 0x0080 },   /* R1567  - OUT2RMIX Input 4 Volume */
+	{ 0x0620, 0x0000 },   /* R1568  - AIF1TX1MIX Input 1 Source */
+	{ 0x0621, 0x0080 },   /* R1569  - AIF1TX1MIX Input 1 Volume */
+	{ 0x0622, 0x0000 },   /* R1570  - AIF1TX1MIX Input 2 Source */
+	{ 0x0623, 0x0080 },   /* R1571  - AIF1TX1MIX Input 2 Volume */
+	{ 0x0624, 0x0000 },   /* R1572  - AIF1TX1MIX Input 3 Source */
+	{ 0x0625, 0x0080 },   /* R1573  - AIF1TX1MIX Input 3 Volume */
+	{ 0x0626, 0x0000 },   /* R1574  - AIF1TX1MIX Input 4 Source */
+	{ 0x0627, 0x0080 },   /* R1575  - AIF1TX1MIX Input 4 Volume */
+	{ 0x0628, 0x0000 },   /* R1576  - AIF1TX2MIX Input 1 Source */
+	{ 0x0629, 0x0080 },   /* R1577  - AIF1TX2MIX Input 1 Volume */
+	{ 0x062A, 0x0000 },   /* R1578  - AIF1TX2MIX Input 2 Source */
+	{ 0x062B, 0x0080 },   /* R1579  - AIF1TX2MIX Input 2 Volume */
+	{ 0x062C, 0x0000 },   /* R1580  - AIF1TX2MIX Input 3 Source */
+	{ 0x062D, 0x0080 },   /* R1581  - AIF1TX2MIX Input 3 Volume */
+	{ 0x062E, 0x0000 },   /* R1582  - AIF1TX2MIX Input 4 Source */
+	{ 0x062F, 0x0080 },   /* R1583  - AIF1TX2MIX Input 4 Volume */
+	{ 0x0630, 0x0000 },   /* R1584  - AIF1TX3MIX Input 1 Source */
+	{ 0x0631, 0x0080 },   /* R1585  - AIF1TX3MIX Input 1 Volume */
+	{ 0x0632, 0x0000 },   /* R1586  - AIF1TX3MIX Input 2 Source */
+	{ 0x0633, 0x0080 },   /* R1587  - AIF1TX3MIX Input 2 Volume */
+	{ 0x0634, 0x0000 },   /* R1588  - AIF1TX3MIX Input 3 Source */
+	{ 0x0635, 0x0080 },   /* R1589  - AIF1TX3MIX Input 3 Volume */
+	{ 0x0636, 0x0000 },   /* R1590  - AIF1TX3MIX Input 4 Source */
+	{ 0x0637, 0x0080 },   /* R1591  - AIF1TX3MIX Input 4 Volume */
+	{ 0x0638, 0x0000 },   /* R1592  - AIF1TX4MIX Input 1 Source */
+	{ 0x0639, 0x0080 },   /* R1593  - AIF1TX4MIX Input 1 Volume */
+	{ 0x063A, 0x0000 },   /* R1594  - AIF1TX4MIX Input 2 Source */
+	{ 0x063B, 0x0080 },   /* R1595  - AIF1TX4MIX Input 2 Volume */
+	{ 0x063C, 0x0000 },   /* R1596  - AIF1TX4MIX Input 3 Source */
+	{ 0x063D, 0x0080 },   /* R1597  - AIF1TX4MIX Input 3 Volume */
+	{ 0x063E, 0x0000 },   /* R1598  - AIF1TX4MIX Input 4 Source */
+	{ 0x063F, 0x0080 },   /* R1599  - AIF1TX4MIX Input 4 Volume */
+	{ 0x0640, 0x0000 },   /* R1600  - AIF1TX5MIX Input 1 Source */
+	{ 0x0641, 0x0080 },   /* R1601  - AIF1TX5MIX Input 1 Volume */
+	{ 0x0642, 0x0000 },   /* R1602  - AIF1TX5MIX Input 2 Source */
+	{ 0x0643, 0x0080 },   /* R1603  - AIF1TX5MIX Input 2 Volume */
+	{ 0x0644, 0x0000 },   /* R1604  - AIF1TX5MIX Input 3 Source */
+	{ 0x0645, 0x0080 },   /* R1605  - AIF1TX5MIX Input 3 Volume */
+	{ 0x0646, 0x0000 },   /* R1606  - AIF1TX5MIX Input 4 Source */
+	{ 0x0647, 0x0080 },   /* R1607  - AIF1TX5MIX Input 4 Volume */
+	{ 0x0648, 0x0000 },   /* R1608  - AIF1TX6MIX Input 1 Source */
+	{ 0x0649, 0x0080 },   /* R1609  - AIF1TX6MIX Input 1 Volume */
+	{ 0x064A, 0x0000 },   /* R1610  - AIF1TX6MIX Input 2 Source */
+	{ 0x064B, 0x0080 },   /* R1611  - AIF1TX6MIX Input 2 Volume */
+	{ 0x064C, 0x0000 },   /* R1612  - AIF1TX6MIX Input 3 Source */
+	{ 0x064D, 0x0080 },   /* R1613  - AIF1TX6MIX Input 3 Volume */
+	{ 0x064E, 0x0000 },   /* R1614  - AIF1TX6MIX Input 4 Source */
+	{ 0x064F, 0x0080 },   /* R1615  - AIF1TX6MIX Input 4 Volume */
+	{ 0x0650, 0x0000 },   /* R1616  - EQLMIX Input 1 Source */
+	{ 0x0651, 0x0080 },   /* R1617  - EQLMIX Input 1 Volume */
+	{ 0x0652, 0x0000 },   /* R1618  - EQLMIX Input 2 Source */
+	{ 0x0653, 0x0080 },   /* R1619  - EQLMIX Input 2 Volume */
+	{ 0x0654, 0x0000 },   /* R1620  - EQLMIX Input 3 Source */
+	{ 0x0655, 0x0080 },   /* R1621  - EQLMIX Input 3 Volume */
+	{ 0x0656, 0x0000 },   /* R1622  - EQLMIX Input 4 Source */
+	{ 0x0657, 0x0080 },   /* R1623  - EQLMIX Input 4 Volume */
+	{ 0x0658, 0x0000 },   /* R1624  - EQRMIX Input 1 Source */
+	{ 0x0659, 0x0080 },   /* R1625  - EQRMIX Input 1 Volume */
+	{ 0x065A, 0x0000 },   /* R1626  - EQRMIX Input 2 Source */
+	{ 0x065B, 0x0080 },   /* R1627  - EQRMIX Input 2 Volume */
+	{ 0x065C, 0x0000 },   /* R1628  - EQRMIX Input 3 Source */
+	{ 0x065D, 0x0080 },   /* R1629  - EQRMIX Input 3 Volume */
+	{ 0x065E, 0x0000 },   /* R1630  - EQRMIX Input 4 Source */
+	{ 0x065F, 0x0080 },   /* R1631  - EQRMIX Input 4 Volume */
+	{ 0x0660, 0x0000 },   /* R1632  - LHPF1MIX Input 1 Source */
+	{ 0x0661, 0x0080 },   /* R1633  - LHPF1MIX Input 1 Volume */
+	{ 0x0662, 0x0000 },   /* R1634  - LHPF1MIX Input 2 Source */
+	{ 0x0663, 0x0080 },   /* R1635  - LHPF1MIX Input 2 Volume */
+	{ 0x0664, 0x0000 },   /* R1636  - LHPF1MIX Input 3 Source */
+	{ 0x0665, 0x0080 },   /* R1637  - LHPF1MIX Input 3 Volume */
+	{ 0x0666, 0x0000 },   /* R1638  - LHPF1MIX Input 4 Source */
+	{ 0x0667, 0x0080 },   /* R1639  - LHPF1MIX Input 4 Volume */
+	{ 0x0668, 0x0000 },   /* R1640  - LHPF2MIX Input 1 Source */
+	{ 0x0669, 0x0080 },   /* R1641  - LHPF2MIX Input 1 Volume */
+	{ 0x066A, 0x0000 },   /* R1642  - LHPF2MIX Input 2 Source */
+	{ 0x066B, 0x0080 },   /* R1643  - LHPF2MIX Input 2 Volume */
+	{ 0x066C, 0x0000 },   /* R1644  - LHPF2MIX Input 3 Source */
+	{ 0x066D, 0x0080 },   /* R1645  - LHPF2MIX Input 3 Volume */
+	{ 0x066E, 0x0000 },   /* R1646  - LHPF2MIX Input 4 Source */
+	{ 0x066F, 0x0080 },   /* R1647  - LHPF2MIX Input 4 Volume */
+	{ 0x0670, 0x0000 },   /* R1648  - DSP1LMIX Input 1 Source */
+	{ 0x0671, 0x0080 },   /* R1649  - DSP1LMIX Input 1 Volume */
+	{ 0x0672, 0x0000 },   /* R1650  - DSP1LMIX Input 2 Source */
+	{ 0x0673, 0x0080 },   /* R1651  - DSP1LMIX Input 2 Volume */
+	{ 0x0674, 0x0000 },   /* R1652  - DSP1LMIX Input 3 Source */
+	{ 0x0675, 0x0080 },   /* R1653  - DSP1LMIX Input 3 Volume */
+	{ 0x0676, 0x0000 },   /* R1654  - DSP1LMIX Input 4 Source */
+	{ 0x0677, 0x0080 },   /* R1655  - DSP1LMIX Input 4 Volume */
+	{ 0x0678, 0x0000 },   /* R1656  - DSP1RMIX Input 1 Source */
+	{ 0x0679, 0x0080 },   /* R1657  - DSP1RMIX Input 1 Volume */
+	{ 0x067A, 0x0000 },   /* R1658  - DSP1RMIX Input 2 Source */
+	{ 0x067B, 0x0080 },   /* R1659  - DSP1RMIX Input 2 Volume */
+	{ 0x067C, 0x0000 },   /* R1660  - DSP1RMIX Input 3 Source */
+	{ 0x067D, 0x0080 },   /* R1661  - DSP1RMIX Input 3 Volume */
+	{ 0x067E, 0x0000 },   /* R1662  - DSP1RMIX Input 4 Source */
+	{ 0x067F, 0x0080 },   /* R1663  - DSP1RMIX Input 4 Volume */
+	{ 0x0680, 0x0000 },   /* R1664  - DSP1AUX1MIX Input 1 Source */
+	{ 0x0681, 0x0000 },   /* R1665  - DSP1AUX2MIX Input 1 Source */
+	{ 0x0682, 0x0000 },   /* R1666  - DSP1AUX3MIX Input 1 Source */
+	{ 0x0683, 0x0000 },   /* R1667  - DSP1AUX4MIX Input 1 Source */
+	{ 0x0684, 0x0000 },   /* R1668  - DSP1AUX5MIX Input 1 Source */
+	{ 0x0685, 0x0000 },   /* R1669  - DSP1AUX6MIX Input 1 Source */
+	{ 0x0686, 0x0000 },   /* R1670  - DSP2LMIX Input 1 Source */
+	{ 0x0687, 0x0080 },   /* R1671  - DSP2LMIX Input 1 Volume */
+	{ 0x0688, 0x0000 },   /* R1672  - DSP2LMIX Input 2 Source */
+	{ 0x0689, 0x0080 },   /* R1673  - DSP2LMIX Input 2 Volume */
+	{ 0x068A, 0x0000 },   /* R1674  - DSP2LMIX Input 3 Source */
+	{ 0x068B, 0x0080 },   /* R1675  - DSP2LMIX Input 3 Volume */
+	{ 0x068C, 0x0000 },   /* R1676  - DSP2LMIX Input 4 Source */
+	{ 0x068D, 0x0080 },   /* R1677  - DSP2LMIX Input 4 Volume */
+	{ 0x068E, 0x0000 },   /* R1678  - DSP2RMIX Input 1 Source */
+	{ 0x068F, 0x0080 },   /* R1679  - DSP2RMIX Input 1 Volume */
+	{ 0x0690, 0x0000 },   /* R1680  - DSP2RMIX Input 2 Source */
+	{ 0x0691, 0x0080 },   /* R1681  - DSP2RMIX Input 2 Volume */
+	{ 0x0692, 0x0000 },   /* R1682  - DSP2RMIX Input 3 Source */
+	{ 0x0693, 0x0080 },   /* R1683  - DSP2RMIX Input 3 Volume */
+	{ 0x0694, 0x0000 },   /* R1684  - DSP2RMIX Input 4 Source */
+	{ 0x0695, 0x0080 },   /* R1685  - DSP2RMIX Input 4 Volume */
+	{ 0x0696, 0x0000 },   /* R1686  - DSP2AUX1MIX Input 1 Source */
+	{ 0x0697, 0x0000 },   /* R1687  - DSP2AUX2MIX Input 1 Source */
+	{ 0x0698, 0x0000 },   /* R1688  - DSP2AUX3MIX Input 1 Source */
+	{ 0x0699, 0x0000 },   /* R1689  - DSP2AUX4MIX Input 1 Source */
+	{ 0x069A, 0x0000 },   /* R1690  - DSP2AUX5MIX Input 1 Source */
+	{ 0x069B, 0x0000 },   /* R1691  - DSP2AUX6MIX Input 1 Source */
+	{ 0x0700, 0xA101 },   /* R1792  - GPIO CTRL 1 */
+	{ 0x0701, 0xA101 },   /* R1793  - GPIO CTRL 2 */
+	{ 0x0702, 0xA101 },   /* R1794  - GPIO CTRL 3 */
+	{ 0x0703, 0xA101 },   /* R1795  - GPIO CTRL 4 */
+	{ 0x0709, 0x0000 },   /* R1801  - Misc Pad Ctrl 1 */
+	{ 0x0801, 0x00FF },   /* R2049  - Interrupt Status 1 Mask */
+	{ 0x0804, 0xFFFF },   /* R2052  - Interrupt Status 2 Mask */
+	{ 0x0808, 0x0000 },   /* R2056  - Interrupt Control */
+	{ 0x0900, 0x0000 },   /* R2304  - EQL_1 */
+	{ 0x0901, 0x0000 },   /* R2305  - EQL_2 */
+	{ 0x0902, 0x0000 },   /* R2306  - EQL_3 */
+	{ 0x0903, 0x0000 },   /* R2307  - EQL_4 */
+	{ 0x0904, 0x0000 },   /* R2308  - EQL_5 */
+	{ 0x0905, 0x0000 },   /* R2309  - EQL_6 */
+	{ 0x0906, 0x0000 },   /* R2310  - EQL_7 */
+	{ 0x0907, 0x0000 },   /* R2311  - EQL_8 */
+	{ 0x0908, 0x0000 },   /* R2312  - EQL_9 */
+	{ 0x0909, 0x0000 },   /* R2313  - EQL_10 */
+	{ 0x090A, 0x0000 },   /* R2314  - EQL_11 */
+	{ 0x090B, 0x0000 },   /* R2315  - EQL_12 */
+	{ 0x090C, 0x0000 },   /* R2316  - EQL_13 */
+	{ 0x090D, 0x0000 },   /* R2317  - EQL_14 */
+	{ 0x090E, 0x0000 },   /* R2318  - EQL_15 */
+	{ 0x090F, 0x0000 },   /* R2319  - EQL_16 */
+	{ 0x0910, 0x0000 },   /* R2320  - EQL_17 */
+	{ 0x0911, 0x0000 },   /* R2321  - EQL_18 */
+	{ 0x0912, 0x0000 },   /* R2322  - EQL_19 */
+	{ 0x0913, 0x0000 },   /* R2323  - EQL_20 */
+	{ 0x0916, 0x0000 },   /* R2326  - EQR_1 */
+	{ 0x0917, 0x0000 },   /* R2327  - EQR_2 */
+	{ 0x0918, 0x0000 },   /* R2328  - EQR_3 */
+	{ 0x0919, 0x0000 },   /* R2329  - EQR_4 */
+	{ 0x091A, 0x0000 },   /* R2330  - EQR_5 */
+	{ 0x091B, 0x0000 },   /* R2331  - EQR_6 */
+	{ 0x091C, 0x0000 },   /* R2332  - EQR_7 */
+	{ 0x091D, 0x0000 },   /* R2333  - EQR_8 */
+	{ 0x091E, 0x0000 },   /* R2334  - EQR_9 */
+	{ 0x091F, 0x0000 },   /* R2335  - EQR_10 */
+	{ 0x0920, 0x0000 },   /* R2336  - EQR_11 */
+	{ 0x0921, 0x0000 },   /* R2337  - EQR_12 */
+	{ 0x0922, 0x0000 },   /* R2338  - EQR_13 */
+	{ 0x0923, 0x0000 },   /* R2339  - EQR_14 */
+	{ 0x0924, 0x0000 },   /* R2340  - EQR_15 */
+	{ 0x0925, 0x0000 },   /* R2341  - EQR_16 */
+	{ 0x0926, 0x0000 },   /* R2342  - EQR_17 */
+	{ 0x0927, 0x0000 },   /* R2343  - EQR_18 */
+	{ 0x0928, 0x0000 },   /* R2344  - EQR_19 */
+	{ 0x0929, 0x0000 },   /* R2345  - EQR_20 */
+	{ 0x093E, 0x0000 },   /* R2366  - HPLPF1_1 */
+	{ 0x093F, 0x0000 },   /* R2367  - HPLPF1_2 */
+	{ 0x0942, 0x0000 },   /* R2370  - HPLPF2_1 */
+	{ 0x0943, 0x0000 },   /* R2371  - HPLPF2_2 */
+	{ 0x0A00, 0x0000 },   /* R2560  - DSP1 Control 1 */
+	{ 0x0A02, 0x0000 },   /* R2562  - DSP1 Control 2 */
+	{ 0x0A03, 0x0000 },   /* R2563  - DSP1 Control 3 */
+	{ 0x0A04, 0x0000 },   /* R2564  - DSP1 Control 4 */
+	{ 0x0A06, 0x0000 },   /* R2566  - DSP1 Control 5 */
+	{ 0x0A07, 0x0000 },   /* R2567  - DSP1 Control 6 */
+	{ 0x0A08, 0x0000 },   /* R2568  - DSP1 Control 7 */
+	{ 0x0A09, 0x0000 },   /* R2569  - DSP1 Control 8 */
+	{ 0x0A0A, 0x0000 },   /* R2570  - DSP1 Control 9 */
+	{ 0x0A0B, 0x0000 },   /* R2571  - DSP1 Control 10 */
+	{ 0x0A0C, 0x0000 },   /* R2572  - DSP1 Control 11 */
+	{ 0x0A0D, 0x0000 },   /* R2573  - DSP1 Control 12 */
+	{ 0x0A0F, 0x0000 },   /* R2575  - DSP1 Control 13 */
+	{ 0x0A10, 0x0000 },   /* R2576  - DSP1 Control 14 */
+	{ 0x0A11, 0x0000 },   /* R2577  - DSP1 Control 15 */
+	{ 0x0A12, 0x0000 },   /* R2578  - DSP1 Control 16 */
+	{ 0x0A13, 0x0000 },   /* R2579  - DSP1 Control 17 */
+	{ 0x0A14, 0x0000 },   /* R2580  - DSP1 Control 18 */
+	{ 0x0A16, 0x0000 },   /* R2582  - DSP1 Control 19 */
+	{ 0x0A17, 0x0000 },   /* R2583  - DSP1 Control 20 */
+	{ 0x0A18, 0x0000 },   /* R2584  - DSP1 Control 21 */
+	{ 0x0A1A, 0x1800 },   /* R2586  - DSP1 Control 22 */
+	{ 0x0A1B, 0x1000 },   /* R2587  - DSP1 Control 23 */
+	{ 0x0A1C, 0x0400 },   /* R2588  - DSP1 Control 24 */
+	{ 0x0A1E, 0x0000 },   /* R2590  - DSP1 Control 25 */
+	{ 0x0A20, 0x0000 },   /* R2592  - DSP1 Control 26 */
+	{ 0x0A21, 0x0000 },   /* R2593  - DSP1 Control 27 */
+	{ 0x0A22, 0x0000 },   /* R2594  - DSP1 Control 28 */
+	{ 0x0A23, 0x0000 },   /* R2595  - DSP1 Control 29 */
+	{ 0x0A24, 0x0000 },   /* R2596  - DSP1 Control 30 */
+	{ 0x0A26, 0x0000 },   /* R2598  - DSP1 Control 31 */
+	{ 0x0B00, 0x0000 },   /* R2816  - DSP2 Control 1 */
+	{ 0x0B02, 0x0000 },   /* R2818  - DSP2 Control 2 */
+	{ 0x0B03, 0x0000 },   /* R2819  - DSP2 Control 3 */
+	{ 0x0B04, 0x0000 },   /* R2820  - DSP2 Control 4 */
+	{ 0x0B06, 0x0000 },   /* R2822  - DSP2 Control 5 */
+	{ 0x0B07, 0x0000 },   /* R2823  - DSP2 Control 6 */
+	{ 0x0B08, 0x0000 },   /* R2824  - DSP2 Control 7 */
+	{ 0x0B09, 0x0000 },   /* R2825  - DSP2 Control 8 */
+	{ 0x0B0A, 0x0000 },   /* R2826  - DSP2 Control 9 */
+	{ 0x0B0B, 0x0000 },   /* R2827  - DSP2 Control 10 */
+	{ 0x0B0C, 0x0000 },   /* R2828  - DSP2 Control 11 */
+	{ 0x0B0D, 0x0000 },   /* R2829  - DSP2 Control 12 */
+	{ 0x0B0F, 0x0000 },   /* R2831  - DSP2 Control 13 */
+	{ 0x0B10, 0x0000 },   /* R2832  - DSP2 Control 14 */
+	{ 0x0B11, 0x0000 },   /* R2833  - DSP2 Control 15 */
+	{ 0x0B12, 0x0000 },   /* R2834  - DSP2 Control 16 */
+	{ 0x0B13, 0x0000 },   /* R2835  - DSP2 Control 17 */
+	{ 0x0B14, 0x0000 },   /* R2836  - DSP2 Control 18 */
+	{ 0x0B16, 0x0000 },   /* R2838  - DSP2 Control 19 */
+	{ 0x0B17, 0x0000 },   /* R2839  - DSP2 Control 20 */
+	{ 0x0B18, 0x0000 },   /* R2840  - DSP2 Control 21 */
+	{ 0x0B1A, 0x0800 },   /* R2842  - DSP2 Control 22 */
+	{ 0x0B1B, 0x1000 },   /* R2843  - DSP2 Control 23 */
+	{ 0x0B1C, 0x0400 },   /* R2844  - DSP2 Control 24 */
+	{ 0x0B1E, 0x0000 },   /* R2846  - DSP2 Control 25 */
+	{ 0x0B20, 0x0000 },   /* R2848  - DSP2 Control 26 */
+	{ 0x0B21, 0x0000 },   /* R2849  - DSP2 Control 27 */
+	{ 0x0B22, 0x0000 },   /* R2850  - DSP2 Control 28 */
+	{ 0x0B23, 0x0000 },   /* R2851  - DSP2 Control 29 */
+	{ 0x0B24, 0x0000 },   /* R2852  - DSP2 Control 30 */
+	{ 0x0B26, 0x0000 },   /* R2854  - DSP2 Control 31 */
+};
+
+static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM2200_SOFTWARE_RESET:
+	case WM2200_DEVICE_REVISION:
+	case WM2200_ADPS1_IRQ0:
+	case WM2200_ADPS1_IRQ1:
+	case WM2200_INTERRUPT_STATUS_1:
+	case WM2200_INTERRUPT_STATUS_2:
+	case WM2200_INTERRUPT_RAW_STATUS_2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool wm2200_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM2200_SOFTWARE_RESET:
+	case WM2200_DEVICE_REVISION:
+	case WM2200_TONE_GENERATOR_1:
+	case WM2200_CLOCKING_3:
+	case WM2200_CLOCKING_4:
+	case WM2200_FLL_CONTROL_1:
+	case WM2200_FLL_CONTROL_2:
+	case WM2200_FLL_CONTROL_3:
+	case WM2200_FLL_CONTROL_4:
+	case WM2200_FLL_CONTROL_6:
+	case WM2200_FLL_CONTROL_7:
+	case WM2200_FLL_EFS_1:
+	case WM2200_FLL_EFS_2:
+	case WM2200_MIC_CHARGE_PUMP_1:
+	case WM2200_MIC_CHARGE_PUMP_2:
+	case WM2200_DM_CHARGE_PUMP_1:
+	case WM2200_MIC_BIAS_CTRL_1:
+	case WM2200_MIC_BIAS_CTRL_2:
+	case WM2200_EAR_PIECE_CTRL_1:
+	case WM2200_EAR_PIECE_CTRL_2:
+	case WM2200_INPUT_ENABLES:
+	case WM2200_IN1L_CONTROL:
+	case WM2200_IN1R_CONTROL:
+	case WM2200_IN2L_CONTROL:
+	case WM2200_IN2R_CONTROL:
+	case WM2200_IN3L_CONTROL:
+	case WM2200_IN3R_CONTROL:
+	case WM2200_RXANC_SRC:
+	case WM2200_INPUT_VOLUME_RAMP:
+	case WM2200_ADC_DIGITAL_VOLUME_1L:
+	case WM2200_ADC_DIGITAL_VOLUME_1R:
+	case WM2200_ADC_DIGITAL_VOLUME_2L:
+	case WM2200_ADC_DIGITAL_VOLUME_2R:
+	case WM2200_ADC_DIGITAL_VOLUME_3L:
+	case WM2200_ADC_DIGITAL_VOLUME_3R:
+	case WM2200_OUTPUT_ENABLES:
+	case WM2200_DAC_VOLUME_LIMIT_1L:
+	case WM2200_DAC_VOLUME_LIMIT_1R:
+	case WM2200_DAC_VOLUME_LIMIT_2L:
+	case WM2200_DAC_VOLUME_LIMIT_2R:
+	case WM2200_DAC_AEC_CONTROL_1:
+	case WM2200_OUTPUT_VOLUME_RAMP:
+	case WM2200_DAC_DIGITAL_VOLUME_1L:
+	case WM2200_DAC_DIGITAL_VOLUME_1R:
+	case WM2200_DAC_DIGITAL_VOLUME_2L:
+	case WM2200_DAC_DIGITAL_VOLUME_2R:
+	case WM2200_PDM_1:
+	case WM2200_PDM_2:
+	case WM2200_AUDIO_IF_1_1:
+	case WM2200_AUDIO_IF_1_2:
+	case WM2200_AUDIO_IF_1_3:
+	case WM2200_AUDIO_IF_1_4:
+	case WM2200_AUDIO_IF_1_5:
+	case WM2200_AUDIO_IF_1_6:
+	case WM2200_AUDIO_IF_1_7:
+	case WM2200_AUDIO_IF_1_8:
+	case WM2200_AUDIO_IF_1_9:
+	case WM2200_AUDIO_IF_1_10:
+	case WM2200_AUDIO_IF_1_11:
+	case WM2200_AUDIO_IF_1_12:
+	case WM2200_AUDIO_IF_1_13:
+	case WM2200_AUDIO_IF_1_14:
+	case WM2200_AUDIO_IF_1_15:
+	case WM2200_AUDIO_IF_1_16:
+	case WM2200_AUDIO_IF_1_17:
+	case WM2200_AUDIO_IF_1_18:
+	case WM2200_AUDIO_IF_1_19:
+	case WM2200_AUDIO_IF_1_20:
+	case WM2200_AUDIO_IF_1_21:
+	case WM2200_AUDIO_IF_1_22:
+	case WM2200_OUT1LMIX_INPUT_1_SOURCE:
+	case WM2200_OUT1LMIX_INPUT_1_VOLUME:
+	case WM2200_OUT1LMIX_INPUT_2_SOURCE:
+	case WM2200_OUT1LMIX_INPUT_2_VOLUME:
+	case WM2200_OUT1LMIX_INPUT_3_SOURCE:
+	case WM2200_OUT1LMIX_INPUT_3_VOLUME:
+	case WM2200_OUT1LMIX_INPUT_4_SOURCE:
+	case WM2200_OUT1LMIX_INPUT_4_VOLUME:
+	case WM2200_OUT1RMIX_INPUT_1_SOURCE:
+	case WM2200_OUT1RMIX_INPUT_1_VOLUME:
+	case WM2200_OUT1RMIX_INPUT_2_SOURCE:
+	case WM2200_OUT1RMIX_INPUT_2_VOLUME:
+	case WM2200_OUT1RMIX_INPUT_3_SOURCE:
+	case WM2200_OUT1RMIX_INPUT_3_VOLUME:
+	case WM2200_OUT1RMIX_INPUT_4_SOURCE:
+	case WM2200_OUT1RMIX_INPUT_4_VOLUME:
+	case WM2200_OUT2LMIX_INPUT_1_SOURCE:
+	case WM2200_OUT2LMIX_INPUT_1_VOLUME:
+	case WM2200_OUT2LMIX_INPUT_2_SOURCE:
+	case WM2200_OUT2LMIX_INPUT_2_VOLUME:
+	case WM2200_OUT2LMIX_INPUT_3_SOURCE:
+	case WM2200_OUT2LMIX_INPUT_3_VOLUME:
+	case WM2200_OUT2LMIX_INPUT_4_SOURCE:
+	case WM2200_OUT2LMIX_INPUT_4_VOLUME:
+	case WM2200_OUT2RMIX_INPUT_1_SOURCE:
+	case WM2200_OUT2RMIX_INPUT_1_VOLUME:
+	case WM2200_OUT2RMIX_INPUT_2_SOURCE:
+	case WM2200_OUT2RMIX_INPUT_2_VOLUME:
+	case WM2200_OUT2RMIX_INPUT_3_SOURCE:
+	case WM2200_OUT2RMIX_INPUT_3_VOLUME:
+	case WM2200_OUT2RMIX_INPUT_4_SOURCE:
+	case WM2200_OUT2RMIX_INPUT_4_VOLUME:
+	case WM2200_AIF1TX1MIX_INPUT_1_SOURCE:
+	case WM2200_AIF1TX1MIX_INPUT_1_VOLUME:
+	case WM2200_AIF1TX1MIX_INPUT_2_SOURCE:
+	case WM2200_AIF1TX1MIX_INPUT_2_VOLUME:
+	case WM2200_AIF1TX1MIX_INPUT_3_SOURCE:
+	case WM2200_AIF1TX1MIX_INPUT_3_VOLUME:
+	case WM2200_AIF1TX1MIX_INPUT_4_SOURCE:
+	case WM2200_AIF1TX1MIX_INPUT_4_VOLUME:
+	case WM2200_AIF1TX2MIX_INPUT_1_SOURCE:
+	case WM2200_AIF1TX2MIX_INPUT_1_VOLUME:
+	case WM2200_AIF1TX2MIX_INPUT_2_SOURCE:
+	case WM2200_AIF1TX2MIX_INPUT_2_VOLUME:
+	case WM2200_AIF1TX2MIX_INPUT_3_SOURCE:
+	case WM2200_AIF1TX2MIX_INPUT_3_VOLUME:
+	case WM2200_AIF1TX2MIX_INPUT_4_SOURCE:
+	case WM2200_AIF1TX2MIX_INPUT_4_VOLUME:
+	case WM2200_AIF1TX3MIX_INPUT_1_SOURCE:
+	case WM2200_AIF1TX3MIX_INPUT_1_VOLUME:
+	case WM2200_AIF1TX3MIX_INPUT_2_SOURCE:
+	case WM2200_AIF1TX3MIX_INPUT_2_VOLUME:
+	case WM2200_AIF1TX3MIX_INPUT_3_SOURCE:
+	case WM2200_AIF1TX3MIX_INPUT_3_VOLUME:
+	case WM2200_AIF1TX3MIX_INPUT_4_SOURCE:
+	case WM2200_AIF1TX3MIX_INPUT_4_VOLUME:
+	case WM2200_AIF1TX4MIX_INPUT_1_SOURCE:
+	case WM2200_AIF1TX4MIX_INPUT_1_VOLUME:
+	case WM2200_AIF1TX4MIX_INPUT_2_SOURCE:
+	case WM2200_AIF1TX4MIX_INPUT_2_VOLUME:
+	case WM2200_AIF1TX4MIX_INPUT_3_SOURCE:
+	case WM2200_AIF1TX4MIX_INPUT_3_VOLUME:
+	case WM2200_AIF1TX4MIX_INPUT_4_SOURCE:
+	case WM2200_AIF1TX4MIX_INPUT_4_VOLUME:
+	case WM2200_AIF1TX5MIX_INPUT_1_SOURCE:
+	case WM2200_AIF1TX5MIX_INPUT_1_VOLUME:
+	case WM2200_AIF1TX5MIX_INPUT_2_SOURCE:
+	case WM2200_AIF1TX5MIX_INPUT_2_VOLUME:
+	case WM2200_AIF1TX5MIX_INPUT_3_SOURCE:
+	case WM2200_AIF1TX5MIX_INPUT_3_VOLUME:
+	case WM2200_AIF1TX5MIX_INPUT_4_SOURCE:
+	case WM2200_AIF1TX5MIX_INPUT_4_VOLUME:
+	case WM2200_AIF1TX6MIX_INPUT_1_SOURCE:
+	case WM2200_AIF1TX6MIX_INPUT_1_VOLUME:
+	case WM2200_AIF1TX6MIX_INPUT_2_SOURCE:
+	case WM2200_AIF1TX6MIX_INPUT_2_VOLUME:
+	case WM2200_AIF1TX6MIX_INPUT_3_SOURCE:
+	case WM2200_AIF1TX6MIX_INPUT_3_VOLUME:
+	case WM2200_AIF1TX6MIX_INPUT_4_SOURCE:
+	case WM2200_AIF1TX6MIX_INPUT_4_VOLUME:
+	case WM2200_EQLMIX_INPUT_1_SOURCE:
+	case WM2200_EQLMIX_INPUT_1_VOLUME:
+	case WM2200_EQLMIX_INPUT_2_SOURCE:
+	case WM2200_EQLMIX_INPUT_2_VOLUME:
+	case WM2200_EQLMIX_INPUT_3_SOURCE:
+	case WM2200_EQLMIX_INPUT_3_VOLUME:
+	case WM2200_EQLMIX_INPUT_4_SOURCE:
+	case WM2200_EQLMIX_INPUT_4_VOLUME:
+	case WM2200_EQRMIX_INPUT_1_SOURCE:
+	case WM2200_EQRMIX_INPUT_1_VOLUME:
+	case WM2200_EQRMIX_INPUT_2_SOURCE:
+	case WM2200_EQRMIX_INPUT_2_VOLUME:
+	case WM2200_EQRMIX_INPUT_3_SOURCE:
+	case WM2200_EQRMIX_INPUT_3_VOLUME:
+	case WM2200_EQRMIX_INPUT_4_SOURCE:
+	case WM2200_EQRMIX_INPUT_4_VOLUME:
+	case WM2200_LHPF1MIX_INPUT_1_SOURCE:
+	case WM2200_LHPF1MIX_INPUT_1_VOLUME:
+	case WM2200_LHPF1MIX_INPUT_2_SOURCE:
+	case WM2200_LHPF1MIX_INPUT_2_VOLUME:
+	case WM2200_LHPF1MIX_INPUT_3_SOURCE:
+	case WM2200_LHPF1MIX_INPUT_3_VOLUME:
+	case WM2200_LHPF1MIX_INPUT_4_SOURCE:
+	case WM2200_LHPF1MIX_INPUT_4_VOLUME:
+	case WM2200_LHPF2MIX_INPUT_1_SOURCE:
+	case WM2200_LHPF2MIX_INPUT_1_VOLUME:
+	case WM2200_LHPF2MIX_INPUT_2_SOURCE:
+	case WM2200_LHPF2MIX_INPUT_2_VOLUME:
+	case WM2200_LHPF2MIX_INPUT_3_SOURCE:
+	case WM2200_LHPF2MIX_INPUT_3_VOLUME:
+	case WM2200_LHPF2MIX_INPUT_4_SOURCE:
+	case WM2200_LHPF2MIX_INPUT_4_VOLUME:
+	case WM2200_DSP1LMIX_INPUT_1_SOURCE:
+	case WM2200_DSP1LMIX_INPUT_1_VOLUME:
+	case WM2200_DSP1LMIX_INPUT_2_SOURCE:
+	case WM2200_DSP1LMIX_INPUT_2_VOLUME:
+	case WM2200_DSP1LMIX_INPUT_3_SOURCE:
+	case WM2200_DSP1LMIX_INPUT_3_VOLUME:
+	case WM2200_DSP1LMIX_INPUT_4_SOURCE:
+	case WM2200_DSP1LMIX_INPUT_4_VOLUME:
+	case WM2200_DSP1RMIX_INPUT_1_SOURCE:
+	case WM2200_DSP1RMIX_INPUT_1_VOLUME:
+	case WM2200_DSP1RMIX_INPUT_2_SOURCE:
+	case WM2200_DSP1RMIX_INPUT_2_VOLUME:
+	case WM2200_DSP1RMIX_INPUT_3_SOURCE:
+	case WM2200_DSP1RMIX_INPUT_3_VOLUME:
+	case WM2200_DSP1RMIX_INPUT_4_SOURCE:
+	case WM2200_DSP1RMIX_INPUT_4_VOLUME:
+	case WM2200_DSP1AUX1MIX_INPUT_1_SOURCE:
+	case WM2200_DSP1AUX2MIX_INPUT_1_SOURCE:
+	case WM2200_DSP1AUX3MIX_INPUT_1_SOURCE:
+	case WM2200_DSP1AUX4MIX_INPUT_1_SOURCE:
+	case WM2200_DSP1AUX5MIX_INPUT_1_SOURCE:
+	case WM2200_DSP1AUX6MIX_INPUT_1_SOURCE:
+	case WM2200_DSP2LMIX_INPUT_1_SOURCE:
+	case WM2200_DSP2LMIX_INPUT_1_VOLUME:
+	case WM2200_DSP2LMIX_INPUT_2_SOURCE:
+	case WM2200_DSP2LMIX_INPUT_2_VOLUME:
+	case WM2200_DSP2LMIX_INPUT_3_SOURCE:
+	case WM2200_DSP2LMIX_INPUT_3_VOLUME:
+	case WM2200_DSP2LMIX_INPUT_4_SOURCE:
+	case WM2200_DSP2LMIX_INPUT_4_VOLUME:
+	case WM2200_DSP2RMIX_INPUT_1_SOURCE:
+	case WM2200_DSP2RMIX_INPUT_1_VOLUME:
+	case WM2200_DSP2RMIX_INPUT_2_SOURCE:
+	case WM2200_DSP2RMIX_INPUT_2_VOLUME:
+	case WM2200_DSP2RMIX_INPUT_3_SOURCE:
+	case WM2200_DSP2RMIX_INPUT_3_VOLUME:
+	case WM2200_DSP2RMIX_INPUT_4_SOURCE:
+	case WM2200_DSP2RMIX_INPUT_4_VOLUME:
+	case WM2200_DSP2AUX1MIX_INPUT_1_SOURCE:
+	case WM2200_DSP2AUX2MIX_INPUT_1_SOURCE:
+	case WM2200_DSP2AUX3MIX_INPUT_1_SOURCE:
+	case WM2200_DSP2AUX4MIX_INPUT_1_SOURCE:
+	case WM2200_DSP2AUX5MIX_INPUT_1_SOURCE:
+	case WM2200_DSP2AUX6MIX_INPUT_1_SOURCE:
+	case WM2200_GPIO_CTRL_1:
+	case WM2200_GPIO_CTRL_2:
+	case WM2200_GPIO_CTRL_3:
+	case WM2200_GPIO_CTRL_4:
+	case WM2200_ADPS1_IRQ0:
+	case WM2200_ADPS1_IRQ1:
+	case WM2200_MISC_PAD_CTRL_1:
+	case WM2200_INTERRUPT_STATUS_1:
+	case WM2200_INTERRUPT_STATUS_1_MASK:
+	case WM2200_INTERRUPT_STATUS_2:
+	case WM2200_INTERRUPT_RAW_STATUS_2:
+	case WM2200_INTERRUPT_STATUS_2_MASK:
+	case WM2200_INTERRUPT_CONTROL:
+	case WM2200_EQL_1:
+	case WM2200_EQL_2:
+	case WM2200_EQL_3:
+	case WM2200_EQL_4:
+	case WM2200_EQL_5:
+	case WM2200_EQL_6:
+	case WM2200_EQL_7:
+	case WM2200_EQL_8:
+	case WM2200_EQL_9:
+	case WM2200_EQL_10:
+	case WM2200_EQL_11:
+	case WM2200_EQL_12:
+	case WM2200_EQL_13:
+	case WM2200_EQL_14:
+	case WM2200_EQL_15:
+	case WM2200_EQL_16:
+	case WM2200_EQL_17:
+	case WM2200_EQL_18:
+	case WM2200_EQL_19:
+	case WM2200_EQL_20:
+	case WM2200_EQR_1:
+	case WM2200_EQR_2:
+	case WM2200_EQR_3:
+	case WM2200_EQR_4:
+	case WM2200_EQR_5:
+	case WM2200_EQR_6:
+	case WM2200_EQR_7:
+	case WM2200_EQR_8:
+	case WM2200_EQR_9:
+	case WM2200_EQR_10:
+	case WM2200_EQR_11:
+	case WM2200_EQR_12:
+	case WM2200_EQR_13:
+	case WM2200_EQR_14:
+	case WM2200_EQR_15:
+	case WM2200_EQR_16:
+	case WM2200_EQR_17:
+	case WM2200_EQR_18:
+	case WM2200_EQR_19:
+	case WM2200_EQR_20:
+	case WM2200_HPLPF1_1:
+	case WM2200_HPLPF1_2:
+	case WM2200_HPLPF2_1:
+	case WM2200_HPLPF2_2:
+	case WM2200_DSP1_CONTROL_1:
+	case WM2200_DSP1_CONTROL_2:
+	case WM2200_DSP1_CONTROL_3:
+	case WM2200_DSP1_CONTROL_4:
+	case WM2200_DSP1_CONTROL_5:
+	case WM2200_DSP1_CONTROL_6:
+	case WM2200_DSP1_CONTROL_7:
+	case WM2200_DSP1_CONTROL_8:
+	case WM2200_DSP1_CONTROL_9:
+	case WM2200_DSP1_CONTROL_10:
+	case WM2200_DSP1_CONTROL_11:
+	case WM2200_DSP1_CONTROL_12:
+	case WM2200_DSP1_CONTROL_13:
+	case WM2200_DSP1_CONTROL_14:
+	case WM2200_DSP1_CONTROL_15:
+	case WM2200_DSP1_CONTROL_16:
+	case WM2200_DSP1_CONTROL_17:
+	case WM2200_DSP1_CONTROL_18:
+	case WM2200_DSP1_CONTROL_19:
+	case WM2200_DSP1_CONTROL_20:
+	case WM2200_DSP1_CONTROL_21:
+	case WM2200_DSP1_CONTROL_22:
+	case WM2200_DSP1_CONTROL_23:
+	case WM2200_DSP1_CONTROL_24:
+	case WM2200_DSP1_CONTROL_25:
+	case WM2200_DSP1_CONTROL_26:
+	case WM2200_DSP1_CONTROL_27:
+	case WM2200_DSP1_CONTROL_28:
+	case WM2200_DSP1_CONTROL_29:
+	case WM2200_DSP1_CONTROL_30:
+	case WM2200_DSP1_CONTROL_31:
+	case WM2200_DSP2_CONTROL_1:
+	case WM2200_DSP2_CONTROL_2:
+	case WM2200_DSP2_CONTROL_3:
+	case WM2200_DSP2_CONTROL_4:
+	case WM2200_DSP2_CONTROL_5:
+	case WM2200_DSP2_CONTROL_6:
+	case WM2200_DSP2_CONTROL_7:
+	case WM2200_DSP2_CONTROL_8:
+	case WM2200_DSP2_CONTROL_9:
+	case WM2200_DSP2_CONTROL_10:
+	case WM2200_DSP2_CONTROL_11:
+	case WM2200_DSP2_CONTROL_12:
+	case WM2200_DSP2_CONTROL_13:
+	case WM2200_DSP2_CONTROL_14:
+	case WM2200_DSP2_CONTROL_15:
+	case WM2200_DSP2_CONTROL_16:
+	case WM2200_DSP2_CONTROL_17:
+	case WM2200_DSP2_CONTROL_18:
+	case WM2200_DSP2_CONTROL_19:
+	case WM2200_DSP2_CONTROL_20:
+	case WM2200_DSP2_CONTROL_21:
+	case WM2200_DSP2_CONTROL_22:
+	case WM2200_DSP2_CONTROL_23:
+	case WM2200_DSP2_CONTROL_24:
+	case WM2200_DSP2_CONTROL_25:
+	case WM2200_DSP2_CONTROL_26:
+	case WM2200_DSP2_CONTROL_27:
+	case WM2200_DSP2_CONTROL_28:
+	case WM2200_DSP2_CONTROL_29:
+	case WM2200_DSP2_CONTROL_30:
+	case WM2200_DSP2_CONTROL_31:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct reg_default wm2200_reva_patch[] = {
+	{ 0x07, 0x0003 },
+	{ 0x102, 0x0200 },
+	{ 0x203, 0x0084 },
+	{ 0x201, 0x83FF },
+	{ 0x20C, 0x0062 },
+	{ 0x20D, 0x0062 },
+	{ 0x207, 0x2002 },
+	{ 0x208, 0x20C0 },
+	{ 0x21D, 0x01C0 },
+	{ 0x50A, 0x0001 },
+	{ 0x50B, 0x0002 },
+	{ 0x50C, 0x0003 },
+	{ 0x50D, 0x0004 },
+	{ 0x50E, 0x0005 },
+	{ 0x510, 0x0001 },
+	{ 0x511, 0x0002 },
+	{ 0x512, 0x0003 },
+	{ 0x513, 0x0004 },
+	{ 0x514, 0x0005 },
+	{ 0x515, 0x0000 },
+	{ 0x201, 0x8084 },
+	{ 0x202, 0xBBDE },
+	{ 0x203, 0x00EC },
+	{ 0x500, 0x8000 },
+	{ 0x507, 0x1820 },
+	{ 0x508, 0x1820 },
+	{ 0x505, 0x0300 },
+	{ 0x506, 0x0300 },
+	{ 0x302, 0x2280 },
+	{ 0x303, 0x0080 },
+	{ 0x304, 0x2280 },
+	{ 0x305, 0x0080 },
+	{ 0x306, 0x2280 },
+	{ 0x307, 0x0080 },
+	{ 0x401, 0x0080 },
+	{ 0x402, 0x0080 },
+	{ 0x417, 0x3069 },
+	{ 0x900, 0x6318 },
+	{ 0x901, 0x6300 },
+	{ 0x902, 0x0FC8 },
+	{ 0x903, 0x03FE },
+	{ 0x904, 0x00E0 },
+	{ 0x905, 0x1EC4 },
+	{ 0x906, 0xF136 },
+	{ 0x907, 0x0409 },
+	{ 0x908, 0x04CC },
+	{ 0x909, 0x1C9B },
+	{ 0x90A, 0xF337 },
+	{ 0x90B, 0x040B },
+	{ 0x90C, 0x0CBB },
+	{ 0x90D, 0x16F8 },
+	{ 0x90E, 0xF7D9 },
+	{ 0x90F, 0x040A },
+	{ 0x910, 0x1F14 },
+	{ 0x911, 0x058C },
+	{ 0x912, 0x0563 },
+	{ 0x913, 0x4000 },
+	{ 0x916, 0x6318 },
+	{ 0x917, 0x6300 },
+	{ 0x918, 0x0FC8 },
+	{ 0x919, 0x03FE },
+	{ 0x91A, 0x00E0 },
+	{ 0x91B, 0x1EC4 },
+	{ 0x91C, 0xF136 },
+	{ 0x91D, 0x0409 },
+	{ 0x91E, 0x04CC },
+	{ 0x91F, 0x1C9B },
+	{ 0x920, 0xF337 },
+	{ 0x921, 0x040B },
+	{ 0x922, 0x0CBB },
+	{ 0x923, 0x16F8 },
+	{ 0x924, 0xF7D9 },
+	{ 0x925, 0x040A },
+	{ 0x926, 0x1F14 },
+	{ 0x927, 0x058C },
+	{ 0x928, 0x0563 },
+	{ 0x929, 0x4000 },
+	{ 0x709, 0x2000 },
+	{ 0x207, 0x200E },
+	{ 0x208, 0x20D4 },
+	{ 0x20A, 0x0080 },
+	{ 0x07, 0x0000 },
+};
+
+static int wm2200_reset(struct wm2200_priv *wm2200)
+{
+	if (wm2200->pdata.reset) {
+		gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+		gpio_set_value_cansleep(wm2200->pdata.reset, 1);
+
+		return 0;
+	} else {
+		return regmap_write(wm2200->regmap, WM2200_SOFTWARE_RESET,
+				    0x2200);
+	}
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+
+static const char *wm2200_mixer_texts[] = {
+	"None",
+	"Tone Generator",
+	"AEC loopback",
+	"IN1L",
+	"IN1R",
+	"IN2L",
+	"IN2R",
+	"IN3L",
+	"IN3R",
+	"AIF1RX1",
+	"AIF1RX2",
+	"AIF1RX3",
+	"AIF1RX4",
+	"AIF1RX5",
+	"AIF1RX6",
+	"EQL",
+	"EQR",
+	"LHPF1",
+	"LHPF2",
+	"LHPF3",
+	"LHPF4",
+	"DSP1.1",
+	"DSP1.2",
+	"DSP1.3",
+	"DSP1.4",
+	"DSP1.5",
+	"DSP1.6",
+	"DSP2.1",
+	"DSP2.2",
+	"DSP2.3",
+	"DSP2.4",
+	"DSP2.5",
+	"DSP2.6",
+};
+
+static int wm2200_mixer_values[] = {
+	0x00,
+	0x04,   /* Tone */
+	0x08,   /* AEC */
+	0x10,   /* Input */
+	0x11,
+	0x12,
+	0x13,
+	0x14,
+	0x15,
+	0x20,   /* AIF */
+	0x21,
+	0x22,
+	0x23,
+	0x24,
+	0x25,
+	0x50,   /* EQ */
+	0x51,
+	0x52,
+	0x60,   /* LHPF1 */
+	0x61,   /* LHPF2 */
+	0x68,   /* DSP1 */
+	0x69,
+	0x6a,
+	0x6b,
+	0x6c,
+	0x6d,
+	0x70,   /* DSP2 */
+	0x71,
+	0x72,
+	0x73,
+	0x74,
+	0x75,
+};
+
+#define WM2200_MIXER_CONTROLS(name, base) \
+	SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+		       WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+	SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+		       WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+	SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+		       WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+	SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+		       WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM2200_MUX_ENUM_DECL(name, reg) \
+	SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, 			\
+				   wm2200_mixer_texts, wm2200_mixer_values)
+
+#define WM2200_MUX_CTL_DECL(name) \
+	const struct snd_kcontrol_new name##_mux =	\
+		SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM2200_MIXER_ENUMS(name, base_reg) \
+	static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg);	     \
+	static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
+	static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
+	static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
+	static WM2200_MUX_CTL_DECL(name##_in1); \
+	static WM2200_MUX_CTL_DECL(name##_in2); \
+	static WM2200_MUX_CTL_DECL(name##_in3); \
+	static WM2200_MUX_CTL_DECL(name##_in4)
+
+static const struct snd_kcontrol_new wm2200_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
+	   WM2200_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL,
+	   WM2200_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL,
+	   WM2200_IN3_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL,
+		 WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL,
+		 WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL,
+		 WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+
+SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+	     WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+	     WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+	     WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
+		 WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L,
+		 WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L,
+		 WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT,
+		 0xbf, 0, digital_tlv),
+
+SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+	   WM2200_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+	   WM2200_OUT2_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+	     WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L,
+		 WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0,
+		 digital_tlv),
+SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L,
+		 WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT,
+		 0x46, 0, out_tlv),
+
+SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+	     WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
+		 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
+		 digital_tlv),
+SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
+	   WM2200_SPK1R_MUTE_SHIFT, 1, 0),
+};
+
+WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
+
+#define WM2200_MUX(name, ctrl) \
+	SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM2200_MIXER_WIDGETS(name, name_str)	\
+	WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
+	WM2200_MUX(name_str " Input 2", &name##_in2_mux), \
+	WM2200_MUX(name_str " Input 3", &name##_in3_mux), \
+	WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
+	SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM2200_MIXER_INPUT_ROUTES(name)	\
+	{ name, "Tone Generator", "Tone Generator" }, \
+        { name, "IN1L", "IN1L PGA" }, \
+        { name, "IN1R", "IN1R PGA" }, \
+        { name, "IN2L", "IN2L PGA" }, \
+        { name, "IN2R", "IN2R PGA" }, \
+        { name, "IN3L", "IN3L PGA" }, \
+        { name, "IN3R", "IN3R PGA" }, \
+        { name, "DSP1.1", "DSP1" }, \
+        { name, "DSP1.2", "DSP1" }, \
+        { name, "DSP1.3", "DSP1" }, \
+        { name, "DSP1.4", "DSP1" }, \
+        { name, "DSP1.5", "DSP1" }, \
+        { name, "DSP1.6", "DSP1" }, \
+        { name, "DSP2.1", "DSP2" }, \
+        { name, "DSP2.2", "DSP2" }, \
+        { name, "DSP2.3", "DSP2" }, \
+        { name, "DSP2.4", "DSP2" }, \
+        { name, "DSP2.5", "DSP2" }, \
+        { name, "DSP2.6", "DSP2" }, \
+        { name, "AIF1RX1", "AIF1RX1" }, \
+        { name, "AIF1RX2", "AIF1RX2" }, \
+        { name, "AIF1RX3", "AIF1RX3" }, \
+        { name, "AIF1RX4", "AIF1RX4" }, \
+        { name, "AIF1RX5", "AIF1RX5" }, \
+        { name, "AIF1RX6", "AIF1RX6" }, \
+        { name, "EQL", "EQL" }, \
+        { name, "EQR", "EQR" }, \
+        { name, "LHPF1", "LHPF1" }, \
+        { name, "LHPF2", "LHPF2" }
+
+#define WM2200_MIXER_ROUTES(widget, name) \
+	{ widget, NULL, name " Mixer" },         \
+	{ name " Mixer", NULL, name " Input 1" }, \
+	{ name " Mixer", NULL, name " Input 2" }, \
+	{ name " Mixer", NULL, name " Input 3" }, \
+	{ name " Mixer", NULL, name " Input 4" }, \
+	WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \
+	WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \
+	WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
+	WM2200_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
+		    NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0,
+		    NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0,
+		    NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT,
+		    0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT,
+		    0, NULL, 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+
+SND_SOC_DAPM_SIGGEN("TONE"),
+SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1,
+		 WM2200_TONE_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
+		 NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
+		 NULL, 0),
+
+SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
+SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
+		    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
+		   WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
+		   WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+		   WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+		   WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+		   WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+		   WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+		   WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+		   WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+		   WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+		   WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+		   WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+		   WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+		   WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+		   WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT,
+		 0, NULL, 0),
+SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT,
+		 0, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("EPOUTLN"),
+SND_SOC_DAPM_OUTPUT("EPOUTLP"),
+SND_SOC_DAPM_OUTPUT("EPOUTRN"),
+SND_SOC_DAPM_OUTPUT("EPOUTRP"),
+SND_SOC_DAPM_OUTPUT("SPK"),
+
+WM2200_MIXER_WIDGETS(EQL, "EQL"),
+WM2200_MIXER_WIDGETS(EQR, "EQR"),
+
+WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
+
+WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
+WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
+WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
+WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+
+WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+
+WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"),
+WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"),
+WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"),
+WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"),
+};
+
+static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
+	/* Everything needs SYSCLK but only hook up things on the edge
+	 * of the chip */
+	{ "IN1L", NULL, "SYSCLK" },
+	{ "IN1R", NULL, "SYSCLK" },
+	{ "IN2L", NULL, "SYSCLK" },
+	{ "IN2R", NULL, "SYSCLK" },
+	{ "IN3L", NULL, "SYSCLK" },
+	{ "IN3R", NULL, "SYSCLK" },
+	{ "OUT1L", NULL, "SYSCLK" },
+	{ "OUT1R", NULL, "SYSCLK" },
+	{ "OUT2L", NULL, "SYSCLK" },
+	{ "OUT2R", NULL, "SYSCLK" },
+	{ "AIF1RX1", NULL, "SYSCLK" },
+	{ "AIF1RX2", NULL, "SYSCLK" },
+	{ "AIF1RX3", NULL, "SYSCLK" },
+	{ "AIF1RX4", NULL, "SYSCLK" },
+	{ "AIF1RX5", NULL, "SYSCLK" },
+	{ "AIF1RX6", NULL, "SYSCLK" },
+	{ "AIF1TX1", NULL, "SYSCLK" },
+	{ "AIF1TX2", NULL, "SYSCLK" },
+	{ "AIF1TX3", NULL, "SYSCLK" },
+	{ "AIF1TX4", NULL, "SYSCLK" },
+	{ "AIF1TX5", NULL, "SYSCLK" },
+	{ "AIF1TX6", NULL, "SYSCLK" },
+
+	{ "IN1L", NULL, "AVDD" },
+	{ "IN1R", NULL, "AVDD" },
+	{ "IN2L", NULL, "AVDD" },
+	{ "IN2R", NULL, "AVDD" },
+	{ "IN3L", NULL, "AVDD" },
+	{ "IN3R", NULL, "AVDD" },
+	{ "OUT1L", NULL, "AVDD" },
+	{ "OUT1R", NULL, "AVDD" },
+
+	{ "IN1L PGA", NULL, "IN1L" },
+	{ "IN1R PGA", NULL, "IN1R" },
+	{ "IN2L PGA", NULL, "IN2L" },
+	{ "IN2R PGA", NULL, "IN2R" },
+	{ "IN3L PGA", NULL, "IN3L" },
+	{ "IN3R PGA", NULL, "IN3R" },
+
+	{ "Tone Generator", NULL, "TONE" },
+
+	{ "CP2", NULL, "CPVDD" },
+	{ "MICBIAS1", NULL, "CP2" },
+	{ "MICBIAS2", NULL, "CP2" },
+
+	{ "CP1", NULL, "CPVDD" },
+	{ "EPD_LN", NULL, "CP1" },
+	{ "EPD_LP", NULL, "CP1" },
+	{ "EPD_RN", NULL, "CP1" },
+	{ "EPD_RP", NULL, "CP1" },
+
+	{ "EPD_LP", NULL, "OUT1L" },
+	{ "EPD_OUTP_LP", NULL, "EPD_LP" },
+	{ "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" },
+	{ "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" },
+
+	{ "EPD_LN", NULL, "OUT1L" },
+	{ "EPD_OUTP_LN", NULL, "EPD_LN" },
+	{ "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" },
+	{ "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" },
+
+	{ "EPD_RP", NULL, "OUT1R" },
+	{ "EPD_OUTP_RP", NULL, "EPD_RP" },
+	{ "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" },
+	{ "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" },
+
+	{ "EPD_RN", NULL, "OUT1R" },
+	{ "EPD_OUTP_RN", NULL, "EPD_RN" },
+	{ "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" },
+	{ "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" },
+
+	{ "SPK", NULL, "OUT2L" },
+	{ "SPK", NULL, "OUT2R" },
+
+	WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
+	WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
+	WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
+	WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
+
+	WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
+	WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
+	WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
+	WM2200_MIXER_ROUTES("OUT2R", "OUT2R"),
+
+	WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+	WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+	WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+	WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+	WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+	WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+
+	WM2200_MIXER_ROUTES("EQL", "EQL"),
+	WM2200_MIXER_ROUTES("EQR", "EQR"),
+
+	WM2200_MIXER_ROUTES("LHPF1", "LHPF1"),
+	WM2200_MIXER_ROUTES("LHPF2", "LHPF2"),
+};
+
+static int wm2200_probe(struct snd_soc_codec *codec)
+{
+	struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev);
+	int ret;
+
+	wm2200->codec = codec;
+	codec->control_data = wm2200->regmap;
+	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
+
+	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;
+	}
+
+	return ret;
+}
+
+static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	int lrclk, bclk, fmt_val;
+
+	lrclk = 0;
+	bclk = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+		fmt_val = 0;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		fmt_val = 1;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		fmt_val = 2;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		fmt_val = 3;
+		break;
+	default:
+		dev_err(codec->dev, "Unsupported DAI format %d\n",
+			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+		lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		bclk |= WM2200_AIF1_BCLK_MSTR;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+		bclk |= WM2200_AIF1_BCLK_MSTR;
+		break;
+	default:
+		dev_err(codec->dev, "Unsupported master mode %d\n",
+			fmt & SND_SOC_DAIFMT_MASTER_MASK);
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		bclk |= WM2200_AIF1_BCLK_INV;
+		lrclk |= WM2200_AIF1TX_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		bclk |= WM2200_AIF1_BCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		lrclk |= WM2200_AIF1TX_LRCLK_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR |
+			    WM2200_AIF1_BCLK_INV, bclk);
+	snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+			    WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+			    lrclk);
+	snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3,
+			    WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+			    lrclk);
+	snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
+			    WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
+
+	return 0;
+}
+
+static int wm2200_sr_code[] = {
+	0,
+	12000,
+	24000,
+	48000,
+	96000,
+	192000,
+	384000,
+	768000,
+	0,
+	11025,
+	22050,
+	44100,
+	88200,
+	176400,
+	352800,
+	705600,
+	4000,
+	8000,
+	16000,
+	32000,
+	64000,
+	128000,
+	256000,
+	512000,
+};
+
+#define WM2200_NUM_BCLK_RATES 12
+
+static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = {
+	6144000,
+	3072000,
+	2048000,
+	1536000,
+	768000,
+	512000,
+	384000,
+	256000,
+	192000,
+	128000,
+	96000,
+	64000,
+};	
+
+static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = {
+	5644800,
+	2882400,
+	1881600,
+	1411200,
+	705600,
+	470400,
+	352800,
+	176400,
+	117600,
+	88200,
+	58800,
+};
+
+static int wm2200_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+	int i, bclk, lrclk, wl, fl, sr_code;
+	int *bclk_rates;
+
+	/* Data sizes if not using TDM */
+	wl = snd_pcm_format_width(params_format(params));
+	if (wl < 0)
+		return wl;
+	fl = snd_soc_params_to_frame_size(params);
+	if (fl < 0)
+		return fl;
+
+	dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+		wl, fl);
+
+	/* Target BCLK rate */
+	bclk = snd_soc_params_to_bclk(params);
+	if (bclk < 0)
+		return bclk;
+
+	if (!wm2200->sysclk) {
+		dev_err(codec->dev, "SYSCLK has no rate set\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++)
+		if (wm2200_sr_code[i] == params_rate(params))
+			break;
+	if (i == ARRAY_SIZE(wm2200_sr_code)) {
+		dev_err(codec->dev, "Unsupported sample rate: %dHz\n",
+			params_rate(params));
+		return -EINVAL;
+	}
+	sr_code = i;
+
+	dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n",
+		bclk, wm2200->sysclk);
+
+	if (wm2200->sysclk % 4000)
+		bclk_rates = wm2200_bclk_rates_cd;
+	else
+		bclk_rates = wm2200_bclk_rates_dat;
+
+	for (i = 0; i < WM2200_NUM_BCLK_RATES; i++)
+		if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+			break;
+	if (i == WM2200_NUM_BCLK_RATES) {
+		dev_err(codec->dev,
+			"No valid BCLK for %dHz found from %dHz SYSCLK\n",
+			bclk, wm2200->sysclk);
+		return -EINVAL;
+	}
+
+	bclk = i;
+	dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+	snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1,
+			    WM2200_AIF1_BCLK_DIV_MASK, bclk);
+
+	lrclk = bclk_rates[bclk] / params_rate(params);
+	dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+	    dai->symmetric_rates)
+		snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7,
+				    WM2200_AIF1RX_BCPF_MASK, lrclk);
+	else
+		snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6,
+				    WM2200_AIF1TX_BCPF_MASK, lrclk);
+
+	i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9,
+				    WM2200_AIF1RX_WL_MASK |
+				    WM2200_AIF1RX_SLOT_LEN_MASK, i);
+	else
+		snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8,
+				    WM2200_AIF1TX_WL_MASK |
+				    WM2200_AIF1TX_SLOT_LEN_MASK, i);
+
+	snd_soc_update_bits(codec, WM2200_CLOCKING_4,
+			    WM2200_SAMPLE_RATE_1_MASK, sr_code);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops wm2200_dai_ops = {
+	.set_fmt = wm2200_set_fmt,
+	.hw_params = wm2200_hw_params,
+};
+
+static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+			     int source, unsigned int freq, int dir)
+{
+	struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+	int fval;
+
+	switch (clk_id) {
+	case WM2200_CLK_SYSCLK:
+		break;
+
+	default:
+		dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+		return -EINVAL;
+	}
+
+	switch (source) {
+	case WM2200_CLKSRC_MCLK1:
+	case WM2200_CLKSRC_MCLK2:
+	case WM2200_CLKSRC_FLL:
+	case WM2200_CLKSRC_BCLK1:
+		break;
+	default:
+		dev_err(codec->dev, "Invalid source %d\n", source);
+		return -EINVAL;
+	}
+
+	switch (freq) {
+	case 22579200:
+	case 24576000:
+		fval = 2;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+		return -EINVAL;
+	}
+
+	/* TODO: Check if MCLKs are in use and enable/disable pulls to
+	 * match.
+	 */
+
+	snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK |
+			    WM2200_SYSCLK_SRC_MASK,
+			    fval << WM2200_SYSCLK_FREQ_SHIFT | source);
+
+	wm2200->sysclk = freq;
+
+	return 0;
+}
+
+struct _fll_div {
+	u16 fll_fratio;
+	u16 fll_outdiv;
+	u16 fll_refclk_div;
+	u16 n;
+	u16 theta;
+	u16 lambda;
+};
+
+static struct {
+	unsigned int min;
+	unsigned int max;
+	u16 fll_fratio;
+	int ratio;
+} fll_fratios[] = {
+	{       0,    64000, 4, 16 },
+	{   64000,   128000, 3,  8 },
+	{  128000,   256000, 2,  4 },
+	{  256000,  1000000, 1,  2 },
+	{ 1000000, 13500000, 0,  1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+		       unsigned int Fout)
+{
+	unsigned int target;
+	unsigned int div;
+	unsigned int fratio, gcd_fll;
+	int i;
+
+	/* Fref must be <=13.5MHz */
+	div = 1;
+	fll_div->fll_refclk_div = 0;
+	while ((Fref / div) > 13500000) {
+		div *= 2;
+		fll_div->fll_refclk_div++;
+
+		if (div > 8) {
+			pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+			       Fref);
+			return -EINVAL;
+		}
+	}
+
+	pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+	/* Apply the division for our remaining calculations */
+	Fref /= div;
+
+	/* Fvco should be 90-100MHz; don't check the upper bound */
+	div = 2;
+	while (Fout * div < 90000000) {
+		div++;
+		if (div > 64) {
+			pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+			       Fout);
+			return -EINVAL;
+		}
+	}
+	target = Fout * div;
+	fll_div->fll_outdiv = div - 1;
+
+	pr_debug("FLL Fvco=%dHz\n", target);
+
+	/* Find an appropraite FLL_FRATIO and factor it out of the target */
+	for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+		if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+			fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+			fratio = fll_fratios[i].ratio;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(fll_fratios)) {
+		pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+		return -EINVAL;
+	}
+
+	fll_div->n = target / (fratio * Fref);
+
+	if (target % Fref == 0) {
+		fll_div->theta = 0;
+		fll_div->lambda = 0;
+	} else {
+		gcd_fll = gcd(target, fratio * Fref);
+
+		fll_div->theta = (target - (fll_div->n * fratio * Fref))
+			/ gcd_fll;
+		fll_div->lambda = (fratio * Fref) / gcd_fll;
+	}
+
+	pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+		 fll_div->n, fll_div->theta, fll_div->lambda);
+	pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+		 fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+		 fll_div->fll_refclk_div);
+
+	return 0;
+}
+
+static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+			  unsigned int Fref, unsigned int Fout)
+{
+	struct i2c_client *i2c = to_i2c_client(codec->dev);
+	struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+	struct _fll_div factors;
+	int ret, i, timeout;
+
+	if (!Fout) {
+		dev_dbg(codec->dev, "FLL disabled");
+
+		if (wm2200->fll_fout)
+			pm_runtime_put(codec->dev);
+
+		wm2200->fll_fout = 0;
+		snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+				    WM2200_FLL_ENA, 0);
+		return 0;
+	}
+
+	switch (source) {
+	case WM2200_FLL_SRC_MCLK1:
+	case WM2200_FLL_SRC_MCLK2:
+	case WM2200_FLL_SRC_BCLK:
+		break;
+	default:
+		dev_err(codec->dev, "Invalid FLL source %d\n", source);
+		return -EINVAL;
+	}
+
+	ret = fll_factors(&factors, Fref, Fout);
+	if (ret < 0)
+		return ret;
+
+	/* Disable the FLL while we reconfigure */
+	snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0);
+
+	snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2,
+			    WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK,
+			    (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) |
+			    factors.fll_fratio);
+	if (factors.theta) {
+		snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+				    WM2200_FLL_FRACN_ENA,
+				    WM2200_FLL_FRACN_ENA);
+		snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+				    WM2200_FLL_EFS_ENA,
+				    WM2200_FLL_EFS_ENA);
+	} else {
+		snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+				    WM2200_FLL_FRACN_ENA, 0);
+		snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+				    WM2200_FLL_EFS_ENA, 0);
+	}
+
+	snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK,
+			    factors.theta);
+	snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK,
+			    factors.n);
+	snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7,
+			    WM2200_FLL_CLK_REF_DIV_MASK |
+			    WM2200_FLL_CLK_REF_SRC_MASK,
+			    (factors.fll_refclk_div
+			     << WM2200_FLL_CLK_REF_DIV_SHIFT) | source);
+	snd_soc_update_bits(codec, WM2200_FLL_EFS_1,
+			    WM2200_FLL_LAMBDA_MASK, factors.lambda);
+
+	/* Clear any pending completions */
+	try_wait_for_completion(&wm2200->fll_lock);
+
+	pm_runtime_get_sync(codec->dev);
+
+	snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+			    WM2200_FLL_ENA, WM2200_FLL_ENA);
+
+	if (i2c->irq)
+		timeout = 2;
+	else
+		timeout = 50;
+
+	snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA,
+			    WM2200_SYSCLK_ENA);
+
+	/* Poll for the lock; will use the interrupt to exit quickly */
+	for (i = 0; i < timeout; i++) {
+		if (i2c->irq) {
+			ret = wait_for_completion_timeout(&wm2200->fll_lock,
+							  msecs_to_jiffies(25));
+			if (ret > 0)
+				break;
+		} else {
+			msleep(1);
+		}
+
+		ret = snd_soc_read(codec,
+				   WM2200_INTERRUPT_RAW_STATUS_2);
+		if (ret < 0) {
+			dev_err(codec->dev,
+				"Failed to read FLL status: %d\n",
+				ret);
+			continue;
+		}
+		if (ret & WM2200_FLL_LOCK_STS)
+			break;
+	}
+	if (i == timeout) {
+		dev_err(codec->dev, "FLL lock timed out\n");
+		pm_runtime_put(codec->dev);
+		return -ETIMEDOUT;
+	}
+
+	wm2200->fll_src = source;
+	wm2200->fll_fref = Fref;
+	wm2200->fll_fout = Fout;
+
+	dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout);
+
+	return 0;
+}
+
+static int wm2200_dai_probe(struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	unsigned int val = 0;
+	int ret;
+
+	ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1);
+	if (ret >= 0) {
+		if ((ret & WM2200_GP1_FN_MASK) != 0) {
+			dai->symmetric_rates = true;
+			val = WM2200_AIF1TX_LRCLK_SRC;
+		}
+	} else {
+		dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret);
+	}
+
+	snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+			    WM2200_AIF1TX_LRCLK_SRC, val);
+
+	return 0;
+}
+
+#define WM2200_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm2200_dai = {
+	.name = "wm2200",
+	.probe = wm2200_dai_probe,
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = WM2200_RATES,
+		.formats = WM2200_FORMATS,
+	},
+	.capture = {
+		 .stream_name = "Capture",
+		 .channels_min = 2,
+		 .channels_max = 2,
+		 .rates = WM2200_RATES,
+		 .formats = WM2200_FORMATS,
+	 },
+	.ops = &wm2200_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_wm2200 = {
+	.probe = wm2200_probe,
+
+	.idle_bias_off = true,
+	.ignore_pmdown_time = true,
+	.set_sysclk = wm2200_set_sysclk,
+	.set_pll = wm2200_set_fll,
+
+	.controls = wm2200_snd_controls,
+	.num_controls = ARRAY_SIZE(wm2200_snd_controls),
+	.dapm_widgets = wm2200_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets),
+	.dapm_routes = wm2200_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes),
+};
+
+static irqreturn_t wm2200_irq(int irq, void *data)
+{
+	struct wm2200_priv *wm2200 = data;
+	unsigned int val, mask;
+	int ret;
+
+	ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val);
+	if (ret != 0) {
+		dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret);
+		return IRQ_NONE;
+	}
+
+	ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK,
+			   &mask);
+	if (ret != 0) {
+		dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret);
+		mask = 0;
+	}
+
+	val &= ~mask;
+
+	if (val & WM2200_FLL_LOCK_EINT) {
+		dev_dbg(wm2200->dev, "FLL locked\n");
+		complete(&wm2200->fll_lock);
+	}
+
+	if (val) {
+		regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val);
+		
+		return IRQ_HANDLED;
+	} else {
+		return IRQ_NONE;
+	}
+}
+
+static const struct regmap_config wm2200_regmap = {
+	.reg_bits = 16,
+	.val_bits = 16,
+
+	.max_register = WM2200_MAX_REGISTER,
+	.reg_defaults = wm2200_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
+	.volatile_reg = wm2200_volatile_register,
+	.readable_reg = wm2200_readable_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static const unsigned int wm2200_dig_vu[] = {
+	WM2200_DAC_DIGITAL_VOLUME_1L,
+	WM2200_DAC_DIGITAL_VOLUME_1R,
+	WM2200_DAC_DIGITAL_VOLUME_2L,
+	WM2200_DAC_DIGITAL_VOLUME_2R,
+	WM2200_ADC_DIGITAL_VOLUME_1L,
+	WM2200_ADC_DIGITAL_VOLUME_1R,
+	WM2200_ADC_DIGITAL_VOLUME_2L,
+	WM2200_ADC_DIGITAL_VOLUME_2R,
+	WM2200_ADC_DIGITAL_VOLUME_3L,
+	WM2200_ADC_DIGITAL_VOLUME_3R,
+};
+
+static const unsigned int wm2200_mic_ctrl_reg[] = {
+	WM2200_IN1L_CONTROL,
+	WM2200_IN2L_CONTROL,
+	WM2200_IN3L_CONTROL,
+};
+
+static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
+	struct wm2200_priv *wm2200;
+	unsigned int reg;
+	int ret, i;
+
+	wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv),
+			      GFP_KERNEL);
+	if (wm2200 == NULL)
+		return -ENOMEM;
+
+	wm2200->dev = &i2c->dev;
+	init_completion(&wm2200->fll_lock);
+
+	wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+	if (IS_ERR(wm2200->regmap)) {
+		ret = PTR_ERR(wm2200->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err;
+	}
+
+	if (pdata)
+		wm2200->pdata = *pdata;
+
+	i2c_set_clientdata(i2c, wm2200);
+
+	for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
+		wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
+
+	ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
+				 wm2200->core_supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
+			ret);
+		goto err_regmap;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+				    wm2200->core_supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
+			ret);
+		goto err_core;
+	}
+
+	if (wm2200->pdata.ldo_ena) {
+		ret = gpio_request_one(wm2200->pdata.ldo_ena,
+				       GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+		if (ret < 0) {
+			dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+				wm2200->pdata.ldo_ena, ret);
+			goto err_enable;
+		}
+		msleep(2);
+	}
+
+	if (wm2200->pdata.reset) {
+		ret = gpio_request_one(wm2200->pdata.reset,
+				       GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+		if (ret < 0) {
+			dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+				wm2200->pdata.reset, ret);
+			goto err_ldo;
+		}
+	}
+
+	ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+		goto err_reset;
+	}
+	switch (reg) {
+	case 0x2200:
+		break;
+
+	default:
+		dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg);
+		ret = -EINVAL;
+		goto err_reset;
+	}
+
+	ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, &reg);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to read revision register\n");
+		goto err_reset;
+	}
+
+	wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK;
+
+	dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A');
+
+	switch (wm2200->rev) {
+	case 0:
+		ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
+					    ARRAY_SIZE(wm2200_reva_patch));
+		if (ret != 0) {
+			dev_err(&i2c->dev, "Failed to register patch: %d\n",
+				ret);
+		}
+		break;
+	default:
+		break;
+	}
+
+	ret = wm2200_reset(wm2200);
+	if (ret < 0) {
+		dev_err(&i2c->dev, "Failed to issue reset\n");
+		goto err_reset;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) {
+		if (!wm2200->pdata.gpio_defaults[i])
+			continue;
+
+		regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i,
+			     wm2200->pdata.gpio_defaults[i]);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++)
+		regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i],
+				   WM2200_OUT_VU, WM2200_OUT_VU);
+
+	/* Assign slots 1-6 to channels 1-6 for both TX and RX */
+	for (i = 0; i < 6; i++) {
+		regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i);
+		regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) {
+		regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i],
+				   WM2200_IN1_MODE_MASK |
+				   WM2200_IN1_DMIC_SUP_MASK,
+				   (wm2200->pdata.in_mode[i] <<
+				    WM2200_IN1_MODE_SHIFT) |
+				   (wm2200->pdata.dmic_sup[i] <<
+				    WM2200_IN1_DMIC_SUP_SHIFT));
+	}
+
+	if (i2c->irq) {
+		ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq,
+					   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+					   "wm2200", wm2200);
+		if (ret == 0)
+			regmap_update_bits(wm2200->regmap,
+					   WM2200_INTERRUPT_STATUS_2_MASK,
+					   WM2200_FLL_LOCK_EINT, 0);
+		else
+			dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+				i2c->irq, ret);
+	}
+
+	pm_runtime_set_active(&i2c->dev);
+	pm_runtime_enable(&i2c->dev);
+	pm_request_idle(&i2c->dev);
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200,
+				     &wm2200_dai, 1);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+		goto err_pm_runtime;
+	}
+
+	return 0;
+
+err_pm_runtime:
+	pm_runtime_disable(&i2c->dev);
+err_reset:
+	if (wm2200->pdata.reset) {
+		gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+		gpio_free(wm2200->pdata.reset);
+	}
+err_ldo:
+	if (wm2200->pdata.ldo_ena) {
+		gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+		gpio_free(wm2200->pdata.ldo_ena);
+	}
+err_enable:
+	regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+			       wm2200->core_supplies);
+err_core:
+	regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+			    wm2200->core_supplies);
+err_regmap:
+	regmap_exit(wm2200->regmap);
+err:
+	return ret;
+}
+
+static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
+{
+	struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
+
+	snd_soc_unregister_codec(&i2c->dev);
+	if (i2c->irq)
+		free_irq(i2c->irq, wm2200);
+	if (wm2200->pdata.reset) {
+		gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+		gpio_free(wm2200->pdata.reset);
+	}
+	if (wm2200->pdata.ldo_ena) {
+		gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+		gpio_free(wm2200->pdata.ldo_ena);
+	}
+	regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+			    wm2200->core_supplies);
+	regmap_exit(wm2200->regmap);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int wm2200_runtime_suspend(struct device *dev)
+{
+	struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+
+	regcache_cache_only(wm2200->regmap, true);
+	regcache_mark_dirty(wm2200->regmap);
+	if (wm2200->pdata.ldo_ena)
+		gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+	regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+			       wm2200->core_supplies);
+
+	return 0;
+}
+
+static int wm2200_runtime_resume(struct device *dev)
+{
+	struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+				    wm2200->core_supplies);
+	if (ret != 0) {
+		dev_err(dev, "Failed to enable supplies: %d\n",
+			ret);
+		return ret;
+	}
+
+	if (wm2200->pdata.ldo_ena) {
+		gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1);
+		msleep(2);
+	}
+
+	regcache_cache_only(wm2200->regmap, false);
+	regcache_sync(wm2200->regmap);
+
+	return 0;
+}
+#endif
+
+static struct dev_pm_ops wm2200_pm = {
+	SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
+			   NULL)
+};
+
+static const struct i2c_device_id wm2200_i2c_id[] = {
+	{ "wm2200", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
+
+static struct i2c_driver wm2200_i2c_driver = {
+	.driver = {
+		.name = "wm2200",
+		.owner = THIS_MODULE,
+		.pm = &wm2200_pm,
+	},
+	.probe =    wm2200_i2c_probe,
+	.remove =   __devexit_p(wm2200_i2c_remove),
+	.id_table = wm2200_i2c_id,
+};
+
+static int __init wm2200_modinit(void)
+{
+	return i2c_add_driver(&wm2200_i2c_driver);
+}
+module_init(wm2200_modinit);
+
+static void __exit wm2200_exit(void)
+{
+	i2c_del_driver(&wm2200_i2c_driver);
+}
+module_exit(wm2200_exit);
+
+MODULE_DESCRIPTION("ASoC WM2200 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm2200.h b/sound/soc/codecs/wm2200.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d719d6b4a8d17560b51424fbefb0ad0400aed28
--- /dev/null
+++ b/sound/soc/codecs/wm2200.h
@@ -0,0 +1,3674 @@
+/*
+ * wm2200.h - WM2200 audio codec interface
+ *
+ * Copyright 2012 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef _WM2200_H
+#define _WM2200_H
+
+#define WM2200_CLK_SYSCLK 1
+
+#define WM2200_CLKSRC_MCLK1  0
+#define WM2200_CLKSRC_MCLK2  1
+#define WM2200_CLKSRC_FLL    4
+#define WM2200_CLKSRC_BCLK1  8
+
+#define WM2200_FLL_SRC_MCLK1 0
+#define WM2200_FLL_SRC_MCLK2 1
+#define WM2200_FLL_SRC_BCLK  2
+
+/*
+ * Register values.
+ */
+#define WM2200_SOFTWARE_RESET                   0x00
+#define WM2200_DEVICE_REVISION                  0x01
+#define WM2200_TONE_GENERATOR_1                 0x0B
+#define WM2200_CLOCKING_3                       0x102
+#define WM2200_CLOCKING_4                       0x103
+#define WM2200_FLL_CONTROL_1                    0x111
+#define WM2200_FLL_CONTROL_2                    0x112
+#define WM2200_FLL_CONTROL_3                    0x113
+#define WM2200_FLL_CONTROL_4                    0x114
+#define WM2200_FLL_CONTROL_6                    0x116
+#define WM2200_FLL_CONTROL_7                    0x117
+#define WM2200_FLL_EFS_1                        0x119
+#define WM2200_FLL_EFS_2                        0x11A
+#define WM2200_MIC_CHARGE_PUMP_1                0x200
+#define WM2200_MIC_CHARGE_PUMP_2                0x201
+#define WM2200_DM_CHARGE_PUMP_1                 0x202
+#define WM2200_MIC_BIAS_CTRL_1                  0x20C
+#define WM2200_MIC_BIAS_CTRL_2                  0x20D
+#define WM2200_EAR_PIECE_CTRL_1                 0x20F
+#define WM2200_EAR_PIECE_CTRL_2                 0x210
+#define WM2200_INPUT_ENABLES                    0x301
+#define WM2200_IN1L_CONTROL                     0x302
+#define WM2200_IN1R_CONTROL                     0x303
+#define WM2200_IN2L_CONTROL                     0x304
+#define WM2200_IN2R_CONTROL                     0x305
+#define WM2200_IN3L_CONTROL                     0x306
+#define WM2200_IN3R_CONTROL                     0x307
+#define WM2200_RXANC_SRC                        0x30A
+#define WM2200_INPUT_VOLUME_RAMP                0x30B
+#define WM2200_ADC_DIGITAL_VOLUME_1L            0x30C
+#define WM2200_ADC_DIGITAL_VOLUME_1R            0x30D
+#define WM2200_ADC_DIGITAL_VOLUME_2L            0x30E
+#define WM2200_ADC_DIGITAL_VOLUME_2R            0x30F
+#define WM2200_ADC_DIGITAL_VOLUME_3L            0x310
+#define WM2200_ADC_DIGITAL_VOLUME_3R            0x311
+#define WM2200_OUTPUT_ENABLES                   0x400
+#define WM2200_DAC_VOLUME_LIMIT_1L              0x401
+#define WM2200_DAC_VOLUME_LIMIT_1R              0x402
+#define WM2200_DAC_VOLUME_LIMIT_2L              0x403
+#define WM2200_DAC_VOLUME_LIMIT_2R              0x404
+#define WM2200_DAC_AEC_CONTROL_1                0x409
+#define WM2200_OUTPUT_VOLUME_RAMP               0x40A
+#define WM2200_DAC_DIGITAL_VOLUME_1L            0x40B
+#define WM2200_DAC_DIGITAL_VOLUME_1R            0x40C
+#define WM2200_DAC_DIGITAL_VOLUME_2L            0x40D
+#define WM2200_DAC_DIGITAL_VOLUME_2R            0x40E
+#define WM2200_PDM_1                            0x417
+#define WM2200_PDM_2                            0x418
+#define WM2200_AUDIO_IF_1_1                     0x500
+#define WM2200_AUDIO_IF_1_2                     0x501
+#define WM2200_AUDIO_IF_1_3                     0x502
+#define WM2200_AUDIO_IF_1_4                     0x503
+#define WM2200_AUDIO_IF_1_5                     0x504
+#define WM2200_AUDIO_IF_1_6                     0x505
+#define WM2200_AUDIO_IF_1_7                     0x506
+#define WM2200_AUDIO_IF_1_8                     0x507
+#define WM2200_AUDIO_IF_1_9                     0x508
+#define WM2200_AUDIO_IF_1_10                    0x509
+#define WM2200_AUDIO_IF_1_11                    0x50A
+#define WM2200_AUDIO_IF_1_12                    0x50B
+#define WM2200_AUDIO_IF_1_13                    0x50C
+#define WM2200_AUDIO_IF_1_14                    0x50D
+#define WM2200_AUDIO_IF_1_15                    0x50E
+#define WM2200_AUDIO_IF_1_16                    0x50F
+#define WM2200_AUDIO_IF_1_17                    0x510
+#define WM2200_AUDIO_IF_1_18                    0x511
+#define WM2200_AUDIO_IF_1_19                    0x512
+#define WM2200_AUDIO_IF_1_20                    0x513
+#define WM2200_AUDIO_IF_1_21                    0x514
+#define WM2200_AUDIO_IF_1_22                    0x515
+#define WM2200_OUT1LMIX_INPUT_1_SOURCE          0x600
+#define WM2200_OUT1LMIX_INPUT_1_VOLUME          0x601
+#define WM2200_OUT1LMIX_INPUT_2_SOURCE          0x602
+#define WM2200_OUT1LMIX_INPUT_2_VOLUME          0x603
+#define WM2200_OUT1LMIX_INPUT_3_SOURCE          0x604
+#define WM2200_OUT1LMIX_INPUT_3_VOLUME          0x605
+#define WM2200_OUT1LMIX_INPUT_4_SOURCE          0x606
+#define WM2200_OUT1LMIX_INPUT_4_VOLUME          0x607
+#define WM2200_OUT1RMIX_INPUT_1_SOURCE          0x608
+#define WM2200_OUT1RMIX_INPUT_1_VOLUME          0x609
+#define WM2200_OUT1RMIX_INPUT_2_SOURCE          0x60A
+#define WM2200_OUT1RMIX_INPUT_2_VOLUME          0x60B
+#define WM2200_OUT1RMIX_INPUT_3_SOURCE          0x60C
+#define WM2200_OUT1RMIX_INPUT_3_VOLUME          0x60D
+#define WM2200_OUT1RMIX_INPUT_4_SOURCE          0x60E
+#define WM2200_OUT1RMIX_INPUT_4_VOLUME          0x60F
+#define WM2200_OUT2LMIX_INPUT_1_SOURCE          0x610
+#define WM2200_OUT2LMIX_INPUT_1_VOLUME          0x611
+#define WM2200_OUT2LMIX_INPUT_2_SOURCE          0x612
+#define WM2200_OUT2LMIX_INPUT_2_VOLUME          0x613
+#define WM2200_OUT2LMIX_INPUT_3_SOURCE          0x614
+#define WM2200_OUT2LMIX_INPUT_3_VOLUME          0x615
+#define WM2200_OUT2LMIX_INPUT_4_SOURCE          0x616
+#define WM2200_OUT2LMIX_INPUT_4_VOLUME          0x617
+#define WM2200_OUT2RMIX_INPUT_1_SOURCE          0x618
+#define WM2200_OUT2RMIX_INPUT_1_VOLUME          0x619
+#define WM2200_OUT2RMIX_INPUT_2_SOURCE          0x61A
+#define WM2200_OUT2RMIX_INPUT_2_VOLUME          0x61B
+#define WM2200_OUT2RMIX_INPUT_3_SOURCE          0x61C
+#define WM2200_OUT2RMIX_INPUT_3_VOLUME          0x61D
+#define WM2200_OUT2RMIX_INPUT_4_SOURCE          0x61E
+#define WM2200_OUT2RMIX_INPUT_4_VOLUME          0x61F
+#define WM2200_AIF1TX1MIX_INPUT_1_SOURCE        0x620
+#define WM2200_AIF1TX1MIX_INPUT_1_VOLUME        0x621
+#define WM2200_AIF1TX1MIX_INPUT_2_SOURCE        0x622
+#define WM2200_AIF1TX1MIX_INPUT_2_VOLUME        0x623
+#define WM2200_AIF1TX1MIX_INPUT_3_SOURCE        0x624
+#define WM2200_AIF1TX1MIX_INPUT_3_VOLUME        0x625
+#define WM2200_AIF1TX1MIX_INPUT_4_SOURCE        0x626
+#define WM2200_AIF1TX1MIX_INPUT_4_VOLUME        0x627
+#define WM2200_AIF1TX2MIX_INPUT_1_SOURCE        0x628
+#define WM2200_AIF1TX2MIX_INPUT_1_VOLUME        0x629
+#define WM2200_AIF1TX2MIX_INPUT_2_SOURCE        0x62A
+#define WM2200_AIF1TX2MIX_INPUT_2_VOLUME        0x62B
+#define WM2200_AIF1TX2MIX_INPUT_3_SOURCE        0x62C
+#define WM2200_AIF1TX2MIX_INPUT_3_VOLUME        0x62D
+#define WM2200_AIF1TX2MIX_INPUT_4_SOURCE        0x62E
+#define WM2200_AIF1TX2MIX_INPUT_4_VOLUME        0x62F
+#define WM2200_AIF1TX3MIX_INPUT_1_SOURCE        0x630
+#define WM2200_AIF1TX3MIX_INPUT_1_VOLUME        0x631
+#define WM2200_AIF1TX3MIX_INPUT_2_SOURCE        0x632
+#define WM2200_AIF1TX3MIX_INPUT_2_VOLUME        0x633
+#define WM2200_AIF1TX3MIX_INPUT_3_SOURCE        0x634
+#define WM2200_AIF1TX3MIX_INPUT_3_VOLUME        0x635
+#define WM2200_AIF1TX3MIX_INPUT_4_SOURCE        0x636
+#define WM2200_AIF1TX3MIX_INPUT_4_VOLUME        0x637
+#define WM2200_AIF1TX4MIX_INPUT_1_SOURCE        0x638
+#define WM2200_AIF1TX4MIX_INPUT_1_VOLUME        0x639
+#define WM2200_AIF1TX4MIX_INPUT_2_SOURCE        0x63A
+#define WM2200_AIF1TX4MIX_INPUT_2_VOLUME        0x63B
+#define WM2200_AIF1TX4MIX_INPUT_3_SOURCE        0x63C
+#define WM2200_AIF1TX4MIX_INPUT_3_VOLUME        0x63D
+#define WM2200_AIF1TX4MIX_INPUT_4_SOURCE        0x63E
+#define WM2200_AIF1TX4MIX_INPUT_4_VOLUME        0x63F
+#define WM2200_AIF1TX5MIX_INPUT_1_SOURCE        0x640
+#define WM2200_AIF1TX5MIX_INPUT_1_VOLUME        0x641
+#define WM2200_AIF1TX5MIX_INPUT_2_SOURCE        0x642
+#define WM2200_AIF1TX5MIX_INPUT_2_VOLUME        0x643
+#define WM2200_AIF1TX5MIX_INPUT_3_SOURCE        0x644
+#define WM2200_AIF1TX5MIX_INPUT_3_VOLUME        0x645
+#define WM2200_AIF1TX5MIX_INPUT_4_SOURCE        0x646
+#define WM2200_AIF1TX5MIX_INPUT_4_VOLUME        0x647
+#define WM2200_AIF1TX6MIX_INPUT_1_SOURCE        0x648
+#define WM2200_AIF1TX6MIX_INPUT_1_VOLUME        0x649
+#define WM2200_AIF1TX6MIX_INPUT_2_SOURCE        0x64A
+#define WM2200_AIF1TX6MIX_INPUT_2_VOLUME        0x64B
+#define WM2200_AIF1TX6MIX_INPUT_3_SOURCE        0x64C
+#define WM2200_AIF1TX6MIX_INPUT_3_VOLUME        0x64D
+#define WM2200_AIF1TX6MIX_INPUT_4_SOURCE        0x64E
+#define WM2200_AIF1TX6MIX_INPUT_4_VOLUME        0x64F
+#define WM2200_EQLMIX_INPUT_1_SOURCE            0x650
+#define WM2200_EQLMIX_INPUT_1_VOLUME            0x651
+#define WM2200_EQLMIX_INPUT_2_SOURCE            0x652
+#define WM2200_EQLMIX_INPUT_2_VOLUME            0x653
+#define WM2200_EQLMIX_INPUT_3_SOURCE            0x654
+#define WM2200_EQLMIX_INPUT_3_VOLUME            0x655
+#define WM2200_EQLMIX_INPUT_4_SOURCE            0x656
+#define WM2200_EQLMIX_INPUT_4_VOLUME            0x657
+#define WM2200_EQRMIX_INPUT_1_SOURCE            0x658
+#define WM2200_EQRMIX_INPUT_1_VOLUME            0x659
+#define WM2200_EQRMIX_INPUT_2_SOURCE            0x65A
+#define WM2200_EQRMIX_INPUT_2_VOLUME            0x65B
+#define WM2200_EQRMIX_INPUT_3_SOURCE            0x65C
+#define WM2200_EQRMIX_INPUT_3_VOLUME            0x65D
+#define WM2200_EQRMIX_INPUT_4_SOURCE            0x65E
+#define WM2200_EQRMIX_INPUT_4_VOLUME            0x65F
+#define WM2200_LHPF1MIX_INPUT_1_SOURCE          0x660
+#define WM2200_LHPF1MIX_INPUT_1_VOLUME          0x661
+#define WM2200_LHPF1MIX_INPUT_2_SOURCE          0x662
+#define WM2200_LHPF1MIX_INPUT_2_VOLUME          0x663
+#define WM2200_LHPF1MIX_INPUT_3_SOURCE          0x664
+#define WM2200_LHPF1MIX_INPUT_3_VOLUME          0x665
+#define WM2200_LHPF1MIX_INPUT_4_SOURCE          0x666
+#define WM2200_LHPF1MIX_INPUT_4_VOLUME          0x667
+#define WM2200_LHPF2MIX_INPUT_1_SOURCE          0x668
+#define WM2200_LHPF2MIX_INPUT_1_VOLUME          0x669
+#define WM2200_LHPF2MIX_INPUT_2_SOURCE          0x66A
+#define WM2200_LHPF2MIX_INPUT_2_VOLUME          0x66B
+#define WM2200_LHPF2MIX_INPUT_3_SOURCE          0x66C
+#define WM2200_LHPF2MIX_INPUT_3_VOLUME          0x66D
+#define WM2200_LHPF2MIX_INPUT_4_SOURCE          0x66E
+#define WM2200_LHPF2MIX_INPUT_4_VOLUME          0x66F
+#define WM2200_DSP1LMIX_INPUT_1_SOURCE          0x670
+#define WM2200_DSP1LMIX_INPUT_1_VOLUME          0x671
+#define WM2200_DSP1LMIX_INPUT_2_SOURCE          0x672
+#define WM2200_DSP1LMIX_INPUT_2_VOLUME          0x673
+#define WM2200_DSP1LMIX_INPUT_3_SOURCE          0x674
+#define WM2200_DSP1LMIX_INPUT_3_VOLUME          0x675
+#define WM2200_DSP1LMIX_INPUT_4_SOURCE          0x676
+#define WM2200_DSP1LMIX_INPUT_4_VOLUME          0x677
+#define WM2200_DSP1RMIX_INPUT_1_SOURCE          0x678
+#define WM2200_DSP1RMIX_INPUT_1_VOLUME          0x679
+#define WM2200_DSP1RMIX_INPUT_2_SOURCE          0x67A
+#define WM2200_DSP1RMIX_INPUT_2_VOLUME          0x67B
+#define WM2200_DSP1RMIX_INPUT_3_SOURCE          0x67C
+#define WM2200_DSP1RMIX_INPUT_3_VOLUME          0x67D
+#define WM2200_DSP1RMIX_INPUT_4_SOURCE          0x67E
+#define WM2200_DSP1RMIX_INPUT_4_VOLUME          0x67F
+#define WM2200_DSP1AUX1MIX_INPUT_1_SOURCE       0x680
+#define WM2200_DSP1AUX2MIX_INPUT_1_SOURCE       0x681
+#define WM2200_DSP1AUX3MIX_INPUT_1_SOURCE       0x682
+#define WM2200_DSP1AUX4MIX_INPUT_1_SOURCE       0x683
+#define WM2200_DSP1AUX5MIX_INPUT_1_SOURCE       0x684
+#define WM2200_DSP1AUX6MIX_INPUT_1_SOURCE       0x685
+#define WM2200_DSP2LMIX_INPUT_1_SOURCE          0x686
+#define WM2200_DSP2LMIX_INPUT_1_VOLUME          0x687
+#define WM2200_DSP2LMIX_INPUT_2_SOURCE          0x688
+#define WM2200_DSP2LMIX_INPUT_2_VOLUME          0x689
+#define WM2200_DSP2LMIX_INPUT_3_SOURCE          0x68A
+#define WM2200_DSP2LMIX_INPUT_3_VOLUME          0x68B
+#define WM2200_DSP2LMIX_INPUT_4_SOURCE          0x68C
+#define WM2200_DSP2LMIX_INPUT_4_VOLUME          0x68D
+#define WM2200_DSP2RMIX_INPUT_1_SOURCE          0x68E
+#define WM2200_DSP2RMIX_INPUT_1_VOLUME          0x68F
+#define WM2200_DSP2RMIX_INPUT_2_SOURCE          0x690
+#define WM2200_DSP2RMIX_INPUT_2_VOLUME          0x691
+#define WM2200_DSP2RMIX_INPUT_3_SOURCE          0x692
+#define WM2200_DSP2RMIX_INPUT_3_VOLUME          0x693
+#define WM2200_DSP2RMIX_INPUT_4_SOURCE          0x694
+#define WM2200_DSP2RMIX_INPUT_4_VOLUME          0x695
+#define WM2200_DSP2AUX1MIX_INPUT_1_SOURCE       0x696
+#define WM2200_DSP2AUX2MIX_INPUT_1_SOURCE       0x697
+#define WM2200_DSP2AUX3MIX_INPUT_1_SOURCE       0x698
+#define WM2200_DSP2AUX4MIX_INPUT_1_SOURCE       0x699
+#define WM2200_DSP2AUX5MIX_INPUT_1_SOURCE       0x69A
+#define WM2200_DSP2AUX6MIX_INPUT_1_SOURCE       0x69B
+#define WM2200_GPIO_CTRL_1                      0x700
+#define WM2200_GPIO_CTRL_2                      0x701
+#define WM2200_GPIO_CTRL_3                      0x702
+#define WM2200_GPIO_CTRL_4                      0x703
+#define WM2200_ADPS1_IRQ0                       0x707
+#define WM2200_ADPS1_IRQ1                       0x708
+#define WM2200_MISC_PAD_CTRL_1                  0x709
+#define WM2200_INTERRUPT_STATUS_1               0x800
+#define WM2200_INTERRUPT_STATUS_1_MASK          0x801
+#define WM2200_INTERRUPT_STATUS_2               0x802
+#define WM2200_INTERRUPT_RAW_STATUS_2           0x803
+#define WM2200_INTERRUPT_STATUS_2_MASK          0x804
+#define WM2200_INTERRUPT_CONTROL                0x808
+#define WM2200_EQL_1                            0x900
+#define WM2200_EQL_2                            0x901
+#define WM2200_EQL_3                            0x902
+#define WM2200_EQL_4                            0x903
+#define WM2200_EQL_5                            0x904
+#define WM2200_EQL_6                            0x905
+#define WM2200_EQL_7                            0x906
+#define WM2200_EQL_8                            0x907
+#define WM2200_EQL_9                            0x908
+#define WM2200_EQL_10                           0x909
+#define WM2200_EQL_11                           0x90A
+#define WM2200_EQL_12                           0x90B
+#define WM2200_EQL_13                           0x90C
+#define WM2200_EQL_14                           0x90D
+#define WM2200_EQL_15                           0x90E
+#define WM2200_EQL_16                           0x90F
+#define WM2200_EQL_17                           0x910
+#define WM2200_EQL_18                           0x911
+#define WM2200_EQL_19                           0x912
+#define WM2200_EQL_20                           0x913
+#define WM2200_EQR_1                            0x916
+#define WM2200_EQR_2                            0x917
+#define WM2200_EQR_3                            0x918
+#define WM2200_EQR_4                            0x919
+#define WM2200_EQR_5                            0x91A
+#define WM2200_EQR_6                            0x91B
+#define WM2200_EQR_7                            0x91C
+#define WM2200_EQR_8                            0x91D
+#define WM2200_EQR_9                            0x91E
+#define WM2200_EQR_10                           0x91F
+#define WM2200_EQR_11                           0x920
+#define WM2200_EQR_12                           0x921
+#define WM2200_EQR_13                           0x922
+#define WM2200_EQR_14                           0x923
+#define WM2200_EQR_15                           0x924
+#define WM2200_EQR_16                           0x925
+#define WM2200_EQR_17                           0x926
+#define WM2200_EQR_18                           0x927
+#define WM2200_EQR_19                           0x928
+#define WM2200_EQR_20                           0x929
+#define WM2200_HPLPF1_1                         0x93E
+#define WM2200_HPLPF1_2                         0x93F
+#define WM2200_HPLPF2_1                         0x942
+#define WM2200_HPLPF2_2                         0x943
+#define WM2200_DSP1_CONTROL_1                   0xA00
+#define WM2200_DSP1_CONTROL_2                   0xA02
+#define WM2200_DSP1_CONTROL_3                   0xA03
+#define WM2200_DSP1_CONTROL_4                   0xA04
+#define WM2200_DSP1_CONTROL_5                   0xA06
+#define WM2200_DSP1_CONTROL_6                   0xA07
+#define WM2200_DSP1_CONTROL_7                   0xA08
+#define WM2200_DSP1_CONTROL_8                   0xA09
+#define WM2200_DSP1_CONTROL_9                   0xA0A
+#define WM2200_DSP1_CONTROL_10                  0xA0B
+#define WM2200_DSP1_CONTROL_11                  0xA0C
+#define WM2200_DSP1_CONTROL_12                  0xA0D
+#define WM2200_DSP1_CONTROL_13                  0xA0F
+#define WM2200_DSP1_CONTROL_14                  0xA10
+#define WM2200_DSP1_CONTROL_15                  0xA11
+#define WM2200_DSP1_CONTROL_16                  0xA12
+#define WM2200_DSP1_CONTROL_17                  0xA13
+#define WM2200_DSP1_CONTROL_18                  0xA14
+#define WM2200_DSP1_CONTROL_19                  0xA16
+#define WM2200_DSP1_CONTROL_20                  0xA17
+#define WM2200_DSP1_CONTROL_21                  0xA18
+#define WM2200_DSP1_CONTROL_22                  0xA1A
+#define WM2200_DSP1_CONTROL_23                  0xA1B
+#define WM2200_DSP1_CONTROL_24                  0xA1C
+#define WM2200_DSP1_CONTROL_25                  0xA1E
+#define WM2200_DSP1_CONTROL_26                  0xA20
+#define WM2200_DSP1_CONTROL_27                  0xA21
+#define WM2200_DSP1_CONTROL_28                  0xA22
+#define WM2200_DSP1_CONTROL_29                  0xA23
+#define WM2200_DSP1_CONTROL_30                  0xA24
+#define WM2200_DSP1_CONTROL_31                  0xA26
+#define WM2200_DSP2_CONTROL_1                   0xB00
+#define WM2200_DSP2_CONTROL_2                   0xB02
+#define WM2200_DSP2_CONTROL_3                   0xB03
+#define WM2200_DSP2_CONTROL_4                   0xB04
+#define WM2200_DSP2_CONTROL_5                   0xB06
+#define WM2200_DSP2_CONTROL_6                   0xB07
+#define WM2200_DSP2_CONTROL_7                   0xB08
+#define WM2200_DSP2_CONTROL_8                   0xB09
+#define WM2200_DSP2_CONTROL_9                   0xB0A
+#define WM2200_DSP2_CONTROL_10                  0xB0B
+#define WM2200_DSP2_CONTROL_11                  0xB0C
+#define WM2200_DSP2_CONTROL_12                  0xB0D
+#define WM2200_DSP2_CONTROL_13                  0xB0F
+#define WM2200_DSP2_CONTROL_14                  0xB10
+#define WM2200_DSP2_CONTROL_15                  0xB11
+#define WM2200_DSP2_CONTROL_16                  0xB12
+#define WM2200_DSP2_CONTROL_17                  0xB13
+#define WM2200_DSP2_CONTROL_18                  0xB14
+#define WM2200_DSP2_CONTROL_19                  0xB16
+#define WM2200_DSP2_CONTROL_20                  0xB17
+#define WM2200_DSP2_CONTROL_21                  0xB18
+#define WM2200_DSP2_CONTROL_22                  0xB1A
+#define WM2200_DSP2_CONTROL_23                  0xB1B
+#define WM2200_DSP2_CONTROL_24                  0xB1C
+#define WM2200_DSP2_CONTROL_25                  0xB1E
+#define WM2200_DSP2_CONTROL_26                  0xB20
+#define WM2200_DSP2_CONTROL_27                  0xB21
+#define WM2200_DSP2_CONTROL_28                  0xB22
+#define WM2200_DSP2_CONTROL_29                  0xB23
+#define WM2200_DSP2_CONTROL_30                  0xB24
+#define WM2200_DSP2_CONTROL_31                  0xB26
+#define WM2200_ANC_CTRL1                        0xD00
+#define WM2200_ANC_CTRL2                        0xD01
+#define WM2200_ANC_CTRL3                        0xD02
+#define WM2200_ANC_CTRL7                        0xD08
+#define WM2200_ANC_CTRL8                        0xD09
+#define WM2200_ANC_CTRL9                        0xD0A
+#define WM2200_ANC_CTRL10                       0xD0B
+#define WM2200_ANC_CTRL11                       0xD0C
+#define WM2200_ANC_CTRL12                       0xD0D
+#define WM2200_ANC_CTRL13                       0xD0E
+#define WM2200_ANC_CTRL14                       0xD0F
+#define WM2200_ANC_CTRL15                       0xD10
+#define WM2200_ANC_CTRL16                       0xD11
+#define WM2200_ANC_CTRL17                       0xD12
+#define WM2200_ANC_CTRL18                       0xD15
+#define WM2200_ANC_CTRL19                       0xD16
+#define WM2200_ANC_CTRL20                       0xD17
+#define WM2200_ANC_CTRL21                       0xD18
+#define WM2200_ANC_CTRL22                       0xD19
+#define WM2200_ANC_CTRL23                       0xD1A
+#define WM2200_ANC_CTRL24                       0xD1B
+#define WM2200_ANC_CTRL25                       0xD1C
+#define WM2200_ANC_CTRL26                       0xD1D
+#define WM2200_ANC_CTRL27                       0xD1E
+#define WM2200_ANC_CTRL28                       0xD1F
+#define WM2200_ANC_CTRL29                       0xD20
+#define WM2200_ANC_CTRL30                       0xD21
+#define WM2200_ANC_CTRL31                       0xD23
+#define WM2200_ANC_CTRL32                       0xD24
+#define WM2200_ANC_CTRL33                       0xD25
+#define WM2200_ANC_CTRL34                       0xD27
+#define WM2200_ANC_CTRL35                       0xD28
+#define WM2200_ANC_CTRL36                       0xD29
+#define WM2200_ANC_CTRL37                       0xD2A
+#define WM2200_ANC_CTRL38                       0xD2B
+#define WM2200_ANC_CTRL39                       0xD2C
+#define WM2200_ANC_CTRL40                       0xD2D
+#define WM2200_ANC_CTRL41                       0xD2E
+#define WM2200_ANC_CTRL42                       0xD2F
+#define WM2200_ANC_CTRL43                       0xD30
+#define WM2200_ANC_CTRL44                       0xD31
+#define WM2200_ANC_CTRL45                       0xD32
+#define WM2200_ANC_CTRL46                       0xD33
+#define WM2200_ANC_CTRL47                       0xD34
+#define WM2200_ANC_CTRL48                       0xD35
+#define WM2200_ANC_CTRL49                       0xD36
+#define WM2200_ANC_CTRL50                       0xD37
+#define WM2200_ANC_CTRL51                       0xD38
+#define WM2200_ANC_CTRL52                       0xD39
+#define WM2200_ANC_CTRL53                       0xD3A
+#define WM2200_ANC_CTRL54                       0xD3B
+#define WM2200_ANC_CTRL55                       0xD3C
+#define WM2200_ANC_CTRL56                       0xD3D
+#define WM2200_ANC_CTRL57                       0xD3E
+#define WM2200_ANC_CTRL58                       0xD3F
+#define WM2200_ANC_CTRL59                       0xD40
+#define WM2200_ANC_CTRL60                       0xD41
+#define WM2200_ANC_CTRL61                       0xD42
+#define WM2200_ANC_CTRL62                       0xD43
+#define WM2200_ANC_CTRL63                       0xD44
+#define WM2200_ANC_CTRL64                       0xD45
+#define WM2200_ANC_CTRL65                       0xD46
+#define WM2200_ANC_CTRL66                       0xD47
+#define WM2200_ANC_CTRL67                       0xD48
+#define WM2200_ANC_CTRL68                       0xD49
+#define WM2200_ANC_CTRL69                       0xD4A
+#define WM2200_ANC_CTRL70                       0xD4B
+#define WM2200_ANC_CTRL71                       0xD4C
+#define WM2200_ANC_CTRL72                       0xD4D
+#define WM2200_ANC_CTRL73                       0xD4E
+#define WM2200_ANC_CTRL74                       0xD4F
+#define WM2200_ANC_CTRL75                       0xD50
+#define WM2200_ANC_CTRL76                       0xD51
+#define WM2200_ANC_CTRL77                       0xD52
+#define WM2200_ANC_CTRL78                       0xD53
+#define WM2200_ANC_CTRL79                       0xD54
+#define WM2200_ANC_CTRL80                       0xD55
+#define WM2200_ANC_CTRL81                       0xD56
+#define WM2200_ANC_CTRL82                       0xD57
+#define WM2200_ANC_CTRL83                       0xD58
+#define WM2200_ANC_CTRL84                       0xD5B
+#define WM2200_ANC_CTRL85                       0xD5C
+#define WM2200_ANC_CTRL86                       0xD5F
+#define WM2200_ANC_CTRL87                       0xD60
+#define WM2200_ANC_CTRL88                       0xD61
+#define WM2200_ANC_CTRL89                       0xD62
+#define WM2200_ANC_CTRL90                       0xD63
+#define WM2200_ANC_CTRL91                       0xD64
+#define WM2200_ANC_CTRL92                       0xD65
+#define WM2200_ANC_CTRL93                       0xD66
+#define WM2200_ANC_CTRL94                       0xD67
+#define WM2200_ANC_CTRL95                       0xD68
+#define WM2200_ANC_CTRL96                       0xD69
+#define WM2200_DSP1_DM_0                        0x3000
+#define WM2200_DSP1_DM_1                        0x3001
+#define WM2200_DSP1_DM_2                        0x3002
+#define WM2200_DSP1_DM_3                        0x3003
+#define WM2200_DSP1_DM_2044                     0x37FC
+#define WM2200_DSP1_DM_2045                     0x37FD
+#define WM2200_DSP1_DM_2046                     0x37FE
+#define WM2200_DSP1_DM_2047                     0x37FF
+#define WM2200_DSP1_PM_0                        0x3800
+#define WM2200_DSP1_PM_1                        0x3801
+#define WM2200_DSP1_PM_2                        0x3802
+#define WM2200_DSP1_PM_3                        0x3803
+#define WM2200_DSP1_PM_4                        0x3804
+#define WM2200_DSP1_PM_5                        0x3805
+#define WM2200_DSP1_PM_762                      0x3AFA
+#define WM2200_DSP1_PM_763                      0x3AFB
+#define WM2200_DSP1_PM_764                      0x3AFC
+#define WM2200_DSP1_PM_765                      0x3AFD
+#define WM2200_DSP1_PM_766                      0x3AFE
+#define WM2200_DSP1_PM_767                      0x3AFF
+#define WM2200_DSP1_ZM_0                        0x3C00
+#define WM2200_DSP1_ZM_1                        0x3C01
+#define WM2200_DSP1_ZM_2                        0x3C02
+#define WM2200_DSP1_ZM_3                        0x3C03
+#define WM2200_DSP1_ZM_1020                     0x3FFC
+#define WM2200_DSP1_ZM_1021                     0x3FFD
+#define WM2200_DSP1_ZM_1022                     0x3FFE
+#define WM2200_DSP1_ZM_1023                     0x3FFF
+#define WM2200_DSP2_DM_0                        0x4000
+#define WM2200_DSP2_DM_1                        0x4001
+#define WM2200_DSP2_DM_2                        0x4002
+#define WM2200_DSP2_DM_3                        0x4003
+#define WM2200_DSP2_DM_2044                     0x47FC
+#define WM2200_DSP2_DM_2045                     0x47FD
+#define WM2200_DSP2_DM_2046                     0x47FE
+#define WM2200_DSP2_DM_2047                     0x47FF
+#define WM2200_DSP2_PM_0                        0x4800
+#define WM2200_DSP2_PM_1                        0x4801
+#define WM2200_DSP2_PM_2                        0x4802
+#define WM2200_DSP2_PM_3                        0x4803
+#define WM2200_DSP2_PM_4                        0x4804
+#define WM2200_DSP2_PM_5                        0x4805
+#define WM2200_DSP2_PM_762                      0x4AFA
+#define WM2200_DSP2_PM_763                      0x4AFB
+#define WM2200_DSP2_PM_764                      0x4AFC
+#define WM2200_DSP2_PM_765                      0x4AFD
+#define WM2200_DSP2_PM_766                      0x4AFE
+#define WM2200_DSP2_PM_767                      0x4AFF
+#define WM2200_DSP2_ZM_0                        0x4C00
+#define WM2200_DSP2_ZM_1                        0x4C01
+#define WM2200_DSP2_ZM_2                        0x4C02
+#define WM2200_DSP2_ZM_3                        0x4C03
+#define WM2200_DSP2_ZM_1020                     0x4FFC
+#define WM2200_DSP2_ZM_1021                     0x4FFD
+#define WM2200_DSP2_ZM_1022                     0x4FFE
+#define WM2200_DSP2_ZM_1023                     0x4FFF
+
+#define WM2200_REGISTER_COUNT                   494
+#define WM2200_MAX_REGISTER                     0x4FFF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM2200_SW_RESET_CHIP_ID1_MASK           0xFFFF  /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_SHIFT               0  /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_WIDTH              16  /* SW_RESET_CHIP_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM2200_DEVICE_REVISION_MASK             0x000F  /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_SHIFT                 0  /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_WIDTH                 4  /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R11 (0x0B) - Tone Generator 1
+ */
+#define WM2200_TONE_ENA                         0x0001  /* TONE_ENA */
+#define WM2200_TONE_ENA_MASK                    0x0001  /* TONE_ENA */
+#define WM2200_TONE_ENA_SHIFT                        0  /* TONE_ENA */
+#define WM2200_TONE_ENA_WIDTH                        1  /* TONE_ENA */
+
+/*
+ * R258 (0x102) - Clocking 3
+ */
+#define WM2200_SYSCLK_FREQ_MASK                 0x0700  /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_SHIFT                     8  /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_WIDTH                     3  /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_ENA                       0x0040  /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_MASK                  0x0040  /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_SHIFT                      6  /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+#define WM2200_SYSCLK_SRC_MASK                  0x000F  /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_SHIFT                      0  /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_WIDTH                      4  /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R259 (0x103) - Clocking 4
+ */
+#define WM2200_SAMPLE_RATE_1_MASK               0x001F  /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_SHIFT                   0  /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_WIDTH                   5  /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R273 (0x111) - FLL Control 1
+ */
+#define WM2200_FLL_ENA                          0x0001  /* FLL_ENA */
+#define WM2200_FLL_ENA_MASK                     0x0001  /* FLL_ENA */
+#define WM2200_FLL_ENA_SHIFT                         0  /* FLL_ENA */
+#define WM2200_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+
+/*
+ * R274 (0x112) - FLL Control 2
+ */
+#define WM2200_FLL_OUTDIV_MASK                  0x3F00  /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_SHIFT                      8  /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_WIDTH                      6  /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_FRATIO_MASK                  0x0007  /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_WIDTH                      3  /* FLL_FRATIO - [2:0] */
+
+/*
+ * R275 (0x113) - FLL Control 3
+ */
+#define WM2200_FLL_FRACN_ENA                    0x0001  /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_MASK               0x0001  /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_SHIFT                   0  /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_WIDTH                   1  /* FLL_FRACN_ENA */
+
+/*
+ * R276 (0x114) - FLL Control 4
+ */
+#define WM2200_FLL_THETA_MASK                   0xFFFF  /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_SHIFT                       0  /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_WIDTH                      16  /* FLL_THETA - [15:0] */
+
+/*
+ * R278 (0x116) - FLL Control 6
+ */
+#define WM2200_FLL_N_MASK                       0x03FF  /* FLL_N - [9:0] */
+#define WM2200_FLL_N_SHIFT                           0  /* FLL_N - [9:0] */
+#define WM2200_FLL_N_WIDTH                          10  /* FLL_N - [9:0] */
+
+/*
+ * R279 (0x117) - FLL Control 7
+ */
+#define WM2200_FLL_CLK_REF_DIV_MASK             0x0030  /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_SHIFT                 4  /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_WIDTH                 2  /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_SRC_MASK             0x0003  /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_SHIFT                 0  /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_WIDTH                 2  /* FLL_CLK_REF_SRC - [1:0] */
+
+/*
+ * R281 (0x119) - FLL EFS 1
+ */
+#define WM2200_FLL_LAMBDA_MASK                  0xFFFF  /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_SHIFT                      0  /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_WIDTH                     16  /* FLL_LAMBDA - [15:0] */
+
+/*
+ * R282 (0x11A) - FLL EFS 2
+ */
+#define WM2200_FLL_EFS_ENA                      0x0001  /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_MASK                 0x0001  /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_SHIFT                     0  /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_WIDTH                     1  /* FLL_EFS_ENA */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM2200_CPMIC_BYPASS_MODE                0x0020  /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_MASK           0x0020  /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_SHIFT               5  /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_WIDTH               1  /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_ENA                        0x0001  /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_MASK                   0x0001  /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_SHIFT                       0  /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_WIDTH                       1  /* CPMIC_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_MASK     0xF800  /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_SHIFT        11  /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_WIDTH         5  /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+
+/*
+ * R514 (0x202) - DM Charge Pump 1
+ */
+#define WM2200_CPDM_ENA                         0x0001  /* CPDM_ENA */
+#define WM2200_CPDM_ENA_MASK                    0x0001  /* CPDM_ENA */
+#define WM2200_CPDM_ENA_SHIFT                        0  /* CPDM_ENA */
+#define WM2200_CPDM_ENA_WIDTH                        1  /* CPDM_ENA */
+
+/*
+ * R524 (0x20C) - Mic Bias Ctrl 1
+ */
+#define WM2200_MICB1_DISCH                      0x0040  /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_MASK                 0x0040  /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_SHIFT                     6  /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
+#define WM2200_MICB1_RATE                       0x0020  /* MICB1_RATE */
+#define WM2200_MICB1_RATE_MASK                  0x0020  /* MICB1_RATE */
+#define WM2200_MICB1_RATE_SHIFT                      5  /* MICB1_RATE */
+#define WM2200_MICB1_RATE_WIDTH                      1  /* MICB1_RATE */
+#define WM2200_MICB1_LVL_MASK                   0x001C  /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_SHIFT                       2  /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_WIDTH                       3  /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_MODE                       0x0002  /* MICB1_MODE */
+#define WM2200_MICB1_MODE_MASK                  0x0002  /* MICB1_MODE */
+#define WM2200_MICB1_MODE_SHIFT                      1  /* MICB1_MODE */
+#define WM2200_MICB1_MODE_WIDTH                      1  /* MICB1_MODE */
+#define WM2200_MICB1_ENA                        0x0001  /* MICB1_ENA */
+#define WM2200_MICB1_ENA_MASK                   0x0001  /* MICB1_ENA */
+#define WM2200_MICB1_ENA_SHIFT                       0  /* MICB1_ENA */
+#define WM2200_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
+
+/*
+ * R525 (0x20D) - Mic Bias Ctrl 2
+ */
+#define WM2200_MICB2_DISCH                      0x0040  /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_MASK                 0x0040  /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_SHIFT                     6  /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
+#define WM2200_MICB2_RATE                       0x0020  /* MICB2_RATE */
+#define WM2200_MICB2_RATE_MASK                  0x0020  /* MICB2_RATE */
+#define WM2200_MICB2_RATE_SHIFT                      5  /* MICB2_RATE */
+#define WM2200_MICB2_RATE_WIDTH                      1  /* MICB2_RATE */
+#define WM2200_MICB2_LVL_MASK                   0x001C  /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_SHIFT                       2  /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_WIDTH                       3  /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_MODE                       0x0002  /* MICB2_MODE */
+#define WM2200_MICB2_MODE_MASK                  0x0002  /* MICB2_MODE */
+#define WM2200_MICB2_MODE_SHIFT                      1  /* MICB2_MODE */
+#define WM2200_MICB2_MODE_WIDTH                      1  /* MICB2_MODE */
+#define WM2200_MICB2_ENA                        0x0001  /* MICB2_ENA */
+#define WM2200_MICB2_ENA_MASK                   0x0001  /* MICB2_ENA */
+#define WM2200_MICB2_ENA_SHIFT                       0  /* MICB2_ENA */
+#define WM2200_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
+
+/*
+ * R527 (0x20F) - Ear Piece Ctrl 1
+ */
+#define WM2200_EPD_LP_ENA                       0x4000  /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_MASK                  0x4000  /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_SHIFT                     14  /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_WIDTH                      1  /* EPD_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA                  0x2000  /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_MASK             0x2000  /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_SHIFT                13  /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_WIDTH                 1  /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_RMV_SHRT_LP                  0x1000  /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_MASK             0x1000  /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_SHIFT                12  /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_WIDTH                 1  /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_LN_ENA                       0x0800  /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_MASK                  0x0800  /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_SHIFT                     11  /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_WIDTH                      1  /* EPD_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA                  0x0400  /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_MASK             0x0400  /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_SHIFT                10  /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_WIDTH                 1  /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_RMV_SHRT_LN                  0x0200  /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_MASK             0x0200  /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_SHIFT                 9  /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_WIDTH                 1  /* EPD_RMV_SHRT_LN */
+
+/*
+ * R528 (0x210) - Ear Piece Ctrl 2
+ */
+#define WM2200_EPD_RP_ENA                       0x4000  /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_MASK                  0x4000  /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_SHIFT                     14  /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_WIDTH                      1  /* EPD_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA                  0x2000  /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_MASK             0x2000  /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_SHIFT                13  /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_WIDTH                 1  /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_RMV_SHRT_RP                  0x1000  /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_MASK             0x1000  /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_SHIFT                12  /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_WIDTH                 1  /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RN_ENA                       0x0800  /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_MASK                  0x0800  /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_SHIFT                     11  /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_WIDTH                      1  /* EPD_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA                  0x0400  /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_MASK             0x0400  /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_SHIFT                10  /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_WIDTH                 1  /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_RMV_SHRT_RN                  0x0200  /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_MASK             0x0200  /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_SHIFT                 9  /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_WIDTH                 1  /* EPD_RMV_SHRT_RN */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM2200_IN3L_ENA                         0x0020  /* IN3L_ENA */
+#define WM2200_IN3L_ENA_MASK                    0x0020  /* IN3L_ENA */
+#define WM2200_IN3L_ENA_SHIFT                        5  /* IN3L_ENA */
+#define WM2200_IN3L_ENA_WIDTH                        1  /* IN3L_ENA */
+#define WM2200_IN3R_ENA                         0x0010  /* IN3R_ENA */
+#define WM2200_IN3R_ENA_MASK                    0x0010  /* IN3R_ENA */
+#define WM2200_IN3R_ENA_SHIFT                        4  /* IN3R_ENA */
+#define WM2200_IN3R_ENA_WIDTH                        1  /* IN3R_ENA */
+#define WM2200_IN2L_ENA                         0x0008  /* IN2L_ENA */
+#define WM2200_IN2L_ENA_MASK                    0x0008  /* IN2L_ENA */
+#define WM2200_IN2L_ENA_SHIFT                        3  /* IN2L_ENA */
+#define WM2200_IN2L_ENA_WIDTH                        1  /* IN2L_ENA */
+#define WM2200_IN2R_ENA                         0x0004  /* IN2R_ENA */
+#define WM2200_IN2R_ENA_MASK                    0x0004  /* IN2R_ENA */
+#define WM2200_IN2R_ENA_SHIFT                        2  /* IN2R_ENA */
+#define WM2200_IN2R_ENA_WIDTH                        1  /* IN2R_ENA */
+#define WM2200_IN1L_ENA                         0x0002  /* IN1L_ENA */
+#define WM2200_IN1L_ENA_MASK                    0x0002  /* IN1L_ENA */
+#define WM2200_IN1L_ENA_SHIFT                        1  /* IN1L_ENA */
+#define WM2200_IN1L_ENA_WIDTH                        1  /* IN1L_ENA */
+#define WM2200_IN1R_ENA                         0x0001  /* IN1R_ENA */
+#define WM2200_IN1R_ENA_MASK                    0x0001  /* IN1R_ENA */
+#define WM2200_IN1R_ENA_SHIFT                        0  /* IN1R_ENA */
+#define WM2200_IN1R_ENA_WIDTH                        1  /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - IN1L Control
+ */
+#define WM2200_IN1_OSR                          0x2000  /* IN1_OSR */
+#define WM2200_IN1_OSR_MASK                     0x2000  /* IN1_OSR */
+#define WM2200_IN1_OSR_SHIFT                        13  /* IN1_OSR */
+#define WM2200_IN1_OSR_WIDTH                         1  /* IN1_OSR */
+#define WM2200_IN1_DMIC_SUP_MASK                0x1800  /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_SHIFT                   11  /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_WIDTH                    2  /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_MODE_MASK                    0x0600  /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_SHIFT                        9  /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_WIDTH                        2  /* IN1_MODE - [10:9] */
+#define WM2200_IN1L_PGA_VOL_MASK                0x00FE  /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_SHIFT                    1  /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_WIDTH                    7  /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R771 (0x303) - IN1R Control
+ */
+#define WM2200_IN1R_PGA_VOL_MASK                0x00FE  /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_SHIFT                    1  /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_WIDTH                    7  /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R772 (0x304) - IN2L Control
+ */
+#define WM2200_IN2_OSR                          0x2000  /* IN2_OSR */
+#define WM2200_IN2_OSR_MASK                     0x2000  /* IN2_OSR */
+#define WM2200_IN2_OSR_SHIFT                        13  /* IN2_OSR */
+#define WM2200_IN2_OSR_WIDTH                         1  /* IN2_OSR */
+#define WM2200_IN2_DMIC_SUP_MASK                0x1800  /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_SHIFT                   11  /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_WIDTH                    2  /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_MODE_MASK                    0x0600  /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_SHIFT                        9  /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_WIDTH                        2  /* IN2_MODE - [10:9] */
+#define WM2200_IN2L_PGA_VOL_MASK                0x00FE  /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_SHIFT                    1  /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_WIDTH                    7  /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R773 (0x305) - IN2R Control
+ */
+#define WM2200_IN2R_PGA_VOL_MASK                0x00FE  /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_SHIFT                    1  /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_WIDTH                    7  /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R774 (0x306) - IN3L Control
+ */
+#define WM2200_IN3_OSR                          0x2000  /* IN3_OSR */
+#define WM2200_IN3_OSR_MASK                     0x2000  /* IN3_OSR */
+#define WM2200_IN3_OSR_SHIFT                        13  /* IN3_OSR */
+#define WM2200_IN3_OSR_WIDTH                         1  /* IN3_OSR */
+#define WM2200_IN3_DMIC_SUP_MASK                0x1800  /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_SHIFT                   11  /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_WIDTH                    2  /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_MODE_MASK                    0x0600  /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_SHIFT                        9  /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_WIDTH                        2  /* IN3_MODE - [10:9] */
+#define WM2200_IN3L_PGA_VOL_MASK                0x00FE  /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_SHIFT                    1  /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_WIDTH                    7  /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R775 (0x307) - IN3R Control
+ */
+#define WM2200_IN3R_PGA_VOL_MASK                0x00FE  /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_SHIFT                    1  /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_WIDTH                    7  /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R778 (0x30A) - RXANC_SRC
+ */
+#define WM2200_IN_RXANC_SEL_MASK                0x0007  /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_SHIFT                    0  /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_WIDTH                    3  /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R779 (0x30B) - Input Volume Ramp
+ */
+#define WM2200_IN_VD_RAMP_MASK                  0x0070  /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_SHIFT                      4  /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_WIDTH                      3  /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VI_RAMP_MASK                  0x0007  /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_SHIFT                      0  /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_WIDTH                      3  /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R780 (0x30C) - ADC Digital Volume 1L
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN1L_MUTE                        0x0100  /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_MASK                   0x0100  /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_SHIFT                       8  /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_WIDTH                       1  /* IN1L_MUTE */
+#define WM2200_IN1L_DIG_VOL_MASK                0x00FF  /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_SHIFT                    0  /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_WIDTH                    8  /* IN1L_DIG_VOL - [7:0] */
+
+/*
+ * R781 (0x30D) - ADC Digital Volume 1R
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN1R_MUTE                        0x0100  /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_MASK                   0x0100  /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_SHIFT                       8  /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_WIDTH                       1  /* IN1R_MUTE */
+#define WM2200_IN1R_DIG_VOL_MASK                0x00FF  /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_SHIFT                    0  /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_WIDTH                    8  /* IN1R_DIG_VOL - [7:0] */
+
+/*
+ * R782 (0x30E) - ADC Digital Volume 2L
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN2L_MUTE                        0x0100  /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_MASK                   0x0100  /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_SHIFT                       8  /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_WIDTH                       1  /* IN2L_MUTE */
+#define WM2200_IN2L_DIG_VOL_MASK                0x00FF  /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_SHIFT                    0  /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_WIDTH                    8  /* IN2L_DIG_VOL - [7:0] */
+
+/*
+ * R783 (0x30F) - ADC Digital Volume 2R
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN2R_MUTE                        0x0100  /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_MASK                   0x0100  /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_SHIFT                       8  /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_WIDTH                       1  /* IN2R_MUTE */
+#define WM2200_IN2R_DIG_VOL_MASK                0x00FF  /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_SHIFT                    0  /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_WIDTH                    8  /* IN2R_DIG_VOL - [7:0] */
+
+/*
+ * R784 (0x310) - ADC Digital Volume 3L
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN3L_MUTE                        0x0100  /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_MASK                   0x0100  /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_SHIFT                       8  /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_WIDTH                       1  /* IN3L_MUTE */
+#define WM2200_IN3L_DIG_VOL_MASK                0x00FF  /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_SHIFT                    0  /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_WIDTH                    8  /* IN3L_DIG_VOL - [7:0] */
+
+/*
+ * R785 (0x311) - ADC Digital Volume 3R
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN3R_MUTE                        0x0100  /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_MASK                   0x0100  /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_SHIFT                       8  /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_WIDTH                       1  /* IN3R_MUTE */
+#define WM2200_IN3R_DIG_VOL_MASK                0x00FF  /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_SHIFT                    0  /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_WIDTH                    8  /* IN3R_DIG_VOL - [7:0] */
+
+/*
+ * R1024 (0x400) - Output Enables
+ */
+#define WM2200_OUT2L_ENA                        0x0008  /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_MASK                   0x0008  /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_SHIFT                       3  /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_WIDTH                       1  /* OUT2L_ENA */
+#define WM2200_OUT2R_ENA                        0x0004  /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_MASK                   0x0004  /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_SHIFT                       2  /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_WIDTH                       1  /* OUT2R_ENA */
+#define WM2200_OUT1L_ENA                        0x0002  /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_MASK                   0x0002  /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_SHIFT                       1  /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_WIDTH                       1  /* OUT1L_ENA */
+#define WM2200_OUT1R_ENA                        0x0001  /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_MASK                   0x0001  /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_SHIFT                       0  /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_WIDTH                       1  /* OUT1R_ENA */
+
+/*
+ * R1025 (0x401) - DAC Volume Limit 1L
+ */
+#define WM2200_OUT1_OSR                         0x2000  /* OUT1_OSR */
+#define WM2200_OUT1_OSR_MASK                    0x2000  /* OUT1_OSR */
+#define WM2200_OUT1_OSR_SHIFT                       13  /* OUT1_OSR */
+#define WM2200_OUT1_OSR_WIDTH                        1  /* OUT1_OSR */
+#define WM2200_OUT1L_ANC_SRC                    0x0800  /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_MASK               0x0800  /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_SHIFT                  11  /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_WIDTH                   1  /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_PGA_VOL_MASK               0x00FE  /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_SHIFT                   1  /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_WIDTH                   7  /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1026 (0x402) - DAC Volume Limit 1R
+ */
+#define WM2200_OUT1R_ANC_SRC                    0x0800  /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_MASK               0x0800  /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_SHIFT                  11  /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_WIDTH                   1  /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_PGA_VOL_MASK               0x00FE  /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_SHIFT                   1  /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_WIDTH                   7  /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1027 (0x403) - DAC Volume Limit 2L
+ */
+#define WM2200_OUT2_OSR                         0x2000  /* OUT2_OSR */
+#define WM2200_OUT2_OSR_MASK                    0x2000  /* OUT2_OSR */
+#define WM2200_OUT2_OSR_SHIFT                       13  /* OUT2_OSR */
+#define WM2200_OUT2_OSR_WIDTH                        1  /* OUT2_OSR */
+#define WM2200_OUT2L_ANC_SRC                    0x0800  /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_MASK               0x0800  /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_SHIFT                  11  /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_WIDTH                   1  /* OUT2L_ANC_SRC */
+
+/*
+ * R1028 (0x404) - DAC Volume Limit 2R
+ */
+#define WM2200_OUT2R_ANC_SRC                    0x0800  /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_MASK               0x0800  /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_SHIFT                  11  /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_WIDTH                   1  /* OUT2R_ANC_SRC */
+
+/*
+ * R1033 (0x409) - DAC AEC Control 1
+ */
+#define WM2200_AEC_LOOPBACK_ENA                 0x0004  /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_MASK            0x0004  /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_SHIFT                2  /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_WIDTH                1  /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_SRC_MASK            0x0003  /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_SHIFT                0  /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_WIDTH                2  /* AEC_LOOPBACK_SRC - [1:0] */
+
+/*
+ * R1034 (0x40A) - Output Volume Ramp
+ */
+#define WM2200_OUT_VD_RAMP_MASK                 0x0070  /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_SHIFT                     4  /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_WIDTH                     3  /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VI_RAMP_MASK                 0x0007  /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_SHIFT                     0  /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_WIDTH                     3  /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1035 (0x40B) - DAC Digital Volume 1L
+ */
+#define WM2200_OUT_VU                           0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM2200_OUT1L_MUTE                       0x0100  /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_MASK                  0x0100  /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_SHIFT                      8  /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_WIDTH                      1  /* OUT1L_MUTE */
+#define WM2200_OUT1L_VOL_MASK                   0x00FF  /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_SHIFT                       0  /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_WIDTH                       8  /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1036 (0x40C) - DAC Digital Volume 1R
+ */
+#define WM2200_OUT_VU                           0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM2200_OUT1R_MUTE                       0x0100  /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_MASK                  0x0100  /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_SHIFT                      8  /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_WIDTH                      1  /* OUT1R_MUTE */
+#define WM2200_OUT1R_VOL_MASK                   0x00FF  /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_SHIFT                       0  /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_WIDTH                       8  /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1037 (0x40D) - DAC Digital Volume 2L
+ */
+#define WM2200_OUT_VU                           0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM2200_OUT2L_MUTE                       0x0100  /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_MASK                  0x0100  /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_SHIFT                      8  /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_WIDTH                      1  /* OUT2L_MUTE */
+#define WM2200_OUT2L_VOL_MASK                   0x00FF  /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_SHIFT                       0  /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_WIDTH                       8  /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1038 (0x40E) - DAC Digital Volume 2R
+ */
+#define WM2200_OUT_VU                           0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM2200_OUT2R_MUTE                       0x0100  /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_MASK                  0x0100  /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_SHIFT                      8  /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_WIDTH                      1  /* OUT2R_MUTE */
+#define WM2200_OUT2R_VOL_MASK                   0x00FF  /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_SHIFT                       0  /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_WIDTH                       8  /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1047 (0x417) - PDM 1
+ */
+#define WM2200_SPK1R_MUTE                       0x2000  /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_MASK                  0x2000  /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_SHIFT                     13  /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_WIDTH                      1  /* SPK1R_MUTE */
+#define WM2200_SPK1L_MUTE                       0x1000  /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_MASK                  0x1000  /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_SHIFT                     12  /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_WIDTH                      1  /* SPK1L_MUTE */
+#define WM2200_SPK1_MUTE_ENDIAN                 0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_MASK            0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_SHIFT                8  /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_WIDTH                1  /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_SEQL_MASK              0x00FF  /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_SHIFT                  0  /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_WIDTH                  8  /* SPK1_MUTE_SEQL - [7:0] */
+
+/*
+ * R1048 (0x418) - PDM 2
+ */
+#define WM2200_SPK1_FMT                         0x0001  /* SPK1_FMT */
+#define WM2200_SPK1_FMT_MASK                    0x0001  /* SPK1_FMT */
+#define WM2200_SPK1_FMT_SHIFT                        0  /* SPK1_FMT */
+#define WM2200_SPK1_FMT_WIDTH                        1  /* SPK1_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM2200_AIF1_BCLK_INV                    0x0040  /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_MASK               0x0040  /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_SHIFT                   6  /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_WIDTH                   1  /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_FRC                    0x0020  /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_MASK               0x0020  /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_SHIFT                   5  /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_WIDTH                   1  /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_MSTR                   0x0010  /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_MASK              0x0010  /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_SHIFT                  4  /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_WIDTH                  1  /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_DIV_MASK               0x000F  /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_SHIFT                   0  /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_WIDTH                   4  /* AIF1_BCLK_DIV - [3:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM2200_AIF1TX_DAT_TRI                   0x0020  /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_MASK              0x0020  /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_SHIFT                  5  /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_WIDTH                  1  /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_LRCLK_SRC                 0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_MASK            0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_SHIFT                3  /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_WIDTH                1  /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_INV                 0x0004  /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_MASK            0x0004  /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_SHIFT                2  /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_WIDTH                1  /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_FRC                 0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_MASK            0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_SHIFT                1  /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_WIDTH                1  /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_MSTR                0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_MASK           0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_SHIFT               0  /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_WIDTH               1  /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM2200_AIF1RX_LRCLK_INV                 0x0004  /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_MASK            0x0004  /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_SHIFT                2  /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_WIDTH                1  /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_FRC                 0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_MASK            0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_SHIFT                1  /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_WIDTH                1  /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_MSTR                0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_MASK           0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_SHIFT               0  /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_WIDTH               1  /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM2200_AIF1_TRI                         0x0040  /* AIF1_TRI */
+#define WM2200_AIF1_TRI_MASK                    0x0040  /* AIF1_TRI */
+#define WM2200_AIF1_TRI_SHIFT                        6  /* AIF1_TRI */
+#define WM2200_AIF1_TRI_WIDTH                        1  /* AIF1_TRI */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM2200_AIF1_FMT_MASK                    0x0007  /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_SHIFT                        0  /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_WIDTH                        3  /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM2200_AIF1TX_BCPF_MASK                 0x07FF  /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_SHIFT                     0  /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_WIDTH                    11  /* AIF1TX_BCPF - [10:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM2200_AIF1RX_BCPF_MASK                 0x07FF  /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_SHIFT                     0  /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_WIDTH                    11  /* AIF1RX_BCPF - [10:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM2200_AIF1TX_WL_MASK                   0x3F00  /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_SHIFT                       8  /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_WIDTH                       6  /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_SLOT_LEN_MASK             0x00FF  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_SHIFT                 0  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_WIDTH                 8  /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM2200_AIF1RX_WL_MASK                   0x3F00  /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_SHIFT                       8  /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_WIDTH                       6  /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_SLOT_LEN_MASK             0x00FF  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_SHIFT                 0  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_WIDTH                 8  /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM2200_AIF1TX1_SLOT_MASK                0x003F  /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_SHIFT                    0  /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_WIDTH                    6  /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM2200_AIF1TX2_SLOT_MASK                0x003F  /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_SHIFT                    0  /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_WIDTH                    6  /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM2200_AIF1TX3_SLOT_MASK                0x003F  /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_SHIFT                    0  /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_WIDTH                    6  /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM2200_AIF1TX4_SLOT_MASK                0x003F  /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_SHIFT                    0  /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_WIDTH                    6  /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM2200_AIF1TX5_SLOT_MASK                0x003F  /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_SHIFT                    0  /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_WIDTH                    6  /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM2200_AIF1TX6_SLOT_MASK                0x003F  /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_SHIFT                    0  /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_WIDTH                    6  /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM2200_AIF1RX1_SLOT_MASK                0x003F  /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_SHIFT                    0  /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_WIDTH                    6  /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM2200_AIF1RX2_SLOT_MASK                0x003F  /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_SHIFT                    0  /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_WIDTH                    6  /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM2200_AIF1RX3_SLOT_MASK                0x003F  /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_SHIFT                    0  /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_WIDTH                    6  /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM2200_AIF1RX4_SLOT_MASK                0x003F  /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_SHIFT                    0  /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_WIDTH                    6  /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM2200_AIF1RX5_SLOT_MASK                0x003F  /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_SHIFT                    0  /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_WIDTH                    6  /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM2200_AIF1RX6_SLOT_MASK                0x003F  /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_SHIFT                    0  /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_WIDTH                    6  /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM2200_AIF1RX6_ENA                      0x0800  /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_MASK                 0x0800  /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_SHIFT                    11  /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_WIDTH                     1  /* AIF1RX6_ENA */
+#define WM2200_AIF1RX5_ENA                      0x0400  /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_MASK                 0x0400  /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_SHIFT                    10  /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_WIDTH                     1  /* AIF1RX5_ENA */
+#define WM2200_AIF1RX4_ENA                      0x0200  /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_MASK                 0x0200  /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_SHIFT                     9  /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_WIDTH                     1  /* AIF1RX4_ENA */
+#define WM2200_AIF1RX3_ENA                      0x0100  /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_MASK                 0x0100  /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_SHIFT                     8  /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_WIDTH                     1  /* AIF1RX3_ENA */
+#define WM2200_AIF1RX2_ENA                      0x0080  /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_MASK                 0x0080  /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_SHIFT                     7  /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_WIDTH                     1  /* AIF1RX2_ENA */
+#define WM2200_AIF1RX1_ENA                      0x0040  /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_MASK                 0x0040  /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_SHIFT                     6  /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_WIDTH                     1  /* AIF1RX1_ENA */
+#define WM2200_AIF1TX6_ENA                      0x0020  /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_MASK                 0x0020  /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_SHIFT                     5  /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_WIDTH                     1  /* AIF1TX6_ENA */
+#define WM2200_AIF1TX5_ENA                      0x0010  /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_MASK                 0x0010  /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_SHIFT                     4  /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_WIDTH                     1  /* AIF1TX5_ENA */
+#define WM2200_AIF1TX4_ENA                      0x0008  /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_MASK                 0x0008  /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_SHIFT                     3  /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_WIDTH                     1  /* AIF1TX4_ENA */
+#define WM2200_AIF1TX3_ENA                      0x0004  /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_MASK                 0x0004  /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_SHIFT                     2  /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_WIDTH                     1  /* AIF1TX3_ENA */
+#define WM2200_AIF1TX2_ENA                      0x0002  /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_MASK                 0x0002  /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_SHIFT                     1  /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_WIDTH                     1  /* AIF1TX2_ENA */
+#define WM2200_AIF1TX1_ENA                      0x0001  /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_MASK                 0x0001  /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_SHIFT                     0  /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_WIDTH                     1  /* AIF1TX1_ENA */
+
+/*
+ * R1536 (0x600) - OUT1LMIX Input 1 Source
+ */
+#define WM2200_OUT1LMIX_SRC1_MASK               0x007F  /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_SHIFT                   0  /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_WIDTH                   7  /* OUT1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1537 (0x601) - OUT1LMIX Input 1 Volume
+ */
+#define WM2200_OUT1LMIX_VOL1_MASK               0x00FE  /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_SHIFT                   1  /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_WIDTH                   7  /* OUT1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1538 (0x602) - OUT1LMIX Input 2 Source
+ */
+#define WM2200_OUT1LMIX_SRC2_MASK               0x007F  /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_SHIFT                   0  /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_WIDTH                   7  /* OUT1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1539 (0x603) - OUT1LMIX Input 2 Volume
+ */
+#define WM2200_OUT1LMIX_VOL2_MASK               0x00FE  /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_SHIFT                   1  /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_WIDTH                   7  /* OUT1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1540 (0x604) - OUT1LMIX Input 3 Source
+ */
+#define WM2200_OUT1LMIX_SRC3_MASK               0x007F  /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_SHIFT                   0  /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_WIDTH                   7  /* OUT1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1541 (0x605) - OUT1LMIX Input 3 Volume
+ */
+#define WM2200_OUT1LMIX_VOL3_MASK               0x00FE  /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_SHIFT                   1  /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_WIDTH                   7  /* OUT1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1542 (0x606) - OUT1LMIX Input 4 Source
+ */
+#define WM2200_OUT1LMIX_SRC4_MASK               0x007F  /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_SHIFT                   0  /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_WIDTH                   7  /* OUT1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1543 (0x607) - OUT1LMIX Input 4 Volume
+ */
+#define WM2200_OUT1LMIX_VOL4_MASK               0x00FE  /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_SHIFT                   1  /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_WIDTH                   7  /* OUT1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1544 (0x608) - OUT1RMIX Input 1 Source
+ */
+#define WM2200_OUT1RMIX_SRC1_MASK               0x007F  /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_SHIFT                   0  /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_WIDTH                   7  /* OUT1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1545 (0x609) - OUT1RMIX Input 1 Volume
+ */
+#define WM2200_OUT1RMIX_VOL1_MASK               0x00FE  /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_SHIFT                   1  /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_WIDTH                   7  /* OUT1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1546 (0x60A) - OUT1RMIX Input 2 Source
+ */
+#define WM2200_OUT1RMIX_SRC2_MASK               0x007F  /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_SHIFT                   0  /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_WIDTH                   7  /* OUT1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1547 (0x60B) - OUT1RMIX Input 2 Volume
+ */
+#define WM2200_OUT1RMIX_VOL2_MASK               0x00FE  /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_SHIFT                   1  /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_WIDTH                   7  /* OUT1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1548 (0x60C) - OUT1RMIX Input 3 Source
+ */
+#define WM2200_OUT1RMIX_SRC3_MASK               0x007F  /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_SHIFT                   0  /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_WIDTH                   7  /* OUT1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1549 (0x60D) - OUT1RMIX Input 3 Volume
+ */
+#define WM2200_OUT1RMIX_VOL3_MASK               0x00FE  /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_SHIFT                   1  /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_WIDTH                   7  /* OUT1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1550 (0x60E) - OUT1RMIX Input 4 Source
+ */
+#define WM2200_OUT1RMIX_SRC4_MASK               0x007F  /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_SHIFT                   0  /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_WIDTH                   7  /* OUT1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1551 (0x60F) - OUT1RMIX Input 4 Volume
+ */
+#define WM2200_OUT1RMIX_VOL4_MASK               0x00FE  /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_SHIFT                   1  /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_WIDTH                   7  /* OUT1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1552 (0x610) - OUT2LMIX Input 1 Source
+ */
+#define WM2200_OUT2LMIX_SRC1_MASK               0x007F  /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_SHIFT                   0  /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_WIDTH                   7  /* OUT2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1553 (0x611) - OUT2LMIX Input 1 Volume
+ */
+#define WM2200_OUT2LMIX_VOL1_MASK               0x00FE  /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_SHIFT                   1  /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_WIDTH                   7  /* OUT2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1554 (0x612) - OUT2LMIX Input 2 Source
+ */
+#define WM2200_OUT2LMIX_SRC2_MASK               0x007F  /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_SHIFT                   0  /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_WIDTH                   7  /* OUT2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1555 (0x613) - OUT2LMIX Input 2 Volume
+ */
+#define WM2200_OUT2LMIX_VOL2_MASK               0x00FE  /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_SHIFT                   1  /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_WIDTH                   7  /* OUT2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1556 (0x614) - OUT2LMIX Input 3 Source
+ */
+#define WM2200_OUT2LMIX_SRC3_MASK               0x007F  /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_SHIFT                   0  /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_WIDTH                   7  /* OUT2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1557 (0x615) - OUT2LMIX Input 3 Volume
+ */
+#define WM2200_OUT2LMIX_VOL3_MASK               0x00FE  /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_SHIFT                   1  /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_WIDTH                   7  /* OUT2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1558 (0x616) - OUT2LMIX Input 4 Source
+ */
+#define WM2200_OUT2LMIX_SRC4_MASK               0x007F  /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_SHIFT                   0  /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_WIDTH                   7  /* OUT2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1559 (0x617) - OUT2LMIX Input 4 Volume
+ */
+#define WM2200_OUT2LMIX_VOL4_MASK               0x00FE  /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_SHIFT                   1  /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_WIDTH                   7  /* OUT2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1560 (0x618) - OUT2RMIX Input 1 Source
+ */
+#define WM2200_OUT2RMIX_SRC1_MASK               0x007F  /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_SHIFT                   0  /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_WIDTH                   7  /* OUT2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1561 (0x619) - OUT2RMIX Input 1 Volume
+ */
+#define WM2200_OUT2RMIX_VOL1_MASK               0x00FE  /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_SHIFT                   1  /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_WIDTH                   7  /* OUT2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1562 (0x61A) - OUT2RMIX Input 2 Source
+ */
+#define WM2200_OUT2RMIX_SRC2_MASK               0x007F  /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_SHIFT                   0  /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_WIDTH                   7  /* OUT2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1563 (0x61B) - OUT2RMIX Input 2 Volume
+ */
+#define WM2200_OUT2RMIX_VOL2_MASK               0x00FE  /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_SHIFT                   1  /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_WIDTH                   7  /* OUT2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1564 (0x61C) - OUT2RMIX Input 3 Source
+ */
+#define WM2200_OUT2RMIX_SRC3_MASK               0x007F  /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_SHIFT                   0  /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_WIDTH                   7  /* OUT2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1565 (0x61D) - OUT2RMIX Input 3 Volume
+ */
+#define WM2200_OUT2RMIX_VOL3_MASK               0x00FE  /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_SHIFT                   1  /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_WIDTH                   7  /* OUT2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1566 (0x61E) - OUT2RMIX Input 4 Source
+ */
+#define WM2200_OUT2RMIX_SRC4_MASK               0x007F  /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_SHIFT                   0  /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_WIDTH                   7  /* OUT2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1567 (0x61F) - OUT2RMIX Input 4 Volume
+ */
+#define WM2200_OUT2RMIX_VOL4_MASK               0x00FE  /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_SHIFT                   1  /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_WIDTH                   7  /* OUT2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1568 (0x620) - AIF1TX1MIX Input 1 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC1_MASK             0x007F  /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_SHIFT                 0  /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_WIDTH                 7  /* AIF1TX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1569 (0x621) - AIF1TX1MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL1_MASK             0x00FE  /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_SHIFT                 1  /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_WIDTH                 7  /* AIF1TX1MIX_VOL1 - [7:1] */
+
+/*
+ * R1570 (0x622) - AIF1TX1MIX Input 2 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC2_MASK             0x007F  /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_SHIFT                 0  /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_WIDTH                 7  /* AIF1TX1MIX_SRC2 - [6:0] */
+
+/*
+ * R1571 (0x623) - AIF1TX1MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL2_MASK             0x00FE  /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_SHIFT                 1  /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_WIDTH                 7  /* AIF1TX1MIX_VOL2 - [7:1] */
+
+/*
+ * R1572 (0x624) - AIF1TX1MIX Input 3 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC3_MASK             0x007F  /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_SHIFT                 0  /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_WIDTH                 7  /* AIF1TX1MIX_SRC3 - [6:0] */
+
+/*
+ * R1573 (0x625) - AIF1TX1MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL3_MASK             0x00FE  /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_SHIFT                 1  /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_WIDTH                 7  /* AIF1TX1MIX_VOL3 - [7:1] */
+
+/*
+ * R1574 (0x626) - AIF1TX1MIX Input 4 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC4_MASK             0x007F  /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_SHIFT                 0  /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_WIDTH                 7  /* AIF1TX1MIX_SRC4 - [6:0] */
+
+/*
+ * R1575 (0x627) - AIF1TX1MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL4_MASK             0x00FE  /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_SHIFT                 1  /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_WIDTH                 7  /* AIF1TX1MIX_VOL4 - [7:1] */
+
+/*
+ * R1576 (0x628) - AIF1TX2MIX Input 1 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC1_MASK             0x007F  /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_SHIFT                 0  /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_WIDTH                 7  /* AIF1TX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1577 (0x629) - AIF1TX2MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL1_MASK             0x00FE  /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_SHIFT                 1  /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_WIDTH                 7  /* AIF1TX2MIX_VOL1 - [7:1] */
+
+/*
+ * R1578 (0x62A) - AIF1TX2MIX Input 2 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC2_MASK             0x007F  /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_SHIFT                 0  /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_WIDTH                 7  /* AIF1TX2MIX_SRC2 - [6:0] */
+
+/*
+ * R1579 (0x62B) - AIF1TX2MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL2_MASK             0x00FE  /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_SHIFT                 1  /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_WIDTH                 7  /* AIF1TX2MIX_VOL2 - [7:1] */
+
+/*
+ * R1580 (0x62C) - AIF1TX2MIX Input 3 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC3_MASK             0x007F  /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_SHIFT                 0  /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_WIDTH                 7  /* AIF1TX2MIX_SRC3 - [6:0] */
+
+/*
+ * R1581 (0x62D) - AIF1TX2MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL3_MASK             0x00FE  /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_SHIFT                 1  /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_WIDTH                 7  /* AIF1TX2MIX_VOL3 - [7:1] */
+
+/*
+ * R1582 (0x62E) - AIF1TX2MIX Input 4 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC4_MASK             0x007F  /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_SHIFT                 0  /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_WIDTH                 7  /* AIF1TX2MIX_SRC4 - [6:0] */
+
+/*
+ * R1583 (0x62F) - AIF1TX2MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL4_MASK             0x00FE  /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_SHIFT                 1  /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_WIDTH                 7  /* AIF1TX2MIX_VOL4 - [7:1] */
+
+/*
+ * R1584 (0x630) - AIF1TX3MIX Input 1 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC1_MASK             0x007F  /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_SHIFT                 0  /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_WIDTH                 7  /* AIF1TX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1585 (0x631) - AIF1TX3MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL1_MASK             0x00FE  /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_SHIFT                 1  /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_WIDTH                 7  /* AIF1TX3MIX_VOL1 - [7:1] */
+
+/*
+ * R1586 (0x632) - AIF1TX3MIX Input 2 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC2_MASK             0x007F  /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_SHIFT                 0  /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_WIDTH                 7  /* AIF1TX3MIX_SRC2 - [6:0] */
+
+/*
+ * R1587 (0x633) - AIF1TX3MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL2_MASK             0x00FE  /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_SHIFT                 1  /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_WIDTH                 7  /* AIF1TX3MIX_VOL2 - [7:1] */
+
+/*
+ * R1588 (0x634) - AIF1TX3MIX Input 3 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC3_MASK             0x007F  /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_SHIFT                 0  /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_WIDTH                 7  /* AIF1TX3MIX_SRC3 - [6:0] */
+
+/*
+ * R1589 (0x635) - AIF1TX3MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL3_MASK             0x00FE  /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_SHIFT                 1  /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_WIDTH                 7  /* AIF1TX3MIX_VOL3 - [7:1] */
+
+/*
+ * R1590 (0x636) - AIF1TX3MIX Input 4 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC4_MASK             0x007F  /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_SHIFT                 0  /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_WIDTH                 7  /* AIF1TX3MIX_SRC4 - [6:0] */
+
+/*
+ * R1591 (0x637) - AIF1TX3MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL4_MASK             0x00FE  /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_SHIFT                 1  /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_WIDTH                 7  /* AIF1TX3MIX_VOL4 - [7:1] */
+
+/*
+ * R1592 (0x638) - AIF1TX4MIX Input 1 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC1_MASK             0x007F  /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_SHIFT                 0  /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_WIDTH                 7  /* AIF1TX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1593 (0x639) - AIF1TX4MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL1_MASK             0x00FE  /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_SHIFT                 1  /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_WIDTH                 7  /* AIF1TX4MIX_VOL1 - [7:1] */
+
+/*
+ * R1594 (0x63A) - AIF1TX4MIX Input 2 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC2_MASK             0x007F  /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_SHIFT                 0  /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_WIDTH                 7  /* AIF1TX4MIX_SRC2 - [6:0] */
+
+/*
+ * R1595 (0x63B) - AIF1TX4MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL2_MASK             0x00FE  /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_SHIFT                 1  /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_WIDTH                 7  /* AIF1TX4MIX_VOL2 - [7:1] */
+
+/*
+ * R1596 (0x63C) - AIF1TX4MIX Input 3 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC3_MASK             0x007F  /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_SHIFT                 0  /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_WIDTH                 7  /* AIF1TX4MIX_SRC3 - [6:0] */
+
+/*
+ * R1597 (0x63D) - AIF1TX4MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL3_MASK             0x00FE  /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_SHIFT                 1  /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_WIDTH                 7  /* AIF1TX4MIX_VOL3 - [7:1] */
+
+/*
+ * R1598 (0x63E) - AIF1TX4MIX Input 4 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC4_MASK             0x007F  /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_SHIFT                 0  /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_WIDTH                 7  /* AIF1TX4MIX_SRC4 - [6:0] */
+
+/*
+ * R1599 (0x63F) - AIF1TX4MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL4_MASK             0x00FE  /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_SHIFT                 1  /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_WIDTH                 7  /* AIF1TX4MIX_VOL4 - [7:1] */
+
+/*
+ * R1600 (0x640) - AIF1TX5MIX Input 1 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC1_MASK             0x007F  /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_SHIFT                 0  /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_WIDTH                 7  /* AIF1TX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1601 (0x641) - AIF1TX5MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL1_MASK             0x00FE  /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_SHIFT                 1  /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_WIDTH                 7  /* AIF1TX5MIX_VOL1 - [7:1] */
+
+/*
+ * R1602 (0x642) - AIF1TX5MIX Input 2 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC2_MASK             0x007F  /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_SHIFT                 0  /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_WIDTH                 7  /* AIF1TX5MIX_SRC2 - [6:0] */
+
+/*
+ * R1603 (0x643) - AIF1TX5MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL2_MASK             0x00FE  /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_SHIFT                 1  /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_WIDTH                 7  /* AIF1TX5MIX_VOL2 - [7:1] */
+
+/*
+ * R1604 (0x644) - AIF1TX5MIX Input 3 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC3_MASK             0x007F  /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_SHIFT                 0  /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_WIDTH                 7  /* AIF1TX5MIX_SRC3 - [6:0] */
+
+/*
+ * R1605 (0x645) - AIF1TX5MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL3_MASK             0x00FE  /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_SHIFT                 1  /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_WIDTH                 7  /* AIF1TX5MIX_VOL3 - [7:1] */
+
+/*
+ * R1606 (0x646) - AIF1TX5MIX Input 4 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC4_MASK             0x007F  /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_SHIFT                 0  /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_WIDTH                 7  /* AIF1TX5MIX_SRC4 - [6:0] */
+
+/*
+ * R1607 (0x647) - AIF1TX5MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL4_MASK             0x00FE  /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_SHIFT                 1  /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_WIDTH                 7  /* AIF1TX5MIX_VOL4 - [7:1] */
+
+/*
+ * R1608 (0x648) - AIF1TX6MIX Input 1 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC1_MASK             0x007F  /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_SHIFT                 0  /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_WIDTH                 7  /* AIF1TX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1609 (0x649) - AIF1TX6MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL1_MASK             0x00FE  /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_SHIFT                 1  /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_WIDTH                 7  /* AIF1TX6MIX_VOL1 - [7:1] */
+
+/*
+ * R1610 (0x64A) - AIF1TX6MIX Input 2 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC2_MASK             0x007F  /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_SHIFT                 0  /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_WIDTH                 7  /* AIF1TX6MIX_SRC2 - [6:0] */
+
+/*
+ * R1611 (0x64B) - AIF1TX6MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL2_MASK             0x00FE  /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_SHIFT                 1  /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_WIDTH                 7  /* AIF1TX6MIX_VOL2 - [7:1] */
+
+/*
+ * R1612 (0x64C) - AIF1TX6MIX Input 3 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC3_MASK             0x007F  /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_SHIFT                 0  /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_WIDTH                 7  /* AIF1TX6MIX_SRC3 - [6:0] */
+
+/*
+ * R1613 (0x64D) - AIF1TX6MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL3_MASK             0x00FE  /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_SHIFT                 1  /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_WIDTH                 7  /* AIF1TX6MIX_VOL3 - [7:1] */
+
+/*
+ * R1614 (0x64E) - AIF1TX6MIX Input 4 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC4_MASK             0x007F  /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_SHIFT                 0  /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_WIDTH                 7  /* AIF1TX6MIX_SRC4 - [6:0] */
+
+/*
+ * R1615 (0x64F) - AIF1TX6MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL4_MASK             0x00FE  /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_SHIFT                 1  /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_WIDTH                 7  /* AIF1TX6MIX_VOL4 - [7:1] */
+
+/*
+ * R1616 (0x650) - EQLMIX Input 1 Source
+ */
+#define WM2200_EQLMIX_SRC1_MASK                 0x007F  /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_SHIFT                     0  /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_WIDTH                     7  /* EQLMIX_SRC1 - [6:0] */
+
+/*
+ * R1617 (0x651) - EQLMIX Input 1 Volume
+ */
+#define WM2200_EQLMIX_VOL1_MASK                 0x00FE  /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_SHIFT                     1  /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_WIDTH                     7  /* EQLMIX_VOL1 - [7:1] */
+
+/*
+ * R1618 (0x652) - EQLMIX Input 2 Source
+ */
+#define WM2200_EQLMIX_SRC2_MASK                 0x007F  /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_SHIFT                     0  /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_WIDTH                     7  /* EQLMIX_SRC2 - [6:0] */
+
+/*
+ * R1619 (0x653) - EQLMIX Input 2 Volume
+ */
+#define WM2200_EQLMIX_VOL2_MASK                 0x00FE  /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_SHIFT                     1  /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_WIDTH                     7  /* EQLMIX_VOL2 - [7:1] */
+
+/*
+ * R1620 (0x654) - EQLMIX Input 3 Source
+ */
+#define WM2200_EQLMIX_SRC3_MASK                 0x007F  /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_SHIFT                     0  /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_WIDTH                     7  /* EQLMIX_SRC3 - [6:0] */
+
+/*
+ * R1621 (0x655) - EQLMIX Input 3 Volume
+ */
+#define WM2200_EQLMIX_VOL3_MASK                 0x00FE  /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_SHIFT                     1  /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_WIDTH                     7  /* EQLMIX_VOL3 - [7:1] */
+
+/*
+ * R1622 (0x656) - EQLMIX Input 4 Source
+ */
+#define WM2200_EQLMIX_SRC4_MASK                 0x007F  /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_SHIFT                     0  /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_WIDTH                     7  /* EQLMIX_SRC4 - [6:0] */
+
+/*
+ * R1623 (0x657) - EQLMIX Input 4 Volume
+ */
+#define WM2200_EQLMIX_VOL4_MASK                 0x00FE  /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_SHIFT                     1  /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_WIDTH                     7  /* EQLMIX_VOL4 - [7:1] */
+
+/*
+ * R1624 (0x658) - EQRMIX Input 1 Source
+ */
+#define WM2200_EQRMIX_SRC1_MASK                 0x007F  /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_SHIFT                     0  /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_WIDTH                     7  /* EQRMIX_SRC1 - [6:0] */
+
+/*
+ * R1625 (0x659) - EQRMIX Input 1 Volume
+ */
+#define WM2200_EQRMIX_VOL1_MASK                 0x00FE  /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_SHIFT                     1  /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_WIDTH                     7  /* EQRMIX_VOL1 - [7:1] */
+
+/*
+ * R1626 (0x65A) - EQRMIX Input 2 Source
+ */
+#define WM2200_EQRMIX_SRC2_MASK                 0x007F  /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_SHIFT                     0  /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_WIDTH                     7  /* EQRMIX_SRC2 - [6:0] */
+
+/*
+ * R1627 (0x65B) - EQRMIX Input 2 Volume
+ */
+#define WM2200_EQRMIX_VOL2_MASK                 0x00FE  /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_SHIFT                     1  /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_WIDTH                     7  /* EQRMIX_VOL2 - [7:1] */
+
+/*
+ * R1628 (0x65C) - EQRMIX Input 3 Source
+ */
+#define WM2200_EQRMIX_SRC3_MASK                 0x007F  /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_SHIFT                     0  /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_WIDTH                     7  /* EQRMIX_SRC3 - [6:0] */
+
+/*
+ * R1629 (0x65D) - EQRMIX Input 3 Volume
+ */
+#define WM2200_EQRMIX_VOL3_MASK                 0x00FE  /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_SHIFT                     1  /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_WIDTH                     7  /* EQRMIX_VOL3 - [7:1] */
+
+/*
+ * R1630 (0x65E) - EQRMIX Input 4 Source
+ */
+#define WM2200_EQRMIX_SRC4_MASK                 0x007F  /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_SHIFT                     0  /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_WIDTH                     7  /* EQRMIX_SRC4 - [6:0] */
+
+/*
+ * R1631 (0x65F) - EQRMIX Input 4 Volume
+ */
+#define WM2200_EQRMIX_VOL4_MASK                 0x00FE  /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_SHIFT                     1  /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_WIDTH                     7  /* EQRMIX_VOL4 - [7:1] */
+
+/*
+ * R1632 (0x660) - LHPF1MIX Input 1 Source
+ */
+#define WM2200_LHPF1MIX_SRC1_MASK               0x007F  /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_SHIFT                   0  /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_WIDTH                   7  /* LHPF1MIX_SRC1 - [6:0] */
+
+/*
+ * R1633 (0x661) - LHPF1MIX Input 1 Volume
+ */
+#define WM2200_LHPF1MIX_VOL1_MASK               0x00FE  /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_SHIFT                   1  /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_WIDTH                   7  /* LHPF1MIX_VOL1 - [7:1] */
+
+/*
+ * R1634 (0x662) - LHPF1MIX Input 2 Source
+ */
+#define WM2200_LHPF1MIX_SRC2_MASK               0x007F  /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_SHIFT                   0  /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_WIDTH                   7  /* LHPF1MIX_SRC2 - [6:0] */
+
+/*
+ * R1635 (0x663) - LHPF1MIX Input 2 Volume
+ */
+#define WM2200_LHPF1MIX_VOL2_MASK               0x00FE  /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_SHIFT                   1  /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_WIDTH                   7  /* LHPF1MIX_VOL2 - [7:1] */
+
+/*
+ * R1636 (0x664) - LHPF1MIX Input 3 Source
+ */
+#define WM2200_LHPF1MIX_SRC3_MASK               0x007F  /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_SHIFT                   0  /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_WIDTH                   7  /* LHPF1MIX_SRC3 - [6:0] */
+
+/*
+ * R1637 (0x665) - LHPF1MIX Input 3 Volume
+ */
+#define WM2200_LHPF1MIX_VOL3_MASK               0x00FE  /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_SHIFT                   1  /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_WIDTH                   7  /* LHPF1MIX_VOL3 - [7:1] */
+
+/*
+ * R1638 (0x666) - LHPF1MIX Input 4 Source
+ */
+#define WM2200_LHPF1MIX_SRC4_MASK               0x007F  /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_SHIFT                   0  /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_WIDTH                   7  /* LHPF1MIX_SRC4 - [6:0] */
+
+/*
+ * R1639 (0x667) - LHPF1MIX Input 4 Volume
+ */
+#define WM2200_LHPF1MIX_VOL4_MASK               0x00FE  /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_SHIFT                   1  /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_WIDTH                   7  /* LHPF1MIX_VOL4 - [7:1] */
+
+/*
+ * R1640 (0x668) - LHPF2MIX Input 1 Source
+ */
+#define WM2200_LHPF2MIX_SRC1_MASK               0x007F  /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_SHIFT                   0  /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_WIDTH                   7  /* LHPF2MIX_SRC1 - [6:0] */
+
+/*
+ * R1641 (0x669) - LHPF2MIX Input 1 Volume
+ */
+#define WM2200_LHPF2MIX_VOL1_MASK               0x00FE  /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_SHIFT                   1  /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_WIDTH                   7  /* LHPF2MIX_VOL1 - [7:1] */
+
+/*
+ * R1642 (0x66A) - LHPF2MIX Input 2 Source
+ */
+#define WM2200_LHPF2MIX_SRC2_MASK               0x007F  /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_SHIFT                   0  /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_WIDTH                   7  /* LHPF2MIX_SRC2 - [6:0] */
+
+/*
+ * R1643 (0x66B) - LHPF2MIX Input 2 Volume
+ */
+#define WM2200_LHPF2MIX_VOL2_MASK               0x00FE  /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_SHIFT                   1  /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_WIDTH                   7  /* LHPF2MIX_VOL2 - [7:1] */
+
+/*
+ * R1644 (0x66C) - LHPF2MIX Input 3 Source
+ */
+#define WM2200_LHPF2MIX_SRC3_MASK               0x007F  /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_SHIFT                   0  /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_WIDTH                   7  /* LHPF2MIX_SRC3 - [6:0] */
+
+/*
+ * R1645 (0x66D) - LHPF2MIX Input 3 Volume
+ */
+#define WM2200_LHPF2MIX_VOL3_MASK               0x00FE  /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_SHIFT                   1  /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_WIDTH                   7  /* LHPF2MIX_VOL3 - [7:1] */
+
+/*
+ * R1646 (0x66E) - LHPF2MIX Input 4 Source
+ */
+#define WM2200_LHPF2MIX_SRC4_MASK               0x007F  /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_SHIFT                   0  /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_WIDTH                   7  /* LHPF2MIX_SRC4 - [6:0] */
+
+/*
+ * R1647 (0x66F) - LHPF2MIX Input 4 Volume
+ */
+#define WM2200_LHPF2MIX_VOL4_MASK               0x00FE  /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_SHIFT                   1  /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_WIDTH                   7  /* LHPF2MIX_VOL4 - [7:1] */
+
+/*
+ * R1648 (0x670) - DSP1LMIX Input 1 Source
+ */
+#define WM2200_DSP1LMIX_SRC1_MASK               0x007F  /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_SHIFT                   0  /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_WIDTH                   7  /* DSP1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1649 (0x671) - DSP1LMIX Input 1 Volume
+ */
+#define WM2200_DSP1LMIX_VOL1_MASK               0x00FE  /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_SHIFT                   1  /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_WIDTH                   7  /* DSP1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1650 (0x672) - DSP1LMIX Input 2 Source
+ */
+#define WM2200_DSP1LMIX_SRC2_MASK               0x007F  /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_SHIFT                   0  /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_WIDTH                   7  /* DSP1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1651 (0x673) - DSP1LMIX Input 2 Volume
+ */
+#define WM2200_DSP1LMIX_VOL2_MASK               0x00FE  /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_SHIFT                   1  /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_WIDTH                   7  /* DSP1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1652 (0x674) - DSP1LMIX Input 3 Source
+ */
+#define WM2200_DSP1LMIX_SRC3_MASK               0x007F  /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_SHIFT                   0  /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_WIDTH                   7  /* DSP1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1653 (0x675) - DSP1LMIX Input 3 Volume
+ */
+#define WM2200_DSP1LMIX_VOL3_MASK               0x00FE  /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_SHIFT                   1  /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_WIDTH                   7  /* DSP1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1654 (0x676) - DSP1LMIX Input 4 Source
+ */
+#define WM2200_DSP1LMIX_SRC4_MASK               0x007F  /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_SHIFT                   0  /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_WIDTH                   7  /* DSP1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1655 (0x677) - DSP1LMIX Input 4 Volume
+ */
+#define WM2200_DSP1LMIX_VOL4_MASK               0x00FE  /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_SHIFT                   1  /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_WIDTH                   7  /* DSP1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1656 (0x678) - DSP1RMIX Input 1 Source
+ */
+#define WM2200_DSP1RMIX_SRC1_MASK               0x007F  /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_SHIFT                   0  /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_WIDTH                   7  /* DSP1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1657 (0x679) - DSP1RMIX Input 1 Volume
+ */
+#define WM2200_DSP1RMIX_VOL1_MASK               0x00FE  /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_SHIFT                   1  /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_WIDTH                   7  /* DSP1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1658 (0x67A) - DSP1RMIX Input 2 Source
+ */
+#define WM2200_DSP1RMIX_SRC2_MASK               0x007F  /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_SHIFT                   0  /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_WIDTH                   7  /* DSP1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1659 (0x67B) - DSP1RMIX Input 2 Volume
+ */
+#define WM2200_DSP1RMIX_VOL2_MASK               0x00FE  /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_SHIFT                   1  /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_WIDTH                   7  /* DSP1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1660 (0x67C) - DSP1RMIX Input 3 Source
+ */
+#define WM2200_DSP1RMIX_SRC3_MASK               0x007F  /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_SHIFT                   0  /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_WIDTH                   7  /* DSP1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1661 (0x67D) - DSP1RMIX Input 3 Volume
+ */
+#define WM2200_DSP1RMIX_VOL3_MASK               0x00FE  /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_SHIFT                   1  /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_WIDTH                   7  /* DSP1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1662 (0x67E) - DSP1RMIX Input 4 Source
+ */
+#define WM2200_DSP1RMIX_SRC4_MASK               0x007F  /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_SHIFT                   0  /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_WIDTH                   7  /* DSP1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1663 (0x67F) - DSP1RMIX Input 4 Volume
+ */
+#define WM2200_DSP1RMIX_VOL4_MASK               0x00FE  /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_SHIFT                   1  /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_WIDTH                   7  /* DSP1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1664 (0x680) - DSP1AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX1MIX_SRC1_MASK            0x007F  /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_SHIFT                0  /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_WIDTH                7  /* DSP1AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1665 (0x681) - DSP1AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX2MIX_SRC1_MASK            0x007F  /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_SHIFT                0  /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_WIDTH                7  /* DSP1AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1666 (0x682) - DSP1AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX3MIX_SRC1_MASK            0x007F  /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_SHIFT                0  /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_WIDTH                7  /* DSP1AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1667 (0x683) - DSP1AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX4MIX_SRC1_MASK            0x007F  /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_SHIFT                0  /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_WIDTH                7  /* DSP1AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1668 (0x684) - DSP1AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX5MIX_SRC1_MASK            0x007F  /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_SHIFT                0  /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_WIDTH                7  /* DSP1AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1669 (0x685) - DSP1AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX6MIX_SRC1_MASK            0x007F  /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_SHIFT                0  /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_WIDTH                7  /* DSP1AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1670 (0x686) - DSP2LMIX Input 1 Source
+ */
+#define WM2200_DSP2LMIX_SRC1_MASK               0x007F  /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_SHIFT                   0  /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_WIDTH                   7  /* DSP2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1671 (0x687) - DSP2LMIX Input 1 Volume
+ */
+#define WM2200_DSP2LMIX_VOL1_MASK               0x00FE  /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_SHIFT                   1  /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_WIDTH                   7  /* DSP2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1672 (0x688) - DSP2LMIX Input 2 Source
+ */
+#define WM2200_DSP2LMIX_SRC2_MASK               0x007F  /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_SHIFT                   0  /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_WIDTH                   7  /* DSP2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1673 (0x689) - DSP2LMIX Input 2 Volume
+ */
+#define WM2200_DSP2LMIX_VOL2_MASK               0x00FE  /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_SHIFT                   1  /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_WIDTH                   7  /* DSP2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1674 (0x68A) - DSP2LMIX Input 3 Source
+ */
+#define WM2200_DSP2LMIX_SRC3_MASK               0x007F  /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_SHIFT                   0  /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_WIDTH                   7  /* DSP2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1675 (0x68B) - DSP2LMIX Input 3 Volume
+ */
+#define WM2200_DSP2LMIX_VOL3_MASK               0x00FE  /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_SHIFT                   1  /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_WIDTH                   7  /* DSP2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1676 (0x68C) - DSP2LMIX Input 4 Source
+ */
+#define WM2200_DSP2LMIX_SRC4_MASK               0x007F  /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_SHIFT                   0  /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_WIDTH                   7  /* DSP2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1677 (0x68D) - DSP2LMIX Input 4 Volume
+ */
+#define WM2200_DSP2LMIX_VOL4_MASK               0x00FE  /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_SHIFT                   1  /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_WIDTH                   7  /* DSP2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1678 (0x68E) - DSP2RMIX Input 1 Source
+ */
+#define WM2200_DSP2RMIX_SRC1_MASK               0x007F  /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_SHIFT                   0  /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_WIDTH                   7  /* DSP2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1679 (0x68F) - DSP2RMIX Input 1 Volume
+ */
+#define WM2200_DSP2RMIX_VOL1_MASK               0x00FE  /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_SHIFT                   1  /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_WIDTH                   7  /* DSP2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1680 (0x690) - DSP2RMIX Input 2 Source
+ */
+#define WM2200_DSP2RMIX_SRC2_MASK               0x007F  /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_SHIFT                   0  /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_WIDTH                   7  /* DSP2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1681 (0x691) - DSP2RMIX Input 2 Volume
+ */
+#define WM2200_DSP2RMIX_VOL2_MASK               0x00FE  /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_SHIFT                   1  /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_WIDTH                   7  /* DSP2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1682 (0x692) - DSP2RMIX Input 3 Source
+ */
+#define WM2200_DSP2RMIX_SRC3_MASK               0x007F  /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_SHIFT                   0  /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_WIDTH                   7  /* DSP2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1683 (0x693) - DSP2RMIX Input 3 Volume
+ */
+#define WM2200_DSP2RMIX_VOL3_MASK               0x00FE  /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_SHIFT                   1  /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_WIDTH                   7  /* DSP2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1684 (0x694) - DSP2RMIX Input 4 Source
+ */
+#define WM2200_DSP2RMIX_SRC4_MASK               0x007F  /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_SHIFT                   0  /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_WIDTH                   7  /* DSP2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1685 (0x695) - DSP2RMIX Input 4 Volume
+ */
+#define WM2200_DSP2RMIX_VOL4_MASK               0x00FE  /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_SHIFT                   1  /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_WIDTH                   7  /* DSP2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1686 (0x696) - DSP2AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX1MIX_SRC1_MASK            0x007F  /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_SHIFT                0  /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_WIDTH                7  /* DSP2AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1687 (0x697) - DSP2AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX2MIX_SRC1_MASK            0x007F  /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_SHIFT                0  /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_WIDTH                7  /* DSP2AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1688 (0x698) - DSP2AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX3MIX_SRC1_MASK            0x007F  /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_SHIFT                0  /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_WIDTH                7  /* DSP2AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1689 (0x699) - DSP2AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX4MIX_SRC1_MASK            0x007F  /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_SHIFT                0  /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_WIDTH                7  /* DSP2AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1690 (0x69A) - DSP2AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX5MIX_SRC1_MASK            0x007F  /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_SHIFT                0  /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_WIDTH                7  /* DSP2AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1691 (0x69B) - DSP2AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX6MIX_SRC1_MASK            0x007F  /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_SHIFT                0  /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_WIDTH                7  /* DSP2AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1792 (0x700) - GPIO CTRL 1
+ */
+#define WM2200_GP1_DIR                          0x8000  /* GP1_DIR */
+#define WM2200_GP1_DIR_MASK                     0x8000  /* GP1_DIR */
+#define WM2200_GP1_DIR_SHIFT                        15  /* GP1_DIR */
+#define WM2200_GP1_DIR_WIDTH                         1  /* GP1_DIR */
+#define WM2200_GP1_PU                           0x4000  /* GP1_PU */
+#define WM2200_GP1_PU_MASK                      0x4000  /* GP1_PU */
+#define WM2200_GP1_PU_SHIFT                         14  /* GP1_PU */
+#define WM2200_GP1_PU_WIDTH                          1  /* GP1_PU */
+#define WM2200_GP1_PD                           0x2000  /* GP1_PD */
+#define WM2200_GP1_PD_MASK                      0x2000  /* GP1_PD */
+#define WM2200_GP1_PD_SHIFT                         13  /* GP1_PD */
+#define WM2200_GP1_PD_WIDTH                          1  /* GP1_PD */
+#define WM2200_GP1_POL                          0x0400  /* GP1_POL */
+#define WM2200_GP1_POL_MASK                     0x0400  /* GP1_POL */
+#define WM2200_GP1_POL_SHIFT                        10  /* GP1_POL */
+#define WM2200_GP1_POL_WIDTH                         1  /* GP1_POL */
+#define WM2200_GP1_OP_CFG                       0x0200  /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_MASK                  0x0200  /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_SHIFT                      9  /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_WIDTH                      1  /* GP1_OP_CFG */
+#define WM2200_GP1_DB                           0x0100  /* GP1_DB */
+#define WM2200_GP1_DB_MASK                      0x0100  /* GP1_DB */
+#define WM2200_GP1_DB_SHIFT                          8  /* GP1_DB */
+#define WM2200_GP1_DB_WIDTH                          1  /* GP1_DB */
+#define WM2200_GP1_LVL                          0x0040  /* GP1_LVL */
+#define WM2200_GP1_LVL_MASK                     0x0040  /* GP1_LVL */
+#define WM2200_GP1_LVL_SHIFT                         6  /* GP1_LVL */
+#define WM2200_GP1_LVL_WIDTH                         1  /* GP1_LVL */
+#define WM2200_GP1_FN_MASK                      0x003F  /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_SHIFT                          0  /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_WIDTH                          6  /* GP1_FN - [5:0] */
+
+/*
+ * R1793 (0x701) - GPIO CTRL 2
+ */
+#define WM2200_GP2_DIR                          0x8000  /* GP2_DIR */
+#define WM2200_GP2_DIR_MASK                     0x8000  /* GP2_DIR */
+#define WM2200_GP2_DIR_SHIFT                        15  /* GP2_DIR */
+#define WM2200_GP2_DIR_WIDTH                         1  /* GP2_DIR */
+#define WM2200_GP2_PU                           0x4000  /* GP2_PU */
+#define WM2200_GP2_PU_MASK                      0x4000  /* GP2_PU */
+#define WM2200_GP2_PU_SHIFT                         14  /* GP2_PU */
+#define WM2200_GP2_PU_WIDTH                          1  /* GP2_PU */
+#define WM2200_GP2_PD                           0x2000  /* GP2_PD */
+#define WM2200_GP2_PD_MASK                      0x2000  /* GP2_PD */
+#define WM2200_GP2_PD_SHIFT                         13  /* GP2_PD */
+#define WM2200_GP2_PD_WIDTH                          1  /* GP2_PD */
+#define WM2200_GP2_POL                          0x0400  /* GP2_POL */
+#define WM2200_GP2_POL_MASK                     0x0400  /* GP2_POL */
+#define WM2200_GP2_POL_SHIFT                        10  /* GP2_POL */
+#define WM2200_GP2_POL_WIDTH                         1  /* GP2_POL */
+#define WM2200_GP2_OP_CFG                       0x0200  /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_MASK                  0x0200  /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_SHIFT                      9  /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_WIDTH                      1  /* GP2_OP_CFG */
+#define WM2200_GP2_DB                           0x0100  /* GP2_DB */
+#define WM2200_GP2_DB_MASK                      0x0100  /* GP2_DB */
+#define WM2200_GP2_DB_SHIFT                          8  /* GP2_DB */
+#define WM2200_GP2_DB_WIDTH                          1  /* GP2_DB */
+#define WM2200_GP2_LVL                          0x0040  /* GP2_LVL */
+#define WM2200_GP2_LVL_MASK                     0x0040  /* GP2_LVL */
+#define WM2200_GP2_LVL_SHIFT                         6  /* GP2_LVL */
+#define WM2200_GP2_LVL_WIDTH                         1  /* GP2_LVL */
+#define WM2200_GP2_FN_MASK                      0x003F  /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_SHIFT                          0  /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_WIDTH                          6  /* GP2_FN - [5:0] */
+
+/*
+ * R1794 (0x702) - GPIO CTRL 3
+ */
+#define WM2200_GP3_DIR                          0x8000  /* GP3_DIR */
+#define WM2200_GP3_DIR_MASK                     0x8000  /* GP3_DIR */
+#define WM2200_GP3_DIR_SHIFT                        15  /* GP3_DIR */
+#define WM2200_GP3_DIR_WIDTH                         1  /* GP3_DIR */
+#define WM2200_GP3_PU                           0x4000  /* GP3_PU */
+#define WM2200_GP3_PU_MASK                      0x4000  /* GP3_PU */
+#define WM2200_GP3_PU_SHIFT                         14  /* GP3_PU */
+#define WM2200_GP3_PU_WIDTH                          1  /* GP3_PU */
+#define WM2200_GP3_PD                           0x2000  /* GP3_PD */
+#define WM2200_GP3_PD_MASK                      0x2000  /* GP3_PD */
+#define WM2200_GP3_PD_SHIFT                         13  /* GP3_PD */
+#define WM2200_GP3_PD_WIDTH                          1  /* GP3_PD */
+#define WM2200_GP3_POL                          0x0400  /* GP3_POL */
+#define WM2200_GP3_POL_MASK                     0x0400  /* GP3_POL */
+#define WM2200_GP3_POL_SHIFT                        10  /* GP3_POL */
+#define WM2200_GP3_POL_WIDTH                         1  /* GP3_POL */
+#define WM2200_GP3_OP_CFG                       0x0200  /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_MASK                  0x0200  /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_SHIFT                      9  /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_WIDTH                      1  /* GP3_OP_CFG */
+#define WM2200_GP3_DB                           0x0100  /* GP3_DB */
+#define WM2200_GP3_DB_MASK                      0x0100  /* GP3_DB */
+#define WM2200_GP3_DB_SHIFT                          8  /* GP3_DB */
+#define WM2200_GP3_DB_WIDTH                          1  /* GP3_DB */
+#define WM2200_GP3_LVL                          0x0040  /* GP3_LVL */
+#define WM2200_GP3_LVL_MASK                     0x0040  /* GP3_LVL */
+#define WM2200_GP3_LVL_SHIFT                         6  /* GP3_LVL */
+#define WM2200_GP3_LVL_WIDTH                         1  /* GP3_LVL */
+#define WM2200_GP3_FN_MASK                      0x003F  /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_SHIFT                          0  /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_WIDTH                          6  /* GP3_FN - [5:0] */
+
+/*
+ * R1795 (0x703) - GPIO CTRL 4
+ */
+#define WM2200_GP4_DIR                          0x8000  /* GP4_DIR */
+#define WM2200_GP4_DIR_MASK                     0x8000  /* GP4_DIR */
+#define WM2200_GP4_DIR_SHIFT                        15  /* GP4_DIR */
+#define WM2200_GP4_DIR_WIDTH                         1  /* GP4_DIR */
+#define WM2200_GP4_PU                           0x4000  /* GP4_PU */
+#define WM2200_GP4_PU_MASK                      0x4000  /* GP4_PU */
+#define WM2200_GP4_PU_SHIFT                         14  /* GP4_PU */
+#define WM2200_GP4_PU_WIDTH                          1  /* GP4_PU */
+#define WM2200_GP4_PD                           0x2000  /* GP4_PD */
+#define WM2200_GP4_PD_MASK                      0x2000  /* GP4_PD */
+#define WM2200_GP4_PD_SHIFT                         13  /* GP4_PD */
+#define WM2200_GP4_PD_WIDTH                          1  /* GP4_PD */
+#define WM2200_GP4_POL                          0x0400  /* GP4_POL */
+#define WM2200_GP4_POL_MASK                     0x0400  /* GP4_POL */
+#define WM2200_GP4_POL_SHIFT                        10  /* GP4_POL */
+#define WM2200_GP4_POL_WIDTH                         1  /* GP4_POL */
+#define WM2200_GP4_OP_CFG                       0x0200  /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_MASK                  0x0200  /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_SHIFT                      9  /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_WIDTH                      1  /* GP4_OP_CFG */
+#define WM2200_GP4_DB                           0x0100  /* GP4_DB */
+#define WM2200_GP4_DB_MASK                      0x0100  /* GP4_DB */
+#define WM2200_GP4_DB_SHIFT                          8  /* GP4_DB */
+#define WM2200_GP4_DB_WIDTH                          1  /* GP4_DB */
+#define WM2200_GP4_LVL                          0x0040  /* GP4_LVL */
+#define WM2200_GP4_LVL_MASK                     0x0040  /* GP4_LVL */
+#define WM2200_GP4_LVL_SHIFT                         6  /* GP4_LVL */
+#define WM2200_GP4_LVL_WIDTH                         1  /* GP4_LVL */
+#define WM2200_GP4_FN_MASK                      0x003F  /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_SHIFT                          0  /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_WIDTH                          6  /* GP4_FN - [5:0] */
+
+/*
+ * R1799 (0x707) - ADPS1 IRQ0
+ */
+#define WM2200_DSP_IRQ1                         0x0002  /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_MASK                    0x0002  /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_SHIFT                        1  /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_WIDTH                        1  /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ0                         0x0001  /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_MASK                    0x0001  /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_SHIFT                        0  /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_WIDTH                        1  /* DSP_IRQ0 */
+
+/*
+ * R1800 (0x708) - ADPS1 IRQ1
+ */
+#define WM2200_DSP_IRQ3                         0x0002  /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_MASK                    0x0002  /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_SHIFT                        1  /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_WIDTH                        1  /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ2                         0x0001  /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_MASK                    0x0001  /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_SHIFT                        0  /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_WIDTH                        1  /* DSP_IRQ2 */
+
+/*
+ * R1801 (0x709) - Misc Pad Ctrl 1
+ */
+#define WM2200_LDO1ENA_PD                       0x8000  /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_MASK                  0x8000  /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_SHIFT                     15  /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_WIDTH                      1  /* LDO1ENA_PD */
+#define WM2200_MCLK2_PD                         0x2000  /* MCLK2_PD */
+#define WM2200_MCLK2_PD_MASK                    0x2000  /* MCLK2_PD */
+#define WM2200_MCLK2_PD_SHIFT                       13  /* MCLK2_PD */
+#define WM2200_MCLK2_PD_WIDTH                        1  /* MCLK2_PD */
+#define WM2200_MCLK1_PD                         0x1000  /* MCLK1_PD */
+#define WM2200_MCLK1_PD_MASK                    0x1000  /* MCLK1_PD */
+#define WM2200_MCLK1_PD_SHIFT                       12  /* MCLK1_PD */
+#define WM2200_MCLK1_PD_WIDTH                        1  /* MCLK1_PD */
+#define WM2200_DACLRCLK1_PU                     0x0400  /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_MASK                0x0400  /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_SHIFT                   10  /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_WIDTH                    1  /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PD                     0x0200  /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_MASK                0x0200  /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_SHIFT                    9  /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_WIDTH                    1  /* DACLRCLK1_PD */
+#define WM2200_BCLK1_PU                         0x0100  /* BCLK1_PU */
+#define WM2200_BCLK1_PU_MASK                    0x0100  /* BCLK1_PU */
+#define WM2200_BCLK1_PU_SHIFT                        8  /* BCLK1_PU */
+#define WM2200_BCLK1_PU_WIDTH                        1  /* BCLK1_PU */
+#define WM2200_BCLK1_PD                         0x0080  /* BCLK1_PD */
+#define WM2200_BCLK1_PD_MASK                    0x0080  /* BCLK1_PD */
+#define WM2200_BCLK1_PD_SHIFT                        7  /* BCLK1_PD */
+#define WM2200_BCLK1_PD_WIDTH                        1  /* BCLK1_PD */
+#define WM2200_DACDAT1_PU                       0x0040  /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_MASK                  0x0040  /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_SHIFT                      6  /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_WIDTH                      1  /* DACDAT1_PU */
+#define WM2200_DACDAT1_PD                       0x0020  /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_MASK                  0x0020  /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_SHIFT                      5  /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_WIDTH                      1  /* DACDAT1_PD */
+#define WM2200_DMICDAT3_PD                      0x0010  /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_MASK                 0x0010  /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_SHIFT                     4  /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_WIDTH                     1  /* DMICDAT3_PD */
+#define WM2200_DMICDAT2_PD                      0x0008  /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_MASK                 0x0008  /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_SHIFT                     3  /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_WIDTH                     1  /* DMICDAT2_PD */
+#define WM2200_DMICDAT1_PD                      0x0004  /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_MASK                 0x0004  /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_SHIFT                     2  /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_WIDTH                     1  /* DMICDAT1_PD */
+#define WM2200_RSTB_PU                          0x0002  /* RSTB_PU */
+#define WM2200_RSTB_PU_MASK                     0x0002  /* RSTB_PU */
+#define WM2200_RSTB_PU_SHIFT                         1  /* RSTB_PU */
+#define WM2200_RSTB_PU_WIDTH                         1  /* RSTB_PU */
+#define WM2200_ADDR_PD                          0x0001  /* ADDR_PD */
+#define WM2200_ADDR_PD_MASK                     0x0001  /* ADDR_PD */
+#define WM2200_ADDR_PD_SHIFT                         0  /* ADDR_PD */
+#define WM2200_ADDR_PD_WIDTH                         1  /* ADDR_PD */
+
+/*
+ * R2048 (0x800) - Interrupt Status 1
+ */
+#define WM2200_DSP_IRQ0_EINT                    0x0080  /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_MASK               0x0080  /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_SHIFT                   7  /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_WIDTH                   1  /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ1_EINT                    0x0040  /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_MASK               0x0040  /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_SHIFT                   6  /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_WIDTH                   1  /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ2_EINT                    0x0020  /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_MASK               0x0020  /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_SHIFT                   5  /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_WIDTH                   1  /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ3_EINT                    0x0010  /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_MASK               0x0010  /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_SHIFT                   4  /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_WIDTH                   1  /* DSP_IRQ3_EINT */
+#define WM2200_GP4_EINT                         0x0008  /* GP4_EINT */
+#define WM2200_GP4_EINT_MASK                    0x0008  /* GP4_EINT */
+#define WM2200_GP4_EINT_SHIFT                        3  /* GP4_EINT */
+#define WM2200_GP4_EINT_WIDTH                        1  /* GP4_EINT */
+#define WM2200_GP3_EINT                         0x0004  /* GP3_EINT */
+#define WM2200_GP3_EINT_MASK                    0x0004  /* GP3_EINT */
+#define WM2200_GP3_EINT_SHIFT                        2  /* GP3_EINT */
+#define WM2200_GP3_EINT_WIDTH                        1  /* GP3_EINT */
+#define WM2200_GP2_EINT                         0x0002  /* GP2_EINT */
+#define WM2200_GP2_EINT_MASK                    0x0002  /* GP2_EINT */
+#define WM2200_GP2_EINT_SHIFT                        1  /* GP2_EINT */
+#define WM2200_GP2_EINT_WIDTH                        1  /* GP2_EINT */
+#define WM2200_GP1_EINT                         0x0001  /* GP1_EINT */
+#define WM2200_GP1_EINT_MASK                    0x0001  /* GP1_EINT */
+#define WM2200_GP1_EINT_SHIFT                        0  /* GP1_EINT */
+#define WM2200_GP1_EINT_WIDTH                        1  /* GP1_EINT */
+
+/*
+ * R2049 (0x801) - Interrupt Status 1 Mask
+ */
+#define WM2200_IM_DSP_IRQ0_EINT                 0x0080  /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_MASK            0x0080  /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_SHIFT                7  /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_WIDTH                1  /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT                 0x0040  /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_MASK            0x0040  /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_SHIFT                6  /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_WIDTH                1  /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT                 0x0020  /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_MASK            0x0020  /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_SHIFT                5  /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_WIDTH                1  /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT                 0x0010  /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_MASK            0x0010  /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_SHIFT                4  /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_WIDTH                1  /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_GP4_EINT                      0x0008  /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_MASK                 0x0008  /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_SHIFT                     3  /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_WIDTH                     1  /* IM_GP4_EINT */
+#define WM2200_IM_GP3_EINT                      0x0004  /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_MASK                 0x0004  /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_SHIFT                     2  /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_WIDTH                     1  /* IM_GP3_EINT */
+#define WM2200_IM_GP2_EINT                      0x0002  /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_MASK                 0x0002  /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_SHIFT                     1  /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_WIDTH                     1  /* IM_GP2_EINT */
+#define WM2200_IM_GP1_EINT                      0x0001  /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_MASK                 0x0001  /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_SHIFT                     0  /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_WIDTH                     1  /* IM_GP1_EINT */
+
+/*
+ * R2050 (0x802) - Interrupt Status 2
+ */
+#define WM2200_WSEQ_BUSY_EINT                   0x0100  /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_MASK              0x0100  /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_SHIFT                  8  /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_WIDTH                  1  /* WSEQ_BUSY_EINT */
+#define WM2200_FLL_LOCK_EINT                    0x0002  /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_MASK               0x0002  /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_SHIFT                   1  /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_WIDTH                   1  /* FLL_LOCK_EINT */
+#define WM2200_CLKGEN_EINT                      0x0001  /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_MASK                 0x0001  /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_SHIFT                     0  /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_WIDTH                     1  /* CLKGEN_EINT */
+
+/*
+ * R2051 (0x803) - Interrupt Raw Status 2
+ */
+#define WM2200_WSEQ_BUSY_STS                    0x0100  /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_MASK               0x0100  /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_SHIFT                   8  /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_WIDTH                   1  /* WSEQ_BUSY_STS */
+#define WM2200_FLL_LOCK_STS                     0x0002  /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_MASK                0x0002  /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_SHIFT                    1  /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_WIDTH                    1  /* FLL_LOCK_STS */
+#define WM2200_CLKGEN_STS                       0x0001  /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_MASK                  0x0001  /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_SHIFT                      0  /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_WIDTH                      1  /* CLKGEN_STS */
+
+/*
+ * R2052 (0x804) - Interrupt Status 2 Mask
+ */
+#define WM2200_IM_WSEQ_BUSY_EINT                0x0100  /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_MASK           0x0100  /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_SHIFT               8  /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_WIDTH               1  /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_FLL_LOCK_EINT                 0x0002  /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_MASK            0x0002  /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_SHIFT                1  /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_WIDTH                1  /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_CLKGEN_EINT                   0x0001  /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_MASK              0x0001  /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_SHIFT                  0  /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_WIDTH                  1  /* IM_CLKGEN_EINT */
+
+/*
+ * R2056 (0x808) - Interrupt Control
+ */
+#define WM2200_IM_IRQ                           0x0001  /* IM_IRQ */
+#define WM2200_IM_IRQ_MASK                      0x0001  /* IM_IRQ */
+#define WM2200_IM_IRQ_SHIFT                          0  /* IM_IRQ */
+#define WM2200_IM_IRQ_WIDTH                          1  /* IM_IRQ */
+
+/*
+ * R2304 (0x900) - EQL_1
+ */
+#define WM2200_EQL_B1_GAIN_MASK                 0xF800  /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_SHIFT                    11  /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_WIDTH                     5  /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B2_GAIN_MASK                 0x07C0  /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_SHIFT                     6  /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_WIDTH                     5  /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B3_GAIN_MASK                 0x003E  /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_SHIFT                     1  /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_WIDTH                     5  /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_ENA                          0x0001  /* EQL_ENA */
+#define WM2200_EQL_ENA_MASK                     0x0001  /* EQL_ENA */
+#define WM2200_EQL_ENA_SHIFT                         0  /* EQL_ENA */
+#define WM2200_EQL_ENA_WIDTH                         1  /* EQL_ENA */
+
+/*
+ * R2305 (0x901) - EQL_2
+ */
+#define WM2200_EQL_B4_GAIN_MASK                 0xF800  /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_SHIFT                    11  /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_WIDTH                     5  /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B5_GAIN_MASK                 0x07C0  /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_SHIFT                     6  /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_WIDTH                     5  /* EQL_B5_GAIN - [10:6] */
+
+/*
+ * R2306 (0x902) - EQL_3
+ */
+#define WM2200_EQL_B1_A_MASK                    0xFFFF  /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_SHIFT                        0  /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_WIDTH                       16  /* EQL_B1_A - [15:0] */
+
+/*
+ * R2307 (0x903) - EQL_4
+ */
+#define WM2200_EQL_B1_B_MASK                    0xFFFF  /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_SHIFT                        0  /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_WIDTH                       16  /* EQL_B1_B - [15:0] */
+
+/*
+ * R2308 (0x904) - EQL_5
+ */
+#define WM2200_EQL_B1_PG_MASK                   0xFFFF  /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_SHIFT                       0  /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_WIDTH                      16  /* EQL_B1_PG - [15:0] */
+
+/*
+ * R2309 (0x905) - EQL_6
+ */
+#define WM2200_EQL_B2_A_MASK                    0xFFFF  /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_SHIFT                        0  /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_WIDTH                       16  /* EQL_B2_A - [15:0] */
+
+/*
+ * R2310 (0x906) - EQL_7
+ */
+#define WM2200_EQL_B2_B_MASK                    0xFFFF  /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_SHIFT                        0  /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_WIDTH                       16  /* EQL_B2_B - [15:0] */
+
+/*
+ * R2311 (0x907) - EQL_8
+ */
+#define WM2200_EQL_B2_C_MASK                    0xFFFF  /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_SHIFT                        0  /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_WIDTH                       16  /* EQL_B2_C - [15:0] */
+
+/*
+ * R2312 (0x908) - EQL_9
+ */
+#define WM2200_EQL_B2_PG_MASK                   0xFFFF  /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_SHIFT                       0  /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_WIDTH                      16  /* EQL_B2_PG - [15:0] */
+
+/*
+ * R2313 (0x909) - EQL_10
+ */
+#define WM2200_EQL_B3_A_MASK                    0xFFFF  /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_SHIFT                        0  /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_WIDTH                       16  /* EQL_B3_A - [15:0] */
+
+/*
+ * R2314 (0x90A) - EQL_11
+ */
+#define WM2200_EQL_B3_B_MASK                    0xFFFF  /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_SHIFT                        0  /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_WIDTH                       16  /* EQL_B3_B - [15:0] */
+
+/*
+ * R2315 (0x90B) - EQL_12
+ */
+#define WM2200_EQL_B3_C_MASK                    0xFFFF  /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_SHIFT                        0  /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_WIDTH                       16  /* EQL_B3_C - [15:0] */
+
+/*
+ * R2316 (0x90C) - EQL_13
+ */
+#define WM2200_EQL_B3_PG_MASK                   0xFFFF  /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_SHIFT                       0  /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_WIDTH                      16  /* EQL_B3_PG - [15:0] */
+
+/*
+ * R2317 (0x90D) - EQL_14
+ */
+#define WM2200_EQL_B4_A_MASK                    0xFFFF  /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_SHIFT                        0  /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_WIDTH                       16  /* EQL_B4_A - [15:0] */
+
+/*
+ * R2318 (0x90E) - EQL_15
+ */
+#define WM2200_EQL_B4_B_MASK                    0xFFFF  /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_SHIFT                        0  /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_WIDTH                       16  /* EQL_B4_B - [15:0] */
+
+/*
+ * R2319 (0x90F) - EQL_16
+ */
+#define WM2200_EQL_B4_C_MASK                    0xFFFF  /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_SHIFT                        0  /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_WIDTH                       16  /* EQL_B4_C - [15:0] */
+
+/*
+ * R2320 (0x910) - EQL_17
+ */
+#define WM2200_EQL_B4_PG_MASK                   0xFFFF  /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_SHIFT                       0  /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_WIDTH                      16  /* EQL_B4_PG - [15:0] */
+
+/*
+ * R2321 (0x911) - EQL_18
+ */
+#define WM2200_EQL_B5_A_MASK                    0xFFFF  /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_SHIFT                        0  /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_WIDTH                       16  /* EQL_B5_A - [15:0] */
+
+/*
+ * R2322 (0x912) - EQL_19
+ */
+#define WM2200_EQL_B5_B_MASK                    0xFFFF  /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_SHIFT                        0  /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_WIDTH                       16  /* EQL_B5_B - [15:0] */
+
+/*
+ * R2323 (0x913) - EQL_20
+ */
+#define WM2200_EQL_B5_PG_MASK                   0xFFFF  /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_SHIFT                       0  /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_WIDTH                      16  /* EQL_B5_PG - [15:0] */
+
+/*
+ * R2326 (0x916) - EQR_1
+ */
+#define WM2200_EQR_B1_GAIN_MASK                 0xF800  /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_SHIFT                    11  /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_WIDTH                     5  /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B2_GAIN_MASK                 0x07C0  /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_SHIFT                     6  /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_WIDTH                     5  /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B3_GAIN_MASK                 0x003E  /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_SHIFT                     1  /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_WIDTH                     5  /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_ENA                          0x0001  /* EQR_ENA */
+#define WM2200_EQR_ENA_MASK                     0x0001  /* EQR_ENA */
+#define WM2200_EQR_ENA_SHIFT                         0  /* EQR_ENA */
+#define WM2200_EQR_ENA_WIDTH                         1  /* EQR_ENA */
+
+/*
+ * R2327 (0x917) - EQR_2
+ */
+#define WM2200_EQR_B4_GAIN_MASK                 0xF800  /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_SHIFT                    11  /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_WIDTH                     5  /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B5_GAIN_MASK                 0x07C0  /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_SHIFT                     6  /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_WIDTH                     5  /* EQR_B5_GAIN - [10:6] */
+
+/*
+ * R2328 (0x918) - EQR_3
+ */
+#define WM2200_EQR_B1_A_MASK                    0xFFFF  /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_SHIFT                        0  /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_WIDTH                       16  /* EQR_B1_A - [15:0] */
+
+/*
+ * R2329 (0x919) - EQR_4
+ */
+#define WM2200_EQR_B1_B_MASK                    0xFFFF  /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_SHIFT                        0  /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_WIDTH                       16  /* EQR_B1_B - [15:0] */
+
+/*
+ * R2330 (0x91A) - EQR_5
+ */
+#define WM2200_EQR_B1_PG_MASK                   0xFFFF  /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_SHIFT                       0  /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_WIDTH                      16  /* EQR_B1_PG - [15:0] */
+
+/*
+ * R2331 (0x91B) - EQR_6
+ */
+#define WM2200_EQR_B2_A_MASK                    0xFFFF  /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_SHIFT                        0  /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_WIDTH                       16  /* EQR_B2_A - [15:0] */
+
+/*
+ * R2332 (0x91C) - EQR_7
+ */
+#define WM2200_EQR_B2_B_MASK                    0xFFFF  /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_SHIFT                        0  /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_WIDTH                       16  /* EQR_B2_B - [15:0] */
+
+/*
+ * R2333 (0x91D) - EQR_8
+ */
+#define WM2200_EQR_B2_C_MASK                    0xFFFF  /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_SHIFT                        0  /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_WIDTH                       16  /* EQR_B2_C - [15:0] */
+
+/*
+ * R2334 (0x91E) - EQR_9
+ */
+#define WM2200_EQR_B2_PG_MASK                   0xFFFF  /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_SHIFT                       0  /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_WIDTH                      16  /* EQR_B2_PG - [15:0] */
+
+/*
+ * R2335 (0x91F) - EQR_10
+ */
+#define WM2200_EQR_B3_A_MASK                    0xFFFF  /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_SHIFT                        0  /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_WIDTH                       16  /* EQR_B3_A - [15:0] */
+
+/*
+ * R2336 (0x920) - EQR_11
+ */
+#define WM2200_EQR_B3_B_MASK                    0xFFFF  /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_SHIFT                        0  /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_WIDTH                       16  /* EQR_B3_B - [15:0] */
+
+/*
+ * R2337 (0x921) - EQR_12
+ */
+#define WM2200_EQR_B3_C_MASK                    0xFFFF  /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_SHIFT                        0  /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_WIDTH                       16  /* EQR_B3_C - [15:0] */
+
+/*
+ * R2338 (0x922) - EQR_13
+ */
+#define WM2200_EQR_B3_PG_MASK                   0xFFFF  /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_SHIFT                       0  /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_WIDTH                      16  /* EQR_B3_PG - [15:0] */
+
+/*
+ * R2339 (0x923) - EQR_14
+ */
+#define WM2200_EQR_B4_A_MASK                    0xFFFF  /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_SHIFT                        0  /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_WIDTH                       16  /* EQR_B4_A - [15:0] */
+
+/*
+ * R2340 (0x924) - EQR_15
+ */
+#define WM2200_EQR_B4_B_MASK                    0xFFFF  /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_SHIFT                        0  /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_WIDTH                       16  /* EQR_B4_B - [15:0] */
+
+/*
+ * R2341 (0x925) - EQR_16
+ */
+#define WM2200_EQR_B4_C_MASK                    0xFFFF  /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_SHIFT                        0  /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_WIDTH                       16  /* EQR_B4_C - [15:0] */
+
+/*
+ * R2342 (0x926) - EQR_17
+ */
+#define WM2200_EQR_B4_PG_MASK                   0xFFFF  /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_SHIFT                       0  /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_WIDTH                      16  /* EQR_B4_PG - [15:0] */
+
+/*
+ * R2343 (0x927) - EQR_18
+ */
+#define WM2200_EQR_B5_A_MASK                    0xFFFF  /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_SHIFT                        0  /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_WIDTH                       16  /* EQR_B5_A - [15:0] */
+
+/*
+ * R2344 (0x928) - EQR_19
+ */
+#define WM2200_EQR_B5_B_MASK                    0xFFFF  /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_SHIFT                        0  /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_WIDTH                       16  /* EQR_B5_B - [15:0] */
+
+/*
+ * R2345 (0x929) - EQR_20
+ */
+#define WM2200_EQR_B5_PG_MASK                   0xFFFF  /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_SHIFT                       0  /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_WIDTH                      16  /* EQR_B5_PG - [15:0] */
+
+/*
+ * R2366 (0x93E) - HPLPF1_1
+ */
+#define WM2200_LHPF1_MODE                       0x0002  /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_MASK                  0x0002  /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_SHIFT                      1  /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_WIDTH                      1  /* LHPF1_MODE */
+#define WM2200_LHPF1_ENA                        0x0001  /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_MASK                   0x0001  /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_SHIFT                       0  /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_WIDTH                       1  /* LHPF1_ENA */
+
+/*
+ * R2367 (0x93F) - HPLPF1_2
+ */
+#define WM2200_LHPF1_COEFF_MASK                 0xFFFF  /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_SHIFT                     0  /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_WIDTH                    16  /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R2370 (0x942) - HPLPF2_1
+ */
+#define WM2200_LHPF2_MODE                       0x0002  /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_MASK                  0x0002  /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_SHIFT                      1  /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_WIDTH                      1  /* LHPF2_MODE */
+#define WM2200_LHPF2_ENA                        0x0001  /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_MASK                   0x0001  /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_SHIFT                       0  /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_WIDTH                       1  /* LHPF2_ENA */
+
+/*
+ * R2371 (0x943) - HPLPF2_2
+ */
+#define WM2200_LHPF2_COEFF_MASK                 0xFFFF  /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_SHIFT                     0  /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_WIDTH                    16  /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R2560 (0xA00) - DSP1 Control 1
+ */
+#define WM2200_DSP1_RW_SEQUENCE_ENA             0x0001  /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_MASK        0x0001  /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_SHIFT            0  /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_WIDTH            1  /* DSP1_RW_SEQUENCE_ENA */
+
+/*
+ * R2562 (0xA02) - DSP1 Control 2
+ */
+#define WM2200_DSP1_PAGE_BASE_PM_0_MASK         0xFF00  /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_SHIFT             8  /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_WIDTH             8  /* DSP1_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2563 (0xA03) - DSP1 Control 3
+ */
+#define WM2200_DSP1_PAGE_BASE_DM_0_MASK         0xFF00  /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_SHIFT             8  /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_WIDTH             8  /* DSP1_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2564 (0xA04) - DSP1 Control 4
+ */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_MASK         0xFF00  /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT             8  /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_WIDTH             8  /* DSP1_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2566 (0xA06) - DSP1 Control 5
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2567 (0xA07) - DSP1 Control 6
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2568 (0xA08) - DSP1 Control 7
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2569 (0xA09) - DSP1 Control 8
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2570 (0xA0A) - DSP1 Control 9
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2571 (0xA0B) - DSP1 Control 10
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2572 (0xA0C) - DSP1 Control 11
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2573 (0xA0D) - DSP1 Control 12
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2575 (0xA0F) - DSP1 Control 13
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2576 (0xA10) - DSP1 Control 14
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2577 (0xA11) - DSP1 Control 15
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2578 (0xA12) - DSP1 Control 16
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2579 (0xA13) - DSP1 Control 17
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2580 (0xA14) - DSP1 Control 18
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2582 (0xA16) - DSP1 Control 19
+ */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2583 (0xA17) - DSP1 Control 20
+ */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_MASK    0x00FF  /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_SHIFT        0  /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_WIDTH        8  /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2584 (0xA18) - DSP1 Control 21
+ */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_MASK    0x003F  /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_SHIFT        0  /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_WIDTH        6  /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2586 (0xA1A) - DSP1 Control 22
+ */
+#define WM2200_DSP1_DM_SIZE_MASK                0xFFFF  /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_SHIFT                    0  /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_WIDTH                   16  /* DSP1_DM_SIZE - [15:0] */
+
+/*
+ * R2587 (0xA1B) - DSP1 Control 23
+ */
+#define WM2200_DSP1_PM_SIZE_MASK                0xFFFF  /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_SHIFT                    0  /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_WIDTH                   16  /* DSP1_PM_SIZE - [15:0] */
+
+/*
+ * R2588 (0xA1C) - DSP1 Control 24
+ */
+#define WM2200_DSP1_ZM_SIZE_MASK                0xFFFF  /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_SHIFT                    0  /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_WIDTH                   16  /* DSP1_ZM_SIZE - [15:0] */
+
+/*
+ * R2590 (0xA1E) - DSP1 Control 25
+ */
+#define WM2200_DSP1_PING_FULL                   0x8000  /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_MASK              0x8000  /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_SHIFT                 15  /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_WIDTH                  1  /* DSP1_PING_FULL */
+#define WM2200_DSP1_PONG_FULL                   0x4000  /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_MASK              0x4000  /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_SHIFT                 14  /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_WIDTH                  1  /* DSP1_PONG_FULL */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_MASK   0x00FF  /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_SHIFT       0  /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_WIDTH       8  /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2592 (0xA20) - DSP1 Control 26
+ */
+#define WM2200_DSP1_SCRATCH_0_MASK              0xFFFF  /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_SHIFT                  0  /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_WIDTH                 16  /* DSP1_SCRATCH_0 - [15:0] */
+
+/*
+ * R2593 (0xA21) - DSP1 Control 27
+ */
+#define WM2200_DSP1_SCRATCH_1_MASK              0xFFFF  /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_SHIFT                  0  /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_WIDTH                 16  /* DSP1_SCRATCH_1 - [15:0] */
+
+/*
+ * R2594 (0xA22) - DSP1 Control 28
+ */
+#define WM2200_DSP1_SCRATCH_2_MASK              0xFFFF  /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_SHIFT                  0  /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_WIDTH                 16  /* DSP1_SCRATCH_2 - [15:0] */
+
+/*
+ * R2595 (0xA23) - DSP1 Control 29
+ */
+#define WM2200_DSP1_SCRATCH_3_MASK              0xFFFF  /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_SHIFT                  0  /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_WIDTH                 16  /* DSP1_SCRATCH_3 - [15:0] */
+
+/*
+ * R2596 (0xA24) - DSP1 Control 30
+ */
+#define WM2200_DSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
+#define WM2200_DSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
+#define WM2200_DSP1_START                       0x0001  /* DSP1_START */
+#define WM2200_DSP1_START_MASK                  0x0001  /* DSP1_START */
+#define WM2200_DSP1_START_SHIFT                      0  /* DSP1_START */
+#define WM2200_DSP1_START_WIDTH                      1  /* DSP1_START */
+
+/*
+ * R2598 (0xA26) - DSP1 Control 31
+ */
+#define WM2200_DSP1_CLK_RATE_MASK               0x0018  /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_SHIFT                   3  /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_WIDTH                   2  /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_AVAIL                   0x0004  /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_MASK              0x0004  /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_SHIFT                  2  /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_WIDTH                  1  /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_REQ_MASK                0x0003  /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_SHIFT                    0  /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_WIDTH                    2  /* DSP1_CLK_REQ - [1:0] */
+
+/*
+ * R2816 (0xB00) - DSP2 Control 1
+ */
+#define WM2200_DSP2_RW_SEQUENCE_ENA             0x0001  /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_MASK        0x0001  /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_SHIFT            0  /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_WIDTH            1  /* DSP2_RW_SEQUENCE_ENA */
+
+/*
+ * R2818 (0xB02) - DSP2 Control 2
+ */
+#define WM2200_DSP2_PAGE_BASE_PM_0_MASK         0xFF00  /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_SHIFT             8  /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_WIDTH             8  /* DSP2_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2819 (0xB03) - DSP2 Control 3
+ */
+#define WM2200_DSP2_PAGE_BASE_DM_0_MASK         0xFF00  /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_SHIFT             8  /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_WIDTH             8  /* DSP2_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2820 (0xB04) - DSP2 Control 4
+ */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_MASK         0xFF00  /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT             8  /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_WIDTH             8  /* DSP2_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2822 (0xB06) - DSP2 Control 5
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2823 (0xB07) - DSP2 Control 6
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2824 (0xB08) - DSP2 Control 7
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2825 (0xB09) - DSP2 Control 8
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2826 (0xB0A) - DSP2 Control 9
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2827 (0xB0B) - DSP2 Control 10
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2828 (0xB0C) - DSP2 Control 11
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2829 (0xB0D) - DSP2 Control 12
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2831 (0xB0F) - DSP2 Control 13
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2832 (0xB10) - DSP2 Control 14
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2833 (0xB11) - DSP2 Control 15
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2834 (0xB12) - DSP2 Control 16
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2835 (0xB13) - DSP2 Control 17
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2836 (0xB14) - DSP2 Control 18
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2838 (0xB16) - DSP2 Control 19
+ */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2839 (0xB17) - DSP2 Control 20
+ */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_MASK    0x00FF  /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_SHIFT        0  /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_WIDTH        8  /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2840 (0xB18) - DSP2 Control 21
+ */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_MASK    0x003F  /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_SHIFT        0  /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_WIDTH        6  /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2842 (0xB1A) - DSP2 Control 22
+ */
+#define WM2200_DSP2_DM_SIZE_MASK                0xFFFF  /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_SHIFT                    0  /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_WIDTH                   16  /* DSP2_DM_SIZE - [15:0] */
+
+/*
+ * R2843 (0xB1B) - DSP2 Control 23
+ */
+#define WM2200_DSP2_PM_SIZE_MASK                0xFFFF  /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_SHIFT                    0  /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_WIDTH                   16  /* DSP2_PM_SIZE - [15:0] */
+
+/*
+ * R2844 (0xB1C) - DSP2 Control 24
+ */
+#define WM2200_DSP2_ZM_SIZE_MASK                0xFFFF  /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_SHIFT                    0  /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_WIDTH                   16  /* DSP2_ZM_SIZE - [15:0] */
+
+/*
+ * R2846 (0xB1E) - DSP2 Control 25
+ */
+#define WM2200_DSP2_PING_FULL                   0x8000  /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_MASK              0x8000  /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_SHIFT                 15  /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_WIDTH                  1  /* DSP2_PING_FULL */
+#define WM2200_DSP2_PONG_FULL                   0x4000  /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_MASK              0x4000  /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_SHIFT                 14  /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_WIDTH                  1  /* DSP2_PONG_FULL */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_MASK   0x00FF  /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_SHIFT       0  /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_WIDTH       8  /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2848 (0xB20) - DSP2 Control 26
+ */
+#define WM2200_DSP2_SCRATCH_0_MASK              0xFFFF  /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_SHIFT                  0  /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_WIDTH                 16  /* DSP2_SCRATCH_0 - [15:0] */
+
+/*
+ * R2849 (0xB21) - DSP2 Control 27
+ */
+#define WM2200_DSP2_SCRATCH_1_MASK              0xFFFF  /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_SHIFT                  0  /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_WIDTH                 16  /* DSP2_SCRATCH_1 - [15:0] */
+
+/*
+ * R2850 (0xB22) - DSP2 Control 28
+ */
+#define WM2200_DSP2_SCRATCH_2_MASK              0xFFFF  /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_SHIFT                  0  /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_WIDTH                 16  /* DSP2_SCRATCH_2 - [15:0] */
+
+/*
+ * R2851 (0xB23) - DSP2 Control 29
+ */
+#define WM2200_DSP2_SCRATCH_3_MASK              0xFFFF  /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_SHIFT                  0  /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_WIDTH                 16  /* DSP2_SCRATCH_3 - [15:0] */
+
+/*
+ * R2852 (0xB24) - DSP2 Control 30
+ */
+#define WM2200_DSP2_DBG_CLK_ENA                 0x0008  /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_MASK            0x0008  /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_SHIFT                3  /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_WIDTH                1  /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_SYS_ENA                     0x0004  /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_MASK                0x0004  /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_SHIFT                    2  /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_WIDTH                    1  /* DSP2_SYS_ENA */
+#define WM2200_DSP2_CORE_ENA                    0x0002  /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_MASK               0x0002  /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_SHIFT                   1  /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_WIDTH                   1  /* DSP2_CORE_ENA */
+#define WM2200_DSP2_START                       0x0001  /* DSP2_START */
+#define WM2200_DSP2_START_MASK                  0x0001  /* DSP2_START */
+#define WM2200_DSP2_START_SHIFT                      0  /* DSP2_START */
+#define WM2200_DSP2_START_WIDTH                      1  /* DSP2_START */
+
+/*
+ * R2854 (0xB26) - DSP2 Control 31
+ */
+#define WM2200_DSP2_CLK_RATE_MASK               0x0018  /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_SHIFT                   3  /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_WIDTH                   2  /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_AVAIL                   0x0004  /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_MASK              0x0004  /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_SHIFT                  2  /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_WIDTH                  1  /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_REQ_MASK                0x0003  /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_SHIFT                    0  /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_WIDTH                    2  /* DSP2_CLK_REQ - [1:0] */
+
+#endif
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 89f2af77b1c3983afaa407e6ff2740ec95e0c068..b9c185ce64e46e04b0500416d70ba8bc0206701f 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -18,6 +18,7 @@
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/fixed.h>
 #include <linux/slab.h>
@@ -50,13 +51,11 @@ struct wm5100_fll {
 
 /* codec private data */
 struct wm5100_priv {
+	struct device *dev;
 	struct regmap *regmap;
 	struct snd_soc_codec *codec;
 
 	struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
-	struct regulator *cpvdd;
-	struct regulator *dbvdd2;
-	struct regulator *dbvdd3;
 
 	int rev;
 
@@ -73,6 +72,7 @@ struct wm5100_priv {
 	bool jack_detecting;
 	bool jack_mic;
 	int jack_mode;
+	int jack_flips;
 
 	struct wm5100_fll fll[2];
 
@@ -709,6 +709,8 @@ WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE),
 
 WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE),
 WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE),
+SND_SOC_BYTES_MASK("DRC", WM5100_DRC1_CTRL1, 5,
+		   WM5100_DRCL_ENA | WM5100_DRCR_ENA),
 
 WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE),
 WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE),
@@ -776,127 +778,48 @@ static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
-static int wm5100_cp_ev(struct snd_soc_dapm_widget *w,
-			struct snd_kcontrol *kcontrol,
-			int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-	int ret;
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		ret = regulator_enable(wm5100->cpvdd);
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
-				ret);
-			return ret;
-		}
-		return ret;
-
-	case SND_SOC_DAPM_POST_PMD:
-		ret = regulator_disable_deferred(wm5100->cpvdd, 20);
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to disable CPVDD: %d\n",
-				ret);
-			return ret;
-		}
-		return ret;
-
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w,
-			   struct snd_kcontrol *kcontrol,
-			   int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-	struct regulator *regulator;
-	int ret;
-
-	switch (w->shift) {
-	case 2:
-		regulator = wm5100->dbvdd2;
-		break;
-	case 3:
-		regulator = wm5100->dbvdd3;
-		break;
-	default:
-		BUG();
-		return 0;
-	}
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		ret = regulator_enable(regulator);
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
-				w->shift, ret);
-			return ret;
-		}
-		return ret;
-
-	case SND_SOC_DAPM_POST_PMD:
-		ret = regulator_disable(regulator);
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
-				w->shift, ret);
-			return ret;
-		}
-		return ret;
-
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static void wm5100_log_status3(struct snd_soc_codec *codec, int val)
+static void wm5100_log_status3(struct wm5100_priv *wm5100, int val)
 {
 	if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
-		dev_crit(codec->dev, "Speaker shutdown warning\n");
+		dev_crit(wm5100->dev, "Speaker shutdown warning\n");
 	if (val & WM5100_SPK_SHUTDOWN_EINT)
-		dev_crit(codec->dev, "Speaker shutdown\n");
+		dev_crit(wm5100->dev, "Speaker shutdown\n");
 	if (val & WM5100_CLKGEN_ERR_EINT)
-		dev_crit(codec->dev, "SYSCLK underclocked\n");
+		dev_crit(wm5100->dev, "SYSCLK underclocked\n");
 	if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
-		dev_crit(codec->dev, "ASYNCCLK underclocked\n");
+		dev_crit(wm5100->dev, "ASYNCCLK underclocked\n");
 }
 
-static void wm5100_log_status4(struct snd_soc_codec *codec, int val)
+static void wm5100_log_status4(struct wm5100_priv *wm5100, int val)
 {
 	if (val & WM5100_AIF3_ERR_EINT)
-		dev_err(codec->dev, "AIF3 configuration error\n");
+		dev_err(wm5100->dev, "AIF3 configuration error\n");
 	if (val & WM5100_AIF2_ERR_EINT)
-		dev_err(codec->dev, "AIF2 configuration error\n");
+		dev_err(wm5100->dev, "AIF2 configuration error\n");
 	if (val & WM5100_AIF1_ERR_EINT)
-		dev_err(codec->dev, "AIF1 configuration error\n");
+		dev_err(wm5100->dev, "AIF1 configuration error\n");
 	if (val & WM5100_CTRLIF_ERR_EINT)
-		dev_err(codec->dev, "Control interface error\n");
+		dev_err(wm5100->dev, "Control interface error\n");
 	if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "ISRC2 underclocked\n");
+		dev_err(wm5100->dev, "ISRC2 underclocked\n");
 	if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "ISRC1 underclocked\n");
+		dev_err(wm5100->dev, "ISRC1 underclocked\n");
 	if (val & WM5100_FX_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "FX underclocked\n");
+		dev_err(wm5100->dev, "FX underclocked\n");
 	if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "AIF3 underclocked\n");
+		dev_err(wm5100->dev, "AIF3 underclocked\n");
 	if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "AIF2 underclocked\n");
+		dev_err(wm5100->dev, "AIF2 underclocked\n");
 	if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "AIF1 underclocked\n");
+		dev_err(wm5100->dev, "AIF1 underclocked\n");
 	if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "ASRC underclocked\n");
+		dev_err(wm5100->dev, "ASRC underclocked\n");
 	if (val & WM5100_DAC_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "DAC underclocked\n");
+		dev_err(wm5100->dev, "DAC underclocked\n");
 	if (val & WM5100_ADC_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "ADC underclocked\n");
+		dev_err(wm5100->dev, "ADC underclocked\n");
 	if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
-		dev_err(codec->dev, "Mixer underclocked\n");
+		dev_err(wm5100->dev, "Mixer underclocked\n");
 }
 
 static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
@@ -904,16 +827,17 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
 			  int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
 	ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
 	ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
 		WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
 		WM5100_CLKGEN_ERR_ASYNC_STS;
-	wm5100_log_status3(codec, ret);
+	wm5100_log_status3(wm5100, ret);
 
 	ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
-	wm5100_log_status4(codec, ret);
+	wm5100_log_status4(wm5100, ret);
 
 	return 0;
 }
@@ -924,18 +848,16 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
 SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
 		    0, NULL, 0),
 
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
+
 SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
-		    wm5100_cp_ev,
-		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+		    NULL, 0),
 SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
 		    NULL, 0),
 SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
-		    WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev,
-		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev,
-		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev,
-		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+		    WM5100_CP2_BYPASS_SHIFT, 1, NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
 		    0, NULL, 0),
@@ -1146,6 +1068,9 @@ SND_SOC_DAPM_POST("Post", wm5100_post_ev),
 };
 
 static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+	{ "CP1", NULL, "CPVDD" },
+	{ "CP2 Active", NULL, "CPVDD" },
+
 	{ "IN1L", NULL, "SYSCLK" },
 	{ "IN1R", NULL, "SYSCLK" },
 	{ "IN2L", NULL, "SYSCLK" },
@@ -1308,10 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
 	{ "PWM2", NULL, "PWM2 Driver" },
 };
 
-static struct {
-	int reg;
-	int val;
-} wm5100_reva_patches[] = {
+static const __devinitdata struct reg_default wm5100_reva_patches[] = {
 	{ WM5100_AUDIO_IF_1_10, 0 },
 	{ WM5100_AUDIO_IF_1_11, 1 },
 	{ WM5100_AUDIO_IF_1_12, 2 },
@@ -1343,80 +1265,6 @@ static struct {
 	{ WM5100_AUDIO_IF_3_19, 1 },
 };
 
-static int wm5100_set_bias_level(struct snd_soc_codec *codec,
-				 enum snd_soc_bias_level level)
-{
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-	int ret, i;
-
-	switch (level) {
-	case SND_SOC_BIAS_ON:
-		break;
-
-	case SND_SOC_BIAS_PREPARE:
-		break;
-
-	case SND_SOC_BIAS_STANDBY:
-		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-			ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
-						    wm5100->core_supplies);
-			if (ret != 0) {
-				dev_err(codec->dev,
-					"Failed to enable supplies: %d\n",
-					ret);
-				return ret;
-			}
-
-			if (wm5100->pdata.ldo_ena) {
-				gpio_set_value_cansleep(wm5100->pdata.ldo_ena,
-							1);
-				msleep(2);
-			}
-
-			regcache_cache_only(wm5100->regmap, false);
-
-			switch (wm5100->rev) {
-			case 0:
-				regcache_cache_bypass(wm5100->regmap, true);
-				snd_soc_write(codec, 0x11, 0x3);
-				snd_soc_write(codec, 0x203, 0xc);
-				snd_soc_write(codec, 0x206, 0);
-				snd_soc_write(codec, 0x207, 0xf0);
-				snd_soc_write(codec, 0x208, 0x3c);
-				snd_soc_write(codec, 0x209, 0);
-				snd_soc_write(codec, 0x211, 0x20d8);
-				snd_soc_write(codec, 0x11, 0);
-
-				for (i = 0;
-				     i < ARRAY_SIZE(wm5100_reva_patches);
-				     i++)
-					snd_soc_write(codec,
-						      wm5100_reva_patches[i].reg,
-						      wm5100_reva_patches[i].val);
-				regcache_cache_bypass(wm5100->regmap, false);
-				break;
-			default:
-				break;
-			}
-
-			regcache_sync(wm5100->regmap);
-		}
-		break;
-
-	case SND_SOC_BIAS_OFF:
-		regcache_cache_only(wm5100->regmap, true);
-		regcache_mark_dirty(wm5100->regmap);
-		if (wm5100->pdata.ldo_ena)
-			gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
-		regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
-				       wm5100->core_supplies);
-		break;
-	}
-	codec->dapm.bias_level = level;
-
-	return 0;
-}
-
 static int wm5100_dai_to_base(struct snd_soc_dai *dai)
 {
 	switch (dai->id) {
@@ -1944,6 +1792,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 
 	if (!Fout) {
 		dev_dbg(codec->dev, "FLL%d disabled", fll_id);
+		if (fll->fout)
+			pm_runtime_put(codec->dev);
 		fll->fout = 0;
 		snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
 		return 0;
@@ -1988,6 +1838,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 	/* Clear any pending completions */
 	try_wait_for_completion(&fll->lock);
 
+	pm_runtime_get_sync(codec->dev);
+
 	snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
 
 	if (i2c->irq)
@@ -2022,6 +1874,7 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 	}
 	if (i == timeout) {
 		dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
+		pm_runtime_put(codec->dev);
 		return -ETIMEDOUT;
 	}
 
@@ -2124,55 +1977,73 @@ static int wm5100_dig_vu[] = {
 	WM5100_DAC_DIGITAL_VOLUME_6R,
 };
 
-static void wm5100_set_detect_mode(struct snd_soc_codec *codec, int the_mode)
+static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode)
 {
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
 	struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
 
 	BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
 
 	gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
-	snd_soc_update_bits(codec, WM5100_ACCESSORY_DETECT_MODE_1,
-			    WM5100_ACCDET_BIAS_SRC_MASK |
-			    WM5100_ACCDET_SRC,
-			    (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
-			    mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
-	snd_soc_update_bits(codec, WM5100_MISC_CONTROL,
-			    WM5100_HPCOM_SRC,
-			    mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
+	regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1,
+			   WM5100_ACCDET_BIAS_SRC_MASK |
+			   WM5100_ACCDET_SRC,
+			   (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
+			   mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
+	regmap_update_bits(wm5100->regmap, WM5100_MISC_CONTROL,
+			   WM5100_HPCOM_SRC,
+			   mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
 
 	wm5100->jack_mode = the_mode;
 
-	dev_dbg(codec->dev, "Set microphone polarity to %d\n",
+	dev_dbg(wm5100->dev, "Set microphone polarity to %d\n",
 		wm5100->jack_mode);
 }
 
-static void wm5100_micd_irq(struct snd_soc_codec *codec)
+static void wm5100_report_headphone(struct wm5100_priv *wm5100)
 {
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-	int val;
+	dev_dbg(wm5100->dev, "Headphone detected\n");
+	wm5100->jack_detecting = false;
+	snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
+			    SND_JACK_HEADPHONE);
+
+	/* Increase the detection rate a bit for responsiveness. */
+	regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+			   WM5100_ACCDET_RATE_MASK,
+			   7 << WM5100_ACCDET_RATE_SHIFT);
+}
 
-	val = snd_soc_read(codec, WM5100_MIC_DETECT_3);
+static void wm5100_micd_irq(struct wm5100_priv *wm5100)
+{
+	unsigned int val;
+	int ret;
 
-	dev_dbg(codec->dev, "Microphone event: %x\n", val);
+	ret = regmap_read(wm5100->regmap, WM5100_MIC_DETECT_3, &val);
+	if (ret != 0) {
+		dev_err(wm5100->dev, "Failed to read micropone status: %d\n",
+			ret);
+		return;
+	}
+
+	dev_dbg(wm5100->dev, "Microphone event: %x\n", val);
 
 	if (!(val & WM5100_ACCDET_VALID)) {
-		dev_warn(codec->dev, "Microphone detection state invalid\n");
+		dev_warn(wm5100->dev, "Microphone detection state invalid\n");
 		return;
 	}
 
 	/* No accessory, reset everything and report removal */
 	if (!(val & WM5100_ACCDET_STS)) {
-		dev_dbg(codec->dev, "Jack removal detected\n");
+		dev_dbg(wm5100->dev, "Jack removal detected\n");
 		wm5100->jack_mic = false;
 		wm5100->jack_detecting = true;
+		wm5100->jack_flips = 0;
 		snd_soc_jack_report(wm5100->jack, 0,
 				    SND_JACK_LINEOUT | SND_JACK_HEADSET |
 				    SND_JACK_BTN_0);
 
-		snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
-				    WM5100_ACCDET_RATE_MASK,
-				    WM5100_ACCDET_RATE_MASK);
+		regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+				   WM5100_ACCDET_RATE_MASK,
+				   WM5100_ACCDET_RATE_MASK);
 		return;
 	}
 
@@ -2182,7 +2053,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
 	 */
 	if (val & 0x400) {
 		if (wm5100->jack_detecting) {
-			dev_dbg(codec->dev, "Microphone detected\n");
+			dev_dbg(wm5100->dev, "Microphone detected\n");
 			wm5100->jack_mic = true;
 			wm5100->jack_detecting = false;
 			snd_soc_jack_report(wm5100->jack,
@@ -2191,11 +2062,11 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
 
 			/* Increase poll rate to give better responsiveness
 			 * for buttons */
-			snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
-					    WM5100_ACCDET_RATE_MASK,
-					    5 << WM5100_ACCDET_RATE_SHIFT);
+			regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+					   WM5100_ACCDET_RATE_MASK,
+					   5 << WM5100_ACCDET_RATE_SHIFT);
 		} else {
-			dev_dbg(codec->dev, "Mic button up\n");
+			dev_dbg(wm5100->dev, "Mic button up\n");
 			snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0);
 		}
 
@@ -2205,10 +2076,16 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
 	/* If we detected a lower impedence during initial startup
 	 * then we probably have the wrong polarity, flip it.  Don't
 	 * do this for the lowest impedences to speed up detection of
-	 * plain headphones.
+	 * plain headphones and give up if neither polarity looks
+	 * sensible.
 	 */
 	if (wm5100->jack_detecting && (val & 0x3f8)) {
-		wm5100_set_detect_mode(codec, !wm5100->jack_mode);
+		wm5100->jack_flips++;
+
+		if (wm5100->jack_flips > 1)
+			wm5100_report_headphone(wm5100);
+		else
+			wm5100_set_detect_mode(wm5100, !wm5100->jack_mode);
 
 		return;
 	}
@@ -2218,21 +2095,11 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
 	 */
 	if (val & 0x3fc) {
 		if (wm5100->jack_mic) {
-			dev_dbg(codec->dev, "Mic button detected\n");
+			dev_dbg(wm5100->dev, "Mic button detected\n");
 			snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
 					    SND_JACK_BTN_0);
 		} else if (wm5100->jack_detecting) {
-			dev_dbg(codec->dev, "Headphone detected\n");
-			wm5100->jack_detecting = false;
-			snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
-					    SND_JACK_HEADPHONE);
-
-			/* Increase the detection rate a bit for
-			 * responsiveness.
-			 */
-			snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
-					    WM5100_ACCDET_RATE_MASK,
-					    7 << WM5100_ACCDET_RATE_SHIFT);
+			wm5100_report_headphone(wm5100);
 		}
 	}
 }
@@ -2244,8 +2111,9 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
 	if (jack) {
 		wm5100->jack = jack;
 		wm5100->jack_detecting = true;
+		wm5100->jack_flips = 0;
 
-		wm5100_set_detect_mode(codec, 0);
+		wm5100_set_detect_mode(wm5100, 0);
 
 		/* Slowest detection rate, gives debounce for initial
 		 * detection */
@@ -2284,52 +2152,70 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
 
 static irqreturn_t wm5100_irq(int irq, void *data)
 {
-	struct snd_soc_codec *codec = data;
-	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+	struct wm5100_priv *wm5100 = data;
 	irqreturn_t status = IRQ_NONE;
-	int irq_val;
+	unsigned int irq_val, mask_val;
+	int ret;
 
-	irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3);
-	if (irq_val < 0) {
-		dev_err(codec->dev, "Failed to read IRQ status 3: %d\n",
-			irq_val);
+	ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, &irq_val);
+	if (ret < 0) {
+		dev_err(wm5100->dev, "Failed to read IRQ status 3: %d\n",
+			ret);
 		irq_val = 0;
 	}
-	irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK);
 
-	snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val);
+	ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3_MASK,
+			  &mask_val);
+	if (ret < 0) {
+		dev_err(wm5100->dev, "Failed to read IRQ mask 3: %d\n",
+			ret);
+		mask_val = 0xffff;
+	}
+
+	irq_val &= ~mask_val;
+
+	regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, irq_val);
 
 	if (irq_val)
 		status = IRQ_HANDLED;
 
-	wm5100_log_status3(codec, irq_val);
+	wm5100_log_status3(wm5100, irq_val);
 
 	if (irq_val & WM5100_FLL1_LOCK_EINT) {
-		dev_dbg(codec->dev, "FLL1 locked\n");
+		dev_dbg(wm5100->dev, "FLL1 locked\n");
 		complete(&wm5100->fll[0].lock);
 	}
 	if (irq_val & WM5100_FLL2_LOCK_EINT) {
-		dev_dbg(codec->dev, "FLL2 locked\n");
+		dev_dbg(wm5100->dev, "FLL2 locked\n");
 		complete(&wm5100->fll[1].lock);
 	}
 
 	if (irq_val & WM5100_ACCDET_EINT)
-		wm5100_micd_irq(codec);
+		wm5100_micd_irq(wm5100);
 
-	irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4);
-	if (irq_val < 0) {
-		dev_err(codec->dev, "Failed to read IRQ status 4: %d\n",
-			irq_val);
+	ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, &irq_val);
+	if (ret < 0) {
+		dev_err(wm5100->dev, "Failed to read IRQ status 4: %d\n",
+			ret);
 		irq_val = 0;
 	}
-	irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK);
+
+	ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4_MASK,
+			  &mask_val);
+	if (ret < 0) {
+		dev_err(wm5100->dev, "Failed to read IRQ mask 4: %d\n",
+			ret);
+		mask_val = 0xffff;
+	}
+
+	irq_val &= ~mask_val;
 
 	if (irq_val)
 		status = IRQ_HANDLED;
 
-	snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val);
+	regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, irq_val);
 
-	wm5100_log_status4(codec, irq_val);
+	wm5100_log_status4(wm5100, irq_val);
 
 	return status;
 }
@@ -2454,7 +2340,7 @@ static int wm5100_probe(struct snd_soc_codec *codec)
 {
 	struct i2c_client *i2c = to_i2c_client(codec->dev);
 	struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-	int ret, i, irq_flags;
+	int ret, i;
 
 	wm5100->codec = codec;
 	codec->control_data = wm5100->regmap;
@@ -2465,9 +2351,6 @@ static int wm5100_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	regcache_cache_only(wm5100->regmap, true);
-
-
 	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);
@@ -2478,60 +2361,10 @@ static int wm5100_probe(struct snd_soc_codec *codec)
 
 	/* TODO: check if we're symmetric */
 
-	if (i2c->irq) {
-		if (wm5100->pdata.irq_flags)
-			irq_flags = wm5100->pdata.irq_flags;
-		else
-			irq_flags = IRQF_TRIGGER_LOW;
-
-		irq_flags |= IRQF_ONESHOT;
-
-		if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
-			ret = request_threaded_irq(i2c->irq, NULL,
-						   wm5100_edge_irq,
-						   irq_flags, "wm5100", codec);
-		else
-			ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
-						   irq_flags, "wm5100", codec);
-
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
-				i2c->irq, ret);
-		} else {
-			/* Enable default interrupts */
-			snd_soc_update_bits(codec,
-					    WM5100_INTERRUPT_STATUS_3_MASK,
-					    WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
-					    WM5100_IM_SPK_SHUTDOWN_EINT |
-					    WM5100_IM_ASRC2_LOCK_EINT |
-					    WM5100_IM_ASRC1_LOCK_EINT |
-					    WM5100_IM_FLL2_LOCK_EINT |
-					    WM5100_IM_FLL1_LOCK_EINT |
-					    WM5100_CLKGEN_ERR_EINT |
-					    WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
-
-			snd_soc_update_bits(codec,
-					    WM5100_INTERRUPT_STATUS_4_MASK,
-					    WM5100_AIF3_ERR_EINT |
-					    WM5100_AIF2_ERR_EINT |
-					    WM5100_AIF1_ERR_EINT |
-					    WM5100_CTRLIF_ERR_EINT |
-					    WM5100_ISRC2_UNDERCLOCKED_EINT |
-					    WM5100_ISRC1_UNDERCLOCKED_EINT |
-					    WM5100_FX_UNDERCLOCKED_EINT |
-					    WM5100_AIF3_UNDERCLOCKED_EINT |
-					    WM5100_AIF2_UNDERCLOCKED_EINT |
-					    WM5100_AIF1_UNDERCLOCKED_EINT |
-					    WM5100_ASRC_UNDERCLOCKED_EINT |
-					    WM5100_DAC_UNDERCLOCKED_EINT |
-					    WM5100_ADC_UNDERCLOCKED_EINT |
-					    WM5100_MIXER_UNDERCLOCKED_EINT, 0);
-		}
-	} else {
+	if (i2c->irq)
 		snd_soc_dapm_new_controls(&codec->dapm,
 					  wm5100_dapm_widgets_noirq,
 					  ARRAY_SIZE(wm5100_dapm_widgets_noirq));
-	}
 
 	if (wm5100->pdata.hp_pol) {
 		ret = gpio_request_one(wm5100->pdata.hp_pol,
@@ -2543,19 +2376,9 @@ static int wm5100_probe(struct snd_soc_codec *codec)
 		}
 	}
 
-	/* We'll get woken up again when the system has something useful
-	 * for us to do.
-	 */
-	if (wm5100->pdata.ldo_ena)
-		gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
-	regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
-			       wm5100->core_supplies);
-
 	return 0;
 
 err_gpio:
-	if (i2c->irq)
-		free_irq(i2c->irq, codec);
 
 	return ret;
 }
@@ -2563,14 +2386,11 @@ static int wm5100_probe(struct snd_soc_codec *codec)
 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;
 }
 
@@ -2587,7 +2407,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
 
 	.set_sysclk = wm5100_set_sysclk,
 	.set_pll = wm5100_set_fll,
-	.set_bias_level = wm5100_set_bias_level,
 	.idle_bias_off = 1,
 	.reg_cache_size = WM5100_MAX_REGISTER,
 	.volatile_register = wm5100_soc_volatile,
@@ -2626,13 +2445,15 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 	struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
 	struct wm5100_priv *wm5100;
 	unsigned int reg;
-	int ret, i;
+	int ret, i, irq_flags;
 
 	wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv),
 			      GFP_KERNEL);
 	if (wm5100 == NULL)
 		return -ENOMEM;
 
+	wm5100->dev = &i2c->dev;
+
 	wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
 	if (IS_ERR(wm5100->regmap)) {
 		ret = PTR_ERR(wm5100->regmap);
@@ -2652,41 +2473,21 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 	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);
+	ret = devm_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;
+		goto err_regmap;
 	}
 
 	if (wm5100->pdata.ldo_ena) {
@@ -2712,7 +2513,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 
 	ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, &reg);
 	if (ret < 0) {
-		dev_err(&i2c->dev, "Failed to read ID register\n");
+		dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
 		goto err_reset;
 	}
 	switch (reg) {
@@ -2741,6 +2542,22 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 		goto err_reset;
 	}
 
+	switch (wm5100->rev) {
+	case 0:
+		ret = regmap_register_patch(wm5100->regmap,
+					    wm5100_reva_patches,
+					    ARRAY_SIZE(wm5100_reva_patches));
+		if (ret != 0) {
+			dev_err(&i2c->dev, "Failed to register patches: %d\n",
+				ret);
+			goto err_reset;
+		}
+		break;
+	default:
+		break;
+	}
+
+
 	wm5100_init_gpio(i2c);
 
 	for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
@@ -2761,6 +2578,62 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 				    WM5100_IN1_DMIC_SUP_SHIFT));
 	}
 
+	if (i2c->irq) {
+		if (wm5100->pdata.irq_flags)
+			irq_flags = wm5100->pdata.irq_flags;
+		else
+			irq_flags = IRQF_TRIGGER_LOW;
+
+		irq_flags |= IRQF_ONESHOT;
+
+		if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+			ret = request_threaded_irq(i2c->irq, NULL,
+						   wm5100_edge_irq, irq_flags,
+						   "wm5100", wm5100);
+		else
+			ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
+						   irq_flags, "wm5100",
+						   wm5100);
+
+		if (ret != 0) {
+			dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+				i2c->irq, ret);
+		} else {
+			/* Enable default interrupts */
+			regmap_update_bits(wm5100->regmap,
+					   WM5100_INTERRUPT_STATUS_3_MASK,
+					   WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
+					   WM5100_IM_SPK_SHUTDOWN_EINT |
+					   WM5100_IM_ASRC2_LOCK_EINT |
+					   WM5100_IM_ASRC1_LOCK_EINT |
+					   WM5100_IM_FLL2_LOCK_EINT |
+					   WM5100_IM_FLL1_LOCK_EINT |
+					   WM5100_CLKGEN_ERR_EINT |
+					   WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
+
+			regmap_update_bits(wm5100->regmap,
+					   WM5100_INTERRUPT_STATUS_4_MASK,
+					   WM5100_AIF3_ERR_EINT |
+					   WM5100_AIF2_ERR_EINT |
+					   WM5100_AIF1_ERR_EINT |
+					   WM5100_CTRLIF_ERR_EINT |
+					   WM5100_ISRC2_UNDERCLOCKED_EINT |
+					   WM5100_ISRC1_UNDERCLOCKED_EINT |
+					   WM5100_FX_UNDERCLOCKED_EINT |
+					   WM5100_AIF3_UNDERCLOCKED_EINT |
+					   WM5100_AIF2_UNDERCLOCKED_EINT |
+					   WM5100_AIF1_UNDERCLOCKED_EINT |
+					   WM5100_ASRC_UNDERCLOCKED_EINT |
+					   WM5100_DAC_UNDERCLOCKED_EINT |
+					   WM5100_ADC_UNDERCLOCKED_EINT |
+					   WM5100_MIXER_UNDERCLOCKED_EINT, 0);
+		}
+	}
+
+	pm_runtime_set_active(&i2c->dev);
+	pm_runtime_enable(&i2c->dev);
+	pm_request_idle(&i2c->dev);
+
 	ret = snd_soc_register_codec(&i2c->dev,
 				     &soc_codec_dev_wm5100, wm5100_dai,
 				     ARRAY_SIZE(wm5100_dai));
@@ -2772,9 +2645,11 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 	return ret;
 
 err_reset:
+	if (i2c->irq)
+		free_irq(i2c->irq, wm5100);
 	wm5100_free_gpio(i2c);
 	if (wm5100->pdata.reset) {
-		gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+		gpio_set_value_cansleep(wm5100->pdata.reset, 0);
 		gpio_free(wm5100->pdata.reset);
 	}
 err_ldo:
@@ -2785,45 +2660,78 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 err_enable:
 	regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
 			       wm5100->core_supplies);
-err_dbvdd3:
-	regulator_put(wm5100->dbvdd3);
-err_dbvdd2:
-	regulator_put(wm5100->dbvdd2);
-err_cpvdd:
-	regulator_put(wm5100->cpvdd);
-err_core:
-	regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
-			    wm5100->core_supplies);
 err_regmap:
 	regmap_exit(wm5100->regmap);
 err:
 	return ret;
 }
 
-static __devexit int wm5100_i2c_remove(struct i2c_client *client)
+static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
 {
-	struct wm5100_priv *wm5100 = i2c_get_clientdata(client);
+	struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
 
-	snd_soc_unregister_codec(&client->dev);
-	wm5100_free_gpio(client);
+	snd_soc_unregister_codec(&i2c->dev);
+	if (i2c->irq)
+		free_irq(i2c->irq, wm5100);
+	wm5100_free_gpio(i2c);
 	if (wm5100->pdata.reset) {
-		gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+		gpio_set_value_cansleep(wm5100->pdata.reset, 0);
 		gpio_free(wm5100->pdata.reset);
 	}
 	if (wm5100->pdata.ldo_ena) {
 		gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
 		gpio_free(wm5100->pdata.ldo_ena);
 	}
-	regulator_put(wm5100->dbvdd3);
-	regulator_put(wm5100->dbvdd2);
-	regulator_put(wm5100->cpvdd);
-	regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
-			    wm5100->core_supplies);
 	regmap_exit(wm5100->regmap);
 
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int wm5100_runtime_suspend(struct device *dev)
+{
+	struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+
+	regcache_cache_only(wm5100->regmap, true);
+	regcache_mark_dirty(wm5100->regmap);
+	if (wm5100->pdata.ldo_ena)
+		gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+	regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+			       wm5100->core_supplies);
+
+	return 0;
+}
+
+static int wm5100_runtime_resume(struct device *dev)
+{
+	struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+				    wm5100->core_supplies);
+	if (ret != 0) {
+		dev_err(dev, "Failed to enable supplies: %d\n",
+			ret);
+		return ret;
+	}
+
+	if (wm5100->pdata.ldo_ena) {
+		gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1);
+		msleep(2);
+	}
+
+	regcache_cache_only(wm5100->regmap, false);
+	regcache_sync(wm5100->regmap);
+
+	return 0;
+}
+#endif
+
+static struct dev_pm_ops wm5100_pm = {
+	SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume,
+			   NULL)
+};
+
 static const struct i2c_device_id wm5100_i2c_id[] = {
 	{ "wm5100", 0 },
 	{ }
@@ -2834,6 +2742,7 @@ static struct i2c_driver wm5100_i2c_driver = {
 	.driver = {
 		.name = "wm5100",
 		.owner = THIS_MODULE,
+		.pm = &wm5100_pm,
 	},
 	.probe =    wm5100_i2c_probe,
 	.remove =   __devexit_p(wm5100_i2c_remove),
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 8821af70e660b354e4672a5aa7c32fa5fd7fd3f9..a32caa72bd7d727e4e94737e50650d647da1e2db 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,6 +19,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/of_device.h>
@@ -41,7 +42,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8731_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 	struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
 	unsigned int sysclk;
 	int sysclk_type;
@@ -52,16 +53,30 @@ struct wm8731_priv {
 
 /*
  * wm8731 register cache
- * We can't read the WM8731 register space when we are
- * using 2 wire for device control, so we cache them instead.
- * There is no point in caching the reset register
  */
-static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
-	0x0097, 0x0097, 0x0079, 0x0079,
-	0x000a, 0x0008, 0x009f, 0x000a,
-	0x0000, 0x0000
+static const struct reg_default wm8731_reg_defaults[] = {
+	{ 0, 0x0097 },
+	{ 1, 0x0097 },
+	{ 2, 0x0079 },
+	{ 3, 0x0079 },
+	{ 4, 0x000a },
+	{ 5, 0x0008 },
+	{ 6, 0x009f },
+	{ 7, 0x000a },
+	{ 8, 0x0000 },
+	{ 9, 0x0000 },
 };
 
+static bool wm8731_volatile(struct device *dev, unsigned int reg)
+{
+	return reg == WM8731_RESET;
+}
+
+static bool wm8731_writeable(struct device *dev, unsigned int reg)
+{
+	return reg <= WM8731_RESET;
+}
+
 #define wm8731_reset(c)	snd_soc_write(c, WM8731_RESET, 0)
 
 static const char *wm8731_input_select[] = {"Line In", "Mic"};
@@ -441,7 +456,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
 			if (ret != 0)
 				return ret;
 
-			snd_soc_cache_sync(codec);
+			regcache_sync(wm8731->regmap);
 		}
 
 		/* Clear PWROFF, gate CLKOUT, everything else as-is */
@@ -452,7 +467,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
 		snd_soc_write(codec, WM8731_PWR, 0xffff);
 		regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
 				       wm8731->supplies);
-		codec->cache_sync = 1;
+		regcache_mark_dirty(wm8731->regmap);
 		break;
 	}
 	codec->dapm.bias_level = level;
@@ -513,7 +528,8 @@ static int wm8731_probe(struct snd_soc_codec *codec)
 	struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
 	int ret = 0, i;
 
-	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);
+	codec->control_data = wm8731->regmap;
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -585,9 +601,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
 	.suspend =	wm8731_suspend,
 	.resume =	wm8731_resume,
 	.set_bias_level = wm8731_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8731_reg),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8731_reg,
 	.dapm_widgets = wm8731_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
 	.dapm_routes = wm8731_intercon,
@@ -603,6 +616,19 @@ static const struct of_device_id wm8731_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, wm8731_of_match);
 
+static const struct regmap_config wm8731_regmap = {
+	.reg_bits = 7,
+	.val_bits = 9,
+
+	.max_register = WM8731_RESET,
+	.volatile_reg = wm8731_volatile,
+	.writeable_reg = wm8731_writeable,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8731_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8731_reg_defaults),
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8731_spi_probe(struct spi_device *spi)
 {
@@ -613,20 +639,39 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
 	if (wm8731 == NULL)
 		return -ENOMEM;
 
-	wm8731->control_type = SND_SOC_SPI;
+	wm8731->regmap = regmap_init_spi(spi, &wm8731_regmap);
+	if (IS_ERR(wm8731->regmap)) {
+		ret = PTR_ERR(wm8731->regmap);
+		dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err;
+	}
+
 	spi_set_drvdata(spi, wm8731);
 
 	ret = snd_soc_register_codec(&spi->dev,
 			&soc_codec_dev_wm8731, &wm8731_dai, 1);
-	if (ret < 0)
-		kfree(wm8731);
+	if (ret != 0) {
+		dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
+		goto err_regmap;
+	}
+
+	return 0;
+
+err_regmap:
+	regmap_exit(wm8731->regmap);
+err:
+	kfree(wm8731);
 	return ret;
 }
 
 static int __devexit wm8731_spi_remove(struct spi_device *spi)
 {
+	struct wm8731_priv *wm8731 = spi_get_drvdata(spi);
+
 	snd_soc_unregister_codec(&spi->dev);
-	kfree(spi_get_drvdata(spi));
+	regmap_exit(wm8731->regmap);
+	kfree(wm8731);
 	return 0;
 }
 
@@ -652,20 +697,38 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
 	if (wm8731 == NULL)
 		return -ENOMEM;
 
+	wm8731->regmap = regmap_init_i2c(i2c, &wm8731_regmap);
+	if (IS_ERR(wm8731->regmap)) {
+		ret = PTR_ERR(wm8731->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err;
+	}
+
 	i2c_set_clientdata(i2c, wm8731);
-	wm8731->control_type = SND_SOC_I2C;
 
-	ret =  snd_soc_register_codec(&i2c->dev,
+	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8731, &wm8731_dai, 1);
-	if (ret < 0)
-		kfree(wm8731);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+		goto err_regmap;
+	}
+
+	return 0;
+
+err_regmap:
+	regmap_exit(wm8731->regmap);
+err:
+	kfree(wm8731);
 	return ret;
 }
 
 static __devexit int wm8731_i2c_remove(struct i2c_client *client)
 {
+	struct wm8731_priv *wm8731 = i2c_get_clientdata(client);
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm8731->regmap);
+	kfree(wm8731);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index ff95e62c56b9a7ae211c3f2d508d9cff94132931..4fe9d191e2774ab7fad2e00a5ba7542b51580669 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -599,7 +599,7 @@ static int wm8737_probe(struct snd_soc_codec *codec)
 	/* Bias level configuration will have done an extra enable */
 	regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
 
-	snd_soc_add_controls(codec, wm8737_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8737_snd_controls,
 			     ARRAY_SIZE(wm8737_snd_controls));
 	wm8737_add_widgets(codec);
 
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index b114c19f530ab89c30ea9daa24cc2a0eef143f85..e27e7b62b365a0a79942956455d95d40dd4f2e5d 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -39,6 +39,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/of_device.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -65,28 +66,86 @@ static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec,
  * We can't read the WM8753 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8753_reg[] = {
-	0x0000, 0x0008, 0x0000, 0x000a,
-	0x000a, 0x0033, 0x0000, 0x0007,
-	0x00ff, 0x00ff, 0x000f, 0x000f,
-	0x007b, 0x0000, 0x0032, 0x0000,
-	0x00c3, 0x00c3, 0x00c0, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0055, 0x0005, 0x0050, 0x0055,
-	0x0050, 0x0055, 0x0050, 0x0055,
-	0x0079, 0x0079, 0x0079, 0x0079,
-	0x0079, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0097, 0x0097, 0x0000,
-	0x0004, 0x0000, 0x0083, 0x0024,
-	0x01ba, 0x0000, 0x0083, 0x0024,
-	0x01ba, 0x0000, 0x0000, 0x0000
+static const struct reg_default wm8753_reg_defaults[] = {
+	{ 0x00, 0x0000 },
+	{ 0x01, 0x0008 },
+	{ 0x02, 0x0000 },
+	{ 0x03, 0x000a },
+	{ 0x04, 0x000a },
+	{ 0x05, 0x0033 },
+	{ 0x06, 0x0000 },
+	{ 0x07, 0x0007 },
+	{ 0x08, 0x00ff },
+	{ 0x09, 0x00ff },
+	{ 0x0a, 0x000f },
+	{ 0x0b, 0x000f },
+	{ 0x0c, 0x007b },
+	{ 0x0d, 0x0000 },
+	{ 0x0e, 0x0032 },
+	{ 0x0f, 0x0000 },
+	{ 0x10, 0x00c3 },
+	{ 0x11, 0x00c3 },
+	{ 0x12, 0x00c0 },
+	{ 0x13, 0x0000 },
+	{ 0x14, 0x0000 },
+	{ 0x15, 0x0000 },
+	{ 0x16, 0x0000 },
+	{ 0x17, 0x0000 },
+	{ 0x18, 0x0000 },
+	{ 0x19, 0x0000 },
+	{ 0x1a, 0x0000 },
+	{ 0x1b, 0x0000 },
+	{ 0x1c, 0x0000 },
+	{ 0x1d, 0x0000 },
+	{ 0x1e, 0x0000 },
+	{ 0x1f, 0x0000 },
+	{ 0x20, 0x0055 },
+	{ 0x21, 0x0005 },
+	{ 0x22, 0x0050 },
+	{ 0x23, 0x0055 },
+	{ 0x24, 0x0050 },
+	{ 0x25, 0x0055 },
+	{ 0x26, 0x0050 },
+	{ 0x27, 0x0055 },
+	{ 0x28, 0x0079 },
+	{ 0x29, 0x0079 },
+	{ 0x2a, 0x0079 },
+	{ 0x2b, 0x0079 },
+	{ 0x2c, 0x0079 },
+	{ 0x2d, 0x0000 },
+	{ 0x2e, 0x0000 },
+	{ 0x2f, 0x0000 },
+	{ 0x30, 0x0000 },
+	{ 0x31, 0x0097 },
+	{ 0x32, 0x0097 },
+	{ 0x33, 0x0000 },
+	{ 0x34, 0x0004 },
+	{ 0x35, 0x0000 },
+	{ 0x36, 0x0083 },
+	{ 0x37, 0x0024 },
+	{ 0x38, 0x01ba },
+	{ 0x39, 0x0000 },
+	{ 0x3a, 0x0083 },
+	{ 0x3b, 0x0024 },
+	{ 0x3c, 0x01ba },
+	{ 0x3d, 0x0000 },
+	{ 0x3e, 0x0000 },
+	{ 0x3f, 0x0000 },
 };
 
+static bool wm8753_volatile(struct device *dev, unsigned int reg)
+{
+	return reg == WM8753_RESET;
+}
+
+static bool wm8753_writeable(struct device *dev, unsigned int reg)
+{
+	return reg <= WM8753_ADCTL2;
+}
+
 /* codec private data */
 struct wm8753_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 	unsigned int sysclk;
 	unsigned int pcmclk;
 
@@ -1383,25 +1442,15 @@ static void wm8753_work(struct work_struct *work)
 static int wm8753_suspend(struct snd_soc_codec *codec)
 {
 	wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	codec->cache_sync = 1;
 	return 0;
 }
 
 static int wm8753_resume(struct snd_soc_codec *codec)
 {
-	u16 *reg_cache = codec->reg_cache;
-	int i;
-
-	/* Sync reg_cache with the hardware */
-	for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
-		if (i == WM8753_RESET)
-			continue;
-
-		/* No point in writing hardware default values back */
-		if (reg_cache[i] == wm8753_reg[i])
-			continue;
+	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
-		snd_soc_write(codec, i, reg_cache[i]);
-	}
+	regcache_sync(wm8753->regmap);
 
 	wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -1423,7 +1472,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
 
 	INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
 
-	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type);
+	codec->control_data = wm8753->regmap;
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -1473,9 +1523,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
 	.suspend =	wm8753_suspend,
 	.resume =	wm8753_resume,
 	.set_bias_level = wm8753_set_bias_level,
-	.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),
@@ -1491,30 +1538,62 @@ static const struct of_device_id wm8753_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8753_of_match);
 
+static const struct regmap_config wm8753_regmap = {
+	.reg_bits = 7,
+	.val_bits = 9,
+
+	.max_register = WM8753_ADCTL2,
+	.writeable_reg = wm8753_writeable,
+	.volatile_reg = wm8753_volatile,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8753_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8753_reg_defaults),
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8753_spi_probe(struct spi_device *spi)
 {
 	struct wm8753_priv *wm8753;
 	int ret;
 
-	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+	wm8753 = devm_kzalloc(&spi->dev, sizeof(struct wm8753_priv),
+			      GFP_KERNEL);
 	if (wm8753 == NULL)
 		return -ENOMEM;
 
-	wm8753->control_type = SND_SOC_SPI;
 	spi_set_drvdata(spi, wm8753);
 
-	ret = snd_soc_register_codec(&spi->dev,
-			&soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
-	if (ret < 0)
-		kfree(wm8753);
+	wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap);
+	if (IS_ERR(wm8753->regmap)) {
+		ret = PTR_ERR(wm8753->regmap);
+		dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err;
+	}
+
+	ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753,
+				     wm8753_dai, ARRAY_SIZE(wm8753_dai));
+	if (ret != 0) {
+		dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
+		goto err_regmap;
+	}
+
+	return 0;
+
+err_regmap:
+	regmap_exit(wm8753->regmap);
+err:
 	return ret;
 }
 
 static int __devexit wm8753_spi_remove(struct spi_device *spi)
 {
+	struct wm8753_priv *wm8753 = spi_get_drvdata(spi);
+
 	snd_soc_unregister_codec(&spi->dev);
-	kfree(spi_get_drvdata(spi));
+	regmap_exit(wm8753->regmap);
+	kfree(wm8753);
 	return 0;
 }
 
@@ -1536,24 +1615,42 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
 	struct wm8753_priv *wm8753;
 	int ret;
 
-	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+	wm8753 = devm_kzalloc(&i2c->dev, sizeof(struct wm8753_priv),
+			      GFP_KERNEL);
 	if (wm8753 == NULL)
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm8753);
-	wm8753->control_type = SND_SOC_I2C;
 
-	ret =  snd_soc_register_codec(&i2c->dev,
-			&soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
-	if (ret < 0)
-		kfree(wm8753);
+	wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap);
+	if (IS_ERR(wm8753->regmap)) {
+		ret = PTR_ERR(wm8753->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err;
+	}
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753,
+				     wm8753_dai, ARRAY_SIZE(wm8753_dai));
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+		goto err_regmap;
+	}
+
+	return 0;
+
+err_regmap:
+	regmap_exit(wm8753->regmap);
+err:
 	return ret;
 }
 
 static __devexit int wm8753_i2c_remove(struct i2c_client *client)
 {
+	struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
+
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm8753->regmap);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index 19374a9e5ba6ce06fc721e768255fcdb1ea2d97b..a5127b4ff9e1881dd49b5d588d3cd354d33cc746 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -580,8 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
 	wm8770 = snd_soc_codec_get_drvdata(codec);
 	wm8770->codec = codec;
 
-	codec->dapm.idle_bias_off = 1;
-
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -643,7 +641,7 @@ static int wm8770_probe(struct snd_soc_codec *codec)
 	/* mute all DACs */
 	snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
 
-	snd_soc_add_controls(codec, wm8770_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8770_snd_controls,
 			     ARRAY_SIZE(wm8770_snd_controls));
 	snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
 				  ARRAY_SIZE(wm8770_dapm_widgets));
@@ -679,6 +677,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
 	.suspend = wm8770_suspend,
 	.resume = wm8770_resume,
 	.set_bias_level = wm8770_set_bias_level,
+	.idle_bias_off = true,
 	.reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
 	.reg_word_size = sizeof (u16),
 	.reg_cache_default = wm8770_reg_defs
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index 33e97d1d8f4675a46aabdc452ee05122a19550f8..a19db5a0a17ab05fc7503d7b8722ec2a6c0cf13c 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -30,6 +30,11 @@
 
 #include "wm8776.h"
 
+enum wm8776_chip_type {
+	WM8775 = 1,
+	WM8776,
+};
+
 /* codec private data */
 struct wm8776_priv {
 	enum snd_soc_control_type control_type;
@@ -512,7 +517,8 @@ static __devexit int wm8776_i2c_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id wm8776_i2c_id[] = {
-	{ "wm8776", 0 },
+	{ "wm8775", WM8775 },
+	{ "wm8776", WM8776 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index d54a3ca5e19ee3c72550f464e0032d1caeca0bc3..6bd1b767b138881eecb66451d9b468309b650d29 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -18,6 +18,7 @@
 #include <linux/i2c.h>
 #include <linux/of_device.h>
 #include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -35,45 +36,33 @@ static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
 	"DVDD"
 };
 
-static const u8 wm8804_reg_defs[] = {
-	0x05,     /* R0  - RST/DEVID1 */
-	0x88,     /* R1  - DEVID2 */
-	0x04,     /* R2  - DEVREV */
-	0x21,     /* R3  - PLL1 */
-	0xFD,     /* R4  - PLL2 */
-	0x36,     /* R5  - PLL3 */
-	0x07,     /* R6  - PLL4 */
-	0x16,     /* R7  - PLL5 */
-	0x18,     /* R8  - PLL6 */
-	0xFF,     /* R9  - SPDMODE */
-	0x00,     /* R10 - INTMASK */
-	0x00,     /* R11 - INTSTAT */
-	0x00,     /* R12 - SPDSTAT */
-	0x00,     /* R13 - RXCHAN1 */
-	0x00,     /* R14 - RXCHAN2 */
-	0x00,     /* R15 - RXCHAN3 */
-	0x00,     /* R16 - RXCHAN4 */
-	0x00,     /* R17 - RXCHAN5 */
-	0x00,     /* R18 - SPDTX1 */
-	0x00,     /* R19 - SPDTX2 */
-	0x00,     /* R20 - SPDTX3 */
-	0x71,     /* R21 - SPDTX4 */
-	0x0B,     /* R22 - SPDTX5 */
-	0x70,     /* R23 - GPO0 */
-	0x57,     /* R24 - GPO1 */
-	0x00,     /* R25 */
-	0x42,     /* R26 - GPO2 */
-	0x06,     /* R27 - AIFTX */
-	0x06,     /* R28 - AIFRX */
-	0x80,     /* R29 - SPDRX1 */
-	0x07,     /* R30 - PWRDN */
+static const struct reg_default wm8804_reg_defaults[] = {
+	{ 3,  0x21 },     /* R3  - PLL1 */
+	{ 4,  0xFD },     /* R4  - PLL2 */
+	{ 5,  0x36 },     /* R5  - PLL3 */
+	{ 6,  0x07 },     /* R6  - PLL4 */
+	{ 7,  0x16 },     /* R7  - PLL5 */
+	{ 8,  0x18 },     /* R8  - PLL6 */
+	{ 9,  0xFF },     /* R9  - SPDMODE */
+	{ 10, 0x00 },     /* R10 - INTMASK */
+	{ 18, 0x00 },     /* R18 - SPDTX1 */
+	{ 19, 0x00 },     /* R19 - SPDTX2 */
+	{ 20, 0x00 },     /* R20 - SPDTX3 */
+	{ 21, 0x71 },     /* R21 - SPDTX4 */
+	{ 22, 0x0B },     /* R22 - SPDTX5 */
+	{ 23, 0x70 },     /* R23 - GPO0 */
+	{ 24, 0x57 },     /* R24 - GPO1 */
+	{ 26, 0x42 },     /* R26 - GPO2 */
+	{ 27, 0x06 },     /* R27 - AIFTX */
+	{ 28, 0x06 },     /* R28 - AIFRX */
+	{ 29, 0x80 },     /* R29 - SPDRX1 */
+	{ 30, 0x07 },     /* R30 - PWRDN */
 };
 
 struct wm8804_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 	struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
 	struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
-	struct snd_soc_codec *codec;
 };
 
 static int txsrc_get(struct snd_kcontrol *kcontrol,
@@ -94,7 +83,7 @@ static int wm8804_regulator_event_##n(struct notifier_block *nb, \
 	struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
 						  disable_nb[n]); \
 	if (event & REGULATOR_EVENT_DISABLE) { \
-		wm8804->codec->cache_sync = 1; \
+		regcache_mark_dirty(wm8804->regmap);	\
 	} \
 	return 0; \
 }
@@ -176,7 +165,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8804_volatile(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case WM8804_RST_DEVID1:
@@ -189,12 +178,10 @@ static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
 	case WM8804_RXCHAN3:
 	case WM8804_RXCHAN4:
 	case WM8804_RXCHAN5:
-		return 1;
+		return true;
 	default:
-		break;
+		return false;
 	}
-
-	return 0;
 }
 
 static int wm8804_reset(struct snd_soc_codec *codec)
@@ -482,24 +469,6 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
 	return 0;
 }
 
-static void wm8804_sync_cache(struct snd_soc_codec *codec)
-{
-	short i;
-	u8 *cache;
-
-	if (!codec->cache_sync)
-		return;
-
-	codec->cache_only = 0;
-	cache = codec->reg_cache;
-	for (i = 0; i < codec->driver->reg_cache_size; i++) {
-		if (i == WM8804_RST_DEVID1 || cache[i] == wm8804_reg_defs[i])
-			continue;
-		snd_soc_write(codec, i, cache[i]);
-	}
-	codec->cache_sync = 0;
-}
-
 static int wm8804_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
@@ -524,7 +493,7 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
 					ret);
 				return ret;
 			}
-			wm8804_sync_cache(codec);
+			regcache_sync(wm8804->regmap);
 		}
 		/* power down the OSC and the PLL */
 		snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
@@ -579,11 +548,10 @@ static int wm8804_probe(struct snd_soc_codec *codec)
 	int i, id1, id2, ret;
 
 	wm8804 = snd_soc_codec_get_drvdata(codec);
-	wm8804->codec = codec;
 
-	codec->dapm.idle_bias_off = 1;
+	codec->control_data = wm8804->regmap;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 8, wm8804->control_type);
+	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;
@@ -636,8 +604,7 @@ static int wm8804_probe(struct snd_soc_codec *codec)
 
 	id2 = (id2 << 8) | id1;
 
-	if (id2 != ((wm8804_reg_defs[WM8804_DEVID2] << 8)
-			| wm8804_reg_defs[WM8804_RST_DEVID1])) {
+	if (id2 != 0x8805) {
 		dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
 		ret = -EINVAL;
 		goto err_reg_enable;
@@ -710,10 +677,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
 	.suspend = wm8804_suspend,
 	.resume = wm8804_resume,
 	.set_bias_level = wm8804_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8804_reg_defs),
-	.reg_word_size = sizeof(u8),
-	.reg_cache_default = wm8804_reg_defs,
-	.volatile_register = wm8804_volatile,
+	.idle_bias_off = true,
 
 	.controls = wm8804_snd_controls,
 	.num_controls = ARRAY_SIZE(wm8804_snd_controls),
@@ -725,30 +689,47 @@ static const struct of_device_id wm8804_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8804_of_match);
 
+static struct regmap_config wm8804_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = WM8804_MAX_REGISTER,
+	.volatile_reg = wm8804_volatile,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8804_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults),
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8804_spi_probe(struct spi_device *spi)
 {
 	struct wm8804_priv *wm8804;
 	int ret;
 
-	wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+	wm8804 = devm_kzalloc(&spi->dev, sizeof *wm8804, GFP_KERNEL);
 	if (!wm8804)
 		return -ENOMEM;
 
-	wm8804->control_type = SND_SOC_SPI;
+	wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config);
+	if (IS_ERR(wm8804->regmap)) {
+		ret = PTR_ERR(wm8804->regmap);
+		return ret;
+	}
+
 	spi_set_drvdata(spi, wm8804);
 
 	ret = snd_soc_register_codec(&spi->dev,
 				     &soc_codec_dev_wm8804, &wm8804_dai, 1);
-	if (ret < 0)
-		kfree(wm8804);
+
 	return ret;
 }
 
 static int __devexit wm8804_spi_remove(struct spi_device *spi)
 {
+	struct wm8804_priv *wm8804 = spi_get_drvdata(spi);
 	snd_soc_unregister_codec(&spi->dev);
-	kfree(spi_get_drvdata(spi));
+	regmap_exit(wm8804->regmap);
 	return 0;
 }
 
@@ -770,24 +751,37 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
 	struct wm8804_priv *wm8804;
 	int ret;
 
-	wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+	wm8804 = devm_kzalloc(&i2c->dev, sizeof *wm8804, GFP_KERNEL);
 	if (!wm8804)
 		return -ENOMEM;
 
-	wm8804->control_type = SND_SOC_I2C;
+	wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config);
+	if (IS_ERR(wm8804->regmap)) {
+		ret = PTR_ERR(wm8804->regmap);
+		return ret;
+	}
+
 	i2c_set_clientdata(i2c, wm8804);
 
 	ret = snd_soc_register_codec(&i2c->dev,
 				     &soc_codec_dev_wm8804, &wm8804_dai, 1);
-	if (ret < 0)
-		kfree(wm8804);
+	if (ret != 0)
+		goto err;
+
+	return 0;
+
+err:
+	regmap_exit(wm8804->regmap);
 	return ret;
 }
 
-static __devexit int wm8804_i2c_remove(struct i2c_client *client)
+static __devexit int wm8804_i2c_remove(struct i2c_client *i2c)
 {
-	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c);
+
+	snd_soc_unregister_codec(&i2c->dev);
+	regmap_exit(wm8804->regmap);
+
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index f31c754c8865abd5b21ee61c3e47b810f73721a6..65d525d74c549ee9d83bbb1f1ca0a982a103a567 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -47,6 +48,7 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8904_priv {
+	struct regmap *regmap;
 
 	enum wm8904_type devtype;
 
@@ -86,517 +88,230 @@ struct wm8904_priv {
 	int dcs_state[WM8904_NUM_DCS_CHANNELS];
 };
 
-static const u16 wm8904_reg[WM8904_MAX_REGISTER + 1] = {
-	0x8904,     /* R0   - SW Reset and ID */
-	0x0000,     /* R1   - Revision */
-	0x0000,     /* R2 */
-	0x0000,     /* R3 */
-	0x0018,     /* R4   - Bias Control 0 */
-	0x0000,     /* R5   - VMID Control 0 */
-	0x0000,     /* R6   - Mic Bias Control 0 */
-	0x0000,     /* R7   - Mic Bias Control 1 */
-	0x0001,     /* R8   - Analogue DAC 0 */
-	0x9696,     /* R9   - mic Filter Control */
-	0x0001,     /* R10  - Analogue ADC 0 */
-	0x0000,     /* R11 */
-	0x0000,     /* R12  - Power Management 0 */
-	0x0000,     /* R13 */
-	0x0000,     /* R14  - Power Management 2 */
-	0x0000,     /* R15  - Power Management 3 */
-	0x0000,     /* R16 */
-	0x0000,     /* R17 */
-	0x0000,     /* R18  - Power Management 6 */
-	0x0000,     /* R19 */
-	0x945E,     /* R20  - Clock Rates 0 */
-	0x0C05,     /* R21  - Clock Rates 1 */
-	0x0006,     /* R22  - Clock Rates 2 */
-	0x0000,     /* R23 */
-	0x0050,     /* R24  - Audio Interface 0 */
-	0x000A,     /* R25  - Audio Interface 1 */
-	0x00E4,     /* R26  - Audio Interface 2 */
-	0x0040,     /* 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 */
-	0x0008,     /* R33  - DAC Digital 1 */
-	0x0000,     /* R34 */
-	0x0000,     /* R35 */
-	0x00C0,     /* R36  - ADC Digital Volume Left */
-	0x00C0,     /* R37  - ADC Digital Volume Right */
-	0x0010,     /* R38  - ADC Digital 0 */
-	0x0000,     /* R39  - Digital Microphone 0 */
-	0x01AF,     /* R40  - DRC 0 */
-	0x3248,     /* R41  - DRC 1 */
-	0x0000,     /* 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 */
-	0x0000,     /* R50 */
-	0x0000,     /* R51 */
-	0x0000,     /* R52 */
-	0x0000,     /* R53 */
-	0x0000,     /* R54 */
-	0x0000,     /* R55 */
-	0x0000,     /* R56 */
-	0x002D,     /* R57  - Analogue OUT1 Left */
-	0x002D,     /* R58  - Analogue OUT1 Right */
-	0x0039,     /* R59  - Analogue OUT2 Left */
-	0x0039,     /* R60  - Analogue OUT2 Right */
-	0x0000,     /* R61  - Analogue OUT12 ZC */
-	0x0000,     /* R62 */
-	0x0000,     /* R63 */
-	0x0000,     /* R64 */
-	0x0000,     /* R65 */
-	0x0000,     /* R66 */
-	0x0000,     /* R67  - DC Servo 0 */
-	0x0000,     /* R68  - DC Servo 1 */
-	0xAAAA,     /* R69  - DC Servo 2 */
-	0x0000,     /* R70 */
-	0xAAAA,     /* R71  - DC Servo 4 */
-	0xAAAA,     /* R72  - DC Servo 5 */
-	0x0000,     /* R73  - DC Servo 6 */
-	0x0000,     /* R74  - DC Servo 7 */
-	0x0000,     /* R75  - DC Servo 8 */
-	0x0000,     /* R76  - DC Servo 9 */
-	0x0000,     /* R77  - DC Servo Readback 0 */
-	0x0000,     /* R78 */
-	0x0000,     /* R79 */
-	0x0000,     /* R80 */
-	0x0000,     /* R81 */
-	0x0000,     /* R82 */
-	0x0000,     /* R83 */
-	0x0000,     /* R84 */
-	0x0000,     /* R85 */
-	0x0000,     /* R86 */
-	0x0000,     /* R87 */
-	0x0000,     /* R88 */
-	0x0000,     /* R89 */
-	0x0000,     /* R90  - Analogue HP 0 */
-	0x0000,     /* R91 */
-	0x0000,     /* R92 */
-	0x0000,     /* R93 */
-	0x0000,     /* R94  - Analogue Lineout 0 */
-	0x0000,     /* R95 */
-	0x0000,     /* R96 */
-	0x0000,     /* R97 */
-	0x0000,     /* R98  - Charge Pump 0 */
-	0x0000,     /* R99 */
-	0x0000,     /* R100 */
-	0x0000,     /* R101 */
-	0x0000,     /* R102 */
-	0x0000,     /* R103 */
-	0x0004,     /* R104 - Class W 0 */
-	0x0000,     /* R105 */
-	0x0000,     /* 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 */
-	0x0000,     /* R115 */
-	0x0000,     /* R116 - FLL Control 1 */
-	0x0007,     /* R117 - FLL Control 2 */
-	0x0000,     /* R118 - FLL Control 3 */
-	0x2EE0,     /* R119 - FLL Control 4 */
-	0x0004,     /* R120 - FLL Control 5 */
-	0x0014,     /* R121 - GPIO Control 1 */
-	0x0010,     /* R122 - GPIO Control 2 */
-	0x0010,     /* R123 - GPIO Control 3 */
-	0x0000,     /* R124 - GPIO Control 4 */
-	0x0000,     /* R125 */
-	0x0000,     /* R126 - Digital Pulls */
-	0x0000,     /* R127 - Interrupt Status */
-	0xFFFF,     /* R128 - Interrupt Status Mask */
-	0x0000,     /* R129 - Interrupt Polarity */
-	0x0000,     /* R130 - Interrupt Debounce */
-	0x0000,     /* R131 */
-	0x0000,     /* R132 */
-	0x0000,     /* R133 */
-	0x0000,     /* R134 - EQ1 */
-	0x000C,     /* R135 - EQ2 */
-	0x000C,     /* R136 - EQ3 */
-	0x000C,     /* R137 - EQ4 */
-	0x000C,     /* R138 - EQ5 */
-	0x000C,     /* R139 - EQ6 */
-	0x0FCA,     /* R140 - EQ7 */
-	0x0400,     /* R141 - EQ8 */
-	0x00D8,     /* R142 - EQ9 */
-	0x1EB5,     /* R143 - EQ10 */
-	0xF145,     /* R144 - EQ11 */
-	0x0B75,     /* R145 - EQ12 */
-	0x01C5,     /* R146 - EQ13 */
-	0x1C58,     /* R147 - EQ14 */
-	0xF373,     /* R148 - EQ15 */
-	0x0A54,     /* R149 - EQ16 */
-	0x0558,     /* R150 - EQ17 */
-	0x168E,     /* R151 - EQ18 */
-	0xF829,     /* R152 - EQ19 */
-	0x07AD,     /* R153 - EQ20 */
-	0x1103,     /* R154 - EQ21 */
-	0x0564,     /* R155 - EQ22 */
-	0x0559,     /* R156 - EQ23 */
-	0x4000,     /* R157 - EQ24 */
-	0x0000,     /* R158 */
-	0x0000,     /* R159 */
-	0x0000,     /* R160 */
-	0x0000,     /* R161 - Control Interface Test 1 */
-	0x0000,     /* R162 */
-	0x0000,     /* R163 */
-	0x0000,     /* R164 */
-	0x0000,     /* R165 */
-	0x0000,     /* R166 */
-	0x0000,     /* R167 */
-	0x0000,     /* R168 */
-	0x0000,     /* R169 */
-	0x0000,     /* R170 */
-	0x0000,     /* R171 */
-	0x0000,     /* R172 */
-	0x0000,     /* R173 */
-	0x0000,     /* R174 */
-	0x0000,     /* R175 */
-	0x0000,     /* R176 */
-	0x0000,     /* R177 */
-	0x0000,     /* R178 */
-	0x0000,     /* R179 */
-	0x0000,     /* R180 */
-	0x0000,     /* R181 */
-	0x0000,     /* R182 */
-	0x0000,     /* R183 */
-	0x0000,     /* R184 */
-	0x0000,     /* R185 */
-	0x0000,     /* R186 */
-	0x0000,     /* R187 */
-	0x0000,     /* R188 */
-	0x0000,     /* R189 */
-	0x0000,     /* R190 */
-	0x0000,     /* R191 */
-	0x0000,     /* R192 */
-	0x0000,     /* R193 */
-	0x0000,     /* R194 */
-	0x0000,     /* R195 */
-	0x0000,     /* R196 */
-	0x0000,     /* R197 */
-	0x0000,     /* R198 */
-	0x0000,     /* R199 */
-	0x0000,     /* R200 */
-	0x0000,     /* R201 */
-	0x0000,     /* R202 */
-	0x0000,     /* R203 */
-	0x0000,     /* R204 - Analogue Output Bias 0 */
-	0x0000,     /* R205 */
-	0x0000,     /* R206 */
-	0x0000,     /* R207 */
-	0x0000,     /* R208 */
-	0x0000,     /* R209 */
-	0x0000,     /* R210 */
-	0x0000,     /* R211 */
-	0x0000,     /* R212 */
-	0x0000,     /* R213 */
-	0x0000,     /* R214 */
-	0x0000,     /* R215 */
-	0x0000,     /* R216 */
-	0x0000,     /* R217 */
-	0x0000,     /* R218 */
-	0x0000,     /* R219 */
-	0x0000,     /* R220 */
-	0x0000,     /* R221 */
-	0x0000,     /* R222 */
-	0x0000,     /* R223 */
-	0x0000,     /* R224 */
-	0x0000,     /* R225 */
-	0x0000,     /* R226 */
-	0x0000,     /* R227 */
-	0x0000,     /* R228 */
-	0x0000,     /* R229 */
-	0x0000,     /* R230 */
-	0x0000,     /* R231 */
-	0x0000,     /* R232 */
-	0x0000,     /* R233 */
-	0x0000,     /* R234 */
-	0x0000,     /* R235 */
-	0x0000,     /* R236 */
-	0x0000,     /* R237 */
-	0x0000,     /* R238 */
-	0x0000,     /* R239 */
-	0x0000,     /* R240 */
-	0x0000,     /* R241 */
-	0x0000,     /* R242 */
-	0x0000,     /* R243 */
-	0x0000,     /* R244 */
-	0x0000,     /* R245 */
-	0x0000,     /* R246 */
-	0x0000,     /* R247 - FLL NCO Test 0 */
-	0x0019,     /* R248 - FLL NCO Test 1 */
+static const struct reg_default wm8904_reg_defaults[] = {
+	{ 4,   0x0018 },     /* R4   - Bias Control 0 */
+	{ 5,   0x0000 },     /* R5   - VMID Control 0 */
+	{ 6,   0x0000 },     /* R6   - Mic Bias Control 0 */
+	{ 7,   0x0000 },     /* R7   - Mic Bias Control 1 */
+	{ 8,   0x0001 },     /* R8   - Analogue DAC 0 */
+	{ 9,   0x9696 },     /* R9   - mic Filter Control */
+	{ 10,  0x0001 },     /* R10  - Analogue ADC 0 */
+	{ 12,  0x0000 },     /* R12  - Power Management 0 */
+	{ 14,  0x0000 },     /* R14  - Power Management 2 */
+	{ 15,  0x0000 },     /* R15  - Power Management 3 */
+	{ 18,  0x0000 },     /* R18  - Power Management 6 */
+	{ 19,  0x945E },     /* R20  - Clock Rates 0 */
+	{ 21,  0x0C05 },     /* R21  - Clock Rates 1 */
+	{ 22,  0x0006 },     /* R22  - Clock Rates 2 */
+	{ 24,  0x0050 },     /* R24  - Audio Interface 0 */
+	{ 25,  0x000A },     /* R25  - Audio Interface 1 */
+	{ 26,  0x00E4 },     /* R26  - Audio Interface 2 */
+	{ 27,  0x0040 },     /* 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,  0x0008 },     /* R33  - DAC Digital 1 */
+	{ 36,  0x00C0 },     /* R36  - ADC Digital Volume Left */
+	{ 37,  0x00C0 },     /* R37  - ADC Digital Volume Right */
+	{ 38,  0x0010 },     /* R38  - ADC Digital 0 */
+	{ 39,  0x0000 },     /* R39  - Digital Microphone 0 */
+	{ 40,  0x01AF },     /* R40  - DRC 0 */
+	{ 41,  0x3248 },     /* R41  - DRC 1 */
+	{ 42,  0x0000 },     /* 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 */
+	{ 57,  0x002D },     /* R57  - Analogue OUT1 Left */
+	{ 58,  0x002D },     /* R58  - Analogue OUT1 Right */
+	{ 59,  0x0039 },     /* R59  - Analogue OUT2 Left */
+	{ 60,  0x0039 },     /* R60  - Analogue OUT2 Right */
+	{ 61,  0x0000 },     /* R61  - Analogue OUT12 ZC */
+	{ 67,  0x0000 },     /* R67  - DC Servo 0 */
+	{ 69,  0xAAAA },     /* R69  - DC Servo 2 */
+	{ 71,  0xAAAA },     /* R71  - DC Servo 4 */
+	{ 72,  0xAAAA },     /* R72  - DC Servo 5 */
+	{ 90,  0x0000 },     /* R90  - Analogue HP 0 */
+	{ 94,  0x0000 },     /* R94  - Analogue Lineout 0 */
+	{ 98,  0x0000 },     /* R98  - Charge Pump 0 */
+	{ 104, 0x0004 },     /* 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 */
+	{ 116, 0x0000 },     /* R116 - FLL Control 1 */
+	{ 117, 0x0007 },     /* R117 - FLL Control 2 */
+	{ 118, 0x0000 },     /* R118 - FLL Control 3 */
+	{ 119, 0x2EE0 },     /* R119 - FLL Control 4 */
+	{ 120, 0x0004 },     /* R120 - FLL Control 5 */
+	{ 121, 0x0014 },     /* R121 - GPIO Control 1 */
+	{ 122, 0x0010 },     /* R122 - GPIO Control 2 */
+	{ 123, 0x0010 },     /* R123 - GPIO Control 3 */
+	{ 124, 0x0000 },     /* R124 - GPIO Control 4 */
+	{ 126, 0x0000 },     /* R126 - Digital Pulls */
+	{ 128, 0xFFFF },     /* R128 - Interrupt Status Mask */
+	{ 129, 0x0000 },     /* R129 - Interrupt Polarity */
+	{ 130, 0x0000 },     /* R130 - Interrupt Debounce */
+	{ 134, 0x0000 },     /* R134 - EQ1 */
+	{ 135, 0x000C },     /* R135 - EQ2 */
+	{ 136, 0x000C },     /* R136 - EQ3 */
+	{ 137, 0x000C },     /* R137 - EQ4 */
+	{ 138, 0x000C },     /* R138 - EQ5 */
+	{ 139, 0x000C },     /* R139 - EQ6 */
+	{ 140, 0x0FCA },     /* R140 - EQ7 */
+	{ 141, 0x0400 },     /* R141 - EQ8 */
+	{ 142, 0x00D8 },     /* R142 - EQ9 */
+	{ 143, 0x1EB5 },     /* R143 - EQ10 */
+	{ 144, 0xF145 },     /* R144 - EQ11 */
+	{ 145, 0x0B75 },     /* R145 - EQ12 */
+	{ 146, 0x01C5 },     /* R146 - EQ13 */
+	{ 147, 0x1C58 },     /* R147 - EQ14 */
+	{ 148, 0xF373 },     /* R148 - EQ15 */
+	{ 149, 0x0A54 },     /* R149 - EQ16 */
+	{ 150, 0x0558 },     /* R150 - EQ17 */
+	{ 151, 0x168E },     /* R151 - EQ18 */
+	{ 152, 0xF829 },     /* R152 - EQ19 */
+	{ 153, 0x07AD },     /* R153 - EQ20 */
+	{ 154, 0x1103 },     /* R154 - EQ21 */
+	{ 155, 0x0564 },     /* R155 - EQ22 */
+	{ 156, 0x0559 },     /* R156 - EQ23 */
+	{ 157, 0x4000 },     /* R157 - EQ24 */
+	{ 161, 0x0000 },     /* R161 - Control Interface Test 1 */
+	{ 204, 0x0000 },     /* R204 - Analogue Output Bias 0 */
+	{ 247, 0x0000 },     /* R247 - FLL NCO Test 0 */
+	{ 248, 0x0019 },     /* R248 - FLL NCO Test 1 */
 };
 
-static struct {
-	int readable;
-	int writable;
-	int vol;
-} wm8904_access[] = {
-	{ 0xFFFF, 0xFFFF, 1 }, /* R0   - SW Reset and ID */
-	{ 0x0000, 0x0000, 0 }, /* R1   - Revision */
-	{ 0x0000, 0x0000, 0 }, /* R2 */
-	{ 0x0000, 0x0000, 0 }, /* R3 */
-	{ 0x001F, 0x001F, 0 }, /* R4   - Bias Control 0 */
-	{ 0x0047, 0x0047, 0 }, /* R5   - VMID Control 0 */
-	{ 0x007F, 0x007F, 0 }, /* R6   - Mic Bias Control 0 */
-	{ 0xC007, 0xC007, 0 }, /* R7   - Mic Bias Control 1 */
-	{ 0x001E, 0x001E, 0 }, /* R8   - Analogue DAC 0 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R9   - mic Filter Control */
-	{ 0x0001, 0x0001, 0 }, /* R10  - Analogue ADC 0 */
-	{ 0x0000, 0x0000, 0 }, /* R11 */
-	{ 0x0003, 0x0003, 0 }, /* R12  - Power Management 0 */
-	{ 0x0000, 0x0000, 0 }, /* R13 */
-	{ 0x0003, 0x0003, 0 }, /* R14  - Power Management 2 */
-	{ 0x0003, 0x0003, 0 }, /* R15  - Power Management 3 */
-	{ 0x0000, 0x0000, 0 }, /* R16 */
-	{ 0x0000, 0x0000, 0 }, /* R17 */
-	{ 0x000F, 0x000F, 0 }, /* R18  - Power Management 6 */
-	{ 0x0000, 0x0000, 0 }, /* R19 */
-	{ 0x7001, 0x7001, 0 }, /* R20  - Clock Rates 0 */
-	{ 0x3C07, 0x3C07, 0 }, /* R21  - Clock Rates 1 */
-	{ 0xD00F, 0xD00F, 0 }, /* R22  - Clock Rates 2 */
-	{ 0x0000, 0x0000, 0 }, /* R23 */
-	{ 0x1FFF, 0x1FFF, 0 }, /* R24  - Audio Interface 0 */
-	{ 0x3DDF, 0x3DDF, 0 }, /* R25  - Audio Interface 1 */
-	{ 0x0F1F, 0x0F1F, 0 }, /* R26  - Audio Interface 2 */
-	{ 0x0FFF, 0x0FFF, 0 }, /* R27  - Audio Interface 3 */
-	{ 0x0000, 0x0000, 0 }, /* R28 */
-	{ 0x0000, 0x0000, 0 }, /* R29 */
-	{ 0x00FF, 0x01FF, 0 }, /* R30  - DAC Digital Volume Left */
-	{ 0x00FF, 0x01FF, 0 }, /* R31  - DAC Digital Volume Right */
-	{ 0x0FFF, 0x0FFF, 0 }, /* R32  - DAC Digital 0 */
-	{ 0x1E4E, 0x1E4E, 0 }, /* R33  - DAC Digital 1 */
-	{ 0x0000, 0x0000, 0 }, /* R34 */
-	{ 0x0000, 0x0000, 0 }, /* R35 */
-	{ 0x00FF, 0x01FF, 0 }, /* R36  - ADC Digital Volume Left */
-	{ 0x00FF, 0x01FF, 0 }, /* R37  - ADC Digital Volume Right */
-	{ 0x0073, 0x0073, 0 }, /* R38  - ADC Digital 0 */
-	{ 0x1800, 0x1800, 0 }, /* R39  - Digital Microphone 0 */
-	{ 0xDFEF, 0xDFEF, 0 }, /* R40  - DRC 0 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R41  - DRC 1 */
-	{ 0x003F, 0x003F, 0 }, /* R42  - DRC 2 */
-	{ 0x07FF, 0x07FF, 0 }, /* R43  - DRC 3 */
-	{ 0x009F, 0x009F, 0 }, /* R44  - Analogue Left Input 0 */
-	{ 0x009F, 0x009F, 0 }, /* R45  - Analogue Right Input 0 */
-	{ 0x007F, 0x007F, 0 }, /* R46  - Analogue Left Input 1 */
-	{ 0x007F, 0x007F, 0 }, /* R47  - Analogue Right Input 1 */
-	{ 0x0000, 0x0000, 0 }, /* R48 */
-	{ 0x0000, 0x0000, 0 }, /* R49 */
-	{ 0x0000, 0x0000, 0 }, /* R50 */
-	{ 0x0000, 0x0000, 0 }, /* R51 */
-	{ 0x0000, 0x0000, 0 }, /* R52 */
-	{ 0x0000, 0x0000, 0 }, /* R53 */
-	{ 0x0000, 0x0000, 0 }, /* R54 */
-	{ 0x0000, 0x0000, 0 }, /* R55 */
-	{ 0x0000, 0x0000, 0 }, /* R56 */
-	{ 0x017F, 0x01FF, 0 }, /* R57  - Analogue OUT1 Left */
-	{ 0x017F, 0x01FF, 0 }, /* R58  - Analogue OUT1 Right */
-	{ 0x017F, 0x01FF, 0 }, /* R59  - Analogue OUT2 Left */
-	{ 0x017F, 0x01FF, 0 }, /* R60  - Analogue OUT2 Right */
-	{ 0x000F, 0x000F, 0 }, /* R61  - Analogue OUT12 ZC */
-	{ 0x0000, 0x0000, 0 }, /* R62 */
-	{ 0x0000, 0x0000, 0 }, /* R63 */
-	{ 0x0000, 0x0000, 0 }, /* R64 */
-	{ 0x0000, 0x0000, 0 }, /* R65 */
-	{ 0x0000, 0x0000, 0 }, /* R66 */
-	{ 0x000F, 0x000F, 0 }, /* R67  - DC Servo 0 */
-	{ 0xFFFF, 0xFFFF, 1 }, /* R68  - DC Servo 1 */
-	{ 0x0F0F, 0x0F0F, 0 }, /* R69  - DC Servo 2 */
-	{ 0x0000, 0x0000, 0 }, /* R70 */
-	{ 0x007F, 0x007F, 0 }, /* R71  - DC Servo 4 */
-	{ 0x007F, 0x007F, 0 }, /* R72  - DC Servo 5 */
-	{ 0x00FF, 0x00FF, 1 }, /* R73  - DC Servo 6 */
-	{ 0x00FF, 0x00FF, 1 }, /* R74  - DC Servo 7 */
-	{ 0x00FF, 0x00FF, 1 }, /* R75  - DC Servo 8 */
-	{ 0x00FF, 0x00FF, 1 }, /* R76  - DC Servo 9 */
-	{ 0x0FFF, 0x0000, 1 }, /* R77  - DC Servo Readback 0 */
-	{ 0x0000, 0x0000, 0 }, /* R78 */
-	{ 0x0000, 0x0000, 0 }, /* R79 */
-	{ 0x0000, 0x0000, 0 }, /* R80 */
-	{ 0x0000, 0x0000, 0 }, /* R81 */
-	{ 0x0000, 0x0000, 0 }, /* R82 */
-	{ 0x0000, 0x0000, 0 }, /* R83 */
-	{ 0x0000, 0x0000, 0 }, /* R84 */
-	{ 0x0000, 0x0000, 0 }, /* R85 */
-	{ 0x0000, 0x0000, 0 }, /* R86 */
-	{ 0x0000, 0x0000, 0 }, /* R87 */
-	{ 0x0000, 0x0000, 0 }, /* R88 */
-	{ 0x0000, 0x0000, 0 }, /* R89 */
-	{ 0x00FF, 0x00FF, 0 }, /* R90  - Analogue HP 0 */
-	{ 0x0000, 0x0000, 0 }, /* R91 */
-	{ 0x0000, 0x0000, 0 }, /* R92 */
-	{ 0x0000, 0x0000, 0 }, /* R93 */
-	{ 0x00FF, 0x00FF, 0 }, /* R94  - Analogue Lineout 0 */
-	{ 0x0000, 0x0000, 0 }, /* R95 */
-	{ 0x0000, 0x0000, 0 }, /* R96 */
-	{ 0x0000, 0x0000, 0 }, /* R97 */
-	{ 0x0001, 0x0001, 0 }, /* R98  - Charge Pump 0 */
-	{ 0x0000, 0x0000, 0 }, /* R99 */
-	{ 0x0000, 0x0000, 0 }, /* R100 */
-	{ 0x0000, 0x0000, 0 }, /* R101 */
-	{ 0x0000, 0x0000, 0 }, /* R102 */
-	{ 0x0000, 0x0000, 0 }, /* R103 */
-	{ 0x0001, 0x0001, 0 }, /* R104 - Class W 0 */
-	{ 0x0000, 0x0000, 0 }, /* R105 */
-	{ 0x0000, 0x0000, 0 }, /* R106 */
-	{ 0x0000, 0x0000, 0 }, /* R107 */
-	{ 0x011F, 0x011F, 0 }, /* R108 - Write Sequencer 0 */
-	{ 0x7FFF, 0x7FFF, 0 }, /* R109 - Write Sequencer 1 */
-	{ 0x4FFF, 0x4FFF, 0 }, /* R110 - Write Sequencer 2 */
-	{ 0x003F, 0x033F, 0 }, /* R111 - Write Sequencer 3 */
-	{ 0x03F1, 0x0000, 0 }, /* R112 - Write Sequencer 4 */
-	{ 0x0000, 0x0000, 0 }, /* R113 */
-	{ 0x0000, 0x0000, 0 }, /* R114 */
-	{ 0x0000, 0x0000, 0 }, /* R115 */
-	{ 0x0007, 0x0007, 0 }, /* R116 - FLL Control 1 */
-	{ 0x3F77, 0x3F77, 0 }, /* R117 - FLL Control 2 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R118 - FLL Control 3 */
-	{ 0x7FEF, 0x7FEF, 0 }, /* R119 - FLL Control 4 */
-	{ 0x001B, 0x001B, 0 }, /* R120 - FLL Control 5 */
-	{ 0x003F, 0x003F, 0 }, /* R121 - GPIO Control 1 */
-	{ 0x003F, 0x003F, 0 }, /* R122 - GPIO Control 2 */
-	{ 0x003F, 0x003F, 0 }, /* R123 - GPIO Control 3 */
-	{ 0x038F, 0x038F, 0 }, /* R124 - GPIO Control 4 */
-	{ 0x0000, 0x0000, 0 }, /* R125 */
-	{ 0x00FF, 0x00FF, 0 }, /* R126 - Digital Pulls */
-	{ 0x07FF, 0x03FF, 1 }, /* R127 - Interrupt Status */
-	{ 0x03FF, 0x03FF, 0 }, /* R128 - Interrupt Status Mask */
-	{ 0x03FF, 0x03FF, 0 }, /* R129 - Interrupt Polarity */
-	{ 0x03FF, 0x03FF, 0 }, /* R130 - Interrupt Debounce */
-	{ 0x0000, 0x0000, 0 }, /* R131 */
-	{ 0x0000, 0x0000, 0 }, /* R132 */
-	{ 0x0000, 0x0000, 0 }, /* R133 */
-	{ 0x0001, 0x0001, 0 }, /* R134 - EQ1 */
-	{ 0x001F, 0x001F, 0 }, /* R135 - EQ2 */
-	{ 0x001F, 0x001F, 0 }, /* R136 - EQ3 */
-	{ 0x001F, 0x001F, 0 }, /* R137 - EQ4 */
-	{ 0x001F, 0x001F, 0 }, /* R138 - EQ5 */
-	{ 0x001F, 0x001F, 0 }, /* R139 - EQ6 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R140 - EQ7 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R141 - EQ8 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R142 - EQ9 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R143 - EQ10 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R144 - EQ11 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R145 - EQ12 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R146 - EQ13 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R147 - EQ14 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R148 - EQ15 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R149 - EQ16 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R150 - EQ17 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R151wm8523_dai - EQ18 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R152 - EQ19 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R153 - EQ20 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R154 - EQ21 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R155 - EQ22 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R156 - EQ23 */
-	{ 0xFFFF, 0xFFFF, 0 }, /* R157 - EQ24 */
-	{ 0x0000, 0x0000, 0 }, /* R158 */
-	{ 0x0000, 0x0000, 0 }, /* R159 */
-	{ 0x0000, 0x0000, 0 }, /* R160 */
-	{ 0x0002, 0x0002, 0 }, /* R161 - Control Interface Test 1 */
-	{ 0x0000, 0x0000, 0 }, /* R162 */
-	{ 0x0000, 0x0000, 0 }, /* R163 */
-	{ 0x0000, 0x0000, 0 }, /* R164 */
-	{ 0x0000, 0x0000, 0 }, /* R165 */
-	{ 0x0000, 0x0000, 0 }, /* R166 */
-	{ 0x0000, 0x0000, 0 }, /* R167 */
-	{ 0x0000, 0x0000, 0 }, /* R168 */
-	{ 0x0000, 0x0000, 0 }, /* R169 */
-	{ 0x0000, 0x0000, 0 }, /* R170 */
-	{ 0x0000, 0x0000, 0 }, /* R171 */
-	{ 0x0000, 0x0000, 0 }, /* R172 */
-	{ 0x0000, 0x0000, 0 }, /* R173 */
-	{ 0x0000, 0x0000, 0 }, /* R174 */
-	{ 0x0000, 0x0000, 0 }, /* R175 */
-	{ 0x0000, 0x0000, 0 }, /* R176 */
-	{ 0x0000, 0x0000, 0 }, /* R177 */
-	{ 0x0000, 0x0000, 0 }, /* R178 */
-	{ 0x0000, 0x0000, 0 }, /* R179 */
-	{ 0x0000, 0x0000, 0 }, /* R180 */
-	{ 0x0000, 0x0000, 0 }, /* R181 */
-	{ 0x0000, 0x0000, 0 }, /* R182 */
-	{ 0x0000, 0x0000, 0 }, /* R183 */
-	{ 0x0000, 0x0000, 0 }, /* R184 */
-	{ 0x0000, 0x0000, 0 }, /* R185 */
-	{ 0x0000, 0x0000, 0 }, /* R186 */
-	{ 0x0000, 0x0000, 0 }, /* R187 */
-	{ 0x0000, 0x0000, 0 }, /* R188 */
-	{ 0x0000, 0x0000, 0 }, /* R189 */
-	{ 0x0000, 0x0000, 0 }, /* R190 */
-	{ 0x0000, 0x0000, 0 }, /* R191 */
-	{ 0x0000, 0x0000, 0 }, /* R192 */
-	{ 0x0000, 0x0000, 0 }, /* R193 */
-	{ 0x0000, 0x0000, 0 }, /* R194 */
-	{ 0x0000, 0x0000, 0 }, /* R195 */
-	{ 0x0000, 0x0000, 0 }, /* R196 */
-	{ 0x0000, 0x0000, 0 }, /* R197 */
-	{ 0x0000, 0x0000, 0 }, /* R198 */
-	{ 0x0000, 0x0000, 0 }, /* R199 */
-	{ 0x0000, 0x0000, 0 }, /* R200 */
-	{ 0x0000, 0x0000, 0 }, /* R201 */
-	{ 0x0000, 0x0000, 0 }, /* R202 */
-	{ 0x0000, 0x0000, 0 }, /* R203 */
-	{ 0x0070, 0x0070, 0 }, /* R204 - Analogue Output Bias 0 */
-	{ 0x0000, 0x0000, 0 }, /* R205 */
-	{ 0x0000, 0x0000, 0 }, /* R206 */
-	{ 0x0000, 0x0000, 0 }, /* R207 */
-	{ 0x0000, 0x0000, 0 }, /* R208 */
-	{ 0x0000, 0x0000, 0 }, /* R209 */
-	{ 0x0000, 0x0000, 0 }, /* R210 */
-	{ 0x0000, 0x0000, 0 }, /* R211 */
-	{ 0x0000, 0x0000, 0 }, /* R212 */
-	{ 0x0000, 0x0000, 0 }, /* R213 */
-	{ 0x0000, 0x0000, 0 }, /* R214 */
-	{ 0x0000, 0x0000, 0 }, /* R215 */
-	{ 0x0000, 0x0000, 0 }, /* R216 */
-	{ 0x0000, 0x0000, 0 }, /* R217 */
-	{ 0x0000, 0x0000, 0 }, /* R218 */
-	{ 0x0000, 0x0000, 0 }, /* R219 */
-	{ 0x0000, 0x0000, 0 }, /* R220 */
-	{ 0x0000, 0x0000, 0 }, /* R221 */
-	{ 0x0000, 0x0000, 0 }, /* R222 */
-	{ 0x0000, 0x0000, 0 }, /* R223 */
-	{ 0x0000, 0x0000, 0 }, /* R224 */
-	{ 0x0000, 0x0000, 0 }, /* R225 */
-	{ 0x0000, 0x0000, 0 }, /* R226 */
-	{ 0x0000, 0x0000, 0 }, /* R227 */
-	{ 0x0000, 0x0000, 0 }, /* R228 */
-	{ 0x0000, 0x0000, 0 }, /* R229 */
-	{ 0x0000, 0x0000, 0 }, /* R230 */
-	{ 0x0000, 0x0000, 0 }, /* R231 */
-	{ 0x0000, 0x0000, 0 }, /* R232 */
-	{ 0x0000, 0x0000, 0 }, /* R233 */
-	{ 0x0000, 0x0000, 0 }, /* R234 */
-	{ 0x0000, 0x0000, 0 }, /* R235 */
-	{ 0x0000, 0x0000, 0 }, /* R236 */
-	{ 0x0000, 0x0000, 0 }, /* R237 */
-	{ 0x0000, 0x0000, 0 }, /* R238 */
-	{ 0x0000, 0x0000, 0 }, /* R239 */
-	{ 0x0000, 0x0000, 0 }, /* R240 */
-	{ 0x0000, 0x0000, 0 }, /* R241 */
-	{ 0x0000, 0x0000, 0 }, /* R242 */
-	{ 0x0000, 0x0000, 0 }, /* R243 */
-	{ 0x0000, 0x0000, 0 }, /* R244 */
-	{ 0x0000, 0x0000, 0 }, /* R245 */
-	{ 0x0000, 0x0000, 0 }, /* R246 */
-	{ 0x0001, 0x0001, 0 }, /* R247 - FLL NCO Test 0 */
-	{ 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */
-};
+static bool wm8904_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM8904_SW_RESET_AND_ID:
+	case WM8904_REVISION:
+	case WM8904_DC_SERVO_1:
+	case WM8904_DC_SERVO_6:
+	case WM8904_DC_SERVO_7:
+	case WM8904_DC_SERVO_8:
+	case WM8904_DC_SERVO_9:
+	case WM8904_DC_SERVO_READBACK_0:
+	case WM8904_INTERRUPT_STATUS:
+		return true;
+	default:
+		return false;
+	}
+}
 
-static int wm8904_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8904_readable_register(struct device *dev, unsigned int reg)
 {
-	return wm8904_access[reg].vol;
+	switch (reg) {
+	case WM8904_SW_RESET_AND_ID:
+	case WM8904_REVISION:
+	case WM8904_BIAS_CONTROL_0:
+	case WM8904_VMID_CONTROL_0:
+	case WM8904_MIC_BIAS_CONTROL_0:
+	case WM8904_MIC_BIAS_CONTROL_1:
+	case WM8904_ANALOGUE_DAC_0:
+	case WM8904_MIC_FILTER_CONTROL:
+	case WM8904_ANALOGUE_ADC_0:
+	case WM8904_POWER_MANAGEMENT_0:
+	case WM8904_POWER_MANAGEMENT_2:
+	case WM8904_POWER_MANAGEMENT_3:
+	case WM8904_POWER_MANAGEMENT_6:
+	case WM8904_CLOCK_RATES_0:
+	case WM8904_CLOCK_RATES_1:
+	case WM8904_CLOCK_RATES_2:
+	case WM8904_AUDIO_INTERFACE_0:
+	case WM8904_AUDIO_INTERFACE_1:
+	case WM8904_AUDIO_INTERFACE_2:
+	case WM8904_AUDIO_INTERFACE_3:
+	case WM8904_DAC_DIGITAL_VOLUME_LEFT:
+	case WM8904_DAC_DIGITAL_VOLUME_RIGHT:
+	case WM8904_DAC_DIGITAL_0:
+	case WM8904_DAC_DIGITAL_1:
+	case WM8904_ADC_DIGITAL_VOLUME_LEFT:
+	case WM8904_ADC_DIGITAL_VOLUME_RIGHT:
+	case WM8904_ADC_DIGITAL_0:
+	case WM8904_DIGITAL_MICROPHONE_0:
+	case WM8904_DRC_0:
+	case WM8904_DRC_1:
+	case WM8904_DRC_2:
+	case WM8904_DRC_3:
+	case WM8904_ANALOGUE_LEFT_INPUT_0:
+	case WM8904_ANALOGUE_RIGHT_INPUT_0:
+	case WM8904_ANALOGUE_LEFT_INPUT_1:
+	case WM8904_ANALOGUE_RIGHT_INPUT_1:
+	case WM8904_ANALOGUE_OUT1_LEFT:
+	case WM8904_ANALOGUE_OUT1_RIGHT:
+	case WM8904_ANALOGUE_OUT2_LEFT:
+	case WM8904_ANALOGUE_OUT2_RIGHT:
+	case WM8904_ANALOGUE_OUT12_ZC:
+	case WM8904_DC_SERVO_0:
+	case WM8904_DC_SERVO_1:
+	case WM8904_DC_SERVO_2:
+	case WM8904_DC_SERVO_4:
+	case WM8904_DC_SERVO_5:
+	case WM8904_DC_SERVO_6:
+	case WM8904_DC_SERVO_7:
+	case WM8904_DC_SERVO_8:
+	case WM8904_DC_SERVO_9:
+	case WM8904_DC_SERVO_READBACK_0:
+	case WM8904_ANALOGUE_HP_0:
+	case WM8904_ANALOGUE_LINEOUT_0:
+	case WM8904_CHARGE_PUMP_0:
+	case WM8904_CLASS_W_0:
+	case WM8904_WRITE_SEQUENCER_0:
+	case WM8904_WRITE_SEQUENCER_1:
+	case WM8904_WRITE_SEQUENCER_2:
+	case WM8904_WRITE_SEQUENCER_3:
+	case WM8904_WRITE_SEQUENCER_4:
+	case WM8904_FLL_CONTROL_1:
+	case WM8904_FLL_CONTROL_2:
+	case WM8904_FLL_CONTROL_3:
+	case WM8904_FLL_CONTROL_4:
+	case WM8904_FLL_CONTROL_5:
+	case WM8904_GPIO_CONTROL_1:
+	case WM8904_GPIO_CONTROL_2:
+	case WM8904_GPIO_CONTROL_3:
+	case WM8904_GPIO_CONTROL_4:
+	case WM8904_DIGITAL_PULLS:
+	case WM8904_INTERRUPT_STATUS:
+	case WM8904_INTERRUPT_STATUS_MASK:
+	case WM8904_INTERRUPT_POLARITY:
+	case WM8904_INTERRUPT_DEBOUNCE:
+	case WM8904_EQ1:
+	case WM8904_EQ2:
+	case WM8904_EQ3:
+	case WM8904_EQ4:
+	case WM8904_EQ5:
+	case WM8904_EQ6:
+	case WM8904_EQ7:
+	case WM8904_EQ8:
+	case WM8904_EQ9:
+	case WM8904_EQ10:
+	case WM8904_EQ11:
+	case WM8904_EQ12:
+	case WM8904_EQ13:
+	case WM8904_EQ14:
+	case WM8904_EQ15:
+	case WM8904_EQ16:
+	case WM8904_EQ17:
+	case WM8904_EQ18:
+	case WM8904_EQ19:
+	case WM8904_EQ20:
+	case WM8904_EQ21:
+	case WM8904_EQ22:
+	case WM8904_EQ23:
+	case WM8904_EQ24:
+	case WM8904_CONTROL_INTERFACE_TEST_1:
+	case WM8904_ADC_TEST_0:
+	case WM8904_ANALOGUE_OUTPUT_BIAS_0:
+	case WM8904_FLL_NCO_TEST_0:
+	case WM8904_FLL_NCO_TEST_1:
+		return true;
+	default:
+		return true;
+	}
 }
 
 static int wm8904_reset(struct snd_soc_codec *codec)
@@ -855,6 +570,29 @@ static const char *hpf_mode_text[] = {
 static const struct soc_enum hpf_mode =
 	SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text);
 
+static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	unsigned int val;
+	int ret;
+
+	ret = snd_soc_put_volsw(kcontrol, ucontrol);
+	if (ret < 0)
+		return ret;
+
+	if (ucontrol->value.integer.value[0])
+		val = 0;
+	else
+		val = WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5;
+
+	snd_soc_update_bits(codec, WM8904_ADC_TEST_0,
+			    WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5,
+			    val);
+
+	return ret;
+}
+
 static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = {
 SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT,
 		 WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv),
@@ -871,7 +609,12 @@ SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0,
 SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0),
 SOC_ENUM("High Pass Filter Mode", hpf_mode),
 
-SOC_SINGLE("ADC 128x OSR Switch", WM8904_ANALOGUE_ADC_0, 0, 1, 0),
+{       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "ADC 128x OSR Switch",
+	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,
+	.put = wm8904_adc_osr_put,
+	.private_value = SOC_SINGLE_VALUE(WM8904_ANALOGUE_ADC_0, 0, 1, 0),
+},
 };
 
 static const char *drc_path_text[] = {
@@ -1433,11 +1176,11 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
 
 	switch (wm8904->devtype) {
 	case WM8904:
-		snd_soc_add_controls(codec, wm8904_adc_snd_controls,
+		snd_soc_add_codec_controls(codec, wm8904_adc_snd_controls,
 				     ARRAY_SIZE(wm8904_adc_snd_controls));
-		snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+		snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
 				     ARRAY_SIZE(wm8904_dac_snd_controls));
-		snd_soc_add_controls(codec, wm8904_snd_controls,
+		snd_soc_add_codec_controls(codec, wm8904_snd_controls,
 				     ARRAY_SIZE(wm8904_snd_controls));
 
 		snd_soc_dapm_new_controls(dapm, wm8904_adc_dapm_widgets,
@@ -1458,7 +1201,7 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
 		break;
 
 	case WM8912:
-		snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+		snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
 				     ARRAY_SIZE(wm8904_dac_snd_controls));
 
 		snd_soc_dapm_new_controls(dapm, wm8904_dac_dapm_widgets,
@@ -2088,32 +1831,6 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 	return 0;
 }
 
-static void wm8904_sync_cache(struct snd_soc_codec *codec)
-{
-	u16 *reg_cache = codec->reg_cache;
-	int i;
-
-	if (!codec->cache_sync)
-		return;
-
-	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 (!wm8904_access[i].writable)
-			continue;
-
-		if (reg_cache[i] == wm8904_reg[i])
-			continue;
-
-		snd_soc_write(codec, i, reg_cache[i]);
-	}
-
-	codec->cache_sync = 0;
-}
-
 static int wm8904_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
@@ -2146,7 +1863,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
 				return ret;
 			}
 
-			wm8904_sync_cache(codec);
+			regcache_sync(wm8904->regmap);
 
 			/* Enable bias */
 			snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
@@ -2303,7 +2020,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
 	wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
 	wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
 
-	ret = snd_soc_add_controls(codec, &control, 1);
+	ret = snd_soc_add_codec_controls(codec, &control, 1);
 	if (ret != 0)
 		dev_err(codec->dev,
 			"Failed to add ReTune Mobile control: %d\n", ret);
@@ -2316,7 +2033,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
 	int ret, i;
 
 	if (!pdata) {
-		snd_soc_add_controls(codec, wm8904_eq_controls,
+		snd_soc_add_codec_controls(codec, wm8904_eq_controls,
 				     ARRAY_SIZE(wm8904_eq_controls));
 		return;
 	}
@@ -2344,7 +2061,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
 		wm8904->drc_enum.max = pdata->num_drc_cfgs;
 		wm8904->drc_enum.texts = wm8904->drc_texts;
 
-		ret = snd_soc_add_controls(codec, &control, 1);
+		ret = snd_soc_add_codec_controls(codec, &control, 1);
 		if (ret != 0)
 			dev_err(codec->dev,
 				"Failed to add DRC mode control: %d\n", ret);
@@ -2358,7 +2075,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
 	if (pdata->num_retune_mobile_cfgs)
 		wm8904_handle_retune_mobile_pdata(codec);
 	else
-		snd_soc_add_controls(codec, wm8904_eq_controls,
+		snd_soc_add_codec_controls(codec, wm8904_eq_controls,
 				     ARRAY_SIZE(wm8904_eq_controls));
 }
 
@@ -2371,7 +2088,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
 	int ret, i;
 
 	codec->cache_sync = 1;
-	codec->dapm.idle_bias_off = 1;
+	codec->control_data = wm8904->regmap;
 
 	switch (wm8904->devtype) {
 	case WM8904:
@@ -2385,7 +2102,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
 		return -EINVAL;
 	}
 
-	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;
@@ -2413,7 +2130,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
 		dev_err(codec->dev, "Failed to read ID register\n");
 		goto err_enable;
 	}
-	if (ret != wm8904_reg[WM8904_SW_RESET_AND_ID]) {
+	if (ret != 0x8904) {
 		dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret);
 		ret = -EINVAL;
 		goto err_enable;
@@ -2519,38 +2236,62 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
 	.suspend =	wm8904_suspend,
 	.resume =	wm8904_resume,
 	.set_bias_level = wm8904_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8904_reg),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8904_reg,
-	.volatile_register = wm8904_volatile_register,
+	.idle_bias_off = true,
+};
+
+static const struct regmap_config wm8904_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+
+	.max_register = WM8904_MAX_REGISTER,
+	.volatile_reg = wm8904_volatile_register,
+	.readable_reg = wm8904_readable_register,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8904_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8904_priv *wm8904;
 	int ret;
 
-	wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);
+	wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv),
+			      GFP_KERNEL);
 	if (wm8904 == NULL)
 		return -ENOMEM;
 
+	wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap);
+	if (IS_ERR(wm8904->regmap)) {
+		ret = PTR_ERR(wm8904->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
 	wm8904->devtype = id->driver_data;
 	i2c_set_clientdata(i2c, wm8904);
 	wm8904->pdata = i2c->dev.platform_data;
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8904, &wm8904_dai, 1);
-	if (ret < 0)
-		kfree(wm8904);
+	if (ret != 0)
+		goto err;
+
+	return 0;
+
+err:
+	regmap_exit(wm8904->regmap);
 	return ret;
 }
 
 static __devexit int wm8904_i2c_remove(struct i2c_client *client)
 {
+	struct wm8904_priv *wm8904 = i2c_get_clientdata(client);
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm8904->regmap);
 	return 0;
 }
 
@@ -2571,27 +2312,22 @@ static struct i2c_driver wm8904_i2c_driver = {
 	.remove =   __devexit_p(wm8904_i2c_remove),
 	.id_table = wm8904_i2c_id,
 };
-#endif
 
 static int __init wm8904_modinit(void)
 {
 	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&wm8904_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
 		       ret);
 	}
-#endif
 	return ret;
 }
 module_init(wm8904_modinit);
 
 static void __exit wm8904_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8904_i2c_driver);
-#endif
 }
 module_exit(wm8904_exit);
 
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h
index 9e8c84188ba761bb0eb606029e7c80f8d34e8219..c29a0e8131ca97e2d87cffcb9ad4105a87a437b9 100644
--- a/sound/soc/codecs/wm8904.h
+++ b/sound/soc/codecs/wm8904.h
@@ -123,6 +123,7 @@
 #define WM8904_EQ23                             0x9C
 #define WM8904_EQ24                             0x9D
 #define WM8904_CONTROL_INTERFACE_TEST_1         0xA1
+#define WM8904_ADC_TEST_0			0xC6
 #define WM8904_ANALOGUE_OUTPUT_BIAS_0           0xCC
 #define WM8904_FLL_NCO_TEST_0                   0xF7
 #define WM8904_FLL_NCO_TEST_1                   0xF8
@@ -1556,6 +1557,16 @@
 #define WM8904_USER_KEY_SHIFT                        1  /* USER_KEY */
 #define WM8904_USER_KEY_WIDTH                        1  /* USER_KEY */
 
+/*
+ * R198 (0xC6) - ADC Test 0
+ */
+#define WM8904_ADC_128_OSR_TST_MODE             0x0004  /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_128_OSR_TST_MODE_SHIFT            2  /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_128_OSR_TST_MODE_WIDTH            1  /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_BIASX1P5                     0x0001  /* ADC_BIASX1P5 */
+#define WM8904_ADC_BIASX1P5_SHIFT                    0  /* ADC_BIASX1P5 */
+#define WM8904_ADC_BIASX1P5_WIDTH                    1  /* ADC_BIASX1P5 */
+
 /*
  * R204 (0xCC) - Analogue Output Bias 0
  */
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 14039ea2f3e4a13d9e882fefe3c2dd4f387bb670..d2883affea3b2421508c474732d3fdf92192bdb2 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -717,7 +717,7 @@ static int wm8940_probe(struct snd_soc_codec *codec)
 			return ret;
 	}
 
-	ret = snd_soc_add_controls(codec, wm8940_snd_controls,
+	ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls,
 			     ARRAY_SIZE(wm8940_snd_controls));
 	if (ret)
 		return ret;
@@ -743,14 +743,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
 	.volatile_register = wm8940_volatile_register,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8940_priv *wm8940;
 	int ret;
 
-	wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL);
+	wm8940 = devm_kzalloc(&i2c->dev, sizeof(struct wm8940_priv),
+			      GFP_KERNEL);
 	if (wm8940 == NULL)
 		return -ENOMEM;
 
@@ -759,15 +759,14 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8940, &wm8940_dai, 1);
-	if (ret < 0)
-		kfree(wm8940);
+
 	return ret;
 }
 
 static __devexit int wm8940_i2c_remove(struct i2c_client *client)
 {
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+
 	return 0;
 }
 
@@ -786,27 +785,22 @@ static struct i2c_driver wm8940_i2c_driver = {
 	.remove =   __devexit_p(wm8940_i2c_remove),
 	.id_table = wm8940_i2c_id,
 };
-#endif
 
 static int __init wm8940_modinit(void)
 {
 	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&wm8940_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n",
 		       ret);
 	}
-#endif
 	return ret;
 }
 module_init(wm8940_modinit);
 
 static void __exit wm8940_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8940_i2c_driver);
-#endif
 }
 module_exit(wm8940_exit);
 
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 924548182d58f86257e1a4a2d9fde8125e67a8af..61fe97433e738eb43c486115a985fc1bd0ad68f5 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -38,7 +39,7 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8955_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 
 	unsigned int mclk_rate;
 
@@ -48,69 +49,85 @@ struct wm8955_priv {
 	struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
 };
 
-static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
-	0x0000,     /* R0 */
-	0x0000,     /* R1 */
-	0x0079,     /* R2  - LOUT1 volume */
-	0x0079,     /* R3  - ROUT1 volume */
-	0x0000,     /* R4 */
-	0x0008,     /* R5  - DAC Control */
-	0x0000,     /* R6 */
-	0x000A,     /* R7  - Audio Interface */
-	0x0000,     /* R8  - Sample Rate */
-	0x0000,     /* R9 */
-	0x00FF,     /* R10 - Left DAC volume */
-	0x00FF,     /* R11 - Right DAC volume */
-	0x000F,     /* R12 - Bass control */
-	0x000F,     /* R13 - Treble control */
-	0x0000,     /* R14 */
-	0x0000,     /* R15 - Reset */
-	0x0000,     /* R16 */
-	0x0000,     /* R17 */
-	0x0000,     /* R18 */
-	0x0000,     /* R19 */
-	0x0000,     /* R20 */
-	0x0000,     /* R21 */
-	0x0000,     /* R22 */
-	0x00C1,     /* R23 - Additional control (1) */
-	0x0000,     /* R24 - Additional control (2) */
-	0x0000,     /* R25 - Power Management (1) */
-	0x0000,     /* R26 - Power Management (2) */
-	0x0000,     /* R27 - Additional Control (3) */
-	0x0000,     /* R28 */
-	0x0000,     /* R29 */
-	0x0000,     /* R30 */
-	0x0000,     /* R31 */
-	0x0000,     /* R32 */
-	0x0000,     /* R33 */
-	0x0050,     /* R34 - Left out Mix (1) */
-	0x0050,     /* R35 - Left out Mix (2) */
-	0x0050,     /* R36 - Right out Mix (1) */
-	0x0050,     /* R37 - Right Out Mix (2) */
-	0x0050,     /* R38 - Mono out Mix (1) */
-	0x0050,     /* R39 - Mono out Mix (2) */
-	0x0079,     /* R40 - LOUT2 volume */
-	0x0079,     /* R41 - ROUT2 volume */
-	0x0079,     /* R42 - MONOOUT volume */
-	0x0000,     /* R43 - Clocking / PLL */
-	0x0103,     /* R44 - PLL Control 1 */
-	0x0024,     /* R45 - PLL Control 2 */
-	0x01BA,     /* R46 - PLL Control 3 */
-	0x0000,     /* R47 */
-	0x0000,     /* R48 */
-	0x0000,     /* R49 */
-	0x0000,     /* R50 */
-	0x0000,     /* R51 */
-	0x0000,     /* R52 */
-	0x0000,     /* R53 */
-	0x0000,     /* R54 */
-	0x0000,     /* R55 */
-	0x0000,     /* R56 */
-	0x0000,     /* R57 */
-	0x0000,     /* R58 */
-	0x0000,     /* R59 - PLL Control 4 */
+static const struct reg_default wm8955_reg_defaults[] = {
+	{ 2,  0x0079 },     /* R2  - LOUT1 volume */
+	{ 3,  0x0079 },     /* R3  - ROUT1 volume */
+	{ 5,  0x0008 },     /* R5  - DAC Control */
+	{ 7,  0x000A },     /* R7  - Audio Interface */
+	{ 8,  0x0000 },     /* R8  - Sample Rate */
+	{ 10, 0x00FF },     /* R10 - Left DAC volume */
+	{ 11, 0x00FF },     /* R11 - Right DAC volume */
+	{ 12, 0x000F },     /* R12 - Bass control */
+	{ 13, 0x000F },     /* R13 - Treble control */
+	{ 23, 0x00C1 },     /* R23 - Additional control (1) */
+	{ 24, 0x0000 },     /* R24 - Additional control (2) */
+	{ 25, 0x0000 },     /* R25 - Power Management (1) */
+	{ 26, 0x0000 },     /* R26 - Power Management (2) */
+	{ 27, 0x0000 },     /* R27 - Additional Control (3) */
+	{ 34, 0x0050 },     /* R34 - Left out Mix (1) */
+	{ 35, 0x0050 },     /* R35 - Left out Mix (2) */
+	{ 36, 0x0050 },     /* R36 - Right out Mix (1) */
+	{ 37, 0x0050 },     /* R37 - Right Out Mix (2) */
+	{ 38, 0x0050 },     /* R38 - Mono out Mix (1) */
+	{ 39, 0x0050 },     /* R39 - Mono out Mix (2) */
+	{ 40, 0x0079 },     /* R40 - LOUT2 volume */
+	{ 41, 0x0079 },     /* R41 - ROUT2 volume */
+	{ 42, 0x0079 },     /* R42 - MONOOUT volume */
+	{ 43, 0x0000 },     /* R43 - Clocking / PLL */
+	{ 44, 0x0103 },     /* R44 - PLL Control 1 */
+	{ 45, 0x0024 },     /* R45 - PLL Control 2 */
+	{ 46, 0x01BA },     /* R46 - PLL Control 3 */
+	{ 59, 0x0000 },     /* R59 - PLL Control 4 */
 };
 
+static bool wm8955_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM8955_LOUT1_VOLUME:
+	case WM8955_ROUT1_VOLUME:
+	case WM8955_DAC_CONTROL:
+	case WM8955_AUDIO_INTERFACE:
+	case WM8955_SAMPLE_RATE:
+	case WM8955_LEFT_DAC_VOLUME:
+	case WM8955_RIGHT_DAC_VOLUME:
+	case WM8955_BASS_CONTROL:
+	case WM8955_TREBLE_CONTROL:
+	case WM8955_RESET:
+	case WM8955_ADDITIONAL_CONTROL_1:
+	case WM8955_ADDITIONAL_CONTROL_2:
+	case WM8955_POWER_MANAGEMENT_1:
+	case WM8955_POWER_MANAGEMENT_2:
+	case WM8955_ADDITIONAL_CONTROL_3:
+	case WM8955_LEFT_OUT_MIX_1:
+	case WM8955_LEFT_OUT_MIX_2:
+	case WM8955_RIGHT_OUT_MIX_1:
+	case WM8955_RIGHT_OUT_MIX_2:
+	case WM8955_MONO_OUT_MIX_1:
+	case WM8955_MONO_OUT_MIX_2:
+	case WM8955_LOUT2_VOLUME:
+	case WM8955_ROUT2_VOLUME:
+	case WM8955_MONOOUT_VOLUME:
+	case WM8955_CLOCKING_PLL:
+	case WM8955_PLL_CONTROL_1:
+	case WM8955_PLL_CONTROL_2:
+	case WM8955_PLL_CONTROL_3:
+	case WM8955_PLL_CONTROL_4:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool wm8955_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM8955_RESET:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static int wm8955_reset(struct snd_soc_codec *codec)
 {
 	return snd_soc_write(codec, WM8955_RESET, 0);
@@ -527,7 +544,7 @@ SND_SOC_DAPM_OUTPUT("MONOOUT"),
 SND_SOC_DAPM_OUTPUT("OUT3"),
 };
 
-static const struct snd_soc_dapm_route wm8955_intercon[] = {
+static const struct snd_soc_dapm_route wm8955_dapm_routes[] = {
 	{ "DACL", NULL, "SYSCLK" },
 	{ "DACR", NULL, "SYSCLK" },
 
@@ -572,21 +589,6 @@ static const struct snd_soc_dapm_route wm8955_intercon[] = {
 	{ "OUT3", NULL, "OUT3 PGA" },
 };
 
-static int wm8955_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	snd_soc_add_controls(codec, wm8955_snd_controls,
-			     ARRAY_SIZE(wm8955_snd_controls));
-
-	snd_soc_dapm_new_controls(dapm, wm8955_dapm_widgets,
-				  ARRAY_SIZE(wm8955_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, wm8955_intercon,
-				ARRAY_SIZE(wm8955_intercon));
-
-	return 0;
-}
-
 static int wm8955_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
@@ -765,8 +767,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
 	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
-	u16 *reg_cache = codec->reg_cache;
-	int ret, i;
+	int ret;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
@@ -795,18 +796,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
 				return ret;
 			}
 
-			/* Sync back cached values if they're
-			 * different from the hardware default.
-			 */
-			for (i = 0; i < codec->driver->reg_cache_size; i++) {
-				if (i == WM8955_RESET)
-					continue;
-
-				if (reg_cache[i] == wm8955_reg[i])
-					continue;
-
-				snd_soc_write(codec, i, reg_cache[i]);
-			}
+			regcache_sync(wm8955->regmap);
 
 			/* Enable VREF and VMID */
 			snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
@@ -880,8 +870,12 @@ static struct snd_soc_dai_driver wm8955_dai = {
 #ifdef CONFIG_PM
 static int wm8955_suspend(struct snd_soc_codec *codec)
 {
+	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+
 	wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
+	regcache_mark_dirty(wm8955->regmap);
+
 	return 0;
 }
 
@@ -900,10 +894,11 @@ static int wm8955_probe(struct snd_soc_codec *codec)
 {
 	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 	struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
-	u16 *reg_cache = codec->reg_cache;
 	int ret, i;
 
-	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
+	codec->control_data = wm8955->regmap;
+
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -958,12 +953,12 @@ static int wm8955_probe(struct snd_soc_codec *codec)
 	/* Set platform data values */
 	if (pdata) {
 		if (pdata->out2_speaker)
-			reg_cache[WM8955_ADDITIONAL_CONTROL_2]
-				|= WM8955_ROUT2INV;
+			snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2,
+					    WM8955_ROUT2INV, WM8955_ROUT2INV);
 
 		if (pdata->monoin_diff)
-			reg_cache[WM8955_MONO_OUT_MIX_1]
-				|= WM8955_DMEN;
+			snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1,
+					    WM8955_DMEN, WM8955_DMEN);
 	}
 
 	wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -971,7 +966,6 @@ static int wm8955_probe(struct snd_soc_codec *codec)
 	/* Bias level configuration will have done an extra enable */
 	regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
 
-	wm8955_add_widgets(codec);
 	return 0;
 
 err_enable:
@@ -996,36 +990,68 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
 	.suspend =	wm8955_suspend,
 	.resume =	wm8955_resume,
 	.set_bias_level = wm8955_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8955_reg),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8955_reg,
+
+	.controls =	wm8955_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8955_snd_controls),
+	.dapm_widgets = wm8955_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets),
+	.dapm_routes =	wm8955_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes),
+};
+
+static const struct regmap_config wm8955_regmap = {
+	.reg_bits = 7,
+	.val_bits = 9,
+
+	.max_register = WM8955_MAX_REGISTER,
+	.volatile_reg = wm8955_volatile,
+	.writeable_reg = wm8955_writeable,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8955_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8955_priv *wm8955;
 	int ret;
 
-	wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
+	wm8955 = devm_kzalloc(&i2c->dev, sizeof(struct wm8955_priv),
+			      GFP_KERNEL);
 	if (wm8955 == NULL)
 		return -ENOMEM;
 
+	wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap);
+	if (IS_ERR(wm8955->regmap)) {
+		ret = PTR_ERR(wm8955->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
 	i2c_set_clientdata(i2c, wm8955);
-	wm8955->control_type = SND_SOC_I2C;
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8955, &wm8955_dai, 1);
-	if (ret < 0)
-		kfree(wm8955);
+	if (ret != 0)
+		goto err;
+
+	return ret;
+
+err:
+	regmap_exit(wm8955->regmap);
 	return ret;
 }
 
 static __devexit int wm8955_i2c_remove(struct i2c_client *client)
 {
+	struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
+
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm8955->regmap);
+
 	return 0;
 }
 
@@ -1044,27 +1070,22 @@ static struct i2c_driver wm8955_i2c_driver = {
 	.remove =   __devexit_p(wm8955_i2c_remove),
 	.id_table = wm8955_i2c_id,
 };
-#endif
 
 static int __init wm8955_modinit(void)
 {
 	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&wm8955_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n",
 		       ret);
 	}
-#endif
 	return ret;
 }
 module_init(wm8955_modinit);
 
 static void __exit wm8955_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8955_i2c_driver);
-#endif
 }
 module_exit(wm8955_exit);
 
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 40ac888faf3d7633f433257ab96e2f190d6f4174..1332692ef81bc9628e8cad04ccf65cd972c7fb8c 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -920,11 +920,11 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 
 	wm8994->dsp_active = -1;
 
-	snd_soc_add_controls(codec, wm8958_mbc_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8958_mbc_snd_controls,
 			     ARRAY_SIZE(wm8958_mbc_snd_controls));
-	snd_soc_add_controls(codec, wm8958_vss_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8958_vss_snd_controls,
 			     ARRAY_SIZE(wm8958_vss_snd_controls));
-	snd_soc_add_controls(codec, wm8958_enh_eq_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8958_enh_eq_snd_controls,
 			     ARRAY_SIZE(wm8958_enh_eq_snd_controls));
 
 
@@ -958,7 +958,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 		wm8994->mbc_enum.max = pdata->num_mbc_cfgs;
 		wm8994->mbc_enum.texts = wm8994->mbc_texts;
 
-		ret = snd_soc_add_controls(wm8994->codec, control, 1);
+		ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
 		if (ret != 0)
 			dev_err(wm8994->codec->dev,
 				"Failed to add MBC mode controls: %d\n", ret);
@@ -986,7 +986,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 		wm8994->vss_enum.max = pdata->num_vss_cfgs;
 		wm8994->vss_enum.texts = wm8994->vss_texts;
 
-		ret = snd_soc_add_controls(wm8994->codec, control, 1);
+		ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
 		if (ret != 0)
 			dev_err(wm8994->codec->dev,
 				"Failed to add VSS mode controls: %d\n", ret);
@@ -1015,7 +1015,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 		wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs;
 		wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
 
-		ret = snd_soc_add_controls(wm8994->codec, control, 1);
+		ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
 		if (ret != 0)
 			dev_err(wm8994->codec->dev,
 				"Failed to add VSS HPFmode controls: %d\n",
@@ -1045,7 +1045,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 		wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs;
 		wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts;
 
-		ret = snd_soc_add_controls(wm8994->codec, control, 1);
+		ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
 		if (ret != 0)
 			dev_err(wm8994->codec->dev,
 				"Failed to add enhanced EQ controls: %d\n",
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index e5caae32e5419a695f0533b833fb3d719ccbbf4c..840d72086d04c7c3cf8dcf7d813c9a4f8ee149d7 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -940,7 +940,7 @@ static int wm8960_probe(struct snd_soc_codec *codec)
 	snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100);
 	snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100);
 
-	snd_soc_add_controls(codec, wm8960_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8960_snd_controls,
 				     ARRAY_SIZE(wm8960_snd_controls));
 	wm8960_add_widgets(codec);
 
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 4f20c72a0f1d329a824ee2255f6003ef741c07da..05ea7c2740933b0ff4b2cbfedc3be54515670fa8 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -1022,7 +1022,7 @@ static int wm8961_probe(struct snd_soc_codec *codec)
 
 	wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	snd_soc_add_controls(codec, wm8961_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8961_snd_controls,
 				ARRAY_SIZE(wm8961_snd_controls));
 	snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets,
 				  ARRAY_SIZE(wm8961_dapm_widgets));
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 0ac228b7dc049a8d584b7219e3fa844262af3769..15d467ff91b496b6bb72dfbdd5eb4c9bfb5500fa 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -115,11 +116,11 @@ static struct reg_default wm8962_reg[] = {
 	{ 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 */
@@ -128,7 +129,7 @@ static struct reg_default wm8962_reg[] = {
 	{ 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 */
@@ -152,10 +153,6 @@ static struct reg_default wm8962_reg[] = {
 	{ 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 */
-
 	{ 51, 0x0003 },   /* R51    - Class D Control 2 */
 
 	{ 56, 0x0506 },   /* R56    - Clocking 4 */
@@ -167,8 +164,6 @@ static struct reg_default wm8962_reg[] = {
 
 	{ 64, 0x0810 },   /* R64    - DC Servo 4 */
 
-	{ 66, 0x0000 },   /* R66    - DC Servo 6 */
-
 	{ 68, 0x001B },   /* R68    - Analogue PGA Bias */
 	{ 69, 0x0000 },   /* R69    - Analogue HP 0 */
 
@@ -207,8 +202,6 @@ static struct reg_default wm8962_reg[] = {
 	{ 126, 0x000D },   /* R126   - Analogue Clocking3 */
 	{ 127, 0x0000 },   /* R127   - PLL Software Reset */
 
-	{ 129, 0x0000 },   /* R129   - PLL2 */
-
 	{ 131, 0x0000 },   /* R131   - PLL 4 */
 
 	{ 136, 0x0067 },   /* R136   - PLL 9 */
@@ -303,9 +296,6 @@ static struct reg_default wm8962_reg[] = {
 	{ 516, 0x8100 },   /* R516   - GPIO 5 */
 	{ 517, 0x8100 },   /* R517   - GPIO 6 */
 
-	{ 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 */
 
@@ -317,8 +307,6 @@ static struct reg_default wm8962_reg[] = {
 
 	{ 768, 0x1C00 },   /* R768   - DSP2 Power Management */
 
-	{ 1037, 0x0000 },   /* R1037  - DSP2_ExecControl */
-
 	{ 8192, 0x0000 },   /* R8192  - DSP2 Instruction RAM 0 */
 
 	{ 9216, 0x0030 },   /* R9216  - DSP2 Address RAM 2 */
@@ -797,1167 +785,660 @@ static struct reg_default wm8962_reg[] = {
 	{ 21139, 0x8580 },   /* R21139 - VSS_XTS32_0 */
 };
 
-static const struct wm8962_reg_access {
-	u16 read;
-	u16 write;
-	u16 vol;
-} wm8962_reg_access[WM8962_MAX_REGISTER + 1] = {
-	[0] = { 0x00FF, 0x01FF, 0x0000 }, /* R0     - Left 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 */
-	[5] = { 0x007F, 0x007F, 0x0000 }, /* R5     - ADC & DAC Control 1 */
-	[6] = { 0x37ED, 0x37ED, 0x0000 }, /* R6     - ADC & DAC Control 2 */
-	[7] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R7     - Audio Interface 0 */
-	[8] = { 0x0FEF, 0x0FEF, 0xFFFF }, /* R8     - Clocking2 */
-	[9] = { 0x0B9F, 0x039F, 0x0000 }, /* R9     - Audio Interface 1 */
-	[10] = { 0x00FF, 0x01FF, 0x0000 }, /* R10    - Left DAC volume */
-	[11] = { 0x00FF, 0x01FF, 0x0000 }, /* R11    - Right DAC volume */
-	[14] = { 0x07FF, 0x07FF, 0x0000 }, /* R14    - Audio Interface 2 */
-	[15] = { 0xFFFF, 0xFFFF, 0xFFFF }, /* R15    - Software Reset */
-	[17] = { 0x07FF, 0x07FF, 0x0000 }, /* R17    - ALC1 */
-	[18] = { 0xF8FF, 0x00FF, 0xFFFF }, /* R18    - ALC2 */
-	[19] = { 0x1DFF, 0x1DFF, 0x0000 }, /* R19    - ALC3 */
-	[20] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20    - Noise Gate */
-	[21] = { 0x00FF, 0x01FF, 0x0000 }, /* R21    - Left ADC volume */
-	[22] = { 0x00FF, 0x01FF, 0x0000 }, /* R22    - Right ADC volume */
-	[23] = { 0x0161, 0x0161, 0x0000 }, /* R23    - Additional control(1) */
-	[24] = { 0x0008, 0x0008, 0x0000 }, /* R24    - Additional control(2) */
-	[25] = { 0x07FE, 0x07FE, 0x0000 }, /* R25    - Pwr Mgmt (1) */
-	[26] = { 0x01FB, 0x01FB, 0x0000 }, /* R26    - Pwr Mgmt (2) */
-	[27] = { 0x0017, 0x0017, 0x0000 }, /* R27    - Additional Control (3) */
-	[28] = { 0x001C, 0x001C, 0x0000 }, /* R28    - Anti-pop */
-
-	[30] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R30    - Clocking 3 */
-	[31] = { 0x000F, 0x000F, 0x0000 }, /* R31    - Input mixer control (1) */
-	[32] = { 0x01FF, 0x01FF, 0x0000 }, /* R32    - Left input mixer volume */
-	[33] = { 0x01FF, 0x01FF, 0x0000 }, /* R33    - Right input mixer volume */
-	[34] = { 0x003F, 0x003F, 0x0000 }, /* R34    - Input mixer control (2) */
-	[35] = { 0x003F, 0x003F, 0x0000 }, /* R35    - Input bias control */
-	[37] = { 0x001F, 0x001F, 0x0000 }, /* R37    - Left input PGA control */
-	[38] = { 0x001F, 0x001F, 0x0000 }, /* R38    - Right input PGA control */
-	[40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40    - SPKOUTL volume */
-	[41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41    - SPKOUTR volume */
-
-	[47] = { 0x000F, 0x0000, 0xFFFF }, /* R47    - Thermal Shutdown Status */
-	[48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48    - Additional Control (4) */
-	[49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49    - Class D Control 1 */
-	[51] = { 0x0047, 0x0047, 0x0000 }, /* R51    - Class D Control 2 */
-	[56] = { 0x001E, 0x001E, 0x0000 }, /* R56    - Clocking 4 */
-	[57] = { 0x02FC, 0x02FC, 0x0000 }, /* R57    - DAC DSP Mixing (1) */
-	[58] = { 0x00FC, 0x00FC, 0x0000 }, /* R58    - DAC DSP Mixing (2) */
-	[60] = { 0x00CC, 0x00CC, 0x0000 }, /* R60    - DC Servo 0 */
-	[61] = { 0x00DD, 0x00DD, 0x0000 }, /* R61    - DC Servo 1 */
-	[64] = { 0x3F80, 0x3F80, 0x0000 }, /* R64    - DC Servo 4 */
-	[66] = { 0x0780, 0x0000, 0xFFFF }, /* R66    - DC Servo 6 */
-	[68] = { 0x0007, 0x0007, 0x0000 }, /* R68    - Analogue PGA Bias */
-	[69] = { 0x00FF, 0x00FF, 0x0000 }, /* R69    - Analogue HP 0 */
-	[71] = { 0x01FF, 0x01FF, 0x0000 }, /* R71    - Analogue HP 2 */
-	[72] = { 0x0001, 0x0001, 0x0000 }, /* R72    - Charge Pump 1 */
-	[82] = { 0x0001, 0x0001, 0x0000 }, /* R82    - Charge Pump B */
-	[87] = { 0x00A0, 0x00A0, 0x0000 }, /* R87    - Write Sequencer Control 1 */
-	[90] = { 0x007F, 0x01FF, 0x0000 }, /* R90    - Write Sequencer Control 2 */
-	[93] = { 0x03F9, 0x0000, 0x0000 }, /* R93    - Write Sequencer Control 3 */
-	[94] = { 0x0070, 0x0070, 0x0000 }, /* R94    - Control Interface */
-	[99] = { 0x000F, 0x000F, 0x0000 }, /* R99    - Mixer Enables */
-	[100] = { 0x00BF, 0x00BF, 0x0000 }, /* R100   - Headphone Mixer (1) */
-	[101] = { 0x00BF, 0x00BF, 0x0000 }, /* R101   - Headphone Mixer (2) */
-	[102] = { 0x01FF, 0x01FF, 0x0000 }, /* R102   - Headphone Mixer (3) */
-	[103] = { 0x01FF, 0x01FF, 0x0000 }, /* R103   - Headphone Mixer (4) */
-	[105] = { 0x00BF, 0x00BF, 0x0000 }, /* R105   - Speaker Mixer (1) */
-	[106] = { 0x00BF, 0x00BF, 0x0000 }, /* R106   - Speaker Mixer (2) */
-	[107] = { 0x01FF, 0x01FF, 0x0000 }, /* R107   - Speaker Mixer (3) */
-	[108] = { 0x01FF, 0x01FF, 0x0000 }, /* R108   - Speaker Mixer (4) */
-	[109] = { 0x00F0, 0x00F0, 0x0000 }, /* R109   - Speaker Mixer (5) */
-	[110] = { 0x00F7, 0x00F7, 0x0000 }, /* R110   - Beep Generator (1) */
-	[115] = { 0x001F, 0x001F, 0x0000 }, /* R115   - Oscillator Trim (3) */
-	[116] = { 0x001F, 0x001F, 0x0000 }, /* R116   - Oscillator Trim (4) */
-	[119] = { 0x00FF, 0x00FF, 0x0000 }, /* R119   - Oscillator Trim (7) */
-	[124] = { 0x0079, 0x0079, 0x0000 }, /* R124   - Analogue Clocking1 */
-	[125] = { 0x00DF, 0x00DF, 0x0000 }, /* R125   - Analogue Clocking2 */
-	[126] = { 0x000D, 0x000D, 0x0000 }, /* R126   - Analogue Clocking3 */
-	[127] = { 0x0000, 0xFFFF, 0x0000 }, /* R127   - PLL Software Reset */
-	[129] = { 0x00B0, 0x00B0, 0x0000 }, /* R129   - PLL2 */
-	[131] = { 0x0003, 0x0003, 0x0000 }, /* R131   - PLL 4 */
-	[136] = { 0x005F, 0x005F, 0x0000 }, /* R136   - PLL 9 */
-	[137] = { 0x00FF, 0x00FF, 0x0000 }, /* R137   - PLL 10 */
-	[138] = { 0x00FF, 0x00FF, 0x0000 }, /* R138   - PLL 11 */
-	[139] = { 0x00FF, 0x00FF, 0x0000 }, /* R139   - PLL 12 */
-	[140] = { 0x005F, 0x005F, 0x0000 }, /* R140   - PLL 13 */
-	[141] = { 0x00FF, 0x00FF, 0x0000 }, /* R141   - PLL 14 */
-	[142] = { 0x00FF, 0x00FF, 0x0000 }, /* R142   - PLL 15 */
-	[143] = { 0x00FF, 0x00FF, 0x0000 }, /* R143   - PLL 16 */
-	[155] = { 0x0067, 0x0067, 0x0000 }, /* R155   - FLL Control (1) */
-	[156] = { 0x01FB, 0x01FB, 0x0000 }, /* R156   - FLL Control (2) */
-	[157] = { 0x0007, 0x0007, 0x0000 }, /* R157   - FLL Control (3) */
-	[159] = { 0x007F, 0x007F, 0x0000 }, /* R159   - FLL Control (5) */
-	[160] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R160   - FLL Control (6) */
-	[161] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R161   - FLL Control (7) */
-	[162] = { 0x03FF, 0x03FF, 0x0000 }, /* R162   - FLL Control (8) */
-	[252] = { 0x0005, 0x0005, 0x0000 }, /* R252   - General test 1 */
-	[256] = { 0x000F, 0x000F, 0x0000 }, /* R256   - DF1 */
-	[257] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R257   - DF2 */
-	[258] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R258   - DF3 */
-	[259] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R259   - DF4 */
-	[260] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R260   - DF5 */
-	[261] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R261   - DF6 */
-	[262] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R262   - DF7 */
-	[264] = { 0x0003, 0x0003, 0x0000 }, /* R264   - LHPF1 */
-	[265] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R265   - LHPF2 */
-	[268] = { 0x0077, 0x0077, 0x0000 }, /* R268   - THREED1 */
-	[269] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R269   - THREED2 */
-	[270] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R270   - THREED3 */
-	[271] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R271   - THREED4 */
-	[276] = { 0x7FFF, 0x7FFF, 0x0000 }, /* R276   - DRC 1 */
-	[277] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R277   - DRC 2 */
-	[278] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R278   - DRC 3 */
-	[279] = { 0x07FF, 0x07FF, 0x0000 }, /* R279   - DRC 4 */
-	[280] = { 0x03FF, 0x03FF, 0x0000 }, /* R280   - DRC 5 */
-	[285] = { 0x0003, 0x0003, 0x0000 }, /* R285   - Tloopback */
-	[335] = { 0x0007, 0x0007, 0x0000 }, /* R335   - EQ1 */
-	[336] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R336   - EQ2 */
-	[337] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R337   - EQ3 */
-	[338] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R338   - EQ4 */
-	[339] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R339   - EQ5 */
-	[340] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R340   - EQ6 */
-	[341] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R341   - EQ7 */
-	[342] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R342   - EQ8 */
-	[343] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R343   - EQ9 */
-	[344] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R344   - EQ10 */
-	[345] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R345   - EQ11 */
-	[346] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R346   - EQ12 */
-	[347] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R347   - EQ13 */
-	[348] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R348   - EQ14 */
-	[349] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R349   - EQ15 */
-	[350] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R350   - EQ16 */
-	[351] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R351   - EQ17 */
-	[352] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R352   - EQ18 */
-	[353] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R353   - EQ19 */
-	[354] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R354   - EQ20 */
-	[355] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R355   - EQ21 */
-	[356] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R356   - EQ22 */
-	[357] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R357   - EQ23 */
-	[358] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R358   - EQ24 */
-	[359] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R359   - EQ25 */
-	[360] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R360   - EQ26 */
-	[361] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R361   - EQ27 */
-	[362] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R362   - EQ28 */
-	[363] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R363   - EQ29 */
-	[364] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R364   - EQ30 */
-	[365] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R365   - EQ31 */
-	[366] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R366   - EQ32 */
-	[367] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R367   - EQ33 */
-	[368] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R368   - EQ34 */
-	[369] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R369   - EQ35 */
-	[370] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R370   - EQ36 */
-	[371] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R371   - EQ37 */
-	[372] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R372   - EQ38 */
-	[373] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R373   - EQ39 */
-	[374] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R374   - EQ40 */
-	[375] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R375   - EQ41 */
-	[513] = { 0x045F, 0x045F, 0x0000 }, /* R513   - GPIO 2 */
-	[514] = { 0x045F, 0x045F, 0x0000 }, /* R514   - GPIO 3 */
-	[516] = { 0xE75F, 0xE75F, 0x0000 }, /* R516   - GPIO 5 */
-	[517] = { 0xE75F, 0xE75F, 0x0000 }, /* R517   - GPIO 6 */
-	[560] = { 0x0030, 0x0030, 0xFFFF }, /* R560   - Interrupt Status 1 */
-	[561] = { 0xFFED, 0xFFED, 0xFFFF }, /* R561   - Interrupt Status 2 */
-	[568] = { 0x0030, 0x0030, 0x0000 }, /* R568   - Interrupt Status 1 Mask */
-	[569] = { 0xFFED, 0xFFED, 0x0000 }, /* R569   - Interrupt Status 2 Mask */
-	[576] = { 0x0001, 0x0001, 0x0000 }, /* R576   - Interrupt Control */
-	[584] = { 0x002D, 0x002D, 0x0000 }, /* R584   - IRQ Debounce */
-	[586] = { 0xC000, 0xC000, 0x0000 }, /* R586   -  MICINT Source Pol */
-	[768] = { 0x0001, 0x0001, 0x0000 }, /* R768   - DSP2 Power Management */
-	[1037] = { 0x0000, 0x003F, 0xFFFF }, /* R1037  - DSP2_ExecControl */
-	[4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096  - Write Sequencer 0 */
-	[4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097  - Write Sequencer 1 */
-	[4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098  - Write Sequencer 2 */
-	[4099] = { 0x010F, 0x010F, 0x0000 }, /* R4099  - Write Sequencer 3 */
-	[4100] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4100  - Write Sequencer 4 */
-	[4101] = { 0x00FF, 0x00FF, 0x0000 }, /* R4101  - Write Sequencer 5 */
-	[4102] = { 0x070F, 0x070F, 0x0000 }, /* R4102  - Write Sequencer 6 */
-	[4103] = { 0x010F, 0x010F, 0x0000 }, /* R4103  - Write Sequencer 7 */
-	[4104] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4104  - Write Sequencer 8 */
-	[4105] = { 0x00FF, 0x00FF, 0x0000 }, /* R4105  - Write Sequencer 9 */
-	[4106] = { 0x070F, 0x070F, 0x0000 }, /* R4106  - Write Sequencer 10 */
-	[4107] = { 0x010F, 0x010F, 0x0000 }, /* R4107  - Write Sequencer 11 */
-	[4108] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4108  - Write Sequencer 12 */
-	[4109] = { 0x00FF, 0x00FF, 0x0000 }, /* R4109  - Write Sequencer 13 */
-	[4110] = { 0x070F, 0x070F, 0x0000 }, /* R4110  - Write Sequencer 14 */
-	[4111] = { 0x010F, 0x010F, 0x0000 }, /* R4111  - Write Sequencer 15 */
-	[4112] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4112  - Write Sequencer 16 */
-	[4113] = { 0x00FF, 0x00FF, 0x0000 }, /* R4113  - Write Sequencer 17 */
-	[4114] = { 0x070F, 0x070F, 0x0000 }, /* R4114  - Write Sequencer 18 */
-	[4115] = { 0x010F, 0x010F, 0x0000 }, /* R4115  - Write Sequencer 19 */
-	[4116] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4116  - Write Sequencer 20 */
-	[4117] = { 0x00FF, 0x00FF, 0x0000 }, /* R4117  - Write Sequencer 21 */
-	[4118] = { 0x070F, 0x070F, 0x0000 }, /* R4118  - Write Sequencer 22 */
-	[4119] = { 0x010F, 0x010F, 0x0000 }, /* R4119  - Write Sequencer 23 */
-	[4120] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4120  - Write Sequencer 24 */
-	[4121] = { 0x00FF, 0x00FF, 0x0000 }, /* R4121  - Write Sequencer 25 */
-	[4122] = { 0x070F, 0x070F, 0x0000 }, /* R4122  - Write Sequencer 26 */
-	[4123] = { 0x010F, 0x010F, 0x0000 }, /* R4123  - Write Sequencer 27 */
-	[4124] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4124  - Write Sequencer 28 */
-	[4125] = { 0x00FF, 0x00FF, 0x0000 }, /* R4125  - Write Sequencer 29 */
-	[4126] = { 0x070F, 0x070F, 0x0000 }, /* R4126  - Write Sequencer 30 */
-	[4127] = { 0x010F, 0x010F, 0x0000 }, /* R4127  - Write Sequencer 31 */
-	[4128] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4128  - Write Sequencer 32 */
-	[4129] = { 0x00FF, 0x00FF, 0x0000 }, /* R4129  - Write Sequencer 33 */
-	[4130] = { 0x070F, 0x070F, 0x0000 }, /* R4130  - Write Sequencer 34 */
-	[4131] = { 0x010F, 0x010F, 0x0000 }, /* R4131  - Write Sequencer 35 */
-	[4132] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4132  - Write Sequencer 36 */
-	[4133] = { 0x00FF, 0x00FF, 0x0000 }, /* R4133  - Write Sequencer 37 */
-	[4134] = { 0x070F, 0x070F, 0x0000 }, /* R4134  - Write Sequencer 38 */
-	[4135] = { 0x010F, 0x010F, 0x0000 }, /* R4135  - Write Sequencer 39 */
-	[4136] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4136  - Write Sequencer 40 */
-	[4137] = { 0x00FF, 0x00FF, 0x0000 }, /* R4137  - Write Sequencer 41 */
-	[4138] = { 0x070F, 0x070F, 0x0000 }, /* R4138  - Write Sequencer 42 */
-	[4139] = { 0x010F, 0x010F, 0x0000 }, /* R4139  - Write Sequencer 43 */
-	[4140] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4140  - Write Sequencer 44 */
-	[4141] = { 0x00FF, 0x00FF, 0x0000 }, /* R4141  - Write Sequencer 45 */
-	[4142] = { 0x070F, 0x070F, 0x0000 }, /* R4142  - Write Sequencer 46 */
-	[4143] = { 0x010F, 0x010F, 0x0000 }, /* R4143  - Write Sequencer 47 */
-	[4144] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4144  - Write Sequencer 48 */
-	[4145] = { 0x00FF, 0x00FF, 0x0000 }, /* R4145  - Write Sequencer 49 */
-	[4146] = { 0x070F, 0x070F, 0x0000 }, /* R4146  - Write Sequencer 50 */
-	[4147] = { 0x010F, 0x010F, 0x0000 }, /* R4147  - Write Sequencer 51 */
-	[4148] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4148  - Write Sequencer 52 */
-	[4149] = { 0x00FF, 0x00FF, 0x0000 }, /* R4149  - Write Sequencer 53 */
-	[4150] = { 0x070F, 0x070F, 0x0000 }, /* R4150  - Write Sequencer 54 */
-	[4151] = { 0x010F, 0x010F, 0x0000 }, /* R4151  - Write Sequencer 55 */
-	[4152] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4152  - Write Sequencer 56 */
-	[4153] = { 0x00FF, 0x00FF, 0x0000 }, /* R4153  - Write Sequencer 57 */
-	[4154] = { 0x070F, 0x070F, 0x0000 }, /* R4154  - Write Sequencer 58 */
-	[4155] = { 0x010F, 0x010F, 0x0000 }, /* R4155  - Write Sequencer 59 */
-	[4156] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4156  - Write Sequencer 60 */
-	[4157] = { 0x00FF, 0x00FF, 0x0000 }, /* R4157  - Write Sequencer 61 */
-	[4158] = { 0x070F, 0x070F, 0x0000 }, /* R4158  - Write Sequencer 62 */
-	[4159] = { 0x010F, 0x010F, 0x0000 }, /* R4159  - Write Sequencer 63 */
-	[4160] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4160  - Write Sequencer 64 */
-	[4161] = { 0x00FF, 0x00FF, 0x0000 }, /* R4161  - Write Sequencer 65 */
-	[4162] = { 0x070F, 0x070F, 0x0000 }, /* R4162  - Write Sequencer 66 */
-	[4163] = { 0x010F, 0x010F, 0x0000 }, /* R4163  - Write Sequencer 67 */
-	[4164] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4164  - Write Sequencer 68 */
-	[4165] = { 0x00FF, 0x00FF, 0x0000 }, /* R4165  - Write Sequencer 69 */
-	[4166] = { 0x070F, 0x070F, 0x0000 }, /* R4166  - Write Sequencer 70 */
-	[4167] = { 0x010F, 0x010F, 0x0000 }, /* R4167  - Write Sequencer 71 */
-	[4168] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4168  - Write Sequencer 72 */
-	[4169] = { 0x00FF, 0x00FF, 0x0000 }, /* R4169  - Write Sequencer 73 */
-	[4170] = { 0x070F, 0x070F, 0x0000 }, /* R4170  - Write Sequencer 74 */
-	[4171] = { 0x010F, 0x010F, 0x0000 }, /* R4171  - Write Sequencer 75 */
-	[4172] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4172  - Write Sequencer 76 */
-	[4173] = { 0x00FF, 0x00FF, 0x0000 }, /* R4173  - Write Sequencer 77 */
-	[4174] = { 0x070F, 0x070F, 0x0000 }, /* R4174  - Write Sequencer 78 */
-	[4175] = { 0x010F, 0x010F, 0x0000 }, /* R4175  - Write Sequencer 79 */
-	[4176] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4176  - Write Sequencer 80 */
-	[4177] = { 0x00FF, 0x00FF, 0x0000 }, /* R4177  - Write Sequencer 81 */
-	[4178] = { 0x070F, 0x070F, 0x0000 }, /* R4178  - Write Sequencer 82 */
-	[4179] = { 0x010F, 0x010F, 0x0000 }, /* R4179  - Write Sequencer 83 */
-	[4180] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4180  - Write Sequencer 84 */
-	[4181] = { 0x00FF, 0x00FF, 0x0000 }, /* R4181  - Write Sequencer 85 */
-	[4182] = { 0x070F, 0x070F, 0x0000 }, /* R4182  - Write Sequencer 86 */
-	[4183] = { 0x010F, 0x010F, 0x0000 }, /* R4183  - Write Sequencer 87 */
-	[4184] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4184  - Write Sequencer 88 */
-	[4185] = { 0x00FF, 0x00FF, 0x0000 }, /* R4185  - Write Sequencer 89 */
-	[4186] = { 0x070F, 0x070F, 0x0000 }, /* R4186  - Write Sequencer 90 */
-	[4187] = { 0x010F, 0x010F, 0x0000 }, /* R4187  - Write Sequencer 91 */
-	[4188] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4188  - Write Sequencer 92 */
-	[4189] = { 0x00FF, 0x00FF, 0x0000 }, /* R4189  - Write Sequencer 93 */
-	[4190] = { 0x070F, 0x070F, 0x0000 }, /* R4190  - Write Sequencer 94 */
-	[4191] = { 0x010F, 0x010F, 0x0000 }, /* R4191  - Write Sequencer 95 */
-	[4192] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4192  - Write Sequencer 96 */
-	[4193] = { 0x00FF, 0x00FF, 0x0000 }, /* R4193  - Write Sequencer 97 */
-	[4194] = { 0x070F, 0x070F, 0x0000 }, /* R4194  - Write Sequencer 98 */
-	[4195] = { 0x010F, 0x010F, 0x0000 }, /* R4195  - Write Sequencer 99 */
-	[4196] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4196  - Write Sequencer 100 */
-	[4197] = { 0x00FF, 0x00FF, 0x0000 }, /* R4197  - Write Sequencer 101 */
-	[4198] = { 0x070F, 0x070F, 0x0000 }, /* R4198  - Write Sequencer 102 */
-	[4199] = { 0x010F, 0x010F, 0x0000 }, /* R4199  - Write Sequencer 103 */
-	[4200] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4200  - Write Sequencer 104 */
-	[4201] = { 0x00FF, 0x00FF, 0x0000 }, /* R4201  - Write Sequencer 105 */
-	[4202] = { 0x070F, 0x070F, 0x0000 }, /* R4202  - Write Sequencer 106 */
-	[4203] = { 0x010F, 0x010F, 0x0000 }, /* R4203  - Write Sequencer 107 */
-	[4204] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4204  - Write Sequencer 108 */
-	[4205] = { 0x00FF, 0x00FF, 0x0000 }, /* R4205  - Write Sequencer 109 */
-	[4206] = { 0x070F, 0x070F, 0x0000 }, /* R4206  - Write Sequencer 110 */
-	[4207] = { 0x010F, 0x010F, 0x0000 }, /* R4207  - Write Sequencer 111 */
-	[4208] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4208  - Write Sequencer 112 */
-	[4209] = { 0x00FF, 0x00FF, 0x0000 }, /* R4209  - Write Sequencer 113 */
-	[4210] = { 0x070F, 0x070F, 0x0000 }, /* R4210  - Write Sequencer 114 */
-	[4211] = { 0x010F, 0x010F, 0x0000 }, /* R4211  - Write Sequencer 115 */
-	[4212] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4212  - Write Sequencer 116 */
-	[4213] = { 0x00FF, 0x00FF, 0x0000 }, /* R4213  - Write Sequencer 117 */
-	[4214] = { 0x070F, 0x070F, 0x0000 }, /* R4214  - Write Sequencer 118 */
-	[4215] = { 0x010F, 0x010F, 0x0000 }, /* R4215  - Write Sequencer 119 */
-	[4216] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4216  - Write Sequencer 120 */
-	[4217] = { 0x00FF, 0x00FF, 0x0000 }, /* R4217  - Write Sequencer 121 */
-	[4218] = { 0x070F, 0x070F, 0x0000 }, /* R4218  - Write Sequencer 122 */
-	[4219] = { 0x010F, 0x010F, 0x0000 }, /* R4219  - Write Sequencer 123 */
-	[4220] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4220  - Write Sequencer 124 */
-	[4221] = { 0x00FF, 0x00FF, 0x0000 }, /* R4221  - Write Sequencer 125 */
-	[4222] = { 0x070F, 0x070F, 0x0000 }, /* R4222  - Write Sequencer 126 */
-	[4223] = { 0x010F, 0x010F, 0x0000 }, /* R4223  - Write Sequencer 127 */
-	[4224] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4224  - Write Sequencer 128 */
-	[4225] = { 0x00FF, 0x00FF, 0x0000 }, /* R4225  - Write Sequencer 129 */
-	[4226] = { 0x070F, 0x070F, 0x0000 }, /* R4226  - Write Sequencer 130 */
-	[4227] = { 0x010F, 0x010F, 0x0000 }, /* R4227  - Write Sequencer 131 */
-	[4228] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4228  - Write Sequencer 132 */
-	[4229] = { 0x00FF, 0x00FF, 0x0000 }, /* R4229  - Write Sequencer 133 */
-	[4230] = { 0x070F, 0x070F, 0x0000 }, /* R4230  - Write Sequencer 134 */
-	[4231] = { 0x010F, 0x010F, 0x0000 }, /* R4231  - Write Sequencer 135 */
-	[4232] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4232  - Write Sequencer 136 */
-	[4233] = { 0x00FF, 0x00FF, 0x0000 }, /* R4233  - Write Sequencer 137 */
-	[4234] = { 0x070F, 0x070F, 0x0000 }, /* R4234  - Write Sequencer 138 */
-	[4235] = { 0x010F, 0x010F, 0x0000 }, /* R4235  - Write Sequencer 139 */
-	[4236] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4236  - Write Sequencer 140 */
-	[4237] = { 0x00FF, 0x00FF, 0x0000 }, /* R4237  - Write Sequencer 141 */
-	[4238] = { 0x070F, 0x070F, 0x0000 }, /* R4238  - Write Sequencer 142 */
-	[4239] = { 0x010F, 0x010F, 0x0000 }, /* R4239  - Write Sequencer 143 */
-	[4240] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4240  - Write Sequencer 144 */
-	[4241] = { 0x00FF, 0x00FF, 0x0000 }, /* R4241  - Write Sequencer 145 */
-	[4242] = { 0x070F, 0x070F, 0x0000 }, /* R4242  - Write Sequencer 146 */
-	[4243] = { 0x010F, 0x010F, 0x0000 }, /* R4243  - Write Sequencer 147 */
-	[4244] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4244  - Write Sequencer 148 */
-	[4245] = { 0x00FF, 0x00FF, 0x0000 }, /* R4245  - Write Sequencer 149 */
-	[4246] = { 0x070F, 0x070F, 0x0000 }, /* R4246  - Write Sequencer 150 */
-	[4247] = { 0x010F, 0x010F, 0x0000 }, /* R4247  - Write Sequencer 151 */
-	[4248] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4248  - Write Sequencer 152 */
-	[4249] = { 0x00FF, 0x00FF, 0x0000 }, /* R4249  - Write Sequencer 153 */
-	[4250] = { 0x070F, 0x070F, 0x0000 }, /* R4250  - Write Sequencer 154 */
-	[4251] = { 0x010F, 0x010F, 0x0000 }, /* R4251  - Write Sequencer 155 */
-	[4252] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4252  - Write Sequencer 156 */
-	[4253] = { 0x00FF, 0x00FF, 0x0000 }, /* R4253  - Write Sequencer 157 */
-	[4254] = { 0x070F, 0x070F, 0x0000 }, /* R4254  - Write Sequencer 158 */
-	[4255] = { 0x010F, 0x010F, 0x0000 }, /* R4255  - Write Sequencer 159 */
-	[4256] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4256  - Write Sequencer 160 */
-	[4257] = { 0x00FF, 0x00FF, 0x0000 }, /* R4257  - Write Sequencer 161 */
-	[4258] = { 0x070F, 0x070F, 0x0000 }, /* R4258  - Write Sequencer 162 */
-	[4259] = { 0x010F, 0x010F, 0x0000 }, /* R4259  - Write Sequencer 163 */
-	[4260] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4260  - Write Sequencer 164 */
-	[4261] = { 0x00FF, 0x00FF, 0x0000 }, /* R4261  - Write Sequencer 165 */
-	[4262] = { 0x070F, 0x070F, 0x0000 }, /* R4262  - Write Sequencer 166 */
-	[4263] = { 0x010F, 0x010F, 0x0000 }, /* R4263  - Write Sequencer 167 */
-	[4264] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4264  - Write Sequencer 168 */
-	[4265] = { 0x00FF, 0x00FF, 0x0000 }, /* R4265  - Write Sequencer 169 */
-	[4266] = { 0x070F, 0x070F, 0x0000 }, /* R4266  - Write Sequencer 170 */
-	[4267] = { 0x010F, 0x010F, 0x0000 }, /* R4267  - Write Sequencer 171 */
-	[4268] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4268  - Write Sequencer 172 */
-	[4269] = { 0x00FF, 0x00FF, 0x0000 }, /* R4269  - Write Sequencer 173 */
-	[4270] = { 0x070F, 0x070F, 0x0000 }, /* R4270  - Write Sequencer 174 */
-	[4271] = { 0x010F, 0x010F, 0x0000 }, /* R4271  - Write Sequencer 175 */
-	[4272] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4272  - Write Sequencer 176 */
-	[4273] = { 0x00FF, 0x00FF, 0x0000 }, /* R4273  - Write Sequencer 177 */
-	[4274] = { 0x070F, 0x070F, 0x0000 }, /* R4274  - Write Sequencer 178 */
-	[4275] = { 0x010F, 0x010F, 0x0000 }, /* R4275  - Write Sequencer 179 */
-	[4276] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4276  - Write Sequencer 180 */
-	[4277] = { 0x00FF, 0x00FF, 0x0000 }, /* R4277  - Write Sequencer 181 */
-	[4278] = { 0x070F, 0x070F, 0x0000 }, /* R4278  - Write Sequencer 182 */
-	[4279] = { 0x010F, 0x010F, 0x0000 }, /* R4279  - Write Sequencer 183 */
-	[4280] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4280  - Write Sequencer 184 */
-	[4281] = { 0x00FF, 0x00FF, 0x0000 }, /* R4281  - Write Sequencer 185 */
-	[4282] = { 0x070F, 0x070F, 0x0000 }, /* R4282  - Write Sequencer 186 */
-	[4283] = { 0x010F, 0x010F, 0x0000 }, /* R4283  - Write Sequencer 187 */
-	[4284] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4284  - Write Sequencer 188 */
-	[4285] = { 0x00FF, 0x00FF, 0x0000 }, /* R4285  - Write Sequencer 189 */
-	[4286] = { 0x070F, 0x070F, 0x0000 }, /* R4286  - Write Sequencer 190 */
-	[4287] = { 0x010F, 0x010F, 0x0000 }, /* R4287  - Write Sequencer 191 */
-	[4288] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4288  - Write Sequencer 192 */
-	[4289] = { 0x00FF, 0x00FF, 0x0000 }, /* R4289  - Write Sequencer 193 */
-	[4290] = { 0x070F, 0x070F, 0x0000 }, /* R4290  - Write Sequencer 194 */
-	[4291] = { 0x010F, 0x010F, 0x0000 }, /* R4291  - Write Sequencer 195 */
-	[4292] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4292  - Write Sequencer 196 */
-	[4293] = { 0x00FF, 0x00FF, 0x0000 }, /* R4293  - Write Sequencer 197 */
-	[4294] = { 0x070F, 0x070F, 0x0000 }, /* R4294  - Write Sequencer 198 */
-	[4295] = { 0x010F, 0x010F, 0x0000 }, /* R4295  - Write Sequencer 199 */
-	[4296] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4296  - Write Sequencer 200 */
-	[4297] = { 0x00FF, 0x00FF, 0x0000 }, /* R4297  - Write Sequencer 201 */
-	[4298] = { 0x070F, 0x070F, 0x0000 }, /* R4298  - Write Sequencer 202 */
-	[4299] = { 0x010F, 0x010F, 0x0000 }, /* R4299  - Write Sequencer 203 */
-	[4300] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4300  - Write Sequencer 204 */
-	[4301] = { 0x00FF, 0x00FF, 0x0000 }, /* R4301  - Write Sequencer 205 */
-	[4302] = { 0x070F, 0x070F, 0x0000 }, /* R4302  - Write Sequencer 206 */
-	[4303] = { 0x010F, 0x010F, 0x0000 }, /* R4303  - Write Sequencer 207 */
-	[4304] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4304  - Write Sequencer 208 */
-	[4305] = { 0x00FF, 0x00FF, 0x0000 }, /* R4305  - Write Sequencer 209 */
-	[4306] = { 0x070F, 0x070F, 0x0000 }, /* R4306  - Write Sequencer 210 */
-	[4307] = { 0x010F, 0x010F, 0x0000 }, /* R4307  - Write Sequencer 211 */
-	[4308] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4308  - Write Sequencer 212 */
-	[4309] = { 0x00FF, 0x00FF, 0x0000 }, /* R4309  - Write Sequencer 213 */
-	[4310] = { 0x070F, 0x070F, 0x0000 }, /* R4310  - Write Sequencer 214 */
-	[4311] = { 0x010F, 0x010F, 0x0000 }, /* R4311  - Write Sequencer 215 */
-	[4312] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4312  - Write Sequencer 216 */
-	[4313] = { 0x00FF, 0x00FF, 0x0000 }, /* R4313  - Write Sequencer 217 */
-	[4314] = { 0x070F, 0x070F, 0x0000 }, /* R4314  - Write Sequencer 218 */
-	[4315] = { 0x010F, 0x010F, 0x0000 }, /* R4315  - Write Sequencer 219 */
-	[4316] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4316  - Write Sequencer 220 */
-	[4317] = { 0x00FF, 0x00FF, 0x0000 }, /* R4317  - Write Sequencer 221 */
-	[4318] = { 0x070F, 0x070F, 0x0000 }, /* R4318  - Write Sequencer 222 */
-	[4319] = { 0x010F, 0x010F, 0x0000 }, /* R4319  - Write Sequencer 223 */
-	[4320] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4320  - Write Sequencer 224 */
-	[4321] = { 0x00FF, 0x00FF, 0x0000 }, /* R4321  - Write Sequencer 225 */
-	[4322] = { 0x070F, 0x070F, 0x0000 }, /* R4322  - Write Sequencer 226 */
-	[4323] = { 0x010F, 0x010F, 0x0000 }, /* R4323  - Write Sequencer 227 */
-	[4324] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4324  - Write Sequencer 228 */
-	[4325] = { 0x00FF, 0x00FF, 0x0000 }, /* R4325  - Write Sequencer 229 */
-	[4326] = { 0x070F, 0x070F, 0x0000 }, /* R4326  - Write Sequencer 230 */
-	[4327] = { 0x010F, 0x010F, 0x0000 }, /* R4327  - Write Sequencer 231 */
-	[4328] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4328  - Write Sequencer 232 */
-	[4329] = { 0x00FF, 0x00FF, 0x0000 }, /* R4329  - Write Sequencer 233 */
-	[4330] = { 0x070F, 0x070F, 0x0000 }, /* R4330  - Write Sequencer 234 */
-	[4331] = { 0x010F, 0x010F, 0x0000 }, /* R4331  - Write Sequencer 235 */
-	[4332] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4332  - Write Sequencer 236 */
-	[4333] = { 0x00FF, 0x00FF, 0x0000 }, /* R4333  - Write Sequencer 237 */
-	[4334] = { 0x070F, 0x070F, 0x0000 }, /* R4334  - Write Sequencer 238 */
-	[4335] = { 0x010F, 0x010F, 0x0000 }, /* R4335  - Write Sequencer 239 */
-	[4336] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4336  - Write Sequencer 240 */
-	[4337] = { 0x00FF, 0x00FF, 0x0000 }, /* R4337  - Write Sequencer 241 */
-	[4338] = { 0x070F, 0x070F, 0x0000 }, /* R4338  - Write Sequencer 242 */
-	[4339] = { 0x010F, 0x010F, 0x0000 }, /* R4339  - Write Sequencer 243 */
-	[4340] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4340  - Write Sequencer 244 */
-	[4341] = { 0x00FF, 0x00FF, 0x0000 }, /* R4341  - Write Sequencer 245 */
-	[4342] = { 0x070F, 0x070F, 0x0000 }, /* R4342  - Write Sequencer 246 */
-	[4343] = { 0x010F, 0x010F, 0x0000 }, /* R4343  - Write Sequencer 247 */
-	[4344] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4344  - Write Sequencer 248 */
-	[4345] = { 0x00FF, 0x00FF, 0x0000 }, /* R4345  - Write Sequencer 249 */
-	[4346] = { 0x070F, 0x070F, 0x0000 }, /* R4346  - Write Sequencer 250 */
-	[4347] = { 0x010F, 0x010F, 0x0000 }, /* R4347  - Write Sequencer 251 */
-	[4348] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4348  - Write Sequencer 252 */
-	[4349] = { 0x00FF, 0x00FF, 0x0000 }, /* R4349  - Write Sequencer 253 */
-	[4350] = { 0x070F, 0x070F, 0x0000 }, /* R4350  - Write Sequencer 254 */
-	[4351] = { 0x010F, 0x010F, 0x0000 }, /* R4351  - Write Sequencer 255 */
-	[4352] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4352  - Write Sequencer 256 */
-	[4353] = { 0x00FF, 0x00FF, 0x0000 }, /* R4353  - Write Sequencer 257 */
-	[4354] = { 0x070F, 0x070F, 0x0000 }, /* R4354  - Write Sequencer 258 */
-	[4355] = { 0x010F, 0x010F, 0x0000 }, /* R4355  - Write Sequencer 259 */
-	[4356] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4356  - Write Sequencer 260 */
-	[4357] = { 0x00FF, 0x00FF, 0x0000 }, /* R4357  - Write Sequencer 261 */
-	[4358] = { 0x070F, 0x070F, 0x0000 }, /* R4358  - Write Sequencer 262 */
-	[4359] = { 0x010F, 0x010F, 0x0000 }, /* R4359  - Write Sequencer 263 */
-	[4360] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4360  - Write Sequencer 264 */
-	[4361] = { 0x00FF, 0x00FF, 0x0000 }, /* R4361  - Write Sequencer 265 */
-	[4362] = { 0x070F, 0x070F, 0x0000 }, /* R4362  - Write Sequencer 266 */
-	[4363] = { 0x010F, 0x010F, 0x0000 }, /* R4363  - Write Sequencer 267 */
-	[4364] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4364  - Write Sequencer 268 */
-	[4365] = { 0x00FF, 0x00FF, 0x0000 }, /* R4365  - Write Sequencer 269 */
-	[4366] = { 0x070F, 0x070F, 0x0000 }, /* R4366  - Write Sequencer 270 */
-	[4367] = { 0x010F, 0x010F, 0x0000 }, /* R4367  - Write Sequencer 271 */
-	[4368] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4368  - Write Sequencer 272 */
-	[4369] = { 0x00FF, 0x00FF, 0x0000 }, /* R4369  - Write Sequencer 273 */
-	[4370] = { 0x070F, 0x070F, 0x0000 }, /* R4370  - Write Sequencer 274 */
-	[4371] = { 0x010F, 0x010F, 0x0000 }, /* R4371  - Write Sequencer 275 */
-	[4372] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4372  - Write Sequencer 276 */
-	[4373] = { 0x00FF, 0x00FF, 0x0000 }, /* R4373  - Write Sequencer 277 */
-	[4374] = { 0x070F, 0x070F, 0x0000 }, /* R4374  - Write Sequencer 278 */
-	[4375] = { 0x010F, 0x010F, 0x0000 }, /* R4375  - Write Sequencer 279 */
-	[4376] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4376  - Write Sequencer 280 */
-	[4377] = { 0x00FF, 0x00FF, 0x0000 }, /* R4377  - Write Sequencer 281 */
-	[4378] = { 0x070F, 0x070F, 0x0000 }, /* R4378  - Write Sequencer 282 */
-	[4379] = { 0x010F, 0x010F, 0x0000 }, /* R4379  - Write Sequencer 283 */
-	[4380] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4380  - Write Sequencer 284 */
-	[4381] = { 0x00FF, 0x00FF, 0x0000 }, /* R4381  - Write Sequencer 285 */
-	[4382] = { 0x070F, 0x070F, 0x0000 }, /* R4382  - Write Sequencer 286 */
-	[4383] = { 0x010F, 0x010F, 0x0000 }, /* R4383  - Write Sequencer 287 */
-	[4384] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4384  - Write Sequencer 288 */
-	[4385] = { 0x00FF, 0x00FF, 0x0000 }, /* R4385  - Write Sequencer 289 */
-	[4386] = { 0x070F, 0x070F, 0x0000 }, /* R4386  - Write Sequencer 290 */
-	[4387] = { 0x010F, 0x010F, 0x0000 }, /* R4387  - Write Sequencer 291 */
-	[4388] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4388  - Write Sequencer 292 */
-	[4389] = { 0x00FF, 0x00FF, 0x0000 }, /* R4389  - Write Sequencer 293 */
-	[4390] = { 0x070F, 0x070F, 0x0000 }, /* R4390  - Write Sequencer 294 */
-	[4391] = { 0x010F, 0x010F, 0x0000 }, /* R4391  - Write Sequencer 295 */
-	[4392] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4392  - Write Sequencer 296 */
-	[4393] = { 0x00FF, 0x00FF, 0x0000 }, /* R4393  - Write Sequencer 297 */
-	[4394] = { 0x070F, 0x070F, 0x0000 }, /* R4394  - Write Sequencer 298 */
-	[4395] = { 0x010F, 0x010F, 0x0000 }, /* R4395  - Write Sequencer 299 */
-	[4396] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4396  - Write Sequencer 300 */
-	[4397] = { 0x00FF, 0x00FF, 0x0000 }, /* R4397  - Write Sequencer 301 */
-	[4398] = { 0x070F, 0x070F, 0x0000 }, /* R4398  - Write Sequencer 302 */
-	[4399] = { 0x010F, 0x010F, 0x0000 }, /* R4399  - Write Sequencer 303 */
-	[4400] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4400  - Write Sequencer 304 */
-	[4401] = { 0x00FF, 0x00FF, 0x0000 }, /* R4401  - Write Sequencer 305 */
-	[4402] = { 0x070F, 0x070F, 0x0000 }, /* R4402  - Write Sequencer 306 */
-	[4403] = { 0x010F, 0x010F, 0x0000 }, /* R4403  - Write Sequencer 307 */
-	[4404] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4404  - Write Sequencer 308 */
-	[4405] = { 0x00FF, 0x00FF, 0x0000 }, /* R4405  - Write Sequencer 309 */
-	[4406] = { 0x070F, 0x070F, 0x0000 }, /* R4406  - Write Sequencer 310 */
-	[4407] = { 0x010F, 0x010F, 0x0000 }, /* R4407  - Write Sequencer 311 */
-	[4408] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4408  - Write Sequencer 312 */
-	[4409] = { 0x00FF, 0x00FF, 0x0000 }, /* R4409  - Write Sequencer 313 */
-	[4410] = { 0x070F, 0x070F, 0x0000 }, /* R4410  - Write Sequencer 314 */
-	[4411] = { 0x010F, 0x010F, 0x0000 }, /* R4411  - Write Sequencer 315 */
-	[4412] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4412  - Write Sequencer 316 */
-	[4413] = { 0x00FF, 0x00FF, 0x0000 }, /* R4413  - Write Sequencer 317 */
-	[4414] = { 0x070F, 0x070F, 0x0000 }, /* R4414  - Write Sequencer 318 */
-	[4415] = { 0x010F, 0x010F, 0x0000 }, /* R4415  - Write Sequencer 319 */
-	[4416] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4416  - Write Sequencer 320 */
-	[4417] = { 0x00FF, 0x00FF, 0x0000 }, /* R4417  - Write Sequencer 321 */
-	[4418] = { 0x070F, 0x070F, 0x0000 }, /* R4418  - Write Sequencer 322 */
-	[4419] = { 0x010F, 0x010F, 0x0000 }, /* R4419  - Write Sequencer 323 */
-	[4420] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4420  - Write Sequencer 324 */
-	[4421] = { 0x00FF, 0x00FF, 0x0000 }, /* R4421  - Write Sequencer 325 */
-	[4422] = { 0x070F, 0x070F, 0x0000 }, /* R4422  - Write Sequencer 326 */
-	[4423] = { 0x010F, 0x010F, 0x0000 }, /* R4423  - Write Sequencer 327 */
-	[4424] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4424  - Write Sequencer 328 */
-	[4425] = { 0x00FF, 0x00FF, 0x0000 }, /* R4425  - Write Sequencer 329 */
-	[4426] = { 0x070F, 0x070F, 0x0000 }, /* R4426  - Write Sequencer 330 */
-	[4427] = { 0x010F, 0x010F, 0x0000 }, /* R4427  - Write Sequencer 331 */
-	[4428] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4428  - Write Sequencer 332 */
-	[4429] = { 0x00FF, 0x00FF, 0x0000 }, /* R4429  - Write Sequencer 333 */
-	[4430] = { 0x070F, 0x070F, 0x0000 }, /* R4430  - Write Sequencer 334 */
-	[4431] = { 0x010F, 0x010F, 0x0000 }, /* R4431  - Write Sequencer 335 */
-	[4432] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4432  - Write Sequencer 336 */
-	[4433] = { 0x00FF, 0x00FF, 0x0000 }, /* R4433  - Write Sequencer 337 */
-	[4434] = { 0x070F, 0x070F, 0x0000 }, /* R4434  - Write Sequencer 338 */
-	[4435] = { 0x010F, 0x010F, 0x0000 }, /* R4435  - Write Sequencer 339 */
-	[4436] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4436  - Write Sequencer 340 */
-	[4437] = { 0x00FF, 0x00FF, 0x0000 }, /* R4437  - Write Sequencer 341 */
-	[4438] = { 0x070F, 0x070F, 0x0000 }, /* R4438  - Write Sequencer 342 */
-	[4439] = { 0x010F, 0x010F, 0x0000 }, /* R4439  - Write Sequencer 343 */
-	[4440] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4440  - Write Sequencer 344 */
-	[4441] = { 0x00FF, 0x00FF, 0x0000 }, /* R4441  - Write Sequencer 345 */
-	[4442] = { 0x070F, 0x070F, 0x0000 }, /* R4442  - Write Sequencer 346 */
-	[4443] = { 0x010F, 0x010F, 0x0000 }, /* R4443  - Write Sequencer 347 */
-	[4444] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4444  - Write Sequencer 348 */
-	[4445] = { 0x00FF, 0x00FF, 0x0000 }, /* R4445  - Write Sequencer 349 */
-	[4446] = { 0x070F, 0x070F, 0x0000 }, /* R4446  - Write Sequencer 350 */
-	[4447] = { 0x010F, 0x010F, 0x0000 }, /* R4447  - Write Sequencer 351 */
-	[4448] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4448  - Write Sequencer 352 */
-	[4449] = { 0x00FF, 0x00FF, 0x0000 }, /* R4449  - Write Sequencer 353 */
-	[4450] = { 0x070F, 0x070F, 0x0000 }, /* R4450  - Write Sequencer 354 */
-	[4451] = { 0x010F, 0x010F, 0x0000 }, /* R4451  - Write Sequencer 355 */
-	[4452] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4452  - Write Sequencer 356 */
-	[4453] = { 0x00FF, 0x00FF, 0x0000 }, /* R4453  - Write Sequencer 357 */
-	[4454] = { 0x070F, 0x070F, 0x0000 }, /* R4454  - Write Sequencer 358 */
-	[4455] = { 0x010F, 0x010F, 0x0000 }, /* R4455  - Write Sequencer 359 */
-	[4456] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4456  - Write Sequencer 360 */
-	[4457] = { 0x00FF, 0x00FF, 0x0000 }, /* R4457  - Write Sequencer 361 */
-	[4458] = { 0x070F, 0x070F, 0x0000 }, /* R4458  - Write Sequencer 362 */
-	[4459] = { 0x010F, 0x010F, 0x0000 }, /* R4459  - Write Sequencer 363 */
-	[4460] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4460  - Write Sequencer 364 */
-	[4461] = { 0x00FF, 0x00FF, 0x0000 }, /* R4461  - Write Sequencer 365 */
-	[4462] = { 0x070F, 0x070F, 0x0000 }, /* R4462  - Write Sequencer 366 */
-	[4463] = { 0x010F, 0x010F, 0x0000 }, /* R4463  - Write Sequencer 367 */
-	[4464] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4464  - Write Sequencer 368 */
-	[4465] = { 0x00FF, 0x00FF, 0x0000 }, /* R4465  - Write Sequencer 369 */
-	[4466] = { 0x070F, 0x070F, 0x0000 }, /* R4466  - Write Sequencer 370 */
-	[4467] = { 0x010F, 0x010F, 0x0000 }, /* R4467  - Write Sequencer 371 */
-	[4468] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4468  - Write Sequencer 372 */
-	[4469] = { 0x00FF, 0x00FF, 0x0000 }, /* R4469  - Write Sequencer 373 */
-	[4470] = { 0x070F, 0x070F, 0x0000 }, /* R4470  - Write Sequencer 374 */
-	[4471] = { 0x010F, 0x010F, 0x0000 }, /* R4471  - Write Sequencer 375 */
-	[4472] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4472  - Write Sequencer 376 */
-	[4473] = { 0x00FF, 0x00FF, 0x0000 }, /* R4473  - Write Sequencer 377 */
-	[4474] = { 0x070F, 0x070F, 0x0000 }, /* R4474  - Write Sequencer 378 */
-	[4475] = { 0x010F, 0x010F, 0x0000 }, /* R4475  - Write Sequencer 379 */
-	[4476] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4476  - Write Sequencer 380 */
-	[4477] = { 0x00FF, 0x00FF, 0x0000 }, /* R4477  - Write Sequencer 381 */
-	[4478] = { 0x070F, 0x070F, 0x0000 }, /* R4478  - Write Sequencer 382 */
-	[4479] = { 0x010F, 0x010F, 0x0000 }, /* R4479  - Write Sequencer 383 */
-	[4480] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4480  - Write Sequencer 384 */
-	[4481] = { 0x00FF, 0x00FF, 0x0000 }, /* R4481  - Write Sequencer 385 */
-	[4482] = { 0x070F, 0x070F, 0x0000 }, /* R4482  - Write Sequencer 386 */
-	[4483] = { 0x010F, 0x010F, 0x0000 }, /* R4483  - Write Sequencer 387 */
-	[4484] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4484  - Write Sequencer 388 */
-	[4485] = { 0x00FF, 0x00FF, 0x0000 }, /* R4485  - Write Sequencer 389 */
-	[4486] = { 0x070F, 0x070F, 0x0000 }, /* R4486  - Write Sequencer 390 */
-	[4487] = { 0x010F, 0x010F, 0x0000 }, /* R4487  - Write Sequencer 391 */
-	[4488] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4488  - Write Sequencer 392 */
-	[4489] = { 0x00FF, 0x00FF, 0x0000 }, /* R4489  - Write Sequencer 393 */
-	[4490] = { 0x070F, 0x070F, 0x0000 }, /* R4490  - Write Sequencer 394 */
-	[4491] = { 0x010F, 0x010F, 0x0000 }, /* R4491  - Write Sequencer 395 */
-	[4492] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4492  - Write Sequencer 396 */
-	[4493] = { 0x00FF, 0x00FF, 0x0000 }, /* R4493  - Write Sequencer 397 */
-	[4494] = { 0x070F, 0x070F, 0x0000 }, /* R4494  - Write Sequencer 398 */
-	[4495] = { 0x010F, 0x010F, 0x0000 }, /* R4495  - Write Sequencer 399 */
-	[4496] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4496  - Write Sequencer 400 */
-	[4497] = { 0x00FF, 0x00FF, 0x0000 }, /* R4497  - Write Sequencer 401 */
-	[4498] = { 0x070F, 0x070F, 0x0000 }, /* R4498  - Write Sequencer 402 */
-	[4499] = { 0x010F, 0x010F, 0x0000 }, /* R4499  - Write Sequencer 403 */
-	[4500] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4500  - Write Sequencer 404 */
-	[4501] = { 0x00FF, 0x00FF, 0x0000 }, /* R4501  - Write Sequencer 405 */
-	[4502] = { 0x070F, 0x070F, 0x0000 }, /* R4502  - Write Sequencer 406 */
-	[4503] = { 0x010F, 0x010F, 0x0000 }, /* R4503  - Write Sequencer 407 */
-	[4504] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4504  - Write Sequencer 408 */
-	[4505] = { 0x00FF, 0x00FF, 0x0000 }, /* R4505  - Write Sequencer 409 */
-	[4506] = { 0x070F, 0x070F, 0x0000 }, /* R4506  - Write Sequencer 410 */
-	[4507] = { 0x010F, 0x010F, 0x0000 }, /* R4507  - Write Sequencer 411 */
-	[4508] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4508  - Write Sequencer 412 */
-	[4509] = { 0x00FF, 0x00FF, 0x0000 }, /* R4509  - Write Sequencer 413 */
-	[4510] = { 0x070F, 0x070F, 0x0000 }, /* R4510  - Write Sequencer 414 */
-	[4511] = { 0x010F, 0x010F, 0x0000 }, /* R4511  - Write Sequencer 415 */
-	[4512] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4512  - Write Sequencer 416 */
-	[4513] = { 0x00FF, 0x00FF, 0x0000 }, /* R4513  - Write Sequencer 417 */
-	[4514] = { 0x070F, 0x070F, 0x0000 }, /* R4514  - Write Sequencer 418 */
-	[4515] = { 0x010F, 0x010F, 0x0000 }, /* R4515  - Write Sequencer 419 */
-	[4516] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4516  - Write Sequencer 420 */
-	[4517] = { 0x00FF, 0x00FF, 0x0000 }, /* R4517  - Write Sequencer 421 */
-	[4518] = { 0x070F, 0x070F, 0x0000 }, /* R4518  - Write Sequencer 422 */
-	[4519] = { 0x010F, 0x010F, 0x0000 }, /* R4519  - Write Sequencer 423 */
-	[4520] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4520  - Write Sequencer 424 */
-	[4521] = { 0x00FF, 0x00FF, 0x0000 }, /* R4521  - Write Sequencer 425 */
-	[4522] = { 0x070F, 0x070F, 0x0000 }, /* R4522  - Write Sequencer 426 */
-	[4523] = { 0x010F, 0x010F, 0x0000 }, /* R4523  - Write Sequencer 427 */
-	[4524] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4524  - Write Sequencer 428 */
-	[4525] = { 0x00FF, 0x00FF, 0x0000 }, /* R4525  - Write Sequencer 429 */
-	[4526] = { 0x070F, 0x070F, 0x0000 }, /* R4526  - Write Sequencer 430 */
-	[4527] = { 0x010F, 0x010F, 0x0000 }, /* R4527  - Write Sequencer 431 */
-	[4528] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4528  - Write Sequencer 432 */
-	[4529] = { 0x00FF, 0x00FF, 0x0000 }, /* R4529  - Write Sequencer 433 */
-	[4530] = { 0x070F, 0x070F, 0x0000 }, /* R4530  - Write Sequencer 434 */
-	[4531] = { 0x010F, 0x010F, 0x0000 }, /* R4531  - Write Sequencer 435 */
-	[4532] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4532  - Write Sequencer 436 */
-	[4533] = { 0x00FF, 0x00FF, 0x0000 }, /* R4533  - Write Sequencer 437 */
-	[4534] = { 0x070F, 0x070F, 0x0000 }, /* R4534  - Write Sequencer 438 */
-	[4535] = { 0x010F, 0x010F, 0x0000 }, /* R4535  - Write Sequencer 439 */
-	[4536] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4536  - Write Sequencer 440 */
-	[4537] = { 0x00FF, 0x00FF, 0x0000 }, /* R4537  - Write Sequencer 441 */
-	[4538] = { 0x070F, 0x070F, 0x0000 }, /* R4538  - Write Sequencer 442 */
-	[4539] = { 0x010F, 0x010F, 0x0000 }, /* R4539  - Write Sequencer 443 */
-	[4540] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4540  - Write Sequencer 444 */
-	[4541] = { 0x00FF, 0x00FF, 0x0000 }, /* R4541  - Write Sequencer 445 */
-	[4542] = { 0x070F, 0x070F, 0x0000 }, /* R4542  - Write Sequencer 446 */
-	[4543] = { 0x010F, 0x010F, 0x0000 }, /* R4543  - Write Sequencer 447 */
-	[4544] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4544  - Write Sequencer 448 */
-	[4545] = { 0x00FF, 0x00FF, 0x0000 }, /* R4545  - Write Sequencer 449 */
-	[4546] = { 0x070F, 0x070F, 0x0000 }, /* R4546  - Write Sequencer 450 */
-	[4547] = { 0x010F, 0x010F, 0x0000 }, /* R4547  - Write Sequencer 451 */
-	[4548] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4548  - Write Sequencer 452 */
-	[4549] = { 0x00FF, 0x00FF, 0x0000 }, /* R4549  - Write Sequencer 453 */
-	[4550] = { 0x070F, 0x070F, 0x0000 }, /* R4550  - Write Sequencer 454 */
-	[4551] = { 0x010F, 0x010F, 0x0000 }, /* R4551  - Write Sequencer 455 */
-	[4552] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4552  - Write Sequencer 456 */
-	[4553] = { 0x00FF, 0x00FF, 0x0000 }, /* R4553  - Write Sequencer 457 */
-	[4554] = { 0x070F, 0x070F, 0x0000 }, /* R4554  - Write Sequencer 458 */
-	[4555] = { 0x010F, 0x010F, 0x0000 }, /* R4555  - Write Sequencer 459 */
-	[4556] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4556  - Write Sequencer 460 */
-	[4557] = { 0x00FF, 0x00FF, 0x0000 }, /* R4557  - Write Sequencer 461 */
-	[4558] = { 0x070F, 0x070F, 0x0000 }, /* R4558  - Write Sequencer 462 */
-	[4559] = { 0x010F, 0x010F, 0x0000 }, /* R4559  - Write Sequencer 463 */
-	[4560] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4560  - Write Sequencer 464 */
-	[4561] = { 0x00FF, 0x00FF, 0x0000 }, /* R4561  - Write Sequencer 465 */
-	[4562] = { 0x070F, 0x070F, 0x0000 }, /* R4562  - Write Sequencer 466 */
-	[4563] = { 0x010F, 0x010F, 0x0000 }, /* R4563  - Write Sequencer 467 */
-	[4564] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4564  - Write Sequencer 468 */
-	[4565] = { 0x00FF, 0x00FF, 0x0000 }, /* R4565  - Write Sequencer 469 */
-	[4566] = { 0x070F, 0x070F, 0x0000 }, /* R4566  - Write Sequencer 470 */
-	[4567] = { 0x010F, 0x010F, 0x0000 }, /* R4567  - Write Sequencer 471 */
-	[4568] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4568  - Write Sequencer 472 */
-	[4569] = { 0x00FF, 0x00FF, 0x0000 }, /* R4569  - Write Sequencer 473 */
-	[4570] = { 0x070F, 0x070F, 0x0000 }, /* R4570  - Write Sequencer 474 */
-	[4571] = { 0x010F, 0x010F, 0x0000 }, /* R4571  - Write Sequencer 475 */
-	[4572] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4572  - Write Sequencer 476 */
-	[4573] = { 0x00FF, 0x00FF, 0x0000 }, /* R4573  - Write Sequencer 477 */
-	[4574] = { 0x070F, 0x070F, 0x0000 }, /* R4574  - Write Sequencer 478 */
-	[4575] = { 0x010F, 0x010F, 0x0000 }, /* R4575  - Write Sequencer 479 */
-	[4576] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4576  - Write Sequencer 480 */
-	[4577] = { 0x00FF, 0x00FF, 0x0000 }, /* R4577  - Write Sequencer 481 */
-	[4578] = { 0x070F, 0x070F, 0x0000 }, /* R4578  - Write Sequencer 482 */
-	[4579] = { 0x010F, 0x010F, 0x0000 }, /* R4579  - Write Sequencer 483 */
-	[4580] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4580  - Write Sequencer 484 */
-	[4581] = { 0x00FF, 0x00FF, 0x0000 }, /* R4581  - Write Sequencer 485 */
-	[4582] = { 0x070F, 0x070F, 0x0000 }, /* R4582  - Write Sequencer 486 */
-	[4583] = { 0x010F, 0x010F, 0x0000 }, /* R4583  - Write Sequencer 487 */
-	[4584] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4584  - Write Sequencer 488 */
-	[4585] = { 0x00FF, 0x00FF, 0x0000 }, /* R4585  - Write Sequencer 489 */
-	[4586] = { 0x070F, 0x070F, 0x0000 }, /* R4586  - Write Sequencer 490 */
-	[4587] = { 0x010F, 0x010F, 0x0000 }, /* R4587  - Write Sequencer 491 */
-	[4588] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4588  - Write Sequencer 492 */
-	[4589] = { 0x00FF, 0x00FF, 0x0000 }, /* R4589  - Write Sequencer 493 */
-	[4590] = { 0x070F, 0x070F, 0x0000 }, /* R4590  - Write Sequencer 494 */
-	[4591] = { 0x010F, 0x010F, 0x0000 }, /* R4591  - Write Sequencer 495 */
-	[4592] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4592  - Write Sequencer 496 */
-	[4593] = { 0x00FF, 0x00FF, 0x0000 }, /* R4593  - Write Sequencer 497 */
-	[4594] = { 0x070F, 0x070F, 0x0000 }, /* R4594  - Write Sequencer 498 */
-	[4595] = { 0x010F, 0x010F, 0x0000 }, /* R4595  - Write Sequencer 499 */
-	[4596] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4596  - Write Sequencer 500 */
-	[4597] = { 0x00FF, 0x00FF, 0x0000 }, /* R4597  - Write Sequencer 501 */
-	[4598] = { 0x070F, 0x070F, 0x0000 }, /* R4598  - Write Sequencer 502 */
-	[4599] = { 0x010F, 0x010F, 0x0000 }, /* R4599  - Write Sequencer 503 */
-	[4600] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4600  - Write Sequencer 504 */
-	[4601] = { 0x00FF, 0x00FF, 0x0000 }, /* R4601  - Write Sequencer 505 */
-	[4602] = { 0x070F, 0x070F, 0x0000 }, /* R4602  - Write Sequencer 506 */
-	[4603] = { 0x010F, 0x010F, 0x0000 }, /* R4603  - Write Sequencer 507 */
-	[4604] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4604  - Write Sequencer 508 */
-	[4605] = { 0x00FF, 0x00FF, 0x0000 }, /* R4605  - Write Sequencer 509 */
-	[4606] = { 0x070F, 0x070F, 0x0000 }, /* R4606  - Write Sequencer 510 */
-	[4607] = { 0x010F, 0x010F, 0x0000 }, /* R4607  - Write Sequencer 511 */
-	[8192] = { 0x03FF, 0x03FF, 0x0000 }, /* R8192  - DSP2 Instruction RAM 0 */
-	[9216] = { 0x003F, 0x003F, 0x0000 }, /* R9216  - DSP2 Address RAM 2 */
-	[9217] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9217  - DSP2 Address RAM 1 */
-	[9218] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9218  - DSP2 Address RAM 0 */
-	[12288] = { 0x00FF, 0x00FF, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */
-	[12289] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */
-	[13312] = { 0x00FF, 0x00FF, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */
-	[13313] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */
-	[14336] = { 0x00FF, 0x00FF, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */
-	[14337] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */
-	[15360] = { 0x07FF, 0x07FF, 0x0000 }, /* R15360 - DSP2 Coeff RAM 0 */
-	[16384] = { 0x00FF, 0x00FF, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
-	[16385] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
-	[16386] = { 0x00FF, 0x00FF, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
-	[16387] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
-	[16388] = { 0x00FF, 0x00FF, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */
-	[16389] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */
-	[16896] = { 0x00FF, 0x00FF, 0x0000 }, /* R16896 - HDBASS_AI_1 */
-	[16897] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16897 - HDBASS_AI_0 */
-	[16898] = { 0x00FF, 0x00FF, 0x0000 }, /* R16898 - HDBASS_AR_1 */
-	[16899] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16899 - HDBASS_AR_0 */
-	[16900] = { 0x00FF, 0x00FF, 0x0000 }, /* R16900 - HDBASS_B_1 */
-	[16901] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16901 - HDBASS_B_0 */
-	[16902] = { 0x00FF, 0x00FF, 0x0000 }, /* R16902 - HDBASS_K_1 */
-	[16903] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16903 - HDBASS_K_0 */
-	[16904] = { 0x00FF, 0x00FF, 0x0000 }, /* R16904 - HDBASS_N1_1 */
-	[16905] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16905 - HDBASS_N1_0 */
-	[16906] = { 0x00FF, 0x00FF, 0x0000 }, /* R16906 - HDBASS_N2_1 */
-	[16907] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16907 - HDBASS_N2_0 */
-	[16908] = { 0x00FF, 0x00FF, 0x0000 }, /* R16908 - HDBASS_N3_1 */
-	[16909] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16909 - HDBASS_N3_0 */
-	[16910] = { 0x00FF, 0x00FF, 0x0000 }, /* R16910 - HDBASS_N4_1 */
-	[16911] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16911 - HDBASS_N4_0 */
-	[16912] = { 0x00FF, 0x00FF, 0x0000 }, /* R16912 - HDBASS_N5_1 */
-	[16913] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16913 - HDBASS_N5_0 */
-	[16914] = { 0x00FF, 0x00FF, 0x0000 }, /* R16914 - HDBASS_X1_1 */
-	[16915] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16915 - HDBASS_X1_0 */
-	[16916] = { 0x00FF, 0x00FF, 0x0000 }, /* R16916 - HDBASS_X2_1 */
-	[16917] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16917 - HDBASS_X2_0 */
-	[16918] = { 0x00FF, 0x00FF, 0x0000 }, /* R16918 - HDBASS_X3_1 */
-	[16919] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16919 - HDBASS_X3_0 */
-	[16920] = { 0x00FF, 0x00FF, 0x0000 }, /* R16920 - HDBASS_ATK_1 */
-	[16921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16921 - HDBASS_ATK_0 */
-	[16922] = { 0x00FF, 0x00FF, 0x0000 }, /* R16922 - HDBASS_DCY_1 */
-	[16923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16923 - HDBASS_DCY_0 */
-	[16924] = { 0x00FF, 0x00FF, 0x0000 }, /* R16924 - HDBASS_PG_1 */
-	[16925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16925 - HDBASS_PG_0 */
-	[17408] = { 0x00FF, 0x00FF, 0x0000 }, /* R17408 - HPF_C_1 */
-	[17409] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17409 - HPF_C_0 */
-	[17920] = { 0x00FF, 0x00FF, 0x0000 }, /* R17920 - ADCL_RETUNE_C1_1 */
-	[17921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17921 - ADCL_RETUNE_C1_0 */
-	[17922] = { 0x00FF, 0x00FF, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */
-	[17923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */
-	[17924] = { 0x00FF, 0x00FF, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */
-	[17925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */
-	[17926] = { 0x00FF, 0x00FF, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */
-	[17927] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */
-	[17928] = { 0x00FF, 0x00FF, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */
-	[17929] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */
-	[17930] = { 0x00FF, 0x00FF, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */
-	[17931] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */
-	[17932] = { 0x00FF, 0x00FF, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */
-	[17933] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */
-	[17934] = { 0x00FF, 0x00FF, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */
-	[17935] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */
-	[17936] = { 0x00FF, 0x00FF, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */
-	[17937] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */
-	[17938] = { 0x00FF, 0x00FF, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */
-	[17939] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */
-	[17940] = { 0x00FF, 0x00FF, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */
-	[17941] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */
-	[17942] = { 0x00FF, 0x00FF, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */
-	[17943] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */
-	[17944] = { 0x00FF, 0x00FF, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */
-	[17945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */
-	[17946] = { 0x00FF, 0x00FF, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */
-	[17947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */
-	[17948] = { 0x00FF, 0x00FF, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */
-	[17949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */
-	[17950] = { 0x00FF, 0x00FF, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */
-	[17951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */
-	[17952] = { 0x00FF, 0x00FF, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */
-	[17953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */
-	[17954] = { 0x00FF, 0x00FF, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */
-	[17955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */
-	[17956] = { 0x00FF, 0x00FF, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */
-	[17957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */
-	[17958] = { 0x00FF, 0x00FF, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */
-	[17959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */
-	[17960] = { 0x00FF, 0x00FF, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */
-	[17961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */
-	[17962] = { 0x00FF, 0x00FF, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */
-	[17963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */
-	[17964] = { 0x00FF, 0x00FF, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */
-	[17965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */
-	[17966] = { 0x00FF, 0x00FF, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */
-	[17967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */
-	[17968] = { 0x00FF, 0x00FF, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */
-	[17969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */
-	[17970] = { 0x00FF, 0x00FF, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */
-	[17971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */
-	[17972] = { 0x00FF, 0x00FF, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */
-	[17973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */
-	[17974] = { 0x00FF, 0x00FF, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */
-	[17975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */
-	[17976] = { 0x00FF, 0x00FF, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */
-	[17977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */
-	[17978] = { 0x00FF, 0x00FF, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */
-	[17979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */
-	[17980] = { 0x00FF, 0x00FF, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */
-	[17981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */
-	[17982] = { 0x00FF, 0x00FF, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */
-	[17983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */
-	[18432] = { 0x00FF, 0x00FF, 0x0000 }, /* R18432 - RETUNEADC_PG2_1 */
-	[18433] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */
-	[18434] = { 0x00FF, 0x00FF, 0x0000 }, /* R18434 - RETUNEADC_PG_1 */
-	[18435] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */
-	[18944] = { 0x00FF, 0x00FF, 0x0000 }, /* R18944 - ADCR_RETUNE_C1_1 */
-	[18945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18945 - ADCR_RETUNE_C1_0 */
-	[18946] = { 0x00FF, 0x00FF, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */
-	[18947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */
-	[18948] = { 0x00FF, 0x00FF, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */
-	[18949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */
-	[18950] = { 0x00FF, 0x00FF, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */
-	[18951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */
-	[18952] = { 0x00FF, 0x00FF, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */
-	[18953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */
-	[18954] = { 0x00FF, 0x00FF, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */
-	[18955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */
-	[18956] = { 0x00FF, 0x00FF, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */
-	[18957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */
-	[18958] = { 0x00FF, 0x00FF, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */
-	[18959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */
-	[18960] = { 0x00FF, 0x00FF, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */
-	[18961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */
-	[18962] = { 0x00FF, 0x00FF, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */
-	[18963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */
-	[18964] = { 0x00FF, 0x00FF, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */
-	[18965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */
-	[18966] = { 0x00FF, 0x00FF, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */
-	[18967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */
-	[18968] = { 0x00FF, 0x00FF, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */
-	[18969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */
-	[18970] = { 0x00FF, 0x00FF, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */
-	[18971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */
-	[18972] = { 0x00FF, 0x00FF, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */
-	[18973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */
-	[18974] = { 0x00FF, 0x00FF, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */
-	[18975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */
-	[18976] = { 0x00FF, 0x00FF, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */
-	[18977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */
-	[18978] = { 0x00FF, 0x00FF, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */
-	[18979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */
-	[18980] = { 0x00FF, 0x00FF, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */
-	[18981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */
-	[18982] = { 0x00FF, 0x00FF, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */
-	[18983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */
-	[18984] = { 0x00FF, 0x00FF, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */
-	[18985] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */
-	[18986] = { 0x00FF, 0x00FF, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */
-	[18987] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */
-	[18988] = { 0x00FF, 0x00FF, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */
-	[18989] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */
-	[18990] = { 0x00FF, 0x00FF, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */
-	[18991] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */
-	[18992] = { 0x00FF, 0x00FF, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */
-	[18993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */
-	[18994] = { 0x00FF, 0x00FF, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */
-	[18995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */
-	[18996] = { 0x00FF, 0x00FF, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */
-	[18997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */
-	[18998] = { 0x00FF, 0x00FF, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */
-	[18999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */
-	[19000] = { 0x00FF, 0x00FF, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */
-	[19001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */
-	[19002] = { 0x00FF, 0x00FF, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */
-	[19003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */
-	[19004] = { 0x00FF, 0x00FF, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */
-	[19005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */
-	[19006] = { 0x00FF, 0x00FF, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */
-	[19007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */
-	[19456] = { 0x00FF, 0x00FF, 0x0000 }, /* R19456 - DACL_RETUNE_C1_1 */
-	[19457] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19457 - DACL_RETUNE_C1_0 */
-	[19458] = { 0x00FF, 0x00FF, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */
-	[19459] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */
-	[19460] = { 0x00FF, 0x00FF, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */
-	[19461] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */
-	[19462] = { 0x00FF, 0x00FF, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */
-	[19463] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */
-	[19464] = { 0x00FF, 0x00FF, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */
-	[19465] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */
-	[19466] = { 0x00FF, 0x00FF, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */
-	[19467] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */
-	[19468] = { 0x00FF, 0x00FF, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */
-	[19469] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */
-	[19470] = { 0x00FF, 0x00FF, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */
-	[19471] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */
-	[19472] = { 0x00FF, 0x00FF, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */
-	[19473] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */
-	[19474] = { 0x00FF, 0x00FF, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */
-	[19475] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */
-	[19476] = { 0x00FF, 0x00FF, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */
-	[19477] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */
-	[19478] = { 0x00FF, 0x00FF, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */
-	[19479] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */
-	[19480] = { 0x00FF, 0x00FF, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */
-	[19481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */
-	[19482] = { 0x00FF, 0x00FF, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */
-	[19483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */
-	[19484] = { 0x00FF, 0x00FF, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */
-	[19485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */
-	[19486] = { 0x00FF, 0x00FF, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */
-	[19487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */
-	[19488] = { 0x00FF, 0x00FF, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */
-	[19489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */
-	[19490] = { 0x00FF, 0x00FF, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */
-	[19491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */
-	[19492] = { 0x00FF, 0x00FF, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */
-	[19493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */
-	[19494] = { 0x00FF, 0x00FF, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */
-	[19495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */
-	[19496] = { 0x00FF, 0x00FF, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */
-	[19497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */
-	[19498] = { 0x00FF, 0x00FF, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */
-	[19499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */
-	[19500] = { 0x00FF, 0x00FF, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */
-	[19501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */
-	[19502] = { 0x00FF, 0x00FF, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */
-	[19503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */
-	[19504] = { 0x00FF, 0x00FF, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */
-	[19505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */
-	[19506] = { 0x00FF, 0x00FF, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */
-	[19507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */
-	[19508] = { 0x00FF, 0x00FF, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */
-	[19509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */
-	[19510] = { 0x00FF, 0x00FF, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */
-	[19511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */
-	[19512] = { 0x00FF, 0x00FF, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */
-	[19513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */
-	[19514] = { 0x00FF, 0x00FF, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */
-	[19515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */
-	[19516] = { 0x00FF, 0x00FF, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */
-	[19517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */
-	[19518] = { 0x00FF, 0x00FF, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */
-	[19519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */
-	[19968] = { 0x00FF, 0x00FF, 0x0000 }, /* R19968 - RETUNEDAC_PG2_1 */
-	[19969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */
-	[19970] = { 0x00FF, 0x00FF, 0x0000 }, /* R19970 - RETUNEDAC_PG_1 */
-	[19971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */
-	[20480] = { 0x00FF, 0x00FF, 0x0000 }, /* R20480 - DACR_RETUNE_C1_1 */
-	[20481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20481 - DACR_RETUNE_C1_0 */
-	[20482] = { 0x00FF, 0x00FF, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */
-	[20483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */
-	[20484] = { 0x00FF, 0x00FF, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */
-	[20485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */
-	[20486] = { 0x00FF, 0x00FF, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */
-	[20487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */
-	[20488] = { 0x00FF, 0x00FF, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */
-	[20489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */
-	[20490] = { 0x00FF, 0x00FF, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */
-	[20491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */
-	[20492] = { 0x00FF, 0x00FF, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */
-	[20493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */
-	[20494] = { 0x00FF, 0x00FF, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */
-	[20495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */
-	[20496] = { 0x00FF, 0x00FF, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */
-	[20497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */
-	[20498] = { 0x00FF, 0x00FF, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */
-	[20499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */
-	[20500] = { 0x00FF, 0x00FF, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */
-	[20501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */
-	[20502] = { 0x00FF, 0x00FF, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */
-	[20503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */
-	[20504] = { 0x00FF, 0x00FF, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */
-	[20505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */
-	[20506] = { 0x00FF, 0x00FF, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */
-	[20507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */
-	[20508] = { 0x00FF, 0x00FF, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */
-	[20509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */
-	[20510] = { 0x00FF, 0x00FF, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */
-	[20511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */
-	[20512] = { 0x00FF, 0x00FF, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */
-	[20513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */
-	[20514] = { 0x00FF, 0x00FF, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */
-	[20515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */
-	[20516] = { 0x00FF, 0x00FF, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */
-	[20517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */
-	[20518] = { 0x00FF, 0x00FF, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */
-	[20519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */
-	[20520] = { 0x00FF, 0x00FF, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */
-	[20521] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */
-	[20522] = { 0x00FF, 0x00FF, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */
-	[20523] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */
-	[20524] = { 0x00FF, 0x00FF, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */
-	[20525] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */
-	[20526] = { 0x00FF, 0x00FF, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */
-	[20527] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */
-	[20528] = { 0x00FF, 0x00FF, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */
-	[20529] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */
-	[20530] = { 0x00FF, 0x00FF, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */
-	[20531] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */
-	[20532] = { 0x00FF, 0x00FF, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */
-	[20533] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */
-	[20534] = { 0x00FF, 0x00FF, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */
-	[20535] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */
-	[20536] = { 0x00FF, 0x00FF, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */
-	[20537] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */
-	[20538] = { 0x00FF, 0x00FF, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */
-	[20539] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */
-	[20540] = { 0x00FF, 0x00FF, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */
-	[20541] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */
-	[20542] = { 0x00FF, 0x00FF, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */
-	[20543] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */
-	[20992] = { 0x00FF, 0x00FF, 0x0000 }, /* R20992 - VSS_XHD2_1 */
-	[20993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20993 - VSS_XHD2_0 */
-	[20994] = { 0x00FF, 0x00FF, 0x0000 }, /* R20994 - VSS_XHD3_1 */
-	[20995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20995 - VSS_XHD3_0 */
-	[20996] = { 0x00FF, 0x00FF, 0x0000 }, /* R20996 - VSS_XHN1_1 */
-	[20997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20997 - VSS_XHN1_0 */
-	[20998] = { 0x00FF, 0x00FF, 0x0000 }, /* R20998 - VSS_XHN2_1 */
-	[20999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20999 - VSS_XHN2_0 */
-	[21000] = { 0x00FF, 0x00FF, 0x0000 }, /* R21000 - VSS_XHN3_1 */
-	[21001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21001 - VSS_XHN3_0 */
-	[21002] = { 0x00FF, 0x00FF, 0x0000 }, /* R21002 - VSS_XLA_1 */
-	[21003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21003 - VSS_XLA_0 */
-	[21004] = { 0x00FF, 0x00FF, 0x0000 }, /* R21004 - VSS_XLB_1 */
-	[21005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21005 - VSS_XLB_0 */
-	[21006] = { 0x00FF, 0x00FF, 0x0000 }, /* R21006 - VSS_XLG_1 */
-	[21007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21007 - VSS_XLG_0 */
-	[21008] = { 0x00FF, 0x00FF, 0x0000 }, /* R21008 - VSS_PG2_1 */
-	[21009] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21009 - VSS_PG2_0 */
-	[21010] = { 0x00FF, 0x00FF, 0x0000 }, /* R21010 - VSS_PG_1 */
-	[21011] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21011 - VSS_PG_0 */
-	[21012] = { 0x00FF, 0x00FF, 0x0000 }, /* R21012 - VSS_XTD1_1 */
-	[21013] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21013 - VSS_XTD1_0 */
-	[21014] = { 0x00FF, 0x00FF, 0x0000 }, /* R21014 - VSS_XTD2_1 */
-	[21015] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21015 - VSS_XTD2_0 */
-	[21016] = { 0x00FF, 0x00FF, 0x0000 }, /* R21016 - VSS_XTD3_1 */
-	[21017] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21017 - VSS_XTD3_0 */
-	[21018] = { 0x00FF, 0x00FF, 0x0000 }, /* R21018 - VSS_XTD4_1 */
-	[21019] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21019 - VSS_XTD4_0 */
-	[21020] = { 0x00FF, 0x00FF, 0x0000 }, /* R21020 - VSS_XTD5_1 */
-	[21021] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21021 - VSS_XTD5_0 */
-	[21022] = { 0x00FF, 0x00FF, 0x0000 }, /* R21022 - VSS_XTD6_1 */
-	[21023] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21023 - VSS_XTD6_0 */
-	[21024] = { 0x00FF, 0x00FF, 0x0000 }, /* R21024 - VSS_XTD7_1 */
-	[21025] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21025 - VSS_XTD7_0 */
-	[21026] = { 0x00FF, 0x00FF, 0x0000 }, /* R21026 - VSS_XTD8_1 */
-	[21027] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21027 - VSS_XTD8_0 */
-	[21028] = { 0x00FF, 0x00FF, 0x0000 }, /* R21028 - VSS_XTD9_1 */
-	[21029] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21029 - VSS_XTD9_0 */
-	[21030] = { 0x00FF, 0x00FF, 0x0000 }, /* R21030 - VSS_XTD10_1 */
-	[21031] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21031 - VSS_XTD10_0 */
-	[21032] = { 0x00FF, 0x00FF, 0x0000 }, /* R21032 - VSS_XTD11_1 */
-	[21033] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21033 - VSS_XTD11_0 */
-	[21034] = { 0x00FF, 0x00FF, 0x0000 }, /* R21034 - VSS_XTD12_1 */
-	[21035] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21035 - VSS_XTD12_0 */
-	[21036] = { 0x00FF, 0x00FF, 0x0000 }, /* R21036 - VSS_XTD13_1 */
-	[21037] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21037 - VSS_XTD13_0 */
-	[21038] = { 0x00FF, 0x00FF, 0x0000 }, /* R21038 - VSS_XTD14_1 */
-	[21039] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21039 - VSS_XTD14_0 */
-	[21040] = { 0x00FF, 0x00FF, 0x0000 }, /* R21040 - VSS_XTD15_1 */
-	[21041] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21041 - VSS_XTD15_0 */
-	[21042] = { 0x00FF, 0x00FF, 0x0000 }, /* R21042 - VSS_XTD16_1 */
-	[21043] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21043 - VSS_XTD16_0 */
-	[21044] = { 0x00FF, 0x00FF, 0x0000 }, /* R21044 - VSS_XTD17_1 */
-	[21045] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21045 - VSS_XTD17_0 */
-	[21046] = { 0x00FF, 0x00FF, 0x0000 }, /* R21046 - VSS_XTD18_1 */
-	[21047] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21047 - VSS_XTD18_0 */
-	[21048] = { 0x00FF, 0x00FF, 0x0000 }, /* R21048 - VSS_XTD19_1 */
-	[21049] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21049 - VSS_XTD19_0 */
-	[21050] = { 0x00FF, 0x00FF, 0x0000 }, /* R21050 - VSS_XTD20_1 */
-	[21051] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21051 - VSS_XTD20_0 */
-	[21052] = { 0x00FF, 0x00FF, 0x0000 }, /* R21052 - VSS_XTD21_1 */
-	[21053] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21053 - VSS_XTD21_0 */
-	[21054] = { 0x00FF, 0x00FF, 0x0000 }, /* R21054 - VSS_XTD22_1 */
-	[21055] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21055 - VSS_XTD22_0 */
-	[21056] = { 0x00FF, 0x00FF, 0x0000 }, /* R21056 - VSS_XTD23_1 */
-	[21057] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21057 - VSS_XTD23_0 */
-	[21058] = { 0x00FF, 0x00FF, 0x0000 }, /* R21058 - VSS_XTD24_1 */
-	[21059] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21059 - VSS_XTD24_0 */
-	[21060] = { 0x00FF, 0x00FF, 0x0000 }, /* R21060 - VSS_XTD25_1 */
-	[21061] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21061 - VSS_XTD25_0 */
-	[21062] = { 0x00FF, 0x00FF, 0x0000 }, /* R21062 - VSS_XTD26_1 */
-	[21063] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21063 - VSS_XTD26_0 */
-	[21064] = { 0x00FF, 0x00FF, 0x0000 }, /* R21064 - VSS_XTD27_1 */
-	[21065] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21065 - VSS_XTD27_0 */
-	[21066] = { 0x00FF, 0x00FF, 0x0000 }, /* R21066 - VSS_XTD28_1 */
-	[21067] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21067 - VSS_XTD28_0 */
-	[21068] = { 0x00FF, 0x00FF, 0x0000 }, /* R21068 - VSS_XTD29_1 */
-	[21069] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21069 - VSS_XTD29_0 */
-	[21070] = { 0x00FF, 0x00FF, 0x0000 }, /* R21070 - VSS_XTD30_1 */
-	[21071] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21071 - VSS_XTD30_0 */
-	[21072] = { 0x00FF, 0x00FF, 0x0000 }, /* R21072 - VSS_XTD31_1 */
-	[21073] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21073 - VSS_XTD31_0 */
-	[21074] = { 0x00FF, 0x00FF, 0x0000 }, /* R21074 - VSS_XTD32_1 */
-	[21075] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21075 - VSS_XTD32_0 */
-	[21076] = { 0x00FF, 0x00FF, 0x0000 }, /* R21076 - VSS_XTS1_1 */
-	[21077] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21077 - VSS_XTS1_0 */
-	[21078] = { 0x00FF, 0x00FF, 0x0000 }, /* R21078 - VSS_XTS2_1 */
-	[21079] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21079 - VSS_XTS2_0 */
-	[21080] = { 0x00FF, 0x00FF, 0x0000 }, /* R21080 - VSS_XTS3_1 */
-	[21081] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21081 - VSS_XTS3_0 */
-	[21082] = { 0x00FF, 0x00FF, 0x0000 }, /* R21082 - VSS_XTS4_1 */
-	[21083] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21083 - VSS_XTS4_0 */
-	[21084] = { 0x00FF, 0x00FF, 0x0000 }, /* R21084 - VSS_XTS5_1 */
-	[21085] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21085 - VSS_XTS5_0 */
-	[21086] = { 0x00FF, 0x00FF, 0x0000 }, /* R21086 - VSS_XTS6_1 */
-	[21087] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21087 - VSS_XTS6_0 */
-	[21088] = { 0x00FF, 0x00FF, 0x0000 }, /* R21088 - VSS_XTS7_1 */
-	[21089] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21089 - VSS_XTS7_0 */
-	[21090] = { 0x00FF, 0x00FF, 0x0000 }, /* R21090 - VSS_XTS8_1 */
-	[21091] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21091 - VSS_XTS8_0 */
-	[21092] = { 0x00FF, 0x00FF, 0x0000 }, /* R21092 - VSS_XTS9_1 */
-	[21093] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21093 - VSS_XTS9_0 */
-	[21094] = { 0x00FF, 0x00FF, 0x0000 }, /* R21094 - VSS_XTS10_1 */
-	[21095] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21095 - VSS_XTS10_0 */
-	[21096] = { 0x00FF, 0x00FF, 0x0000 }, /* R21096 - VSS_XTS11_1 */
-	[21097] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21097 - VSS_XTS11_0 */
-	[21098] = { 0x00FF, 0x00FF, 0x0000 }, /* R21098 - VSS_XTS12_1 */
-	[21099] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21099 - VSS_XTS12_0 */
-	[21100] = { 0x00FF, 0x00FF, 0x0000 }, /* R21100 - VSS_XTS13_1 */
-	[21101] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21101 - VSS_XTS13_0 */
-	[21102] = { 0x00FF, 0x00FF, 0x0000 }, /* R21102 - VSS_XTS14_1 */
-	[21103] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21103 - VSS_XTS14_0 */
-	[21104] = { 0x00FF, 0x00FF, 0x0000 }, /* R21104 - VSS_XTS15_1 */
-	[21105] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21105 - VSS_XTS15_0 */
-	[21106] = { 0x00FF, 0x00FF, 0x0000 }, /* R21106 - VSS_XTS16_1 */
-	[21107] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21107 - VSS_XTS16_0 */
-	[21108] = { 0x00FF, 0x00FF, 0x0000 }, /* R21108 - VSS_XTS17_1 */
-	[21109] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21109 - VSS_XTS17_0 */
-	[21110] = { 0x00FF, 0x00FF, 0x0000 }, /* R21110 - VSS_XTS18_1 */
-	[21111] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21111 - VSS_XTS18_0 */
-	[21112] = { 0x00FF, 0x00FF, 0x0000 }, /* R21112 - VSS_XTS19_1 */
-	[21113] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21113 - VSS_XTS19_0 */
-	[21114] = { 0x00FF, 0x00FF, 0x0000 }, /* R21114 - VSS_XTS20_1 */
-	[21115] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21115 - VSS_XTS20_0 */
-	[21116] = { 0x00FF, 0x00FF, 0x0000 }, /* R21116 - VSS_XTS21_1 */
-	[21117] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21117 - VSS_XTS21_0 */
-	[21118] = { 0x00FF, 0x00FF, 0x0000 }, /* R21118 - VSS_XTS22_1 */
-	[21119] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21119 - VSS_XTS22_0 */
-	[21120] = { 0x00FF, 0x00FF, 0x0000 }, /* R21120 - VSS_XTS23_1 */
-	[21121] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21121 - VSS_XTS23_0 */
-	[21122] = { 0x00FF, 0x00FF, 0x0000 }, /* R21122 - VSS_XTS24_1 */
-	[21123] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21123 - VSS_XTS24_0 */
-	[21124] = { 0x00FF, 0x00FF, 0x0000 }, /* R21124 - VSS_XTS25_1 */
-	[21125] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21125 - VSS_XTS25_0 */
-	[21126] = { 0x00FF, 0x00FF, 0x0000 }, /* R21126 - VSS_XTS26_1 */
-	[21127] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21127 - VSS_XTS26_0 */
-	[21128] = { 0x00FF, 0x00FF, 0x0000 }, /* R21128 - VSS_XTS27_1 */
-	[21129] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21129 - VSS_XTS27_0 */
-	[21130] = { 0x00FF, 0x00FF, 0x0000 }, /* R21130 - VSS_XTS28_1 */
-	[21131] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21131 - VSS_XTS28_0 */
-	[21132] = { 0x00FF, 0x00FF, 0x0000 }, /* R21132 - VSS_XTS29_1 */
-	[21133] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21133 - VSS_XTS29_0 */
-	[21134] = { 0x00FF, 0x00FF, 0x0000 }, /* R21134 - VSS_XTS30_1 */
-	[21135] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21135 - VSS_XTS30_0 */
-	[21136] = { 0x00FF, 0x00FF, 0x0000 }, /* R21136 - VSS_XTS31_1 */
-	[21137] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21137 - VSS_XTS31_0 */
-	[21138] = { 0x00FF, 0x00FF, 0x0000 }, /* R21138 - VSS_XTS32_1 */
-	[21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
-};
-
 static bool wm8962_volatile_register(struct device *dev, unsigned int reg)
 {
-	if (wm8962_reg_access[reg].vol)
-		return 1;
-	else
-		return 0;
+	switch (reg) {
+	case WM8962_CLOCKING1:
+	case WM8962_CLOCKING2:
+	case WM8962_SOFTWARE_RESET:
+	case WM8962_ALC2:
+	case WM8962_THERMAL_SHUTDOWN_STATUS:
+	case WM8962_ADDITIONAL_CONTROL_4:
+	case WM8962_CLASS_D_CONTROL_1:
+	case WM8962_DC_SERVO_6:
+	case WM8962_INTERRUPT_STATUS_1:
+	case WM8962_INTERRUPT_STATUS_2:
+	case WM8962_DSP2_EXECCONTROL:
+		return true;
+	default:
+		return false;
+	}
 }
 
 static bool wm8962_readable_register(struct device *dev, unsigned int reg)
 {
-	if (wm8962_reg_access[reg].read)
-		return 1;
-	else
-		return 0;
+	switch (reg) {
+	case WM8962_LEFT_INPUT_VOLUME:
+	case WM8962_RIGHT_INPUT_VOLUME:
+	case WM8962_HPOUTL_VOLUME:
+	case WM8962_HPOUTR_VOLUME:
+	case WM8962_CLOCKING1:
+	case WM8962_ADC_DAC_CONTROL_1:
+	case WM8962_ADC_DAC_CONTROL_2:
+	case WM8962_AUDIO_INTERFACE_0:
+	case WM8962_CLOCKING2:
+	case WM8962_AUDIO_INTERFACE_1:
+	case WM8962_LEFT_DAC_VOLUME:
+	case WM8962_RIGHT_DAC_VOLUME:
+	case WM8962_AUDIO_INTERFACE_2:
+	case WM8962_SOFTWARE_RESET:
+	case WM8962_ALC1:
+	case WM8962_ALC2:
+	case WM8962_ALC3:
+	case WM8962_NOISE_GATE:
+	case WM8962_LEFT_ADC_VOLUME:
+	case WM8962_RIGHT_ADC_VOLUME:
+	case WM8962_ADDITIONAL_CONTROL_1:
+	case WM8962_ADDITIONAL_CONTROL_2:
+	case WM8962_PWR_MGMT_1:
+	case WM8962_PWR_MGMT_2:
+	case WM8962_ADDITIONAL_CONTROL_3:
+	case WM8962_ANTI_POP:
+	case WM8962_CLOCKING_3:
+	case WM8962_INPUT_MIXER_CONTROL_1:
+	case WM8962_LEFT_INPUT_MIXER_VOLUME:
+	case WM8962_RIGHT_INPUT_MIXER_VOLUME:
+	case WM8962_INPUT_MIXER_CONTROL_2:
+	case WM8962_INPUT_BIAS_CONTROL:
+	case WM8962_LEFT_INPUT_PGA_CONTROL:
+	case WM8962_RIGHT_INPUT_PGA_CONTROL:
+	case WM8962_SPKOUTL_VOLUME:
+	case WM8962_SPKOUTR_VOLUME:
+	case WM8962_THERMAL_SHUTDOWN_STATUS:
+	case WM8962_ADDITIONAL_CONTROL_4:
+	case WM8962_CLASS_D_CONTROL_1:
+	case WM8962_CLASS_D_CONTROL_2:
+	case WM8962_CLOCKING_4:
+	case WM8962_DAC_DSP_MIXING_1:
+	case WM8962_DAC_DSP_MIXING_2:
+	case WM8962_DC_SERVO_0:
+	case WM8962_DC_SERVO_1:
+	case WM8962_DC_SERVO_4:
+	case WM8962_DC_SERVO_6:
+	case WM8962_ANALOGUE_PGA_BIAS:
+	case WM8962_ANALOGUE_HP_0:
+	case WM8962_ANALOGUE_HP_2:
+	case WM8962_CHARGE_PUMP_1:
+	case WM8962_CHARGE_PUMP_B:
+	case WM8962_WRITE_SEQUENCER_CONTROL_1:
+	case WM8962_WRITE_SEQUENCER_CONTROL_2:
+	case WM8962_WRITE_SEQUENCER_CONTROL_3:
+	case WM8962_CONTROL_INTERFACE:
+	case WM8962_MIXER_ENABLES:
+	case WM8962_HEADPHONE_MIXER_1:
+	case WM8962_HEADPHONE_MIXER_2:
+	case WM8962_HEADPHONE_MIXER_3:
+	case WM8962_HEADPHONE_MIXER_4:
+	case WM8962_SPEAKER_MIXER_1:
+	case WM8962_SPEAKER_MIXER_2:
+	case WM8962_SPEAKER_MIXER_3:
+	case WM8962_SPEAKER_MIXER_4:
+	case WM8962_SPEAKER_MIXER_5:
+	case WM8962_BEEP_GENERATOR_1:
+	case WM8962_OSCILLATOR_TRIM_3:
+	case WM8962_OSCILLATOR_TRIM_4:
+	case WM8962_OSCILLATOR_TRIM_7:
+	case WM8962_ANALOGUE_CLOCKING1:
+	case WM8962_ANALOGUE_CLOCKING2:
+	case WM8962_ANALOGUE_CLOCKING3:
+	case WM8962_PLL_SOFTWARE_RESET:
+	case WM8962_PLL2:
+	case WM8962_PLL_4:
+	case WM8962_PLL_9:
+	case WM8962_PLL_10:
+	case WM8962_PLL_11:
+	case WM8962_PLL_12:
+	case WM8962_PLL_13:
+	case WM8962_PLL_14:
+	case WM8962_PLL_15:
+	case WM8962_PLL_16:
+	case WM8962_FLL_CONTROL_1:
+	case WM8962_FLL_CONTROL_2:
+	case WM8962_FLL_CONTROL_3:
+	case WM8962_FLL_CONTROL_5:
+	case WM8962_FLL_CONTROL_6:
+	case WM8962_FLL_CONTROL_7:
+	case WM8962_FLL_CONTROL_8:
+	case WM8962_GENERAL_TEST_1:
+	case WM8962_DF1:
+	case WM8962_DF2:
+	case WM8962_DF3:
+	case WM8962_DF4:
+	case WM8962_DF5:
+	case WM8962_DF6:
+	case WM8962_DF7:
+	case WM8962_LHPF1:
+	case WM8962_LHPF2:
+	case WM8962_THREED1:
+	case WM8962_THREED2:
+	case WM8962_THREED3:
+	case WM8962_THREED4:
+	case WM8962_DRC_1:
+	case WM8962_DRC_2:
+	case WM8962_DRC_3:
+	case WM8962_DRC_4:
+	case WM8962_DRC_5:
+	case WM8962_TLOOPBACK:
+	case WM8962_EQ1:
+	case WM8962_EQ2:
+	case WM8962_EQ3:
+	case WM8962_EQ4:
+	case WM8962_EQ5:
+	case WM8962_EQ6:
+	case WM8962_EQ7:
+	case WM8962_EQ8:
+	case WM8962_EQ9:
+	case WM8962_EQ10:
+	case WM8962_EQ11:
+	case WM8962_EQ12:
+	case WM8962_EQ13:
+	case WM8962_EQ14:
+	case WM8962_EQ15:
+	case WM8962_EQ16:
+	case WM8962_EQ17:
+	case WM8962_EQ18:
+	case WM8962_EQ19:
+	case WM8962_EQ20:
+	case WM8962_EQ21:
+	case WM8962_EQ22:
+	case WM8962_EQ23:
+	case WM8962_EQ24:
+	case WM8962_EQ25:
+	case WM8962_EQ26:
+	case WM8962_EQ27:
+	case WM8962_EQ28:
+	case WM8962_EQ29:
+	case WM8962_EQ30:
+	case WM8962_EQ31:
+	case WM8962_EQ32:
+	case WM8962_EQ33:
+	case WM8962_EQ34:
+	case WM8962_EQ35:
+	case WM8962_EQ36:
+	case WM8962_EQ37:
+	case WM8962_EQ38:
+	case WM8962_EQ39:
+	case WM8962_EQ40:
+	case WM8962_EQ41:
+	case WM8962_GPIO_BASE:
+	case WM8962_GPIO_2:
+	case WM8962_GPIO_3:
+	case WM8962_GPIO_5:
+	case WM8962_GPIO_6:
+	case WM8962_INTERRUPT_STATUS_1:
+	case WM8962_INTERRUPT_STATUS_2:
+	case WM8962_INTERRUPT_STATUS_1_MASK:
+	case WM8962_INTERRUPT_STATUS_2_MASK:
+	case WM8962_INTERRUPT_CONTROL:
+	case WM8962_IRQ_DEBOUNCE:
+	case WM8962_MICINT_SOURCE_POL:
+	case WM8962_DSP2_POWER_MANAGEMENT:
+	case WM8962_DSP2_EXECCONTROL:
+	case WM8962_DSP2_INSTRUCTION_RAM_0:
+	case WM8962_DSP2_ADDRESS_RAM_2:
+	case WM8962_DSP2_ADDRESS_RAM_1:
+	case WM8962_DSP2_ADDRESS_RAM_0:
+	case WM8962_DSP2_DATA1_RAM_1:
+	case WM8962_DSP2_DATA1_RAM_0:
+	case WM8962_DSP2_DATA2_RAM_1:
+	case WM8962_DSP2_DATA2_RAM_0:
+	case WM8962_DSP2_DATA3_RAM_1:
+	case WM8962_DSP2_DATA3_RAM_0:
+	case WM8962_DSP2_COEFF_RAM_0:
+	case WM8962_RETUNEADC_SHARED_COEFF_1:
+	case WM8962_RETUNEADC_SHARED_COEFF_0:
+	case WM8962_RETUNEDAC_SHARED_COEFF_1:
+	case WM8962_RETUNEDAC_SHARED_COEFF_0:
+	case WM8962_SOUNDSTAGE_ENABLES_1:
+	case WM8962_SOUNDSTAGE_ENABLES_0:
+	case WM8962_HDBASS_AI_1:
+	case WM8962_HDBASS_AI_0:
+	case WM8962_HDBASS_AR_1:
+	case WM8962_HDBASS_AR_0:
+	case WM8962_HDBASS_B_1:
+	case WM8962_HDBASS_B_0:
+	case WM8962_HDBASS_K_1:
+	case WM8962_HDBASS_K_0:
+	case WM8962_HDBASS_N1_1:
+	case WM8962_HDBASS_N1_0:
+	case WM8962_HDBASS_N2_1:
+	case WM8962_HDBASS_N2_0:
+	case WM8962_HDBASS_N3_1:
+	case WM8962_HDBASS_N3_0:
+	case WM8962_HDBASS_N4_1:
+	case WM8962_HDBASS_N4_0:
+	case WM8962_HDBASS_N5_1:
+	case WM8962_HDBASS_N5_0:
+	case WM8962_HDBASS_X1_1:
+	case WM8962_HDBASS_X1_0:
+	case WM8962_HDBASS_X2_1:
+	case WM8962_HDBASS_X2_0:
+	case WM8962_HDBASS_X3_1:
+	case WM8962_HDBASS_X3_0:
+	case WM8962_HDBASS_ATK_1:
+	case WM8962_HDBASS_ATK_0:
+	case WM8962_HDBASS_DCY_1:
+	case WM8962_HDBASS_DCY_0:
+	case WM8962_HDBASS_PG_1:
+	case WM8962_HDBASS_PG_0:
+	case WM8962_HPF_C_1:
+	case WM8962_HPF_C_0:
+	case WM8962_ADCL_RETUNE_C1_1:
+	case WM8962_ADCL_RETUNE_C1_0:
+	case WM8962_ADCL_RETUNE_C2_1:
+	case WM8962_ADCL_RETUNE_C2_0:
+	case WM8962_ADCL_RETUNE_C3_1:
+	case WM8962_ADCL_RETUNE_C3_0:
+	case WM8962_ADCL_RETUNE_C4_1:
+	case WM8962_ADCL_RETUNE_C4_0:
+	case WM8962_ADCL_RETUNE_C5_1:
+	case WM8962_ADCL_RETUNE_C5_0:
+	case WM8962_ADCL_RETUNE_C6_1:
+	case WM8962_ADCL_RETUNE_C6_0:
+	case WM8962_ADCL_RETUNE_C7_1:
+	case WM8962_ADCL_RETUNE_C7_0:
+	case WM8962_ADCL_RETUNE_C8_1:
+	case WM8962_ADCL_RETUNE_C8_0:
+	case WM8962_ADCL_RETUNE_C9_1:
+	case WM8962_ADCL_RETUNE_C9_0:
+	case WM8962_ADCL_RETUNE_C10_1:
+	case WM8962_ADCL_RETUNE_C10_0:
+	case WM8962_ADCL_RETUNE_C11_1:
+	case WM8962_ADCL_RETUNE_C11_0:
+	case WM8962_ADCL_RETUNE_C12_1:
+	case WM8962_ADCL_RETUNE_C12_0:
+	case WM8962_ADCL_RETUNE_C13_1:
+	case WM8962_ADCL_RETUNE_C13_0:
+	case WM8962_ADCL_RETUNE_C14_1:
+	case WM8962_ADCL_RETUNE_C14_0:
+	case WM8962_ADCL_RETUNE_C15_1:
+	case WM8962_ADCL_RETUNE_C15_0:
+	case WM8962_ADCL_RETUNE_C16_1:
+	case WM8962_ADCL_RETUNE_C16_0:
+	case WM8962_ADCL_RETUNE_C17_1:
+	case WM8962_ADCL_RETUNE_C17_0:
+	case WM8962_ADCL_RETUNE_C18_1:
+	case WM8962_ADCL_RETUNE_C18_0:
+	case WM8962_ADCL_RETUNE_C19_1:
+	case WM8962_ADCL_RETUNE_C19_0:
+	case WM8962_ADCL_RETUNE_C20_1:
+	case WM8962_ADCL_RETUNE_C20_0:
+	case WM8962_ADCL_RETUNE_C21_1:
+	case WM8962_ADCL_RETUNE_C21_0:
+	case WM8962_ADCL_RETUNE_C22_1:
+	case WM8962_ADCL_RETUNE_C22_0:
+	case WM8962_ADCL_RETUNE_C23_1:
+	case WM8962_ADCL_RETUNE_C23_0:
+	case WM8962_ADCL_RETUNE_C24_1:
+	case WM8962_ADCL_RETUNE_C24_0:
+	case WM8962_ADCL_RETUNE_C25_1:
+	case WM8962_ADCL_RETUNE_C25_0:
+	case WM8962_ADCL_RETUNE_C26_1:
+	case WM8962_ADCL_RETUNE_C26_0:
+	case WM8962_ADCL_RETUNE_C27_1:
+	case WM8962_ADCL_RETUNE_C27_0:
+	case WM8962_ADCL_RETUNE_C28_1:
+	case WM8962_ADCL_RETUNE_C28_0:
+	case WM8962_ADCL_RETUNE_C29_1:
+	case WM8962_ADCL_RETUNE_C29_0:
+	case WM8962_ADCL_RETUNE_C30_1:
+	case WM8962_ADCL_RETUNE_C30_0:
+	case WM8962_ADCL_RETUNE_C31_1:
+	case WM8962_ADCL_RETUNE_C31_0:
+	case WM8962_ADCL_RETUNE_C32_1:
+	case WM8962_ADCL_RETUNE_C32_0:
+	case WM8962_RETUNEADC_PG2_1:
+	case WM8962_RETUNEADC_PG2_0:
+	case WM8962_RETUNEADC_PG_1:
+	case WM8962_RETUNEADC_PG_0:
+	case WM8962_ADCR_RETUNE_C1_1:
+	case WM8962_ADCR_RETUNE_C1_0:
+	case WM8962_ADCR_RETUNE_C2_1:
+	case WM8962_ADCR_RETUNE_C2_0:
+	case WM8962_ADCR_RETUNE_C3_1:
+	case WM8962_ADCR_RETUNE_C3_0:
+	case WM8962_ADCR_RETUNE_C4_1:
+	case WM8962_ADCR_RETUNE_C4_0:
+	case WM8962_ADCR_RETUNE_C5_1:
+	case WM8962_ADCR_RETUNE_C5_0:
+	case WM8962_ADCR_RETUNE_C6_1:
+	case WM8962_ADCR_RETUNE_C6_0:
+	case WM8962_ADCR_RETUNE_C7_1:
+	case WM8962_ADCR_RETUNE_C7_0:
+	case WM8962_ADCR_RETUNE_C8_1:
+	case WM8962_ADCR_RETUNE_C8_0:
+	case WM8962_ADCR_RETUNE_C9_1:
+	case WM8962_ADCR_RETUNE_C9_0:
+	case WM8962_ADCR_RETUNE_C10_1:
+	case WM8962_ADCR_RETUNE_C10_0:
+	case WM8962_ADCR_RETUNE_C11_1:
+	case WM8962_ADCR_RETUNE_C11_0:
+	case WM8962_ADCR_RETUNE_C12_1:
+	case WM8962_ADCR_RETUNE_C12_0:
+	case WM8962_ADCR_RETUNE_C13_1:
+	case WM8962_ADCR_RETUNE_C13_0:
+	case WM8962_ADCR_RETUNE_C14_1:
+	case WM8962_ADCR_RETUNE_C14_0:
+	case WM8962_ADCR_RETUNE_C15_1:
+	case WM8962_ADCR_RETUNE_C15_0:
+	case WM8962_ADCR_RETUNE_C16_1:
+	case WM8962_ADCR_RETUNE_C16_0:
+	case WM8962_ADCR_RETUNE_C17_1:
+	case WM8962_ADCR_RETUNE_C17_0:
+	case WM8962_ADCR_RETUNE_C18_1:
+	case WM8962_ADCR_RETUNE_C18_0:
+	case WM8962_ADCR_RETUNE_C19_1:
+	case WM8962_ADCR_RETUNE_C19_0:
+	case WM8962_ADCR_RETUNE_C20_1:
+	case WM8962_ADCR_RETUNE_C20_0:
+	case WM8962_ADCR_RETUNE_C21_1:
+	case WM8962_ADCR_RETUNE_C21_0:
+	case WM8962_ADCR_RETUNE_C22_1:
+	case WM8962_ADCR_RETUNE_C22_0:
+	case WM8962_ADCR_RETUNE_C23_1:
+	case WM8962_ADCR_RETUNE_C23_0:
+	case WM8962_ADCR_RETUNE_C24_1:
+	case WM8962_ADCR_RETUNE_C24_0:
+	case WM8962_ADCR_RETUNE_C25_1:
+	case WM8962_ADCR_RETUNE_C25_0:
+	case WM8962_ADCR_RETUNE_C26_1:
+	case WM8962_ADCR_RETUNE_C26_0:
+	case WM8962_ADCR_RETUNE_C27_1:
+	case WM8962_ADCR_RETUNE_C27_0:
+	case WM8962_ADCR_RETUNE_C28_1:
+	case WM8962_ADCR_RETUNE_C28_0:
+	case WM8962_ADCR_RETUNE_C29_1:
+	case WM8962_ADCR_RETUNE_C29_0:
+	case WM8962_ADCR_RETUNE_C30_1:
+	case WM8962_ADCR_RETUNE_C30_0:
+	case WM8962_ADCR_RETUNE_C31_1:
+	case WM8962_ADCR_RETUNE_C31_0:
+	case WM8962_ADCR_RETUNE_C32_1:
+	case WM8962_ADCR_RETUNE_C32_0:
+	case WM8962_DACL_RETUNE_C1_1:
+	case WM8962_DACL_RETUNE_C1_0:
+	case WM8962_DACL_RETUNE_C2_1:
+	case WM8962_DACL_RETUNE_C2_0:
+	case WM8962_DACL_RETUNE_C3_1:
+	case WM8962_DACL_RETUNE_C3_0:
+	case WM8962_DACL_RETUNE_C4_1:
+	case WM8962_DACL_RETUNE_C4_0:
+	case WM8962_DACL_RETUNE_C5_1:
+	case WM8962_DACL_RETUNE_C5_0:
+	case WM8962_DACL_RETUNE_C6_1:
+	case WM8962_DACL_RETUNE_C6_0:
+	case WM8962_DACL_RETUNE_C7_1:
+	case WM8962_DACL_RETUNE_C7_0:
+	case WM8962_DACL_RETUNE_C8_1:
+	case WM8962_DACL_RETUNE_C8_0:
+	case WM8962_DACL_RETUNE_C9_1:
+	case WM8962_DACL_RETUNE_C9_0:
+	case WM8962_DACL_RETUNE_C10_1:
+	case WM8962_DACL_RETUNE_C10_0:
+	case WM8962_DACL_RETUNE_C11_1:
+	case WM8962_DACL_RETUNE_C11_0:
+	case WM8962_DACL_RETUNE_C12_1:
+	case WM8962_DACL_RETUNE_C12_0:
+	case WM8962_DACL_RETUNE_C13_1:
+	case WM8962_DACL_RETUNE_C13_0:
+	case WM8962_DACL_RETUNE_C14_1:
+	case WM8962_DACL_RETUNE_C14_0:
+	case WM8962_DACL_RETUNE_C15_1:
+	case WM8962_DACL_RETUNE_C15_0:
+	case WM8962_DACL_RETUNE_C16_1:
+	case WM8962_DACL_RETUNE_C16_0:
+	case WM8962_DACL_RETUNE_C17_1:
+	case WM8962_DACL_RETUNE_C17_0:
+	case WM8962_DACL_RETUNE_C18_1:
+	case WM8962_DACL_RETUNE_C18_0:
+	case WM8962_DACL_RETUNE_C19_1:
+	case WM8962_DACL_RETUNE_C19_0:
+	case WM8962_DACL_RETUNE_C20_1:
+	case WM8962_DACL_RETUNE_C20_0:
+	case WM8962_DACL_RETUNE_C21_1:
+	case WM8962_DACL_RETUNE_C21_0:
+	case WM8962_DACL_RETUNE_C22_1:
+	case WM8962_DACL_RETUNE_C22_0:
+	case WM8962_DACL_RETUNE_C23_1:
+	case WM8962_DACL_RETUNE_C23_0:
+	case WM8962_DACL_RETUNE_C24_1:
+	case WM8962_DACL_RETUNE_C24_0:
+	case WM8962_DACL_RETUNE_C25_1:
+	case WM8962_DACL_RETUNE_C25_0:
+	case WM8962_DACL_RETUNE_C26_1:
+	case WM8962_DACL_RETUNE_C26_0:
+	case WM8962_DACL_RETUNE_C27_1:
+	case WM8962_DACL_RETUNE_C27_0:
+	case WM8962_DACL_RETUNE_C28_1:
+	case WM8962_DACL_RETUNE_C28_0:
+	case WM8962_DACL_RETUNE_C29_1:
+	case WM8962_DACL_RETUNE_C29_0:
+	case WM8962_DACL_RETUNE_C30_1:
+	case WM8962_DACL_RETUNE_C30_0:
+	case WM8962_DACL_RETUNE_C31_1:
+	case WM8962_DACL_RETUNE_C31_0:
+	case WM8962_DACL_RETUNE_C32_1:
+	case WM8962_DACL_RETUNE_C32_0:
+	case WM8962_RETUNEDAC_PG2_1:
+	case WM8962_RETUNEDAC_PG2_0:
+	case WM8962_RETUNEDAC_PG_1:
+	case WM8962_RETUNEDAC_PG_0:
+	case WM8962_DACR_RETUNE_C1_1:
+	case WM8962_DACR_RETUNE_C1_0:
+	case WM8962_DACR_RETUNE_C2_1:
+	case WM8962_DACR_RETUNE_C2_0:
+	case WM8962_DACR_RETUNE_C3_1:
+	case WM8962_DACR_RETUNE_C3_0:
+	case WM8962_DACR_RETUNE_C4_1:
+	case WM8962_DACR_RETUNE_C4_0:
+	case WM8962_DACR_RETUNE_C5_1:
+	case WM8962_DACR_RETUNE_C5_0:
+	case WM8962_DACR_RETUNE_C6_1:
+	case WM8962_DACR_RETUNE_C6_0:
+	case WM8962_DACR_RETUNE_C7_1:
+	case WM8962_DACR_RETUNE_C7_0:
+	case WM8962_DACR_RETUNE_C8_1:
+	case WM8962_DACR_RETUNE_C8_0:
+	case WM8962_DACR_RETUNE_C9_1:
+	case WM8962_DACR_RETUNE_C9_0:
+	case WM8962_DACR_RETUNE_C10_1:
+	case WM8962_DACR_RETUNE_C10_0:
+	case WM8962_DACR_RETUNE_C11_1:
+	case WM8962_DACR_RETUNE_C11_0:
+	case WM8962_DACR_RETUNE_C12_1:
+	case WM8962_DACR_RETUNE_C12_0:
+	case WM8962_DACR_RETUNE_C13_1:
+	case WM8962_DACR_RETUNE_C13_0:
+	case WM8962_DACR_RETUNE_C14_1:
+	case WM8962_DACR_RETUNE_C14_0:
+	case WM8962_DACR_RETUNE_C15_1:
+	case WM8962_DACR_RETUNE_C15_0:
+	case WM8962_DACR_RETUNE_C16_1:
+	case WM8962_DACR_RETUNE_C16_0:
+	case WM8962_DACR_RETUNE_C17_1:
+	case WM8962_DACR_RETUNE_C17_0:
+	case WM8962_DACR_RETUNE_C18_1:
+	case WM8962_DACR_RETUNE_C18_0:
+	case WM8962_DACR_RETUNE_C19_1:
+	case WM8962_DACR_RETUNE_C19_0:
+	case WM8962_DACR_RETUNE_C20_1:
+	case WM8962_DACR_RETUNE_C20_0:
+	case WM8962_DACR_RETUNE_C21_1:
+	case WM8962_DACR_RETUNE_C21_0:
+	case WM8962_DACR_RETUNE_C22_1:
+	case WM8962_DACR_RETUNE_C22_0:
+	case WM8962_DACR_RETUNE_C23_1:
+	case WM8962_DACR_RETUNE_C23_0:
+	case WM8962_DACR_RETUNE_C24_1:
+	case WM8962_DACR_RETUNE_C24_0:
+	case WM8962_DACR_RETUNE_C25_1:
+	case WM8962_DACR_RETUNE_C25_0:
+	case WM8962_DACR_RETUNE_C26_1:
+	case WM8962_DACR_RETUNE_C26_0:
+	case WM8962_DACR_RETUNE_C27_1:
+	case WM8962_DACR_RETUNE_C27_0:
+	case WM8962_DACR_RETUNE_C28_1:
+	case WM8962_DACR_RETUNE_C28_0:
+	case WM8962_DACR_RETUNE_C29_1:
+	case WM8962_DACR_RETUNE_C29_0:
+	case WM8962_DACR_RETUNE_C30_1:
+	case WM8962_DACR_RETUNE_C30_0:
+	case WM8962_DACR_RETUNE_C31_1:
+	case WM8962_DACR_RETUNE_C31_0:
+	case WM8962_DACR_RETUNE_C32_1:
+	case WM8962_DACR_RETUNE_C32_0:
+	case WM8962_VSS_XHD2_1:
+	case WM8962_VSS_XHD2_0:
+	case WM8962_VSS_XHD3_1:
+	case WM8962_VSS_XHD3_0:
+	case WM8962_VSS_XHN1_1:
+	case WM8962_VSS_XHN1_0:
+	case WM8962_VSS_XHN2_1:
+	case WM8962_VSS_XHN2_0:
+	case WM8962_VSS_XHN3_1:
+	case WM8962_VSS_XHN3_0:
+	case WM8962_VSS_XLA_1:
+	case WM8962_VSS_XLA_0:
+	case WM8962_VSS_XLB_1:
+	case WM8962_VSS_XLB_0:
+	case WM8962_VSS_XLG_1:
+	case WM8962_VSS_XLG_0:
+	case WM8962_VSS_PG2_1:
+	case WM8962_VSS_PG2_0:
+	case WM8962_VSS_PG_1:
+	case WM8962_VSS_PG_0:
+	case WM8962_VSS_XTD1_1:
+	case WM8962_VSS_XTD1_0:
+	case WM8962_VSS_XTD2_1:
+	case WM8962_VSS_XTD2_0:
+	case WM8962_VSS_XTD3_1:
+	case WM8962_VSS_XTD3_0:
+	case WM8962_VSS_XTD4_1:
+	case WM8962_VSS_XTD4_0:
+	case WM8962_VSS_XTD5_1:
+	case WM8962_VSS_XTD5_0:
+	case WM8962_VSS_XTD6_1:
+	case WM8962_VSS_XTD6_0:
+	case WM8962_VSS_XTD7_1:
+	case WM8962_VSS_XTD7_0:
+	case WM8962_VSS_XTD8_1:
+	case WM8962_VSS_XTD8_0:
+	case WM8962_VSS_XTD9_1:
+	case WM8962_VSS_XTD9_0:
+	case WM8962_VSS_XTD10_1:
+	case WM8962_VSS_XTD10_0:
+	case WM8962_VSS_XTD11_1:
+	case WM8962_VSS_XTD11_0:
+	case WM8962_VSS_XTD12_1:
+	case WM8962_VSS_XTD12_0:
+	case WM8962_VSS_XTD13_1:
+	case WM8962_VSS_XTD13_0:
+	case WM8962_VSS_XTD14_1:
+	case WM8962_VSS_XTD14_0:
+	case WM8962_VSS_XTD15_1:
+	case WM8962_VSS_XTD15_0:
+	case WM8962_VSS_XTD16_1:
+	case WM8962_VSS_XTD16_0:
+	case WM8962_VSS_XTD17_1:
+	case WM8962_VSS_XTD17_0:
+	case WM8962_VSS_XTD18_1:
+	case WM8962_VSS_XTD18_0:
+	case WM8962_VSS_XTD19_1:
+	case WM8962_VSS_XTD19_0:
+	case WM8962_VSS_XTD20_1:
+	case WM8962_VSS_XTD20_0:
+	case WM8962_VSS_XTD21_1:
+	case WM8962_VSS_XTD21_0:
+	case WM8962_VSS_XTD22_1:
+	case WM8962_VSS_XTD22_0:
+	case WM8962_VSS_XTD23_1:
+	case WM8962_VSS_XTD23_0:
+	case WM8962_VSS_XTD24_1:
+	case WM8962_VSS_XTD24_0:
+	case WM8962_VSS_XTD25_1:
+	case WM8962_VSS_XTD25_0:
+	case WM8962_VSS_XTD26_1:
+	case WM8962_VSS_XTD26_0:
+	case WM8962_VSS_XTD27_1:
+	case WM8962_VSS_XTD27_0:
+	case WM8962_VSS_XTD28_1:
+	case WM8962_VSS_XTD28_0:
+	case WM8962_VSS_XTD29_1:
+	case WM8962_VSS_XTD29_0:
+	case WM8962_VSS_XTD30_1:
+	case WM8962_VSS_XTD30_0:
+	case WM8962_VSS_XTD31_1:
+	case WM8962_VSS_XTD31_0:
+	case WM8962_VSS_XTD32_1:
+	case WM8962_VSS_XTD32_0:
+	case WM8962_VSS_XTS1_1:
+	case WM8962_VSS_XTS1_0:
+	case WM8962_VSS_XTS2_1:
+	case WM8962_VSS_XTS2_0:
+	case WM8962_VSS_XTS3_1:
+	case WM8962_VSS_XTS3_0:
+	case WM8962_VSS_XTS4_1:
+	case WM8962_VSS_XTS4_0:
+	case WM8962_VSS_XTS5_1:
+	case WM8962_VSS_XTS5_0:
+	case WM8962_VSS_XTS6_1:
+	case WM8962_VSS_XTS6_0:
+	case WM8962_VSS_XTS7_1:
+	case WM8962_VSS_XTS7_0:
+	case WM8962_VSS_XTS8_1:
+	case WM8962_VSS_XTS8_0:
+	case WM8962_VSS_XTS9_1:
+	case WM8962_VSS_XTS9_0:
+	case WM8962_VSS_XTS10_1:
+	case WM8962_VSS_XTS10_0:
+	case WM8962_VSS_XTS11_1:
+	case WM8962_VSS_XTS11_0:
+	case WM8962_VSS_XTS12_1:
+	case WM8962_VSS_XTS12_0:
+	case WM8962_VSS_XTS13_1:
+	case WM8962_VSS_XTS13_0:
+	case WM8962_VSS_XTS14_1:
+	case WM8962_VSS_XTS14_0:
+	case WM8962_VSS_XTS15_1:
+	case WM8962_VSS_XTS15_0:
+	case WM8962_VSS_XTS16_1:
+	case WM8962_VSS_XTS16_0:
+	case WM8962_VSS_XTS17_1:
+	case WM8962_VSS_XTS17_0:
+	case WM8962_VSS_XTS18_1:
+	case WM8962_VSS_XTS18_0:
+	case WM8962_VSS_XTS19_1:
+	case WM8962_VSS_XTS19_0:
+	case WM8962_VSS_XTS20_1:
+	case WM8962_VSS_XTS20_0:
+	case WM8962_VSS_XTS21_1:
+	case WM8962_VSS_XTS21_0:
+	case WM8962_VSS_XTS22_1:
+	case WM8962_VSS_XTS22_0:
+	case WM8962_VSS_XTS23_1:
+	case WM8962_VSS_XTS23_0:
+	case WM8962_VSS_XTS24_1:
+	case WM8962_VSS_XTS24_0:
+	case WM8962_VSS_XTS25_1:
+	case WM8962_VSS_XTS25_0:
+	case WM8962_VSS_XTS26_1:
+	case WM8962_VSS_XTS26_0:
+	case WM8962_VSS_XTS27_1:
+	case WM8962_VSS_XTS27_0:
+	case WM8962_VSS_XTS28_1:
+	case WM8962_VSS_XTS28_0:
+	case WM8962_VSS_XTS29_1:
+	case WM8962_VSS_XTS29_0:
+	case WM8962_VSS_XTS30_1:
+	case WM8962_VSS_XTS30_0:
+	case WM8962_VSS_XTS31_1:
+	case WM8962_VSS_XTS31_0:
+	case WM8962_VSS_XTS32_1:
+	case WM8962_VSS_XTS32_0:
+		return true;
+	default:
+		return false;
+	}
 }
 
 static int wm8962_reset(struct wm8962_priv *wm8962)
@@ -2221,6 +1702,8 @@ SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
 SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME,
 		 WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv),
 SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0),
+SOC_SINGLE("DAC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 5, 1, 0),
+SOC_SINGLE("ADC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 8, 1, 0),
 
 SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1,
 	   5, 1, 0),
@@ -2337,65 +1820,6 @@ SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
 	       4, 1, 0, inmix_tlv),
 };
 
-static int sysclk_event(struct snd_soc_dapm_widget *w,
-			struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	unsigned long timeout;
-	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) {
-	case 0:      /* MCLK */
-		fll = 0;
-		break;
-	case 0x200:  /* FLL */
-		fll = 1;
-		break;
-	default:
-		dev_err(codec->dev, "Unknown SYSCLK source %x\n", src);
-		return -EINVAL;
-	}
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		if (fll) {
-			try_wait_for_completion(&wm8962->fll_lock);
-
-			snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
-					    WM8962_FLL_ENA, WM8962_FLL_ENA);
-
-			timeout = msecs_to_jiffies(5);
-			timeout = wait_for_completion_timeout(&wm8962->fll_lock,
-							      timeout);
-
-			if (wm8962->irq && timeout == 0)
-				dev_err(codec->dev,
-					"Timed out starting FLL\n");
-		}
-		break;
-
-	case SND_SOC_DAPM_POST_PMD:
-		if (fll)
-			snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
-					    WM8962_FLL_ENA, 0);
-		break;
-
-	default:
-		BUG();
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static int cp_event(struct snd_soc_dapm_widget *w,
 		    struct snd_kcontrol *kcontrol, int event)
 {
@@ -2681,8 +2105,7 @@ SND_SOC_DAPM_INPUT("DMICDAT"),
 SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
-SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
-		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event,
 		    SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
@@ -2796,9 +2219,11 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
 
 	{ "STL", "Left", "ADCL" },
 	{ "STL", "Right", "ADCR" },
+	{ "STL", NULL, "Class G" },
 
 	{ "STR", "Left", "ADCL" },
 	{ "STR", "Right", "ADCR" },
+	{ "STR", NULL, "Class G" },
 
 	{ "DACL", NULL, "SYSCLK" },
 	{ "DACL", NULL, "TOCLK" },
@@ -2910,13 +2335,13 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
 	struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-	snd_soc_add_controls(codec, wm8962_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8962_snd_controls,
 			     ARRAY_SIZE(wm8962_snd_controls));
 	if (pdata && pdata->spk_mono)
-		snd_soc_add_controls(codec, wm8962_spk_mono_controls,
+		snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls,
 				     ARRAY_SIZE(wm8962_spk_mono_controls));
 	else
-		snd_soc_add_controls(codec, wm8962_spk_stereo_controls,
+		snd_soc_add_codec_controls(codec, wm8962_spk_stereo_controls,
 				     ARRAY_SIZE(wm8962_spk_stereo_controls));
 
 
@@ -2950,7 +2375,7 @@ static const int bclk_divs[] = {
 };
 
 static const int sysclk_rates[] = {
-	64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+	64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, 3072, 6144
 };
 
 static void wm8962_configure_bclk(struct snd_soc_codec *codec)
@@ -2984,6 +2409,8 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
 		return;
 	}
 
+	dev_dbg(codec->dev, "Selected sysclk ratio %d\n", sysclk_rates[i]);
+
 	snd_soc_update_bits(codec, WM8962_CLOCKING_4,
 			    WM8962_SYSCLK_RATE_MASK, clocking4);
 
@@ -3042,9 +2469,6 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
 static int wm8962_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
-	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	int ret;
-
 	if (level == codec->dapm.bias_level)
 		return 0;
 
@@ -3061,51 +2485,15 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
 		break;
 
 	case SND_SOC_BIAS_STANDBY:
-		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-			ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
-						    wm8962->supplies);
-			if (ret != 0) {
-				dev_err(codec->dev,
-					"Failed to enable supplies: %d\n",
-					ret);
-				return ret;
-			}
-
-			regcache_cache_only(wm8962->regmap, false);
-			regcache_sync(wm8962->regmap);
-
-			snd_soc_update_bits(codec, WM8962_ANTI_POP,
-					    WM8962_STARTUP_BIAS_ENA |
-					    WM8962_VMID_BUF_ENA,
-					    WM8962_STARTUP_BIAS_ENA |
-					    WM8962_VMID_BUF_ENA);
-
-			/* Bias enable at 2*50k for ramp */
-			snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
-					    WM8962_VMID_SEL_MASK |
-					    WM8962_BIAS_ENA,
-					    WM8962_BIAS_ENA | 0x180);
-
-			msleep(5);
-		}
-
 		/* VMID 2*250k */
 		snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
 				    WM8962_VMID_SEL_MASK, 0x100);
 		break;
 
 	case SND_SOC_BIAS_OFF:
-		snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
-				    WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
-
-		snd_soc_update_bits(codec, WM8962_ANTI_POP,
-				    WM8962_STARTUP_BIAS_ENA |
-				    WM8962_VMID_BUF_ENA, 0);
-
-		regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
-				       wm8962->supplies);
 		break;
 	}
+
 	codec->dapm.bias_level = level;
 	return 0;
 }
@@ -3139,6 +2527,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
 	int adctl3 = 0;
 
 	wm8962->bclk = snd_soc_params_to_bclk(params);
+	if (params_channels(params) == 1)
+		wm8962->bclk *= 2;
+
 	wm8962->lrclk = params_rate(params);
 
 	for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
@@ -3177,7 +2568,8 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
 			    WM8962_SAMPLE_RATE_INT_MODE |
 			    WM8962_SAMPLE_RATE_MASK, adctl3);
 
-	wm8962_configure_bclk(codec);
+	if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+		wm8962_configure_bclk(codec);
 
 	return 0;
 }
@@ -3207,6 +2599,8 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
 
 	wm8962->sysclk_rate = freq;
 
+	wm8962_configure_bclk(codec);
+
 	return 0;
 }
 
@@ -3385,8 +2779,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 	struct _fll_div fll_div;
 	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;
+	int fll1 = 0;
 
 	/* Any change? */
 	if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
@@ -3402,6 +2795,8 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 		snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
 				    WM8962_FLL_ENA, 0);
 
+		pm_runtime_put(codec->dev);
+
 		return 0;
 	}
 
@@ -3409,6 +2804,9 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 	if (ret != 0)
 		return ret;
 
+	/* Parameters good, disable so we can reprogram */
+	snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
+
 	switch (fll_id) {
 	case WM8962_FLL_MCLK:
 	case WM8962_FLL_BCLK:
@@ -3447,12 +2845,11 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 
 	try_wait_for_completion(&wm8962->fll_lock);
 
-	if (sysclk)
-		fll1 |= WM8962_FLL_ENA;
+	pm_runtime_get_sync(codec->dev);
 
 	snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
 			    WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
-			    WM8962_FLL_ENA, fll1);
+			    WM8962_FLL_ENA, fll1 | WM8962_FLL_ENA);
 
 	dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
 
@@ -3513,14 +2910,14 @@ static struct snd_soc_dai_driver wm8962_dai = {
 	.name = "wm8962",
 	.playback = {
 		.stream_name = "Playback",
-		.channels_min = 2,
+		.channels_min = 1,
 		.channels_max = 2,
 		.rates = WM8962_RATES,
 		.formats = WM8962_FORMATS,
 	},
 	.capture = {
 		.stream_name = "Capture",
-		.channels_min = 2,
+		.channels_min = 1,
 		.channels_max = 2,
 		.rates = WM8962_RATES,
 		.formats = WM8962_FORMATS,
@@ -3561,54 +2958,73 @@ static void wm8962_mic_work(struct work_struct *work)
 
 static irqreturn_t wm8962_irq(int irq, void *data)
 {
-	struct snd_soc_codec *codec = data;
-	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	int mask;
-	int active;
-	int reg;
+	struct device *dev = data;
+	struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+	unsigned int mask;
+	unsigned int active;
+	int reg, ret;
 
-	mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
+	ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK,
+			  &mask);
+	if (ret != 0) {
+		dev_err(dev, "Failed to read interrupt mask: %d\n",
+			ret);
+		return IRQ_NONE;
+	}
+
+	ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active);
+	if (ret != 0) {
+		dev_err(dev, "Failed to read interrupt: %d\n", ret);
+		return IRQ_NONE;
+	}
 
-	active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
 	active &= ~mask;
 
 	if (!active)
 		return IRQ_NONE;
 
 	/* Acknowledge the interrupts */
-	snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
+	ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active);
+	if (ret != 0)
+		dev_warn(dev, "Failed to ack interrupt: %d\n", ret);
 
 	if (active & WM8962_FLL_LOCK_EINT) {
-		dev_dbg(codec->dev, "FLL locked\n");
+		dev_dbg(dev, "FLL locked\n");
 		complete(&wm8962->fll_lock);
 	}
 
 	if (active & WM8962_FIFOS_ERR_EINT)
-		dev_err(codec->dev, "FIFO error\n");
+		dev_err(dev, "FIFO error\n");
 
 	if (active & WM8962_TEMP_SHUT_EINT) {
-		dev_crit(codec->dev, "Thermal shutdown\n");
+		dev_crit(dev, "Thermal shutdown\n");
 
-		reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS);
+		ret = regmap_read(wm8962->regmap,
+				  WM8962_THERMAL_SHUTDOWN_STATUS,  &reg);
+		if (ret != 0) {
+			dev_warn(dev, "Failed to read thermal status: %d\n",
+				 ret);
+			reg = 0;
+		}
 
 		if (reg & WM8962_TEMP_ERR_HP)
-			dev_crit(codec->dev, "Headphone thermal error\n");
+			dev_crit(dev, "Headphone thermal error\n");
 		if (reg & WM8962_TEMP_WARN_HP)
-			dev_crit(codec->dev, "Headphone thermal warning\n");
+			dev_crit(dev, "Headphone thermal warning\n");
 		if (reg & WM8962_TEMP_ERR_SPK)
-			dev_crit(codec->dev, "Speaker thermal error\n");
+			dev_crit(dev, "Speaker thermal error\n");
 		if (reg & WM8962_TEMP_WARN_SPK)
-			dev_crit(codec->dev, "Speaker thermal warning\n");
+			dev_crit(dev, "Speaker thermal warning\n");
 	}
 
 	if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
-		dev_dbg(codec->dev, "Microphone event detected\n");
+		dev_dbg(dev, "Microphone event detected\n");
 
 #ifndef CONFIG_SND_SOC_WM8962_MODULE
-		trace_snd_soc_jack_irq(dev_name(codec->dev));
+		trace_snd_soc_jack_irq(dev_name(dev));
 #endif
 
-		pm_wakeup_event(codec->dev, 300);
+		pm_wakeup_event(dev, 300);
 
 		schedule_delayed_work(&wm8962->mic_work,
 				      msecs_to_jiffies(250));
@@ -4089,7 +3505,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
 
 		ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
 					   trigger | IRQF_ONESHOT,
-					   "wm8962", codec);
+					   "wm8962", codec->dev);
 		if (ret != 0) {
 			dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
 				wm8962->irq, ret);
@@ -4127,20 +3543,19 @@ static int wm8962_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
-static int wm8962_soc_volatile(struct snd_soc_codec *codec,
-			       unsigned int reg)
-{
-	return true;
-}
-
-
 static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
 	.probe =	wm8962_probe,
 	.remove =	wm8962_remove,
 	.set_bias_level = wm8962_set_bias_level,
 	.set_pll = wm8962_set_fll,
-	.reg_cache_size	= WM8962_MAX_REGISTER,
-	.volatile_register = wm8962_soc_volatile,
+	.idle_bias_off = true,
+};
+
+/* Improve power consumption for IN4 DC measurement mode */
+static const struct reg_default wm8962_dc_measure[] = {
+	{ 0xfd, 0x1 },
+	{ 0xcc, 0x40 },
+	{ 0xfd, 0 },
 };
 
 static const struct regmap_config wm8962_regmap = {
@@ -4155,10 +3570,10 @@ static const struct regmap_config wm8962_regmap = {
 	.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_pdata *pdata = dev_get_platdata(&i2c->dev);
 	struct wm8962_priv *wm8962;
 	unsigned int reg;
 	int ret, i;
@@ -4212,7 +3627,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
 	}
 	if (reg != 0x6243) {
 		dev_err(&i2c->dev,
-			"Device is not a WM8962, ID %x != 0x6243\n", ret);
+			"Device is not a WM8962, ID %x != 0x6243\n", reg);
 		ret = -EINVAL;
 		goto err_regmap;
 	}
@@ -4237,7 +3652,18 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
 		goto err_regmap;
 	}
 
-	regcache_cache_only(wm8962->regmap, true);
+	if (pdata && pdata->in4_dc_measure) {
+		ret = regmap_register_patch(wm8962->regmap,
+					    wm8962_dc_measure,
+					    ARRAY_SIZE(wm8962_dc_measure));
+		if (ret != 0)
+			dev_err(&i2c->dev,
+				"Failed to configure for DC mesurement: %d\n",
+				ret);
+	}
+
+	pm_runtime_enable(&i2c->dev);
+	pm_request_idle(&i2c->dev);
 
 	ret = snd_soc_register_codec(&i2c->dev,
 				     &soc_codec_dev_wm8962, &wm8962_dai, 1);
@@ -4269,6 +3695,65 @@ static __devexit int wm8962_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int wm8962_runtime_resume(struct device *dev)
+{
+	struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+				    wm8962->supplies);
+	if (ret != 0) {
+		dev_err(dev,
+			"Failed to enable supplies: %d\n", ret);
+		return ret;
+	}
+
+	regcache_cache_only(wm8962->regmap, false);
+	regcache_sync(wm8962->regmap);
+
+	regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+			   WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA,
+			   WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA);
+
+	/* Bias enable at 2*50k for ramp */
+	regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+			   WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA,
+			   WM8962_BIAS_ENA | 0x180);
+
+	msleep(5);
+
+	/* VMID back to 2x250k for standby */
+	regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+			   WM8962_VMID_SEL_MASK, 0x100);
+
+	return 0;
+}
+
+static int wm8962_runtime_suspend(struct device *dev)
+{
+	struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+
+	regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+			   WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
+
+	regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+			   WM8962_STARTUP_BIAS_ENA |
+			   WM8962_VMID_BUF_ENA, 0);
+
+	regcache_cache_only(wm8962->regmap, true);
+
+	regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
+			       wm8962->supplies);
+
+	return 0;
+}
+#endif
+
+static struct dev_pm_ops wm8962_pm = {
+	SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
+};
+
 static const struct i2c_device_id wm8962_i2c_id[] = {
 	{ "wm8962", 0 },
 	{ }
@@ -4279,34 +3764,14 @@ static struct i2c_driver wm8962_i2c_driver = {
 	.driver = {
 		.name = "wm8962",
 		.owner = THIS_MODULE,
+		.pm = &wm8962_pm,
 	},
 	.probe =    wm8962_i2c_probe,
 	.remove =   __devexit_p(wm8962_i2c_remove),
 	.id_table = wm8962_i2c_id,
 };
-#endif
-
-static int __init wm8962_modinit(void)
-{
-	int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	ret = i2c_add_driver(&wm8962_i2c_driver);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register WM8962 I2C driver: %d\n",
-		       ret);
-	}
-#endif
-	return 0;
-}
-module_init(wm8962_modinit);
 
-static void __exit wm8962_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	i2c_del_driver(&wm8962_i2c_driver);
-#endif
-}
-module_exit(wm8962_exit);
+module_i2c_driver(wm8962_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8962 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 4af893601f00e2da9c33101de59ed42ff949904b..28fe59e3ce011c4d96eac242276214b91d3d9c86 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -252,7 +252,7 @@ static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = {
 	SND_SOC_DAPM_INPUT("MIC"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8971_dapm_routes[] = {
 	/* left mixer */
 	{"Left Mixer", "Playback Switch", "Left DAC"},
 	{"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
@@ -329,17 +329,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"Right ADC", NULL, "Right ADC Mux"},
 };
 
-static int wm8971_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	snd_soc_dapm_new_controls(dapm, wm8971_dapm_widgets,
-				  ARRAY_SIZE(wm8971_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	return 0;
-}
-
 struct _coeff_div {
 	u32 mclk;
 	u32 rate;
@@ -659,10 +648,6 @@ static int wm8971_probe(struct snd_soc_codec *codec)
 	snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100);
 	snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100);
 
-	snd_soc_add_controls(codec, wm8971_snd_controls,
-				ARRAY_SIZE(wm8971_snd_controls));
-	wm8971_add_widgets(codec);
-
 	return ret;
 }
 
@@ -686,16 +671,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
 	.reg_cache_size = ARRAY_SIZE(wm8971_reg),
 	.reg_word_size = sizeof(u16),
 	.reg_cache_default = wm8971_reg,
+
+	.controls = wm8971_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8971_snd_controls),
+	.dapm_widgets = wm8971_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets),
+	.dapm_routes = wm8971_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8971_priv *wm8971;
 	int ret;
 
-	wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
+	wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
+			      GFP_KERNEL);
 	if (wm8971 == NULL)
 		return -ENOMEM;
 
@@ -704,15 +696,13 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8971, &wm8971_dai, 1);
-	if (ret < 0)
-		kfree(wm8971);
+
 	return ret;
 }
 
 static __devexit int wm8971_i2c_remove(struct i2c_client *client)
 {
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
@@ -731,27 +721,22 @@ static struct i2c_driver wm8971_i2c_driver = {
 	.remove =   __devexit_p(wm8971_i2c_remove),
 	.id_table = wm8971_i2c_id,
 };
-#endif
 
 static int __init wm8971_modinit(void)
 {
 	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&wm8971_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n",
 		       ret);
 	}
-#endif
 	return ret;
 }
 module_init(wm8971_modinit);
 
 static void __exit wm8971_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8971_i2c_driver);
-#endif
 }
 module_exit(wm8971_exit);
 
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 4a6a7b5a61ba442583cce6d1d6e6338836130f70..d93c03f820c9e802f87d2cfcd0fb7357d7b9fa15 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -48,10 +48,6 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
 #define WM8974_POWER1_BIASEN  0x08
 #define WM8974_POWER1_BUFIOEN 0x04
 
-struct wm8974_priv {
-	enum snd_soc_control_type control_type;
-};
-
 #define wm8974_reset(c)	snd_soc_write(c, WM8974_RESET, 0)
 
 static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
@@ -235,7 +231,7 @@ SND_SOC_DAPM_OUTPUT("SPKOUTP"),
 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8974_dapm_routes[] = {
 	/* Mono output mixer */
 	{"Mono Mixer", "PCM Playback Switch", "DAC"},
 	{"Mono Mixer", "Aux Playback Switch", "Aux Input"},
@@ -269,17 +265,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"Aux Input", NULL, "AUX"},
 };
 
-static int wm8974_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	snd_soc_dapm_new_controls(dapm, wm8974_dapm_widgets,
-				  ARRAY_SIZE(wm8974_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	return 0;
-}
-
 struct pll_ {
 	unsigned int pre_div:1;
 	unsigned int n:4;
@@ -611,9 +596,6 @@ static int wm8974_probe(struct snd_soc_codec *codec)
 	}
 
 	wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	snd_soc_add_controls(codec, wm8974_snd_controls,
-			     ARRAY_SIZE(wm8974_snd_controls));
-	wm8974_add_widgets(codec);
 
 	return ret;
 }
@@ -634,32 +616,30 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
 	.reg_cache_size = ARRAY_SIZE(wm8974_reg),
 	.reg_word_size = sizeof(u16),
 	.reg_cache_default = wm8974_reg,
+
+	.controls = wm8974_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8974_snd_controls),
+	.dapm_widgets = wm8974_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets),
+	.dapm_routes = wm8974_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
-	struct wm8974_priv *wm8974;
 	int ret;
 
-	wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);
-	if (wm8974 == NULL)
-		return -ENOMEM;
-
-	i2c_set_clientdata(i2c, wm8974);
-
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8974, &wm8974_dai, 1);
-	if (ret < 0)
-		kfree(wm8974);
+
 	return ret;
 }
 
 static __devexit int wm8974_i2c_remove(struct i2c_client *client)
 {
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+
 	return 0;
 }
 
@@ -678,27 +658,22 @@ static struct i2c_driver wm8974_i2c_driver = {
 	.remove =   __devexit_p(wm8974_i2c_remove),
 	.id_table = wm8974_i2c_id,
 };
-#endif
 
 static int __init wm8974_modinit(void)
 {
 	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&wm8974_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n",
 		       ret);
 	}
-#endif
 	return ret;
 }
 module_init(wm8974_modinit);
 
 static void __exit wm8974_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8974_i2c_driver);
-#endif
 }
 module_exit(wm8974_exit);
 
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 85d514d63a4c8862e9be6f7c4a751f1aa749a6ab..72d5fdcd3cc2b8b1eb6453f847eea219cb920b35 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -18,6 +18,7 @@
 #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>
@@ -29,28 +30,74 @@
 
 #include "wm8978.h"
 
-/* wm8978 register cache. Note that register 0 is not included in the cache. */
-static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
-	0x0000, 0x0000, 0x0000, 0x0000,	/* 0x00...0x03 */
-	0x0050, 0x0000, 0x0140, 0x0000,	/* 0x04...0x07 */
-	0x0000, 0x0000, 0x0000, 0x00ff,	/* 0x08...0x0b */
-	0x00ff, 0x0000, 0x0100, 0x00ff,	/* 0x0c...0x0f */
-	0x00ff, 0x0000, 0x012c, 0x002c,	/* 0x10...0x13 */
-	0x002c, 0x002c, 0x002c, 0x0000,	/* 0x14...0x17 */
-	0x0032, 0x0000, 0x0000, 0x0000,	/* 0x18...0x1b */
-	0x0000, 0x0000, 0x0000, 0x0000,	/* 0x1c...0x1f */
-	0x0038, 0x000b, 0x0032, 0x0000,	/* 0x20...0x23 */
-	0x0008, 0x000c, 0x0093, 0x00e9,	/* 0x24...0x27 */
-	0x0000, 0x0000, 0x0000, 0x0000,	/* 0x28...0x2b */
-	0x0033, 0x0010, 0x0010, 0x0100,	/* 0x2c...0x2f */
-	0x0100, 0x0002, 0x0001, 0x0001,	/* 0x30...0x33 */
-	0x0039, 0x0039, 0x0039, 0x0039,	/* 0x34...0x37 */
-	0x0001,	0x0001,			/* 0x38...0x3b */
+static const struct reg_default wm8978_reg_defaults[] = {
+	{ 1, 0x0000 },
+	{ 2, 0x0000 },
+	{ 3, 0x0000 },
+	{ 4, 0x0050 },
+	{ 5, 0x0000 },
+	{ 6, 0x0140 },
+	{ 7, 0x0000 },
+	{ 8, 0x0000 },
+	{ 9, 0x0000 },
+	{ 10, 0x0000 },
+	{ 11, 0x00ff },
+	{ 12, 0x00ff },
+	{ 13, 0x0000 },
+	{ 14, 0x0100 },
+	{ 15, 0x00ff },
+	{ 16, 0x00ff },
+	{ 17, 0x0000 },
+	{ 18, 0x012c },
+	{ 19, 0x002c },
+	{ 20, 0x002c },
+	{ 21, 0x002c },
+	{ 22, 0x002c },
+	{ 23, 0x0000 },
+	{ 24, 0x0032 },
+	{ 25, 0x0000 },
+	{ 26, 0x0000 },
+	{ 27, 0x0000 },
+	{ 28, 0x0000 },
+	{ 29, 0x0000 },
+	{ 30, 0x0000 },
+	{ 31, 0x0000 },
+	{ 32, 0x0038 },
+	{ 33, 0x000b },
+	{ 34, 0x0032 },
+	{ 35, 0x0000 },
+	{ 36, 0x0008 },
+	{ 37, 0x000c },
+	{ 38, 0x0093 },
+	{ 39, 0x00e9 },
+	{ 40, 0x0000 },
+	{ 41, 0x0000 },
+	{ 42, 0x0000 },
+	{ 43, 0x0000 },
+	{ 44, 0x0033 },
+	{ 45, 0x0010 },
+	{ 46, 0x0010 },
+	{ 47, 0x0100 },
+	{ 48, 0x0100 },
+	{ 49, 0x0002 },
+	{ 50, 0x0001 },
+	{ 51, 0x0001 },
+	{ 52, 0x0039 },
+	{ 53, 0x0039 },
+	{ 54, 0x0039 },
+	{ 55, 0x0039 },
+	{ 56, 0x0001 },
+	{ 57, 0x0001 },
 };
 
+static bool wm8978_volatile(struct device *dev, unsigned int reg)
+{
+	return reg == WM8978_RESET;
+}
+
 /* codec private data */
 struct wm8978_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 	unsigned int f_pllout;
 	unsigned int f_mclk;
 	unsigned int f_256fs;
@@ -303,7 +350,7 @@ static const struct snd_soc_dapm_widget wm8978_dapm_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("RSPK"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8978_dapm_routes[] = {
 	/* Output mixer */
 	{"Right Output Mixer", "PCM Playback Switch", "Right DAC"},
 	{"Right Output Mixer", "Aux Playback Switch", "RAUX"},
@@ -352,18 +399,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"Left Input Mixer", "MicP Switch", "LMICP"},
 };
 
-static int wm8978_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	snd_soc_dapm_new_controls(dapm, wm8978_dapm_widgets,
-				  ARRAY_SIZE(wm8978_dapm_widgets));
-	/* set up the WM8978 audio map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	return 0;
-}
-
 /* PLL divisors */
 struct wm8978_pll_div {
 	u32 k;
@@ -894,26 +929,23 @@ static struct snd_soc_dai_driver wm8978_dai = {
 
 static int wm8978_suspend(struct snd_soc_codec *codec)
 {
+	struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
+
 	wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	/* Also switch PLL off */
 	snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0);
 
+	regcache_mark_dirty(wm8978->regmap);
+
 	return 0;
 }
 
 static int wm8978_resume(struct snd_soc_codec *codec)
 {
 	struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
-	int i;
-	u16 *cache = codec->reg_cache;
 
 	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8978_reg); i++) {
-		if (i == WM8978_RESET)
-			continue;
-		if (cache[i] != wm8978_reg[i])
-			snd_soc_write(codec, i, cache[i]);
-	}
+	regcache_sync(wm8978->regmap);
 
 	wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -953,7 +985,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
 	 * default hardware setting
 	 */
 	wm8978->sysclk = WM8978_PLL;
-	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
+	codec->control_data = wm8978->regmap;
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -967,19 +1000,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
 	for (i = 0; i < ARRAY_SIZE(update_reg); i++)
 		snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100);
 
-	/* Reset the codec */
-	ret = snd_soc_write(codec, WM8978_RESET, 0);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to issue reset\n");
-		return ret;
-	}
-
 	wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	snd_soc_add_controls(codec, wm8978_snd_controls,
-			     ARRAY_SIZE(wm8978_snd_controls));
-	wm8978_add_widgets(codec);
-
 	return 0;
 }
 
@@ -996,35 +1018,75 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
 	.suspend =	wm8978_suspend,
 	.resume =	wm8978_resume,
 	.set_bias_level = wm8978_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8978_reg),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8978_reg,
+
+	.controls = wm8978_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8978_snd_controls),
+	.dapm_widgets = wm8978_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets),
+	.dapm_routes = wm8978_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes),
+};
+
+static const struct regmap_config wm8978_regmap_config = {
+	.reg_bits = 7,
+	.val_bits = 9,
+
+	.max_register = WM8978_MAX_REGISTER,
+	.volatile_reg = wm8978_volatile,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8978_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8978_priv *wm8978;
 	int ret;
 
-	wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL);
+	wm8978 = devm_kzalloc(&i2c->dev, sizeof(struct wm8978_priv),
+			      GFP_KERNEL);
 	if (wm8978 == NULL)
 		return -ENOMEM;
 
+	wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config);
+	if (IS_ERR(wm8978->regmap)) {
+		ret = PTR_ERR(wm8978->regmap);
+		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+		return ret;
+	}
+
 	i2c_set_clientdata(i2c, wm8978);
 
+	/* Reset the codec */
+	ret = regmap_write(wm8978->regmap, WM8978_RESET, 0);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
+		goto err;
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8978, &wm8978_dai, 1);
-	if (ret < 0)
-		kfree(wm8978);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	regmap_exit(wm8978->regmap);
 	return ret;
 }
 
 static __devexit int wm8978_i2c_remove(struct i2c_client *client)
 {
+	struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
+
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm8978->regmap);
+
 	return 0;
 }
 
@@ -1043,27 +1105,22 @@ static struct i2c_driver wm8978_i2c_driver = {
 	.remove =   __devexit_p(wm8978_i2c_remove),
 	.id_table = wm8978_i2c_id,
 };
-#endif
 
 static int __init wm8978_modinit(void)
 {
 	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&wm8978_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n",
 		       ret);
 	}
-#endif
 	return ret;
 }
 module_init(wm8978_modinit);
 
 static void __exit wm8978_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&wm8978_i2c_driver);
-#endif
 }
 module_exit(wm8978_exit);
 
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h
index c75525b7f154c9fe25e88a91cb55e99d7e0b37c2..6ae43495b7cf922f171b4afc77b83c3b78ad5754 100644
--- a/sound/soc/codecs/wm8978.h
+++ b/sound/soc/codecs/wm8978.h
@@ -67,6 +67,8 @@
 #define WM8978_OUT3_MIXER_CONTROL		0x38
 #define WM8978_OUT4_MIXER_CONTROL		0x39
 
+#define WM8978_MAX_REGISTER			0x39
+
 #define WM8978_CACHEREGNUM			58
 
 /* Clock divider Id's */
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index cebde568d1919a0e961601b1e308be8ebb1accc8..367388fdc486484202e4bb550420bdcda31a8fdf 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -249,9 +249,6 @@ static const char *eq5_cutoff_text[] = {
 static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5,
 				  eq5_cutoff_text);
 
-static const char *speaker_mode_text[] = { "Class A/B", "Class D" };
-static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
-
 static const char *depth_3d_text[] = {
 	"Off",
 	"6.67%",
@@ -369,8 +366,6 @@ static const struct snd_kcontrol_new wm8983_snd_controls[] = {
 	SOC_SINGLE_TLV("EQ5 Volume", WM8983_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),
 
 	SOC_ENUM("3D Depth", depth_3d),
-
-	SOC_ENUM("Speaker Mode", speaker_mode)
 };
 
 static const struct snd_kcontrol_new left_out_mixer[] = {
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index c0c86b3c6adf69076be221308d0fe0fcc48a1c08..14f666398d0c9a0bb7677fa6a1bdbac43125c0fe 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
@@ -39,73 +40,127 @@ static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = {
 	"AVDD2"
 };
 
-static const u16 wm8985_reg_defs[] = {
-	0x0000,     /* R0  - Software Reset */
-	0x0000,     /* R1  - Power management 1 */
-	0x0000,     /* R2  - Power management 2 */
-	0x0000,     /* R3  - Power management 3 */
-	0x0050,     /* R4  - Audio Interface */
-	0x0000,     /* R5  - Companding control */
-	0x0140,     /* R6  - Clock Gen control */
-	0x0000,     /* R7  - Additional control */
-	0x0000,     /* R8  - GPIO Control */
-	0x0000,     /* R9  - Jack Detect Control 1 */
-	0x0000,     /* R10 - DAC Control */
-	0x00FF,     /* R11 - Left DAC digital Vol */
-	0x00FF,     /* R12 - Right DAC digital vol */
-	0x0000,     /* R13 - Jack Detect Control 2 */
-	0x0100,     /* R14 - ADC Control */
-	0x00FF,     /* R15 - Left ADC Digital Vol */
-	0x00FF,     /* R16 - Right ADC Digital Vol */
-	0x0000,     /* R17 */
-	0x012C,     /* R18 - EQ1 - low shelf */
-	0x002C,     /* R19 - EQ2 - peak 1 */
-	0x002C,     /* R20 - EQ3 - peak 2 */
-	0x002C,     /* R21 - EQ4 - peak 3 */
-	0x002C,     /* R22 - EQ5 - high shelf */
-	0x0000,     /* R23 */
-	0x0032,     /* R24 - DAC Limiter 1 */
-	0x0000,     /* R25 - DAC Limiter 2 */
-	0x0000,     /* R26 */
-	0x0000,     /* R27 - Notch Filter 1 */
-	0x0000,     /* R28 - Notch Filter 2 */
-	0x0000,     /* R29 - Notch Filter 3 */
-	0x0000,     /* R30 - Notch Filter 4 */
-	0x0000,     /* R31 */
-	0x0038,     /* R32 - ALC control 1 */
-	0x000B,     /* R33 - ALC control 2 */
-	0x0032,     /* R34 - ALC control 3 */
-	0x0000,     /* R35 - Noise Gate */
-	0x0008,     /* R36 - PLL N */
-	0x000C,     /* R37 - PLL K 1 */
-	0x0093,     /* R38 - PLL K 2 */
-	0x00E9,     /* R39 - PLL K 3 */
-	0x0000,     /* R40 */
-	0x0000,     /* R41 - 3D control */
-	0x0000,     /* R42 - OUT4 to ADC */
-	0x0000,     /* R43 - Beep control */
-	0x0033,     /* R44 - Input ctrl */
-	0x0010,     /* R45 - Left INP PGA gain ctrl */
-	0x0010,     /* R46 - Right INP PGA gain ctrl */
-	0x0100,     /* R47 - Left ADC BOOST ctrl */
-	0x0100,     /* R48 - Right ADC BOOST ctrl */
-	0x0002,     /* R49 - Output ctrl */
-	0x0001,     /* R50 - Left mixer ctrl */
-	0x0001,     /* R51 - Right mixer ctrl */
-	0x0039,     /* R52 - LOUT1 (HP) volume ctrl */
-	0x0039,     /* R53 - ROUT1 (HP) volume ctrl */
-	0x0039,     /* R54 - LOUT2 (SPK) volume ctrl */
-	0x0039,     /* R55 - ROUT2 (SPK) volume ctrl */
-	0x0001,     /* R56 - OUT3 mixer ctrl */
-	0x0001,     /* R57 - OUT4 (MONO) mix ctrl */
-	0x0001,     /* R58 */
-	0x0000,     /* R59 */
-	0x0004,     /* R60 - OUTPUT ctrl */
-	0x0000,     /* R61 - BIAS CTRL */
-	0x0180,     /* R62 */
-	0x0000      /* R63 */
+static const struct reg_default wm8985_reg_defaults[] = {
+	{ 1,  0x0000 },     /* R1  - Power management 1 */
+	{ 2,  0x0000 },     /* R2  - Power management 2 */
+	{ 3,  0x0000 },     /* R3  - Power management 3 */
+	{ 4,  0x0050 },     /* R4  - Audio Interface */
+	{ 5,  0x0000 },     /* R5  - Companding control */
+	{ 6,  0x0140 },     /* R6  - Clock Gen control */
+	{ 7,  0x0000 },     /* R7  - Additional control */
+	{ 8,  0x0000 },     /* R8  - GPIO Control */
+	{ 9,  0x0000 },     /* R9  - Jack Detect Control 1 */
+	{ 10, 0x0000 },     /* R10 - DAC Control */
+	{ 11, 0x00FF },     /* R11 - Left DAC digital Vol */
+	{ 12, 0x00FF },     /* R12 - Right DAC digital vol */
+	{ 13, 0x0000 },     /* R13 - Jack Detect Control 2 */
+	{ 14, 0x0100 },     /* R14 - ADC Control */
+	{ 15, 0x00FF },     /* R15 - Left ADC Digital Vol */
+	{ 16, 0x00FF },     /* R16 - Right ADC Digital Vol */
+	{ 18, 0x012C },     /* R18 - EQ1 - low shelf */
+	{ 19, 0x002C },     /* R19 - EQ2 - peak 1 */
+	{ 20, 0x002C },     /* R20 - EQ3 - peak 2 */
+	{ 21, 0x002C },     /* R21 - EQ4 - peak 3 */
+	{ 22, 0x002C },     /* R22 - EQ5 - high shelf */
+	{ 24, 0x0032 },     /* R24 - DAC Limiter 1 */
+	{ 25, 0x0000 },     /* R25 - DAC Limiter 2 */
+	{ 27, 0x0000 },     /* R27 - Notch Filter 1 */
+	{ 28, 0x0000 },     /* R28 - Notch Filter 2 */
+	{ 29, 0x0000 },     /* R29 - Notch Filter 3 */
+	{ 30, 0x0000 },     /* R30 - Notch Filter 4 */
+	{ 32, 0x0038 },     /* R32 - ALC control 1 */
+	{ 33, 0x000B },     /* R33 - ALC control 2 */
+	{ 34, 0x0032 },     /* R34 - ALC control 3 */
+	{ 35, 0x0000 },     /* R35 - Noise Gate */
+	{ 36, 0x0008 },     /* R36 - PLL N */
+	{ 37, 0x000C },     /* R37 - PLL K 1 */
+	{ 38, 0x0093 },     /* R38 - PLL K 2 */
+	{ 39, 0x00E9 },     /* R39 - PLL K 3 */
+	{ 41, 0x0000 },     /* R41 - 3D control */
+	{ 42, 0x0000 },     /* R42 - OUT4 to ADC */
+	{ 43, 0x0000 },     /* R43 - Beep control */
+	{ 44, 0x0033 },     /* R44 - Input ctrl */
+	{ 45, 0x0010 },     /* R45 - Left INP PGA gain ctrl */
+	{ 46, 0x0010 },     /* R46 - Right INP PGA gain ctrl */
+	{ 47, 0x0100 },     /* R47 - Left ADC BOOST ctrl */
+	{ 48, 0x0100 },     /* R48 - Right ADC BOOST ctrl */
+	{ 49, 0x0002 },     /* R49 - Output ctrl */
+	{ 50, 0x0001 },     /* R50 - Left mixer ctrl */
+	{ 51, 0x0001 },     /* R51 - Right mixer ctrl */
+	{ 52, 0x0039 },     /* R52 - LOUT1 (HP) volume ctrl */
+	{ 53, 0x0039 },     /* R53 - ROUT1 (HP) volume ctrl */
+	{ 54, 0x0039 },     /* R54 - LOUT2 (SPK) volume ctrl */
+	{ 55, 0x0039 },     /* R55 - ROUT2 (SPK) volume ctrl */
+	{ 56, 0x0001 },     /* R56 - OUT3 mixer ctrl */
+	{ 57, 0x0001 },     /* R57 - OUT4 (MONO) mix ctrl */
+	{ 60, 0x0004 },     /* R60 - OUTPUT ctrl */
+	{ 61, 0x0000 },     /* R61 - BIAS CTRL */
 };
 
+static bool wm8985_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM8985_SOFTWARE_RESET:
+	case WM8985_POWER_MANAGEMENT_1:
+	case WM8985_POWER_MANAGEMENT_2:
+	case WM8985_POWER_MANAGEMENT_3:
+	case WM8985_AUDIO_INTERFACE:
+	case WM8985_COMPANDING_CONTROL:
+	case WM8985_CLOCK_GEN_CONTROL:
+	case WM8985_ADDITIONAL_CONTROL:
+	case WM8985_GPIO_CONTROL:
+	case WM8985_JACK_DETECT_CONTROL_1:
+	case WM8985_DAC_CONTROL:
+	case WM8985_LEFT_DAC_DIGITAL_VOL:
+	case WM8985_RIGHT_DAC_DIGITAL_VOL:
+	case WM8985_JACK_DETECT_CONTROL_2:
+	case WM8985_ADC_CONTROL:
+	case WM8985_LEFT_ADC_DIGITAL_VOL:
+	case WM8985_RIGHT_ADC_DIGITAL_VOL:
+	case WM8985_EQ1_LOW_SHELF:
+	case WM8985_EQ2_PEAK_1:
+	case WM8985_EQ3_PEAK_2:
+	case WM8985_EQ4_PEAK_3:
+	case WM8985_EQ5_HIGH_SHELF:
+	case WM8985_DAC_LIMITER_1:
+	case WM8985_DAC_LIMITER_2:
+	case WM8985_NOTCH_FILTER_1:
+	case WM8985_NOTCH_FILTER_2:
+	case WM8985_NOTCH_FILTER_3:
+	case WM8985_NOTCH_FILTER_4:
+	case WM8985_ALC_CONTROL_1:
+	case WM8985_ALC_CONTROL_2:
+	case WM8985_ALC_CONTROL_3:
+	case WM8985_NOISE_GATE:
+	case WM8985_PLL_N:
+	case WM8985_PLL_K_1:
+	case WM8985_PLL_K_2:
+	case WM8985_PLL_K_3:
+	case WM8985_3D_CONTROL:
+	case WM8985_OUT4_TO_ADC:
+	case WM8985_BEEP_CONTROL:
+	case WM8985_INPUT_CTRL:
+	case WM8985_LEFT_INP_PGA_GAIN_CTRL:
+	case WM8985_RIGHT_INP_PGA_GAIN_CTRL:
+	case WM8985_LEFT_ADC_BOOST_CTRL:
+	case WM8985_RIGHT_ADC_BOOST_CTRL:
+	case WM8985_OUTPUT_CTRL0:
+	case WM8985_LEFT_MIXER_CTRL:
+	case WM8985_RIGHT_MIXER_CTRL:
+	case WM8985_LOUT1_HP_VOLUME_CTRL:
+	case WM8985_ROUT1_HP_VOLUME_CTRL:
+	case WM8985_LOUT2_SPK_VOLUME_CTRL:
+	case WM8985_ROUT2_SPK_VOLUME_CTRL:
+	case WM8985_OUT3_MIXER_CTRL:
+	case WM8985_OUT4_MONO_MIX_CTRL:
+	case WM8985_OUTPUT_CTRL1:
+	case WM8985_BIAS_CTRL:
+		return true;
+	default:
+		return false;
+	}
+}
+
 /*
  * latch bit 8 of these registers to ensure instant
  * volume updates
@@ -124,7 +179,7 @@ static const int volume_update_regs[] = {
 };
 
 struct wm8985_priv {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 	struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES];
 	unsigned int sysclk;
 	unsigned int bclk;
@@ -428,7 +483,7 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("SPKR")
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
 	{ "Right Output Mixer", "PCM Switch", "Right DAC" },
 	{ "Right Output Mixer", "Aux Switch", "AUXR" },
 	{ "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
@@ -531,17 +586,6 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static int wm8985_add_widgets(struct snd_soc_codec *codec)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	snd_soc_dapm_new_controls(dapm, wm8985_dapm_widgets,
-				  ARRAY_SIZE(wm8985_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, audio_map,
-				ARRAY_SIZE(audio_map));
-	return 0;
-}
-
 static int wm8985_reset(struct snd_soc_codec *codec)
 {
 	return snd_soc_write(codec, WM8985_SOFTWARE_RESET, 0x0);
@@ -845,25 +889,6 @@ static int wm8985_set_sysclk(struct snd_soc_dai *dai,
 	return 0;
 }
 
-static void wm8985_sync_cache(struct snd_soc_codec *codec)
-{
-	short i;
-	u16 *cache;
-
-	if (!codec->cache_sync)
-		return;
-	codec->cache_only = 0;
-	/* restore cache */
-	cache = codec->reg_cache;
-	for (i = 0; i < codec->driver->reg_cache_size; i++) {
-		if (i == WM8985_SOFTWARE_RESET
-				|| cache[i] == wm8985_reg_defs[i])
-			continue;
-		snd_soc_write(codec, i, cache[i]);
-	}
-	codec->cache_sync = 0;
-}
-
 static int wm8985_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
@@ -890,7 +915,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
 				return ret;
 			}
 
-			wm8985_sync_cache(codec);
+			regcache_sync(wm8985->regmap);
 
 			/* enable anti-pop features */
 			snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
@@ -933,7 +958,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
 		snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, 0);
 		snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, 0);
 
-		codec->cache_sync = 1;
+		regcache_mark_dirty(wm8985->regmap);
 
 		regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies),
 				       wm8985->supplies);
@@ -976,11 +1001,11 @@ static int wm8985_probe(struct snd_soc_codec *codec)
 	size_t i;
 	struct wm8985_priv *wm8985;
 	int ret;
-	u16 *cache;
 
 	wm8985 = snd_soc_codec_get_drvdata(codec);
+	codec->control_data = wm8985->regmap;
 
-	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8985->control_type);
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
 		return ret;
@@ -1009,17 +1034,13 @@ static int wm8985_probe(struct snd_soc_codec *codec)
 		goto err_reg_enable;
 	}
 
-	cache = codec->reg_cache;
 	/* latch volume update bits */
 	for (i = 0; i < ARRAY_SIZE(volume_update_regs); ++i)
-		cache[volume_update_regs[i]] |= 0x100;
+		snd_soc_update_bits(codec, volume_update_regs[i],
+				    0x100, 0x100);
 	/* enable BIASCUT */
-	cache[WM8985_BIAS_CTRL] |= WM8985_BIASCUT;
-	codec->cache_sync = 1;
-
-	snd_soc_add_controls(codec, wm8985_snd_controls,
-			     ARRAY_SIZE(wm8985_snd_controls));
-	wm8985_add_widgets(codec);
+	snd_soc_update_bits(codec, WM8985_BIAS_CTRL, WM8985_BIASCUT,
+			    WM8985_BIASCUT);
 
 	wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	return 0;
@@ -1068,9 +1089,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8985 = {
 	.suspend = wm8985_suspend,
 	.resume = wm8985_resume,
 	.set_bias_level = wm8985_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8985_reg_defs),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8985_reg_defs
+
+	.controls = wm8985_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8985_snd_controls),
+	.dapm_widgets = wm8985_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8985_dapm_widgets),
+	.dapm_routes = wm8985_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm8985_dapm_routes),
+};
+
+static const struct regmap_config wm8985_regmap = {
+	.reg_bits = 7,
+	.val_bits = 9,
+
+	.max_register = WM8985_MAX_REGISTER,
+	.writeable_reg = wm8985_writeable,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8985_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8985_reg_defaults),
 };
 
 #if defined(CONFIG_SPI_MASTER)
@@ -1079,24 +1116,39 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi)
 	struct wm8985_priv *wm8985;
 	int ret;
 
-	wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+	wm8985 = devm_kzalloc(&spi->dev, sizeof *wm8985, GFP_KERNEL);
 	if (!wm8985)
 		return -ENOMEM;
 
-	wm8985->control_type = SND_SOC_SPI;
 	spi_set_drvdata(spi, wm8985);
 
+	wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap);
+	if (IS_ERR(wm8985->regmap)) {
+		ret = PTR_ERR(wm8985->regmap);
+		dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err;
+	}
+
 	ret = snd_soc_register_codec(&spi->dev,
 				     &soc_codec_dev_wm8985, &wm8985_dai, 1);
-	if (ret < 0)
-		kfree(wm8985);
+	if (ret != 0)
+		goto err;
+
+	return 0;
+
+err:
+	regmap_exit(wm8985->regmap);
 	return ret;
 }
 
 static int __devexit wm8985_spi_remove(struct spi_device *spi)
 {
+	struct wm8985_priv *wm8985 = spi_get_drvdata(spi);
+
 	snd_soc_unregister_codec(&spi->dev);
-	kfree(spi_get_drvdata(spi));
+	regmap_exit(wm8985->regmap);
+
 	return 0;
 }
 
@@ -1117,24 +1169,39 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
 	struct wm8985_priv *wm8985;
 	int ret;
 
-	wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+	wm8985 = devm_kzalloc(&i2c->dev, sizeof *wm8985, GFP_KERNEL);
 	if (!wm8985)
 		return -ENOMEM;
 
-	wm8985->control_type = SND_SOC_I2C;
 	i2c_set_clientdata(i2c, wm8985);
 
+	wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap);
+	if (IS_ERR(wm8985->regmap)) {
+		ret = PTR_ERR(wm8985->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		goto err;
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev,
 				     &soc_codec_dev_wm8985, &wm8985_dai, 1);
-	if (ret < 0)
-		kfree(wm8985);
+	if (ret != 0)
+		goto err;
+
+	return 0;
+
+err:
+	regmap_exit(wm8985->regmap);
 	return ret;
 }
 
-static __devexit int wm8985_i2c_remove(struct i2c_client *client)
+static __devexit int wm8985_i2c_remove(struct i2c_client *i2c)
 {
-	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c);
+
+	snd_soc_unregister_codec(&i2c->dev);
+	regmap_exit(wm8985->regmap);
+
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index ab52963dd04c976a21fab1badfffb6f775f30de7..6cdf6a2bc28304db51b59128584689bfcc29139c 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -33,24 +33,89 @@
  * We can't read the WM8988 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8988_reg[] = {
-	0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
-	0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
-	0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
-	0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
-	0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
-	0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
-	0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
-	0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
-	0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
-	0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
-	0x0079, 0x0079, 0x0079,          /* 40 */
+static const struct reg_default wm8988_reg_defaults[] = {
+	{ 0, 0x0097 },
+	{ 1, 0x0097 },
+	{ 2, 0x0079 },
+	{ 3, 0x0079 },
+	{ 5, 0x0008 },
+	{ 7, 0x000a },
+	{ 8, 0x0000 },
+	{ 10, 0x00ff },
+	{ 11, 0x00ff },
+	{ 12, 0x000f },
+	{ 13, 0x000f },
+	{ 16, 0x0000 },
+	{ 17, 0x007b },
+	{ 18, 0x0000 },
+	{ 19, 0x0032 },
+	{ 20, 0x0000 },
+	{ 21, 0x00c3 },
+	{ 22, 0x00c3 },
+	{ 23, 0x00c0 },
+	{ 24, 0x0000 },
+	{ 25, 0x0000 },
+	{ 26, 0x0000 },
+	{ 27, 0x0000 },
+	{ 31, 0x0000 },
+	{ 32, 0x0000 },
+	{ 33, 0x0000 },
+	{ 34, 0x0050 },
+	{ 35, 0x0050 },
+	{ 36, 0x0050 },
+	{ 37, 0x0050 },
+	{ 40, 0x0079 },
+	{ 41, 0x0079 },
+	{ 42, 0x0079 },
 };
 
+static bool wm8988_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM8988_LINVOL:
+	case WM8988_RINVOL:
+	case WM8988_LOUT1V:
+	case WM8988_ROUT1V:
+	case WM8988_ADCDAC:
+	case WM8988_IFACE:
+	case WM8988_SRATE:
+	case WM8988_LDAC:
+	case WM8988_RDAC:
+	case WM8988_BASS:
+	case WM8988_TREBLE:
+	case WM8988_RESET:
+	case WM8988_3D:
+	case WM8988_ALC1:
+	case WM8988_ALC2:
+	case WM8988_ALC3:
+	case WM8988_NGATE:
+	case WM8988_LADC:
+	case WM8988_RADC:
+	case WM8988_ADCTL1:
+	case WM8988_ADCTL2:
+	case WM8988_PWR1:
+	case WM8988_PWR2:
+	case WM8988_ADCTL3:
+	case WM8988_ADCIN:
+	case WM8988_LADCIN:
+	case WM8988_RADCIN:
+	case WM8988_LOUTM1:
+	case WM8988_LOUTM2:
+	case WM8988_ROUTM1:
+	case WM8988_ROUTM2:
+	case WM8988_LOUT2V:
+	case WM8988_ROUT2V:
+	case WM8988_LPPB:
+		return true;
+	default:
+		return false;
+	}
+}
+
 /* codec private data */
 struct wm8988_priv {
+	struct regmap *regmap;
 	unsigned int sysclk;
-	enum snd_soc_control_type control_type;
 	struct snd_pcm_hw_constraint_list *sysclk_constraints;
 };
 
@@ -317,7 +382,7 @@ static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
 	SND_SOC_DAPM_INPUT("RINPUT2"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8988_dapm_routes[] = {
 
 	{ "Left Line Mux", "Line 1", "LINPUT1" },
 	{ "Left Line Mux", "Line 2", "LINPUT2" },
@@ -661,6 +726,7 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute)
 static int wm8988_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
+	struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
 	u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
 
 	switch (level) {
@@ -674,7 +740,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
 
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-			snd_soc_cache_sync(codec);
+			regcache_sync(wm8988->regmap);
 
 			/* VREF, VMID=2x5k */
 			snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
@@ -730,7 +796,10 @@ static struct snd_soc_dai_driver wm8988_dai = {
 
 static int wm8988_suspend(struct snd_soc_codec *codec)
 {
+	struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
+
 	wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	regcache_mark_dirty(wm8988->regmap);
 	return 0;
 }
 
@@ -743,10 +812,10 @@ static int wm8988_resume(struct snd_soc_codec *codec)
 static int wm8988_probe(struct snd_soc_codec *codec)
 {
 	struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret = 0;
 
-	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
+	codec->control_data = wm8988->regmap;
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -767,12 +836,6 @@ static int wm8988_probe(struct snd_soc_codec *codec)
 
 	wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	snd_soc_add_controls(codec, wm8988_snd_controls,
-				ARRAY_SIZE(wm8988_snd_controls));
-	snd_soc_dapm_new_controls(dapm, wm8988_dapm_widgets,
-				  ARRAY_SIZE(wm8988_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
 	return 0;
 }
 
@@ -788,9 +851,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
 	.suspend =	wm8988_suspend,
 	.resume =	wm8988_resume,
 	.set_bias_level = wm8988_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8988_reg),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8988_reg,
+
+	.controls = wm8988_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8988_snd_controls),
+	.dapm_widgets = wm8988_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets),
+	.dapm_routes = wm8988_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
+};
+
+static struct regmap_config wm8988_regmap = {
+	.reg_bits = 7,
+	.val_bits = 9,
+
+	.max_register = WM8988_LPPB,
+	.writeable_reg = wm8988_writeable,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8988_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults),
 };
 
 #if defined(CONFIG_SPI_MASTER)
@@ -799,24 +878,33 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
 	struct wm8988_priv *wm8988;
 	int ret;
 
-	wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+	wm8988 = devm_kzalloc(&spi->dev, sizeof(struct wm8988_priv),
+			      GFP_KERNEL);
 	if (wm8988 == NULL)
 		return -ENOMEM;
 
-	wm8988->control_type = SND_SOC_SPI;
+	wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
+	if (IS_ERR(wm8988->regmap)) {
+		ret = PTR_ERR(wm8988->regmap);
+		dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
+		return ret;
+	}
+
 	spi_set_drvdata(spi, wm8988);
 
 	ret = snd_soc_register_codec(&spi->dev,
 			&soc_codec_dev_wm8988, &wm8988_dai, 1);
-	if (ret < 0)
-		kfree(wm8988);
+	if (ret != 0)
+		regmap_exit(wm8988->regmap);
+
 	return ret;
 }
 
 static int __devexit wm8988_spi_remove(struct spi_device *spi)
 {
+	struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
 	snd_soc_unregister_codec(&spi->dev);
-	kfree(spi_get_drvdata(spi));
+	regmap_exit(wm8988->regmap);
 	return 0;
 }
 
@@ -837,24 +925,33 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
 	struct wm8988_priv *wm8988;
 	int ret;
 
-	wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+	wm8988 = devm_kzalloc(&i2c->dev, sizeof(struct wm8988_priv),
+			      GFP_KERNEL);
 	if (wm8988 == NULL)
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm8988);
-	wm8988->control_type = SND_SOC_I2C;
+
+	wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
+	if (IS_ERR(wm8988->regmap)) {
+		ret = PTR_ERR(wm8988->regmap);
+		dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+		return ret;
+	}
 
 	ret =  snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8988, &wm8988_dai, 1);
-	if (ret < 0)
-		kfree(wm8988);
+	if (ret != 0)
+		regmap_exit(wm8988->regmap);
+
 	return ret;
 }
 
 static __devexit int wm8988_i2c_remove(struct i2c_client *client)
 {
+	struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
 	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	regmap_exit(wm8988->regmap);
 	return 0;
 }
 
@@ -866,7 +963,7 @@ MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
 
 static struct i2c_driver wm8988_i2c_driver = {
 	.driver = {
-		.name = "wm8988-codec",
+		.name = "wm8988",
 		.owner = THIS_MODULE,
 	},
 	.probe =    wm8988_i2c_probe,
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index e538edaae1f0dbd6d9cdd82f34bb8bc232b7b549..9d242351e6e837211c70ffb37033874830ccb8b3 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1356,7 +1356,7 @@ static int wm8990_probe(struct snd_soc_codec *codec)
 	snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
 	snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-	snd_soc_add_controls(codec, wm8990_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8990_snd_controls,
 				ARRAY_SIZE(wm8990_snd_controls));
 	wm8990_add_widgets(codec);
 
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index 7ee40da8dbb52021db9427ec84f7b2751236b7d5..9ac31ba9b82e1ad635167baa38563da16d1e6ee2 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -1297,7 +1297,7 @@ static int wm8991_probe(struct snd_soc_codec *codec)
 	snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
 	snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-	snd_soc_add_controls(codec, wm8991_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8991_snd_controls,
 			     ARRAY_SIZE(wm8991_snd_controls));
 
 	snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 7c7fd925db8da78c1ad6bb08bdde66eb60d7210b..d256a934064490abb621b738020463e30490610b 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
@@ -40,134 +41,113 @@ static const char *wm8993_supply_names[WM8993_NUM_SUPPLIES] = {
 	"SPKVDD",
 };
 
-static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = {
-	0x8993,     /* R0   - Software Reset */
-	0x0000,     /* R1   - Power Management (1) */
-	0x6000,     /* R2   - Power Management (2) */
-	0x0000,     /* R3   - Power Management (3) */
-	0x4050,     /* R4   - Audio Interface (1) */
-	0x4000,     /* R5   - Audio Interface (2) */
-	0x01C8,     /* R6   - Clocking 1 */
-	0x0000,     /* R7   - Clocking 2 */
-	0x0000,     /* R8   - Audio Interface (3) */
-	0x0040,     /* R9   - Audio Interface (4) */
-	0x0004,     /* R10  - DAC CTRL */
-	0x00C0,     /* R11  - Left DAC Digital Volume */
-	0x00C0,     /* R12  - Right DAC Digital Volume */
-	0x0000,     /* R13  - Digital Side Tone */
-	0x0300,     /* R14  - ADC CTRL */
-	0x00C0,     /* R15  - Left ADC Digital Volume */
-	0x00C0,     /* R16  - Right ADC Digital Volume */
-	0x0000,     /* R17 */
-	0x0000,     /* R18  - GPIO CTRL 1 */
-	0x0010,     /* R19  - GPIO1 */
-	0x0000,     /* R20  - IRQ_DEBOUNCE */
-	0x0000,     /* R21 */
-	0x8000,     /* R22  - GPIOCTRL 2 */
-	0x0800,     /* R23  - GPIO_POL */
-	0x008B,     /* R24  - Left Line Input 1&2 Volume */
-	0x008B,     /* R25  - Left Line Input 3&4 Volume */
-	0x008B,     /* R26  - Right Line Input 1&2 Volume */
-	0x008B,     /* R27  - Right Line Input 3&4 Volume */
-	0x006D,     /* R28  - Left Output Volume */
-	0x006D,     /* R29  - Right Output Volume */
-	0x0066,     /* R30  - Line Outputs Volume */
-	0x0020,     /* R31  - HPOUT2 Volume */
-	0x0079,     /* R32  - Left OPGA Volume */
-	0x0079,     /* R33  - Right OPGA Volume */
-	0x0003,     /* R34  - SPKMIXL Attenuation */
-	0x0003,     /* R35  - SPKMIXR Attenuation */
-	0x0011,     /* R36  - SPKOUT Mixers */
-	0x0100,     /* R37  - SPKOUT Boost */
-	0x0079,     /* R38  - Speaker Volume Left */
-	0x0079,     /* R39  - Speaker Volume Right */
-	0x0000,     /* R40  - Input Mixer2 */
-	0x0000,     /* R41  - Input Mixer3 */
-	0x0000,     /* R42  - Input Mixer4 */
-	0x0000,     /* R43  - Input Mixer5 */
-	0x0000,     /* R44  - Input Mixer6 */
-	0x0000,     /* R45  - Output Mixer1 */
-	0x0000,     /* R46  - Output Mixer2 */
-	0x0000,     /* R47  - Output Mixer3 */
-	0x0000,     /* R48  - Output Mixer4 */
-	0x0000,     /* R49  - Output Mixer5 */
-	0x0000,     /* R50  - Output Mixer6 */
-	0x0000,     /* R51  - HPOUT2 Mixer */
-	0x0000,     /* R52  - Line Mixer1 */
-	0x0000,     /* R53  - Line Mixer2 */
-	0x0000,     /* R54  - Speaker Mixer */
-	0x0000,     /* R55  - Additional Control */
-	0x0000,     /* R56  - AntiPOP1 */
-	0x0000,     /* R57  - AntiPOP2 */
-	0x0000,     /* R58  - MICBIAS */
-	0x0000,     /* R59 */
-	0x0000,     /* R60  - FLL Control 1 */
-	0x0000,     /* R61  - FLL Control 2 */
-	0x0000,     /* R62  - FLL Control 3 */
-	0x2EE0,     /* R63  - FLL Control 4 */
-	0x0002,     /* R64  - FLL Control 5 */
-	0x2287,     /* R65  - Clocking 3 */
-	0x025F,     /* R66  - Clocking 4 */
-	0x0000,     /* R67  - MW Slave Control */
-	0x0000,     /* R68 */
-	0x0002,     /* R69  - Bus Control 1 */
-	0x0000,     /* R70  - Write Sequencer 0 */
-	0x0000,     /* R71  - Write Sequencer 1 */
-	0x0000,     /* R72  - Write Sequencer 2 */
-	0x0000,     /* R73  - Write Sequencer 3 */
-	0x0000,     /* R74  - Write Sequencer 4 */
-	0x0000,     /* R75  - Write Sequencer 5 */
-	0x1F25,     /* R76  - Charge Pump 1 */
-	0x0000,     /* R77 */
-	0x0000,     /* R78 */
-	0x0000,     /* R79 */
-	0x0000,     /* R80 */
-	0x0000,     /* R81  - Class W 0 */
-	0x0000,     /* R82 */
-	0x0000,     /* R83 */
-	0x0000,     /* R84  - DC Servo 0 */
-	0x054A,     /* R85  - DC Servo 1 */
-	0x0000,     /* R86 */
-	0x0000,     /* R87  - DC Servo 3 */
-	0x0000,     /* R88  - DC Servo Readback 0 */
-	0x0000,     /* R89  - DC Servo Readback 1 */
-	0x0000,     /* R90  - DC Servo Readback 2 */
-	0x0000,     /* R91 */
-	0x0000,     /* R92 */
-	0x0000,     /* R93 */
-	0x0000,     /* R94 */
-	0x0000,     /* R95 */
-	0x0100,     /* R96  - Analogue HP 0 */
-	0x0000,     /* R97 */
-	0x0000,     /* R98  - EQ1 */
-	0x000C,     /* R99  - EQ2 */
-	0x000C,     /* R100 - EQ3 */
-	0x000C,     /* R101 - EQ4 */
-	0x000C,     /* R102 - EQ5 */
-	0x000C,     /* R103 - EQ6 */
-	0x0FCA,     /* R104 - EQ7 */
-	0x0400,     /* R105 - EQ8 */
-	0x00D8,     /* R106 - EQ9 */
-	0x1EB5,     /* R107 - EQ10 */
-	0xF145,     /* R108 - EQ11 */
-	0x0B75,     /* R109 - EQ12 */
-	0x01C5,     /* R110 - EQ13 */
-	0x1C58,     /* R111 - EQ14 */
-	0xF373,     /* R112 - EQ15 */
-	0x0A54,     /* R113 - EQ16 */
-	0x0558,     /* R114 - EQ17 */
-	0x168E,     /* R115 - EQ18 */
-	0xF829,     /* R116 - EQ19 */
-	0x07AD,     /* R117 - EQ20 */
-	0x1103,     /* R118 - EQ21 */
-	0x0564,     /* R119 - EQ22 */
-	0x0559,     /* R120 - EQ23 */
-	0x4000,     /* R121 - EQ24 */
-	0x0000,     /* R122 - Digital Pulls */
-	0x0F08,     /* R123 - DRC Control 1 */
-	0x0000,     /* R124 - DRC Control 2 */
-	0x0080,     /* R125 - DRC Control 3 */
-	0x0000,     /* R126 - DRC Control 4 */
+static struct reg_default wm8993_reg_defaults[] = {
+	{ 1,   0x0000 },     /* R1   - Power Management (1) */
+	{ 2,   0x6000 },     /* R2   - Power Management (2) */
+	{ 3,   0x0000 },     /* R3   - Power Management (3) */
+	{ 4,   0x4050 },     /* R4   - Audio Interface (1) */
+	{ 5,   0x4000 },     /* R5   - Audio Interface (2) */
+	{ 6,   0x01C8 },     /* R6   - Clocking 1 */
+	{ 7,   0x0000 },     /* R7   - Clocking 2 */
+	{ 8,   0x0000 },     /* R8   - Audio Interface (3) */
+	{ 9,   0x0040 },     /* R9   - Audio Interface (4) */
+	{ 10,  0x0004 },     /* R10  - DAC CTRL */
+	{ 11,  0x00C0 },     /* R11  - Left DAC Digital Volume */
+	{ 12,  0x00C0 },     /* R12  - Right DAC Digital Volume */
+	{ 13,  0x0000 },     /* R13  - Digital Side Tone */
+	{ 14,  0x0300 },     /* R14  - ADC CTRL */
+	{ 15,  0x00C0 },     /* R15  - Left ADC Digital Volume */
+	{ 16,  0x00C0 },     /* R16  - Right ADC Digital Volume */
+	{ 18,  0x0000 },     /* R18  - GPIO CTRL 1 */
+	{ 19,  0x0010 },     /* R19  - GPIO1 */
+	{ 20,  0x0000 },     /* R20  - IRQ_DEBOUNCE */
+	{ 21,  0x0000 },     /* R21  - Inputs Clamp */
+	{ 22,  0x8000 },     /* R22  - GPIOCTRL 2 */
+	{ 23,  0x0800 },     /* R23  - GPIO_POL */
+	{ 24,  0x008B },     /* R24  - Left Line Input 1&2 Volume */
+	{ 25,  0x008B },     /* R25  - Left Line Input 3&4 Volume */
+	{ 26,  0x008B },     /* R26  - Right Line Input 1&2 Volume */
+	{ 27,  0x008B },     /* R27  - Right Line Input 3&4 Volume */
+	{ 28,  0x006D },     /* R28  - Left Output Volume */
+	{ 29,  0x006D },     /* R29  - Right Output Volume */
+	{ 30,  0x0066 },     /* R30  - Line Outputs Volume */
+	{ 31,  0x0020 },     /* R31  - HPOUT2 Volume */
+	{ 32,  0x0079 },     /* R32  - Left OPGA Volume */
+	{ 33,  0x0079 },     /* R33  - Right OPGA Volume */
+	{ 34,  0x0003 },     /* R34  - SPKMIXL Attenuation */
+	{ 35,  0x0003 },     /* R35  - SPKMIXR Attenuation */
+	{ 36,  0x0011 },     /* R36  - SPKOUT Mixers */
+	{ 37,  0x0100 },     /* R37  - SPKOUT Boost */
+	{ 38,  0x0079 },     /* R38  - Speaker Volume Left */
+	{ 39,  0x0079 },     /* R39  - Speaker Volume Right */
+	{ 40,  0x0000 },     /* R40  - Input Mixer2 */
+	{ 41,  0x0000 },     /* R41  - Input Mixer3 */
+	{ 42,  0x0000 },     /* R42  - Input Mixer4 */
+	{ 43,  0x0000 },     /* R43  - Input Mixer5 */
+	{ 44,  0x0000 },     /* R44  - Input Mixer6 */
+	{ 45,  0x0000 },     /* R45  - Output Mixer1 */
+	{ 46,  0x0000 },     /* R46  - Output Mixer2 */
+	{ 47,  0x0000 },     /* R47  - Output Mixer3 */
+	{ 48,  0x0000 },     /* R48  - Output Mixer4 */
+	{ 49,  0x0000 },     /* R49  - Output Mixer5 */
+	{ 50,  0x0000 },     /* R50  - Output Mixer6 */
+	{ 51,  0x0000 },     /* R51  - HPOUT2 Mixer */
+	{ 52,  0x0000 },     /* R52  - Line Mixer1 */
+	{ 53,  0x0000 },     /* R53  - Line Mixer2 */
+	{ 54,  0x0000 },     /* R54  - Speaker Mixer */
+	{ 55,  0x0000 },     /* R55  - Additional Control */
+	{ 56,  0x0000 },     /* R56  - AntiPOP1 */
+	{ 57,  0x0000 },     /* R57  - AntiPOP2 */
+	{ 58,  0x0000 },     /* R58  - MICBIAS */
+	{ 60,  0x0000 },     /* R60  - FLL Control 1 */
+	{ 61,  0x0000 },     /* R61  - FLL Control 2 */
+	{ 62,  0x0000 },     /* R62  - FLL Control 3 */
+	{ 63,  0x2EE0 },     /* R63  - FLL Control 4 */
+	{ 64,  0x0002 },     /* R64  - FLL Control 5 */
+	{ 65,  0x2287 },     /* R65  - Clocking 3 */
+	{ 66,  0x025F },     /* R66  - Clocking 4 */
+	{ 67,  0x0000 },     /* R67  - MW Slave Control */
+	{ 69,  0x0002 },     /* R69  - Bus Control 1 */
+	{ 70,  0x0000 },     /* R70  - Write Sequencer 0 */
+	{ 71,  0x0000 },     /* R71  - Write Sequencer 1 */
+	{ 72,  0x0000 },     /* R72  - Write Sequencer 2 */
+	{ 73,  0x0000 },     /* R73  - Write Sequencer 3 */
+	{ 74,  0x0000 },     /* R74  - Write Sequencer 4 */
+	{ 75,  0x0000 },     /* R75  - Write Sequencer 5 */
+	{ 76,  0x1F25 },     /* R76  - Charge Pump 1 */
+	{ 81,  0x0000 },     /* R81  - Class W 0 */
+	{ 85,  0x054A },     /* R85  - DC Servo 1 */
+	{ 87,  0x0000 },     /* R87  - DC Servo 3 */
+	{ 96,  0x0100 },     /* R96  - Analogue HP 0 */
+	{ 98,  0x0000 },     /* R98  - EQ1 */
+	{ 99,  0x000C },     /* R99  - EQ2 */
+	{ 100, 0x000C },     /* R100 - EQ3 */
+	{ 101, 0x000C },     /* R101 - EQ4 */
+	{ 102, 0x000C },     /* R102 - EQ5 */
+	{ 103, 0x000C },     /* R103 - EQ6 */
+	{ 104, 0x0FCA },     /* R104 - EQ7 */
+	{ 105, 0x0400 },     /* R105 - EQ8 */
+	{ 106, 0x00D8 },     /* R106 - EQ9 */
+	{ 107, 0x1EB5 },     /* R107 - EQ10 */
+	{ 108, 0xF145 },     /* R108 - EQ11 */
+	{ 109, 0x0B75 },     /* R109 - EQ12 */
+	{ 110, 0x01C5 },     /* R110 - EQ13 */
+	{ 111, 0x1C58 },     /* R111 - EQ14 */
+	{ 112, 0xF373 },     /* R112 - EQ15 */
+	{ 113, 0x0A54 },     /* R113 - EQ16 */
+	{ 114, 0x0558 },     /* R114 - EQ17 */
+	{ 115, 0x168E },     /* R115 - EQ18 */
+	{ 116, 0xF829 },     /* R116 - EQ19 */
+	{ 117, 0x07AD },     /* R117 - EQ20 */
+	{ 118, 0x1103 },     /* R118 - EQ21 */
+	{ 119, 0x0564 },     /* R119 - EQ22 */
+	{ 120, 0x0559 },     /* R120 - EQ23 */
+	{ 121, 0x4000 },     /* R121 - EQ24 */
+	{ 122, 0x0000 },     /* R122 - Digital Pulls */
+	{ 123, 0x0F08 },     /* R123 - DRC Control 1 */
+	{ 124, 0x0000 },     /* R124 - DRC Control 2 */
+	{ 125, 0x0080 },     /* R125 - DRC Control 3 */
+	{ 126, 0x0000 },     /* R126 - DRC Control 4 */
 };
 
 static struct {
@@ -225,9 +205,11 @@ static struct {
 
 struct wm8993_priv {
 	struct wm_hubs_data hubs_data;
+	struct device *dev;
+	struct regmap *regmap;
 	struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES];
 	struct wm8993_platform_data pdata;
-	enum snd_soc_control_type control_type;
+	struct completion fll_lock;
 	int master;
 	int sysclk_source;
 	int tdm_slots;
@@ -242,17 +224,137 @@ struct wm8993_priv {
 	int fll_src;
 };
 
-static int wm8993_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8993_volatile(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case WM8993_SOFTWARE_RESET:
+	case WM8993_GPIO_CTRL_1:
 	case WM8993_DC_SERVO_0:
 	case WM8993_DC_SERVO_READBACK_0:
 	case WM8993_DC_SERVO_READBACK_1:
 	case WM8993_DC_SERVO_READBACK_2:
-		return 1;
+		return true;
 	default:
-		return 0;
+		return false;
+	}
+}
+
+static bool wm8993_readable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM8993_SOFTWARE_RESET:
+	case WM8993_POWER_MANAGEMENT_1:
+	case WM8993_POWER_MANAGEMENT_2:
+	case WM8993_POWER_MANAGEMENT_3:
+	case WM8993_AUDIO_INTERFACE_1:
+	case WM8993_AUDIO_INTERFACE_2:
+	case WM8993_CLOCKING_1:
+	case WM8993_CLOCKING_2:
+	case WM8993_AUDIO_INTERFACE_3:
+	case WM8993_AUDIO_INTERFACE_4:
+	case WM8993_DAC_CTRL:
+	case WM8993_LEFT_DAC_DIGITAL_VOLUME:
+	case WM8993_RIGHT_DAC_DIGITAL_VOLUME:
+	case WM8993_DIGITAL_SIDE_TONE:
+	case WM8993_ADC_CTRL:
+	case WM8993_LEFT_ADC_DIGITAL_VOLUME:
+	case WM8993_RIGHT_ADC_DIGITAL_VOLUME:
+	case WM8993_GPIO_CTRL_1:
+	case WM8993_GPIO1:
+	case WM8993_IRQ_DEBOUNCE:
+	case WM8993_GPIOCTRL_2:
+	case WM8993_GPIO_POL:
+	case WM8993_LEFT_LINE_INPUT_1_2_VOLUME:
+	case WM8993_LEFT_LINE_INPUT_3_4_VOLUME:
+	case WM8993_RIGHT_LINE_INPUT_1_2_VOLUME:
+	case WM8993_RIGHT_LINE_INPUT_3_4_VOLUME:
+	case WM8993_LEFT_OUTPUT_VOLUME:
+	case WM8993_RIGHT_OUTPUT_VOLUME:
+	case WM8993_LINE_OUTPUTS_VOLUME:
+	case WM8993_HPOUT2_VOLUME:
+	case WM8993_LEFT_OPGA_VOLUME:
+	case WM8993_RIGHT_OPGA_VOLUME:
+	case WM8993_SPKMIXL_ATTENUATION:
+	case WM8993_SPKMIXR_ATTENUATION:
+	case WM8993_SPKOUT_MIXERS:
+	case WM8993_SPKOUT_BOOST:
+	case WM8993_SPEAKER_VOLUME_LEFT:
+	case WM8993_SPEAKER_VOLUME_RIGHT:
+	case WM8993_INPUT_MIXER2:
+	case WM8993_INPUT_MIXER3:
+	case WM8993_INPUT_MIXER4:
+	case WM8993_INPUT_MIXER5:
+	case WM8993_INPUT_MIXER6:
+	case WM8993_OUTPUT_MIXER1:
+	case WM8993_OUTPUT_MIXER2:
+	case WM8993_OUTPUT_MIXER3:
+	case WM8993_OUTPUT_MIXER4:
+	case WM8993_OUTPUT_MIXER5:
+	case WM8993_OUTPUT_MIXER6:
+	case WM8993_HPOUT2_MIXER:
+	case WM8993_LINE_MIXER1:
+	case WM8993_LINE_MIXER2:
+	case WM8993_SPEAKER_MIXER:
+	case WM8993_ADDITIONAL_CONTROL:
+	case WM8993_ANTIPOP1:
+	case WM8993_ANTIPOP2:
+	case WM8993_MICBIAS:
+	case WM8993_FLL_CONTROL_1:
+	case WM8993_FLL_CONTROL_2:
+	case WM8993_FLL_CONTROL_3:
+	case WM8993_FLL_CONTROL_4:
+	case WM8993_FLL_CONTROL_5:
+	case WM8993_CLOCKING_3:
+	case WM8993_CLOCKING_4:
+	case WM8993_MW_SLAVE_CONTROL:
+	case WM8993_BUS_CONTROL_1:
+	case WM8993_WRITE_SEQUENCER_0:
+	case WM8993_WRITE_SEQUENCER_1:
+	case WM8993_WRITE_SEQUENCER_2:
+	case WM8993_WRITE_SEQUENCER_3:
+	case WM8993_WRITE_SEQUENCER_4:
+	case WM8993_WRITE_SEQUENCER_5:
+	case WM8993_CHARGE_PUMP_1:
+	case WM8993_CLASS_W_0:
+	case WM8993_DC_SERVO_0:
+	case WM8993_DC_SERVO_1:
+	case WM8993_DC_SERVO_3:
+	case WM8993_DC_SERVO_READBACK_0:
+	case WM8993_DC_SERVO_READBACK_1:
+	case WM8993_DC_SERVO_READBACK_2:
+	case WM8993_ANALOGUE_HP_0:
+	case WM8993_EQ1:
+	case WM8993_EQ2:
+	case WM8993_EQ3:
+	case WM8993_EQ4:
+	case WM8993_EQ5:
+	case WM8993_EQ6:
+	case WM8993_EQ7:
+	case WM8993_EQ8:
+	case WM8993_EQ9:
+	case WM8993_EQ10:
+	case WM8993_EQ11:
+	case WM8993_EQ12:
+	case WM8993_EQ13:
+	case WM8993_EQ14:
+	case WM8993_EQ15:
+	case WM8993_EQ16:
+	case WM8993_EQ17:
+	case WM8993_EQ18:
+	case WM8993_EQ19:
+	case WM8993_EQ20:
+	case WM8993_EQ21:
+	case WM8993_EQ22:
+	case WM8993_EQ23:
+	case WM8993_EQ24:
+	case WM8993_DIGITAL_PULLS:
+	case WM8993_DRC_CONTROL_1:
+	case WM8993_DRC_CONTROL_2:
+	case WM8993_DRC_CONTROL_3:
+	case WM8993_DRC_CONTROL_4:
+		return true;
+	default:
+		return false;
 	}
 }
 
@@ -369,8 +471,10 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 			  unsigned int Fref, unsigned int Fout)
 {
 	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
+	struct i2c_client *i2c = to_i2c_client(codec->dev);
 	u16 reg1, reg4, reg5;
 	struct _fll_div fll_div;
+	unsigned int timeout;
 	int ret;
 
 	/* Any change? */
@@ -441,14 +545,22 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 	reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT;
 	snd_soc_write(codec, WM8993_FLL_CONTROL_5, reg5);
 
+	/* If we've got an interrupt wired up make sure we get it */
+	if (i2c->irq)
+		timeout = msecs_to_jiffies(20);
+	else if (Fref < 1000000)
+		timeout = msecs_to_jiffies(3);
+	else
+		timeout = msecs_to_jiffies(1);
+
+	try_wait_for_completion(&wm8993->fll_lock);
+
 	/* Enable the FLL */
 	snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
 
-	/* Both overestimates */
-	if (Fref < 1000000)
-		msleep(3);
-	else
-		msleep(1);
+	timeout = wait_for_completion_timeout(&wm8993->fll_lock, timeout);
+	if (i2c->irq && !timeout)
+		dev_warn(codec->dev, "Timed out waiting for FLL\n");
 
 	dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
 
@@ -946,6 +1058,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
 	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
+	wm_hubs_set_bias_level(codec, level);
+
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 	case SND_SOC_BIAS_PREPARE:
@@ -963,12 +1077,10 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
 			if (ret != 0)
 				return ret;
 
-			snd_soc_cache_sync(codec);
+			regcache_cache_only(wm8993->regmap, false);
+			regcache_sync(wm8993->regmap);
 
-			/* Tune DC servo configuration */
-			snd_soc_write(codec, 0x44, 3);
-			snd_soc_write(codec, 0x56, 3);
-			snd_soc_write(codec, 0x44, 0);
+			wm_hubs_vmid_ena(codec);
 
 			/* Bring up VMID with fast soft start */
 			snd_soc_update_bits(codec, WM8993_ANTIPOP2,
@@ -1024,14 +1136,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
 				    WM8993_VMID_RAMP_MASK |
 				    WM8993_BIAS_SRC, 0);
 
-#ifdef CONFIG_REGULATOR
-               /* Post 2.6.34 we will be able to get a callback when
-                * the regulators are disabled which we can use but
-		* for now just assume that the power will be cut if
-		* the regulator API is in use.
-		*/
-		codec->cache_sync = 1;
-#endif
+		regcache_cache_only(wm8993->regmap, true);
+		regcache_mark_dirty(wm8993->regmap);
 
 		regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies),
 				       wm8993->supplies);
@@ -1378,6 +1484,45 @@ static int wm8993_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 	return 0;
 }
 
+static irqreturn_t wm8993_irq(int irq, void *data)
+{
+	struct wm8993_priv *wm8993 = data;
+	int mask, val, ret;
+
+	ret = regmap_read(wm8993->regmap, WM8993_GPIO_CTRL_1, &val);
+	if (ret != 0) {
+		dev_err(wm8993->dev, "Failed to read interrupt status: %d\n",
+			ret);
+		return IRQ_NONE;
+	}
+
+	ret = regmap_read(wm8993->regmap, WM8993_GPIOCTRL_2, &mask);
+	if (ret != 0) {
+		dev_err(wm8993->dev, "Failed to read interrupt mask: %d\n",
+			ret);
+		return IRQ_NONE;
+	}
+
+	/* The IRQ pin status is visible in the register too */
+	val &= ~(mask | WM8993_IRQ);
+	if (!val)
+		return IRQ_NONE;
+
+	if (val & WM8993_TEMPOK_EINT)
+		dev_crit(wm8993->dev, "Thermal warning\n");
+
+	if (val & WM8993_FLL_LOCK_EINT) {
+		dev_dbg(wm8993->dev, "FLL locked\n");
+		complete(&wm8993->fll_lock);
+	}
+
+	ret = regmap_write(wm8993->regmap, WM8993_GPIO_CTRL_1, val);
+	if (ret != 0)
+		dev_err(wm8993->dev, "Failed to ack interrupt: %d\n", ret);
+
+	return IRQ_HANDLED;
+}
+
 static const struct snd_soc_dai_ops wm8993_ops = {
 	.set_sysclk = wm8993_set_sysclk,
 	.set_fmt = wm8993_set_dai_fmt,
@@ -1402,6 +1547,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
 		.channels_max = 2,
 		.rates = WM8993_RATES,
 		.formats = WM8993_FORMATS,
+		.sig_bits = 24,
 	},
 	.capture = {
 		 .stream_name = "Capture",
@@ -1409,6 +1555,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
 		 .channels_max = 2,
 		 .rates = WM8993_RATES,
 		 .formats = WM8993_FORMATS,
+		 .sig_bits = 24,
 	 },
 	.ops = &wm8993_ops,
 	.symmetric_rates = 1,
@@ -1418,49 +1565,20 @@ static int wm8993_probe(struct snd_soc_codec *codec)
 {
 	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int ret, i, val;
+	int ret;
 
 	wm8993->hubs_data.hp_startup_mode = 1;
 	wm8993->hubs_data.dcs_codes_l = -2;
 	wm8993->hubs_data.dcs_codes_r = -2;
 	wm8993->hubs_data.series_startup = 1;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+	codec->control_data = wm8993->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;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
-		wm8993->supplies[i].supply = wm8993_supply_names[i];
-
-	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
-				 wm8993->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-		return ret;
-	}
-
-	ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
-				    wm8993->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-		goto err_get;
-	}
-
-	val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
-	if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
-		dev_err(codec->dev, "Invalid ID register value %x\n", val);
-		ret = -EINVAL;
-		goto err_enable;
-	}
-
-	ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
-	if (ret != 0)
-		goto err_enable;
-
-	codec->cache_only = 1;
-
 	/* By default we're using the output mixers */
 	wm8993->class_w_users = 2;
 
@@ -1489,15 +1607,15 @@ static int wm8993_probe(struct snd_soc_codec *codec)
 
 	ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	if (ret != 0)
-		goto err_enable;
+		return ret;
 
-	snd_soc_add_controls(codec, wm8993_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8993_snd_controls,
 			     ARRAY_SIZE(wm8993_snd_controls));
 	if (wm8993->pdata.num_retune_configs != 0) {
 		dev_dbg(codec->dev, "Using ReTune Mobile\n");
 	} else {
 		dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
-		snd_soc_add_controls(codec, wm8993_eq_controls,
+		snd_soc_add_codec_controls(codec, wm8993_eq_controls,
 				     ARRAY_SIZE(wm8993_eq_controls));
 	}
 
@@ -1509,13 +1627,14 @@ static int wm8993_probe(struct snd_soc_codec *codec)
 	wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
 				    wm8993->pdata.lineout2_diff);
 
+	/* If the line outputs are differential then we aren't presenting
+	 * VMID as an output and can disable it.
+	 */
+	if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff)
+		codec->dapm.idle_bias_off = 1;
+
 	return 0;
 
-err_enable:
-	regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err_get:
-	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-	return ret;
 }
 
 static int wm8993_remove(struct snd_soc_codec *codec)
@@ -1578,41 +1697,149 @@ static int wm8993_resume(struct snd_soc_codec *codec)
 #define wm8993_resume NULL
 #endif
 
+/* Tune DC servo configuration */
+static struct reg_default wm8993_regmap_patch[] = {
+	{ 0x44, 3 },
+	{ 0x56, 3 },
+	{ 0x44, 0 },
+};
+
+static const struct regmap_config wm8993_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+
+	.max_register = WM8993_MAX_REGISTER,
+	.volatile_reg = wm8993_volatile,
+	.readable_reg = wm8993_readable,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm8993_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm8993_reg_defaults),
+};
+
 static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
 	.probe = 	wm8993_probe,
 	.remove = 	wm8993_remove,
 	.suspend =	wm8993_suspend,
 	.resume =	wm8993_resume,
 	.set_bias_level = wm8993_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(wm8993_reg_defaults),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm8993_reg_defaults,
-	.volatile_register = wm8993_volatile,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8993_priv *wm8993;
-	int ret;
+	unsigned int reg;
+	int ret, i;
 
 	wm8993 = devm_kzalloc(&i2c->dev, sizeof(struct wm8993_priv),
 			      GFP_KERNEL);
 	if (wm8993 == NULL)
 		return -ENOMEM;
 
+	wm8993->dev = &i2c->dev;
+	init_completion(&wm8993->fll_lock);
+
+	wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap);
+	if (IS_ERR(wm8993->regmap)) {
+		ret = PTR_ERR(wm8993->regmap);
+		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+		return ret;
+	}
+
 	i2c_set_clientdata(i2c, wm8993);
 
+	for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
+		wm8993->supplies[i].supply = wm8993_supply_names[i];
+
+	ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
+				 wm8993->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+		goto err;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
+				    wm8993->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+		goto err_get;
+	}
+
+	ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, &reg);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+		goto err_enable;
+	}
+
+	if (reg != 0x8993) {
+		dev_err(&i2c->dev, "Invalid ID register value %x\n", reg);
+		ret = -EINVAL;
+		goto err_enable;
+	}
+
+	ret = regmap_write(wm8993->regmap, WM8993_SOFTWARE_RESET, 0xffff);
+	if (ret != 0)
+		goto err_enable;
+
+	ret = regmap_register_patch(wm8993->regmap, wm8993_regmap_patch,
+				    ARRAY_SIZE(wm8993_regmap_patch));
+	if (ret != 0)
+		dev_warn(wm8993->dev, "Failed to apply regmap patch: %d\n",
+			 ret);
+
+	if (i2c->irq) {
+		/* Put GPIO1 into interrupt mode (only GPIO1 can output IRQ) */
+		ret = regmap_update_bits(wm8993->regmap, WM8993_GPIO1,
+					 WM8993_GPIO1_PD |
+					 WM8993_GPIO1_SEL_MASK, 7);
+		if (ret != 0)
+			goto err_enable;
+
+		ret = request_threaded_irq(i2c->irq, NULL, wm8993_irq,
+					   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+					   "wm8993", wm8993);
+		if (ret != 0)
+			goto err_enable;
+
+	}
+
+	regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+
+	regcache_cache_only(wm8993->regmap, true);
+
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8993, &wm8993_dai, 1);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+		goto err_irq;
+	}
+
+	return 0;
+
+err_irq:
+	if (i2c->irq)
+		free_irq(i2c->irq, wm8993);
+err_enable:
+	regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err_get:
+	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err:
+	regmap_exit(wm8993->regmap);
 	return ret;
 }
 
-static __devexit int wm8993_i2c_remove(struct i2c_client *client)
+static __devexit int wm8993_i2c_remove(struct i2c_client *i2c)
 {
-	snd_soc_unregister_codec(&client->dev);
-	kfree(i2c_get_clientdata(client));
+	struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c);
+
+	snd_soc_unregister_codec(&i2c->dev);
+	if (i2c->irq)
+		free_irq(i2c->irq, wm8993);
+	regmap_exit(wm8993->regmap);
+	regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+
 	return 0;
 }
 
@@ -1631,30 +1858,8 @@ static struct i2c_driver wm8993_i2c_driver = {
 	.remove =   __devexit_p(wm8993_i2c_remove),
 	.id_table = wm8993_i2c_id,
 };
-#endif
-
-static int __init wm8993_modinit(void)
-{
-	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	ret = i2c_add_driver(&wm8993_i2c_driver);
-	if (ret != 0) {
-		pr_err("WM8993: Unable to register I2C driver: %d\n",
-		       ret);
-	}
-#endif
-	return ret;
-}
-module_init(wm8993_modinit);
-
-static void __exit wm8993_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	i2c_del_driver(&wm8993_i2c_driver);
-#endif
-}
-module_exit(wm8993_exit);
 
+module_i2c_driver(wm8993_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8993 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
index 2184617b96117bfabac14cc7411eb24d2dadb317..4478b40c86e3191ccdad133c33b2d0b1f17272b7 100644
--- a/sound/soc/codecs/wm8993.h
+++ b/sound/soc/codecs/wm8993.h
@@ -31,6 +31,7 @@
 #define WM8993_GPIO_CTRL_1                      0x12
 #define WM8993_GPIO1                            0x13
 #define WM8993_IRQ_DEBOUNCE                     0x14
+#define WM8993_INPUTS_CLAMP_REG			0x15
 #define WM8993_GPIOCTRL_2                       0x16
 #define WM8993_GPIO_POL                         0x17
 #define WM8993_LEFT_LINE_INPUT_1_2_VOLUME       0x18
@@ -655,6 +656,14 @@
 #define WM8993_GPIO1_DB_SHIFT                        0  /* GPIO1_DB */
 #define WM8993_GPIO1_DB_WIDTH                        1  /* GPIO1_DB */
 
+/*
+ * R21 (0x15) - Inputs Clamp
+ */
+#define WM8993_INPUTS_CLAMP                     0x0040  /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_MASK                0x0040  /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_SHIFT                    7  /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_WIDTH                    1  /* INPUTS_CLAMP */
+
 /*
  * R22 (0x16) - GPIOCTRL 2
  */
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index ec69a6c152fea9a8b55a7c16c1f3935fb3dc305d..9685dff44dd8a9a9cc87d2ddb7173e2d26ba7e7c 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -686,14 +686,23 @@ 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->jackdet || !wm8994->jack_cb)
+		return;
+
 	if (wm8994->active_refcount)
 		mode = WM1811_JACKDET_MODE_AUDIO;
 
+	if (mode == wm8994->jackdet_mode)
+		return;
+
+	wm8994->jackdet_mode = mode;
+
+	/* Always use audio mode to detect while the system is active */
+	if (mode != WM1811_JACKDET_MODE_NONE)
+		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)
@@ -707,15 +716,8 @@ static void active_reference(struct snd_soc_codec *codec)
 	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);
-		}
-	}
+	/* If we're using jack detection go into audio mode */
+	wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_AUDIO);
 
 	mutex_unlock(&wm8994->accdet_lock);
 }
@@ -734,16 +736,12 @@ static void active_dereference(struct snd_soc_codec *codec)
 
 	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;
+		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);
-		}
+		wm1811_jackdet_set_mode(codec, mode);
 	}
 
 	mutex_unlock(&wm8994->accdet_lock);
@@ -778,27 +776,69 @@ static void vmid_reference(struct snd_soc_codec *codec)
 		wm8994->vmid_refcount);
 
 	if (wm8994->vmid_refcount == 1) {
-		/* Startup bias, VMID ramp & buffer */
-		snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-				    WM8994_STARTUP_BIAS_ENA |
-				    WM8994_VMID_BUF_ENA |
-				    WM8994_VMID_RAMP_MASK,
-				    WM8994_STARTUP_BIAS_ENA |
-				    WM8994_VMID_BUF_ENA |
-				    (0x3 << WM8994_VMID_RAMP_SHIFT));
-
-		/* Remove discharge for line out */
 		snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
 				    WM8994_LINEOUT1_DISCH |
 				    WM8994_LINEOUT2_DISCH, 0);
 
-		/* Main bias enable, VMID=2x40k */
-		snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-				    WM8994_BIAS_ENA |
-				    WM8994_VMID_SEL_MASK,
-				    WM8994_BIAS_ENA | 0x2);
+		wm_hubs_vmid_ena(codec);
+
+		switch (wm8994->vmid_mode) {
+		default:
+			WARN_ON(0 == "Invalid VMID mode");
+		case WM8994_VMID_NORMAL:
+			/* Startup bias, VMID ramp & buffer */
+			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+					    WM8994_BIAS_SRC |
+					    WM8994_VMID_DISCH |
+					    WM8994_STARTUP_BIAS_ENA |
+					    WM8994_VMID_BUF_ENA |
+					    WM8994_VMID_RAMP_MASK,
+					    WM8994_BIAS_SRC |
+					    WM8994_STARTUP_BIAS_ENA |
+					    WM8994_VMID_BUF_ENA |
+					    (0x3 << WM8994_VMID_RAMP_SHIFT));
+
+			/* Main bias enable, VMID=2x40k */
+			snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+					    WM8994_BIAS_ENA |
+					    WM8994_VMID_SEL_MASK,
+					    WM8994_BIAS_ENA | 0x2);
+
+			msleep(50);
+
+			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+					    WM8994_VMID_RAMP_MASK |
+					    WM8994_BIAS_SRC,
+					    0);
+			break;
+
+		case WM8994_VMID_FORCE:
+			/* Startup bias, slow VMID ramp & buffer */
+			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+					    WM8994_BIAS_SRC |
+					    WM8994_VMID_DISCH |
+					    WM8994_STARTUP_BIAS_ENA |
+					    WM8994_VMID_BUF_ENA |
+					    WM8994_VMID_RAMP_MASK,
+					    WM8994_BIAS_SRC |
+					    WM8994_STARTUP_BIAS_ENA |
+					    WM8994_VMID_BUF_ENA |
+					    (0x2 << WM8994_VMID_RAMP_SHIFT));
+
+			/* Main bias enable, VMID=2x40k */
+			snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+					    WM8994_BIAS_ENA |
+					    WM8994_VMID_SEL_MASK,
+					    WM8994_BIAS_ENA | 0x2);
+
+			msleep(400);
 
-		msleep(20);
+			snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+					    WM8994_VMID_RAMP_MASK |
+					    WM8994_BIAS_SRC,
+					    0);
+			break;
+		}
 	}
 }
 
@@ -812,30 +852,55 @@ static void vmid_dereference(struct snd_soc_codec *codec)
 		wm8994->vmid_refcount);
 
 	if (wm8994->vmid_refcount == 0) {
-		/* Switch over to startup biases */
+		if (wm8994->hubs.lineout1_se)
+			snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
+					    WM8994_LINEOUT1N_ENA |
+					    WM8994_LINEOUT1P_ENA,
+					    WM8994_LINEOUT1N_ENA |
+					    WM8994_LINEOUT1P_ENA);
+
+		if (wm8994->hubs.lineout2_se)
+			snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
+					    WM8994_LINEOUT2N_ENA |
+					    WM8994_LINEOUT2P_ENA,
+					    WM8994_LINEOUT2N_ENA |
+					    WM8994_LINEOUT2P_ENA);
+
+		/* Start discharging VMID */
 		snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
 				    WM8994_BIAS_SRC |
-				    WM8994_STARTUP_BIAS_ENA |
-				    WM8994_VMID_BUF_ENA |
-				    WM8994_VMID_RAMP_MASK,
+				    WM8994_VMID_DISCH,
 				    WM8994_BIAS_SRC |
-				    WM8994_STARTUP_BIAS_ENA |
-				    WM8994_VMID_BUF_ENA |
-				    (1 << WM8994_VMID_RAMP_SHIFT));
+				    WM8994_VMID_DISCH);
 
-		/* Disable main biases */
-		snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-				    WM8994_BIAS_ENA |
-				    WM8994_VMID_SEL_MASK, 0);
+		switch (wm8994->vmid_mode) {
+		case WM8994_VMID_FORCE:
+			msleep(350);
+			break;
+		default:
+			break;
+		}
+
+		snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
+				    WM8994_VROI, WM8994_VROI);
 
-		/* Discharge line */
+		/* Active discharge */
 		snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
 				    WM8994_LINEOUT1_DISCH |
 				    WM8994_LINEOUT2_DISCH,
 				    WM8994_LINEOUT1_DISCH |
 				    WM8994_LINEOUT2_DISCH);
 
-		msleep(5);
+		msleep(150);
+
+		snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
+				    WM8994_LINEOUT1N_ENA |
+				    WM8994_LINEOUT1P_ENA |
+				    WM8994_LINEOUT2N_ENA |
+				    WM8994_LINEOUT2P_ENA, 0);
+
+		snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
+				    WM8994_VROI, 0);
 
 		/* Switch off startup biases */
 		snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
@@ -843,6 +908,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
 				    WM8994_STARTUP_BIAS_ENA |
 				    WM8994_VMID_BUF_ENA |
 				    WM8994_VMID_RAMP_MASK, 0);
+
+		snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+				    WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
+
+		snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+				    WM8994_VMID_RAMP_MASK, 0);
 	}
 
 	pm_runtime_put(codec->dev);
@@ -1459,17 +1530,17 @@ SND_SOC_DAPM_AIF_IN_E("AIF2DACR", NULL, 0,
 		      WM8994_POWER_MANAGEMENT_5, 12, 0, wm8958_aif_ev,
 		      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
-SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF2DACDAT", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF1DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT",  NULL, 0, SND_SOC_NOPM, 0, 0),
 
 SND_SOC_DAPM_MUX("AIF1DAC Mux", SND_SOC_NOPM, 0, 0, &aif1dac_mux),
 SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
 SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
 
-SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF3DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
 
 SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
 
@@ -1584,6 +1655,14 @@ static const struct snd_soc_dapm_route intercon[] = {
 
 	{ "TOCLK", NULL, "CLK_SYS" },
 
+	{ "AIF1DACDAT", NULL, "AIF1 Playback" },
+	{ "AIF2DACDAT", NULL, "AIF2 Playback" },
+	{ "AIF3DACDAT", NULL, "AIF3 Playback" },
+
+	{ "AIF1 Capture", NULL, "AIF1ADCDAT" },
+	{ "AIF2 Capture", NULL, "AIF2ADCDAT" },
+	{ "AIF3 Capture", NULL, "AIF3ADCDAT" },
+
 	/* AIF1 outputs */
 	{ "AIF1ADC1L", NULL, "AIF1ADC1L Mixer" },
 	{ "AIF1ADC1L Mixer", "ADC/DMIC Switch", "ADCL Mux" },
@@ -1896,7 +1975,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
 			    WM8994_FLL1_OUTDIV_MASK |
 			    WM8994_FLL1_FRATIO_MASK, reg);
 
-	snd_soc_write(codec, WM8994_FLL1_CONTROL_3 + reg_offset, fll.k);
+	snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_3 + reg_offset,
+			    WM8994_FLL1_K_MASK, fll.k);
 
 	snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset,
 			    WM8994_FLL1_N_MASK,
@@ -2074,6 +2154,8 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
 
+	wm_hubs_set_bias_level(codec, level);
+
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		break;
@@ -2168,11 +2250,61 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
 			wm8994->cur_fw = NULL;
 		break;
 	}
+
 	codec->dapm.bias_level = level;
 
 	return 0;
 }
 
+int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode)
+{
+	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+	switch (mode) {
+	case WM8994_VMID_NORMAL:
+		if (wm8994->hubs.lineout1_se) {
+			snd_soc_dapm_disable_pin(&codec->dapm,
+						 "LINEOUT1N Driver");
+			snd_soc_dapm_disable_pin(&codec->dapm,
+						 "LINEOUT1P Driver");
+		}
+		if (wm8994->hubs.lineout2_se) {
+			snd_soc_dapm_disable_pin(&codec->dapm,
+						 "LINEOUT2N Driver");
+			snd_soc_dapm_disable_pin(&codec->dapm,
+						 "LINEOUT2P Driver");
+		}
+
+		/* Do the sync with the old mode to allow it to clean up */
+		snd_soc_dapm_sync(&codec->dapm);
+		wm8994->vmid_mode = mode;
+		break;
+
+	case WM8994_VMID_FORCE:
+		if (wm8994->hubs.lineout1_se) {
+			snd_soc_dapm_force_enable_pin(&codec->dapm,
+						      "LINEOUT1N Driver");
+			snd_soc_dapm_force_enable_pin(&codec->dapm,
+						      "LINEOUT1P Driver");
+		}
+		if (wm8994->hubs.lineout2_se) {
+			snd_soc_dapm_force_enable_pin(&codec->dapm,
+						      "LINEOUT2N Driver");
+			snd_soc_dapm_force_enable_pin(&codec->dapm,
+						      "LINEOUT2P Driver");
+		}
+
+		wm8994->vmid_mode = mode;
+		snd_soc_dapm_sync(&codec->dapm);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct snd_soc_codec *codec = dai->codec;
@@ -2654,6 +2786,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
 			.channels_max = 2,
 			.rates = WM8994_RATES,
 			.formats = WM8994_FORMATS,
+			.sig_bits = 24,
 		},
 		.capture = {
 			.stream_name = "AIF1 Capture",
@@ -2661,6 +2794,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
 			.channels_max = 2,
 			.rates = WM8994_RATES,
 			.formats = WM8994_FORMATS,
+			.sig_bits = 24,
 		 },
 		.ops = &wm8994_aif1_dai_ops,
 	},
@@ -2673,6 +2807,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
 			.channels_max = 2,
 			.rates = WM8994_RATES,
 			.formats = WM8994_FORMATS,
+			.sig_bits = 24,
 		},
 		.capture = {
 			.stream_name = "AIF2 Capture",
@@ -2680,6 +2815,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
 			.channels_max = 2,
 			.rates = WM8994_RATES,
 			.formats = WM8994_FORMATS,
+			.sig_bits = 24,
 		},
 		.probe = wm8994_aif2_probe,
 		.ops = &wm8994_aif2_dai_ops,
@@ -2693,6 +2829,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
 			.channels_max = 2,
 			.rates = WM8994_RATES,
 			.formats = WM8994_FORMATS,
+			.sig_bits = 24,
 		},
 		.capture = {
 			.stream_name = "AIF3 Capture",
@@ -2700,13 +2837,14 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
 			.channels_max = 2,
 			.rates = WM8994_RATES,
 			.formats = WM8994_FORMATS,
-		},
+			.sig_bits = 24,
+		 },
 		.ops = &wm8994_aif3_dai_ops,
 	}
 };
 
 #ifdef CONFIG_PM
-static int wm8994_suspend(struct snd_soc_codec *codec)
+static int wm8994_codec_suspend(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
@@ -2740,7 +2878,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec)
 	return 0;
 }
 
-static int wm8994_resume(struct snd_soc_codec *codec)
+static int wm8994_codec_resume(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
@@ -2762,8 +2900,6 @@ static int wm8994_resume(struct snd_soc_codec *codec)
 		codec->cache_only = 0;
 	}
 
-	wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
 		if (!wm8994->fll_suspend[i].out)
 			continue;
@@ -2791,6 +2927,7 @@ static int wm8994_resume(struct snd_soc_codec *codec)
 					    WM1811_JACKDET_MODE_JACK);
 			break;
 		}
+		break;
 	case WM8958:
 		if (wm8994->jack_cb)
 			snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
@@ -2801,8 +2938,8 @@ static int wm8994_resume(struct snd_soc_codec *codec)
 	return 0;
 }
 #else
-#define wm8994_suspend NULL
-#define wm8994_resume NULL
+#define wm8994_codec_suspend NULL
+#define wm8994_codec_resume NULL
 #endif
 
 static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
@@ -2865,7 +3002,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
 	wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;
 	wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts;
 
-	ret = snd_soc_add_controls(wm8994->codec, controls,
+	ret = snd_soc_add_codec_controls(wm8994->codec, controls,
 				   ARRAY_SIZE(controls));
 	if (ret != 0)
 		dev_err(wm8994->codec->dev,
@@ -2918,7 +3055,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
 		wm8994->drc_enum.max = pdata->num_drc_cfgs;
 		wm8994->drc_enum.texts = wm8994->drc_texts;
 
-		ret = snd_soc_add_controls(wm8994->codec, controls,
+		ret = snd_soc_add_codec_controls(wm8994->codec, controls,
 					   ARRAY_SIZE(controls));
 		if (ret != 0)
 			dev_err(wm8994->codec->dev,
@@ -2934,7 +3071,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
 	if (pdata->num_retune_mobile_cfgs)
 		wm8994_handle_retune_mobile_pdata(wm8994);
 	else
-		snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
+		snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls,
 				     ARRAY_SIZE(wm8994_eq_controls));
 
 	for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) {
@@ -2951,8 +3088,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
  * @codec:   WM8994 codec
  * @jack:    jack to report detection events on
  * @micbias: microphone bias to detect on
- * @det:     value to report for presence detection
- * @shrt:    value to report for short detection
  *
  * Enable microphone detection via IRQ on the WM8994.  If GPIOs are
  * being used to bring out signals to the processor then only platform
@@ -2963,43 +3098,63 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
  * and micbias2_lvl platform data members.
  */
 int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
-		      int micbias, int det, int shrt)
+		      int micbias)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994_micdet *micdet;
 	struct wm8994 *control = wm8994->wm8994;
-	int reg;
+	int reg, ret;
 
-	if (control->type != WM8994)
+	if (control->type != WM8994) {
+		dev_warn(codec->dev, "Not a WM8994\n");
 		return -EINVAL;
+	}
 
 	switch (micbias) {
 	case 1:
 		micdet = &wm8994->micdet[0];
+		if (jack)
+			ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+							    "MICBIAS1");
+		else
+			ret = snd_soc_dapm_disable_pin(&codec->dapm,
+						       "MICBIAS1");
 		break;
 	case 2:
 		micdet = &wm8994->micdet[1];
+		if (jack)
+			ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+							    "MICBIAS1");
+		else
+			ret = snd_soc_dapm_disable_pin(&codec->dapm,
+						       "MICBIAS1");
 		break;
 	default:
+		dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias);
 		return -EINVAL;
-	}	
+	}
 
-	dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
-		micbias, det, shrt);
+	if (ret != 0)
+		dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n",
+			 micbias, ret);
+
+	dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n",
+		micbias, jack);
 
 	/* Store the configuration */
 	micdet->jack = jack;
-	micdet->det = det;
-	micdet->shrt = shrt;
+	micdet->detecting = true;
 
 	/* If either of the jacks is set up then enable detection */
 	if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
 		reg = WM8994_MICD_ENA;
-	else 
+	else
 		reg = 0;
 
 	snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
 
+	snd_soc_dapm_sync(&codec->dapm);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(wm8994_mic_detect);
@@ -3025,20 +3180,42 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
 	dev_dbg(codec->dev, "Microphone status: %x\n", reg);
 
 	report = 0;
-	if (reg & WM8994_MIC1_DET_STS)
-		report |= priv->micdet[0].det;
-	if (reg & WM8994_MIC1_SHRT_STS)
-		report |= priv->micdet[0].shrt;
+	if (reg & WM8994_MIC1_DET_STS) {
+		if (priv->micdet[0].detecting)
+			report = SND_JACK_HEADSET;
+	}
+	if (reg & WM8994_MIC1_SHRT_STS) {
+		if (priv->micdet[0].detecting)
+			report = SND_JACK_HEADPHONE;
+		else
+			report |= SND_JACK_BTN_0;
+	}
+	if (report)
+		priv->micdet[0].detecting = false;
+	else
+		priv->micdet[0].detecting = true;
+
 	snd_soc_jack_report(priv->micdet[0].jack, report,
-			    priv->micdet[0].det | priv->micdet[0].shrt);
+			    SND_JACK_HEADSET | SND_JACK_BTN_0);
 
 	report = 0;
-	if (reg & WM8994_MIC2_DET_STS)
-		report |= priv->micdet[1].det;
-	if (reg & WM8994_MIC2_SHRT_STS)
-		report |= priv->micdet[1].shrt;
+	if (reg & WM8994_MIC2_DET_STS) {
+		if (priv->micdet[1].detecting)
+			report = SND_JACK_HEADSET;
+	}
+	if (reg & WM8994_MIC2_SHRT_STS) {
+		if (priv->micdet[1].detecting)
+			report = SND_JACK_HEADPHONE;
+		else
+			report |= SND_JACK_BTN_0;
+	}
+	if (report)
+		priv->micdet[1].detecting = false;
+	else
+		priv->micdet[1].detecting = true;
+
 	snd_soc_jack_report(priv->micdet[1].jack, report,
-			    priv->micdet[1].det | priv->micdet[1].shrt);
+			    SND_JACK_HEADSET | SND_JACK_BTN_0);
 
 	return IRQ_HANDLED;
 }
@@ -3087,7 +3264,7 @@ static void wm8958_default_micdet(u16 status, void *data)
 	}
 
 
-	if (wm8994->mic_detecting && status & 0x4) {
+	if (wm8994->mic_detecting && status & 0xfc) {
 		dev_dbg(codec->dev, "Detected headphone\n");
 		wm8994->mic_detecting = false;
 
@@ -3098,11 +3275,23 @@ static void wm8958_default_micdet(u16 status, void *data)
 
 		/* If we have jackdet that will detect removal */
 		if (wm8994->jackdet) {
+			mutex_lock(&wm8994->accdet_lock);
+
 			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);
+
+			if (wm8994->pdata->jd_ext_cap) {
+				mutex_lock(&codec->mutex);
+				snd_soc_dapm_disable_pin(&codec->dapm,
+							 "MICBIAS2");
+				snd_soc_dapm_sync(&codec->dapm);
+				mutex_unlock(&codec->mutex);
+			}
 		}
 	}
 
@@ -3137,6 +3326,7 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 	struct wm8994_priv *wm8994 = data;
 	struct snd_soc_codec *codec = wm8994->codec;
 	int reg;
+	bool present;
 
 	mutex_lock(&wm8994->accdet_lock);
 
@@ -3149,11 +3339,17 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 
 	dev_dbg(codec->dev, "JACKDET %x\n", reg);
 
-	if (reg & WM1811_JACKDET_LVL) {
+	present = reg & WM1811_JACKDET_LVL;
+
+	if (present) {
 		dev_dbg(codec->dev, "Jack detected\n");
 
-		snd_soc_jack_report(wm8994->micdet[0].jack,
-				    SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
+		snd_soc_update_bits(codec, WM8958_MICBIAS2,
+				    WM8958_MICB2_DISCH, 0);
+
+		/* Disable debounce while inserted */
+		snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
+				    WM1811_JACKDET_DB, 0);
 
 		/*
 		 * Start off measument of microphone impedence to find
@@ -3161,14 +3357,18 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 		 */
 		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);
+		snd_soc_update_bits(codec, WM8958_MICBIAS2,
+				    WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
+
+		/* Enable debounce while removed */
+		snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
+				    WM1811_JACKDET_DB, WM1811_JACKDET_DB);
 
 		wm8994->mic_detecting = false;
 		wm8994->jack_mic = false;
@@ -3179,6 +3379,28 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 
 	mutex_unlock(&wm8994->accdet_lock);
 
+	/* If required for an external cap force MICBIAS on */
+	if (wm8994->pdata->jd_ext_cap) {
+		mutex_lock(&codec->mutex);
+
+		if (present)
+			snd_soc_dapm_force_enable_pin(&codec->dapm,
+						      "MICBIAS2");
+		else
+			snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
+
+		snd_soc_dapm_sync(&codec->dapm);
+		mutex_unlock(&codec->mutex);
+	}
+
+	if (present)
+		snd_soc_jack_report(wm8994->micdet[0].jack,
+				    SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
+	else
+		snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+				    SND_JACK_MECHANICAL | SND_JACK_HEADSET |
+				    wm8994->btn_mask);
+
 	return IRQ_HANDLED;
 }
 
@@ -3221,6 +3443,7 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 		}
 
 		snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
+		snd_soc_dapm_sync(&codec->dapm);
 
 		wm8994->micdet[0].jack = jack;
 		wm8994->jack_cb = cb;
@@ -3251,6 +3474,9 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 		 * otherwise jump straight to microphone detection.
 		 */
 		if (wm8994->jackdet) {
+			snd_soc_update_bits(codec, WM8958_MICBIAS2,
+					    WM8958_MICB2_DISCH,
+					    WM8958_MICB2_DISCH);
 			snd_soc_update_bits(codec, WM8994_LDO_1,
 					    WM8994_LDO1_DISCH, 0);
 			wm1811_jackdet_set_mode(codec,
@@ -3263,7 +3489,9 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 	} else {
 		snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
 				    WM8958_MICD_ENA, 0);
+		wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_NONE);
 		snd_soc_dapm_disable_pin(&codec->dapm, "CLK_SYS");
+		snd_soc_dapm_sync(&codec->dapm);
 	}
 
 	return 0;
@@ -3276,17 +3504,13 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
 	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);
+	if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA))
 		return IRQ_HANDLED;
-	}
 
 	/* We may occasionally read a detection without an impedence
 	 * range being provided - if that happens loop again.
@@ -3295,7 +3519,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
 	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);
@@ -3326,8 +3549,6 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
 		dev_warn(codec->dev, "Accessory detection with no callback\n");
 
 out:
-	mutex_unlock(&wm8994->accdet_lock);
-
 	return IRQ_HANDLED;
 }
 
@@ -3361,23 +3582,16 @@ static irqreturn_t wm8994_temp_shut(int irq, void *data)
 static int wm8994_codec_probe(struct snd_soc_codec *codec)
 {
 	struct wm8994 *control = dev_get_drvdata(codec->dev->parent);
-	struct wm8994_priv *wm8994;
+	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	unsigned int reg;
 	int ret, i;
 
+	wm8994->codec = codec;
 	codec->control_data = control->regmap;
 
-	wm8994 = devm_kzalloc(codec->dev, sizeof(struct wm8994_priv),
-			      GFP_KERNEL);
-	if (wm8994 == NULL)
-		return -ENOMEM;
-	snd_soc_codec_set_drvdata(codec, wm8994);
-
 	snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 
-	wm8994->wm8994 = dev_get_drvdata(codec->dev->parent);
-	wm8994->pdata = dev_get_platdata(codec->dev->parent);
 	wm8994->codec = codec;
 
 	mutex_init(&wm8994->accdet_lock);
@@ -3392,12 +3606,20 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 				     WM8994_IRQ_MIC1_DET;
 
 	pm_runtime_enable(codec->dev);
-	pm_runtime_resume(codec->dev);
+	pm_runtime_idle(codec->dev);
+
+	/* By default use idle_bias_off, will override for WM8994 */
+	codec->dapm.idle_bias_off = 1;
 
 	/* Set revision-specific configuration */
 	wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION);
 	switch (control->type) {
 	case WM8994:
+		/* Single ended line outputs should have VMID on. */
+		if (!wm8994->pdata->lineout1_diff ||
+		    !wm8994->pdata->lineout2_diff)
+			codec->dapm.idle_bias_off = 0;
+
 		switch (wm8994->revision) {
 		case 2:
 		case 3:
@@ -3415,11 +3637,14 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
 	case WM8958:
 		wm8994->hubs.dcs_readback_mode = 1;
+		wm8994->hubs.hp_startup_mode = 1;
 		break;
 
 	case WM1811:
 		wm8994->hubs.dcs_readback_mode = 2;
 		wm8994->hubs.no_series_update = 1;
+		wm8994->hubs.hp_startup_mode = 1;
+		wm8994->hubs.no_cache_class_w = true;
 
 		switch (wm8994->revision) {
 		case 0:
@@ -3536,6 +3761,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 			wm8994->fll_locked_irq = false;
 	}
 
+	/* Make sure we can read from the GPIOs if they're inputs */
+	pm_runtime_get_sync(codec->dev);
+
 	/* Remember if AIFnLRCLK is configured as a GPIO.  This should be
 	 * configured on init - if a system wants to do this dynamically
 	 * at runtime we can deal with that then.
@@ -3564,7 +3792,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 		wm8994->lrclk_shared[1] = 0;
 	}
 
-	wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	pm_runtime_put(codec->dev);
 
 	/* Latch volume updates (right only; we always do left then right). */
 	snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME,
@@ -3642,7 +3870,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 	wm8994_handle_pdata(wm8994);
 
 	wm_hubs_add_analogue_controls(codec);
-	snd_soc_add_controls(codec, wm8994_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8994_snd_controls,
 			     ARRAY_SIZE(wm8994_snd_controls));
 	snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
 				  ARRAY_SIZE(wm8994_dapm_widgets));
@@ -3668,7 +3896,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 		}
 		break;
 	case WM8958:
-		snd_soc_add_controls(codec, wm8958_snd_controls,
+		snd_soc_add_codec_controls(codec, wm8958_snd_controls,
 				     ARRAY_SIZE(wm8958_snd_controls));
 		snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
 					  ARRAY_SIZE(wm8958_dapm_widgets));
@@ -3690,7 +3918,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 		break;
 
 	case WM1811:
-		snd_soc_add_controls(codec, wm8958_snd_controls,
+		snd_soc_add_codec_controls(codec, wm8958_snd_controls,
 				     ARRAY_SIZE(wm8958_snd_controls));
 		snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
 					  ARRAY_SIZE(wm8958_dapm_widgets));
@@ -3819,24 +4047,27 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
-static int wm8994_soc_volatile(struct snd_soc_codec *codec,
-			       unsigned int reg)
-{
-	return true;
-}
-
 static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
 	.probe =	wm8994_codec_probe,
 	.remove =	wm8994_codec_remove,
-	.suspend =	wm8994_suspend,
-	.resume =	wm8994_resume,
+	.suspend =	wm8994_codec_suspend,
+	.resume =	wm8994_codec_resume,
 	.set_bias_level = wm8994_set_bias_level,
-	.reg_cache_size	= WM8994_MAX_REGISTER,
-	.volatile_register = wm8994_soc_volatile,
 };
 
 static int __devinit wm8994_probe(struct platform_device *pdev)
 {
+	struct wm8994_priv *wm8994;
+
+	wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv),
+			      GFP_KERNEL);
+	if (wm8994 == NULL)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, wm8994);
+
+	wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
+	wm8994->pdata = dev_get_platdata(pdev->dev.parent);
+
 	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
 			wm8994_dai, ARRAY_SIZE(wm8994_dai));
 }
@@ -3847,11 +4078,43 @@ static int __devexit wm8994_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int wm8994_suspend(struct device *dev)
+{
+	struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
+
+	/* Drop down to power saving mode when system is suspended */
+	if (wm8994->jackdet && !wm8994->active_refcount)
+		regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
+				   WM1811_JACKDET_MODE_MASK,
+				   wm8994->jackdet_mode);
+
+	return 0;
+}
+
+static int wm8994_resume(struct device *dev)
+{
+	struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
+
+	if (wm8994->jackdet && wm8994->jack_cb)
+		regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
+				   WM1811_JACKDET_MODE_MASK,
+				   WM1811_JACKDET_MODE_AUDIO);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops wm8994_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume)
+};
+
 static struct platform_driver wm8994_codec_driver = {
 	.driver = {
-		   .name = "wm8994-codec",
-		   .owner = THIS_MODULE,
-		   },
+		.name = "wm8994-codec",
+		.owner = THIS_MODULE,
+		.pm = &wm8994_pm_ops,
+	},
 	.probe = wm8994_probe,
 	.remove = __devexit_p(wm8994_remove),
 };
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index c3a42474ab19a6656fdd8549c3068559318b1a05..c724112998d87038fc55a219ae9b3eea66e1032f 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -32,13 +32,20 @@
 #define WM8994_FLL_SRC_LRCLK  3
 #define WM8994_FLL_SRC_BCLK   4
 
+enum wm8994_vmid_mode {
+	WM8994_VMID_NORMAL,
+	WM8994_VMID_FORCE,
+};
+
 typedef void (*wm8958_micdet_cb)(u16 status, void *data);
 
 int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
-		      int micbias, int det, int shrt);
+		      int micbias);
 int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 		      wm8958_micdet_cb cb, void *cb_data);
 
+int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode);
+
 int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
 		  struct snd_kcontrol *kcontrol, int event);
 
@@ -46,8 +53,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec);
 
 struct wm8994_micdet {
 	struct snd_soc_jack *jack;
-	int det;
-	int shrt;
+	bool detecting;
 };
 
 /* codec private data */
@@ -76,6 +82,7 @@ struct wm8994_priv {
 
 	int vmid_refcount;
 	int active_refcount;
+	enum wm8994_vmid_mode vmid_mode;
 
 	int dac_rates[2];
 	int lrclk_shared[2];
@@ -123,6 +130,7 @@ struct wm8994_priv {
 	bool jack_mic;
 	int btn_mask;
 	bool jackdet;
+	int jackdet_mode;
 
 	wm8958_micdet_cb jack_cb;
 	void *jack_cb_data;
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index c8aada597d7049cfc756cf887a886bd9f30cd54b..28c89b094c6ee6a5af57bab43a4a7f1c7d84f1f7 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -2047,7 +2047,6 @@ static int wm8995_probe(struct snd_soc_codec *codec)
 	int i;
 	int ret;
 
-	codec->dapm.idle_bias_off = 1;
 	wm8995 = snd_soc_codec_get_drvdata(codec);
 	wm8995->codec = codec;
 
@@ -2137,7 +2136,7 @@ static int wm8995_probe(struct snd_soc_codec *codec)
 
 	wm8995_update_class_w(codec);
 
-	snd_soc_add_controls(codec, wm8995_snd_controls,
+	snd_soc_add_codec_controls(codec, wm8995_snd_controls,
 			     ARRAY_SIZE(wm8995_snd_controls));
 	snd_soc_dapm_new_controls(&codec->dapm, wm8995_dapm_widgets,
 				  ARRAY_SIZE(wm8995_dapm_widgets));
@@ -2241,6 +2240,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
 	.suspend = wm8995_suspend,
 	.resume = wm8995_resume,
 	.set_bias_level = wm8995_set_bias_level,
+	.idle_bias_off = true,
 };
 
 static struct regmap_config wm8995_regmap = {
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 61f7daa4d0e681571222fce0910ab148e8b0f18a..1fd635494045f71e44731e1abe7959b980a33b45 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -73,7 +73,6 @@ struct wm8996_priv {
 
 	struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES];
 	struct notifier_block disable_nb[WM8996_NUM_SUPPLIES];
-	struct regulator *cpvdd;
 	int bg_ena;
 
 	struct wm8996_pdata pdata;
@@ -90,6 +89,7 @@ struct wm8996_priv {
 	struct snd_soc_jack *jack;
 	bool detecting;
 	bool jack_mic;
+	int jack_flips;
 	wm8996_polarity_fn polarity_cb;
 
 #ifdef CONFIG_GPIOLIB
@@ -118,7 +118,6 @@ WM8996_REGULATOR_EVENT(1)
 WM8996_REGULATOR_EVENT(2)
 
 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 },
@@ -153,7 +152,6 @@ static struct reg_default wm8996_reg[] = {
 	{ 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 },
@@ -716,10 +714,16 @@ SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
 SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0),
 SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0),
 SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0),
+SND_SOC_BYTES_MASK("DSP1 DRC", WM8996_DSP1_DRC_1, 5,
+		   WM8996_DSP1RX_DRC_ENA | WM8996_DSP1TXL_DRC_ENA |
+		   WM8996_DSP1TXR_DRC_ENA),
 
 SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0),
 SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0),
 SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0),
+SND_SOC_BYTES_MASK("DSP2 DRC", WM8996_DSP2_DRC_1, 5,
+		   WM8996_DSP2RX_DRC_ENA | WM8996_DSP2TXL_DRC_ENA |
+		   WM8996_DSP2TXR_DRC_ENA),
 };
 
 static const struct snd_kcontrol_new wm8996_eq_controls[] = {
@@ -792,29 +796,18 @@ static int bg_event(struct snd_soc_dapm_widget *w,
 static int cp_event(struct snd_soc_dapm_widget *w,
 		    struct snd_kcontrol *kcontrol, int event)
 {
-	struct snd_soc_codec *codec = w->codec;
-	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	int ret = 0;
 
 	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		ret = regulator_enable(wm8996->cpvdd);
-		if (ret != 0)
-			dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
-				ret);
-		break;
 	case SND_SOC_DAPM_POST_PMU:
 		msleep(5);
 		break;
-	case SND_SOC_DAPM_POST_PMD:
-		regulator_disable_deferred(wm8996->cpvdd, 20);
-		break;
 	default:
 		BUG();
 		ret = -EINVAL;
 	}
 
-	return ret;
+	return 0;
 }
 
 static int rmv_short_event(struct snd_soc_dapm_widget *w,
@@ -897,8 +890,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
 		val = 0;
 		mask = 0;
 		if (wm8996->hpout_pending & HPOUT1L) {
-			val |= WM8996_HPOUT1L_RMV_SHORT;
-			mask |= WM8996_HPOUT1L_RMV_SHORT;
+			val |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP;
+			mask |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP;
 		} else {
 			mask |= WM8996_HPOUT1L_RMV_SHORT |
 				WM8996_HPOUT1L_OUTP |
@@ -906,8 +899,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
 		}
 
 		if (wm8996->hpout_pending & HPOUT1R) {
-			val |= WM8996_HPOUT1R_RMV_SHORT;
-			mask |= WM8996_HPOUT1R_RMV_SHORT;
+			val |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP;
+			mask |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP;
 		} else {
 			mask |= WM8996_HPOUT1R_RMV_SHORT |
 				WM8996_HPOUT1R_OUTP |
@@ -919,8 +912,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
 		val = 0;
 		mask = 0;
 		if (wm8996->hpout_pending & HPOUT2L) {
-			val |= WM8996_HPOUT2L_RMV_SHORT;
-			mask |= WM8996_HPOUT2L_RMV_SHORT;
+			val |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP;
+			mask |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP;
 		} else {
 			mask |= WM8996_HPOUT2L_RMV_SHORT |
 				WM8996_HPOUT2L_OUTP |
@@ -928,8 +921,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
 		}
 
 		if (wm8996->hpout_pending & HPOUT2R) {
-			val |= WM8996_HPOUT2R_RMV_SHORT;
-			mask |= WM8996_HPOUT2R_RMV_SHORT;
+			val |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP;
+			mask |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP;
 		} else {
 			mask |= WM8996_HPOUT2R_RMV_SHORT |
 				WM8996_HPOUT2R_OUTP |
@@ -1116,12 +1109,12 @@ SND_SOC_DAPM_INPUT("IN2RP"),
 SND_SOC_DAPM_INPUT("DMIC1DAT"),
 SND_SOC_DAPM_INPUT("DMIC2DAT"),
 
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
 SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
-		      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-		      SND_SOC_DAPM_POST_PMD),
+		      SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
 		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
@@ -1180,41 +1173,25 @@ SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0),
 SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0),
 SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0),
 
-SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
-		    WM8996_POWER_MANAGEMENT_4, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1,
-		    WM8996_POWER_MANAGEMENT_4, 8, 0),
-
-SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
-		    WM8996_POWER_MANAGEMENT_6, 9, 0),
-SND_SOC_DAPM_AIF_OUT("AIF2TX0", "AIF2 Capture", 1,
-		    WM8996_POWER_MANAGEMENT_6, 8, 0),
-
-SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
-		    WM8996_POWER_MANAGEMENT_4, 5, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 4,
-		    WM8996_POWER_MANAGEMENT_4, 4, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 3,
-		    WM8996_POWER_MANAGEMENT_4, 3, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 2,
-		    WM8996_POWER_MANAGEMENT_4, 2, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 1,
-		    WM8996_POWER_MANAGEMENT_4, 1, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX0", "AIF1 Playback", 0,
-		    WM8996_POWER_MANAGEMENT_4, 0, 0),
-
-SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 5,
-		     WM8996_POWER_MANAGEMENT_6, 5, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 4,
-		     WM8996_POWER_MANAGEMENT_6, 4, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 3,
-		     WM8996_POWER_MANAGEMENT_6, 3, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 2,
-		     WM8996_POWER_MANAGEMENT_6, 2, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 1,
-		     WM8996_POWER_MANAGEMENT_6, 1, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX0", "AIF1 Capture", 0,
-		     WM8996_POWER_MANAGEMENT_6, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, WM8996_POWER_MANAGEMENT_4, 9, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX0", NULL, 1, WM8996_POWER_MANAGEMENT_4, 8, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, WM8996_POWER_MANAGEMENT_6, 9, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX0", NULL, 1, WM8996_POWER_MANAGEMENT_6, 8, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 5, WM8996_POWER_MANAGEMENT_4, 5, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 4, WM8996_POWER_MANAGEMENT_4, 4, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 3, WM8996_POWER_MANAGEMENT_4, 3, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 2, WM8996_POWER_MANAGEMENT_4, 2, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 1, WM8996_POWER_MANAGEMENT_4, 1, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX0", NULL, 0, WM8996_POWER_MANAGEMENT_4, 0, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 5, WM8996_POWER_MANAGEMENT_6, 5, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 4, WM8996_POWER_MANAGEMENT_6, 4, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 3, WM8996_POWER_MANAGEMENT_6, 3, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 2, WM8996_POWER_MANAGEMENT_6, 2, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 1, WM8996_POWER_MANAGEMENT_6, 1, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX0", NULL, 0, WM8996_POWER_MANAGEMENT_6, 0, 0),
 
 /* We route as stereo pairs so define some dummy widgets to squash
  * things down for now.  RXA = 0,1, RXB = 2,3 and so on */
@@ -1237,7 +1214,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8996_POWER_MANAGEMENT_1, 7, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8996_ANALOGUE_HP_2, 5, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8996_DC_SERVO_1, 2, 0, dcs_start,
 		   SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT2L_OUTP", 3, WM8996_ANALOGUE_HP_2, 6, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0,
 		   rmv_short_event,
 		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1246,7 +1222,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8996_POWER_MANAGEMENT_1, 6, 0,NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8996_ANALOGUE_HP_2, 1, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8996_DC_SERVO_1, 3, 0, dcs_start,
 		   SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT2R_OUTP", 3, WM8996_ANALOGUE_HP_2, 2, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0,
 		   rmv_short_event,
 		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1255,7 +1230,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8996_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8996_ANALOGUE_HP_1, 5, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8996_DC_SERVO_1, 0, 0, dcs_start,
 		   SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT1L_OUTP", 3, WM8996_ANALOGUE_HP_1, 6, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0,
 		   rmv_short_event,
 		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1264,7 +1238,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8996_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8996_ANALOGUE_HP_1, 1, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8996_DC_SERVO_1, 1, 0, dcs_start,
 		   SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT1R_OUTP", 3, WM8996_ANALOGUE_HP_1, 2, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0,
 		   rmv_short_event,
 		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1280,6 +1253,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
 	{ "AIFCLK", NULL, "SYSCLK" },
 	{ "SYSDSPCLK", NULL, "SYSCLK" },
 	{ "Charge Pump", NULL, "SYSCLK" },
+	{ "Charge Pump", NULL, "CPVDD" },
 
 	{ "MICB1", NULL, "LDO2" },
 	{ "MICB1", NULL, "MICB1 Audio" },
@@ -1288,6 +1262,26 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
 	{ "MICB2", NULL, "MICB2 Audio" },
 	{ "MICB2", NULL, "Bandgap" },
 
+	{ "AIF1RX0", NULL, "AIF1 Playback" },
+	{ "AIF1RX1", NULL, "AIF1 Playback" },
+	{ "AIF1RX2", NULL, "AIF1 Playback" },
+	{ "AIF1RX3", NULL, "AIF1 Playback" },
+	{ "AIF1RX4", NULL, "AIF1 Playback" },
+	{ "AIF1RX5", NULL, "AIF1 Playback" },
+
+	{ "AIF2RX0", NULL, "AIF2 Playback" },
+	{ "AIF2RX1", NULL, "AIF2 Playback" },
+
+	{ "AIF1 Capture", NULL, "AIF1TX0" },
+	{ "AIF1 Capture", NULL, "AIF1TX1" },
+	{ "AIF1 Capture", NULL, "AIF1TX2" },
+	{ "AIF1 Capture", NULL, "AIF1TX3" },
+	{ "AIF1 Capture", NULL, "AIF1TX4" },
+	{ "AIF1 Capture", NULL, "AIF1TX5" },
+
+	{ "AIF2 Capture", NULL, "AIF2TX0" },
+	{ "AIF2 Capture", NULL, "AIF2TX1" },
+
 	{ "IN1L PGA", NULL, "IN2LN" },
 	{ "IN1L PGA", NULL, "IN2LP" },
 	{ "IN1L PGA", NULL, "IN1LN" },
@@ -1436,32 +1430,28 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
 	{ "HPOUT2L PGA", NULL, "DAC2L" },
 	{ "HPOUT2L_DLY", NULL, "HPOUT2L PGA" },
 	{ "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" },
-	{ "HPOUT2L_OUTP", NULL, "HPOUT2L_DCS" },
-	{ "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" },
+	{ "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_DCS" },
 
 	{ "HPOUT2R PGA", NULL, "Charge Pump" },
 	{ "HPOUT2R PGA", NULL, "Bandgap" },
 	{ "HPOUT2R PGA", NULL, "DAC2R" },
 	{ "HPOUT2R_DLY", NULL, "HPOUT2R PGA" },
 	{ "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" },
-	{ "HPOUT2R_OUTP", NULL, "HPOUT2R_DCS" },
-	{ "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" },
+	{ "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_DCS" },
 
 	{ "HPOUT1L PGA", NULL, "Charge Pump" },
 	{ "HPOUT1L PGA", NULL, "Bandgap" },
 	{ "HPOUT1L PGA", NULL, "DAC1L" },
 	{ "HPOUT1L_DLY", NULL, "HPOUT1L PGA" },
 	{ "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" },
-	{ "HPOUT1L_OUTP", NULL, "HPOUT1L_DCS" },
-	{ "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" },
+	{ "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_DCS" },
 
 	{ "HPOUT1R PGA", NULL, "Charge Pump" },
 	{ "HPOUT1R PGA", NULL, "Bandgap" },
 	{ "HPOUT1R PGA", NULL, "DAC1R" },
 	{ "HPOUT1R_DLY", NULL, "HPOUT1R PGA" },
 	{ "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" },
-	{ "HPOUT1R_OUTP", NULL, "HPOUT1R_DCS" },
-	{ "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_OUTP" },
+	{ "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_DCS" },
 
 	{ "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" },
 	{ "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" },
@@ -1720,6 +1710,7 @@ static int wm8996_reset(struct wm8996_priv *wm8996)
 {
 	if (wm8996->pdata.ldo_ena > 0) {
 		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+		gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
 		return 0;
 	} else {
 		return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
@@ -1923,7 +1914,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_codec *codec = dai->codec;
 	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
-	int bits, i, bclk_rate;
+	int bits, i, bclk_rate, best;
 	int aifdata = 0;
 	int lrclk = 0;
 	int dsp = 0;
@@ -1972,14 +1963,11 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
 		return bits;
 	aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits;
 
+	best = 0;
 	for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) {
-		if (dsp_divs[i] == params_rate(params))
-			break;
-	}
-	if (i == ARRAY_SIZE(dsp_divs)) {
-		dev_err(codec->dev, "Unsupported sample rate %dHz\n",
-			params_rate(params));
-		return -EINVAL;
+		if (abs(dsp_divs[i] - params_rate(params)) <
+		    abs(dsp_divs[best] - params_rate(params)))
+			best = i;
 	}
 	dsp |= i << dsp_shift;
 
@@ -2039,13 +2027,16 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
 	}
 
 	switch (wm8996->sysclk) {
+	case 5644800:
 	case 6144000:
 		snd_soc_update_bits(codec, WM8996_AIF_RATE,
 				    WM8996_SYSCLK_RATE, 0);
 		break;
+	case 22579200:
 	case 24576000:
 		ratediv = WM8996_SYSCLK_DIV;
 		wm8996->sysclk /= 2;
+	case 11289600:
 	case 12288000:
 		snd_soc_update_bits(codec, WM8996_AIF_RATE,
 				    WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE);
@@ -2438,6 +2429,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 	wm8996->jack = jack;
 	wm8996->detecting = true;
 	wm8996->polarity_cb = polarity_cb;
+	wm8996->jack_flips = 0;
 
 	if (wm8996->polarity_cb)
 		wm8996->polarity_cb(codec, 0);
@@ -2553,6 +2545,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec)
 			    WM8996_HP_POLL, WM8996_HP_POLL);
 }
 
+static void wm8996_report_headphone(struct snd_soc_codec *codec)
+{
+	dev_dbg(codec->dev, "Headphone detected\n");
+	wm8996_hpdet_start(codec);
+
+	/* Increase the detection rate a bit for responsiveness. */
+	snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+			    WM8996_MICD_RATE_MASK |
+			    WM8996_MICD_BIAS_STARTTIME_MASK,
+			    7 << WM8996_MICD_RATE_SHIFT |
+			    7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+}
+
 static void wm8996_micd(struct snd_soc_codec *codec)
 {
 	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
@@ -2572,6 +2577,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
 		dev_dbg(codec->dev, "Jack removal detected\n");
 		wm8996->jack_mic = false;
 		wm8996->detecting = true;
+		wm8996->jack_flips = 0;
 		snd_soc_jack_report(wm8996->jack, 0,
 				    SND_JACK_LINEOUT | SND_JACK_HEADSET |
 				    SND_JACK_BTN_0);
@@ -2612,9 +2618,17 @@ static void wm8996_micd(struct snd_soc_codec *codec)
 	/* If we detected a lower impedence during initial startup
 	 * then we probably have the wrong polarity, flip it.  Don't
 	 * do this for the lowest impedences to speed up detection of
-	 * plain headphones.
+	 * plain headphones.  If both polarities report a low
+	 * impedence then give up and report headphones.
 	 */
 	if (wm8996->detecting && (val & 0x3f0)) {
+		wm8996->jack_flips++;
+
+		if (wm8996->jack_flips > 1) {
+			wm8996_report_headphone(codec);
+			return;
+		}
+
 		reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
 		reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
 			WM8996_MICD_BIAS_SRC;
@@ -2641,17 +2655,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
 			snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0,
 					    SND_JACK_BTN_0);
 		} else if (wm8996->detecting) {
-			dev_dbg(codec->dev, "Headphone detected\n");
-			wm8996_hpdet_start(codec);
-
-			/* Increase the detection rate a bit for
-			 * responsiveness.
-			 */
-			snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
-					    WM8996_MICD_RATE_MASK |
-					    WM8996_MICD_BIAS_STARTTIME_MASK,
-					    7 << WM8996_MICD_RATE_SHIFT |
-					    7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+			wm8996_report_headphone(codec);
 		}
 	}
 }
@@ -2768,7 +2772,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec)
 	wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts;
 	wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts;
 
-	ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+	ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
 	if (ret != 0)
 		dev_err(codec->dev,
 			"Failed to add ReTune Mobile controls: %d\n", ret);
@@ -2791,7 +2795,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
 	int ret;
 	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	struct i2c_client *i2c = to_i2c_client(codec->dev);
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int i, irq_flags;
 
 	wm8996->codec = codec;
@@ -2799,8 +2802,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
 	init_completion(&wm8996->dcs_done);
 	init_completion(&wm8996->fll_lock);
 
-	dapm->idle_bias_off = true;
-
 	codec->control_data = wm8996->regmap;
 
 	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
@@ -2966,7 +2967,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
 	if (wm8996->pdata.num_retune_mobile_cfgs)
 		wm8996_retune_mobile_pdata(codec);
 	else
-		snd_soc_add_controls(codec, wm8996_eq_controls,
+		snd_soc_add_codec_controls(codec, wm8996_eq_controls,
 				     ARRAY_SIZE(wm8996_eq_controls));
 
 	/* If the TX LRCLK pins are not in LRCLK mode configure the
@@ -3038,22 +3039,16 @@ static int wm8996_remove(struct snd_soc_codec *codec)
 	for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
 		regulator_unregister_notifier(wm8996->supplies[i].consumer,
 					      &wm8996->disable_nb[i]);
-	regulator_put(wm8996->cpvdd);
 	regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
 
 	return 0;
 }
 
-static int wm8996_soc_volatile_register(struct snd_soc_codec *codec,
-					unsigned int reg)
-{
-	return true;
-}
-
 static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
 	.probe =	wm8996_probe,
 	.remove =	wm8996_remove,
 	.set_bias_level = wm8996_set_bias_level,
+	.idle_bias_off	= true,
 	.seq_notifier = wm8996_seq_notifier,
 	.controls = wm8996_snd_controls,
 	.num_controls = ARRAY_SIZE(wm8996_snd_controls),
@@ -3062,12 +3057,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
 	.dapm_routes = wm8996_dapm_routes,
 	.num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes),
 	.set_pll = wm8996_set_fll,
-	.reg_cache_size = WM8996_MAX_REGISTER,
-	.volatile_register = wm8996_soc_volatile_register,
 };
 
 #define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
-		      SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+		      SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
+		      SNDRV_PCM_RATE_48000)
 #define WM8996_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
 			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\
 			SNDRV_PCM_FMTBIT_S32_LE)
@@ -3087,6 +3081,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
 			.channels_max = 6,
 			.rates = WM8996_RATES,
 			.formats = WM8996_FORMATS,
+			.sig_bits = 24,
 		},
 		.capture = {
 			 .stream_name = "AIF1 Capture",
@@ -3094,6 +3089,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
 			 .channels_max = 6,
 			 .rates = WM8996_RATES,
 			 .formats = WM8996_FORMATS,
+			 .sig_bits = 24,
 		 },
 		.ops = &wm8996_dai_ops,
 	},
@@ -3105,6 +3101,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
 			.channels_max = 2,
 			.rates = WM8996_RATES,
 			.formats = WM8996_FORMATS,
+			.sig_bits = 24,
 		},
 		.capture = {
 			 .stream_name = "AIF2 Capture",
@@ -3112,6 +3109,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
 			 .channels_max = 2,
 			 .rates = WM8996_RATES,
 			 .formats = WM8996_FORMATS,
+			.sig_bits = 24,
 		 },
 		.ops = &wm8996_dai_ops,
 	},
@@ -3149,25 +3147,18 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
 	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);
+	ret = devm_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;
+		goto err_gpio;
 	}
 
 	if (wm8996->pdata.ldo_ena > 0) {
@@ -3188,7 +3179,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
 		goto err_regmap;
 	}
 	if (reg != 0x8915) {
-		dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", ret);
+		dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", reg);
 		ret = -EINVAL;
 		goto err_regmap;
 	}
@@ -3229,10 +3220,6 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
 	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);
@@ -3247,8 +3234,6 @@ static __devexit int wm8996_i2c_remove(struct i2c_client *client)
 
 	snd_soc_unregister_codec(&client->dev);
 	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);
@@ -3273,25 +3258,7 @@ static struct i2c_driver wm8996_i2c_driver = {
 	.id_table = wm8996_i2c_id,
 };
 
-static int __init wm8996_modinit(void)
-{
-	int ret;
-
-	ret = i2c_add_driver(&wm8996_i2c_driver);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register WM8996 I2C driver: %d\n",
-		       ret);
-	}
-
-	return ret;
-}
-module_init(wm8996_modinit);
-
-static void __exit wm8996_exit(void)
-{
-	i2c_del_driver(&wm8996_i2c_driver);
-}
-module_exit(wm8996_exit);
+module_i2c_driver(wm8996_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8996 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index a6bab392700e94bfe138e8ae2322f1df47d3a70d..076c126ed9b1812b63cc186138859a43832a8b9e 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -824,6 +824,8 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
 static int wm9081_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
+	struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
+
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		break;
@@ -841,6 +843,9 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
 	case SND_SOC_BIAS_STANDBY:
 		/* Initial cold start */
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			regcache_cache_only(wm9081->regmap, false);
+			regcache_sync(wm9081->regmap);
+
 			/* Disable LINEOUT discharge */
 			snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
 					    WM9081_LINEOUT_DISCH, 0);
@@ -892,6 +897,8 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
 		snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
 				    WM9081_LINEOUT_DISCH,
 				    WM9081_LINEOUT_DISCH);
+
+		regcache_cache_only(wm9081->regmap, true);
 		break;
 	}
 
@@ -1258,7 +1265,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
 {
 	struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
 	int ret;
-	u16 reg;
 
 	codec->control_data = wm9081->regmap;
 
@@ -1268,16 +1274,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
-	reg = 0;
-	if (wm9081->pdata.irq_high)
-		reg |= WM9081_IRQ_POL;
-	if (!wm9081->pdata.irq_cmos)
-		reg |= WM9081_IRQ_OP_CTRL;
-	snd_soc_update_bits(codec, WM9081_INTERRUPT_CONTROL,
-			    WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
-
-	wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
 	/* Enable zero cross by default */
 	snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
 			    WM9081_LINEOUTZC, WM9081_LINEOUTZC);
@@ -1287,7 +1283,7 @@ static int wm9081_probe(struct snd_soc_codec *codec)
 	if (!wm9081->pdata.num_retune_configs) {
 		dev_dbg(codec->dev,
 			"No ReTune Mobile data, using normal EQ\n");
-		snd_soc_add_controls(codec, wm9081_eq_controls,
+		snd_soc_add_codec_controls(codec, wm9081_eq_controls,
 				     ARRAY_SIZE(wm9081_eq_controls));
 	}
 
@@ -1300,38 +1296,15 @@ static int wm9081_remove(struct snd_soc_codec *codec)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int wm9081_suspend(struct snd_soc_codec *codec)
-{
-	wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-	return 0;
-}
-
-static int wm9081_resume(struct snd_soc_codec *codec)
-{
-	struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
-
-	regcache_sync(wm9081->regmap);
-
-	wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-	return 0;
-}
-#else
-#define wm9081_suspend NULL
-#define wm9081_resume NULL
-#endif
-
 static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
 	.probe = 	wm9081_probe,
 	.remove = 	wm9081_remove,
-	.suspend =	wm9081_suspend,
-	.resume =	wm9081_resume,
 
 	.set_sysclk = wm9081_set_sysclk,
 	.set_bias_level = wm9081_set_bias_level,
 
+	.idle_bias_off = true,
+
 	.controls         = wm9081_snd_controls,
 	.num_controls     = ARRAY_SIZE(wm9081_snd_controls),
 	.dapm_widgets	  = wm9081_dapm_widgets,
@@ -1395,6 +1368,16 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
 		memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
 		       sizeof(wm9081->pdata));
 
+	reg = 0;
+	if (wm9081->pdata.irq_high)
+		reg |= WM9081_IRQ_POL;
+	if (!wm9081->pdata.irq_cmos)
+		reg |= WM9081_IRQ_OP_CTRL;
+	regmap_update_bits(wm9081->regmap, WM9081_INTERRUPT_CONTROL,
+			   WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
+
+	regcache_cache_only(wm9081->regmap, true);
+
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm9081, &wm9081_dai, 1);
 	if (ret < 0)
@@ -1435,28 +1418,7 @@ static struct i2c_driver wm9081_i2c_driver = {
 };
 #endif
 
-static int __init wm9081_modinit(void)
-{
-	int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	ret = i2c_add_driver(&wm9081_i2c_driver);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
-		       ret);
-	}
-#endif
-	return ret;
-}
-module_init(wm9081_modinit);
-
-static void __exit wm9081_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	i2c_del_driver(&wm9081_i2c_driver);
-#endif
-}
-module_exit(wm9081_exit);
-
+module_i2c_driver(wm9081_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM9081 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 41ebe0dce772c908bcbcf53fdaff8264ac497e55..4b263b6edf13793908d3d1ab11c2630e5bee9054 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -25,6 +25,7 @@
 #include <linux/device.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
@@ -33,116 +34,51 @@
 
 #include "wm9090.h"
 
-static const u16 wm9090_reg_defaults[] = {
-	0x9093,     /* R0   - Software Reset */
-	0x0006,     /* R1   - Power Management (1) */
-	0x6000,     /* R2   - Power Management (2) */
-	0x0000,     /* R3   - Power Management (3) */
-	0x0000,     /* R4 */
-	0x0000,     /* R5 */
-	0x01C0,     /* R6   - Clocking 1 */
-	0x0000,     /* R7 */
-	0x0000,     /* R8 */
-	0x0000,     /* R9 */
-	0x0000,     /* R10 */
-	0x0000,     /* R11 */
-	0x0000,     /* R12 */
-	0x0000,     /* R13 */
-	0x0000,     /* R14 */
-	0x0000,     /* R15 */
-	0x0000,     /* R16 */
-	0x0000,     /* R17 */
-	0x0000,     /* R18 */
-	0x0000,     /* R19 */
-	0x0000,     /* R20 */
-	0x0000,     /* R21 */
-	0x0003,     /* R22  - IN1 Line Control */
-	0x0003,     /* R23  - IN2 Line Control */
-	0x0083,     /* R24  - IN1 Line Input A Volume */
-	0x0083,     /* R25  - IN1  Line Input B Volume */
-	0x0083,     /* R26  - IN2 Line Input A Volume */
-	0x0083,     /* R27  - IN2 Line Input B Volume */
-	0x002D,     /* R28  - Left Output Volume */
-	0x002D,     /* R29  - Right Output Volume */
-	0x0000,     /* R30 */
-	0x0000,     /* R31 */
-	0x0000,     /* R32 */
-	0x0000,     /* R33 */
-	0x0100,     /* R34  - SPKMIXL Attenuation */
-	0x0000,     /* R35 */
-	0x0010,     /* R36  - SPKOUT Mixers */
-	0x0140,     /* R37  - ClassD3 */
-	0x0039,     /* R38  - Speaker Volume Left */
-	0x0000,     /* R39 */
-	0x0000,     /* R40 */
-	0x0000,     /* R41 */
-	0x0000,     /* R42 */
-	0x0000,     /* R43 */
-	0x0000,     /* R44 */
-	0x0000,     /* R45  - Output Mixer1 */
-	0x0000,     /* R46  - Output Mixer2 */
-	0x0100,     /* R47  - Output Mixer3 */
-	0x0100,     /* R48  - Output Mixer4 */
-	0x0000,     /* R49 */
-	0x0000,     /* R50 */
-	0x0000,     /* R51 */
-	0x0000,     /* R52 */
-	0x0000,     /* R53 */
-	0x0000,     /* R54  - Speaker Mixer */
-	0x0000,     /* R55 */
-	0x0000,     /* R56 */
-	0x000D,     /* R57  - AntiPOP2 */
-	0x0000,     /* R58 */
-	0x0000,     /* R59 */
-	0x0000,     /* R60 */
-	0x0000,     /* R61 */
-	0x0000,     /* R62 */
-	0x0000,     /* R63 */
-	0x0000,     /* R64 */
-	0x0000,     /* R65 */
-	0x0000,     /* R66 */
-	0x0000,     /* R67 */
-	0x0000,     /* R68 */
-	0x0000,     /* R69 */
-	0x0000,     /* R70  - Write Sequencer 0 */
-	0x0000,     /* R71  - Write Sequencer 1 */
-	0x0000,     /* R72  - Write Sequencer 2 */
-	0x0000,     /* R73  - Write Sequencer 3 */
-	0x0000,     /* R74  - Write Sequencer 4 */
-	0x0000,     /* R75  - Write Sequencer 5 */
-	0x1F25,     /* R76  - Charge Pump 1 */
-	0x0000,     /* R77 */
-	0x0000,     /* R78 */
-	0x0000,     /* R79 */
-	0x0000,     /* R80 */
-	0x0000,     /* R81 */
-	0x0000,     /* R82 */
-	0x0000,     /* R83 */
-	0x0000,     /* R84  - DC Servo 0 */
-	0x054A,     /* R85  - DC Servo 1 */
-	0x0000,     /* R86 */
-	0x0000,     /* R87  - DC Servo 3 */
-	0x0000,     /* R88  - DC Servo Readback 0 */
-	0x0000,     /* R89  - DC Servo Readback 1 */
-	0x0000,     /* R90  - DC Servo Readback 2 */
-	0x0000,     /* R91 */
-	0x0000,     /* R92 */
-	0x0000,     /* R93 */
-	0x0000,     /* R94 */
-	0x0000,     /* R95 */
-	0x0100,     /* R96  - Analogue HP 0 */
-	0x0000,     /* R97 */
-	0x8640,     /* R98  - AGC Control 0 */
-	0xC000,     /* R99  - AGC Control 1 */
-	0x0200,     /* R100 - AGC Control 2 */
+static const struct reg_default wm9090_reg_defaults[] = {
+	{ 1,  0x0006 },     /* R1   - Power Management (1) */
+	{ 2,  0x6000 },     /* R2   - Power Management (2) */
+	{ 3,  0x0000 },     /* R3   - Power Management (3) */
+	{ 6,  0x01C0 },     /* R6   - Clocking 1 */
+	{ 22, 0x0003 },     /* R22  - IN1 Line Control */
+	{ 23, 0x0003 },     /* R23  - IN2 Line Control */
+	{ 24, 0x0083 },     /* R24  - IN1 Line Input A Volume */
+	{ 25, 0x0083 },     /* R25  - IN1  Line Input B Volume */
+	{ 26, 0x0083 },     /* R26  - IN2 Line Input A Volume */
+	{ 27, 0x0083 },     /* R27  - IN2 Line Input B Volume */
+	{ 28, 0x002D },     /* R28  - Left Output Volume */
+	{ 29, 0x002D },     /* R29  - Right Output Volume */
+	{ 34, 0x0100 },     /* R34  - SPKMIXL Attenuation */
+	{ 35, 0x0010 },     /* R36  - SPKOUT Mixers */
+	{ 37, 0x0140 },     /* R37  - ClassD3 */
+	{ 38, 0x0039 },     /* R38  - Speaker Volume Left */
+	{ 45, 0x0000 },     /* R45  - Output Mixer1 */
+	{ 46, 0x0000 },     /* R46  - Output Mixer2 */
+	{ 47, 0x0100 },     /* R47  - Output Mixer3 */
+	{ 48, 0x0100 },     /* R48  - Output Mixer4 */
+	{ 54, 0x0000 },     /* R54  - Speaker Mixer */
+	{ 57, 0x000D },     /* R57  - AntiPOP2 */
+	{ 70, 0x0000 },     /* R70  - Write Sequencer 0 */
+	{ 71, 0x0000 },     /* R71  - Write Sequencer 1 */
+	{ 72, 0x0000 },     /* R72  - Write Sequencer 2 */
+	{ 73, 0x0000 },     /* R73  - Write Sequencer 3 */
+	{ 74, 0x0000 },     /* R74  - Write Sequencer 4 */
+	{ 75, 0x0000 },     /* R75  - Write Sequencer 5 */
+	{ 76, 0x1F25 },     /* R76  - Charge Pump 1 */
+	{ 85, 0x054A },     /* R85  - DC Servo 1 */
+	{ 87, 0x0000 },     /* R87  - DC Servo 3 */
+	{ 96, 0x0100 },     /* R96  - Analogue HP 0 */
+	{ 98, 0x8640 },     /* R98  - AGC Control 0 */
+	{ 99, 0xC000 },     /* R99  - AGC Control 1 */
+	{ 100, 0x0200 },     /* R100 - AGC Control 2 */
 };
 
 /* This struct is used to save the context */
 struct wm9090_priv {
 	struct wm9090_platform_data pdata;
+	struct regmap *regmap;
 };
 
-static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm9090_volatile(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case WM9090_SOFTWARE_RESET:
@@ -150,10 +86,60 @@ static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
 	case WM9090_DC_SERVO_READBACK_0:
 	case WM9090_DC_SERVO_READBACK_1:
 	case WM9090_DC_SERVO_READBACK_2:
-		return 1;
+		return true;
 
 	default:
-		return 0;
+		return false;
+	}
+}
+
+static bool wm9090_readable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case WM9090_SOFTWARE_RESET:
+	case WM9090_POWER_MANAGEMENT_1:
+	case WM9090_POWER_MANAGEMENT_2:
+	case WM9090_POWER_MANAGEMENT_3:
+	case WM9090_CLOCKING_1:
+	case WM9090_IN1_LINE_CONTROL:
+	case WM9090_IN2_LINE_CONTROL:
+	case WM9090_IN1_LINE_INPUT_A_VOLUME:
+	case WM9090_IN1_LINE_INPUT_B_VOLUME:
+	case WM9090_IN2_LINE_INPUT_A_VOLUME:
+	case WM9090_IN2_LINE_INPUT_B_VOLUME:
+	case WM9090_LEFT_OUTPUT_VOLUME:
+	case WM9090_RIGHT_OUTPUT_VOLUME:
+	case WM9090_SPKMIXL_ATTENUATION:
+	case WM9090_SPKOUT_MIXERS:
+	case WM9090_CLASSD3:
+	case WM9090_SPEAKER_VOLUME_LEFT:
+	case WM9090_OUTPUT_MIXER1:
+	case WM9090_OUTPUT_MIXER2:
+	case WM9090_OUTPUT_MIXER3:
+	case WM9090_OUTPUT_MIXER4:
+	case WM9090_SPEAKER_MIXER:
+	case WM9090_ANTIPOP2:
+	case WM9090_WRITE_SEQUENCER_0:
+	case WM9090_WRITE_SEQUENCER_1:
+	case WM9090_WRITE_SEQUENCER_2:
+	case WM9090_WRITE_SEQUENCER_3:
+	case WM9090_WRITE_SEQUENCER_4:
+	case WM9090_WRITE_SEQUENCER_5:
+	case WM9090_CHARGE_PUMP_1:
+	case WM9090_DC_SERVO_0:
+	case WM9090_DC_SERVO_1:
+	case WM9090_DC_SERVO_3:
+	case WM9090_DC_SERVO_READBACK_0:
+	case WM9090_DC_SERVO_READBACK_1:
+	case WM9090_DC_SERVO_READBACK_2:
+	case WM9090_ANALOGUE_HP_0:
+	case WM9090_AGC_CONTROL_0:
+	case WM9090_AGC_CONTROL_1:
+	case WM9090_AGC_CONTROL_2:
+		return true;
+
+	default:
+		return false;
 	}
 }
 
@@ -447,7 +433,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
 
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-	snd_soc_add_controls(codec, wm9090_controls,
+	snd_soc_add_codec_controls(codec, wm9090_controls,
 			     ARRAY_SIZE(wm9090_controls));
 
 	if (wm9090->pdata.lin1_diff) {
@@ -456,7 +442,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
 	} else {
 		snd_soc_dapm_add_routes(dapm, audio_map_in1_se,
 					ARRAY_SIZE(audio_map_in1_se));
-		snd_soc_add_controls(codec, wm9090_in1_se_controls,
+		snd_soc_add_codec_controls(codec, wm9090_in1_se_controls,
 				     ARRAY_SIZE(wm9090_in1_se_controls));
 	}
 
@@ -466,7 +452,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
 	} else {
 		snd_soc_dapm_add_routes(dapm, audio_map_in2_se,
 					ARRAY_SIZE(audio_map_in2_se));
-		snd_soc_add_controls(codec, wm9090_in2_se_controls,
+		snd_soc_add_codec_controls(codec, wm9090_in2_se_controls,
 				     ARRAY_SIZE(wm9090_in2_se_controls));
 	}
 
@@ -492,8 +478,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
 static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
-	u16 *reg_cache = codec->reg_cache;
-	int i, ret;
+	struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
@@ -513,7 +498,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
 			/* Restore the register cache */
-			snd_soc_cache_sync(codec);
+			regcache_sync(wm9090->regmap);
 		}
 
 		/* We keep VMID off during standby since the combination of
@@ -537,26 +522,16 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 
 static int wm9090_probe(struct snd_soc_codec *codec)
 {
+	struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev);
 	int ret;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+	codec->control_data = wm9090->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;
 	}
 
-	ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
-	if (ret < 0)
-		return ret;
-	if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
-		dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
-		return -EINVAL;
-	}
-
-	ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
-	if (ret < 0)
-		return ret;
-
 	/* Configure some defaults; they will be written out when we
 	 * bring the bias up.
 	 */
@@ -624,16 +599,27 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
 	.suspend = 	wm9090_suspend,
 	.resume =	wm9090_resume,
 	.set_bias_level = wm9090_set_bias_level,
-	.reg_cache_size = (WM9090_MAX_REGISTER + 1),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = wm9090_reg_defaults,
-	.volatile_register = wm9090_volatile,
 };
 
+static const struct regmap_config wm9090_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+
+	.max_register = WM9090_MAX_REGISTER,
+	.volatile_reg = wm9090_volatile,
+	.readable_reg = wm9090_readable,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = wm9090_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(wm9090_reg_defaults),
+};
+
+
 static int wm9090_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct wm9090_priv *wm9090;
+	unsigned int reg;
 	int ret;
 
 	wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL);
@@ -642,6 +628,26 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
 		return -ENOMEM;
 	}
 
+	wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap);
+	if (IS_ERR(wm9090->regmap)) {
+		ret = PTR_ERR(wm9090->regmap);
+		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+		return ret;
+	}
+
+	ret = regmap_read(wm9090->regmap, WM9090_SOFTWARE_RESET, &reg);
+	if (ret < 0)
+		goto err;
+	if (reg != 0x9093) {
+		dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ret = regmap_write(wm9090->regmap, WM9090_SOFTWARE_RESET, 0);
+	if (ret < 0)
+		goto err;
+
 	if (i2c->dev.platform_data)
 		memcpy(&wm9090->pdata, i2c->dev.platform_data,
 		       sizeof(wm9090->pdata));
@@ -650,6 +656,15 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
 
 	ret =  snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm9090,  NULL, 0);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	regmap_exit(wm9090->regmap);
 	return ret;
 }
 
@@ -658,6 +673,7 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
 	struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
 
 	snd_soc_unregister_codec(&i2c->dev);
+	regmap_exit(wm9090->regmap);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 40c92ead85a34526e4ce5d49c09e43595b8ae6c1..cacc6a86b46f05b1fd5ea54b08fae3d4ad7eb4be 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -351,7 +351,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)
 	if (ret)
 		goto reset_err;
 
-	snd_soc_add_controls(codec, wm9705_snd_ac97_controls,
+	snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls,
 				ARRAY_SIZE(wm9705_snd_ac97_controls));
 
 	return 0;
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index b7b31f84c10b579432591d7d7caff670b1b6d9b7..b342ae50bcd6e294b5fe017f2bb7cdb77f4440ab 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -20,10 +20,9 @@
 #include <sound/ac97_codec.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/tlv.h>
 #include "wm9712.h"
 
-#define WM9712_VERSION "0.4"
-
 static unsigned int ac97_read(struct snd_soc_codec *codec,
 	unsigned int reg);
 static int ac97_write(struct snd_soc_codec *codec,
@@ -71,6 +70,9 @@ static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
 static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
 static const char *wm9712_diff_sel[] = {"Mic", "Line"};
 
+static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 2000, 0);
+
 static const struct soc_enum wm9712_enum[] = {
 SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
 SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
@@ -149,9 +151,9 @@ SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
 SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
 SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
 
-SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
-SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
-SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
+SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv),
 };
 
 /* We have to create a fake left and right HP mixers because
@@ -619,8 +621,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
 {
 	int ret = 0;
 
-	printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
-
 	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
 	if (ret < 0) {
 		printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
@@ -637,7 +637,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
 	ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
 
 	wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
+	snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls,
 				ARRAY_SIZE(wm9712_snd_ac97_controls));
 
 	return 0;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 2b8479bfcd93b822c48daa1f4e6797cf679d8cec..2d22cc70d5362d72c2372710597318e1cae61e6b 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1216,7 +1216,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
 	reg = ac97_read(codec, AC97_CD) & 0x7fff;
 	ac97_write(codec, AC97_CD, reg);
 
-	snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
+	snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls,
 				ARRAY_SIZE(wm9713_snd_ac97_controls));
 
 	return 0;
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 8a68cea4a3ee6af7860ae65f4ccab119b10cc425..f13f2886339ca4dee110746da3bbe838d99976c1 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -172,7 +172,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
 		break;
 	default:
 		WARN(1, "Unknown DCS readback method\n");
-		break;
+		return;
 	}
 
 	dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r);
@@ -207,7 +207,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
 
 	/* Save the callibrated offset if we're in class W mode and
 	 * therefore don't have any analogue signal mixed in. */
-	if (hubs->class_w)
+	if (hubs->class_w && !hubs->no_cache_class_w)
 		hubs->class_w_dcs = dcs_cfg;
 }
 
@@ -500,6 +500,36 @@ static int earpiece_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int lineout_event(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *control, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+	bool *flag;
+
+	switch (w->shift) {
+	case WM8993_LINEOUT1N_ENA_SHIFT:
+		flag = &hubs->lineout1n_ena;
+		break;
+	case WM8993_LINEOUT1P_ENA_SHIFT:
+		flag = &hubs->lineout1p_ena;
+		break;
+	case WM8993_LINEOUT2N_ENA_SHIFT:
+		flag = &hubs->lineout2n_ena;
+		break;
+	case WM8993_LINEOUT2P_ENA_SHIFT:
+		flag = &hubs->lineout2p_ena;
+		break;
+	default:
+		WARN(1, "Unknown line output");
+		return -EINVAL;
+	}
+
+	*flag = SND_SOC_DAPM_EVENT_ON(event);
+
+	return 0;
+}
+
 static const struct snd_kcontrol_new in1l_pga[] = {
 SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
 SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
@@ -613,8 +643,6 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
 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_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0),
-
 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
 		   in1l_pga, ARRAY_SIZE(in1l_pga)),
 SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
@@ -640,9 +668,8 @@ SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event, 
 		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0,
-		   NULL, 0,
-		   hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
+		       hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
 		   earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
@@ -656,10 +683,10 @@ 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,
-		 NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
+		     NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
+		     NULL, 0),
 
 SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
 		   line1_mix, ARRAY_SIZE(line1_mix)),
@@ -675,14 +702,18 @@ SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
 SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
 		   line2p_mix, ARRAY_SIZE(line2p_mix)),
 
-SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
-		 NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
-		 NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
-		 NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
-		 NULL, 0),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
+		       NULL, 0, lineout_event,
+		     SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
+		       NULL, 0, lineout_event,
+		       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
+		       NULL, 0, lineout_event,
+		       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
+		       NULL, 0, lineout_event,
+		       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
 SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
 SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
@@ -836,11 +867,9 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
 };
 
 static const struct snd_soc_dapm_route lineout1_se_routes[] = {
-	{ "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },
 	{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
 	{ "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
 
-	{ "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },
 	{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
 
 	{ "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
@@ -857,11 +886,9 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
 };
 
 static const struct snd_soc_dapm_route lineout2_se_routes[] = {
-	{ "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },
 	{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
 	{ "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
 
-	{ "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },
 	{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
 
 	{ "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
@@ -901,7 +928,7 @@ int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
 			    WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
 			    WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
 
-	snd_soc_add_controls(codec, analogue_snd_controls,
+	snd_soc_add_codec_controls(codec, analogue_snd_controls,
 			     ARRAY_SIZE(analogue_snd_controls));
 
 	snd_soc_dapm_new_controls(dapm, analogue_dapm_widgets,
@@ -949,6 +976,11 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
 				  int jd_scthr, int jd_thr, int micbias1_lvl,
 				  int micbias2_lvl)
 {
+	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+
+	hubs->lineout1_se = !lineout1_diff;
+	hubs->lineout2_se = !lineout2_diff;
+
 	if (!lineout1_diff)
 		snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
 				    WM8993_LINEOUT1_MODE,
@@ -958,11 +990,10 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
 				    WM8993_LINEOUT2_MODE,
 				    WM8993_LINEOUT2_MODE);
 
-	/* If the line outputs are differential then we aren't presenting
-	 * VMID as an output and can disable it.
-	 */
-	if (lineout1_diff && lineout2_diff)
-		codec->dapm.idle_bias_off = 1;
+	if (!lineout1_diff && !lineout2_diff)
+		snd_soc_update_bits(codec, WM8993_ANTIPOP1,
+				    WM8993_LINEOUT_VMID_BUF_ENA,
+				    WM8993_LINEOUT_VMID_BUF_ENA);
 
 	if (lineout1fb)
 		snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
@@ -984,6 +1015,69 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
 }
 EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
 
+void wm_hubs_vmid_ena(struct snd_soc_codec *codec)
+{
+	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+	int val = 0;
+
+	if (hubs->lineout1_se)
+		val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
+
+	if (hubs->lineout2_se)
+		val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
+
+	/* Enable the line outputs while we power up */
+	snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3, val, val);
+}
+EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena);
+
+void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+			    enum snd_soc_bias_level level)
+{
+	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+	int val;
+
+	switch (level) {
+	case SND_SOC_BIAS_STANDBY:
+		/* Clamp the inputs to VMID while we ramp to charge caps */
+		snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+				    WM8993_INPUTS_CLAMP, WM8993_INPUTS_CLAMP);
+		break;
+
+	case SND_SOC_BIAS_ON:
+		/* Turn off any unneded single ended outputs */
+		val = 0;
+
+		if (hubs->lineout1_se && hubs->lineout1n_ena)
+			val |= WM8993_LINEOUT1N_ENA;
+
+		if (hubs->lineout1_se && hubs->lineout1p_ena)
+			val |= WM8993_LINEOUT1P_ENA;
+
+		if (hubs->lineout2_se && hubs->lineout2n_ena)
+			val |= WM8993_LINEOUT2N_ENA;
+
+		if (hubs->lineout2_se && hubs->lineout2p_ena)
+			val |= WM8993_LINEOUT2P_ENA;
+
+		snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3,
+				    WM8993_LINEOUT1N_ENA |
+				    WM8993_LINEOUT1P_ENA |
+				    WM8993_LINEOUT2N_ENA |
+				    WM8993_LINEOUT2P_ENA,
+				    val);
+
+		/* Remove the input clamps */
+		snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+				    WM8993_INPUTS_CLAMP, 0);
+		break;
+
+	default:
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level);
+
 MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index c674c7a502a64e1d02889edfa839522686afdf9b..5705276f49438f396eb5252b8bb65514cdfb8498 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -30,9 +30,18 @@ struct wm_hubs_data {
 	int series_startup;
 	int no_series_update;
 
+	bool no_cache_class_w;
 	bool class_w;
 	u16 class_w_dcs;
 
+	bool lineout1_se;
+	bool lineout1n_ena;
+	bool lineout1p_ena;
+
+	bool lineout2_se;
+	bool lineout2n_ena;
+	bool lineout2p_ena;
+
 	bool dcs_done_irq;
 	struct completion dcs_done;
 };
@@ -46,5 +55,8 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
 					 int micbias1_lvl, int micbias2_lvl);
 
 extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
+extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec);
+extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+				   enum snd_soc_bias_level level);
 
 #endif
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index b26401f87b8509ea23eea61e1530f77eeb082377..97d77b298968fc714c4125fb48392afcd4bc60fe 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -826,7 +826,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
 	}
 }
 
-static u64 davinci_pcm_dmamask = 0xffffffff;
+static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32);
 
 static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
@@ -837,7 +837,7 @@ static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &davinci_pcm_dmamask;
 	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = 0xffffffff;
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
 	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
 		ret = davinci_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index 91a28de941094dd6b71067311bd0d8447beb2c14..88143db7e7537acd96eea026d91427a29983755d 100644
--- a/sound/soc/ep93xx/Kconfig
+++ b/sound/soc/ep93xx/Kconfig
@@ -1,6 +1,7 @@
 config SND_EP93XX_SOC
 	tristate "SoC Audio support for the Cirrus Logic EP93xx series"
 	depends on ARCH_EP93XX && SND_SOC
+	select SND_SOC_DMAENGINE_PCM
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the EP93xx I2S or AC97 interfaces.
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c
index bae5cbbbd2b2d28c817c954f25e6dfc08faed22c..e01cb02abd3a91e17cfc9b3e22ee1df563feb22b 100644
--- a/sound/soc/ep93xx/edb93xx.c
+++ b/sound/soc/ep93xx/edb93xx.c
@@ -85,9 +85,7 @@ static int __devinit edb93xx_probe(struct platform_device *pdev)
 	struct snd_soc_card *card = &snd_soc_edb93xx;
 	int ret;
 
-	ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
-				 EP93XX_SYSCON_I2SCLKDIV_ORIDE |
-				 EP93XX_SYSCON_I2SCLKDIV_SPOL);
+	ret = ep93xx_i2s_acquire();
 	if (ret)
 		return ret;
 
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index de83904498730dbf43447cdcc4ef42cd34a9d0d7..162dbb74f4cca6ce793f292fb1dacf7aeaddac97 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -23,6 +23,7 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include <mach/dma.h>
 #include <mach/hardware.h>
@@ -52,26 +53,6 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
 	.fifo_size		= 32,
 };
 
-struct ep93xx_runtime_data
-{
-	int				pointer_bytes;
-	int				periods;
-	int				period_bytes;
-	struct dma_chan			*dma_chan;
-	struct ep93xx_dma_data		dma_data;
-};
-
-static void ep93xx_pcm_dma_callback(void *data)
-{
-	struct snd_pcm_substream *substream = data;
-	struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
-
-	rtd->pointer_bytes += rtd->period_bytes;
-	rtd->pointer_bytes %= rtd->period_bytes * rtd->periods;
-
-	snd_pcm_period_elapsed(substream);
-}
-
 static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
 {
 	struct ep93xx_dma_data *data = filter_param;
@@ -86,98 +67,48 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
 
 static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
 {
-	struct snd_soc_pcm_runtime *soc_rtd = substream->private_data;
-	struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct ep93xx_pcm_dma_params *dma_params;
-	struct ep93xx_runtime_data *rtd;    
-	dma_cap_mask_t mask;
+	struct ep93xx_dma_data *dma_data;
 	int ret;
 
-	ret = snd_pcm_hw_constraint_integer(substream->runtime,
-					    SNDRV_PCM_HW_PARAM_PERIODS);
-	if (ret < 0)
-		return ret;
-
 	snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
 
-	rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
-	if (!rtd) 
+	dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
+	if (!dma_data)
 		return -ENOMEM;
 
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	dma_cap_set(DMA_CYCLIC, mask);
-
 	dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
-	rtd->dma_data.port = dma_params->dma_port;
-	rtd->dma_data.name = dma_params->name;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		rtd->dma_data.direction = DMA_MEM_TO_DEV;
-	else
-		rtd->dma_data.direction = DMA_DEV_TO_MEM;
-
-	rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter,
-					    &rtd->dma_data);
-	if (!rtd->dma_chan) {
-		kfree(rtd);
-		return -EINVAL;
-	}
-	
-	substream->runtime->private_data = rtd;
-	return 0;
-}
+	dma_data->port = dma_params->dma_port;
+	dma_data->name = dma_params->name;
+	dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
 
-static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
-{
-	struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
+	ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
+	if (ret) {
+		kfree(dma_data);
+		return ret;
+	}
 
-	dma_release_channel(rtd->dma_chan);
-	kfree(rtd);
-	return 0;
-}
+	snd_dmaengine_pcm_set_data(substream, dma_data);
 
-static int ep93xx_pcm_dma_submit(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct ep93xx_runtime_data *rtd = runtime->private_data;
-	struct dma_chan *chan = rtd->dma_chan;
-	struct dma_device *dma_dev = chan->device;
-	struct dma_async_tx_descriptor *desc;
-
-	rtd->pointer_bytes = 0;
-	desc = dma_dev->device_prep_dma_cyclic(chan, runtime->dma_addr,
-					       rtd->period_bytes * rtd->periods,
-					       rtd->period_bytes,
-					       rtd->dma_data.direction);
-	if (!desc)
-		return -EINVAL;
-
-	desc->callback = ep93xx_pcm_dma_callback;
-	desc->callback_param = substream;
-
-	dmaengine_submit(desc);
 	return 0;
 }
 
-static void ep93xx_pcm_dma_flush(struct snd_pcm_substream *substream)
+static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct ep93xx_runtime_data *rtd = runtime->private_data;
+	struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
 
-	dmaengine_terminate_all(rtd->dma_chan);
+	snd_dmaengine_pcm_close(substream);
+	kfree(dma_data);
+	return 0;
 }
 
 static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct ep93xx_runtime_data *rtd = runtime->private_data;
-
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
-	rtd->periods = params_periods(params);
-	rtd->period_bytes = params_period_bytes(params);
 	return 0;
 }
 
@@ -187,41 +118,6 @@ static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	int ret;
-
-	ret = 0;
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		ret = ep93xx_pcm_dma_submit(substream);
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		ep93xx_pcm_dma_flush(substream);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
-
-	/* FIXME: implement this with sub-period granularity */
-	return bytes_to_frames(runtime, rtd->pointer_bytes);
-}
-
 static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
 			   struct vm_area_struct *vma)
 {
@@ -239,8 +135,8 @@ static struct snd_pcm_ops ep93xx_pcm_ops = {
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= ep93xx_pcm_hw_params,
 	.hw_free	= ep93xx_pcm_hw_free,
-	.trigger	= ep93xx_pcm_trigger,
-	.pointer	= ep93xx_pcm_pointer,
+	.trigger	= snd_dmaengine_pcm_trigger,
+	.pointer	= snd_dmaengine_pcm_pointer,
 	.mmap		= ep93xx_pcm_mmap,
 };
 
@@ -281,7 +177,7 @@ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 	}
 }
 
-static u64 ep93xx_pcm_dmamask = 0xffffffff;
+static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32);
 
 static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
@@ -292,7 +188,7 @@ static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &ep93xx_pcm_dmamask;
 	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = 0xffffffff;
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
 	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
 		ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index ccae34a3f280dc08d8e33942389f46b27215ec87..a193cea3cf3cc73406a201db9e5aeb10b7772cc6 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -103,9 +103,7 @@ static int __devinit snappercl15_probe(struct platform_device *pdev)
 	struct snd_soc_card *card = &snd_soc_snappercl15;
 	int ret;
 
-	ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
-				 EP93XX_SYSCON_I2SCLKDIV_ORIDE |
-				 EP93XX_SYSCON_I2SCLKDIV_SPOL);
+	ret = ep93xx_i2s_acquire();
 	if (ret)
 		return ret;
 
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 4f59bbaba48f4fcb8ae70e0ced615f19ab71404e..96bb92dd174c0ae14c0b262ae4f55fd6df2d3f70 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -311,23 +311,23 @@ static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
 	 * should allocate a DMA buffer only for the streams that are valid.
 	 */
 
-	if (pcm->streams[0].substream) {
+	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
 		ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
 			fsl_dma_hardware.buffer_bytes_max,
-			&pcm->streams[0].substream->dma_buffer);
+			&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
 		if (ret) {
 			dev_err(card->dev, "can't alloc playback dma buffer\n");
 			return ret;
 		}
 	}
 
-	if (pcm->streams[1].substream) {
+	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
 		ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
 			fsl_dma_hardware.buffer_bytes_max,
-			&pcm->streams[1].substream->dma_buffer);
+			&pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
 		if (ret) {
 			dev_err(card->dev, "can't alloc capture dma buffer\n");
-			snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+			snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
 			return ret;
 		}
 	}
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 3e066966d8783f8c7e558c9c8677b64406c6b17b..2eb407fa3b4893e2a43c5adbf7ba7f3bcc1762a7 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -716,12 +716,12 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
 	}
 
 	/* Trigger the machine driver's probe function.  The platform driver
-	 * name of the machine driver is taken from the /model property of the
+	 * name of the machine driver is taken from /compatible property of the
 	 * device tree.  We also pass the address of the CPU DAI driver
 	 * structure.
 	 */
-	sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
-	/* Sometimes the model name has a "fsl," prefix, so we strip that. */
+	sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
+	/* Sometimes the compatible name has a "fsl," prefix, so we strip it. */
 	p = strrchr(sprop, ',');
 	if (p)
 		sprop = p + 1;
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index e7803d34c425a35a8be366ccd5b9324b8eb41cad..9a3f7c5ab68748c5c05916d831defac13e0e7edb 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -8,6 +8,7 @@
 
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/of_platform.h>
 
@@ -298,7 +299,7 @@ static struct snd_pcm_ops psc_dma_ops = {
 	.hw_params	= psc_dma_hw_params,
 };
 
-static u64 psc_dma_dmamask = 0xffffffff;
+static u64 psc_dma_dmamask = DMA_BIT_MASK(32);
 static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
@@ -314,18 +315,18 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &psc_dma_dmamask;
 	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = 0xffffffff;
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-	if (pcm->streams[0].substream) {
+	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
 		rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-				size, &pcm->streams[0].substream->dma_buffer);
+				size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
 		if (rc)
 			goto playback_alloc_err;
 	}
 
-	if (pcm->streams[1].substream) {
+	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
 		rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-				size, &pcm->streams[1].substream->dma_buffer);
+				size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
 		if (rc)
 			goto capture_alloc_err;
 	}
@@ -336,8 +337,8 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
 	return 0;
 
  capture_alloc_err:
-	if (pcm->streams[0].substream)
-		snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
+		snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
 
  playback_alloc_err:
 	dev_err(card->dev, "Cannot allocate buffer(s)\n");
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 0ea4a5a96e06533e53ae95e5bebd60cdc16e7832..afbabf427f27dcb72b01e9be5a96dc0c8540176e 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -245,7 +245,7 @@ static int get_parent_cell_index(struct device_node *np)
  * 'struct device'  It's ugly and hackish, but it works.
  *
  * The dev_name for such devices include the bus number and I2C address. For
- * example, "cs4270-codec.0-004f".
+ * example, "cs4270.0-004f".
  */
 static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 {
@@ -267,13 +267,13 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 	if (!i2c)
 		return -ENODEV;
 
-	snprintf(buf, len, "%s-codec.%u-%04x", temp, i2c->adapter->nr, addr);
+	snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
 
 	return 0;
 }
 
 static int get_dma_channel(struct device_node *ssi_np,
-			   const char *compatible,
+			   const char *name,
 			   struct snd_soc_dai_link *dai,
 			   unsigned int *dma_channel_id,
 			   unsigned int *dma_id)
@@ -283,7 +283,7 @@ static int get_dma_channel(struct device_node *ssi_np,
 	const u32 *iprop;
 	int ret;
 
-	dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+	dma_channel_np = get_node_by_phandle_name(ssi_np, name,
 						  "fsl,ssi-dma-channel");
 	if (!dma_channel_np)
 		return -EINVAL;
@@ -336,12 +336,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
 	const char *sprop;
 	const u32 *iprop;
 
-	/* We are only interested in SSIs with a codec phandle in them,
-	 * so let's make sure this SSI has one. The MPC8610 HPCD only
-	 * knows about the CS4270 codec, so reject anything else.
-	 */
-	codec_np = get_node_by_phandle_name(np, "codec-handle",
-					    "cirrus,cs4270");
+	/* Find the codec node for this SSI. */
+	codec_np = of_parse_phandle(np, "codec-handle", 0);
 	if (!codec_np) {
 		dev_err(dev, "invalid codec node\n");
 		return -EINVAL;
@@ -550,7 +546,7 @@ static struct platform_driver mpc8610_hpcd_driver = {
 	.probe = mpc8610_hpcd_probe,
 	.remove = __devexit_p(mpc8610_hpcd_remove),
 	.driver = {
-		/* The name must match the 'model' property in the device tree,
+		/* The name must match 'compatible' property in the device tree,
 		 * in lowercase letters.
 		 */
 		.name = "snd-soc-mpc8610hpcd",
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index a5d4e80a9cf441140d017c8a0228770761999661..46623405a2ce29ea00ae80080a4c88edc0a9e37b 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -276,7 +276,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 }
 
 static int get_dma_channel(struct device_node *ssi_np,
-			   const char *compatible,
+			   const char *name,
 			   struct snd_soc_dai_link *dai,
 			   unsigned int *dma_channel_id,
 			   unsigned int *dma_id)
@@ -286,7 +286,7 @@ static int get_dma_channel(struct device_node *ssi_np,
 	const u32 *iprop;
 	int ret;
 
-	dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+	dma_channel_np = get_node_by_phandle_name(ssi_np, name,
 						  "fsl,ssi-dma-channel");
 	if (!dma_channel_np)
 		return -EINVAL;
@@ -395,7 +395,8 @@ static int p1022_ds_probe(struct platform_device *pdev)
 	}
 
 	if (strcasecmp(sprop, "i2s-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_I2S;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 
@@ -412,31 +413,38 @@ static int p1022_ds_probe(struct platform_device *pdev)
 		}
 		mdata->clk_frequency = be32_to_cpup(iprop);
 	} else if (strcasecmp(sprop, "i2s-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_I2S;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "lj-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "lj-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "rj-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "rj-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "ac97-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_AC97;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "ac97-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_AC97;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else {
@@ -543,6 +551,11 @@ static struct platform_driver p1022_ds_driver = {
 	.probe = p1022_ds_probe,
 	.remove = __devexit_p(p1022_ds_remove),
 	.driver = {
+		/*
+		 * The name must match 'compatible' property in the device tree,
+		 * in lowercase letters.
+		 */
+		.name = "snd-soc-p1022ds",
 		.owner = THIS_MODULE,
 	},
 };
@@ -556,33 +569,6 @@ static int __init p1022_ds_init(void)
 {
 	struct device_node *guts_np;
 	struct resource res;
-	const char *sprop;
-
-	/*
-	 * 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");
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index 738391757f2ccb1a5aa6a8883de0ba127fedea68..810acaa0900955f0a24b3b99089356ec413a01e8 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -1,9 +1,6 @@
 menuconfig SND_IMX_SOC
 	tristate "SoC Audio for Freescale i.MX CPUs"
 	depends on ARCH_MXC
-	select SND_PCM
-	select FIQ
-	select SND_SOC_AC97_BUS
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the i.MX SSI interface.
@@ -11,10 +8,23 @@ menuconfig SND_IMX_SOC
 
 if SND_IMX_SOC
 
+config SND_SOC_IMX_SSI
+	tristate
+
+config SND_SOC_IMX_PCM
+	tristate
+
 config SND_MXC_SOC_FIQ
 	tristate
+	select FIQ
+	select SND_SOC_IMX_PCM
 
 config SND_MXC_SOC_MX2
+	select SND_SOC_DMAENGINE_PCM
+	tristate
+	select SND_SOC_IMX_PCM
+
+config SND_SOC_IMX_AUDMUX
 	tristate
 
 config SND_MXC_SOC_WM1133_EV1
@@ -22,6 +32,8 @@ config SND_MXC_SOC_WM1133_EV1
 	depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
 	select SND_SOC_WM8350
 	select SND_MXC_SOC_FIQ
+	select SND_SOC_IMX_AUDMUX
+	select SND_SOC_IMX_SSI
 	help
 	  Enable support for audio on the i.MX31ADS with the WM1133-EV1
 	  PMIC board with WM8835x fitted.
@@ -31,6 +43,8 @@ config SND_SOC_MX27VIS_AIC32X4
 	depends on MACH_IMX27_VISSTRIM_M10 && I2C
 	select SND_SOC_TLV320AIC32X4
 	select SND_MXC_SOC_MX2
+	select SND_SOC_IMX_AUDMUX
+	select SND_SOC_IMX_SSI
 	help
 	  Say Y if you want to add support for SoC audio on Visstrim SM10
 	  board with TLV320AIC32X4 codec.
@@ -38,8 +52,11 @@ config SND_SOC_MX27VIS_AIC32X4
 config SND_SOC_PHYCORE_AC97
 	tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
 	depends on MACH_PCM043 || MACH_PCA100
+	select SND_SOC_AC97_BUS
 	select SND_SOC_WM9712
 	select SND_MXC_SOC_FIQ
+	select SND_SOC_IMX_AUDMUX
+	select SND_SOC_IMX_SSI
 	help
 	  Say Y if you want to add support for SoC audio on Phytec phyCORE
 	  and phyCARD boards in AC97 mode
@@ -53,6 +70,8 @@ config SND_SOC_EUKREA_TLV320
 	depends on I2C
 	select SND_SOC_TLV320AIC23
 	select SND_MXC_SOC_FIQ
+	select SND_SOC_IMX_AUDMUX
+	select SND_SOC_IMX_SSI
 	help
 	  Enable I2S based access to the TLV320AIC23B codec attached
 	  to the SSI interface
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index d6d609ba7e24afa539e0cc9804caee1a43026379..f5db3e92d0d11e5527087932a03380aa93b3a9f5 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -1,11 +1,14 @@
 # i.MX Platform Support
-snd-soc-imx-objs := imx-ssi.o
-snd-soc-imx-fiq-objs := imx-pcm-fiq.o
-snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o
+snd-soc-imx-ssi-objs := imx-ssi.o
+snd-soc-imx-audmux-objs := imx-audmux.o
 
-obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
-obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o
-obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o
+obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
+obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
+
+obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
+snd-soc-imx-pcm-y := imx-pcm.o
+snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o
+snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c
index 1c1fdd10f73f6b39e39f01a318d3df3bc6ad74f5..7d4475cfdb242bf6da4a74393a45c7b80b053d33 100644
--- a/sound/soc/imx/eukrea-tlv320.c
+++ b/sound/soc/imx/eukrea-tlv320.c
@@ -26,6 +26,7 @@
 
 #include "../codecs/tlv320aic23.h"
 #include "imx-ssi.h"
+#include "imx-audmux.h"
 
 #define CODEC_CLOCK 12000000
 
@@ -97,12 +98,43 @@ static struct platform_device *eukrea_tlv320_snd_device;
 static int __init eukrea_tlv320_init(void)
 {
 	int ret;
-
-	if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd()
-		&& !machine_is_eukrea_cpuimx35sd()
-		&& !machine_is_eukrea_cpuimx51sd())
+	int int_port = 0, ext_port;
+
+	if (machine_is_eukrea_cpuimx27()) {
+		imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+			IMX_AUDMUX_V1_PCR_SYN |
+			IMX_AUDMUX_V1_PCR_TFSDIR |
+			IMX_AUDMUX_V1_PCR_TCLKDIR |
+			IMX_AUDMUX_V1_PCR_RFSDIR |
+			IMX_AUDMUX_V1_PCR_RCLKDIR |
+			IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
+			IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
+			IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4)
+		);
+		imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4,
+			IMX_AUDMUX_V1_PCR_SYN |
+			IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
+		);
+	} else if (machine_is_eukrea_cpuimx25sd() ||
+		   machine_is_eukrea_cpuimx35sd() ||
+		   machine_is_eukrea_cpuimx51sd()) {
+		ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3;
+		imx_audmux_v2_configure_port(int_port,
+			IMX_AUDMUX_V2_PTCR_SYN |
+			IMX_AUDMUX_V2_PTCR_TFSDIR |
+			IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
+			IMX_AUDMUX_V2_PTCR_TCLKDIR |
+			IMX_AUDMUX_V2_PTCR_TCSEL(ext_port),
+			IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)
+		);
+		imx_audmux_v2_configure_port(ext_port,
+			IMX_AUDMUX_V2_PTCR_SYN,
+			IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)
+		);
+	} else {
 		/* return happy. We might run on a totally different machine */
 		return 0;
+	}
 
 	eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!eukrea_tlv320_snd_device)
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/sound/soc/imx/imx-audmux.c
similarity index 52%
rename from arch/arm/plat-mxc/audmux-v2.c
rename to sound/soc/imx/imx-audmux.c
index 8cced35009bd6c1fcb3388772582a26e766c1f1b..a839494c5ea888b110e194db9dffeab31e7f1323 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/sound/soc/imx/imx-audmux.c
@@ -1,4 +1,6 @@
 /*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
  * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
  *
  * Initial development of this code was funded by
@@ -15,20 +17,25 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <mach/audmux.h>
-#include <mach/hardware.h>
+
+#include "imx-audmux.h"
+
+#define DRIVER_NAME "imx-audmux"
 
 static struct clk *audmux_clk;
 static void __iomem *audmux_base;
 
-#define MXC_AUDMUX_V2_PTCR(x)		((x) * 8)
-#define MXC_AUDMUX_V2_PDCR(x)		((x) * 8 + 4)
+#define IMX_AUDMUX_V2_PTCR(x)		((x) * 8)
+#define IMX_AUDMUX_V2_PDCR(x)		((x) * 8 + 4)
 
 #ifdef CONFIG_DEBUG_FS
 static struct dentry *audmux_debugfs_root;
@@ -75,8 +82,8 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 	if (audmux_clk)
 		clk_enable(audmux_clk);
 
-	ptcr = readl(audmux_base + MXC_AUDMUX_V2_PTCR(port));
-	pdcr = readl(audmux_base + MXC_AUDMUX_V2_PDCR(port));
+	ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port));
+	pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port));
 
 	if (audmux_clk)
 		clk_disable(audmux_clk);
@@ -84,7 +91,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 	ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
 		       pdcr, ptcr);
 
-	if (ptcr & MXC_AUDMUX_V2_PTCR_TFSDIR)
+	if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
 		ret += snprintf(buf + ret, PAGE_SIZE - ret,
 				"TxFS output from %s, ",
 				audmux_port_string((ptcr >> 27) & 0x7));
@@ -92,7 +99,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 		ret += snprintf(buf + ret, PAGE_SIZE - ret,
 				"TxFS input, ");
 
-	if (ptcr & MXC_AUDMUX_V2_PTCR_TCLKDIR)
+	if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
 		ret += snprintf(buf + ret, PAGE_SIZE - ret,
 				"TxClk output from %s",
 				audmux_port_string((ptcr >> 22) & 0x7));
@@ -102,11 +109,11 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 
 	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
-	if (ptcr & MXC_AUDMUX_V2_PTCR_SYN) {
+	if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
 		ret += snprintf(buf + ret, PAGE_SIZE - ret,
 				"Port is symmetric");
 	} else {
-		if (ptcr & MXC_AUDMUX_V2_PTCR_RFSDIR)
+		if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
 			ret += snprintf(buf + ret, PAGE_SIZE - ret,
 					"RxFS output from %s, ",
 					audmux_port_string((ptcr >> 17) & 0x7));
@@ -114,7 +121,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 			ret += snprintf(buf + ret, PAGE_SIZE - ret,
 					"RxFS input, ");
 
-		if (ptcr & MXC_AUDMUX_V2_PTCR_RCLKDIR)
+		if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
 			ret += snprintf(buf + ret, PAGE_SIZE - ret,
 					"RxClk output from %s",
 					audmux_port_string((ptcr >> 12) & 0x7));
@@ -140,7 +147,7 @@ static const struct file_operations audmux_debugfs_fops = {
 	.llseek = default_llseek,
 };
 
-static void audmux_debugfs_init(void)
+static void __init audmux_debugfs_init(void)
 {
 	int i;
 	char buf[20];
@@ -159,61 +166,149 @@ static void audmux_debugfs_init(void)
 				   i);
 	}
 }
+
+static void __devexit audmux_debugfs_remove(void)
+{
+	debugfs_remove_recursive(audmux_debugfs_root);
+}
 #else
 static inline void audmux_debugfs_init(void)
 {
 }
+
+static inline void audmux_debugfs_remove(void)
+{
+}
 #endif
 
-int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
+enum imx_audmux_type {
+	IMX21_AUDMUX,
+	IMX31_AUDMUX,
+} audmux_type;
+
+static struct platform_device_id imx_audmux_ids[] = {
+	{
+		.name = "imx21-audmux",
+		.driver_data = IMX21_AUDMUX,
+	}, {
+		.name = "imx31-audmux",
+		.driver_data = IMX31_AUDMUX,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, imx_audmux_ids);
+
+static const struct of_device_id imx_audmux_dt_ids[] = {
+	{ .compatible = "fsl,imx21-audmux", .data = &imx_audmux_ids[0], },
+	{ .compatible = "fsl,imx31-audmux", .data = &imx_audmux_ids[1], },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_audmux_dt_ids);
+
+static const uint8_t port_mapping[] = {
+	0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
+};
+
+int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
+{
+	if (audmux_type != IMX21_AUDMUX)
+		return -EINVAL;
+
+	if (!audmux_base)
+		return -ENOSYS;
+
+	if (port >= ARRAY_SIZE(port_mapping))
+		return -EINVAL;
+
+	writel(pcr, audmux_base + port_mapping[port]);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port);
+
+int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
 		unsigned int pdcr)
 {
+	if (audmux_type != IMX31_AUDMUX)
+		return -EINVAL;
+
 	if (!audmux_base)
 		return -ENOSYS;
 
 	if (audmux_clk)
 		clk_enable(audmux_clk);
 
-	writel(ptcr, audmux_base + MXC_AUDMUX_V2_PTCR(port));
-	writel(pdcr, audmux_base + MXC_AUDMUX_V2_PDCR(port));
+	writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port));
+	writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port));
 
 	if (audmux_clk)
 		clk_disable(audmux_clk);
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port);
+EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
 
-static int mxc_audmux_v2_init(void)
+static int __devinit imx_audmux_probe(struct platform_device *pdev)
 {
-	int ret;
-	if (cpu_is_mx51()) {
-		audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
-	} else if (cpu_is_mx31()) {
-		audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
-	} else if (cpu_is_mx35()) {
-		audmux_clk = clk_get(NULL, "audmux");
-		if (IS_ERR(audmux_clk)) {
-			ret = PTR_ERR(audmux_clk);
-			printk(KERN_ERR "%s: cannot get clock: %d\n", __func__,
-					ret);
-			return ret;
-		}
-		audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
-	} else if (cpu_is_mx25()) {
-		audmux_clk = clk_get(NULL, "audmux");
-		if (IS_ERR(audmux_clk)) {
-			ret = PTR_ERR(audmux_clk);
-			printk(KERN_ERR "%s: cannot get clock: %d\n", __func__,
-					ret);
-			return ret;
-		}
-		audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
+	struct resource *res;
+	const struct of_device_id *of_id =
+			of_match_device(imx_audmux_dt_ids, &pdev->dev);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	audmux_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!audmux_base)
+		return -EADDRNOTAVAIL;
+
+	audmux_clk = clk_get(&pdev->dev, "audmux");
+	if (IS_ERR(audmux_clk)) {
+		dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
+				PTR_ERR(audmux_clk));
+		audmux_clk = NULL;
 	}
 
-	audmux_debugfs_init();
+	if (of_id)
+		pdev->id_entry = of_id->data;
+	audmux_type = pdev->id_entry->driver_data;
+	if (audmux_type == IMX31_AUDMUX)
+		audmux_debugfs_init();
+
+	return 0;
+}
+
+static int __devexit imx_audmux_remove(struct platform_device *pdev)
+{
+	if (audmux_type == IMX31_AUDMUX)
+		audmux_debugfs_remove();
+	clk_put(audmux_clk);
 
 	return 0;
 }
 
-postcore_initcall(mxc_audmux_v2_init);
+static struct platform_driver imx_audmux_driver = {
+	.probe		= imx_audmux_probe,
+	.remove		= __devexit_p(imx_audmux_remove),
+	.id_table	= imx_audmux_ids,
+	.driver	= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = imx_audmux_dt_ids,
+	}
+};
+
+static int __init imx_audmux_init(void)
+{
+	return platform_driver_register(&imx_audmux_driver);
+}
+subsys_initcall(imx_audmux_init);
+
+static void __exit imx_audmux_exit(void)
+{
+	platform_driver_unregister(&imx_audmux_driver);
+}
+module_exit(imx_audmux_exit);
+
+MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/sound/soc/imx/imx-audmux.h b/sound/soc/imx/imx-audmux.h
new file mode 100644
index 0000000000000000000000000000000000000000..04ebbab8d7b98ab521e01f91b395506893510431
--- /dev/null
+++ b/sound/soc/imx/imx-audmux.h
@@ -0,0 +1,60 @@
+#ifndef __IMX_AUDMUX_H
+#define __IMX_AUDMUX_H
+
+#define MX27_AUDMUX_HPCR1_SSI0		0
+#define MX27_AUDMUX_HPCR2_SSI1		1
+#define MX27_AUDMUX_HPCR3_SSI_PINS_4	2
+#define MX27_AUDMUX_PPCR1_SSI_PINS_1	3
+#define MX27_AUDMUX_PPCR2_SSI_PINS_2	4
+#define MX27_AUDMUX_PPCR3_SSI_PINS_3	5
+
+#define MX31_AUDMUX_PORT1_SSI0		0
+#define MX31_AUDMUX_PORT2_SSI1		1
+#define MX31_AUDMUX_PORT3_SSI_PINS_3	2
+#define MX31_AUDMUX_PORT4_SSI_PINS_4	3
+#define MX31_AUDMUX_PORT5_SSI_PINS_5	4
+#define MX31_AUDMUX_PORT6_SSI_PINS_6	5
+
+#define MX51_AUDMUX_PORT1_SSI0		0
+#define MX51_AUDMUX_PORT2_SSI1		1
+#define MX51_AUDMUX_PORT3		2
+#define MX51_AUDMUX_PORT4		3
+#define MX51_AUDMUX_PORT5		4
+#define MX51_AUDMUX_PORT6		5
+#define MX51_AUDMUX_PORT7		6
+
+/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
+#define IMX_AUDMUX_V1_PCR_INMMASK(x)	((x) & 0xff)
+#define IMX_AUDMUX_V1_PCR_INMEN		(1 << 8)
+#define IMX_AUDMUX_V1_PCR_TXRXEN	(1 << 10)
+#define IMX_AUDMUX_V1_PCR_SYN		(1 << 12)
+#define IMX_AUDMUX_V1_PCR_RXDSEL(x)	(((x) & 0x7) << 13)
+#define IMX_AUDMUX_V1_PCR_RFCSEL(x)	(((x) & 0xf) << 20)
+#define IMX_AUDMUX_V1_PCR_RCLKDIR	(1 << 24)
+#define IMX_AUDMUX_V1_PCR_RFSDIR	(1 << 25)
+#define IMX_AUDMUX_V1_PCR_TFCSEL(x)	(((x) & 0xf) << 26)
+#define IMX_AUDMUX_V1_PCR_TCLKDIR	(1 << 30)
+#define IMX_AUDMUX_V1_PCR_TFSDIR	(1 << 31)
+
+/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
+#define IMX_AUDMUX_V2_PTCR_TFSDIR	(1 << 31)
+#define IMX_AUDMUX_V2_PTCR_TFSEL(x)	(((x) & 0xf) << 27)
+#define IMX_AUDMUX_V2_PTCR_TCLKDIR	(1 << 26)
+#define IMX_AUDMUX_V2_PTCR_TCSEL(x)	(((x) & 0xf) << 22)
+#define IMX_AUDMUX_V2_PTCR_RFSDIR	(1 << 21)
+#define IMX_AUDMUX_V2_PTCR_RFSEL(x)	(((x) & 0xf) << 17)
+#define IMX_AUDMUX_V2_PTCR_RCLKDIR	(1 << 16)
+#define IMX_AUDMUX_V2_PTCR_RCSEL(x)	(((x) & 0xf) << 12)
+#define IMX_AUDMUX_V2_PTCR_SYN		(1 << 11)
+
+#define IMX_AUDMUX_V2_PDCR_RXDSEL(x)	(((x) & 0x7) << 13)
+#define IMX_AUDMUX_V2_PDCR_TXRXEN	(1 << 12)
+#define IMX_AUDMUX_V2_PDCR_MODE(x)	(((x) & 0x3) << 8)
+#define IMX_AUDMUX_V2_PDCR_INMMASK(x)	((x) & 0xff)
+
+int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr);
+
+int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
+		unsigned int pdcr);
+
+#endif /* __IMX_AUDMUX_H */
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 5780c9b9d569cf78f82edb63104322c896b7c234..e43c8fa2788b34062b5601066b112c6c667e5c67 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -27,212 +27,54 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include <mach/dma.h>
 
-#include "imx-ssi.h"
-
-struct imx_pcm_runtime_data {
-	int period_bytes;
-	int periods;
-	int dma;
-	unsigned long offset;
-	unsigned long size;
-	void *buf;
-	int period_time;
-	struct dma_async_tx_descriptor *desc;
-	struct dma_chan *dma_chan;
-	struct imx_dma_data dma_data;
-};
-
-static void audio_dma_irq(void *data)
-{
-	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
-	iprtd->offset += iprtd->period_bytes;
-	iprtd->offset %= iprtd->period_bytes * iprtd->periods;
-
-	snd_pcm_period_elapsed(substream);
-}
+#include "imx-pcm.h"
 
 static bool filter(struct dma_chan *chan, void *param)
 {
-	struct imx_pcm_runtime_data *iprtd = param;
-
 	if (!imx_dma_is_general_purpose(chan))
 		return false;
 
-        chan->private = &iprtd->dma_data;
+	chan->private = param;
 
-        return true;
+	return true;
 }
 
-static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
+static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
 	struct imx_pcm_dma_params *dma_params;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
 	struct dma_slave_config slave_config;
-	dma_cap_mask_t mask;
-	enum dma_slave_buswidth buswidth;
 	int ret;
 
 	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
-	iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI;
-	iprtd->dma_data.priority = DMA_PRIO_HIGH;
-	iprtd->dma_data.dma_request = dma_params->dma;
-
-	/* Try to grab a DMA channel */
-	if (!iprtd->dma_chan) {
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
-		iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
-		if (!iprtd->dma_chan)
-			return -EINVAL;
-	}
-
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
-		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		break;
-	default:
-		return 0;
-	}
+	ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
+	if (ret)
+		return ret;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		slave_config.direction = DMA_MEM_TO_DEV;
 		slave_config.dst_addr = dma_params->dma_addr;
-		slave_config.dst_addr_width = buswidth;
 		slave_config.dst_maxburst = dma_params->burstsize;
 	} else {
-		slave_config.direction = DMA_DEV_TO_MEM;
 		slave_config.src_addr = dma_params->dma_addr;
-		slave_config.src_addr_width = buswidth;
 		slave_config.src_maxburst = dma_params->burstsize;
 	}
 
-	ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
+	ret = dmaengine_slave_config(chan, &slave_config);
 	if (ret)
 		return ret;
 
-	return 0;
-}
-
-static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-	unsigned long dma_addr;
-	struct dma_chan *chan;
-	struct imx_pcm_dma_params *dma_params;
-	int ret;
-
-	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-	ret = imx_ssi_dma_alloc(substream, params);
-	if (ret)
-		return ret;
-	chan = iprtd->dma_chan;
-
-	iprtd->size = params_buffer_bytes(params);
-	iprtd->periods = params_periods(params);
-	iprtd->period_bytes = params_period_bytes(params);
-	iprtd->offset = 0;
-	iprtd->period_time = HZ / (params_rate(params) /
-			params_period_size(params));
-
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
-	dma_addr = runtime->dma_addr;
-
-	iprtd->buf = (unsigned int *)substream->dma_buffer.area;
-
-	iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
-			iprtd->period_bytes * iprtd->periods,
-			iprtd->period_bytes,
-			substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-			DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
-	if (!iprtd->desc) {
-		dev_err(&chan->dev->device, "cannot prepare slave dma\n");
-		return -EINVAL;
-	}
-
-	iprtd->desc->callback = audio_dma_irq;
-	iprtd->desc->callback_param = substream;
-
-	return 0;
-}
-
-static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
-	if (iprtd->dma_chan) {
-		dma_release_channel(iprtd->dma_chan);
-		iprtd->dma_chan = NULL;
-	}
-
-	return 0;
-}
-
-static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct imx_pcm_dma_params *dma_params;
-
-	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
 	return 0;
 }
 
-static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		dmaengine_submit(iprtd->desc);
-
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		dmaengine_terminate_all(iprtd->dma_chan);
-
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
-	pr_debug("%s: %ld %ld\n", __func__, iprtd->offset,
-			bytes_to_frames(substream->runtime, iprtd->offset));
-
-	return bytes_to_frames(substream->runtime, iprtd->offset);
-}
-
 static struct snd_pcm_hardware snd_imx_hardware = {
 	.info = SNDRV_PCM_INFO_INTERLEAVED |
 		SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -254,33 +96,37 @@ static struct snd_pcm_hardware snd_imx_hardware = {
 
 static int snd_imx_open(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct imx_pcm_runtime_data *iprtd;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct imx_pcm_dma_params *dma_params;
+	struct imx_dma_data *dma_data;
 	int ret;
 
-	iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
-	if (iprtd == NULL)
-		return -ENOMEM;
-	runtime->private_data = iprtd;
+	snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
 
-	ret = snd_pcm_hw_constraint_integer(substream->runtime,
-			SNDRV_PCM_HW_PARAM_PERIODS);
-	if (ret < 0) {
-		kfree(iprtd);
-		return ret;
+	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+	dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
+	dma_data->peripheral_type = IMX_DMATYPE_SSI;
+	dma_data->priority = DMA_PRIO_HIGH;
+	dma_data->dma_request = dma_params->dma;
+
+	ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
+	if (ret) {
+		kfree(dma_data);
+		return 0;
 	}
 
-	snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+	snd_dmaengine_pcm_set_data(substream, dma_data);
 
 	return 0;
 }
 
 static int snd_imx_close(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
+	struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
 
-	kfree(iprtd);
+	snd_dmaengine_pcm_close(substream);
+	kfree(dma_data);
 
 	return 0;
 }
@@ -290,10 +136,8 @@ static struct snd_pcm_ops imx_pcm_ops = {
 	.close		= snd_imx_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= snd_imx_pcm_hw_params,
-	.hw_free	= snd_imx_pcm_hw_free,
-	.prepare	= snd_imx_pcm_prepare,
-	.trigger	= snd_imx_pcm_trigger,
-	.pointer	= snd_imx_pcm_pointer,
+	.trigger	= snd_dmaengine_pcm_trigger,
+	.pointer	= snd_dmaengine_pcm_pointer,
 	.mmap		= snd_imx_pcm_mmap,
 };
 
@@ -305,11 +149,6 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
 
 static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
 {
-	struct imx_ssi *ssi = platform_get_drvdata(pdev);
-
-	ssi->dma_params_tx.burstsize = 6;
-	ssi->dma_params_rx.burstsize = 4;
-
 	return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
 }
 
diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/imx/imx-pcm.c
new file mode 100644
index 0000000000000000000000000000000000000000..93dc360b17770cbb2833afdc6fc7eb5c70c5b19a
--- /dev/null
+++ b/sound/soc/imx/imx-pcm.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is based on code copyrighted by Freescale,
+ * Liam Girdwood, Javier Martin and probably others.
+ *
+ * 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 <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include "imx-pcm.h"
+
+int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
+		struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int ret;
+
+	ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
+		runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+
+	pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
+			runtime->dma_area,
+			runtime->dma_addr,
+			runtime->dma_bytes);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
+
+static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = IMX_SSI_DMABUF_SIZE;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+					   &buf->addr, GFP_KERNEL);
+	if (!buf->area)
+		return -ENOMEM;
+	buf->bytes = size;
+
+	return 0;
+}
+
+static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
+
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_pcm *pcm = rtd->pcm;
+	int ret = 0;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &imx_pcm_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+		ret = imx_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			goto out;
+	}
+
+	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+		ret = imx_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_CAPTURE);
+		if (ret)
+			goto out;
+	}
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(imx_pcm_new);
+
+void imx_pcm_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+	int stream;
+
+	for (stream = 0; stream < 2; stream++) {
+		substream = pcm->streams[stream].substream;
+		if (!substream)
+			continue;
+
+		buf = &substream->dma_buffer;
+		if (!buf->area)
+			continue;
+
+		dma_free_writecombine(pcm->card->dev, buf->bytes,
+				      buf->area, buf->addr);
+		buf->area = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(imx_pcm_free);
diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/imx/imx-pcm.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5f5c3acf34d30348342e4ebad2abc4cdf2e214e
--- /dev/null
+++ b/sound/soc/imx/imx-pcm.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is based on code copyrighted by Freescale,
+ * Liam Girdwood, Javier Martin and probably others.
+ *
+ * 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 _IMX_PCM_H
+#define _IMX_PCM_H
+
+/*
+ * Do not change this as the FIQ handler depends on this size
+ */
+#define IMX_SSI_DMABUF_SIZE	(64 * 1024)
+
+struct imx_pcm_dma_params {
+	int dma;
+	unsigned long dma_addr;
+	int burstsize;
+};
+
+int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
+		     struct vm_area_struct *vma);
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
+void imx_pcm_free(struct snd_pcm *pcm);
+
+#endif /* _IMX_PCM_H */
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index b6adbed6e506c1585503dff1355b46d4afbaa4cf..4f81ed456325c044e1dc9f0781de9b4dc4d46310 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -233,6 +233,23 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
 	return 0;
 }
 
+static int imx_ssi_startup(struct snd_pcm_substream *substream,
+			   struct snd_soc_dai *cpu_dai)
+{
+	struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+	struct imx_pcm_dma_params *dma_data;
+
+	/* Tx/Rx config */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dma_data = &ssi->dma_params_tx;
+	else
+		dma_data = &ssi->dma_params_rx;
+
+	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+
+	return 0;
+}
+
 /*
  * Should only be called when port is inactive (i.e. SSIEN = 0),
  * although can be called multiple times by upper layers.
@@ -242,23 +259,17 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_soc_dai *cpu_dai)
 {
 	struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
-	struct imx_pcm_dma_params *dma_data;
 	u32 reg, sccr;
 
 	/* Tx/Rx config */
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		reg = SSI_STCCR;
-		dma_data = &ssi->dma_params_tx;
-	} else {
+	else
 		reg = SSI_SRCCR;
-		dma_data = &ssi->dma_params_rx;
-	}
 
 	if (ssi->flags & IMX_SSI_SYN)
 		reg = SSI_STCCR;
 
-	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
-
 	sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
 
 	/* DAI data (word) size */
@@ -343,6 +354,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
 }
 
 static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
+	.startup	= imx_ssi_startup,
 	.hw_params	= imx_ssi_hw_params,
 	.set_fmt	= imx_ssi_set_dai_fmt,
 	.set_clkdiv	= imx_ssi_set_dai_clkdiv,
@@ -351,94 +363,6 @@ static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
 	.trigger	= imx_ssi_trigger,
 };
 
-int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
-		struct vm_area_struct *vma)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	int ret;
-
-	ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
-		runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
-
-	pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
-			runtime->dma_area,
-			runtime->dma_addr,
-			runtime->dma_bytes);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
-
-static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-	struct snd_dma_buffer *buf = &substream->dma_buffer;
-	size_t size = IMX_SSI_DMABUF_SIZE;
-
-	buf->dev.type = SNDRV_DMA_TYPE_DEV;
-	buf->dev.dev = pcm->card->dev;
-	buf->private_data = NULL;
-	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
-					   &buf->addr, GFP_KERNEL);
-	if (!buf->area)
-		return -ENOMEM;
-	buf->bytes = size;
-
-	return 0;
-}
-
-static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
-
-int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_card *card = rtd->card->snd_card;
-	struct snd_pcm *pcm = rtd->pcm;
-	int ret = 0;
-
-	if (!card->dev->dma_mask)
-		card->dev->dma_mask = &imx_pcm_dmamask;
-	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
-	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-		ret = imx_pcm_preallocate_dma_buffer(pcm,
-			SNDRV_PCM_STREAM_PLAYBACK);
-		if (ret)
-			goto out;
-	}
-
-	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-		ret = imx_pcm_preallocate_dma_buffer(pcm,
-			SNDRV_PCM_STREAM_CAPTURE);
-		if (ret)
-			goto out;
-	}
-
-out:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(imx_pcm_new);
-
-void imx_pcm_free(struct snd_pcm *pcm)
-{
-	struct snd_pcm_substream *substream;
-	struct snd_dma_buffer *buf;
-	int stream;
-
-	for (stream = 0; stream < 2; stream++) {
-		substream = pcm->streams[stream].substream;
-		if (!substream)
-			continue;
-
-		buf = &substream->dma_buffer;
-		if (!buf->area)
-			continue;
-
-		dma_free_writecombine(pcm->card->dev, buf->bytes,
-				      buf->area, buf->addr);
-		buf->area = NULL;
-	}
-}
-EXPORT_SYMBOL_GPL(imx_pcm_free);
-
 static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
 {
 	struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
@@ -656,7 +580,7 @@ static int imx_ssi_probe(struct platform_device *pdev)
 	ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0;
 	ssi->dma_params_tx.dma_addr = res->start + SSI_STX0;
 
-	ssi->dma_params_tx.burstsize = 4;
+	ssi->dma_params_tx.burstsize = 6;
 	ssi->dma_params_rx.burstsize = 4;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index 1072dfb53e4772f306c9dfcb38262e6c02c8d62c..5744e86ca8781537dce529523bb58a37b35e5293 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -187,12 +187,7 @@
 
 #include <linux/dmaengine.h>
 #include <mach/dma.h>
-
-struct imx_pcm_dma_params {
-	int dma;
-	unsigned long dma_addr;
-	int burstsize;
-};
+#include "imx-pcm.h"
 
 struct imx_ssi {
 	struct platform_device *ac97_dev;
@@ -218,13 +213,4 @@ struct imx_ssi {
 	struct platform_device *soc_platform_pdev_fiq;
 };
 
-int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
-int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
-void imx_pcm_free(struct snd_pcm *pcm);
-
-/*
- * Do not change this as the FIQ handler depends on this size
- */
-#define IMX_SSI_DMABUF_SIZE	(64 * 1024)
-
 #endif /* _IMX_SSI_H */
diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c
index 3c2eed9094d57b135594ae3cd444c498cf19459a..f6d04ad4bb39f99e83752e06c9e253d3c8bff8cd 100644
--- a/sound/soc/imx/mx27vis-aic32x4.c
+++ b/sound/soc/imx/mx27vis-aic32x4.c
@@ -25,15 +25,36 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/tlv.h>
 #include <asm/mach-types.h>
-#include <mach/audmux.h>
+#include <mach/iomux-mx27.h>
 
 #include "../codecs/tlv320aic32x4.h"
 #include "imx-ssi.h"
+#include "imx-audmux.h"
+
+#define MX27VIS_AMP_GAIN	0
+#define MX27VIS_AMP_MUTE	1
+
+#define MX27VIS_PIN_G0		(GPIO_PORTF + 9)
+#define MX27VIS_PIN_G1		(GPIO_PORTF + 8)
+#define MX27VIS_PIN_SDL		(GPIO_PORTE + 5)
+#define MX27VIS_PIN_SDR		(GPIO_PORTF + 7)
+
+static int mx27vis_amp_gain;
+static int mx27vis_amp_mute;
+
+static const int mx27vis_amp_pins[] = {
+	MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT,
+	MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT,
+	MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT,
+	MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT,
+};
 
 static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_pcm_hw_params *params)
@@ -74,6 +95,76 @@ static struct snd_soc_ops mx27vis_aic32x4_snd_ops = {
 	.hw_params	= mx27vis_aic32x4_hw_params,
 };
 
+static int mx27vis_amp_set(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	int value = ucontrol->value.integer.value[0];
+	unsigned int reg = mc->reg;
+	int max = mc->max;
+
+	if (value > max)
+		return -EINVAL;
+
+	switch (reg) {
+	case MX27VIS_AMP_GAIN:
+		gpio_set_value(MX27VIS_PIN_G0, value & 1);
+		gpio_set_value(MX27VIS_PIN_G1, value >> 1);
+		mx27vis_amp_gain = value;
+		break;
+	case MX27VIS_AMP_MUTE:
+		gpio_set_value(MX27VIS_PIN_SDL, value & 1);
+		gpio_set_value(MX27VIS_PIN_SDR, value >> 1);
+		mx27vis_amp_mute = value;
+		break;
+	}
+	return 0;
+}
+
+static int mx27vis_amp_get(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	unsigned int reg = mc->reg;
+
+	switch (reg) {
+	case MX27VIS_AMP_GAIN:
+		ucontrol->value.integer.value[0] = mx27vis_amp_gain;
+		break;
+	case MX27VIS_AMP_MUTE:
+		ucontrol->value.integer.value[0] = mx27vis_amp_mute;
+		break;
+	}
+	return 0;
+}
+
+/* From 6dB to 24dB in steps of 6dB */
+static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0);
+
+static const struct snd_kcontrol_new mx27vis_aic32x4_controls[] = {
+	SOC_DAPM_PIN_SWITCH("External Mic"),
+	SOC_SINGLE_EXT_TLV("LO Ext Boost", MX27VIS_AMP_GAIN, 0, 3, 0,
+		       mx27vis_amp_get, mx27vis_amp_set, mx27vis_amp_tlv),
+	SOC_DOUBLE_EXT("LO Ext Mute Switch", MX27VIS_AMP_MUTE, 0, 1, 1, 0,
+		       mx27vis_amp_get, mx27vis_amp_set),
+};
+
+static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("External Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
+	{"Mic Bias", NULL, "External Mic"},
+	{"IN1_R", NULL, "Mic Bias"},
+	{"IN2_R", NULL, "Mic Bias"},
+	{"IN3_R", NULL, "Mic Bias"},
+	{"IN1_L", NULL, "Mic Bias"},
+	{"IN2_L", NULL, "Mic Bias"},
+	{"IN3_L", NULL, "Mic Bias"},
+};
+
 static struct snd_soc_dai_link mx27vis_aic32x4_dai = {
 	.name		= "tlv320aic32x4",
 	.stream_name	= "TLV320AIC32X4",
@@ -89,50 +180,66 @@ static struct snd_soc_card mx27vis_aic32x4 = {
 	.owner		= THIS_MODULE,
 	.dai_link	= &mx27vis_aic32x4_dai,
 	.num_links	= 1,
+	.controls	= mx27vis_aic32x4_controls,
+	.num_controls	= ARRAY_SIZE(mx27vis_aic32x4_controls),
+	.dapm_widgets	= aic32x4_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets),
+	.dapm_routes	= aic32x4_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
 };
 
-static struct platform_device *mx27vis_aic32x4_snd_device;
-
-static int __init mx27vis_aic32x4_init(void)
+static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
 {
 	int ret;
 
-	mx27vis_aic32x4_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!mx27vis_aic32x4_snd_device)
-		return -ENOMEM;
-
-	platform_set_drvdata(mx27vis_aic32x4_snd_device, &mx27vis_aic32x4);
-	ret = platform_device_add(mx27vis_aic32x4_snd_device);
-
+	mx27vis_aic32x4.dev = &pdev->dev;
+	ret = snd_soc_register_card(&mx27vis_aic32x4);
 	if (ret) {
-		printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-		platform_device_put(mx27vis_aic32x4_snd_device);
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+			ret);
+		return ret;
 	}
 
 	/* Connect SSI0 as clock slave to SSI1 external pins */
-	mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
-			MXC_AUDMUX_V1_PCR_SYN |
-			MXC_AUDMUX_V1_PCR_TFSDIR |
-			MXC_AUDMUX_V1_PCR_TCLKDIR |
-			MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
-			MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1)
+	imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+			IMX_AUDMUX_V1_PCR_SYN |
+			IMX_AUDMUX_V1_PCR_TFSDIR |
+			IMX_AUDMUX_V1_PCR_TCLKDIR |
+			IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
+			IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1)
 	);
-	mxc_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1,
-			MXC_AUDMUX_V1_PCR_SYN |
-			MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
+	imx_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1,
+			IMX_AUDMUX_V1_PCR_SYN |
+			IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
 	);
 
+	ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins,
+			ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP");
+	if (ret)
+		printk(KERN_ERR "ASoC: unable to setup gpios\n");
+
 	return ret;
 }
 
-static void __exit mx27vis_aic32x4_exit(void)
+static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev)
 {
-	platform_device_unregister(mx27vis_aic32x4_snd_device);
+	snd_soc_unregister_card(&mx27vis_aic32x4);
+
+	return 0;
 }
 
-module_init(mx27vis_aic32x4_init);
-module_exit(mx27vis_aic32x4_exit);
+static struct platform_driver mx27vis_aic32x4_audio_driver = {
+	.driver = {
+		.name = "mx27vis",
+		.owner = THIS_MODULE,
+	},
+	.probe = mx27vis_aic32x4_probe,
+	.remove = __devexit_p(mx27vis_aic32x4_remove),
+};
+
+module_platform_driver(mx27vis_aic32x4_audio_driver);
 
 MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
 MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mx27vis");
diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c
index 6ac12111de6a4ad108be9a0d39684389cc8b3c49..f8da6dd115ed1c292d66fe0d7bee395ba849f2f7 100644
--- a/sound/soc/imx/phycore-ac97.c
+++ b/sound/soc/imx/phycore-ac97.c
@@ -19,6 +19,8 @@
 #include <sound/soc.h>
 #include <asm/mach-types.h>
 
+#include "imx-audmux.h"
+
 static struct snd_soc_card imx_phycore;
 
 static struct snd_soc_ops imx_phycore_hifi_ops = {
@@ -50,9 +52,32 @@ static int __init imx_phycore_init(void)
 {
 	int ret;
 
-	if (!machine_is_pcm043() && !machine_is_pca100())
+	if (machine_is_pca100()) {
+		imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+			IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */
+			IMX_AUDMUX_V1_PCR_TFCSEL(3) |
+			IMX_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */
+			IMX_AUDMUX_V1_PCR_RXDSEL(3));
+		imx_audmux_v1_configure_port(3,
+			IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */
+			IMX_AUDMUX_V1_PCR_TFCSEL(0) |
+			IMX_AUDMUX_V1_PCR_TFSDIR |
+			IMX_AUDMUX_V1_PCR_RXDSEL(0));
+	} else if (machine_is_pcm043()) {
+		imx_audmux_v2_configure_port(3,
+			IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
+			IMX_AUDMUX_V2_PTCR_TFSEL(0) |
+			IMX_AUDMUX_V2_PTCR_TFSDIR,
+			IMX_AUDMUX_V2_PDCR_RXDSEL(0));
+		imx_audmux_v2_configure_port(0,
+			IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
+			IMX_AUDMUX_V2_PTCR_TCSEL(3) |
+			IMX_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
+			IMX_AUDMUX_V2_PDCR_RXDSEL(3));
+	} else {
 		/* return happy. We might run on a totally different machine */
 		return 0;
+	}
 
 	imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1);
 	if (!imx_phycore_snd_ac97_device)
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c
index 37480c90e9979265e43171326d4bfab6310d25f5..fe54a69073e5cca05920b9d9b1864f916b261696 100644
--- a/sound/soc/imx/wm1133-ev1.c
+++ b/sound/soc/imx/wm1133-ev1.c
@@ -21,10 +21,9 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
-#include <mach/audmux.h>
-
 #include "imx-ssi.h"
 #include "../codecs/wm8350.h"
+#include "imx-audmux.h"
 
 /* There is a silicon mic on the board optionally connected via a solder pad
  * SP1.  Define this to enable it.
@@ -268,17 +267,17 @@ static int __init wm1133_ev1_audio_init(void)
 	unsigned int ptcr, pdcr;
 
 	/* SSI0 mastered by port 5 */
-	ptcr = MXC_AUDMUX_V2_PTCR_SYN |
-		MXC_AUDMUX_V2_PTCR_TFSDIR |
-		MXC_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
-		MXC_AUDMUX_V2_PTCR_TCLKDIR |
-		MXC_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
-	pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
-	mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
-
-	ptcr = MXC_AUDMUX_V2_PTCR_SYN;
-	pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
-	mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
+	ptcr = IMX_AUDMUX_V2_PTCR_SYN |
+		IMX_AUDMUX_V2_PTCR_TFSDIR |
+		IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
+		IMX_AUDMUX_V2_PTCR_TCLKDIR |
+		IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
+	pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
+	imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
+
+	ptcr = IMX_AUDMUX_V2_PTCR_SYN;
+	pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
+	imx_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
 
 	wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!wm1133_ev1_snd_device)
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
index 0097c3b13a1a31a1e1d48c99d71d62d3db72281d..e8aaff18d7cc4c9b18ed2d178cc69c2ddc77a6cb 100644
--- a/sound/soc/jz4740/qi_lb60.c
+++ b/sound/soc/jz4740/qi_lb60.c
@@ -91,56 +91,52 @@ static struct snd_soc_card qi_lb60 = {
 	.num_dapm_routes = ARRAY_SIZE(qi_lb60_routes),
 };
 
-static struct platform_device *qi_lb60_snd_device;
-
 static const struct gpio qi_lb60_gpios[] = {
 	{ QI_LB60_SND_GPIO, GPIOF_OUT_INIT_LOW, "SND" },
 	{ QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" },
 };
 
-static int __init qi_lb60_init(void)
+static int __devinit qi_lb60_probe(struct platform_device *pdev)
 {
+	struct snd_soc_card *card = &qi_lb60;
 	int ret;
 
-	qi_lb60_snd_device = platform_device_alloc("soc-audio", -1);
-
-	if (!qi_lb60_snd_device)
-		return -ENOMEM;
-
 	ret = gpio_request_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
-	if (ret) {
-		pr_err("qi_lb60 snd: Failed to request gpios: %d\n", ret);
-		goto err_device_put;
-	}
+	if (ret)
+		return ret;
 
-	platform_set_drvdata(qi_lb60_snd_device, &qi_lb60);
+	card->dev = &pdev->dev;
 
-	ret = platform_device_add(qi_lb60_snd_device);
+	ret = snd_soc_register_card(card);
 	if (ret) {
-		pr_err("qi_lb60 snd: Failed to add snd soc device: %d\n", ret);
-		goto err_unset_pdata;
+		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+			ret);
+		gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
 	}
-
-	 return 0;
-
-err_unset_pdata:
-	platform_set_drvdata(qi_lb60_snd_device, NULL);
-/*err_gpio_free_array:*/
-	gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
-err_device_put:
-	platform_device_put(qi_lb60_snd_device);
-
 	return ret;
 }
-module_init(qi_lb60_init);
 
-static void __exit qi_lb60_exit(void)
+static int __devexit qi_lb60_remove(struct platform_device *pdev)
 {
-	platform_device_unregister(qi_lb60_snd_device);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
 	gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
+	return 0;
 }
-module_exit(qi_lb60_exit);
+
+static struct platform_driver qi_lb60_driver = {
+	.driver		= {
+		.name	= "qi-lb60-audio",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= qi_lb60_probe,
+	.remove		= __devexit_p(qi_lb60_remove),
+};
+
+module_platform_driver(qi_lb60_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qi-lb60-audio");
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index d038540271285f90b8d093643fcfeb7de07cc8b6..b9f16598324c9b4b85373b6f55d785011c4d8b68 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -55,7 +55,7 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
 	.fifo_size		= 0,
 };
 
-static u64 kirkwood_dma_dmamask = 0xFFFFFFFFUL;
+static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
 
 static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
 {
@@ -324,7 +324,7 @@ static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &kirkwood_dma_dmamask;
 	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = 0xffffffff;
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
 	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
 		ret = kirkwood_dma_preallocate_dma_buffer(pcm,
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index 55d2ed3df30d6296dfaad03857e64ddde5505775..80bd59c33be4cb2d87297f5a47be17da014ea4e1 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -71,41 +71,41 @@ static struct snd_soc_card openrd_client = {
 	.num_links = ARRAY_SIZE(openrd_client_dai),
 };
 
-static struct platform_device *openrd_client_snd_device;
-
-static int __init openrd_client_init(void)
+static int __devinit openrd_probe(struct platform_device *pdev)
 {
+	struct snd_soc_card *card = &openrd_client;
 	int ret;
 
-	if (!machine_is_openrd_client() && !machine_is_openrd_ultimate())
-		return 0;
-
-	openrd_client_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!openrd_client_snd_device)
-		return -ENOMEM;
-
-	platform_set_drvdata(openrd_client_snd_device,
-			&openrd_client);
-
-	ret = platform_device_add(openrd_client_snd_device);
-	if (ret) {
-		printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
-		platform_device_put(openrd_client_snd_device);
-	}
+	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;
 }
 
-static void __exit openrd_client_exit(void)
+static int __devexit openrd_remove(struct platform_device *pdev)
 {
-	platform_device_unregister(openrd_client_snd_device);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+	return 0;
 }
 
-module_init(openrd_client_init);
-module_exit(openrd_client_exit);
+static struct platform_driver openrd_driver = {
+	.driver		= {
+		.name	= "openrd-client-audio",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= openrd_probe,
+	.remove		= __devexit_p(openrd_remove),
+};
+
+module_platform_driver(openrd_driver);
 
 /* Module information */
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:soc-audio");
+MODULE_ALIAS("platform:openrd-client-audio");
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index b47cc4e9b746a39dc7d91e86244d430c03b0fde3..f8983635f7efc21c3f69544c5329900745dbe2a4 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -80,7 +80,6 @@ static struct snd_soc_dai_link t5325_dai[] = {
 },
 };
 
-
 static struct snd_soc_card t5325 = {
 	.name = "t5325",
 	.owner = THIS_MODULE,
@@ -93,38 +92,40 @@ static struct snd_soc_card t5325 = {
 	.num_dapm_routes = ARRAY_SIZE(t5325_route),
 };
 
-static struct platform_device *t5325_snd_device;
-
-static int __init t5325_init(void)
+static int __devinit t5325_probe(struct platform_device *pdev)
 {
+	struct snd_soc_card *card = &t5325;
 	int ret;
 
-	if (!machine_is_t5325())
-		return 0;
-
-	t5325_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!t5325_snd_device)
-		return -ENOMEM;
-
-	platform_set_drvdata(t5325_snd_device,
-			&t5325);
-
-	ret = platform_device_add(t5325_snd_device);
-	if (ret) {
-		printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
-		platform_device_put(t5325_snd_device);
-	}
+	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;
 }
-module_init(t5325_init);
 
-static void __exit t5325_exit(void)
+static int __devexit t5325_remove(struct platform_device *pdev)
 {
-	platform_device_unregister(t5325_snd_device);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+	return 0;
 }
-module_exit(t5325_exit);
+
+static struct platform_driver t5325_driver = {
+	.driver		= {
+		.name	= "t5325-audio",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= t5325_probe,
+	.remove		= __devexit_p(t5325_remove),
+};
+
+module_platform_driver(t5325_driver);
 
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:t5325-audio");
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index 6f77eef0f13164b08507c15a1c554e9a1f35c9dc..2937e54da49ef596f52243cbce586a4cbba8712b 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -235,7 +235,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
 	snd_soc_dapm_enable_pin(dapm, "Headphones");
 	snd_soc_dapm_enable_pin(dapm, "Mic");
 
-	ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
+	ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls,
 				ARRAY_SIZE(mfld_snd_controls));
 	if (ret_val) {
 		pr_err("soc_add_controls failed %d", ret_val);
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
index e4ba8d5f25fa40eb3052ec02d3ae6aa93067a6d6..99a997f19bb9d9f76c5fa7a93af992d7dce6b0eb 100644
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -1,7 +1,7 @@
 menuconfig SND_MXS_SOC
 	tristate "SoC Audio for Freescale MXS CPUs"
 	depends on ARCH_MXS
-	select SND_PCM
+	select SND_SOC_DMAENGINE_PCM
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the MXS SAIF interface.
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index 105f42a394df6460e80899f22c567f3ac6192c7f..6ca1f46d84a49cc5d0cd5ab2b886975ec63879b9 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -34,10 +34,16 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include <mach/dma.h>
 #include "mxs-pcm.h"
 
+struct mxs_pcm_dma_data {
+	struct mxs_dma_data dma_data;
+	struct mxs_pcm_dma_params *dma_params;
+};
+
 static struct snd_pcm_hardware snd_mxs_hardware = {
 	.info			= SNDRV_PCM_INFO_MMAP |
 				  SNDRV_PCM_INFO_MMAP_VALID |
@@ -58,21 +64,10 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
 
 };
 
-static void audio_dma_irq(void *data)
-{
-	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
-	iprtd->offset += iprtd->period_bytes;
-	iprtd->offset %= iprtd->period_bytes * iprtd->periods;
-	snd_pcm_period_elapsed(substream);
-}
-
 static bool filter(struct dma_chan *chan, void *param)
 {
-	struct mxs_pcm_runtime_data *iprtd = param;
-	struct mxs_pcm_dma_params *dma_params = iprtd->dma_params;
+	struct mxs_pcm_dma_data *pcm_dma_data = param;
+	struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
 
 	if (!mxs_dma_is_apbx(chan))
 		return false;
@@ -80,150 +75,51 @@ static bool filter(struct dma_chan *chan, void *param)
 	if (chan->chan_id != dma_params->chan_num)
 		return false;
 
-	chan->private = &iprtd->dma_data;
+	chan->private = &pcm_dma_data->dma_data;
 
 	return true;
 }
 
-static int mxs_dma_alloc(struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-	dma_cap_mask_t mask;
-
-	iprtd->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	iprtd->dma_data.chan_irq = iprtd->dma_params->chan_irq;
-	iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
-	if (!iprtd->dma_chan)
-		return -EINVAL;
-
-	return 0;
-}
-
 static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-	unsigned long dma_addr;
-	struct dma_chan *chan;
-	int ret;
-
-	ret = mxs_dma_alloc(substream, params);
-	if (ret)
-		return ret;
-	chan = iprtd->dma_chan;
-
-	iprtd->size = params_buffer_bytes(params);
-	iprtd->periods = params_periods(params);
-	iprtd->period_bytes = params_period_bytes(params);
-	iprtd->offset = 0;
-	iprtd->period_time = HZ / (params_rate(params) /
-			params_period_size(params));
-
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
-	dma_addr = runtime->dma_addr;
-
-	iprtd->buf = substream->dma_buffer.area;
-
-	iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
-			iprtd->period_bytes * iprtd->periods,
-			iprtd->period_bytes,
-			substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-			DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
-	if (!iprtd->desc) {
-		dev_err(&chan->dev->device, "cannot prepare slave dma\n");
-		return -EINVAL;
-	}
-
-	iprtd->desc->callback = audio_dma_irq;
-	iprtd->desc->callback_param = substream;
-
-	return 0;
-}
-
-static int snd_mxs_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
-	if (iprtd->dma_chan) {
-		dma_release_channel(iprtd->dma_chan);
-		iprtd->dma_chan = NULL;
-	}
-
-	return 0;
-}
-
-static int snd_mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		dmaengine_submit(iprtd->desc);
-
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		dmaengine_terminate_all(iprtd->dma_chan);
-
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	return 0;
 }
 
-static snd_pcm_uframes_t snd_mxs_pcm_pointer(
-		struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
-	return bytes_to_frames(substream->runtime, iprtd->offset);
-}
-
 static int snd_mxs_open(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct mxs_pcm_runtime_data *iprtd;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct mxs_pcm_dma_data *pcm_dma_data;
 	int ret;
 
-	iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
-	if (iprtd == NULL)
+	pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
+	if (pcm_dma_data == NULL)
 		return -ENOMEM;
-	runtime->private_data = iprtd;
 
-	ret = snd_pcm_hw_constraint_integer(substream->runtime,
-			SNDRV_PCM_HW_PARAM_PERIODS);
-	if (ret < 0) {
-		kfree(iprtd);
+	pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+	pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
+
+	ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
+	if (ret) {
+		kfree(pcm_dma_data);
 		return ret;
 	}
 
 	snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
 
+	snd_dmaengine_pcm_set_data(substream, pcm_dma_data);
+
 	return 0;
 }
 
 static int snd_mxs_close(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
+	struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
 
-	kfree(iprtd);
+	snd_dmaengine_pcm_close(substream);
+	kfree(pcm_dma_data);
 
 	return 0;
 }
@@ -244,9 +140,8 @@ static struct snd_pcm_ops mxs_pcm_ops = {
 	.close		= snd_mxs_close,
 	.ioctl		= snd_pcm_lib_ioctl,
 	.hw_params	= snd_mxs_pcm_hw_params,
-	.hw_free	= snd_mxs_pcm_hw_free,
-	.trigger	= snd_mxs_pcm_trigger,
-	.pointer	= snd_mxs_pcm_pointer,
+	.trigger	= snd_dmaengine_pcm_trigger,
+	.pointer	= snd_dmaengine_pcm_pointer,
 	.mmap		= snd_mxs_pcm_mmap,
 };
 
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index f55ac4f7a76a4f11e42dd5782d5178afd2ebcd57..5f01a9124b3ddcdbbb103f871a6cdd8c8fe293c8 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -19,25 +19,9 @@
 #ifndef _MXS_PCM_H
 #define _MXS_PCM_H
 
-#include <mach/dma.h>
-
 struct mxs_pcm_dma_params {
 	int chan_irq;
 	int chan_num;
 };
 
-struct mxs_pcm_runtime_data {
-	int period_bytes;
-	int periods;
-	int dma;
-	unsigned long offset;
-	unsigned long size;
-	void *buf;
-	int period_time;
-	struct dma_async_tx_descriptor *desc;
-	struct dma_chan *dma_chan;
-	struct mxs_dma_data dma_data;
-	struct mxs_pcm_dma_params *dma_params;
-};
-
 #endif
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index f204dbac11d4e044edf12501b51238adcd069c28..12be05b16880aacc05d896d15564fd548686bb55 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -630,7 +630,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
 	if (pdev->id >= ARRAY_SIZE(mxs_saif))
 		return -EINVAL;
 
-	saif = kzalloc(sizeof(*saif), GFP_KERNEL);
+	saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL);
 	if (!saif)
 		return -ENOMEM;
 
@@ -655,29 +655,16 @@ static int mxs_saif_probe(struct platform_device *pdev)
 		ret = PTR_ERR(saif->clk);
 		dev_err(&pdev->dev, "Cannot get the clock: %d\n",
 			ret);
-		goto failed_clk;
+		return ret;
 	}
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!iores) {
-		ret = -ENODEV;
-		dev_err(&pdev->dev, "failed to get io resource: %d\n",
-			ret);
-		goto failed_get_resource;
-	}
 
-	if (!request_mem_region(iores->start, resource_size(iores),
-				"mxs-saif")) {
-		dev_err(&pdev->dev, "request_mem_region failed\n");
-		ret = -EBUSY;
-		goto failed_get_resource;
-	}
-
-	saif->base = ioremap(iores->start, resource_size(iores));
+	saif->base = devm_request_and_ioremap(&pdev->dev, iores);
 	if (!saif->base) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENODEV;
-		goto failed_ioremap;
+		goto failed_get_resource;
 	}
 
 	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -685,7 +672,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
 		ret = -ENODEV;
 		dev_err(&pdev->dev, "failed to get dma resource: %d\n",
 			ret);
-		goto failed_ioremap;
+		goto failed_get_resource;
 	}
 	saif->dma_param.chan_num = dmares->start;
 
@@ -694,14 +681,15 @@ static int mxs_saif_probe(struct platform_device *pdev)
 		ret = saif->irq;
 		dev_err(&pdev->dev, "failed to get irq resource: %d\n",
 			ret);
-		goto failed_get_irq1;
+		goto failed_get_resource;
 	}
 
 	saif->dev = &pdev->dev;
-	ret = request_irq(saif->irq, mxs_saif_irq, 0, "mxs-saif", saif);
+	ret = devm_request_irq(&pdev->dev, saif->irq, mxs_saif_irq, 0,
+			       "mxs-saif", saif);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to request irq\n");
-		goto failed_get_irq1;
+		goto failed_get_resource;
 	}
 
 	saif->dma_param.chan_irq = platform_get_irq(pdev, 1);
@@ -709,7 +697,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
 		ret = saif->dma_param.chan_irq;
 		dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
 			ret);
-		goto failed_get_irq2;
+		goto failed_get_resource;
 	}
 
 	platform_set_drvdata(pdev, saif);
@@ -717,7 +705,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
 	ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai);
 	if (ret) {
 		dev_err(&pdev->dev, "register DAI failed\n");
-		goto failed_register;
+		goto failed_get_resource;
 	}
 
 	saif->soc_platform_pdev = platform_device_alloc(
@@ -740,36 +728,19 @@ static int mxs_saif_probe(struct platform_device *pdev)
 	platform_device_put(saif->soc_platform_pdev);
 failed_pdev_alloc:
 	snd_soc_unregister_dai(&pdev->dev);
-failed_register:
-failed_get_irq2:
-	free_irq(saif->irq, saif);
-failed_get_irq1:
-	iounmap(saif->base);
-failed_ioremap:
-	release_mem_region(iores->start, resource_size(iores));
 failed_get_resource:
 	clk_put(saif->clk);
-failed_clk:
-	kfree(saif);
 
 	return ret;
 }
 
 static int __devexit mxs_saif_remove(struct platform_device *pdev)
 {
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct mxs_saif *saif = platform_get_drvdata(pdev);
 
 	platform_device_unregister(saif->soc_platform_pdev);
-
 	snd_soc_unregister_dai(&pdev->dev);
-
-	iounmap(saif->base);
-	release_mem_region(res->start, resource_size(res));
-	free_irq(saif->irq, saif);
-
 	clk_put(saif->clk);
-	kfree(saif);
 
 	return 0;
 }
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index fb1bf2581efb1b224aadbdd040ec83feab61f88d..e00dd0b1139ca17144048a41148fb2a656b2db7c 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -7,7 +7,6 @@ config SND_OMAP_SOC_DMIC
 
 config SND_OMAP_SOC_MCBSP
 	tristate
-	select OMAP_MCBSP
 
 config SND_OMAP_SOC_MCPDM
 	tristate
@@ -27,7 +26,6 @@ config SND_OMAP_SOC_N810
 config SND_OMAP_SOC_RX51
 	tristate "SoC Audio support for Nokia RX-51"
 	depends on SND_OMAP_SOC && MACH_NOKIA_RX51
-	select OMAP_MCBSP
 	select SND_OMAP_SOC_MCBSP
 	select SND_SOC_TLV320AIC3X
 	select SND_SOC_TPA6130A2
@@ -97,16 +95,19 @@ config SND_OMAP_SOC_SDP3430
 	  Say Y if you want to add support for SoC audio on Texas Instruments
 	  SDP3430.
 
-config SND_OMAP_SOC_SDP4430
-	tristate "SoC Audio support for Texas Instruments SDP4430"
-	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_4430SDP
+config SND_OMAP_SOC_OMAP_ABE_TWL6040
+	tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
+	depends on TWL4030_CORE && SND_OMAP_SOC && ARCH_OMAP4
 	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.
+	  Say Y if you want to add support for SoC audio on OMAP boards using
+	  ABE and twl6040 codec. This driver currently supports:
+	  - SDP4430/Blaze boards
+	  - PandaBoard (4430)
+	  - PandaBoardES (4460)
 
 config SND_OMAP_SOC_OMAP4_HDMI
 	tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 1fd723fb559d0e14b55bd4b2bf549f77a532ea5c..1d656bce01d48e599f18e7a1ec74f91cd1fcb573 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -1,7 +1,7 @@
 # OMAP Platform Support
 snd-soc-omap-objs := omap-pcm.o
 snd-soc-omap-dmic-objs := omap-dmic.o
-snd-soc-omap-mcbsp-objs := omap-mcbsp.o
+snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o
 snd-soc-omap-mcpdm-objs := omap-mcpdm.o
 snd-soc-omap-hdmi-objs := omap-hdmi.o
 
@@ -20,7 +20,7 @@ snd-soc-overo-objs := overo.o
 snd-soc-omap3evm-objs := omap3evm.o
 snd-soc-am3517evm-objs := am3517evm.o
 snd-soc-sdp3430-objs := sdp3430.o
-snd-soc-sdp4430-objs := sdp4430.o
+snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o
 snd-soc-omap3pandora-objs := omap3pandora.o
 snd-soc-omap3beagle-objs := omap3beagle.o
 snd-soc-zoom2-objs := zoom2.o
@@ -36,7 +36,7 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
 obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
 obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
-obj-$(CONFIG_SND_OMAP_SOC_SDP4430) += snd-soc-sdp4430.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
 obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index add4866d7e67bce97b95083f2d36ce4f06e4ccd9..009533ab8d1894054ed07c05ae140362d6738582 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -95,7 +95,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
 static struct snd_soc_dai_link am3517evm_dai = {
 	.name = "TLV320AIC23",
 	.stream_name = "AIC23",
-	.cpu_dai_name ="omap-mcbsp-dai.0",
+	.cpu_dai_name = "omap-mcbsp.1",
 	.codec_dai_name = "tlv320aic23-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "tlv320aic23-codec.2-001a",
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index a67f4370bc9f8fc0096e92abb8ba6cbc3771c220..49fe63ce51f7443d63d6f3f962cd72fb172dd221 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -570,7 +570,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_disable_pin(dapm, "AGCOUT");
 
 	/* Add virtual switch */
-	ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
+	ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls,
 					ARRAY_SIZE(ams_delta_audio_controls));
 	if (ret)
 		dev_warn(card->dev,
@@ -584,7 +584,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link ams_delta_dai_link = {
 	.name = "CX20442",
 	.stream_name = "CX20442",
-	.cpu_dai_name ="omap-mcbsp-dai.0",
+	.cpu_dai_name = "omap-mcbsp.1",
 	.codec_dai_name = "cx20442-voice",
 	.init = ams_delta_cx20442_init,
 	.platform_name = "omap-pcm-audio",
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
index ccae58a1339cc859e88a2346663fdb812ac3b9c0..e8357819175bd145b54fd20d41b525cfa6e207df 100644
--- a/sound/soc/omap/igep0020.c
+++ b/sound/soc/omap/igep0020.c
@@ -60,7 +60,7 @@ static struct snd_soc_ops igep2_ops = {
 static struct snd_soc_dai_link igep2_dai = {
 	.name = "TWL4030",
 	.stream_name = "TWL4030",
-	.cpu_dai_name = "omap-mcbsp-dai.1",
+	.cpu_dai_name = "omap-mcbsp.2",
 	.codec_dai_name = "twl4030-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "twl4030-codec",
diff --git a/arch/arm/plat-omap/mcbsp.c b/sound/soc/omap/mcbsp.c
similarity index 66%
rename from arch/arm/plat-omap/mcbsp.c
rename to sound/soc/omap/mcbsp.c
index 4b15cd7926d7e974a61111d141943ea22b7e697c..e5f44440d1b948fda1de18196bd1190b5aa707a4 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -1,9 +1,11 @@
 /*
- * linux/arch/arm/plat-omap/mcbsp.c
+ * sound/soc/omap/mcbsp.c
  *
  * Copyright (C) 2004 Nokia Corporation
  * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
  *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.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
@@ -24,13 +26,8 @@
 #include <linux/slab.h>
 
 #include <plat/mcbsp.h>
-#include <linux/pm_runtime.h>
 
-struct omap_mcbsp **mcbsp_ptr;
-int omap_mcbsp_count;
-
-#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
+#include "mcbsp.h"
 
 static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
@@ -80,10 +77,8 @@ static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 #define MCBSP_ST_WRITE(mcbsp, reg, val) \
 			omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val)
 
-static void omap_mcbsp_dump_reg(u8 id)
+static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id);
-
 	dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id);
 	dev_dbg(mcbsp->dev, "DRR2:  0x%04x\n",
 			MCBSP_READ(mcbsp, DRR2));
@@ -156,16 +151,9 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
  * You either call this function or set the McBSP registers
  * by yourself before calling omap_mcbsp_start().
  */
-void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
+void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
+		       const struct omap_mcbsp_reg_cfg *config)
 {
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
 	dev_dbg(mcbsp->dev, "Configuring McBSP%d  phys_base: 0x%08lx\n",
 			mcbsp->id, mcbsp->phys_base);
 
@@ -185,33 +173,10 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
 		MCBSP_WRITE(mcbsp, XCCR, config->xccr);
 		MCBSP_WRITE(mcbsp, RCCR, config->rccr);
 	}
+	/* Enable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
 }
-EXPORT_SYMBOL(omap_mcbsp_config);
-
-/**
- * omap_mcbsp_dma_params - returns the dma channel number
- * @id - mcbsp id
- * @stream - indicates the direction of data flow (rx or tx)
- *
- * Returns the dma channel number for the rx channel or tx channel
- * based on the value of @stream for the requested mcbsp given by @id
- */
-int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream)
-{
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	if (stream)
-		return mcbsp->dma_rx_sync;
-	else
-		return mcbsp->dma_tx_sync;
-}
-EXPORT_SYMBOL(omap_mcbsp_dma_ch_params);
 
 /**
  * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register
@@ -222,17 +187,11 @@ EXPORT_SYMBOL(omap_mcbsp_dma_ch_params);
  * to be used by DMA for transferring/receiving data based on the value of
  * @stream for the requested mcbsp given by @id
  */
-int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
+static int omap_mcbsp_dma_reg_params(struct omap_mcbsp *mcbsp,
+				     unsigned int stream)
 {
-	struct omap_mcbsp *mcbsp;
 	int data_reg;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
 	if (mcbsp->pdata->reg_size == 2) {
 		if (stream)
 			data_reg = OMAP_MCBSP_REG_DRR1;
@@ -247,7 +206,6 @@ int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
 
 	return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
 }
-EXPORT_SYMBOL(omap_mcbsp_dma_reg_params);
 
 static void omap_st_on(struct omap_mcbsp *mcbsp)
 {
@@ -316,20 +274,11 @@ static void omap_st_chgain(struct omap_mcbsp *mcbsp)
 		      ST_CH1GAIN(st_data->ch1gain));
 }
 
-int omap_st_set_chgain(unsigned int id, int channel, s16 chgain)
+int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain)
 {
-	struct omap_mcbsp *mcbsp;
-	struct omap_mcbsp_st_data *st_data;
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 	int ret = 0;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-	st_data = mcbsp->st_data;
-
 	if (!st_data)
 		return -ENOENT;
 
@@ -347,22 +296,12 @@ int omap_st_set_chgain(unsigned int id, int channel, s16 chgain)
 
 	return ret;
 }
-EXPORT_SYMBOL(omap_st_set_chgain);
 
-int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain)
+int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain)
 {
-	struct omap_mcbsp *mcbsp;
-	struct omap_mcbsp_st_data *st_data;
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 	int ret = 0;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-	st_data = mcbsp->st_data;
-
 	if (!st_data)
 		return -ENOENT;
 
@@ -377,13 +316,12 @@ int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain)
 
 	return ret;
 }
-EXPORT_SYMBOL(omap_st_get_chgain);
 
 static int omap_st_start(struct omap_mcbsp *mcbsp)
 {
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 
-	if (st_data && st_data->enabled && !st_data->running) {
+	if (st_data->enabled && !st_data->running) {
 		omap_st_fir_write(mcbsp, st_data->taps);
 		omap_st_chgain(mcbsp);
 
@@ -396,18 +334,9 @@ static int omap_st_start(struct omap_mcbsp *mcbsp)
 	return 0;
 }
 
-int omap_st_enable(unsigned int id)
+int omap_st_enable(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp;
-	struct omap_mcbsp_st_data *st_data;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-	st_data = mcbsp->st_data;
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 
 	if (!st_data)
 		return -ENODEV;
@@ -419,13 +348,12 @@ int omap_st_enable(unsigned int id)
 
 	return 0;
 }
-EXPORT_SYMBOL(omap_st_enable);
 
 static int omap_st_stop(struct omap_mcbsp *mcbsp)
 {
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 
-	if (st_data && st_data->running) {
+	if (st_data->running) {
 		if (!mcbsp->free) {
 			omap_st_off(mcbsp);
 			st_data->running = 0;
@@ -435,20 +363,11 @@ static int omap_st_stop(struct omap_mcbsp *mcbsp)
 	return 0;
 }
 
-int omap_st_disable(unsigned int id)
+int omap_st_disable(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp;
-	struct omap_mcbsp_st_data *st_data;
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 	int ret = 0;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-	st_data = mcbsp->st_data;
-
 	if (!st_data)
 		return -ENODEV;
 
@@ -459,136 +378,52 @@ int omap_st_disable(unsigned int id)
 
 	return ret;
 }
-EXPORT_SYMBOL(omap_st_disable);
 
-int omap_st_is_enabled(unsigned int id)
+int omap_st_is_enabled(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp;
-	struct omap_mcbsp_st_data *st_data;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-	st_data = mcbsp->st_data;
+	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 
 	if (!st_data)
 		return -ENODEV;
 
-
 	return st_data->enabled;
 }
-EXPORT_SYMBOL(omap_st_is_enabled);
 
 /*
  * omap_mcbsp_set_rx_threshold configures the transmit threshold in words.
  * The threshold parameter is 1 based, and it is converted (threshold - 1)
  * for the THRSH2 register.
  */
-void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
+void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
 {
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
 	if (mcbsp->pdata->buffer_size == 0)
 		return;
 
 	if (threshold && threshold <= mcbsp->max_tx_thres)
 		MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
 }
-EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold);
 
 /*
  * omap_mcbsp_set_rx_threshold configures the receive threshold in words.
  * The threshold parameter is 1 based, and it is converted (threshold - 1)
  * for the THRSH1 register.
  */
-void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
+void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
 {
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
 	if (mcbsp->pdata->buffer_size == 0)
 		return;
 
 	if (threshold && threshold <= mcbsp->max_rx_thres)
 		MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
 }
-EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold);
-
-/*
- * omap_mcbsp_get_max_tx_thres just return the current configured
- * maximum threshold for transmission
- */
-u16 omap_mcbsp_get_max_tx_threshold(unsigned int id)
-{
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	return mcbsp->max_tx_thres;
-}
-EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold);
-
-/*
- * omap_mcbsp_get_max_rx_thres just return the current configured
- * maximum threshold for reception
- */
-u16 omap_mcbsp_get_max_rx_threshold(unsigned int id)
-{
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	return mcbsp->max_rx_thres;
-}
-EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold);
-
-u16 omap_mcbsp_get_fifo_size(unsigned int id)
-{
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	return mcbsp->pdata->buffer_size;
-}
-EXPORT_SYMBOL(omap_mcbsp_get_fifo_size);
 
 /*
  * omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
  */
-u16 omap_mcbsp_get_tx_delay(unsigned int id)
+u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp;
 	u16 buffstat;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
 	if (mcbsp->pdata->buffer_size == 0)
 		return 0;
 
@@ -598,22 +433,15 @@ u16 omap_mcbsp_get_tx_delay(unsigned int id)
 	/* Number of slots are different in McBSP ports */
 	return mcbsp->pdata->buffer_size - buffstat;
 }
-EXPORT_SYMBOL(omap_mcbsp_get_tx_delay);
 
 /*
  * omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
  * to reach the threshold value (when the DMA will be triggered to read it)
  */
-u16 omap_mcbsp_get_rx_delay(unsigned int id)
+u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp;
 	u16 buffstat, threshold;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
 	if (mcbsp->pdata->buffer_size == 0)
 		return 0;
 
@@ -628,41 +456,12 @@ u16 omap_mcbsp_get_rx_delay(unsigned int id)
 	else
 		return threshold - buffstat;
 }
-EXPORT_SYMBOL(omap_mcbsp_get_rx_delay);
-
-/*
- * omap_mcbsp_get_dma_op_mode just return the current configured
- * operating mode for the mcbsp channel
- */
-int omap_mcbsp_get_dma_op_mode(unsigned int id)
-{
-	struct omap_mcbsp *mcbsp;
-	int dma_op_mode;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	dma_op_mode = mcbsp->dma_op_mode;
-
-	return dma_op_mode;
-}
-EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
 
-int omap_mcbsp_request(unsigned int id)
+int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp;
 	void *reg_cache;
 	int err;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
 	reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
 	if (!reg_cache) {
 		return -ENOMEM;
@@ -681,13 +480,7 @@ int omap_mcbsp_request(unsigned int id)
 	spin_unlock(&mcbsp->lock);
 
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
-		mcbsp->pdata->ops->request(id);
-
-	pm_runtime_get_sync(mcbsp->dev);
-
-	/* Enable wakeup behavior */
-	if (mcbsp->pdata->has_wakeup)
-		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
+		mcbsp->pdata->ops->request(mcbsp->id - 1);
 
 	/*
 	 * Make sure that transmitter, receiver and sample-rate generator are
@@ -722,14 +515,12 @@ int omap_mcbsp_request(unsigned int id)
 	free_irq(mcbsp->tx_irq, (void *)mcbsp);
 err_clk_disable:
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
-		mcbsp->pdata->ops->free(id);
+		mcbsp->pdata->ops->free(mcbsp->id - 1);
 
 	/* Disable wakeup behavior */
 	if (mcbsp->pdata->has_wakeup)
 		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
-	pm_runtime_put_sync(mcbsp->dev);
-
 	spin_lock(&mcbsp->lock);
 	mcbsp->free = true;
 	mcbsp->reg_cache = NULL;
@@ -739,34 +530,34 @@ int omap_mcbsp_request(unsigned int id)
 
 	return err;
 }
-EXPORT_SYMBOL(omap_mcbsp_request);
 
-void omap_mcbsp_free(unsigned int id)
+void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp;
 	void *reg_cache;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
-		mcbsp->pdata->ops->free(id);
+		mcbsp->pdata->ops->free(mcbsp->id - 1);
 
 	/* Disable wakeup behavior */
 	if (mcbsp->pdata->has_wakeup)
 		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
-	pm_runtime_put_sync(mcbsp->dev);
-
 	if (mcbsp->rx_irq)
 		free_irq(mcbsp->rx_irq, (void *)mcbsp);
 	free_irq(mcbsp->tx_irq, (void *)mcbsp);
 
 	reg_cache = mcbsp->reg_cache;
 
+	/*
+	 * Select CLKS source from internal source unconditionally before
+	 * marking the McBSP port as free.
+	 * If the external clock source via MCBSP_CLKS pin has been selected the
+	 * system will refuse to enter idle if the CLKS pin source is not reset
+	 * back to internal source.
+	 */
+	if (!cpu_class_is_omap1())
+		omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC);
+
 	spin_lock(&mcbsp->lock);
 	if (mcbsp->free)
 		dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
@@ -778,25 +569,17 @@ void omap_mcbsp_free(unsigned int id)
 	if (reg_cache)
 		kfree(reg_cache);
 }
-EXPORT_SYMBOL(omap_mcbsp_free);
 
 /*
  * Here we start the McBSP, by enabling transmitter, receiver or both.
  * If no transmitter or receiver is active prior calling, then sample-rate
  * generator and frame sync are started.
  */
-void omap_mcbsp_start(unsigned int id, int tx, int rx)
+void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx)
 {
-	struct omap_mcbsp *mcbsp;
 	int enable_srg = 0;
 	u16 w;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
 	if (mcbsp->st_data)
 		omap_st_start(mcbsp);
 
@@ -846,23 +629,14 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
 	}
 
 	/* Dump McBSP Regs */
-	omap_mcbsp_dump_reg(id);
+	omap_mcbsp_dump_reg(mcbsp);
 }
-EXPORT_SYMBOL(omap_mcbsp_start);
 
-void omap_mcbsp_stop(unsigned int id, int tx, int rx)
+void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx)
 {
-	struct omap_mcbsp *mcbsp;
 	int idle;
 	u16 w;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-
 	/* Reset transmitter */
 	tx &= 1;
 	if (mcbsp->pdata->has_ccr) {
@@ -895,19 +669,11 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
 	if (mcbsp->st_data)
 		omap_st_stop(mcbsp);
 }
-EXPORT_SYMBOL(omap_mcbsp_stop);
 
-int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
 {
-	struct omap_mcbsp *mcbsp;
 	const char *src;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
-		return -EINVAL;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
 	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
 		src = "clks_ext";
 	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
@@ -920,43 +686,37 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 	else
 		return -EINVAL;
 }
-EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
-void omap2_mcbsp1_mux_clkr_src(u8 mux)
+int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux)
 {
-	struct omap_mcbsp *mcbsp;
-	const char *src;
-
-	if (mux == CLKR_SRC_CLKR)
-		src = "clkr";
-	else if (mux == CLKR_SRC_CLKX)
-		src = "clkx";
-	else
-		return;
+	const char *signal, *src;
 
-	mcbsp = id_to_mcbsp_ptr(0);
 	if (mcbsp->pdata->mux_signal)
-		mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src);
-}
-EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
-
-void omap2_mcbsp1_mux_fsr_src(u8 mux)
-{
-	struct omap_mcbsp *mcbsp;
-	const char *src;
+		return -EINVAL;
 
-	if (mux == FSR_SRC_FSR)
+	switch (mux) {
+	case CLKR_SRC_CLKR:
+		signal = "clkr";
+		src = "clkr";
+		break;
+	case CLKR_SRC_CLKX:
+		signal = "clkr";
+		src = "clkx";
+		break;
+	case FSR_SRC_FSR:
+		signal = "fsr";
 		src = "fsr";
-	else if (mux == FSR_SRC_FSX)
+		break;
+	case FSR_SRC_FSX:
+		signal = "fsr";
 		src = "fsx";
-	else
-		return;
+		break;
+	default:
+		return -EINVAL;
+	}
 
-	mcbsp = id_to_mcbsp_ptr(0);
-	if (mcbsp->pdata->mux_signal)
-		mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src);
+	return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src);
 }
-EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
 #define max_thres(m)			(mcbsp->pdata->buffer_size)
 #define valid_threshold(m, val)		((val) <= max_thres(m))
@@ -1132,97 +892,56 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
 	struct omap_mcbsp_st_data *st_data;
 	int err;
 
-	st_data = kzalloc(sizeof(*mcbsp->st_data), GFP_KERNEL);
-	if (!st_data) {
-		err = -ENOMEM;
-		goto err1;
-	}
+	st_data = devm_kzalloc(mcbsp->dev, sizeof(*mcbsp->st_data), GFP_KERNEL);
+	if (!st_data)
+		return -ENOMEM;
 
-	st_data->io_base_st = ioremap(res->start, resource_size(res));
-	if (!st_data->io_base_st) {
-		err = -ENOMEM;
-		goto err2;
-	}
+	st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start,
+					   resource_size(res));
+	if (!st_data->io_base_st)
+		return -ENOMEM;
 
 	err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group);
 	if (err)
-		goto err3;
+		return err;
 
 	mcbsp->st_data = st_data;
 	return 0;
-
-err3:
-	iounmap(st_data->io_base_st);
-err2:
-	kfree(st_data);
-err1:
-	return err;
-
-}
-
-static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp)
-{
-	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
-
-	sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
-	iounmap(st_data->io_base_st);
-	kfree(st_data);
 }
 
 /*
  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
  * 730 has only 2 McBSP, and both of them are MPU peripherals.
  */
-static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
+int __devinit omap_mcbsp_init(struct platform_device *pdev)
 {
-	struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
-	struct omap_mcbsp *mcbsp;
-	int id = pdev->id - 1;
+	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
 	struct resource *res;
 	int ret = 0;
 
-	if (!pdata) {
-		dev_err(&pdev->dev, "McBSP device initialized without"
-				"platform data\n");
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id);
-
-	if (id >= omap_mcbsp_count) {
-		dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id);
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	mcbsp = kzalloc(sizeof(struct omap_mcbsp), GFP_KERNEL);
-	if (!mcbsp) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-
 	spin_lock_init(&mcbsp->lock);
-	mcbsp->id = id + 1;
 	mcbsp->free = true;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
 	if (!res) {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 		if (!res) {
-			dev_err(&pdev->dev, "%s:mcbsp%d has invalid memory"
-					"resource\n", __func__, pdev->id);
-			ret = -ENOMEM;
-			goto exit;
+			dev_err(mcbsp->dev, "invalid memory resource\n");
+			return -ENOMEM;
 		}
 	}
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				     dev_name(&pdev->dev))) {
+		dev_err(mcbsp->dev, "memory region already claimed\n");
+		return -ENODEV;
+	}
+
 	mcbsp->phys_base = res->start;
 	mcbsp->reg_cache_size = resource_size(res);
-	mcbsp->io_base = ioremap(res->start, resource_size(res));
-	if (!mcbsp->io_base) {
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
+	mcbsp->io_base = devm_ioremap(&pdev->dev, res->start,
+				      resource_size(res));
+	if (!mcbsp->io_base)
+		return -ENOMEM;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
 	if (!res)
@@ -1234,40 +953,38 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 	mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
 
 	/* From OMAP4 there will be a single irq line */
-	if (mcbsp->tx_irq == -ENXIO)
+	if (mcbsp->tx_irq == -ENXIO) {
 		mcbsp->tx_irq = platform_get_irq(pdev, 0);
+		mcbsp->rx_irq = 0;
+	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
 	if (!res) {
-		dev_err(&pdev->dev, "%s:mcbsp%d has invalid rx DMA channel\n",
-					__func__, pdev->id);
-		ret = -ENODEV;
-		goto err_res;
+		dev_err(&pdev->dev, "invalid rx DMA channel\n");
+		return -ENODEV;
 	}
-	mcbsp->dma_rx_sync = res->start;
+	/* RX DMA request number, and port address configuration */
+	mcbsp->dma_data[1].name = "Audio Capture";
+	mcbsp->dma_data[1].dma_req = res->start;
+	mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
 	if (!res) {
-		dev_err(&pdev->dev, "%s:mcbsp%d has invalid tx DMA channel\n",
-					__func__, pdev->id);
-		ret = -ENODEV;
-		goto err_res;
+		dev_err(&pdev->dev, "invalid tx DMA channel\n");
+		return -ENODEV;
 	}
-	mcbsp->dma_tx_sync = res->start;
+	/* TX DMA request number, and port address configuration */
+	mcbsp->dma_data[0].name = "Audio Playback";
+	mcbsp->dma_data[0].dma_req = res->start;
+	mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0);
 
 	mcbsp->fclk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(mcbsp->fclk)) {
 		ret = PTR_ERR(mcbsp->fclk);
-		dev_err(&pdev->dev, "unable to get fck: %d\n", ret);
-		goto err_res;
+		dev_err(mcbsp->dev, "unable to get fck: %d\n", ret);
+		return ret;
 	}
 
-	mcbsp->pdata = pdata;
-	mcbsp->dev = &pdev->dev;
-	mcbsp_ptr[id] = mcbsp;
-	platform_set_drvdata(pdev, mcbsp);
-	pm_runtime_enable(mcbsp->dev);
-
 	mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
 	if (mcbsp->pdata->buffer_size) {
 		/*
@@ -1307,55 +1024,17 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 
 err_st:
 	if (mcbsp->pdata->buffer_size)
-		sysfs_remove_group(&mcbsp->dev->kobj,
-				   &additional_attr_group);
+		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
 err_thres:
 	clk_put(mcbsp->fclk);
-err_res:
-	iounmap(mcbsp->io_base);
-err_ioremap:
-	kfree(mcbsp);
-exit:
 	return ret;
 }
 
-static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
+void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
-
-	platform_set_drvdata(pdev, NULL);
-	if (mcbsp) {
-
-		if (mcbsp->pdata && mcbsp->pdata->ops &&
-				mcbsp->pdata->ops->free)
-			mcbsp->pdata->ops->free(mcbsp->id);
-
-		if (mcbsp->pdata->buffer_size)
-			sysfs_remove_group(&mcbsp->dev->kobj,
-					   &additional_attr_group);
-
-		if (mcbsp->st_data)
-			omap_st_remove(mcbsp);
-
-		clk_put(mcbsp->fclk);
-
-		iounmap(mcbsp->io_base);
-		kfree(mcbsp);
-	}
-
-	return 0;
-}
-
-static struct platform_driver omap_mcbsp_driver = {
-	.probe		= omap_mcbsp_probe,
-	.remove		= __devexit_p(omap_mcbsp_remove),
-	.driver		= {
-		.name	= "omap-mcbsp",
-	},
-};
+	if (mcbsp->pdata->buffer_size)
+		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
 
-int __init omap_mcbsp_init(void)
-{
-	/* Register the McBSP driver */
-	return platform_driver_register(&omap_mcbsp_driver);
+	if (mcbsp->st_data)
+		sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
 }
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
new file mode 100644
index 0000000000000000000000000000000000000000..a944fcc9073c619f82667c7c5a2bd0a8861f4f3f
--- /dev/null
+++ b/sound/soc/omap/mcbsp.h
@@ -0,0 +1,346 @@
+/*
+ * sound/soc/omap/mcbsp.h
+ *
+ * OMAP Multi-Channel Buffered Serial Port
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __ASOC_MCBSP_H
+#define __ASOC_MCBSP_H
+
+#include "omap-pcm.h"
+
+/* McBSP register numbers. Register address offset = num * reg_step */
+enum {
+	/* Common registers */
+	OMAP_MCBSP_REG_SPCR2 = 4,
+	OMAP_MCBSP_REG_SPCR1,
+	OMAP_MCBSP_REG_RCR2,
+	OMAP_MCBSP_REG_RCR1,
+	OMAP_MCBSP_REG_XCR2,
+	OMAP_MCBSP_REG_XCR1,
+	OMAP_MCBSP_REG_SRGR2,
+	OMAP_MCBSP_REG_SRGR1,
+	OMAP_MCBSP_REG_MCR2,
+	OMAP_MCBSP_REG_MCR1,
+	OMAP_MCBSP_REG_RCERA,
+	OMAP_MCBSP_REG_RCERB,
+	OMAP_MCBSP_REG_XCERA,
+	OMAP_MCBSP_REG_XCERB,
+	OMAP_MCBSP_REG_PCR0,
+	OMAP_MCBSP_REG_RCERC,
+	OMAP_MCBSP_REG_RCERD,
+	OMAP_MCBSP_REG_XCERC,
+	OMAP_MCBSP_REG_XCERD,
+	OMAP_MCBSP_REG_RCERE,
+	OMAP_MCBSP_REG_RCERF,
+	OMAP_MCBSP_REG_XCERE,
+	OMAP_MCBSP_REG_XCERF,
+	OMAP_MCBSP_REG_RCERG,
+	OMAP_MCBSP_REG_RCERH,
+	OMAP_MCBSP_REG_XCERG,
+	OMAP_MCBSP_REG_XCERH,
+
+	/* OMAP1-OMAP2420 registers */
+	OMAP_MCBSP_REG_DRR2 = 0,
+	OMAP_MCBSP_REG_DRR1,
+	OMAP_MCBSP_REG_DXR2,
+	OMAP_MCBSP_REG_DXR1,
+
+	/* OMAP2430 and onwards */
+	OMAP_MCBSP_REG_DRR = 0,
+	OMAP_MCBSP_REG_DXR = 2,
+	OMAP_MCBSP_REG_SYSCON =	35,
+	OMAP_MCBSP_REG_THRSH2,
+	OMAP_MCBSP_REG_THRSH1,
+	OMAP_MCBSP_REG_IRQST = 40,
+	OMAP_MCBSP_REG_IRQEN,
+	OMAP_MCBSP_REG_WAKEUPEN,
+	OMAP_MCBSP_REG_XCCR,
+	OMAP_MCBSP_REG_RCCR,
+	OMAP_MCBSP_REG_XBUFFSTAT,
+	OMAP_MCBSP_REG_RBUFFSTAT,
+	OMAP_MCBSP_REG_SSELCR,
+};
+
+/* OMAP3 sidetone control registers */
+#define OMAP_ST_REG_REV		0x00
+#define OMAP_ST_REG_SYSCONFIG	0x10
+#define OMAP_ST_REG_IRQSTATUS	0x18
+#define OMAP_ST_REG_IRQENABLE	0x1C
+#define OMAP_ST_REG_SGAINCR	0x24
+#define OMAP_ST_REG_SFIRCR	0x28
+#define OMAP_ST_REG_SSELCR	0x2C
+
+/************************** McBSP SPCR1 bit definitions ***********************/
+#define RRST			BIT(0)
+#define RRDY			BIT(1)
+#define RFULL			BIT(2)
+#define RSYNC_ERR		BIT(3)
+#define RINTM(value)		(((value) & 0x3) << 4)	/* bits 4:5 */
+#define ABIS			BIT(6)
+#define DXENA			BIT(7)
+#define CLKSTP(value)		(((value) & 0x3) << 11)	/* bits 11:12 */
+#define RJUST(value)		(((value) & 0x3) << 13)	/* bits 13:14 */
+#define ALB			BIT(15)
+#define DLB			BIT(15)
+
+/************************** McBSP SPCR2 bit definitions ***********************/
+#define XRST			BIT(0)
+#define XRDY			BIT(1)
+#define XEMPTY			BIT(2)
+#define XSYNC_ERR		BIT(3)
+#define XINTM(value)		(((value) & 0x3) << 4)	/* bits 4:5 */
+#define GRST			BIT(6)
+#define FRST			BIT(7)
+#define SOFT			BIT(8)
+#define FREE			BIT(9)
+
+/************************** McBSP PCR bit definitions *************************/
+#define CLKRP			BIT(0)
+#define CLKXP			BIT(1)
+#define FSRP			BIT(2)
+#define FSXP			BIT(3)
+#define DR_STAT			BIT(4)
+#define DX_STAT			BIT(5)
+#define CLKS_STAT		BIT(6)
+#define SCLKME			BIT(7)
+#define CLKRM			BIT(8)
+#define CLKXM			BIT(9)
+#define FSRM			BIT(10)
+#define FSXM			BIT(11)
+#define RIOEN			BIT(12)
+#define XIOEN			BIT(13)
+#define IDLE_EN			BIT(14)
+
+/************************** McBSP RCR1 bit definitions ************************/
+#define RWDLEN1(value)		(((value) & 0x7) << 5)	/* Bits 5:7 */
+#define RFRLEN1(value)		(((value) & 0x7f) << 8)	/* Bits 8:14 */
+
+/************************** McBSP XCR1 bit definitions ************************/
+#define XWDLEN1(value)		(((value) & 0x7) << 5)	/* Bits 5:7 */
+#define XFRLEN1(value)		(((value) & 0x7f) << 8)	/* Bits 8:14 */
+
+/*************************** McBSP RCR2 bit definitions ***********************/
+#define RDATDLY(value)		((value) & 0x3)		/* Bits 0:1 */
+#define RFIG			BIT(2)
+#define RCOMPAND(value)		(((value) & 0x3) << 3)	/* Bits 3:4 */
+#define RWDLEN2(value)		(((value) & 0x7) << 5)	/* Bits 5:7 */
+#define RFRLEN2(value)		(((value) & 0x7f) << 8)	/* Bits 8:14 */
+#define RPHASE			BIT(15)
+
+/*************************** McBSP XCR2 bit definitions ***********************/
+#define XDATDLY(value)		((value) & 0x3)		/* Bits 0:1 */
+#define XFIG			BIT(2)
+#define XCOMPAND(value)		(((value) & 0x3) << 3)	/* Bits 3:4 */
+#define XWDLEN2(value)		(((value) & 0x7) << 5)	/* Bits 5:7 */
+#define XFRLEN2(value)		(((value) & 0x7f) << 8)	/* Bits 8:14 */
+#define XPHASE			BIT(15)
+
+/************************* McBSP SRGR1 bit definitions ************************/
+#define CLKGDV(value)		((value) & 0x7f)		/* Bits 0:7 */
+#define FWID(value)		(((value) & 0xff) << 8)	/* Bits 8:15 */
+
+/************************* McBSP SRGR2 bit definitions ************************/
+#define FPER(value)		((value) & 0x0fff)	/* Bits 0:11 */
+#define FSGM			BIT(12)
+#define CLKSM			BIT(13)
+#define CLKSP			BIT(14)
+#define GSYNC			BIT(15)
+
+/************************* McBSP MCR1 bit definitions *************************/
+#define RMCM			BIT(0)
+#define RCBLK(value)		(((value) & 0x7) << 2)	/* Bits 2:4 */
+#define RPABLK(value)		(((value) & 0x3) << 5)	/* Bits 5:6 */
+#define RPBBLK(value)		(((value) & 0x3) << 7)	/* Bits 7:8 */
+
+/************************* McBSP MCR2 bit definitions *************************/
+#define XMCM(value)		((value) & 0x3)		/* Bits 0:1 */
+#define XCBLK(value)		(((value) & 0x7) << 2)	/* Bits 2:4 */
+#define XPABLK(value)		(((value) & 0x3) << 5)	/* Bits 5:6 */
+#define XPBBLK(value)		(((value) & 0x3) << 7)	/* Bits 7:8 */
+
+/*********************** McBSP XCCR bit definitions *************************/
+#define XDISABLE		BIT(0)
+#define XDMAEN			BIT(3)
+#define DILB			BIT(5)
+#define XFULL_CYCLE		BIT(11)
+#define DXENDLY(value)		(((value) & 0x3) << 12)	/* Bits 12:13 */
+#define PPCONNECT		BIT(14)
+#define EXTCLKGATE		BIT(15)
+
+/********************** McBSP RCCR bit definitions *************************/
+#define RDISABLE		BIT(0)
+#define RDMAEN			BIT(3)
+#define RFULL_CYCLE		BIT(11)
+
+/********************** McBSP SYSCONFIG bit definitions ********************/
+#define SOFTRST			BIT(1)
+#define ENAWAKEUP		BIT(2)
+#define SIDLEMODE(value)	(((value) & 0x3) << 3)
+#define CLOCKACTIVITY(value)	(((value) & 0x3) << 8)
+
+/********************** McBSP SSELCR bit definitions ***********************/
+#define SIDETONEEN		BIT(10)
+
+/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
+#define ST_AUTOIDLE		BIT(0)
+
+/********************** McBSP Sidetone SGAINCR bit definitions *************/
+#define ST_CH0GAIN(value)	((value) & 0xffff)	/* Bits 0:15 */
+#define ST_CH1GAIN(value)	(((value) & 0xffff) << 16) /* Bits 16:31 */
+
+/********************** McBSP Sidetone SFIRCR bit definitions **************/
+#define ST_FIRCOEFF(value)	((value) & 0xffff)	/* Bits 0:15 */
+
+/********************** McBSP Sidetone SSELCR bit definitions **************/
+#define ST_SIDETONEEN		BIT(0)
+#define ST_COEFFWREN		BIT(1)
+#define ST_COEFFWRDONE		BIT(2)
+
+/********************** McBSP DMA operating modes **************************/
+#define MCBSP_DMA_MODE_ELEMENT		0
+#define MCBSP_DMA_MODE_THRESHOLD	1
+#define MCBSP_DMA_MODE_FRAME		2
+
+/********************** McBSP WAKEUPEN bit definitions *********************/
+#define RSYNCERREN		BIT(0)
+#define RFSREN			BIT(1)
+#define REOFEN			BIT(2)
+#define RRDYEN			BIT(3)
+#define XSYNCERREN		BIT(7)
+#define XFSXEN			BIT(8)
+#define XEOFEN			BIT(9)
+#define XRDYEN			BIT(10)
+#define XEMPTYEOFEN		BIT(14)
+
+/* Clock signal muxing options */
+#define CLKR_SRC_CLKR		0 /* CLKR signal is from the CLKR pin */
+#define CLKR_SRC_CLKX		1 /* CLKR signal is from the CLKX pin */
+#define FSR_SRC_FSR		2 /* FSR signal is from the FSR pin */
+#define FSR_SRC_FSX		3 /* FSR signal is from the FSX pin */
+
+/* McBSP functional clock sources */
+#define MCBSP_CLKS_PRCM_SRC	0
+#define MCBSP_CLKS_PAD_SRC	1
+
+/* we don't do multichannel for now */
+struct omap_mcbsp_reg_cfg {
+	u16 spcr2;
+	u16 spcr1;
+	u16 rcr2;
+	u16 rcr1;
+	u16 xcr2;
+	u16 xcr1;
+	u16 srgr2;
+	u16 srgr1;
+	u16 mcr2;
+	u16 mcr1;
+	u16 pcr0;
+	u16 rcerc;
+	u16 rcerd;
+	u16 xcerc;
+	u16 xcerd;
+	u16 rcere;
+	u16 rcerf;
+	u16 xcere;
+	u16 xcerf;
+	u16 rcerg;
+	u16 rcerh;
+	u16 xcerg;
+	u16 xcerh;
+	u16 xccr;
+	u16 rccr;
+};
+
+struct omap_mcbsp_st_data {
+	void __iomem *io_base_st;
+	bool running;
+	bool enabled;
+	s16 taps[128];	/* Sidetone filter coefficients */
+	int nr_taps;	/* Number of filter coefficients in use */
+	s16 ch0gain;
+	s16 ch1gain;
+};
+
+struct omap_mcbsp {
+	struct device *dev;
+	struct clk *fclk;
+	spinlock_t lock;
+	unsigned long phys_base;
+	unsigned long phys_dma_base;
+	void __iomem *io_base;
+	u8 id;
+	/*
+	 * Flags indicating is the bus already activated and configured by
+	 * another substream
+	 */
+	int active;
+	int configured;
+	u8 free;
+
+	int rx_irq;
+	int tx_irq;
+
+	/* Protect the field .free, while checking if the mcbsp is in use */
+	struct omap_mcbsp_platform_data *pdata;
+	struct omap_mcbsp_st_data *st_data;
+	struct omap_mcbsp_reg_cfg cfg_regs;
+	struct omap_pcm_dma_data dma_data[2];
+	int dma_op_mode;
+	u16 max_tx_thres;
+	u16 max_rx_thres;
+	void *reg_cache;
+	int reg_cache_size;
+
+	unsigned int fmt;
+	unsigned int in_freq;
+	int clk_div;
+	int wlen;
+};
+
+void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
+		       const struct omap_mcbsp_reg_cfg *config);
+void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold);
+void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold);
+u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp);
+u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_get_dma_op_mode(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_request(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_free(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx);
+void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx);
+
+/* McBSP functional clock source changing function */
+int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id);
+
+/* McBSP signal muxing API */
+int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux);
+
+/* Sidetone specific API */
+int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain);
+int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain);
+int omap_st_enable(struct omap_mcbsp *mcbsp);
+int omap_st_disable(struct omap_mcbsp *mcbsp);
+int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
+
+int __devinit omap_mcbsp_init(struct platform_device *pdev);
+void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+
+#endif /* __ASOC_MCBSP_H */
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 597be412f1e40080336be9604940cbfab72012fd..abac4b6907508a00d8e4b63817b1fbb5d2e92ce1 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -55,9 +55,8 @@ static int n810_spk_func;
 static int n810_jack_func;
 static int n810_dmic_func;
 
-static void n810_ext_control(struct snd_soc_codec *codec)
+static void n810_ext_control(struct snd_soc_dapm_context *dapm)
 {
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int hp = 0, line1l = 0;
 
 	switch (n810_jack_func) {
@@ -102,7 +101,7 @@ static int n810_startup(struct snd_pcm_substream *substream)
 	snd_pcm_hw_constraint_minmax(runtime,
 				     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
 
-	n810_ext_control(codec);
+	n810_ext_control(&codec->dapm);
 	return clk_enable(sys_clkout2);
 }
 
@@ -142,13 +141,13 @@ static int n810_get_spk(struct snd_kcontrol *kcontrol,
 static int n810_set_spk(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
 	if (n810_spk_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	n810_spk_func = ucontrol->value.integer.value[0];
-	n810_ext_control(codec);
+	n810_ext_control(&card->dapm);
 
 	return 1;
 }
@@ -164,13 +163,13 @@ static int n810_get_jack(struct snd_kcontrol *kcontrol,
 static int n810_set_jack(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
 	if (n810_jack_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	n810_jack_func = ucontrol->value.integer.value[0];
-	n810_ext_control(codec);
+	n810_ext_control(&card->dapm);
 
 	return 1;
 }
@@ -186,13 +185,13 @@ static int n810_get_input(struct snd_kcontrol *kcontrol,
 static int n810_set_input(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
 	if (n810_dmic_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	n810_dmic_func = ucontrol->value.integer.value[0];
-	n810_ext_control(codec);
+	n810_ext_control(&card->dapm);
 
 	return 1;
 }
@@ -276,7 +275,7 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link n810_dai = {
 	.name = "TLV320AIC33",
 	.stream_name = "AIC33",
-	.cpu_dai_name = "omap-mcbsp-dai.1",
+	.cpu_dai_name = "omap-mcbsp.2",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "tlv320aic3x-codec.2-0018",
 	.codec_dai_name = "tlv320aic3x-hifi",
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
new file mode 100644
index 0000000000000000000000000000000000000000..93bb8eee22b32cdcf00f4d6d2b1fa54510711fb4
--- /dev/null
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -0,0 +1,349 @@
+/*
+ * omap-abe-twl6040.c  --  SoC audio for TI OMAP based boards with ABE and
+ *			   twl6040 codec
+ *
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/platform_data/omap-abe-twl6040.h>
+#include <linux/module.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+#include <plat/hardware.h>
+#include <plat/mux.h>
+
+#include "omap-dmic.h"
+#include "omap-mcpdm.h"
+#include "omap-pcm.h"
+#include "../codecs/twl6040.h"
+
+static int omap_abe_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;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *card = codec->card;
+	struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
+	int clk_id, freq;
+	int ret;
+
+	clk_id = twl6040_get_clk_id(rtd->codec);
+	if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
+		freq = pdata->mclk_freq;
+	else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
+		freq = 32768;
+	else
+		return -EINVAL;
+
+	/* set the codec mclk */
+	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
+				SND_SOC_CLOCK_IN);
+	if (ret) {
+		printk(KERN_ERR "can't set codec system clock\n");
+		return ret;
+	}
+	return ret;
+}
+
+static struct snd_soc_ops omap_abe_ops = {
+	.hw_params = omap_abe_hw_params,
+};
+
+static int omap_abe_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 omap_abe_dmic_ops = {
+	.hw_params = omap_abe_dmic_hw_params,
+};
+
+/* Headset jack */
+static struct snd_soc_jack hs_jack;
+
+/*Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+	{
+		.pin = "Headset Mic",
+		.mask = SND_JACK_MICROPHONE,
+	},
+	{
+		.pin = "Headset Stereophone",
+		.mask = SND_JACK_HEADPHONE,
+	},
+};
+
+/* SDP4430 machine DAPM */
+static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
+	/* Outputs */
+	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+	SND_SOC_DAPM_SPK("Earphone Spk", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+	SND_SOC_DAPM_LINE("Line Out", NULL),
+	SND_SOC_DAPM_SPK("Vibrator", NULL),
+
+	/* Inputs */
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Main Handset Mic", NULL),
+	SND_SOC_DAPM_MIC("Sub Handset Mic", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* Routings for outputs */
+	{"Headset Stereophone", NULL, "HSOL"},
+	{"Headset Stereophone", NULL, "HSOR"},
+
+	{"Earphone Spk", NULL, "EP"},
+
+	{"Ext Spk", NULL, "HFL"},
+	{"Ext Spk", NULL, "HFR"},
+
+	{"Line Out", NULL, "AUXL"},
+	{"Line Out", NULL, "AUXR"},
+
+	{"Vibrator", NULL, "VIBRAL"},
+	{"Vibrator", NULL, "VIBRAR"},
+
+	/* Routings for inputs */
+	{"HSMIC", NULL, "Headset Mic"},
+	{"Headset Mic", NULL, "Headset Mic Bias"},
+
+	{"MAINMIC", NULL, "Main Handset Mic"},
+	{"Main Handset Mic", NULL, "Main Mic Bias"},
+
+	{"SUBMIC", NULL, "Sub Handset Mic"},
+	{"Sub Handset Mic", NULL, "Main Mic Bias"},
+
+	{"AFML", NULL, "Line In"},
+	{"AFMR", NULL, "Line In"},
+};
+
+static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm,
+					  int connected, char *pin)
+{
+	if (!connected)
+		snd_soc_dapm_disable_pin(dapm, pin);
+}
+
+static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *card = codec->card;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
+	int hs_trim;
+	int ret = 0;
+
+	/* Disable not connected paths if not used */
+	twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
+	twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
+	twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
+	twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
+	twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
+	twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
+	twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
+	twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
+	twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
+
+	/*
+	 * Configure McPDM offset cancellation based on the HSOTRIM value from
+	 * twl6040.
+	 */
+	hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
+	omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
+					TWL6040_HSF_TRIM_RIGHT(hs_trim));
+
+	/* Headset jack detection only if it is supported */
+	if (pdata->jack_detection) {
+		ret = snd_soc_jack_new(codec, "Headset Jack",
+					SND_JACK_HEADSET, &hs_jack);
+		if (ret)
+			return ret;
+
+		ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+					hs_jack_pins);
+		twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
+	}
+
+	return ret;
+}
+
+static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Digital Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route dmic_audio_map[] = {
+	{"DMic", NULL, "Digital Mic"},
+	{"Digital Mic", NULL, "Digital Mic1 Bias"},
+};
+
+static int omap_abe_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, dmic_dapm_widgets,
+				ARRAY_SIZE(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 twl6040_dmic_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 = omap_abe_twl6040_init,
+		.ops = &omap_abe_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 = omap_abe_dmic_init,
+		.ops = &omap_abe_dmic_ops,
+	},
+};
+
+static struct snd_soc_dai_link twl6040_only_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 = omap_abe_twl6040_init,
+		.ops = &omap_abe_ops,
+	},
+};
+
+/* Audio machine driver */
+static struct snd_soc_card omap_abe_card = {
+	.owner = THIS_MODULE,
+
+	.dapm_widgets = twl6040_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static __devinit int omap_abe_probe(struct platform_device *pdev)
+{
+	struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
+	struct snd_soc_card *card = &omap_abe_card;
+	int ret;
+
+	card->dev = &pdev->dev;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Missing pdata\n");
+		return -ENODEV;
+	}
+
+	if (pdata->card_name) {
+		card->name = pdata->card_name;
+	} else {
+		dev_err(&pdev->dev, "Card name is not provided\n");
+		return -ENODEV;
+	}
+
+	if (!pdata->mclk_freq) {
+		dev_err(&pdev->dev, "MCLK frequency missing\n");
+		return -ENODEV;
+	}
+
+	if (pdata->has_dmic) {
+		card->dai_link = twl6040_dmic_dai;
+		card->num_links = ARRAY_SIZE(twl6040_dmic_dai);
+	} else {
+		card->dai_link = twl6040_only_dai;
+		card->num_links = ARRAY_SIZE(twl6040_only_dai);
+	}
+
+	ret = snd_soc_register_card(card);
+	if (ret)
+		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+			ret);
+
+	return ret;
+}
+
+static int __devexit omap_abe_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 omap_abe_driver = {
+	.driver = {
+		.name = "omap-abe-twl6040",
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = omap_abe_probe,
+	.remove = __devexit_p(omap_abe_remove),
+};
+
+module_platform_driver(omap_abe_driver);
+
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC for OMAP boards with ABE and twl6040 codec");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:omap-abe-twl6040");
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 0855c1cfa7fd84df5d66d3ab190682a250438b17..4dcb5a7e40e874c37440cbcf82073844ebf6d4d7 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -113,12 +113,10 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
 
 	mutex_lock(&dmic->mutex);
 
-	if (!dai->active) {
-		snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
+	if (!dai->active)
 		dmic->active = 1;
-	} else {
+	else
 		ret = -EBUSY;
-	}
 
 	mutex_unlock(&dmic->mutex);
 
@@ -445,6 +443,7 @@ static struct snd_soc_dai_driver omap_dmic_dai = {
 		.channels_max = 6,
 		.rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
 		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+		.sig_bits = 24,
 	},
 	.ops = &omap_dmic_dai_ops,
 };
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 017371913ec3cf0629acbdc549d8bbe99d5f7ea7..6912ac7cb6250ae8cf30b886d507e0ffdfe2df9a 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/pm_runtime.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -33,6 +34,7 @@
 
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
+#include "mcbsp.h"
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
 
@@ -46,42 +48,31 @@
 	.private_value = (unsigned long) &(struct soc_mixer_control) \
 	{.min = xmin, .max = xmax} }
 
-struct omap_mcbsp_data {
-	unsigned int			bus_id;
-	struct omap_mcbsp_reg_cfg	regs;
-	unsigned int			fmt;
-	/*
-	 * Flags indicating is the bus already activated and configured by
-	 * another substream
-	 */
-	int				active;
-	int				configured;
-	unsigned int			in_freq;
-	int				clk_div;
-	int				wlen;
+enum {
+	OMAP_MCBSP_WORD_8 = 0,
+	OMAP_MCBSP_WORD_12,
+	OMAP_MCBSP_WORD_16,
+	OMAP_MCBSP_WORD_20,
+	OMAP_MCBSP_WORD_24,
+	OMAP_MCBSP_WORD_32,
 };
 
-static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
-
 /*
  * Stream DMA parameters. DMA request line and port address are set runtime
  * since they are different between OMAP1 and later OMAPs
  */
-static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
-
 static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
 	struct omap_pcm_dma_data *dma_data;
-	int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
 	int words;
 
 	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
-	if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
+	if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
 		/*
 		 * Configure McBSP threshold based on either:
 		 * packet_size, when the sDMA is in packet mode, or
@@ -91,15 +82,15 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
 			words = dma_data->packet_size;
 		else
 			words = snd_pcm_lib_period_bytes(substream) /
-							(mcbsp_data->wlen / 8);
+							(mcbsp->wlen / 8);
 	else
 		words = 1;
 
 	/* Configure McBSP internal buffer usage */
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words);
+		omap_mcbsp_set_tx_threshold(mcbsp, words);
 	else
-		omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
+		omap_mcbsp_set_rx_threshold(mcbsp, words);
 }
 
 static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
@@ -109,12 +100,12 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
 					SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
 	struct snd_interval *channels = hw_param_interval(params,
 					SNDRV_PCM_HW_PARAM_CHANNELS);
-	struct omap_mcbsp_data *mcbsp_data = rule->private;
+	struct omap_mcbsp *mcbsp = rule->private;
 	struct snd_interval frames;
 	int size;
 
 	snd_interval_any(&frames);
-	size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id);
+	size = mcbsp->pdata->buffer_size;
 
 	frames.min = size / channels->min;
 	frames.integer = 1;
@@ -124,12 +115,11 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *cpu_dai)
 {
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
-	int bus_id = mcbsp_data->bus_id;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
 	int err = 0;
 
 	if (!cpu_dai->active)
-		err = omap_mcbsp_request(bus_id);
+		err = omap_mcbsp_request(mcbsp);
 
 	/*
 	 * OMAP3 McBSP FIFO is word structured.
@@ -146,16 +136,16 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
 	 * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
 	 * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
 	 */
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->buffer_size) {
 		/*
 		* Rule for the buffer size. We should not allow
 		* smaller buffer than the FIFO size to avoid underruns
 		*/
 		snd_pcm_hw_rule_add(substream->runtime, 0,
-				    SNDRV_PCM_HW_PARAM_CHANNELS,
+				    SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
 				    omap_mcbsp_hwrule_min_buffersize,
-				    mcbsp_data,
-				    SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
+				    mcbsp,
+				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
 
 		/* Make sure, that the period size is always even */
 		snd_pcm_hw_constraint_step(substream->runtime, 0,
@@ -168,33 +158,33 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
 static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *cpu_dai)
 {
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
 
 	if (!cpu_dai->active) {
-		omap_mcbsp_free(mcbsp_data->bus_id);
-		mcbsp_data->configured = 0;
+		omap_mcbsp_free(mcbsp);
+		mcbsp->configured = 0;
 	}
 }
 
 static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 				  struct snd_soc_dai *cpu_dai)
 {
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
 	int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		mcbsp_data->active++;
-		omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
+		mcbsp->active++;
+		omap_mcbsp_start(mcbsp, play, !play);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
-		mcbsp_data->active--;
+		omap_mcbsp_stop(mcbsp, play, !play);
+		mcbsp->active--;
 		break;
 	default:
 		err = -EINVAL;
@@ -209,14 +199,14 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
 	u16 fifo_use;
 	snd_pcm_sframes_t delay;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
+		fifo_use = omap_mcbsp_get_tx_delay(mcbsp);
 	else
-		fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
+		fifo_use = omap_mcbsp_get_rx_delay(mcbsp);
 
 	/*
 	 * Divide the used locations with the channel count to get the
@@ -232,19 +222,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_pcm_hw_params *params,
 				    struct snd_soc_dai *cpu_dai)
 {
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
-	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
 	struct omap_pcm_dma_data *dma_data;
-	int dma, bus_id = mcbsp_data->bus_id;
 	int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
 	int pkt_size = 0;
-	unsigned long port;
 	unsigned int format, div, framesize, master;
 
-	dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
-
-	dma = omap_mcbsp_dma_ch_params(bus_id, substream->stream);
-	port = omap_mcbsp_dma_reg_params(bus_id, substream->stream);
+	dma_data = &mcbsp->dma_data[substream->stream];
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
@@ -258,20 +243,17 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 	default:
 		return -EINVAL;
 	}
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->buffer_size) {
 		dma_data->set_threshold = omap_mcbsp_set_threshold;
 		/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
-		if (omap_mcbsp_get_dma_op_mode(bus_id) ==
-						MCBSP_DMA_MODE_THRESHOLD) {
+		if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
 			int period_words, max_thrsh;
 
 			period_words = params_period_bytes(params) / (wlen / 8);
 			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-				max_thrsh = omap_mcbsp_get_max_tx_threshold(
-							    mcbsp_data->bus_id);
+				max_thrsh = mcbsp->max_tx_thres;
 			else
-				max_thrsh = omap_mcbsp_get_max_rx_threshold(
-							    mcbsp_data->bus_id);
+				max_thrsh = mcbsp->max_rx_thres;
 			/*
 			 * If the period contains less or equal number of words,
 			 * we are using the original threshold mode setup:
@@ -304,15 +286,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 		}
 	}
 
-	dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback";
-	dma_data->dma_req = dma;
-	dma_data->port_addr = port;
 	dma_data->sync_mode = sync_mode;
 	dma_data->packet_size = pkt_size;
 
 	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 
-	if (mcbsp_data->configured) {
+	if (mcbsp->configured) {
 		/* McBSP already configured by another stream */
 		return 0;
 	}
@@ -321,7 +300,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 	regs->xcr2	&= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
 	regs->rcr1	&= ~(RFRLEN1(0x7f) | RWDLEN1(7));
 	regs->xcr1	&= ~(XFRLEN1(0x7f) | XWDLEN1(7));
-	format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+	format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 	wpf = channels = params_channels(params);
 	if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
 			      format == SND_SOC_DAIFMT_LEFT_J)) {
@@ -359,10 +338,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 
 	/* In McBSP master modes, FRAME (i.e. sample rate) is generated
 	 * by _counting_ BCLKs. Calculate frame size in BCLKs */
-	master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
+	master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK;
 	if (master ==	SND_SOC_DAIFMT_CBS_CFS) {
-		div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
-		framesize = (mcbsp_data->in_freq / div) / params_rate(params);
+		div = mcbsp->clk_div ? mcbsp->clk_div : 1;
+		framesize = (mcbsp->in_freq / div) / params_rate(params);
 
 		if (framesize < wlen * channels) {
 			printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
@@ -388,9 +367,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	omap_mcbsp_config(bus_id, &mcbsp_data->regs);
-	mcbsp_data->wlen = wlen;
-	mcbsp_data->configured = 1;
+	omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs);
+	mcbsp->wlen = wlen;
+	mcbsp->configured = 1;
 
 	return 0;
 }
@@ -402,14 +381,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 				      unsigned int fmt)
 {
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
-	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
 	bool inv_fs = false;
 
-	if (mcbsp_data->configured)
+	if (mcbsp->configured)
 		return 0;
 
-	mcbsp_data->fmt = fmt;
+	mcbsp->fmt = fmt;
 	memset(regs, 0, sizeof(*regs));
 	/* Generic McBSP register settings */
 	regs->spcr2	|= XINTM(3) | FREE;
@@ -504,13 +483,13 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
 				     int div_id, int div)
 {
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
-	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
 
 	if (div_id != OMAP_MCBSP_CLKGDV)
 		return -ENODEV;
 
-	mcbsp_data->clk_div = div;
+	mcbsp->clk_div = div;
 	regs->srgr1	&= ~CLKGDV(0xff);
 	regs->srgr1	|= CLKGDV(div - 1);
 
@@ -521,28 +500,32 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 					 int clk_id, unsigned int freq,
 					 int dir)
 {
-	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
-	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+	struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
 	int err = 0;
 
-	if (mcbsp_data->active) {
-		if (freq == mcbsp_data->in_freq)
+	if (mcbsp->active) {
+		if (freq == mcbsp->in_freq)
 			return 0;
 		else
 			return -EBUSY;
 	}
 
-	/* The McBSP signal muxing functions are only available on McBSP1 */
-	if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
-	    clk_id == OMAP_MCBSP_CLKR_SRC_CLKX ||
-	    clk_id == OMAP_MCBSP_FSR_SRC_FSR ||
-	    clk_id == OMAP_MCBSP_FSR_SRC_FSX)
-		if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0)
-			return -EINVAL;
-
-	mcbsp_data->in_freq = freq;
-	regs->srgr2	&= ~CLKSM;
-	regs->pcr0	&= ~SCLKME;
+	if (clk_id == OMAP_MCBSP_SYSCLK_CLK ||
+	    clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK ||
+	    clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT ||
+	    clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT ||
+	    clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) {
+		mcbsp->in_freq = freq;
+		regs->srgr2	&= ~CLKSM;
+		regs->pcr0	&= ~SCLKME;
+	} else if (cpu_class_is_omap1()) {
+		/*
+		 * McBSP CLKR/FSR signal muxing functions are only available on
+		 * OMAP2 or newer versions
+		 */
+		return -EINVAL;
+	}
 
 	switch (clk_id) {
 	case OMAP_MCBSP_SYSCLK_CLK:
@@ -553,7 +536,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 			err = -EINVAL;
 			break;
 		}
-		err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+		err = omap2_mcbsp_set_clks_src(mcbsp,
 					       MCBSP_CLKS_PRCM_SRC);
 		break;
 	case OMAP_MCBSP_SYSCLK_CLKS_EXT:
@@ -561,7 +544,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 			err = 0;
 			break;
 		}
-		err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+		err = omap2_mcbsp_set_clks_src(mcbsp,
 					       MCBSP_CLKS_PAD_SRC);
 		break;
 
@@ -573,24 +556,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 
 
 	case OMAP_MCBSP_CLKR_SRC_CLKR:
-		if (cpu_class_is_omap1())
-			break;
-		omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
+		err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR);
 		break;
 	case OMAP_MCBSP_CLKR_SRC_CLKX:
-		if (cpu_class_is_omap1())
-			break;
-		omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
+		err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX);
 		break;
 	case OMAP_MCBSP_FSR_SRC_FSR:
-		if (cpu_class_is_omap1())
-			break;
-		omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
+		err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR);
 		break;
 	case OMAP_MCBSP_FSR_SRC_FSX:
-		if (cpu_class_is_omap1())
-			break;
-		omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
+		err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX);
 		break;
 	default:
 		err = -ENODEV;
@@ -610,15 +585,27 @@ static const struct snd_soc_dai_ops mcbsp_dai_ops = {
 	.set_sysclk	= omap_mcbsp_dai_set_dai_sysclk,
 };
 
-static int mcbsp_dai_probe(struct snd_soc_dai *dai)
+static int omap_mcbsp_probe(struct snd_soc_dai *dai)
 {
-	mcbsp_data[dai->id].bus_id = dai->id;
-	snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
+
+	pm_runtime_enable(mcbsp->dev);
+
+	return 0;
+}
+
+static int omap_mcbsp_remove(struct snd_soc_dai *dai)
+{
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
+
+	pm_runtime_disable(mcbsp->dev);
+
 	return 0;
 }
 
 static struct snd_soc_dai_driver omap_mcbsp_dai = {
-	.probe = mcbsp_dai_probe,
+	.probe = omap_mcbsp_probe,
+	.remove = omap_mcbsp_remove,
 	.playback = {
 		.channels_min = 1,
 		.channels_max = 16,
@@ -649,11 +636,13 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel)			\
+#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel)			\
 static int								\
-omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
+omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
 					struct snd_ctl_elem_value *uc)	\
 {									\
+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc);		\
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);	\
 	struct soc_mixer_control *mc =					\
 		(struct soc_mixer_control *)kc->private_value;		\
 	int max = mc->max;						\
@@ -664,46 +653,44 @@ omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
 		return -EINVAL;						\
 									\
 	/* OMAP McBSP implementation uses index values 0..4 */		\
-	return omap_st_set_chgain((id)-1, channel, val);		\
+	return omap_st_set_chgain(mcbsp, channel, val);			\
 }
 
-#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel)			\
+#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel)			\
 static int								\
-omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
+omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
 					struct snd_ctl_elem_value *uc)	\
 {									\
+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc);		\
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);	\
 	s16 chgain;							\
 									\
-	if (omap_st_get_chgain((id)-1, channel, &chgain))		\
+	if (omap_st_get_chgain(mcbsp, channel, &chgain))		\
 		return -EAGAIN;						\
 									\
 	uc->value.integer.value[0] = chgain;				\
 	return 0;							\
 }
 
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1)
 
 static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
 	u8 value = ucontrol->value.integer.value[0];
 
-	if (value == omap_st_is_enabled(mc->reg))
+	if (value == omap_st_is_enabled(mcbsp))
 		return 0;
 
 	if (value)
-		omap_st_enable(mc->reg);
+		omap_st_enable(mcbsp);
 	else
-		omap_st_disable(mc->reg);
+		omap_st_disable(mcbsp);
 
 	return 1;
 }
@@ -711,10 +698,10 @@ static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
 static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
 
-	ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg);
+	ucontrol->value.integer.value[0] = omap_st_is_enabled(mcbsp);
 	return 0;
 }
 
@@ -723,12 +710,12 @@ static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
 			omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
 	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
 				      -32768, 32767,
-				      omap_mcbsp2_get_st_ch0_volume,
-				      omap_mcbsp2_set_st_ch0_volume),
+				      omap_mcbsp_get_st_ch0_volume,
+				      omap_mcbsp_set_st_ch0_volume),
 	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
 				      -32768, 32767,
-				      omap_mcbsp2_get_st_ch1_volume,
-				      omap_mcbsp2_set_st_ch1_volume),
+				      omap_mcbsp_get_st_ch1_volume,
+				      omap_mcbsp_set_st_ch1_volume),
 };
 
 static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
@@ -736,25 +723,30 @@ static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
 			omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
 	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
 				      -32768, 32767,
-				      omap_mcbsp3_get_st_ch0_volume,
-				      omap_mcbsp3_set_st_ch0_volume),
+				      omap_mcbsp_get_st_ch0_volume,
+				      omap_mcbsp_set_st_ch0_volume),
 	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
 				      -32768, 32767,
-				      omap_mcbsp3_get_st_ch1_volume,
-				      omap_mcbsp3_set_st_ch1_volume),
+				      omap_mcbsp_get_st_ch1_volume,
+				      omap_mcbsp_set_st_ch1_volume),
 };
 
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
 {
-	if (!cpu_is_omap34xx())
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+
+	if (!mcbsp->st_data)
 		return -ENODEV;
 
-	switch (mcbsp_id) {
-	case 1: /* McBSP 2 */
-		return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
+	switch (cpu_dai->id) {
+	case 2: /* McBSP 2 */
+		return snd_soc_add_dai_controls(cpu_dai,
+					omap_mcbsp2_st_controls,
 					ARRAY_SIZE(omap_mcbsp2_st_controls));
-	case 2: /* McBSP 3 */
-		return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
+	case 3: /* McBSP 3 */
+		return snd_soc_add_dai_controls(cpu_dai,
+					omap_mcbsp3_st_controls,
 					ARRAY_SIZE(omap_mcbsp3_st_controls));
 	default:
 		break;
@@ -766,18 +758,51 @@ EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
 
 static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
 {
-	return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+	struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct omap_mcbsp *mcbsp;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "missing platform data.\n");
+		return -EINVAL;
+	}
+	mcbsp = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcbsp), GFP_KERNEL);
+	if (!mcbsp)
+		return -ENOMEM;
+
+	mcbsp->id = pdev->id;
+	mcbsp->pdata = pdata;
+	mcbsp->dev = &pdev->dev;
+	platform_set_drvdata(pdev, mcbsp);
+
+	ret = omap_mcbsp_init(pdev);
+	if (!ret)
+		return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+
+	return ret;
 }
 
 static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
 {
+	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+
 	snd_soc_unregister_dai(&pdev->dev);
+
+	if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+		mcbsp->pdata->ops->free(mcbsp->id);
+
+	omap_mcbsp_sysfs_remove(mcbsp);
+
+	clk_put(mcbsp->fclk);
+
+	platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
 
 static struct platform_driver asoc_mcbsp_driver = {
 	.driver = {
-			.name = "omap-mcbsp-dai",
+			.name = "omap-mcbsp",
 			.owner = THIS_MODULE,
 	},
 
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index 65cde9d3807b5ffc11c4072dcd8fb606c3e1fb12..f877b16f19c94d08fe3f6bf71052d576f1cede24 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -59,6 +59,6 @@ enum omap_mcbsp_div {
 #define NUM_LINKS	5
 #endif
 
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd);
 
 #endif
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 0e25df4fa9e5cf20e380582a36082e23596d2f0b..39705561131a6c10f4a62a486a31208ccbe075a4 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -419,12 +419,14 @@ static struct snd_soc_dai_driver omap_mcpdm_dai = {
 		.channels_max = 5,
 		.rates = OMAP_MCPDM_RATES,
 		.formats = OMAP_MCPDM_FORMATS,
+		.sig_bits = 24,
 	},
 	.capture = {
 		.channels_min = 1,
 		.channels_max = 3,
 		.rates = OMAP_MCPDM_RATES,
 		.formats = OMAP_MCPDM_FORMATS,
+		.sig_bits = 24,
 	},
 	.ops = &omap_mcpdm_dai_ops,
 };
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index f95fe30641727917bfc9ab6a8806d9c5f8e52833..b92248cbd47a86fe60aa0a2db505a4d976d400d5 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -25,6 +25,8 @@
 #ifndef __OMAP_PCM_H__
 #define __OMAP_PCM_H__
 
+struct snd_pcm_substream;
+
 struct omap_pcm_dma_data {
 	char		*name;		/* stream identifier */
 	int		dma_req;	/* DMA request line */
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
index 3357dcc47ed48ccaf26fa1dfe9854c7ffb8ed0cb..2830dfd05661544c6b25e5984fde3a3941cca74f 100644
--- a/sound/soc/omap/omap3beagle.c
+++ b/sound/soc/omap/omap3beagle.c
@@ -91,7 +91,7 @@ static struct snd_soc_ops omap3beagle_ops = {
 static struct snd_soc_dai_link omap3beagle_dai = {
 	.name = "TWL4030",
 	.stream_name = "TWL4030",
-	.cpu_dai_name = "omap-mcbsp-dai.1",
+	.cpu_dai_name = "omap-mcbsp.2",
 	.platform_name = "omap-pcm-audio",
 	.codec_dai_name = "twl4030-hifi",
 	.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
index 071fcb09b8b27df357394ef0e11adbd1bf543b6e..3d468c9179d7493923bd2d66d90d6c800b5e9394 100644
--- a/sound/soc/omap/omap3evm.c
+++ b/sound/soc/omap/omap3evm.c
@@ -58,7 +58,7 @@ static struct snd_soc_ops omap3evm_ops = {
 static struct snd_soc_dai_link omap3evm_dai = {
 	.name 		= "TWL4030",
 	.stream_name 	= "TWL4030",
-	.cpu_dai_name = "omap-mcbsp-dai.1",
+	.cpu_dai_name = "omap-mcbsp.2",
 	.codec_dai_name = "twl4030-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 07794bd10952f7355232a64cd46790e9283d02a0..4c3a0978578a92b5c9ed66a3a93d7ff66dd71f86 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -208,7 +208,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
 	{
 		.name = "PCM1773",
 		.stream_name = "HiFi Out",
-		.cpu_dai_name = "omap-mcbsp-dai.1",
+		.cpu_dai_name = "omap-mcbsp.2",
 		.codec_dai_name = "twl4030-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
@@ -219,7 +219,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
 	}, {
 		.name = "TWL4030",
 		.stream_name = "Line/Mic In",
-		.cpu_dai_name = "omap-mcbsp-dai.3",
+		.cpu_dai_name = "omap-mcbsp.4",
 		.codec_dai_name = "twl4030-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index d859b597e7ec973cf5477b0bd9f620f5be55b4ab..b1a9d64cbc56f4970eb31e36ab273c6aad536bc5 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -96,7 +96,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
 static struct snd_soc_dai_link osk_dai = {
 	.name = "TLV320AIC23",
 	.stream_name = "AIC23",
-	.cpu_dai_name = "omap-mcbsp-dai.0",
+	.cpu_dai_name = "omap-mcbsp.1",
 	.codec_dai_name = "tlv320aic23-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "tlv320aic23-codec",
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index 2ee889c502564f42fa69ac8ef31c3f9dd22fe0af..6ac3e0c3c2826dd0c932b9f1bba2506461a4d6e1 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -60,7 +60,7 @@ static struct snd_soc_ops overo_ops = {
 static struct snd_soc_dai_link overo_dai = {
 	.name = "TWL4030",
 	.stream_name = "TWL4030",
-	.cpu_dai_name = "omap-mcbsp-dai.1",
+	.cpu_dai_name = "omap-mcbsp.2",
 	.codec_dai_name = "twl4030-hifi",
 	.platform_name = "omap-pcm-audio",
 	.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index fada6ef43eeae736750ef60de289efb0fa48af1d..2712dd232b6d477032648ecfc9f70f5a37d62c64 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -59,9 +59,8 @@ static int rx51_spk_func;
 static int rx51_dmic_func;
 static int rx51_jack_func;
 
-static void rx51_ext_control(struct snd_soc_codec *codec)
+static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
 {
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int hp = 0, hs = 0, tvout = 0;
 
 	switch (rx51_jack_func) {
@@ -102,11 +101,11 @@ static int rx51_startup(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *card = rtd->card;
 
 	snd_pcm_hw_constraint_minmax(runtime,
 				     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
-	rx51_ext_control(codec);
+	rx51_ext_control(&card->dapm);
 
 	return 0;
 }
@@ -138,13 +137,13 @@ static int rx51_get_spk(struct snd_kcontrol *kcontrol,
 static int rx51_set_spk(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
 	if (rx51_spk_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	rx51_spk_func = ucontrol->value.integer.value[0];
-	rx51_ext_control(codec);
+	rx51_ext_control(&card->dapm);
 
 	return 1;
 }
@@ -184,13 +183,13 @@ static int rx51_get_input(struct snd_kcontrol *kcontrol,
 static int rx51_set_input(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
 	if (rx51_dmic_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	rx51_dmic_func = ucontrol->value.integer.value[0];
-	rx51_ext_control(codec);
+	rx51_ext_control(&card->dapm);
 
 	return 1;
 }
@@ -206,13 +205,13 @@ static int rx51_get_jack(struct snd_kcontrol *kcontrol,
 static int rx51_set_jack(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
 	if (rx51_jack_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	rx51_jack_func = ucontrol->value.integer.value[0];
-	rx51_ext_control(codec);
+	rx51_ext_control(&card->dapm);
 
 	return 1;
 }
@@ -297,7 +296,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "LINE1R");
 
 	/* Add RX-51 specific controls */
-	err = snd_soc_add_controls(codec, aic34_rx51_controls,
+	err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls,
 				   ARRAY_SIZE(aic34_rx51_controls));
 	if (err < 0)
 		return err;
@@ -314,7 +313,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 		return err;
 	snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
 
-	err = omap_mcbsp_st_add_controls(codec, 1);
+	err = omap_mcbsp_st_add_controls(rtd);
 	if (err < 0)
 		return err;
 
@@ -335,7 +334,7 @@ static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
 {
 	int err;
 
-	err = snd_soc_add_controls(dapm->codec, aic34_rx51_controlsb,
+	err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb,
 				   ARRAY_SIZE(aic34_rx51_controlsb));
 	if (err < 0)
 		return err;
@@ -354,7 +353,7 @@ static struct snd_soc_dai_link rx51_dai[] = {
 	{
 		.name = "TLV320AIC34",
 		.stream_name = "AIC34",
-		.cpu_dai_name = "omap-mcbsp-dai.1",
+		.cpu_dai_name = "omap-mcbsp.2",
 		.codec_dai_name = "tlv320aic3x-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "tlv320aic3x-codec.2-0018",
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index 2c850662ea7ea79f70978ac19916cf07c9ee7542..0e283226e2bf8deecf215b54ef22c700c72fff0d 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -187,7 +187,7 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
 	{
 		.name = "TWL4030 I2S",
 		.stream_name = "TWL4030 Audio",
-		.cpu_dai_name = "omap-mcbsp-dai.1",
+		.cpu_dai_name = "omap-mcbsp.2",
 		.codec_dai_name = "twl4030-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
@@ -199,7 +199,7 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
 	{
 		.name = "TWL4030 PCM",
 		.stream_name = "TWL4030 Voice",
-		.cpu_dai_name = "omap-mcbsp-dai.2",
+		.cpu_dai_name = "omap-mcbsp.3",
 		.codec_dai_name = "twl4030-voice",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
deleted file mode 100644
index 175ba9a04edfbd449b8b4822df6b5d1561a25e3a..0000000000000000000000000000000000000000
--- a/sound/soc/omap/sdp4430.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * sdp4430.c  --  SoC audio for TI OMAP4430 SDP
- *
- * Author: Misael Lopez Cruz <x0052729@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/clk.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/twl6040.h>
-#include <linux/module.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/jack.h>
-
-#include <asm/mach-types.h>
-#include <plat/hardware.h>
-#include <plat/mux.h>
-
-#include "omap-dmic.h"
-#include "omap-mcpdm.h"
-#include "omap-pcm.h"
-#include "../codecs/twl6040.h"
-
-static int sdp4430_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 clk_id, freq;
-	int ret;
-
-	clk_id = twl6040_get_clk_id(rtd->codec);
-	if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
-		freq = 38400000;
-	else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
-		freq = 32768;
-	else
-		return -EINVAL;
-
-	/* set the codec mclk */
-	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
-				SND_SOC_CLOCK_IN);
-	if (ret) {
-		printk(KERN_ERR "can't set codec system clock\n");
-		return ret;
-	}
-	return ret;
-}
-
-static struct snd_soc_ops sdp4430_ops = {
-	.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;
-
-/*Headset jack detection DAPM pins */
-static struct snd_soc_jack_pin hs_jack_pins[] = {
-	{
-		.pin = "Headset Mic",
-		.mask = SND_JACK_MICROPHONE,
-	},
-	{
-		.pin = "Headset Stereophone",
-		.mask = SND_JACK_HEADPHONE,
-	},
-};
-
-/* SDP4430 machine DAPM */
-static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
-	SND_SOC_DAPM_MIC("Ext Mic", NULL),
-	SND_SOC_DAPM_SPK("Ext Spk", NULL),
-	SND_SOC_DAPM_MIC("Headset Mic", NULL),
-	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
-	SND_SOC_DAPM_SPK("Earphone Spk", NULL),
-	SND_SOC_DAPM_INPUT("FM Stereo In"),
-};
-
-static const struct snd_soc_dapm_route audio_map[] = {
-	/* External Mics: MAINMIC, SUBMIC with bias*/
-	{"MAINMIC", NULL, "Main Mic Bias"},
-	{"SUBMIC", NULL, "Main Mic Bias"},
-	{"Main Mic Bias", NULL, "Ext Mic"},
-
-	/* External Speakers: HFL, HFR */
-	{"Ext Spk", NULL, "HFL"},
-	{"Ext Spk", NULL, "HFR"},
-
-	/* Headset Mic: HSMIC with bias */
-	{"HSMIC", NULL, "Headset Mic Bias"},
-	{"Headset Mic Bias", NULL, "Headset Mic"},
-
-	/* Headset Stereophone (Headphone): HSOL, HSOR */
-	{"Headset Stereophone", NULL, "HSOL"},
-	{"Headset Stereophone", NULL, "HSOR"},
-
-	/* Earphone speaker */
-	{"Earphone Spk", NULL, "EP"},
-
-	/* Aux/FM Stereo In: AFML, AFMR */
-	{"AFML", NULL, "FM Stereo In"},
-	{"AFMR", NULL, "FM Stereo In"},
-};
-
-static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_soc_codec *codec = rtd->codec;
-	int ret, hs_trim;
-
-	/*
-	 * Configure McPDM offset cancellation based on the HSOTRIM value from
-	 * twl6040.
-	 */
-	hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
-	omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
-					TWL6040_HSF_TRIM_RIGHT(hs_trim));
-
-	/* Headset jack detection */
-	ret = snd_soc_jack_new(codec, "Headset Jack",
-				SND_JACK_HEADSET, &hs_jack);
-	if (ret)
-		return ret;
-
-	ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
-				hs_jack_pins);
-
-	if (machine_is_omap_4430sdp())
-		twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
-	else
-		snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
-
-	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,
-	},
-	{
-		.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",
-	.owner = THIS_MODULE,
-	.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),
-	.dapm_routes = audio_map,
-	.num_dapm_routes = ARRAY_SIZE(audio_map),
-};
-
-static struct platform_device *sdp4430_snd_device;
-
-static int __init sdp4430_soc_init(void)
-{
-	int ret;
-
-	if (!machine_is_omap_4430sdp())
-		return -ENODEV;
-	printk(KERN_INFO "SDP4430 SoC init\n");
-
-	sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!sdp4430_snd_device) {
-		printk(KERN_ERR "Platform device allocation failed\n");
-		return -ENOMEM;
-	}
-
-	platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
-
-	ret = platform_device_add(sdp4430_snd_device);
-	if (ret)
-		goto err;
-
-	return 0;
-
-err:
-	printk(KERN_ERR "Unable to add platform device\n");
-	platform_device_put(sdp4430_snd_device);
-	return ret;
-}
-module_init(sdp4430_soc_init);
-
-static void __exit sdp4430_soc_exit(void)
-{
-	platform_device_unregister(sdp4430_snd_device);
-}
-module_exit(sdp4430_soc_exit);
-
-MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
-MODULE_DESCRIPTION("ALSA SoC SDP4430");
-MODULE_LICENSE("GPL");
-
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
index 981616d61f6762ff459f1a7dd8c3fa9e2a621fd4..920e0d9e03db1531ff994156c2a02a3120af447f 100644
--- a/sound/soc/omap/zoom2.c
+++ b/sound/soc/omap/zoom2.c
@@ -131,7 +131,7 @@ static struct snd_soc_dai_link zoom2_dai[] = {
 	{
 		.name = "TWL4030 I2S",
 		.stream_name = "TWL4030 Audio",
-		.cpu_dai_name = "omap-mcbsp-dai.1",
+		.cpu_dai_name = "omap-mcbsp.2",
 		.codec_dai_name = "twl4030-hifi",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
@@ -143,7 +143,7 @@ static struct snd_soc_dai_link zoom2_dai[] = {
 	{
 		.name = "TWL4030 PCM",
 		.stream_name = "TWL4030 Voice",
-		.cpu_dai_name = "omap-mcbsp-dai.2",
+		.cpu_dai_name = "omap-mcbsp.3",
 		.codec_dai_name = "twl4030-voice",
 		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl4030-codec",
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index bc21944851c4c69f274fc4df418dd499e45a0bdd..863367ad89ce6aa1b173914f8c2541903d4f9846 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -45,10 +45,8 @@
 static int corgi_jack_func;
 static int corgi_spk_func;
 
-static void corgi_ext_control(struct snd_soc_codec *codec)
+static void corgi_ext_control(struct snd_soc_dapm_context *dapm)
 {
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
 	/* set up jack connection */
 	switch (corgi_jack_func) {
 	case CORGI_HP:
@@ -104,7 +102,7 @@ static int corgi_startup(struct snd_pcm_substream *substream)
 	mutex_lock(&codec->mutex);
 
 	/* check the jack status at stream startup */
-	corgi_ext_control(codec);
+	corgi_ext_control(&codec->dapm);
 
 	mutex_unlock(&codec->mutex);
 
@@ -173,13 +171,13 @@ static int corgi_get_jack(struct snd_kcontrol *kcontrol,
 static int corgi_set_jack(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
 	if (corgi_jack_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	corgi_jack_func = ucontrol->value.integer.value[0];
-	corgi_ext_control(codec);
+	corgi_ext_control(&card->dapm);
 	return 1;
 }
 
@@ -193,13 +191,13 @@ static int corgi_get_spk(struct snd_kcontrol *kcontrol,
 static int corgi_set_spk(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
 	if (corgi_spk_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	corgi_spk_func = ucontrol->value.integer.value[0];
-	corgi_ext_control(codec);
+	corgi_ext_control(&card->dapm);
 	return 1;
 }
 
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 3f7a8ecb97206b875469d5de5a2bf21410dd9034..aace19e0fe2c217f734dbd0164b4d242a93be1d1 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -411,7 +411,7 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "VINR");
 
 	/* Add magician specific controls */
-	err = snd_soc_add_controls(codec, uda1380_magician_controls,
+	err = snd_soc_add_codec_controls(codec, uda1380_magician_controls,
 				ARRAY_SIZE(uda1380_magician_controls));
 	if (err < 0)
 		return err;
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index fd0ed10c6fe7346065ee18c65d0cb02f4cee6724..d2cc81735036ea8dd6a1aff7f61465caa29fd2fd 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -43,10 +43,8 @@
 static int poodle_jack_func;
 static int poodle_spk_func;
 
-static void poodle_ext_control(struct snd_soc_codec *codec)
+static void poodle_ext_control(struct snd_soc_dapm_context *dapm)
 {
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
 	/* set up jack connection */
 	if (poodle_jack_func == POODLE_HP) {
 		/* set = unmute headphone */
@@ -81,7 +79,7 @@ static int poodle_startup(struct snd_pcm_substream *substream)
 	mutex_lock(&codec->mutex);
 
 	/* check the jack status at stream startup */
-	poodle_ext_control(codec);
+	poodle_ext_control(&codec->dapm);
 
 	mutex_unlock(&codec->mutex);
 
@@ -152,13 +150,13 @@ static int poodle_get_jack(struct snd_kcontrol *kcontrol,
 static int poodle_set_jack(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
 	if (poodle_jack_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	poodle_jack_func = ucontrol->value.integer.value[0];
-	poodle_ext_control(codec);
+	poodle_ext_control(&card->dapm);
 	return 1;
 }
 
@@ -172,13 +170,13 @@ static int poodle_get_spk(struct snd_kcontrol *kcontrol,
 static int poodle_set_spk(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
 	if (poodle_spk_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	poodle_spk_func = ucontrol->value.integer.value[0];
-	poodle_ext_control(codec);
+	poodle_ext_control(&card->dapm);
 	return 1;
 }
 
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index a57cfbc038e3cc1522c33b98d9fd648203948337..fd04ce139031d56b99800a8e0c6a7e6faeb4d662 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream,
+				    struct ssp_device *ssp, int value)
+{
+	uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
+	uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1);
+	uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP);
+	uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR);
+
+	if (value && (sscr0 & SSCR0_SSE))
+		pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (value)
+			sscr1 |= SSCR1_TSRE;
+		else
+			sscr1 &= ~SSCR1_TSRE;
+	} else {
+		if (value)
+			sscr1 |= SSCR1_RSRE;
+		else
+			sscr1 &= ~SSCR1_RSRE;
+	}
+
+	pxa_ssp_write_reg(ssp, SSCR1, sscr1);
+
+	if (value) {
+		pxa_ssp_write_reg(ssp, SSSR, sssr);
+		pxa_ssp_write_reg(ssp, SSPSP, sspsp);
+		pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE);
+	}
+}
+
 static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
 			   struct snd_soc_dai *cpu_dai)
 {
@@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
 		pxa_ssp_enable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val |= SSCR1_TSRE;
-		else
-			val |= SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 1);
 		val = pxa_ssp_read_reg(ssp, SSSR);
 		pxa_ssp_write_reg(ssp, SSSR, val);
 		break;
 	case SNDRV_PCM_TRIGGER_START:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val |= SSCR1_TSRE;
-		else
-			val |= SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
-		pxa_ssp_enable(ssp);
+		pxa_ssp_set_running_bit(substream, ssp, 1);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val &= ~SSCR1_TSRE;
-		else
-			val &= ~SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 0);
 		break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 		pxa_ssp_disable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val &= ~SSCR1_TSRE;
-		else
-			val &= ~SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 0);
 		break;
 
 	default:
@@ -764,7 +775,8 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai)
 
 #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
 			  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |	\
-			  SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |	\
+			  SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |	\
+			  SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 |	\
 			  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
 #define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 837ff341fd6dda45954f2ec34fd263f24a54d62e..4800d5fe568dcdd38adbbe424a1c0e595139775b 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -103,7 +103,7 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
 #define pxa2xx_ac97_resume	NULL
 #endif
 
-static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
+static int __devinit pxa2xx_ac97_probe(struct snd_soc_dai *dai)
 {
 	return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
 }
@@ -179,7 +179,7 @@ static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
  * There is only 1 physical AC97 interface for pxa2xx, but it
  * has extra fifo's that can be used for aux DACs and ADCs.
  */
-static struct snd_soc_dai_driver pxa_ac97_dai[] = {
+static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
 {
 	.name = "pxa2xx-ac97",
 	.ac97_control = 1,
@@ -244,13 +244,13 @@ static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 	 * driver to do interesting things with the clocking to get us up
 	 * and running.
 	 */
-	return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai,
-			ARRAY_SIZE(pxa_ac97_dai));
+	return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai_driver,
+			ARRAY_SIZE(pxa_ac97_dai_driver));
 }
 
 static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
 {
-	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai));
+	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
 	return 0;
 }
 
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
index ba1545188ec66150b953234bd086f5cccc0f0882..083706595495956005fa6b91e731dc1796de44db 100644
--- a/sound/soc/pxa/raumfeld.c
+++ b/sound/soc/pxa/raumfeld.c
@@ -232,7 +232,7 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {
 	.cpu_dai_name	= "pxa-ssp-dai.0",		\
 	.platform_name	= "pxa-pcm-audio",		\
 	.codec_dai_name	= "cs4270-hifi",		\
-	.codec_name	= "cs4270-codec.0-0048",	\
+	.codec_name	= "cs4270.0-0048",	\
 	.ops		= &raumfeld_cs4270_ops,		\
 }
 
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 90c5245c4742493bc7406d27d5d7bf11d2a74423..fc052d8247ff245aa6b5baead314ac893e77930c 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -44,10 +44,8 @@ static int spitz_jack_func;
 static int spitz_spk_func;
 static int spitz_mic_gpio;
 
-static void spitz_ext_control(struct snd_soc_codec *codec)
+static void spitz_ext_control(struct snd_soc_dapm_context *dapm)
 {
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
 	if (spitz_spk_func == SPITZ_SPK_ON)
 		snd_soc_dapm_enable_pin(dapm, "Ext Spk");
 	else
@@ -113,7 +111,7 @@ static int spitz_startup(struct snd_pcm_substream *substream)
 	mutex_lock(&codec->mutex);
 
 	/* check the jack status at stream startup */
-	spitz_ext_control(codec);
+	spitz_ext_control(&codec->dapm);
 
 	mutex_unlock(&codec->mutex);
 
@@ -173,13 +171,13 @@ static int spitz_get_jack(struct snd_kcontrol *kcontrol,
 static int spitz_set_jack(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
 	if (spitz_jack_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	spitz_jack_func = ucontrol->value.integer.value[0];
-	spitz_ext_control(codec);
+	spitz_ext_control(&card->dapm);
 	return 1;
 }
 
@@ -193,13 +191,13 @@ static int spitz_get_spk(struct snd_kcontrol *kcontrol,
 static int spitz_set_spk(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
 	if (spitz_spk_func == ucontrol->value.integer.value[0])
 		return 0;
 
 	spitz_spk_func = ucontrol->value.integer.value[0];
-	spitz_ext_control(codec);
+	spitz_ext_control(&card->dapm);
 	return 1;
 }
 
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 564ef08a89f2d410efae0d45dcdc1691d9e32b5d..2aec63f3706acf826f8f9424fa496a1a479814ab 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -197,7 +197,7 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "MONOOUT");
 
 	/* add tosa specific controls */
-	err = snd_soc_add_controls(codec, tosa_controls,
+	err = snd_soc_add_codec_controls(codec, tosa_controls,
 				ARRAY_SIZE(tosa_controls));
 	if (err < 0)
 		return err;
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 43c014f362f60643a9f5f4d798a2c651b6c0af1b..716da861c629399de5e5322b1556c4e7ae46d08e 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -435,7 +435,8 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
 {
 	struct snd_soc_pcm_runtime *runtime = pcm->private_data;
 	struct s6000_pcm_dma_params *params =
-		snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream);
+		snd_soc_dai_get_dma_data(runtime->cpu_dai,
+			pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
 
 	free_irq(params->irq, pcm);
 	snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -451,7 +452,7 @@ static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
 	int res;
 
 	params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
-			pcm->streams[0].substream);
+			pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
 
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &s6000_pcm_dmamask;
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 7b9bf93e3701edf92bd47b74d39c8d58de4f690e..3d04c1fa678115d2bd0767a14d515733235855c1 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -4,7 +4,7 @@
  * 	Evolved from s3c2443-ac97.c
  *
  * Copyright (c) 2010 Samsung Electronics Co. Ltd
- * 	Author: Jaswinder Singh <jassi.brar@samsung.com>
+ *	Author: Jaswinder Singh <jassisinghbrar@gmail.com>
  * 	Credits: Graeme Gregory, Sean Choi
  *
  * This program is free software; you can redistribute it and/or modify
@@ -511,7 +511,7 @@ static struct platform_driver s3c_ac97_driver = {
 
 module_platform_driver(s3c_ac97_driver);
 
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
 MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:samsung-ac97");
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index e4ba17ce6b32cf3c8d3d3a0762d70c7b7c969b3c..ddc6cde14e2a588763531d94f22b0dab2b1d9a49 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -411,7 +411,7 @@ static int dma_new(struct snd_soc_pcm_runtime *rtd)
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &dma_mask;
 	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = 0xffffffff;
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
 	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
 		ret = preallocate_dma_buffer(pcm,
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 87a874dc7a3542d12735d8e9b13a97181e4ab86f..6ac7b8281a02fc9af3327bfe54d0a5206e9dfbff 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -3,7 +3,7 @@
  * ALSA SoC Audio Layer - Samsung I2S Controller driver
  *
  * Copyright (c) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
+ *	Jaswinder Singh <jassisinghbrar@gmail.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
@@ -559,6 +559,17 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 		mod |= MOD_DC1_EN;
 		break;
 	case 2:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			i2s->dma_playback.dma_size = 4;
+		else
+			i2s->dma_capture.dma_size = 4;
+		break;
+	case 1:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			i2s->dma_playback.dma_size = 2;
+		else
+			i2s->dma_capture.dma_size = 2;
+
 		break;
 	default:
 		dev_err(&i2s->pdev->dev, "%d channels not supported\n",
@@ -761,15 +772,13 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		local_irq_save(flags);
 
-		if (capture)
+		if (capture) {
 			i2s_rxctrl(i2s, 0);
-		else
-			i2s_txctrl(i2s, 0);
-
-		if (capture)
 			i2s_fifo(i2s, FIC_RXFLUSH);
-		else
+		} else {
+			i2s_txctrl(i2s, 0);
 			i2s_fifo(i2s, FIC_TXFLUSH);
+		}
 
 		local_irq_restore(flags);
 		break;
@@ -965,7 +974,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 	i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;
 
 	if (!sec) {
-		i2s->i2s_dai_drv.capture.channels_min = 2;
+		i2s->i2s_dai_drv.capture.channels_min = 1;
 		i2s->i2s_dai_drv.capture.channels_max = 2;
 		i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;
 		i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
@@ -1143,7 +1152,7 @@ static struct platform_driver samsung_i2s_driver = {
 module_platform_driver(samsung_i2s_driver);
 
 /* Module information */
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
 MODULE_DESCRIPTION("Samsung I2S Interface");
 MODULE_ALIAS("platform:samsung-i2s");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h
index 8e15f6a616d170446985c302cb2ea00a19824b3f..d420a7ca56cada50ac1db744a9df05fffa143168 100644
--- a/sound/soc/samsung/i2s.h
+++ b/sound/soc/samsung/i2s.h
@@ -3,7 +3,7 @@
  * ALSA SoC Audio Layer - Samsung I2S Controller driver
  *
  * Copyright (c) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
+ *	Jaswinder Singh <jassisinghbrar@gmail.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
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index 9dd818bde06fb6347d9a6e2f79717ae9766123d8..e7416851bf7d0237e97f33fd58b60886ab3ec4f0 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -189,6 +189,9 @@ static int littlemill_late_probe(struct snd_soc_card *card)
 	/* This will check device compatibility itself */
 	wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
 
+	/* As will this */
+	wm8994_mic_detect(codec, &littlemill_headset, 1);
+
 	return 0;
 }
 
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index d23b19a59d8383f4b6f5aa2036699831793a762e..321d51134e47789a02c6d6483a0cb508a5b187c1 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -296,7 +296,7 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
 	if (ret)
 		return ret;
 
-	ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls,
+	ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls,
 			ARRAY_SIZE(neo1973_gta02_wm8753_controls));
 	if (ret)
 		return ret;
@@ -328,7 +328,7 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
 		return ret;
 
 	/* add neo1973 specific controls */
-	ret = snd_soc_add_controls(codec, neo1973_wm8753_controls,
+	ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls,
 			ARRAY_SIZE(neo1973_wm8753_controls));
 	if (ret)
 		return ret;
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 56780206c000be484f2f9651e6be53158794cc7d..b7b2a1f9142521d931a94fe65cd5ea9a580869d2 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -3,7 +3,7 @@
  * ALSA SoC Audio Layer - S3C PCM-Controller driver
  *
  * Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
  * based upon I2S drivers by Ben Dooks.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -639,7 +639,7 @@ static struct platform_driver s3c_pcm_driver = {
 module_platform_driver(s3c_pcm_driver);
 
 /* Module information */
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
 MODULE_DESCRIPTION("S3C PCM Controller Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:samsung-pcm");
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
index a253bcc1646aabee42c7b4844bcf960578f49b1b..656d5afe4ca945a944b2d7efdca3e7a78c197228 100644
--- a/sound/soc/samsung/s3c24xx_simtec.c
+++ b/sound/soc/samsung/s3c24xx_simtec.c
@@ -134,18 +134,18 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = {
 
 void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *card = rtd->card;
 
 	if (pdata->amp_gpio > 0) {
 		pr_debug("%s: adding amp routes\n", __func__);
 
-		snd_soc_add_controls(codec, amp_unmute_controls,
+		snd_soc_add_card_controls(card, amp_unmute_controls,
 				     ARRAY_SIZE(amp_unmute_controls));
 	}
 
 	if (pdata->amp_gain[0] > 0) {
 		pr_debug("%s: adding amp controls\n", __func__);
-		snd_soc_add_controls(codec, amp_gain_controls,
+		snd_soc_add_card_controls(card, amp_gain_controls,
 				     ARRAY_SIZE(amp_gain_controls));
 	}
 }
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index bff8758e7f20807e38253a6c202d91d5421c402e..ade2809cf393eebc97d74952b44c65aaa35835ac 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -2,7 +2,7 @@
  *  smdk_wm8580.c
  *
  *  Copyright (c) 2009 Samsung Electronics Co. Ltd
- *  Author: Jaswinder Singh <jassi.brar@samsung.com>
+ *  Author: Jaswinder Singh <jassisinghbrar@gmail.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -253,6 +253,6 @@ static void __exit smdk_audio_exit(void)
 }
 module_exit(smdk_audio_exit);
 
-MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
+MODULE_AUTHOR("Jaswinder Singh, jassisinghbrar@gmail.com");
 MODULE_DESCRIPTION("ALSA SoC SMDK WM8580");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c
index 8e26a730fcdc787abb7d758e980d12fe6153f133..55b2ca7f3290a624d1b63145eb5997eafa770e7e 100644
--- a/sound/soc/samsung/smdk_wm9713.c
+++ b/sound/soc/samsung/smdk_wm9713.c
@@ -2,7 +2,7 @@
  * smdk_wm9713.c  --  SoC audio for SMDK
  *
  * Copyright 2010 Samsung Electronics Co. Ltd.
- * Author: Jaswinder Singh Brar <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh Brar <jassisinghbrar@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -103,6 +103,6 @@ module_init(smdk_init);
 module_exit(smdk_exit);
 
 /* Module information */
-MODULE_AUTHOR("Jaswinder Singh Brar, jassi.brar@samsung.com");
+MODULE_AUTHOR("Jaswinder Singh Brar, jassisinghbrar@gmail.com");
 MODULE_DESCRIPTION("ALSA SoC SMDK+WM9713");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index ea4a82d01160f5657e19a4f1f4df4ca928d1737a..378cc5b056d72f6c9ed5d28481869e3a608df871 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -13,8 +13,11 @@
  */
 
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/sh_dma.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <sound/soc.h>
@@ -53,6 +56,7 @@
 
 /* DO_FMT */
 /* DI_FMT */
+#define CR_BWS_MASK	(0x3 << 20) /* FSI2 */
 #define CR_BWS_24	(0x0 << 20) /* FSI2 */
 #define CR_BWS_16	(0x1 << 20) /* FSI2 */
 #define CR_BWS_20	(0x2 << 20) /* FSI2 */
@@ -68,6 +72,15 @@
 #define CR_TDM		(0x4 << 4)
 #define CR_TDM_D	(0x5 << 4)
 
+/* OUT_DMAC */
+/* IN_DMAC */
+#define VDMD_MASK	(0x3 << 4)
+#define VDMD_FRONT	(0x0 << 4) /* Package in front */
+#define VDMD_BACK	(0x1 << 4) /* Package in back */
+#define VDMD_STREAM	(0x2 << 4) /* Stream mode(16bit * 2) */
+
+#define DMA_ON		(0x1 << 0)
+
 /* DOFF_CTL */
 /* DIFF_CTL */
 #define IRQ_HALF	0x00100000
@@ -116,7 +129,7 @@
 
 #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
 
-typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable);
+typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
 
 /*
  * FSI driver use below type name for variable
@@ -159,22 +172,41 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
  *		struct
  */
 
+struct fsi_stream_handler;
 struct fsi_stream {
-	struct snd_pcm_substream *substream;
 
+	/*
+	 * these are initialized by fsi_stream_init()
+	 */
+	struct snd_pcm_substream *substream;
 	int fifo_sample_capa;	/* sample capacity of FSI FIFO */
 	int buff_sample_capa;	/* sample capacity of ALSA buffer */
 	int buff_sample_pos;	/* sample position of ALSA buffer */
 	int period_samples;	/* sample number / 1 period */
 	int period_pos;		/* current period position */
-
+	int sample_width;	/* sample width */
 	int uerr_num;
 	int oerr_num;
+
+	/*
+	 * thse are initialized by fsi_handler_init()
+	 */
+	struct fsi_stream_handler *handler;
+	struct fsi_priv		*priv;
+
+	/*
+	 * these are for DMAEngine
+	 */
+	struct dma_chan		*chan;
+	struct sh_dmae_slave	slave; /* see fsi_handler_init() */
+	struct tasklet_struct	tasklet;
+	dma_addr_t		dma;
 };
 
 struct fsi_priv {
 	void __iomem *base;
 	struct fsi_master *master;
+	struct sh_fsi_port_info *info;
 
 	struct fsi_stream playback;
 	struct fsi_stream capture;
@@ -189,6 +221,20 @@ struct fsi_priv {
 	long rate;
 };
 
+struct fsi_stream_handler {
+	int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
+	int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
+	int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
+	int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
+	int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
+	void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
+			   int enable);
+};
+#define fsi_stream_handler_call(io, func, args...)	\
+	(!(io) ? -ENODEV :				\
+	 !((io)->handler->func) ? 0 :			\
+	 (io)->handler->func(args))
+
 struct fsi_core {
 	int ver;
 
@@ -205,10 +251,11 @@ struct fsi_master {
 	struct fsi_priv fsia;
 	struct fsi_priv fsib;
 	struct fsi_core *core;
-	struct sh_fsi_platform_info *info;
 	spinlock_t lock;
 };
 
+static int fsi_stream_is_play(struct fsi_priv *fsi, struct fsi_stream *io);
+
 /*
  *		basic read write function
  */
@@ -295,6 +342,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
 	return fsi->spdif;
 }
 
+static int fsi_is_play(struct snd_pcm_substream *substream)
+{
+	return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
 static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -317,44 +369,25 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
 	return fsi_get_priv_frm_dai(fsi_get_dai(substream));
 }
 
-static set_rate_func fsi_get_info_set_rate(struct fsi_master *master)
+static set_rate_func fsi_get_info_set_rate(struct fsi_priv *fsi)
 {
-	if (!master->info)
+	if (!fsi->info)
 		return NULL;
 
-	return master->info->set_rate;
+	return fsi->info->set_rate;
 }
 
 static u32 fsi_get_info_flags(struct fsi_priv *fsi)
 {
-	int is_porta = fsi_is_port_a(fsi);
-	struct fsi_master *master = fsi_get_master(fsi);
-
-	if (!master->info)
+	if (!fsi->info)
 		return 0;
 
-	return is_porta ? master->info->porta_flags :
-		master->info->portb_flags;
-}
-
-static inline int fsi_stream_is_play(int stream)
-{
-	return stream == SNDRV_PCM_STREAM_PLAYBACK;
-}
-
-static inline int fsi_is_play(struct snd_pcm_substream *substream)
-{
-	return fsi_stream_is_play(substream->stream);
+	return fsi->info->flags;
 }
 
-static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi,
-						int is_play)
-{
-	return is_play ? &fsi->playback : &fsi->capture;
-}
-
-static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
+static u32 fsi_get_port_shift(struct fsi_priv *fsi, struct fsi_stream *io)
 {
+	int is_play = fsi_stream_is_play(fsi, io);
 	int is_porta = fsi_is_port_a(fsi);
 	u32 shift;
 
@@ -376,26 +409,81 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples)
 	return samples / fsi->chan_num;
 }
 
+static int fsi_get_current_fifo_samples(struct fsi_priv *fsi,
+					struct fsi_stream *io)
+{
+	int is_play = fsi_stream_is_play(fsi, io);
+	u32 status;
+	int frames;
+
+	status = is_play ?
+		fsi_reg_read(fsi, DOFF_ST) :
+		fsi_reg_read(fsi, DIFF_ST);
+
+	frames = 0x1ff & (status >> 8);
+
+	return fsi_frame2sample(fsi, frames);
+}
+
+static void fsi_count_fifo_err(struct fsi_priv *fsi)
+{
+	u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
+	u32 istatus = fsi_reg_read(fsi, DIFF_ST);
+
+	if (ostatus & ERR_OVER)
+		fsi->playback.oerr_num++;
+
+	if (ostatus & ERR_UNDER)
+		fsi->playback.uerr_num++;
+
+	if (istatus & ERR_OVER)
+		fsi->capture.oerr_num++;
+
+	if (istatus & ERR_UNDER)
+		fsi->capture.uerr_num++;
+
+	fsi_reg_write(fsi, DOFF_ST, 0);
+	fsi_reg_write(fsi, DIFF_ST, 0);
+}
+
+/*
+ *		fsi_stream_xx() function
+ */
+static inline int fsi_stream_is_play(struct fsi_priv *fsi,
+				     struct fsi_stream *io)
+{
+	return &fsi->playback == io;
+}
+
+static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi,
+					struct snd_pcm_substream *substream)
+{
+	return fsi_is_play(substream) ? &fsi->playback : &fsi->capture;
+}
+
 static int fsi_stream_is_working(struct fsi_priv *fsi,
-				  int is_play)
+				 struct fsi_stream *io)
 {
-	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
 	struct fsi_master *master = fsi_get_master(fsi);
 	unsigned long flags;
 	int ret;
 
 	spin_lock_irqsave(&master->lock, flags);
-	ret = !!io->substream;
+	ret = !!(io->substream && io->substream->runtime);
 	spin_unlock_irqrestore(&master->lock, flags);
 
 	return ret;
 }
 
-static void fsi_stream_push(struct fsi_priv *fsi,
-			    int is_play,
+static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io)
+{
+	return io->priv;
+}
+
+static void fsi_stream_init(struct fsi_priv *fsi,
+			    struct fsi_stream *io,
 			    struct snd_pcm_substream *substream)
 {
-	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct fsi_master *master = fsi_get_master(fsi);
 	unsigned long flags;
@@ -406,14 +494,15 @@ static void fsi_stream_push(struct fsi_priv *fsi,
 	io->buff_sample_pos	= 0;
 	io->period_samples	= fsi_frame2sample(fsi, runtime->period_size);
 	io->period_pos		= 0;
+	io->sample_width	= samples_to_bytes(runtime, 1);
 	io->oerr_num	= -1; /* ignore 1st err */
 	io->uerr_num	= -1; /* ignore 1st err */
+	fsi_stream_handler_call(io, init, fsi, io);
 	spin_unlock_irqrestore(&master->lock, flags);
 }
 
-static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
+static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
 	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
 	struct fsi_master *master = fsi_get_master(fsi);
 	unsigned long flags;
@@ -426,127 +515,87 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
 	if (io->uerr_num > 0)
 		dev_err(dai->dev, "under_run = %d\n", io->uerr_num);
 
+	fsi_stream_handler_call(io, quit, fsi, io);
 	io->substream	= NULL;
 	io->buff_sample_capa	= 0;
 	io->buff_sample_pos	= 0;
 	io->period_samples	= 0;
 	io->period_pos		= 0;
+	io->sample_width	= 0;
 	io->oerr_num	= 0;
 	io->uerr_num	= 0;
 	spin_unlock_irqrestore(&master->lock, flags);
 }
 
-static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play)
+static int fsi_stream_transfer(struct fsi_stream *io)
 {
-	u32 status;
-	int frames;
-
-	status = is_play ?
-		fsi_reg_read(fsi, DOFF_ST) :
-		fsi_reg_read(fsi, DIFF_ST);
-
-	frames = 0x1ff & (status >> 8);
-
-	return fsi_frame2sample(fsi, frames);
-}
-
-static void fsi_count_fifo_err(struct fsi_priv *fsi)
-{
-	u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
-	u32 istatus = fsi_reg_read(fsi, DIFF_ST);
-
-	if (ostatus & ERR_OVER)
-		fsi->playback.oerr_num++;
-
-	if (ostatus & ERR_UNDER)
-		fsi->playback.uerr_num++;
-
-	if (istatus & ERR_OVER)
-		fsi->capture.oerr_num++;
-
-	if (istatus & ERR_UNDER)
-		fsi->capture.uerr_num++;
+	struct fsi_priv *fsi = fsi_stream_to_priv(io);
+	if (!fsi)
+		return -EIO;
 
-	fsi_reg_write(fsi, DOFF_ST, 0);
-	fsi_reg_write(fsi, DIFF_ST, 0);
+	return fsi_stream_handler_call(io, transfer, fsi, io);
 }
 
-/*
- *		dma function
- */
+#define fsi_stream_start(fsi, io)\
+	fsi_stream_handler_call(io, start_stop, fsi, io, 1)
 
-static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream)
-{
-	int is_play = fsi_stream_is_play(stream);
-	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
-	struct snd_pcm_runtime *runtime = io->substream->runtime;
+#define fsi_stream_stop(fsi, io)\
+	fsi_stream_handler_call(io, start_stop, fsi, io, 0)
 
-	return runtime->dma_area +
-		samples_to_bytes(runtime, io->buff_sample_pos);
-}
-
-static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num)
+static int fsi_stream_probe(struct fsi_priv *fsi)
 {
-	u16 *start;
-	int i;
-
-	start  = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+	struct fsi_stream *io;
+	int ret1, ret2;
 
-	for (i = 0; i < num; i++)
-		fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8));
-}
-
-static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num)
-{
-	u16 *start;
-	int i;
+	io = &fsi->playback;
+	ret1 = fsi_stream_handler_call(io, probe, fsi, io);
 
-	start  = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
+	io = &fsi->capture;
+	ret2 = fsi_stream_handler_call(io, probe, fsi, io);
 
+	if (ret1 < 0)
+		return ret1;
+	if (ret2 < 0)
+		return ret2;
 
-	for (i = 0; i < num; i++)
-		*(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
+	return 0;
 }
 
-static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num)
+static int fsi_stream_remove(struct fsi_priv *fsi)
 {
-	u32 *start;
-	int i;
+	struct fsi_stream *io;
+	int ret1, ret2;
 
-	start  = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
-
-
-	for (i = 0; i < num; i++)
-		fsi_reg_write(fsi, DODT, *(start + i));
-}
+	io = &fsi->playback;
+	ret1 = fsi_stream_handler_call(io, remove, fsi, io);
 
-static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num)
-{
-	u32 *start;
-	int i;
+	io = &fsi->capture;
+	ret2 = fsi_stream_handler_call(io, remove, fsi, io);
 
-	start  = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
+	if (ret1 < 0)
+		return ret1;
+	if (ret2 < 0)
+		return ret2;
 
-	for (i = 0; i < num; i++)
-		*(start + i) = fsi_reg_read(fsi, DIDT);
+	return 0;
 }
 
 /*
  *		irq function
  */
 
-static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_enable(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+	u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
 	struct fsi_master *master = fsi_get_master(fsi);
 
 	fsi_core_mask_set(master, imsk,  data, data);
 	fsi_core_mask_set(master, iemsk, data, data);
 }
 
-static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_disable(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+	u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
 	struct fsi_master *master = fsi_get_master(fsi);
 
 	fsi_core_mask_set(master, imsk,  data, 0);
@@ -563,8 +612,8 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
 	u32 data = 0;
 	struct fsi_master *master = fsi_get_master(fsi);
 
-	data |= AB_IO(1, fsi_get_port_shift(fsi, 0));
-	data |= AB_IO(1, fsi_get_port_shift(fsi, 1));
+	data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback));
+	data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture));
 
 	/* clear interrupt factor */
 	fsi_core_mask_set(master, int_st, data, 0);
@@ -600,11 +649,14 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
 			      long rate, int enable)
 {
 	struct fsi_master *master = fsi_get_master(fsi);
-	set_rate_func set_rate = fsi_get_info_set_rate(master);
+	set_rate_func set_rate = fsi_get_info_set_rate(fsi);
 	int fsi_ver = master->core->ver;
 	int ret;
 
-	ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable);
+	if (!set_rate)
+		return 0;
+
+	ret = set_rate(dev, rate, enable);
 	if (ret < 0) /* error */
 		return ret;
 
@@ -671,96 +723,64 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
 	return ret;
 }
 
-#define fsi_port_start(f, i)	__fsi_port_clk_ctrl(f, i, 1)
-#define fsi_port_stop(f, i)	__fsi_port_clk_ctrl(f, i, 0)
-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable)
+/*
+ *		pio data transfer handler
+ */
+static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
 {
-	struct fsi_master *master = fsi_get_master(fsi);
-	u32 clk  = fsi_is_port_a(fsi) ? CRA  : CRB;
+	u16 *buf = (u16 *)_buf;
+	int i;
 
-	if (enable)
-		fsi_irq_enable(fsi, is_play);
-	else
-		fsi_irq_disable(fsi, is_play);
+	for (i = 0; i < samples; i++)
+		fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+}
 
-	if (fsi_is_clk_master(fsi))
-		fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+	u16 *buf = (u16 *)_buf;
+	int i;
+
+	for (i = 0; i < samples; i++)
+		*(buf + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
 }
 
-/*
- *		ctrl function
- */
-static void fsi_fifo_init(struct fsi_priv *fsi,
-			  int is_play,
-			  struct device *dev)
+static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int samples)
 {
-	struct fsi_master *master = fsi_get_master(fsi);
-	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
-	u32 shift, i;
-	int frame_capa;
+	u32 *buf = (u32 *)_buf;
+	int i;
 
-	/* get on-chip RAM capacity */
-	shift = fsi_master_read(master, FIFO_SZ);
-	shift >>= fsi_get_port_shift(fsi, is_play);
-	shift &= FIFO_SZ_MASK;
-	frame_capa = 256 << shift;
-	dev_dbg(dev, "fifo = %d words\n", frame_capa);
+	for (i = 0; i < samples; i++)
+		fsi_reg_write(fsi, DODT, *(buf + i));
+}
 
-	/*
-	 * The maximum number of sample data varies depending
-	 * on the number of channels selected for the format.
-	 *
-	 * FIFOs are used in 4-channel units in 3-channel mode
-	 * and in 8-channel units in 5- to 7-channel mode
-	 * meaning that more FIFOs than the required size of DPRAM
-	 * are used.
-	 *
-	 * ex) if 256 words of DP-RAM is connected
-	 * 1 channel:  256 (256 x 1 = 256)
-	 * 2 channels: 128 (128 x 2 = 256)
-	 * 3 channels:  64 ( 64 x 3 = 192)
-	 * 4 channels:  64 ( 64 x 4 = 256)
-	 * 5 channels:  32 ( 32 x 5 = 160)
-	 * 6 channels:  32 ( 32 x 6 = 192)
-	 * 7 channels:  32 ( 32 x 7 = 224)
-	 * 8 channels:  32 ( 32 x 8 = 256)
-	 */
-	for (i = 1; i < fsi->chan_num; i <<= 1)
-		frame_capa >>= 1;
-	dev_dbg(dev, "%d channel %d store\n",
-		fsi->chan_num, frame_capa);
+static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+	u32 *buf = (u32 *)_buf;
+	int i;
 
-	io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+	for (i = 0; i < samples; i++)
+		*(buf + i) = fsi_reg_read(fsi, DIDT);
+}
 
-	/*
-	 * set interrupt generation factor
-	 * clear FIFO
-	 */
-	if (is_play) {
-		fsi_reg_write(fsi,	DOFF_CTL, IRQ_HALF);
-		fsi_reg_mask_set(fsi,	DOFF_CTL, FIFO_CLR, FIFO_CLR);
-	} else {
-		fsi_reg_write(fsi,	DIFF_CTL, IRQ_HALF);
-		fsi_reg_mask_set(fsi,	DIFF_CTL, FIFO_CLR, FIFO_CLR);
-	}
+static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+	struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+	return runtime->dma_area +
+		samples_to_bytes(runtime, io->buff_sample_pos);
 }
 
-static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
+static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
+		void (*run16)(struct fsi_priv *fsi, u8 *buf, int samples),
+		void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples),
+		int samples)
 {
 	struct snd_pcm_runtime *runtime;
-	struct snd_pcm_substream *substream = NULL;
-	int is_play = fsi_stream_is_play(stream);
-	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
-	int sample_residues;
-	int sample_width;
-	int samples;
-	int samples_max;
+	struct snd_pcm_substream *substream;
+	u8 *buf;
 	int over_period;
-	void (*fn)(struct fsi_priv *fsi, int size);
 
-	if (!fsi			||
-	    !io->substream		||
-	    !io->substream->runtime)
+	if (!fsi_stream_is_working(fsi, io))
 		return -EINVAL;
 
 	over_period	= 0;
@@ -780,60 +800,19 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
 			io->buff_sample_pos = 0;
 	}
 
-	/* get 1 sample data width */
-	sample_width = samples_to_bytes(runtime, 1);
+	buf = fsi_pio_get_area(fsi, io);
 
-	/* get number of residue samples */
-	sample_residues = io->buff_sample_capa - io->buff_sample_pos;
-
-	if (is_play) {
-		/*
-		 * for play-back
-		 *
-		 * samples_max	: number of FSI fifo free samples space
-		 * samples	: number of ALSA residue samples
-		 */
-		samples_max  = io->fifo_sample_capa;
-		samples_max -= fsi_get_current_fifo_samples(fsi, is_play);
-
-		samples = sample_residues;
-
-		switch (sample_width) {
-		case 2:
-			fn = fsi_dma_soft_push16;
-			break;
-		case 4:
-			fn = fsi_dma_soft_push32;
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
-		/*
-		 * for capture
-		 *
-		 * samples_max	: number of ALSA free samples space
-		 * samples	: number of samples in FSI fifo
-		 */
-		samples_max = sample_residues;
-		samples     = fsi_get_current_fifo_samples(fsi, is_play);
-
-		switch (sample_width) {
-		case 2:
-			fn = fsi_dma_soft_pop16;
-			break;
-		case 4:
-			fn = fsi_dma_soft_pop32;
-			break;
-		default:
-			return -EINVAL;
-		}
+	switch (io->sample_width) {
+	case 2:
+		run16(fsi, buf, samples);
+		break;
+	case 4:
+		run32(fsi, buf, samples);
+		break;
+	default:
+		return -EINVAL;
 	}
 
-	samples = min(samples, samples_max);
-
-	fn(fsi, samples);
-
 	/* update buff_sample_pos */
 	io->buff_sample_pos += samples;
 
@@ -843,16 +822,66 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
 	return 0;
 }
 
-static int fsi_data_pop(struct fsi_priv *fsi)
+static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+	int sample_residues;	/* samples in FSI fifo */
+	int sample_space;	/* ALSA free samples space */
+	int samples;
+
+	sample_residues	= fsi_get_current_fifo_samples(fsi, io);
+	sample_space	= io->buff_sample_capa - io->buff_sample_pos;
+
+	samples = min(sample_residues, sample_space);
+
+	return fsi_pio_transfer(fsi, io,
+				  fsi_pio_pop16,
+				  fsi_pio_pop32,
+				  samples);
+}
+
+static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_CAPTURE);
+	int sample_residues;	/* ALSA residue samples */
+	int sample_space;	/* FSI fifo free samples space */
+	int samples;
+
+	sample_residues	= io->buff_sample_capa - io->buff_sample_pos;
+	sample_space	= io->fifo_sample_capa -
+		fsi_get_current_fifo_samples(fsi, io);
+
+	samples = min(sample_residues, sample_space);
+
+	return fsi_pio_transfer(fsi, io,
+				  fsi_pio_push16,
+				  fsi_pio_push32,
+				  samples);
 }
 
-static int fsi_data_push(struct fsi_priv *fsi)
+static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+			       int enable)
 {
-	return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+	struct fsi_master *master = fsi_get_master(fsi);
+	u32 clk  = fsi_is_port_a(fsi) ? CRA  : CRB;
+
+	if (enable)
+		fsi_irq_enable(fsi, io);
+	else
+		fsi_irq_disable(fsi, io);
+
+	if (fsi_is_clk_master(fsi))
+		fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
 }
 
+static struct fsi_stream_handler fsi_pio_push_handler = {
+	.transfer	= fsi_pio_push,
+	.start_stop	= fsi_pio_start_stop,
+};
+
+static struct fsi_stream_handler fsi_pio_pop_handler = {
+	.transfer	= fsi_pio_pop,
+	.start_stop	= fsi_pio_start_stop,
+};
+
 static irqreturn_t fsi_interrupt(int irq, void *data)
 {
 	struct fsi_master *master = data;
@@ -863,13 +892,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
 	fsi_master_mask_set(master, SOFT_RST, IR, IR);
 
 	if (int_st & AB_IO(1, AO_SHIFT))
-		fsi_data_push(&master->fsia);
+		fsi_stream_transfer(&master->fsia.playback);
 	if (int_st & AB_IO(1, BO_SHIFT))
-		fsi_data_push(&master->fsib);
+		fsi_stream_transfer(&master->fsib.playback);
 	if (int_st & AB_IO(1, AI_SHIFT))
-		fsi_data_pop(&master->fsia);
+		fsi_stream_transfer(&master->fsia.capture);
 	if (int_st & AB_IO(1, BI_SHIFT))
-		fsi_data_pop(&master->fsib);
+		fsi_stream_transfer(&master->fsib.capture);
 
 	fsi_count_fifo_err(&master->fsia);
 	fsi_count_fifo_err(&master->fsib);
@@ -880,12 +909,272 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+/*
+ *		dma data transfer handler
+ */
+static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+	struct snd_pcm_runtime *runtime = io->substream->runtime;
+	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+	enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+				DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+	io->dma = dma_map_single(dai->dev, runtime->dma_area,
+				 snd_pcm_lib_buffer_bytes(io->substream), dir);
+	return 0;
+}
+
+static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+	enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+		DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+	dma_unmap_single(dai->dev, io->dma,
+			 snd_pcm_lib_buffer_bytes(io->substream), dir);
+	return 0;
+}
+
+static void fsi_dma_complete(void *data)
+{
+	struct fsi_stream *io = (struct fsi_stream *)data;
+	struct fsi_priv *fsi = fsi_stream_to_priv(io);
+	struct snd_pcm_runtime *runtime = io->substream->runtime;
+	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+	enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+		DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+	dma_sync_single_for_cpu(dai->dev, io->dma,
+			samples_to_bytes(runtime, io->period_samples), dir);
+
+	io->buff_sample_pos += io->period_samples;
+	io->period_pos++;
+
+	if (io->period_pos >= runtime->periods) {
+		io->period_pos = 0;
+		io->buff_sample_pos = 0;
+	}
+
+	fsi_count_fifo_err(fsi);
+	fsi_stream_transfer(io);
+
+	snd_pcm_period_elapsed(io->substream);
+}
+
+static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
+{
+	struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+	return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
+}
+
+static void fsi_dma_do_tasklet(unsigned long data)
+{
+	struct fsi_stream *io = (struct fsi_stream *)data;
+	struct fsi_priv *fsi = fsi_stream_to_priv(io);
+	struct dma_chan *chan;
+	struct snd_soc_dai *dai;
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist sg;
+	struct snd_pcm_runtime *runtime;
+	enum dma_data_direction dir;
+	dma_cookie_t cookie;
+	int is_play = fsi_stream_is_play(fsi, io);
+	int len;
+	dma_addr_t buf;
+
+	if (!fsi_stream_is_working(fsi, io))
+		return;
+
+	dai	= fsi_get_dai(io->substream);
+	chan	= io->chan;
+	runtime	= io->substream->runtime;
+	dir	= is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+	len	= samples_to_bytes(runtime, io->period_samples);
+	buf	= fsi_dma_get_area(io);
+
+	dma_sync_single_for_device(dai->dev, io->dma, len, dir);
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
+		    len , offset_in_page(buf));
+	sg_dma_address(&sg) = buf;
+	sg_dma_len(&sg) = len;
+
+	desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir,
+						  DMA_PREP_INTERRUPT |
+						  DMA_CTRL_ACK);
+	if (!desc) {
+		dev_err(dai->dev, "device_prep_slave_sg() fail\n");
+		return;
+	}
+
+	desc->callback		= fsi_dma_complete;
+	desc->callback_param	= io;
+
+	cookie = desc->tx_submit(desc);
+	if (cookie < 0) {
+		dev_err(dai->dev, "tx_submit() fail\n");
+		return;
+	}
+
+	dma_async_issue_pending(chan);
+
+	/*
+	 * FIXME
+	 *
+	 * In DMAEngine case, codec and FSI cannot be started simultaneously
+	 * since FSI is using tasklet.
+	 * Therefore, in capture case, probably FSI FIFO will have got
+	 * overflow error in this point.
+	 * in that case, DMA cannot start transfer until error was cleared.
+	 */
+	if (!is_play) {
+		if (ERR_OVER & fsi_reg_read(fsi, DIFF_ST)) {
+			fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
+			fsi_reg_write(fsi, DIFF_ST, 0);
+		}
+	}
+}
+
+static bool fsi_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct sh_dmae_slave *slave = param;
+
+	chan->private = slave;
+
+	return true;
+}
+
+static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+	tasklet_schedule(&io->tasklet);
+
+	return 0;
+}
+
+static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+				 int start)
+{
+	u32 bws;
+	u32 dma;
+
+	switch (io->sample_width * start) {
+	case 2:
+		bws = CR_BWS_16;
+		dma = VDMD_STREAM | DMA_ON;
+		break;
+	case 4:
+		bws = CR_BWS_24;
+		dma = VDMD_BACK | DMA_ON;
+		break;
+	default:
+		bws = 0;
+		dma = 0;
+	}
+
+	fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
+	fsi_reg_write(fsi, OUT_DMAC, dma);
+}
+
+static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+	dma_cap_mask_t mask;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
+	if (!io->chan)
+		return -EIO;
+
+	tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
+
+	return 0;
+}
+
+static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+	tasklet_kill(&io->tasklet);
+
+	fsi_stream_stop(fsi, io);
+
+	if (io->chan)
+		dma_release_channel(io->chan);
+
+	io->chan = NULL;
+	return 0;
+}
+
+static struct fsi_stream_handler fsi_dma_push_handler = {
+	.init		= fsi_dma_init,
+	.quit		= fsi_dma_quit,
+	.probe		= fsi_dma_probe,
+	.transfer	= fsi_dma_transfer,
+	.remove		= fsi_dma_remove,
+	.start_stop	= fsi_dma_push_start_stop,
+};
+
 /*
  *		dai ops
  */
+static void fsi_fifo_init(struct fsi_priv *fsi,
+			  struct fsi_stream *io,
+			  struct device *dev)
+{
+	struct fsi_master *master = fsi_get_master(fsi);
+	int is_play = fsi_stream_is_play(fsi, io);
+	u32 shift, i;
+	int frame_capa;
+
+	/* get on-chip RAM capacity */
+	shift = fsi_master_read(master, FIFO_SZ);
+	shift >>= fsi_get_port_shift(fsi, io);
+	shift &= FIFO_SZ_MASK;
+	frame_capa = 256 << shift;
+	dev_dbg(dev, "fifo = %d words\n", frame_capa);
+
+	/*
+	 * The maximum number of sample data varies depending
+	 * on the number of channels selected for the format.
+	 *
+	 * FIFOs are used in 4-channel units in 3-channel mode
+	 * and in 8-channel units in 5- to 7-channel mode
+	 * meaning that more FIFOs than the required size of DPRAM
+	 * are used.
+	 *
+	 * ex) if 256 words of DP-RAM is connected
+	 * 1 channel:  256 (256 x 1 = 256)
+	 * 2 channels: 128 (128 x 2 = 256)
+	 * 3 channels:  64 ( 64 x 3 = 192)
+	 * 4 channels:  64 ( 64 x 4 = 256)
+	 * 5 channels:  32 ( 32 x 5 = 160)
+	 * 6 channels:  32 ( 32 x 6 = 192)
+	 * 7 channels:  32 ( 32 x 7 = 224)
+	 * 8 channels:  32 ( 32 x 8 = 256)
+	 */
+	for (i = 1; i < fsi->chan_num; i <<= 1)
+		frame_capa >>= 1;
+	dev_dbg(dev, "%d channel %d store\n",
+		fsi->chan_num, frame_capa);
+
+	io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+
+	/*
+	 * set interrupt generation factor
+	 * clear FIFO
+	 */
+	if (is_play) {
+		fsi_reg_write(fsi,	DOFF_CTL, IRQ_HALF);
+		fsi_reg_mask_set(fsi,	DOFF_CTL, FIFO_CLR, FIFO_CLR);
+	} else {
+		fsi_reg_write(fsi,	DIFF_CTL, IRQ_HALF);
+		fsi_reg_mask_set(fsi,	DIFF_CTL, FIFO_CLR, FIFO_CLR);
+	}
+}
 
 static int fsi_hw_startup(struct fsi_priv *fsi,
-			  int is_play,
+			  struct fsi_stream *io,
 			  struct device *dev)
 {
 	struct fsi_master *master = fsi_get_master(fsi);
@@ -934,17 +1223,16 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
 	}
 
 	/* irq clear */
-	fsi_irq_disable(fsi, is_play);
+	fsi_irq_disable(fsi, io);
 	fsi_irq_clear_status(fsi);
 
 	/* fifo init */
-	fsi_fifo_init(fsi, is_play, dev);
+	fsi_fifo_init(fsi, io, dev);
 
 	return 0;
 }
 
 static void fsi_hw_shutdown(struct fsi_priv *fsi,
-			    int is_play,
 			    struct device *dev)
 {
 	if (fsi_is_clk_master(fsi))
@@ -955,18 +1243,16 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 			   struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
-	int is_play = fsi_is_play(substream);
 
-	return fsi_hw_startup(fsi, is_play, dai->dev);
+	return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
 }
 
 static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
 			     struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
-	int is_play = fsi_is_play(substream);
 
-	fsi_hw_shutdown(fsi, is_play, dai->dev);
+	fsi_hw_shutdown(fsi, dai->dev);
 	fsi->rate = 0;
 }
 
@@ -974,18 +1260,19 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 			   struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
-	int is_play = fsi_is_play(substream);
+	struct fsi_stream *io = fsi_stream_get(fsi, substream);
 	int ret = 0;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		fsi_stream_push(fsi, is_play, substream);
-		ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
-		fsi_port_start(fsi, is_play);
+		fsi_stream_init(fsi, io, substream);
+		ret = fsi_stream_transfer(io);
+		if (0 == ret)
+			fsi_stream_start(fsi, io);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		fsi_port_stop(fsi, is_play);
-		fsi_stream_pop(fsi, is_play);
+		fsi_stream_stop(fsi, io);
+		fsi_stream_quit(fsi, io);
 		break;
 	}
 
@@ -1036,8 +1323,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
 static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
-	struct fsi_master *master = fsi_get_master(fsi);
-	set_rate_func set_rate = fsi_get_info_set_rate(master);
+	set_rate_func set_rate = fsi_get_info_set_rate(fsi);
 	u32 flags = fsi_get_info_flags(fsi);
 	int ret;
 
@@ -1151,7 +1437,7 @@ static int fsi_hw_free(struct snd_pcm_substream *substream)
 static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
-	struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
+	struct fsi_stream *io = fsi_stream_get(fsi, substream);
 
 	return fsi_sample2frame(fsi, io->buff_sample_pos);
 }
@@ -1239,11 +1525,24 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
 /*
  *		platform function
  */
+static void fsi_handler_init(struct fsi_priv *fsi)
+{
+	fsi->playback.handler	= &fsi_pio_push_handler; /* default PIO */
+	fsi->playback.priv	= fsi;
+	fsi->capture.handler	= &fsi_pio_pop_handler;  /* default PIO */
+	fsi->capture.priv	= fsi;
+
+	if (fsi->info->tx_id) {
+		fsi->playback.slave.slave_id	= fsi->info->tx_id;
+		fsi->playback.handler		= &fsi_dma_push_handler;
+	}
+}
 
 static int fsi_probe(struct platform_device *pdev)
 {
 	struct fsi_master *master;
 	const struct platform_device_id	*id_entry;
+	struct sh_fsi_platform_info *info = pdev->dev.platform_data;
 	struct resource *res;
 	unsigned int irq;
 	int ret;
@@ -1278,17 +1577,30 @@ static int fsi_probe(struct platform_device *pdev)
 
 	/* master setting */
 	master->irq		= irq;
-	master->info		= pdev->dev.platform_data;
 	master->core		= (struct fsi_core *)id_entry->driver_data;
 	spin_lock_init(&master->lock);
 
 	/* FSI A setting */
 	master->fsia.base	= master->base;
 	master->fsia.master	= master;
+	master->fsia.info	= &info->port_a;
+	fsi_handler_init(&master->fsia);
+	ret = fsi_stream_probe(&master->fsia);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "FSIA stream probe failed\n");
+		goto exit_iounmap;
+	}
 
 	/* FSI B setting */
 	master->fsib.base	= master->base + 0x40;
 	master->fsib.master	= master;
+	master->fsib.info	= &info->port_b;
+	fsi_handler_init(&master->fsib);
+	ret = fsi_stream_probe(&master->fsib);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "FSIB stream probe failed\n");
+		goto exit_fsia;
+	}
 
 	pm_runtime_enable(&pdev->dev);
 	dev_set_drvdata(&pdev->dev, master);
@@ -1297,7 +1609,7 @@ static int fsi_probe(struct platform_device *pdev)
 			  id_entry->name, master);
 	if (ret) {
 		dev_err(&pdev->dev, "irq request err\n");
-		goto exit_iounmap;
+		goto exit_fsib;
 	}
 
 	ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
@@ -1319,6 +1631,10 @@ static int fsi_probe(struct platform_device *pdev)
 	snd_soc_unregister_platform(&pdev->dev);
 exit_free_irq:
 	free_irq(irq, master);
+exit_fsib:
+	fsi_stream_remove(&master->fsib);
+exit_fsia:
+	fsi_stream_remove(&master->fsia);
 exit_iounmap:
 	iounmap(master->base);
 	pm_runtime_disable(&pdev->dev);
@@ -1341,6 +1657,9 @@ static int fsi_remove(struct platform_device *pdev)
 	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
 	snd_soc_unregister_platform(&pdev->dev);
 
+	fsi_stream_remove(&master->fsia);
+	fsi_stream_remove(&master->fsib);
+
 	iounmap(master->base);
 	kfree(master);
 
@@ -1348,30 +1667,29 @@ static int fsi_remove(struct platform_device *pdev)
 }
 
 static void __fsi_suspend(struct fsi_priv *fsi,
-			  int is_play,
+			  struct fsi_stream *io,
 			  struct device *dev)
 {
-	if (!fsi_stream_is_working(fsi, is_play))
+	if (!fsi_stream_is_working(fsi, io))
 		return;
 
-	fsi_port_stop(fsi, is_play);
-	fsi_hw_shutdown(fsi, is_play, dev);
+	fsi_stream_stop(fsi, io);
+	fsi_hw_shutdown(fsi, dev);
 }
 
 static void __fsi_resume(struct fsi_priv *fsi,
-			 int is_play,
+			 struct fsi_stream *io,
 			 struct device *dev)
 {
-	if (!fsi_stream_is_working(fsi, is_play))
+	if (!fsi_stream_is_working(fsi, io))
 		return;
 
-	fsi_hw_startup(fsi, is_play, dev);
+	fsi_hw_startup(fsi, io, dev);
 
 	if (fsi_is_clk_master(fsi) && fsi->rate)
 		fsi_set_master_clk(dev, fsi, fsi->rate, 1);
 
-	fsi_port_start(fsi, is_play);
-
+	fsi_stream_start(fsi, io);
 }
 
 static int fsi_suspend(struct device *dev)
@@ -1380,11 +1698,11 @@ static int fsi_suspend(struct device *dev)
 	struct fsi_priv *fsia = &master->fsia;
 	struct fsi_priv *fsib = &master->fsib;
 
-	__fsi_suspend(fsia, 1, dev);
-	__fsi_suspend(fsia, 0, dev);
+	__fsi_suspend(fsia, &fsia->playback, dev);
+	__fsi_suspend(fsia, &fsia->capture, dev);
 
-	__fsi_suspend(fsib, 1, dev);
-	__fsi_suspend(fsib, 0, dev);
+	__fsi_suspend(fsib, &fsib->playback, dev);
+	__fsi_suspend(fsib, &fsib->capture, dev);
 
 	return 0;
 }
@@ -1395,32 +1713,18 @@ static int fsi_resume(struct device *dev)
 	struct fsi_priv *fsia = &master->fsia;
 	struct fsi_priv *fsib = &master->fsib;
 
-	__fsi_resume(fsia, 1, dev);
-	__fsi_resume(fsia, 0, dev);
+	__fsi_resume(fsia, &fsia->playback, dev);
+	__fsi_resume(fsia, &fsia->capture, dev);
 
-	__fsi_resume(fsib, 1, dev);
-	__fsi_resume(fsib, 0, dev);
+	__fsi_resume(fsib, &fsib->playback, dev);
+	__fsi_resume(fsib, &fsib->capture, dev);
 
 	return 0;
 }
 
-static int fsi_runtime_nop(struct device *dev)
-{
-	/* Runtime PM callback shared between ->runtime_suspend()
-	 * and ->runtime_resume(). Simply returns success.
-	 *
-	 * This driver re-initializes all registers after
-	 * pm_runtime_get_sync() anyway so there is no need
-	 * to save and restore registers here.
-	 */
-	return 0;
-}
-
 static struct dev_pm_ops fsi_pm_ops = {
 	.suspend		= fsi_suspend,
 	.resume			= fsi_resume,
-	.runtime_suspend	= fsi_runtime_nop,
-	.runtime_resume		= fsi_runtime_nop,
 };
 
 static struct fsi_core fsi1_core = {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 92cee24ed2dcce7eb7b7e8de3a87f09d0ffe5138..a4deebc0801ab2e8ec5f3864b3cd1d1dc9aa7780 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -277,8 +277,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
 	codec->debugfs_codec_root = debugfs_create_dir(codec->name,
 						       debugfs_card_root);
 	if (!codec->debugfs_codec_root) {
-		printk(KERN_WARNING
-		       "ASoC: Failed to create codec debugfs directory\n");
+		dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
 		return;
 	}
 
@@ -291,8 +290,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
 						 codec->debugfs_codec_root,
 						 codec, &codec_reg_fops);
 	if (!codec->debugfs_reg)
-		printk(KERN_WARNING
-		       "ASoC: Failed to create codec register debugfs file\n");
+		dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
 
 	snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
 }
@@ -302,6 +300,27 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
 	debugfs_remove_recursive(codec->debugfs_codec_root);
 }
 
+static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+	struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
+
+	platform->debugfs_platform_root = debugfs_create_dir(platform->name,
+						       debugfs_card_root);
+	if (!platform->debugfs_platform_root) {
+		dev_warn(platform->dev,
+			"Failed to create platform debugfs directory\n");
+		return;
+	}
+
+	snd_soc_dapm_debugfs_init(&platform->dapm,
+		platform->debugfs_platform_root);
+}
+
+static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+	debugfs_remove_recursive(platform->debugfs_platform_root);
+}
+
 static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
 				    size_t count, loff_t *ppos)
 {
@@ -435,6 +454,14 @@ static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
 {
 }
 
+static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
+static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
 static inline void soc_init_card_debugfs(struct snd_soc_card *card)
 {
 }
@@ -546,18 +573,20 @@ int snd_soc_suspend(struct device *dev)
 	}
 
 	for (i = 0; i < card->num_rtd; i++) {
-		struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+		struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
 
 		if (card->rtd[i].dai_link->ignore_suspend)
 			continue;
 
-		if (driver->playback.stream_name != NULL)
-			snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
-				SND_SOC_DAPM_STREAM_SUSPEND);
+		snd_soc_dapm_stream_event(&card->rtd[i],
+					  SNDRV_PCM_STREAM_PLAYBACK,
+					  codec_dai,
+					  SND_SOC_DAPM_STREAM_SUSPEND);
 
-		if (driver->capture.stream_name != NULL)
-			snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
-				SND_SOC_DAPM_STREAM_SUSPEND);
+		snd_soc_dapm_stream_event(&card->rtd[i],
+					  SNDRV_PCM_STREAM_CAPTURE,
+					  codec_dai,
+					  SND_SOC_DAPM_STREAM_SUSPEND);
 	}
 
 	/* suspend all CODECs */
@@ -660,18 +689,18 @@ static void soc_resume_deferred(struct work_struct *work)
 	}
 
 	for (i = 0; i < card->num_rtd; i++) {
-		struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+		struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
 
 		if (card->rtd[i].dai_link->ignore_suspend)
 			continue;
 
-		if (driver->playback.stream_name != NULL)
-			snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
-				SND_SOC_DAPM_STREAM_RESUME);
+		snd_soc_dapm_stream_event(&card->rtd[i],
+					  SNDRV_PCM_STREAM_PLAYBACK, codec_dai,
+					  SND_SOC_DAPM_STREAM_RESUME);
 
-		if (driver->capture.stream_name != NULL)
-			snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
-				SND_SOC_DAPM_STREAM_RESUME);
+		snd_soc_dapm_stream_event(&card->rtd[i],
+					  SNDRV_PCM_STREAM_CAPTURE, codec_dai,
+					  SND_SOC_DAPM_STREAM_RESUME);
 	}
 
 	/* unmute any active DACs */
@@ -904,7 +933,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 		if (codec_dai->driver->remove) {
 			err = codec_dai->driver->remove(codec_dai);
 			if (err < 0)
-				printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);
+				pr_err("asoc: failed to remove %s: %d\n",
+							codec_dai->name, err);
 		}
 		codec_dai->probed = 0;
 		list_del(&codec_dai->card_list);
@@ -916,12 +946,14 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 		if (platform->driver->remove) {
 			err = platform->driver->remove(platform);
 			if (err < 0)
-				printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
+				pr_err("asoc: failed to remove %s: %d\n",
+							platform->name, err);
 		}
 
 		/* Make sure all DAPM widgets are freed */
 		snd_soc_dapm_free(&platform->dapm);
 
+		soc_cleanup_platform_debugfs(platform);
 		platform->probed = 0;
 		list_del(&platform->card_list);
 		module_put(platform->dev->driver->owner);
@@ -938,7 +970,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 		if (cpu_dai->driver->remove) {
 			err = cpu_dai->driver->remove(cpu_dai);
 			if (err < 0)
-				printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);
+				pr_err("asoc: failed to remove %s: %d\n",
+							cpu_dai->name, err);
 		}
 		cpu_dai->probed = 0;
 		list_del(&cpu_dai->card_list);
@@ -980,6 +1013,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
 {
 	int ret = 0;
 	const struct snd_soc_codec_driver *driver = codec->driver;
+	struct snd_soc_dai *dai;
 
 	codec->card = card;
 	codec->dapm.card = card;
@@ -994,6 +1028,14 @@ static int soc_probe_codec(struct snd_soc_card *card,
 		snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
 					  driver->num_dapm_widgets);
 
+	/* Create DAPM widgets for each DAI stream */
+	list_for_each_entry(dai, &dai_list, list) {
+		if (dai->dev != codec->dev)
+			continue;
+
+		snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
+	}
+
 	codec->dapm.idle_bias_off = driver->idle_bias_off;
 
 	if (driver->probe) {
@@ -1007,7 +1049,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
 	}
 
 	if (driver->controls)
-		snd_soc_add_controls(codec, driver->controls,
+		snd_soc_add_codec_controls(codec, driver->controls,
 				     driver->num_controls);
 	if (driver->dapm_routes)
 		snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes,
@@ -1039,6 +1081,8 @@ static int soc_probe_platform(struct snd_soc_card *card,
 	if (!try_module_get(platform->dev->driver->owner))
 		return -ENODEV;
 
+	soc_init_platform_debugfs(platform);
+
 	if (driver->dapm_widgets)
 		snd_soc_dapm_new_controls(&platform->dapm,
 			driver->dapm_widgets, driver->num_dapm_widgets);
@@ -1068,6 +1112,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
 	return 0;
 
 err_probe:
+	soc_cleanup_platform_debugfs(platform);
 	module_put(platform->dev->driver->owner);
 
 	return ret;
@@ -1183,8 +1228,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 		if (cpu_dai->driver->probe) {
 			ret = cpu_dai->driver->probe(cpu_dai);
 			if (ret < 0) {
-				printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
-						cpu_dai->name);
+				pr_err("asoc: failed to probe CPU DAI %s: %d\n",
+							cpu_dai->name, ret);
 				module_put(cpu_dai->dev->driver->owner);
 				return ret;
 			}
@@ -1215,8 +1260,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 		if (codec_dai->driver->probe) {
 			ret = codec_dai->driver->probe(codec_dai);
 			if (ret < 0) {
-				printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
-						codec_dai->name);
+				pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
+							codec_dai->name, ret);
 				return ret;
 			}
 		}
@@ -1236,12 +1281,13 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 
 	ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
 	if (ret < 0)
-		printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
+		pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
 
 	/* create the pcm */
 	ret = soc_new_pcm(rtd, num);
 	if (ret < 0) {
-		printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name);
+		pr_err("asoc: can't create pcm %s :%d\n",
+				dai_link->stream_name, ret);
 		return ret;
 	}
 
@@ -1274,7 +1320,7 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
 
 		ret = soc_ac97_dev_register(rtd->codec);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: AC97 device register failed\n");
+			pr_err("asoc: AC97 device register failed:%d\n", ret);
 			return ret;
 		}
 
@@ -1414,8 +1460,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 	ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
 			card->owner, 0, &card->snd_card);
 	if (ret < 0) {
-		printk(KERN_ERR "asoc: can't create sound card for card %s\n",
-			card->name);
+		pr_err("asoc: can't create sound card for card %s: %d\n",
+			card->name, ret);
 		mutex_unlock(&card->mutex);
 		return;
 	}
@@ -1468,13 +1514,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 		}
 	}
 
-	/* We should have a non-codec control add function but we don't */
+	snd_soc_dapm_link_dai_widgets(card);
+
 	if (card->controls)
-		snd_soc_add_controls(list_first_entry(&card->codec_dev_list,
-						      struct snd_soc_codec,
-						      card_list),
-				     card->controls,
-				     card->num_controls);
+		snd_soc_add_card_controls(card, card->controls, card->num_controls);
 
 	if (card->dapm_routes)
 		snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
@@ -1488,14 +1531,14 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 		if (dai_link->dai_fmt) {
 			ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
 						  dai_link->dai_fmt);
-			if (ret != 0)
+			if (ret != 0 && ret != -ENOTSUPP)
 				dev_warn(card->rtd[i].codec_dai->dev,
 					 "Failed to set DAI format: %d\n",
 					 ret);
 
 			ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
 						  dai_link->dai_fmt);
-			if (ret != 0)
+			if (ret != 0 && ret != -ENOTSUPP)
 				dev_warn(card->rtd[i].cpu_dai->dev,
 					 "Failed to set DAI format: %d\n",
 					 ret);
@@ -1538,7 +1581,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 
 	ret = snd_card_register(card->snd_card);
 	if (ret < 0) {
-		printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
+		pr_err("asoc: failed to register soundcard for %s: %d\n",
+							card->name, ret);
 		goto probe_aux_dev_err;
 	}
 
@@ -1547,7 +1591,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 	for (i = 0; i < card->num_rtd; i++) {
 		ret = soc_register_ac97_dai_link(&card->rtd[i]);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+			pr_err("asoc: failed to register AC97 %s: %d\n",
+							card->name, ret);
 			while (--i >= 0)
 				soc_unregister_ac97_dai_link(card->rtd[i].codec);
 			goto probe_aux_dev_err;
@@ -1600,6 +1645,10 @@ static int soc_probe(struct platform_device *pdev)
 	if (!card)
 		return -EINVAL;
 
+	dev_warn(&pdev->dev,
+		 "ASoC machine %s should use snd_soc_register_card()\n",
+		 card->name);
+
 	/* Bodge while we unpick instantiation */
 	card->dev = &pdev->dev;
 
@@ -1637,7 +1686,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
 
 	snd_soc_dapm_free(&card->dapm);
 
-	kfree(card->rtd);
 	snd_card_free(card->snd_card);
 	return 0;
 
@@ -1676,7 +1724,10 @@ EXPORT_SYMBOL_GPL(snd_soc_poweroff);
 const struct dev_pm_ops snd_soc_pm_ops = {
 	.suspend = snd_soc_suspend,
 	.resume = snd_soc_resume,
+	.freeze = snd_soc_suspend,
+	.thaw = snd_soc_resume,
 	.poweroff = snd_soc_poweroff,
+	.restore = snd_soc_resume,
 };
 EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
 
@@ -1880,23 +1931,28 @@ EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
 				unsigned int mask, unsigned int value)
 {
-	int change;
+	bool change;
 	unsigned int old, new;
 	int ret;
 
-	ret = snd_soc_read(codec, reg);
-	if (ret < 0)
-		return ret;
-
-	old = ret;
-	new = (old & ~mask) | (value & mask);
-	change = old != new;
-	if (change) {
-		ret = snd_soc_write(codec, reg, new);
+	if (codec->using_regmap) {
+		ret = regmap_update_bits_check(codec->control_data, reg,
+					       mask, value, &change);
+	} else {
+		ret = snd_soc_read(codec, reg);
 		if (ret < 0)
 			return ret;
+
+		old = ret;
+		new = (old & ~mask) | (value & mask);
+		change = old != new;
+		if (change)
+			ret = snd_soc_write(codec, reg, new);
 	}
 
+	if (ret < 0)
+		return ret;
+
 	return change;
 }
 EXPORT_SYMBOL_GPL(snd_soc_update_bits);
@@ -1987,7 +2043,7 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
  * Returns 0 for success, else error.
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
-				  void *data, char *long_name,
+				  void *data, const char *long_name,
 				  const char *prefix)
 {
 	struct snd_kcontrol_new template;
@@ -2022,9 +2078,28 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 }
 EXPORT_SYMBOL_GPL(snd_soc_cnew);
 
+static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
+	const struct snd_kcontrol_new *controls, int num_controls,
+	const char *prefix, void *data)
+{
+	int err, i;
+
+	for (i = 0; i < num_controls; i++) {
+		const struct snd_kcontrol_new *control = &controls[i];
+		err = snd_ctl_add(card, snd_soc_cnew(control, data,
+						     control->name, prefix));
+		if (err < 0) {
+			dev_err(dev, "Failed to add %s: %d\n", control->name, err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
 /**
- * snd_soc_add_controls - add an array of controls to a codec.
- * Convienience function to add a list of controls. Many codecs were
+ * snd_soc_add_codec_controls - add an array of controls to a codec.
+ * Convenience function to add a list of controls. Many codecs were
  * duplicating this code.
  *
  * @codec: codec to add controls to
@@ -2033,31 +2108,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
  *
  * Return 0 for success, else error.
  */
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
 	const struct snd_kcontrol_new *controls, int num_controls)
 {
 	struct snd_card *card = codec->card->snd_card;
-	int err, i;
-
-	for (i = 0; i < num_controls; i++) {
-		const struct snd_kcontrol_new *control = &controls[i];
-		err = snd_ctl_add(card, snd_soc_cnew(control, codec,
-						     control->name,
-						     codec->name_prefix));
-		if (err < 0) {
-			dev_err(codec->dev, "%s: Failed to add %s: %d\n",
-				codec->name, control->name, err);
-			return err;
-		}
-	}
 
-	return 0;
+	return snd_soc_add_controls(card, codec->dev, controls, num_controls,
+			codec->name_prefix, codec);
 }
-EXPORT_SYMBOL_GPL(snd_soc_add_controls);
+EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
 
 /**
  * snd_soc_add_platform_controls - add an array of controls to a platform.
- * Convienience function to add a list of controls.
+ * Convenience function to add a list of controls.
  *
  * @platform: platform to add controls to
  * @controls: array of controls to add
@@ -2069,22 +2132,52 @@ int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
 	const struct snd_kcontrol_new *controls, int num_controls)
 {
 	struct snd_card *card = platform->card->snd_card;
-	int err, i;
-
-	for (i = 0; i < num_controls; i++) {
-		const struct snd_kcontrol_new *control = &controls[i];
-		err = snd_ctl_add(card, snd_soc_cnew(control, platform,
-				control->name, NULL));
-		if (err < 0) {
-			dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
-			return err;
-		}
-	}
 
-	return 0;
+	return snd_soc_add_controls(card, platform->dev, controls, num_controls,
+			NULL, platform);
 }
 EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
 
+/**
+ * snd_soc_add_card_controls - add an array of controls to a SoC card.
+ * Convenience function to add a list of controls.
+ *
+ * @soc_card: SoC card to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+	const struct snd_kcontrol_new *controls, int num_controls)
+{
+	struct snd_card *card = soc_card->snd_card;
+
+	return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
+			NULL, soc_card);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
+
+/**
+ * snd_soc_add_dai_controls - add an array of controls to a DAI.
+ * Convienience function to add a list of controls.
+ *
+ * @dai: DAI to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
+	const struct snd_kcontrol_new *controls, int num_controls)
+{
+	struct snd_card *card = dai->card->snd_card;
+
+	return snd_soc_add_controls(card, dai->dev, controls, num_controls,
+			NULL, dai);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
+
 /**
  * snd_soc_info_enum_double - enumerated double mixer info callback
  * @kcontrol: mixer control
@@ -2651,6 +2744,115 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
 
+int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
+		       struct snd_ctl_elem_info *uinfo)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct soc_bytes *params = (void *)kcontrol->private_value;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+	uinfo->count = params->num_regs * codec->val_bytes;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
+
+int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_bytes *params = (void *)kcontrol->private_value;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int ret;
+
+	if (codec->using_regmap)
+		ret = regmap_raw_read(codec->control_data, params->base,
+				      ucontrol->value.bytes.data,
+				      params->num_regs * codec->val_bytes);
+	else
+		ret = -EINVAL;
+
+	/* Hide any masked bytes to ensure consistent data reporting */
+	if (ret == 0 && params->mask) {
+		switch (codec->val_bytes) {
+		case 1:
+			ucontrol->value.bytes.data[0] &= ~params->mask;
+			break;
+		case 2:
+			((u16 *)(&ucontrol->value.bytes.data))[0]
+				&= ~params->mask;
+			break;
+		case 4:
+			((u32 *)(&ucontrol->value.bytes.data))[0]
+				&= ~params->mask;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
+
+int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_bytes *params = (void *)kcontrol->private_value;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int ret, len;
+	unsigned int val;
+	void *data;
+
+	if (!codec->using_regmap)
+		return -EINVAL;
+
+	data = ucontrol->value.bytes.data;
+	len = params->num_regs * codec->val_bytes;
+
+	/*
+	 * If we've got a mask then we need to preserve the register
+	 * bits.  We shouldn't modify the incoming data so take a
+	 * copy.
+	 */
+	if (params->mask) {
+		ret = regmap_read(codec->control_data, params->base, &val);
+		if (ret != 0)
+			return ret;
+
+		val &= params->mask;
+
+		data = kmemdup(data, len, GFP_KERNEL);
+		if (!data)
+			return -ENOMEM;
+
+		switch (codec->val_bytes) {
+		case 1:
+			((u8 *)data)[0] &= ~params->mask;
+			((u8 *)data)[0] |= val;
+			break;
+		case 2:
+			((u16 *)data)[0] &= cpu_to_be16(~params->mask);
+			((u16 *)data)[0] |= cpu_to_be16(val);
+			break;
+		case 4:
+			((u32 *)data)[0] &= cpu_to_be32(~params->mask);
+			((u32 *)data)[0] |= cpu_to_be32(val);
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	ret = regmap_raw_write(codec->control_data, params->base,
+			       data, len);
+
+	if (params->mask)
+		kfree(data);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
+
 /**
  * snd_soc_dai_set_sysclk - configure DAI system or master clock.
  * @dai: DAI
@@ -2768,10 +2970,11 @@ EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
  */
 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-	if (dai->driver && dai->driver->ops->set_fmt)
-		return dai->driver->ops->set_fmt(dai, fmt);
-	else
+	if (dai->driver == NULL)
 		return -EINVAL;
+	if (dai->driver->ops->set_fmt == NULL)
+		return -ENOTSUPP;
+	return dai->driver->ops->set_fmt(dai, fmt);
 }
 EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
 
@@ -2875,7 +3078,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
 		 */
 		if (!!link->codec_name == !!link->codec_of_node) {
 			dev_err(card->dev,
-				"Neither/both codec name/of_node are set\n");
+				"Neither/both codec name/of_node are set for %s\n",
+				link->name);
 			return -EINVAL;
 		}
 
@@ -2885,7 +3089,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
 		 */
 		if (link->platform_name && link->platform_of_node) {
 			dev_err(card->dev,
-				"Both platform name/of_node are set\n");
+				"Both platform name/of_node are set for %s\n", link->name);
 			return -EINVAL;
 		}
 
@@ -2895,7 +3099,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
 		 */
 		if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) {
 			dev_err(card->dev,
-				"Neither/both cpu_dai name/of_node are set\n");
+				"Neither/both cpu_dai name/of_node are set for %s\n",
+				link->name);
 			return -EINVAL;
 		}
 	}
@@ -2906,9 +3111,10 @@ int snd_soc_register_card(struct snd_soc_card *card)
 
 	soc_init_card_debugfs(card);
 
-	card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) *
-			    (card->num_links + card->num_aux_devs),
-			    GFP_KERNEL);
+	card->rtd = devm_kzalloc(card->dev,
+				 sizeof(struct snd_soc_pcm_runtime) *
+				 (card->num_links + card->num_aux_devs),
+				 GFP_KERNEL);
 	if (card->rtd == NULL)
 		return -ENOMEM;
 	card->rtd_aux = &card->rtd[card->num_links];
@@ -3002,7 +3208,7 @@ static inline char *fmt_multiple_name(struct device *dev,
 		struct snd_soc_dai_driver *dai_drv)
 {
 	if (dai_drv->name == NULL) {
-		printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n",
+		pr_err("asoc: error - multiple DAI %s registered with no name\n",
 				dev_name(dev));
 		return NULL;
 	}
@@ -3177,6 +3383,7 @@ int snd_soc_register_platform(struct device *dev,
 	platform->dapm.dev = dev;
 	platform->dapm.platform = platform;
 	platform->dapm.stream_event = platform_drv->stream_event;
+	mutex_init(&platform->mutex);
 
 	mutex_lock(&client_mutex);
 	list_add(&platform->list, &platform_list);
@@ -3285,6 +3492,7 @@ int snd_soc_register_codec(struct device *dev,
 	codec->volatile_register = codec_drv->volatile_register;
 	codec->readable_register = codec_drv->readable_register;
 	codec->writable_register = codec_drv->writable_register;
+	codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time;
 	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
 	codec->dapm.dev = dev;
 	codec->dapm.codec = codec;
@@ -3473,8 +3681,7 @@ static int __init snd_soc_init(void)
 #ifdef CONFIG_DEBUG_FS
 	snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
 	if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
-		printk(KERN_WARNING
-		       "ASoC: Failed to create debugfs directory\n");
+		pr_warn("ASoC: Failed to create debugfs directory\n");
 		snd_soc_debugfs_root = NULL;
 	}
 
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1315663c1c0990787f226c8358700bce5e0d7963..6241490fff30e2e850e4be82e177bb6656ecfbc0 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -14,19 +14,13 @@
  *      dynamic configuration of codec internal audio paths and active
  *      DACs/ADCs.
  *    o Platform power domain - can support external components i.e. amps and
- *      mic/meadphone insertion events.
+ *      mic/headphone insertion events.
  *    o Automatic Mic Bias support
  *    o Jack insertion power event initiation - e.g. hp insertion will enable
  *      sinks, dacs, etc
- *    o Delayed powerdown of audio susbsystem to reduce pops between a quick
+ *    o Delayed power down of audio subsystem to reduce pops between a quick
  *      device reopen.
  *
- *  Todo:
- *    o DAPM power change sequencing - allow for configurable per
- *      codec sequences.
- *    o Support for analogue bias optimisation.
- *    o Support for reduced codec oversampling rates.
- *    o Support for reduced codec bias currents.
  */
 
 #include <linux/module.h>
@@ -40,6 +34,7 @@
 #include <linux/jiffies.h>
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -55,7 +50,9 @@
 static int dapm_up_seq[] = {
 	[snd_soc_dapm_pre] = 0,
 	[snd_soc_dapm_supply] = 1,
+	[snd_soc_dapm_regulator_supply] = 1,
 	[snd_soc_dapm_micbias] = 2,
+	[snd_soc_dapm_dai] = 3,
 	[snd_soc_dapm_aif_in] = 3,
 	[snd_soc_dapm_aif_out] = 3,
 	[snd_soc_dapm_mic] = 4,
@@ -90,6 +87,8 @@ static int dapm_down_seq[] = {
 	[snd_soc_dapm_value_mux] = 9,
 	[snd_soc_dapm_aif_in] = 10,
 	[snd_soc_dapm_aif_out] = 10,
+	[snd_soc_dapm_dai] = 10,
+	[snd_soc_dapm_regulator_supply] = 11,
 	[snd_soc_dapm_supply] = 11,
 	[snd_soc_dapm_post] = 12,
 };
@@ -172,6 +171,19 @@ static inline struct snd_soc_card *dapm_get_soc_card(
 	return NULL;
 }
 
+static void dapm_reset(struct snd_soc_card *card)
+{
+	struct snd_soc_dapm_widget *w;
+
+	memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
+
+	list_for_each_entry(w, &card->widgets, list) {
+		w->power_checked = false;
+		w->inputs = -1;
+		w->outputs = -1;
+	}
+}
+
 static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
 {
 	if (w->codec)
@@ -197,21 +209,28 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
 static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
 	unsigned short reg, unsigned int mask, unsigned int value)
 {
-	int change;
+	bool change;
 	unsigned int old, new;
 	int ret;
 
-	ret = soc_widget_read(w, reg);
-	if (ret < 0)
-		return ret;
-
-	old = ret;
-	new = (old & ~mask) | (value & mask);
-	change = old != new;
-	if (change) {
-		ret = soc_widget_write(w, reg, new);
+	if (w->codec && w->codec->using_regmap) {
+		ret = regmap_update_bits_check(w->codec->control_data,
+					       reg, mask, value, &change);
+		if (ret != 0)
+			return ret;
+	} else {
+		ret = soc_widget_read(w, reg);
 		if (ret < 0)
 			return ret;
+
+		old = ret;
+		new = (old & ~mask) | (value & mask);
+		change = old != new;
+		if (change) {
+			ret = soc_widget_write(w, reg, new);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	return change;
@@ -345,8 +364,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 	case snd_soc_dapm_micbias:
 	case snd_soc_dapm_vmid:
 	case snd_soc_dapm_supply:
+	case snd_soc_dapm_regulator_supply:
 	case snd_soc_dapm_aif_in:
 	case snd_soc_dapm_aif_out:
+	case snd_soc_dapm_dai:
 	case snd_soc_dapm_hp:
 	case snd_soc_dapm_mic:
 	case snd_soc_dapm_spk:
@@ -504,17 +525,17 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
 				 * for widgets so cut the prefix off
 				 * the front of the widget name.
 				 */
-				snprintf(path->long_name, name_len, "%s %s",
-					 w->name + prefix_len,
+				snprintf((char *)path->long_name, name_len,
+					 "%s %s", w->name + prefix_len,
 					 w->kcontrol_news[i].name);
 				break;
 			case snd_soc_dapm_mixer_named_ctl:
-				snprintf(path->long_name, name_len, "%s",
-					 w->kcontrol_news[i].name);
+				snprintf((char *)path->long_name, name_len,
+					 "%s", w->kcontrol_news[i].name);
 				break;
 			}
 
-			path->long_name[name_len - 1] = '\0';
+			((char *)path->long_name)[name_len - 1] = '\0';
 
 			path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
 						      wlist, path->long_name,
@@ -548,7 +569,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
 	struct snd_soc_dapm_widget_list *wlist;
 	int shared, wlistentries;
 	size_t wlistsize;
-	char *name;
+	const char *name;
 
 	if (w->num_kcontrols != 1) {
 		dev_err(dapm->dev,
@@ -673,12 +694,18 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
 
 	DAPM_UPDATE_STAT(widget, path_checks);
 
-	if (widget->id == snd_soc_dapm_supply)
+	switch (widget->id) {
+	case snd_soc_dapm_supply:
+	case snd_soc_dapm_regulator_supply:
 		return 0;
+	default:
+		break;
+	}
 
 	switch (widget->id) {
 	case snd_soc_dapm_adc:
 	case snd_soc_dapm_aif_out:
+	case snd_soc_dapm_dai:
 		if (widget->active) {
 			widget->outputs = snd_soc_dapm_suspend_check(widget);
 			return widget->outputs;
@@ -738,13 +765,19 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
 
 	DAPM_UPDATE_STAT(widget, path_checks);
 
-	if (widget->id == snd_soc_dapm_supply)
+	switch (widget->id) {
+	case snd_soc_dapm_supply:
+	case snd_soc_dapm_regulator_supply:
 		return 0;
+	default:
+		break;
+	}
 
 	/* active stream ? */
 	switch (widget->id) {
 	case snd_soc_dapm_dac:
 	case snd_soc_dapm_aif_in:
+	case snd_soc_dapm_dai:
 		if (widget->active) {
 			widget->inputs = snd_soc_dapm_suspend_check(widget);
 			return widget->inputs;
@@ -821,6 +854,19 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
 }
 EXPORT_SYMBOL_GPL(dapm_reg_event);
 
+/*
+ * Handler for regulator supply widget.
+ */
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+		   struct snd_kcontrol *kcontrol, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		return regulator_enable(w->priv);
+	else
+		return regulator_disable_deferred(w->priv, w->shift);
+}
+EXPORT_SYMBOL_GPL(dapm_regulator_event);
+
 static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
 {
 	if (w->power_checked)
@@ -851,6 +897,13 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
 	return out != 0 && in != 0;
 }
 
+static int dapm_dai_check_power(struct snd_soc_dapm_widget *w)
+{
+	DAPM_UPDATE_STAT(w, power_checks);
+
+	return w->active;
+}
+
 /* Check to see if an ADC has power */
 static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
 {
@@ -1251,7 +1304,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
 			dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
 
 		if (d->dev)
-			pm_runtime_put_sync(d->dev);
+			pm_runtime_put(d->dev);
 	}
 
 	/* If we just powered up then move to active bias */
@@ -1301,6 +1354,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
 	}
 	switch (w->id) {
 	case snd_soc_dapm_supply:
+	case snd_soc_dapm_regulator_supply:
 		/* Supplies can't affect their outputs, only their inputs */
 		break;
 	default:
@@ -1373,13 +1427,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 		}
 	}
 
-	memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
-
-	list_for_each_entry(w, &card->widgets, list) {
-		w->power_checked = false;
-		w->inputs = -1;
-		w->outputs = -1;
-	}
+	dapm_reset(card);
 
 	/* Check which widgets we need to power and store them in
 	 * lists indicating if they should be powered up or down.  We
@@ -1400,10 +1448,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 			/* Supplies and micbiases only bring the
 			 * context up to STANDBY as unless something
 			 * else is active and passing audio they
-			 * generally don't require full power.
+			 * generally don't require full power.  Signal
+			 * generators are virtual pins and have no
+			 * power impact themselves.
 			 */
 			switch (w->id) {
+			case snd_soc_dapm_siggen:
+				break;
 			case snd_soc_dapm_supply:
+			case snd_soc_dapm_regulator_supply:
 			case snd_soc_dapm_micbias:
 				if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
 					d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1475,6 +1528,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 					&async_domain);
 	async_synchronize_full_domain(&async_domain);
 
+	/* do we need to notify any clients that DAPM event is complete */
+	list_for_each_entry(d, &card->dapm_list, list) {
+		if (d->stream_event)
+			d->stream_event(d, event);
+	}
+
 	pop_dbg(dapm->dev, card->pop_time,
 		"DAPM sequencing finished, waiting %dms\n", card->pop_time);
 	pop_wait(card->pop_time);
@@ -1510,8 +1569,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 	out = is_connected_output_ep(w);
 	dapm_clear_walk(w->dapm);
 
-	ret = snprintf(buf, PAGE_SIZE, "%s: %s  in %d out %d",
-		       w->name, w->power ? "On" : "Off", in, out);
+	ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
+		       w->name, w->power ? "On" : "Off",
+		       w->force ? " (forced)" : "", in, out);
 
 	if (w->reg >= 0)
 		ret += snprintf(buf + ret, PAGE_SIZE - ret,
@@ -1607,7 +1667,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
 	dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
 
 	if (!dapm->debugfs_dapm) {
-		printk(KERN_WARNING
+		dev_warn(dapm->dev,
 		       "Failed to create DAPM debugfs directory\n");
 		return;
 	}
@@ -1659,9 +1719,8 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
 #endif
 
 /* test and update the power status of a mux widget */
-static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
-				 struct snd_kcontrol *kcontrol, int change,
-				 int mux, struct soc_enum *e)
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+				 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
 {
 	struct snd_soc_dapm_path *path;
 	int found = 0;
@@ -1671,9 +1730,6 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 	    widget->id != snd_soc_dapm_value_mux)
 		return -ENODEV;
 
-	if (!change)
-		return 0;
-
 	/* find dapm widget path assoc with kcontrol */
 	list_for_each_entry(path, &widget->dapm->card->paths, list) {
 		if (path->kcontrol != kcontrol)
@@ -1702,9 +1758,10 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
 
 /* test and update the power status of a mixer or switch widget */
-static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
 				   struct snd_kcontrol *kcontrol, int connect)
 {
 	struct snd_soc_dapm_path *path;
@@ -1733,6 +1790,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
 
 /* show dapm widget status in sys fs */
 static ssize_t dapm_widget_show(struct device *dev,
@@ -1762,6 +1820,7 @@ static ssize_t dapm_widget_show(struct device *dev,
 		case snd_soc_dapm_mixer:
 		case snd_soc_dapm_mixer_named_ctl:
 		case snd_soc_dapm_supply:
+		case snd_soc_dapm_regulator_supply:
 			if (w->name)
 				count += sprintf(buf + count, "%s: %s\n",
 					w->name, w->power ? "On":"Off");
@@ -1869,10 +1928,12 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
 		return -EINVAL;
 	}
 
+	if (w->connected != status)
+		dapm_mark_dirty(w, "pin configuration");
+
 	w->connected = status;
 	if (status == 0)
 		w->force = 0;
-	dapm_mark_dirty(w, "pin configuration");
 
 	return 0;
 }
@@ -2000,8 +2061,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
 	case snd_soc_dapm_pre:
 	case snd_soc_dapm_post:
 	case snd_soc_dapm_supply:
+	case snd_soc_dapm_regulator_supply:
 	case snd_soc_dapm_aif_in:
 	case snd_soc_dapm_aif_out:
+	case snd_soc_dapm_dai:
 		list_add(&path->list, &dapm->card->paths);
 		list_add(&path->list_sink, &wsink->sources);
 		list_add(&path->list_source, &wsource->sinks);
@@ -2315,7 +2378,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 			update.val = val;
 			widget->dapm->update = &update;
 
-			dapm_mixer_update_power(widget, kcontrol, connect);
+			snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
 
 			widget->dapm->update = NULL;
 		}
@@ -2406,7 +2469,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 			update.val = val;
 			widget->dapm->update = &update;
 
-			dapm_mux_update_power(widget, kcontrol, change, mux, e);
+			snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
 
 			widget->dapm->update = NULL;
 		}
@@ -2467,8 +2530,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
 
 			widget->value = ucontrol->value.enumerated.item[0];
 
-			dapm_mux_update_power(widget, kcontrol, change,
-					      widget->value, e);
+			snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
 		}
 	}
 
@@ -2571,7 +2633,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
 			update.val = val;
 			widget->dapm->update = &update;
 
-			dapm_mux_update_power(widget, kcontrol, change, mux, e);
+			snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
 
 			widget->dapm->update = NULL;
 		}
@@ -2611,15 +2673,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 	const char *pin = (const char *)kcontrol->private_value;
 
-	mutex_lock(&codec->mutex);
+	mutex_lock(&card->mutex);
 
 	ucontrol->value.integer.value[0] =
-		snd_soc_dapm_get_pin_status(&codec->dapm, pin);
+		snd_soc_dapm_get_pin_status(&card->dapm, pin);
 
-	mutex_unlock(&codec->mutex);
+	mutex_unlock(&card->mutex);
 
 	return 0;
 }
@@ -2634,41 +2696,48 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 	const char *pin = (const char *)kcontrol->private_value;
 
-	mutex_lock(&codec->mutex);
+	mutex_lock(&card->mutex);
 
 	if (ucontrol->value.integer.value[0])
-		snd_soc_dapm_enable_pin(&codec->dapm, pin);
+		snd_soc_dapm_enable_pin(&card->dapm, pin);
 	else
-		snd_soc_dapm_disable_pin(&codec->dapm, pin);
+		snd_soc_dapm_disable_pin(&card->dapm, pin);
 
-	snd_soc_dapm_sync(&codec->dapm);
+	snd_soc_dapm_sync(&card->dapm);
 
-	mutex_unlock(&codec->mutex);
+	mutex_unlock(&card->mutex);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
 
-/**
- * snd_soc_dapm_new_control - create new dapm control
- * @dapm: DAPM context
- * @widget: widget template
- *
- * Creates a new dapm control based upon the template.
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
-	const struct snd_soc_dapm_widget *widget)
+static struct snd_soc_dapm_widget *
+snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
+			 const struct snd_soc_dapm_widget *widget)
 {
 	struct snd_soc_dapm_widget *w;
 	size_t name_len;
+	int ret;
 
 	if ((w = dapm_cnew_widget(widget)) == NULL)
-		return -ENOMEM;
+		return NULL;
+
+	switch (w->id) {
+	case snd_soc_dapm_regulator_supply:
+		w->priv = devm_regulator_get(dapm->dev, w->name);
+		if (IS_ERR(w->priv)) {
+			ret = PTR_ERR(w->priv);
+			dev_err(dapm->dev, "Failed to request %s: %d\n",
+				w->name, ret);
+			return NULL;
+		}
+		break;
+	default:
+		break;
+	}
 
 	name_len = strlen(widget->name) + 1;
 	if (dapm->codec && dapm->codec->name_prefix)
@@ -2676,13 +2745,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 	w->name = kmalloc(name_len, GFP_KERNEL);
 	if (w->name == NULL) {
 		kfree(w);
-		return -ENOMEM;
+		return NULL;
 	}
 	if (dapm->codec && dapm->codec->name_prefix)
-		snprintf(w->name, name_len, "%s %s",
+		snprintf((char *)w->name, name_len, "%s %s",
 			dapm->codec->name_prefix, widget->name);
 	else
-		snprintf(w->name, name_len, "%s", widget->name);
+		snprintf((char *)w->name, name_len, "%s", widget->name);
 
 	switch (w->id) {
 	case snd_soc_dapm_switch:
@@ -2715,8 +2784,12 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 		w->power_check = dapm_generic_check_power;
 		break;
 	case snd_soc_dapm_supply:
+	case snd_soc_dapm_regulator_supply:
 		w->power_check = dapm_supply_check_power;
 		break;
+	case snd_soc_dapm_dai:
+		w->power_check = dapm_dai_check_power;
+		break;
 	default:
 		w->power_check = dapm_always_on_check_power;
 		break;
@@ -2734,9 +2807,8 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 
 	/* machine layer set ups unconnected pins and insertions */
 	w->connected = 1;
-	return 0;
+	return w;
 }
-EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
 
 /**
  * snd_soc_dapm_new_controls - create new dapm controls
@@ -2752,15 +2824,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
 	const struct snd_soc_dapm_widget *widget,
 	int num)
 {
-	int i, ret;
+	struct snd_soc_dapm_widget *w;
+	int i;
 
 	for (i = 0; i < num; i++) {
-		ret = snd_soc_dapm_new_control(dapm, widget);
-		if (ret < 0) {
+		w = snd_soc_dapm_new_control(dapm, widget);
+		if (!w) {
 			dev_err(dapm->dev,
-				"ASoC: Failed to create DAPM control %s: %d\n",
-				widget->name, ret);
-			return ret;
+				"ASoC: Failed to create DAPM control %s\n",
+				widget->name);
+			return -ENOMEM;
 		}
 		widget++;
 	}
@@ -2768,40 +2841,140 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
 
-static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
-	const char *stream, int event)
+int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
+				 struct snd_soc_dai *dai)
 {
+	struct snd_soc_dapm_widget template;
 	struct snd_soc_dapm_widget *w;
 
-	list_for_each_entry(w, &dapm->card->widgets, list)
-	{
-		if (!w->sname || w->dapm != dapm)
+	WARN_ON(dapm->dev != dai->dev);
+
+	memset(&template, 0, sizeof(template));
+	template.reg = SND_SOC_NOPM;
+
+	if (dai->driver->playback.stream_name) {
+		template.id = snd_soc_dapm_dai;
+		template.name = dai->driver->playback.stream_name;
+		template.sname = dai->driver->playback.stream_name;
+
+		dev_dbg(dai->dev, "adding %s widget\n",
+			template.name);
+
+		w = snd_soc_dapm_new_control(dapm, &template);
+		if (!w) {
+			dev_err(dapm->dev, "Failed to create %s widget\n",
+				dai->driver->playback.stream_name);
+		}
+
+		w->priv = dai;
+		dai->playback_widget = w;
+	}
+
+	if (dai->driver->capture.stream_name) {
+		template.id = snd_soc_dapm_dai;
+		template.name = dai->driver->capture.stream_name;
+		template.sname = dai->driver->capture.stream_name;
+
+		dev_dbg(dai->dev, "adding %s widget\n",
+			template.name);
+
+		w = snd_soc_dapm_new_control(dapm, &template);
+		if (!w) {
+			dev_err(dapm->dev, "Failed to create %s widget\n",
+				dai->driver->capture.stream_name);
+		}
+
+		w->priv = dai;
+		dai->capture_widget = w;
+	}
+
+	return 0;
+}
+
+int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
+{
+	struct snd_soc_dapm_widget *dai_w, *w;
+	struct snd_soc_dai *dai;
+	struct snd_soc_dapm_route r;
+
+	memset(&r, 0, sizeof(r));
+
+	/* For each DAI widget... */
+	list_for_each_entry(dai_w, &card->widgets, list) {
+		if (dai_w->id != snd_soc_dapm_dai)
 			continue;
-		dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
-			w->name, w->sname, stream, event);
-		if (strstr(w->sname, stream)) {
-			dapm_mark_dirty(w, "stream event");
-			switch(event) {
-			case SND_SOC_DAPM_STREAM_START:
-				w->active = 1;
-				break;
-			case SND_SOC_DAPM_STREAM_STOP:
-				w->active = 0;
-				break;
-			case SND_SOC_DAPM_STREAM_SUSPEND:
-			case SND_SOC_DAPM_STREAM_RESUME:
-			case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
-			case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
-				break;
+
+		dai = dai_w->priv;
+
+		/* ...find all widgets with the same stream and link them */
+		list_for_each_entry(w, &card->widgets, list) {
+			if (w->dapm != dai_w->dapm)
+				continue;
+
+			if (w->id == snd_soc_dapm_dai)
+				continue;
+
+			if (!w->sname)
+				continue;
+
+			if (dai->driver->playback.stream_name &&
+			    strstr(w->sname,
+				   dai->driver->playback.stream_name)) {
+				r.source = dai->playback_widget->name;
+				r.sink = w->name;
+				dev_dbg(dai->dev, "%s -> %s\n",
+					 r.source, r.sink);
+
+				snd_soc_dapm_add_route(w->dapm, &r);
+			}
+
+			if (dai->driver->capture.stream_name &&
+			    strstr(w->sname,
+				   dai->driver->capture.stream_name)) {
+				r.source = w->name;
+				r.sink = dai->capture_widget->name;
+				dev_dbg(dai->dev, "%s -> %s\n",
+					r.source, r.sink);
+
+				snd_soc_dapm_add_route(w->dapm, &r);
 			}
 		}
 	}
 
-	dapm_power_widgets(dapm, event);
+	return 0;
+}
 
-	/* do we need to notify any clients that DAPM stream is complete */
-	if (dapm->stream_event)
-		dapm->stream_event(dapm, event);
+static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
+				  int stream, struct snd_soc_dai *dai,
+				  int event)
+{
+	struct snd_soc_dapm_widget *w;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+		w = dai->playback_widget;
+	else
+		w = dai->capture_widget;
+
+	if (!w)
+		return;
+
+	dapm_mark_dirty(w, "stream event");
+
+	switch (event) {
+	case SND_SOC_DAPM_STREAM_START:
+		w->active = 1;
+		break;
+	case SND_SOC_DAPM_STREAM_STOP:
+		w->active = 0;
+		break;
+	case SND_SOC_DAPM_STREAM_SUSPEND:
+	case SND_SOC_DAPM_STREAM_RESUME:
+	case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+	case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+		break;
+	}
+
+	dapm_power_widgets(dapm, event);
 }
 
 /**
@@ -2815,16 +2988,13 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
  *
  * Returns 0 for success else error.
  */
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
-	const char *stream, int event)
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+			      struct snd_soc_dai *dai, int event)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 
-	if (stream == NULL)
-		return 0;
-
 	mutex_lock(&codec->mutex);
-	soc_dapm_stream_event(&codec->dapm, stream, event);
+	soc_dapm_stream_event(&codec->dapm, stream, dai, event);
 	mutex_unlock(&codec->mutex);
 	return 0;
 }
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
new file mode 100644
index 0000000000000000000000000000000000000000..4420b7030c837a477eb8d143c0d8ec99b7d64913
--- /dev/null
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -0,0 +1,288 @@
+/*
+ *  Copyright (C) 2012, Analog Devices Inc.
+ *	Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  Based on:
+ *	imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *	mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *	ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *		      Copyright (C) 2006 Applied Data Systems
+ *
+ *  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.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dmaengine.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <sound/dmaengine_pcm.h>
+
+struct dmaengine_pcm_runtime_data {
+	struct dma_chan *dma_chan;
+
+	unsigned int pos;
+
+	void *data;
+};
+
+static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
+	const struct snd_pcm_substream *substream)
+{
+	return substream->runtime->private_data;
+}
+
+/**
+ * snd_dmaengine_pcm_set_data - Set dmaengine substream private data
+ * @substream: PCM substream
+ * @data: Data to set
+ */
+void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data)
+{
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+	prtd->data = data;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data);
+
+/**
+ * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data
+ * @substream: PCM substream
+ *
+ * Returns the data previously set with snd_dmaengine_pcm_set_data
+ */
+void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream)
+{
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+	return prtd->data;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data);
+
+struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
+{
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+	return prtd->dma_chan;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan);
+
+/**
+ * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config
+ * @substream: PCM substream
+ * @params: hw_params
+ * @slave_config: DMA slave config
+ *
+ * This function can be used to initialize a dma_slave_config from a substream
+ * and hw_params in a dmaengine based PCM driver implementation.
+ */
+int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
+	const struct snd_pcm_hw_params *params,
+	struct dma_slave_config *slave_config)
+{
+	enum dma_slave_buswidth buswidth;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+	case SNDRV_PCM_FORMAT_S20_3LE:
+	case SNDRV_PCM_FORMAT_S24_LE:
+	case SNDRV_PCM_FORMAT_S32_LE:
+		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		slave_config->direction = DMA_MEM_TO_DEV;
+		slave_config->dst_addr_width = buswidth;
+	} else {
+		slave_config->direction = DMA_DEV_TO_MEM;
+		slave_config->src_addr_width = buswidth;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
+
+static void dmaengine_pcm_dma_complete(void *arg)
+{
+	struct snd_pcm_substream *substream = arg;
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+	prtd->pos += snd_pcm_lib_period_bytes(substream);
+	if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
+		prtd->pos = 0;
+
+	snd_pcm_period_elapsed(substream);
+}
+
+static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
+{
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+	struct dma_chan *chan = prtd->dma_chan;
+	struct dma_async_tx_descriptor *desc;
+	enum dma_transfer_direction direction;
+
+	direction = snd_pcm_substream_to_dma_direction(substream);
+
+	prtd->pos = 0;
+	desc = chan->device->device_prep_dma_cyclic(chan,
+		substream->runtime->dma_addr,
+		snd_pcm_lib_buffer_bytes(substream),
+		snd_pcm_lib_period_bytes(substream), direction);
+
+	if (!desc)
+		return -ENOMEM;
+
+	desc->callback = dmaengine_pcm_dma_complete;
+	desc->callback_param = substream;
+	dmaengine_submit(desc);
+
+	return 0;
+}
+
+/**
+ * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation
+ * @substream: PCM substream
+ * @cmd: Trigger command
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function can be used as the PCM trigger callback for dmaengine based PCM
+ * driver implementations.
+ */
+int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+	int ret;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		ret = dmaengine_pcm_prepare_and_submit(substream);
+		if (ret)
+			return ret;
+		dma_async_issue_pending(prtd->dma_chan);
+		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		dmaengine_resume(prtd->dma_chan);
+		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		dmaengine_pause(prtd->dma_chan);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		dmaengine_terminate_all(prtd->dma_chan);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
+
+/**
+ * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation
+ * @substream: PCM substream
+ *
+ * This function can be used as the PCM pointer callback for dmaengine based PCM
+ * driver implementations.
+ */
+snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+	return bytes_to_frames(substream->runtime, prtd->pos);
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
+
+static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd,
+	dma_filter_fn filter_fn, void *filter_data)
+{
+	dma_cap_mask_t mask;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+	prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data);
+
+	if (!prtd->dma_chan)
+		return -ENXIO;
+
+	return 0;
+}
+
+/**
+ * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
+ * @substream: PCM substream
+ * @filter_fn: Filter function used to request the DMA channel
+ * @filter_data: Data passed to the DMA filter function
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function will request a DMA channel using the passed filter function and
+ * data. The function should usually be called from the pcm open callback.
+ *
+ * Note that this function will use private_data field of the substream's
+ * runtime. So it is not availabe to your pcm driver implementation. If you need
+ * to keep additional data attached to a substream use
+ * snd_dmaeinge_pcm_{set,get}_data.
+ */
+int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
+	dma_filter_fn filter_fn, void *filter_data)
+{
+	struct dmaengine_pcm_runtime_data *prtd;
+	int ret;
+
+	ret = snd_pcm_hw_constraint_integer(substream->runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		return ret;
+
+	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+	if (!prtd)
+		return -ENOMEM;
+
+	ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data);
+	if (ret < 0) {
+		kfree(prtd);
+		return ret;
+	}
+
+	substream->runtime->private_data = prtd;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
+
+/**
+ * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
+ * @substream: PCM substream
+ */
+int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+	dma_release_channel(prtd->dma_chan);
+	kfree(prtd);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index c8610cbf34a51cf9f2e856cc847a730f64a1d016..4d8dc6a27d4d170f1586999a88a531fa30ea6807 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -114,6 +114,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 			       enum snd_soc_control_type control)
 {
 	struct regmap_config config;
+	int ret;
 
 	memset(&config, 0, sizeof(config));
 	codec->write = hw_write;
@@ -140,6 +141,12 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 
 	case SND_SOC_REGMAP:
 		/* Device has made its own regmap arrangements */
+		codec->using_regmap = true;
+
+		ret = regmap_get_val_bytes(codec->control_data);
+		/* Errors are legitimate for non-integer byte multiples */
+		if (ret > 0)
+			codec->val_bytes = ret;
 		break;
 
 	default:
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index cdc860a5ff37ca0fe070bdc9f6f4532e1cd6a7c3..0ad8dcacd2f39eefbdc434ac8bed0a4a56e3ea6f 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -62,6 +62,41 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+/*
+ * List of sample sizes that might go over the bus for parameter
+ * application.  There ought to be a wildcard sample size for things
+ * like the DAC/ADC resolution to use but there isn't right now.
+ */
+static int sample_sizes[] = {
+	24, 32,
+};
+
+static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
+			      struct snd_soc_dai *dai)
+{
+	int ret, i, bits;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		bits = dai->driver->playback.sig_bits;
+	else
+		bits = dai->driver->capture.sig_bits;
+
+	if (!bits)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(sample_sizes); i++) {
+		if (bits >= sample_sizes[i])
+			continue;
+
+		ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
+						   sample_sizes[i], bits);
+		if (ret != 0)
+			dev_warn(dai->dev,
+				 "Failed to set MSB %d/%d: %d\n",
+				 bits, sample_sizes[i], ret);
+	}
+}
+
 /*
  * Called by ALSA when a PCM substream is opened, the runtime->hw record is
  * then initialized and any private data can be allocated. This also calls
@@ -88,8 +123,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	if (cpu_dai->driver->ops->startup) {
 		ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't open interface %s\n",
-				cpu_dai->name);
+			dev_err(cpu_dai->dev, "can't open interface %s: %d\n",
+				cpu_dai->name, ret);
 			goto out;
 		}
 	}
@@ -97,7 +132,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	if (platform->driver->ops && platform->driver->ops->open) {
 		ret = platform->driver->ops->open(substream);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
+			dev_err(platform->dev, "can't open platform %s: %d\n",
+				platform->name, ret);
 			goto platform_err;
 		}
 	}
@@ -105,8 +141,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	if (codec_dai->driver->ops->startup) {
 		ret = codec_dai->driver->ops->startup(substream, codec_dai);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't open codec %s\n",
-				codec_dai->name);
+			dev_err(codec_dai->dev, "can't open codec %s: %d\n",
+				codec_dai->name, ret);
 			goto codec_dai_err;
 		}
 	}
@@ -114,7 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 	if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
 		ret = rtd->dai_link->ops->startup(substream);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
+			pr_err("asoc: %s startup failed: %d\n",
+			       rtd->dai_link->name, ret);
 			goto machine_err;
 		}
 	}
@@ -187,6 +224,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 		goto config_err;
 	}
 
+	soc_pcm_apply_msb(substream, codec_dai);
+	soc_pcm_apply_msb(substream, cpu_dai);
+
 	/* Symmetry only applies if we've already got an active stream. */
 	if (cpu_dai->active) {
 		ret = soc_pcm_apply_symmetry(substream, cpu_dai);
@@ -267,9 +307,8 @@ static void close_delayed_work(struct work_struct *work)
 	/* are we waiting on this codec DAI stream */
 	if (codec_dai->pop_wait == 1) {
 		codec_dai->pop_wait = 0;
-		snd_soc_dapm_stream_event(rtd,
-			codec_dai->driver->playback.stream_name,
-			SND_SOC_DAPM_STREAM_STOP);
+		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+					  codec_dai, SND_SOC_DAPM_STREAM_STOP);
 	}
 
 	mutex_unlock(&rtd->pcm_mutex);
@@ -329,12 +368,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 	cpu_dai->runtime = NULL;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		if (codec->ignore_pmdown_time ||
+		if (!rtd->pmdown_time || 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,
-				SND_SOC_DAPM_STREAM_STOP);
+						  SNDRV_PCM_STREAM_PLAYBACK,
+						  codec_dai,
+						  SND_SOC_DAPM_STREAM_STOP);
 		} else {
 			/* start delayed pop wq here for playback streams */
 			codec_dai->pop_wait = 1;
@@ -343,9 +383,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 		}
 	} else {
 		/* capture streams can be powered down now */
-		snd_soc_dapm_stream_event(rtd,
-			codec_dai->driver->capture.stream_name,
-			SND_SOC_DAPM_STREAM_STOP);
+		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
+					  codec_dai, SND_SOC_DAPM_STREAM_STOP);
 	}
 
 	mutex_unlock(&rtd->pcm_mutex);
@@ -375,7 +414,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 	if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
 		ret = rtd->dai_link->ops->prepare(substream);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: machine prepare error\n");
+			pr_err("asoc: machine prepare error: %d\n", ret);
 			goto out;
 		}
 	}
@@ -383,7 +422,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 	if (platform->driver->ops && platform->driver->ops->prepare) {
 		ret = platform->driver->ops->prepare(substream);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: platform prepare error\n");
+			dev_err(platform->dev, "platform prepare error: %d\n",
+				ret);
 			goto out;
 		}
 	}
@@ -391,7 +431,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 	if (codec_dai->driver->ops->prepare) {
 		ret = codec_dai->driver->ops->prepare(substream, codec_dai);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: codec DAI prepare error\n");
+			dev_err(codec_dai->dev, "DAI prepare error: %d\n",
+				ret);
 			goto out;
 		}
 	}
@@ -399,7 +440,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 	if (cpu_dai->driver->ops->prepare) {
 		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: cpu DAI prepare error\n");
+			dev_err(cpu_dai->dev, "DAI prepare error: %d\n",
+				ret);
 			goto out;
 		}
 	}
@@ -411,14 +453,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 		cancel_delayed_work(&rtd->delayed_work);
 	}
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		snd_soc_dapm_stream_event(rtd,
-					  codec_dai->driver->playback.stream_name,
-					  SND_SOC_DAPM_STREAM_START);
-	else
-		snd_soc_dapm_stream_event(rtd,
-					  codec_dai->driver->capture.stream_name,
-					  SND_SOC_DAPM_STREAM_START);
+	snd_soc_dapm_stream_event(rtd, substream->stream, codec_dai,
+				  SND_SOC_DAPM_STREAM_START);
 
 	snd_soc_dai_digital_mute(codec_dai, 0);
 
@@ -446,7 +482,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
 		ret = rtd->dai_link->ops->hw_params(substream, params);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: machine hw_params failed\n");
+			pr_err("asoc: machine hw_params failed: %d\n", ret);
 			goto out;
 		}
 	}
@@ -454,8 +490,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (codec_dai->driver->ops->hw_params) {
 		ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
-				codec_dai->name);
+			dev_err(codec_dai->dev, "can't set %s hw params: %d\n",
+				codec_dai->name, ret);
 			goto codec_err;
 		}
 	}
@@ -463,8 +499,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (cpu_dai->driver->ops->hw_params) {
 		ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: interface %s hw params failed\n",
-				cpu_dai->name);
+			dev_err(cpu_dai->dev, "%s hw params failed: %d\n",
+				cpu_dai->name, ret);
 			goto interface_err;
 		}
 	}
@@ -472,8 +508,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (platform->driver->ops && platform->driver->ops->hw_params) {
 		ret = platform->driver->ops->hw_params(substream, params);
 		if (ret < 0) {
-			printk(KERN_ERR "asoc: platform %s hw params failed\n",
-				platform->name);
+			dev_err(platform->dev, "%s hw params failed: %d\n",
+			       platform->name, ret);
 			goto platform_err;
 		}
 	}
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 4220bb0f27301aa962964b9eb645fd0f5e51e17c..60053709e417b0bdcecc81d13ac676fc885021e7 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -89,14 +89,32 @@ static struct snd_soc_platform_driver dummy_platform = {
 	.ops = &dummy_dma_ops,
 };
 
+static struct snd_soc_codec_driver dummy_codec;
+static struct snd_soc_dai_driver dummy_dai = {
+	.name = "snd-soc-dummy-dai",
+};
+
 static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
 {
-	return snd_soc_register_platform(&pdev->dev, &dummy_platform);
+	int ret;
+
+	ret = snd_soc_register_codec(&pdev->dev, &dummy_codec, &dummy_dai, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_register_platform(&pdev->dev, &dummy_platform);
+	if (ret < 0) {
+		snd_soc_unregister_codec(&pdev->dev);
+		return ret;
+	}
+
+	return ret;
 }
 
 static __devexit int snd_soc_dummy_remove(struct platform_device *pdev)
 {
 	snd_soc_unregister_platform(&pdev->dev);
+	snd_soc_unregister_codec(&pdev->dev);
 
 	return 0;
 }
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 4a0e805c4edd1b770cf84c85369be81d94375d2f..e45ccd851f6a9133065303ab8c04c6737f53e0ec 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 
 #include <sound/core.h>
 #include <sound/jack.h>
@@ -34,8 +35,13 @@
 
 #define DRV_NAME "tegra-alc5632"
 
+#define GPIO_HP_DET     BIT(0)
+
 struct tegra_alc5632 {
 	struct tegra_asoc_utils_data util_data;
+	struct platform_device *pcm_dev;
+	int gpio_requested;
+	int gpio_hp_det;
 };
 
 static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
@@ -85,24 +91,18 @@ static struct snd_soc_jack_pin tegra_alc5632_hs_jack_pins[] = {
 	},
 };
 
+static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {
+	.name = "Headset detection",
+	.report = SND_JACK_HEADSET,
+	.debounce_time = 150,
+	.invert = 1,
+};
+
 static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = {
 	SND_SOC_DAPM_SPK("Int Spk", NULL),
 	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
-};
-
-static const struct snd_soc_dapm_route tegra_alc5632_audio_map[] = {
-	/* Internal Speaker */
-	{"Int Spk", NULL, "SPKOUT"},
-	{"Int Spk", NULL, "SPKOUTN"},
-
-	/* Headset Mic */
-	{"MIC1", NULL, "MICBIAS1"},
-	{"MICBIAS1", NULL, "Headset Mic"},
-
-	/* Headset Stereophone */
-	{"Headset Stereophone", NULL, "HPR"},
-	{"Headset Stereophone", NULL, "HPL"},
+	SND_SOC_DAPM_MIC("Digital Mic", NULL),
 };
 
 static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
@@ -113,6 +113,8 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct device_node *np = codec->card->dev->of_node;
+	struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
 
 	snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
 			 &tegra_alc5632_hs_jack);
@@ -120,6 +122,16 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
 			ARRAY_SIZE(tegra_alc5632_hs_jack_pins),
 			tegra_alc5632_hs_jack_pins);
 
+	machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+
+	if (gpio_is_valid(machine->gpio_hp_det)) {
+		tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
+		snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack,
+						1,
+						&tegra_alc5632_hp_jack_gpio);
+		machine->gpio_requested |= GPIO_HP_DET;
+	}
+
 	snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
 
 	return 0;
@@ -128,9 +140,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link tegra_alc5632_dai = {
 	.name = "ALC5632",
 	.stream_name = "ALC5632 PCM",
-	.codec_name = "alc5632.0-001e",
 	.platform_name = "tegra-pcm-audio",
-	.cpu_dai_name = "tegra-i2s.0",
 	.codec_dai_name = "alc5632-hifi",
 	.init = tegra_alc5632_asoc_init,
 	.ops = &tegra_alc5632_asoc_ops,
@@ -148,8 +158,6 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
 	.num_controls = ARRAY_SIZE(tegra_alc5632_controls),
 	.dapm_widgets = tegra_alc5632_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(tegra_alc5632_dapm_widgets),
-	.dapm_routes = tegra_alc5632_audio_map,
-	.num_dapm_routes = ARRAY_SIZE(tegra_alc5632_audio_map),
 	.fully_routed = true,
 };
 
@@ -163,45 +171,111 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
 			sizeof(struct tegra_alc5632), GFP_KERNEL);
 	if (!alc5632) {
 		dev_err(&pdev->dev, "Can't allocate tegra_alc5632\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err;
 	}
 
-	ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
-	if (ret)
-		return ret;
-
 	card->dev = &pdev->dev;
 	platform_set_drvdata(pdev, card);
 	snd_soc_card_set_drvdata(card, alc5632);
 
+	alc5632->pcm_dev = ERR_PTR(-EINVAL);
+
+	if (!(pdev->dev.of_node)) {
+		dev_err(&pdev->dev, "Must be instantiated using device tree\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+	if (ret)
+		goto err;
+
+	ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+	if (ret)
+		goto err;
+
+	tegra_alc5632_dai.codec_of_node = of_parse_phandle(
+			pdev->dev.of_node, "nvidia,audio-codec", 0);
+
+	if (!tegra_alc5632_dai.codec_of_node) {
+		dev_err(&pdev->dev,
+			"Property 'nvidia,audio-codec' missing or invalid\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle(
+			pdev->dev.of_node, "nvidia,i2s-controller", 0);
+	if (!tegra_alc5632_dai.cpu_dai_of_node) {
+		dev_err(&pdev->dev,
+		"Property 'nvidia,i2s-controller' missing or invalid\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	alc5632->pcm_dev = platform_device_register_simple(
+		"tegra-pcm-audio", -1, NULL, 0);
+	if (IS_ERR(alc5632->pcm_dev)) {
+		dev_err(&pdev->dev,
+			"Can't instantiate tegra-pcm-audio\n");
+		ret = PTR_ERR(alc5632->pcm_dev);
+		goto err;
+	}
+
+	ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
+	if (ret)
+		goto err_unregister;
+
 	ret = snd_soc_register_card(card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
 			ret);
-		tegra_asoc_utils_fini(&alc5632->util_data);
-		return ret;
+		goto err_fini_utils;
 	}
 
 	return 0;
+
+err_fini_utils:
+	tegra_asoc_utils_fini(&alc5632->util_data);
+err_unregister:
+	if (!IS_ERR(alc5632->pcm_dev))
+		platform_device_unregister(alc5632->pcm_dev);
+err:
+	return ret;
 }
 
 static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
-	struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
+	struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
+
+	if (machine->gpio_requested & GPIO_HP_DET)
+		snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack,
+					1,
+					&tegra_alc5632_hp_jack_gpio);
+	machine->gpio_requested = 0;
 
 	snd_soc_unregister_card(card);
 
-	tegra_asoc_utils_fini(&alc5632->util_data);
+	tegra_asoc_utils_fini(&machine->util_data);
+	if (!IS_ERR(machine->pcm_dev))
+		platform_device_unregister(machine->pcm_dev);
 
 	return 0;
 }
 
+static const struct of_device_id tegra_alc5632_of_match[] __devinitconst = {
+	{ .compatible = "nvidia,tegra-audio-alc5632", },
+	{},
+};
+
 static struct platform_driver tegra_alc5632_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
 		.pm = &snd_soc_pm_ops,
+		.of_match_table = tegra_alc5632_of_match,
 	},
 	.probe = tegra_alc5632_probe,
 	.remove = __devexit_p(tegra_alc5632_remove),
@@ -212,3 +286,4 @@ MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
 MODULE_DESCRIPTION("Tegra+ALC5632 machine ASoC driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_alc5632_of_match);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index c22431516ab200ebcdc9b2b1b86894afb8cf5a3a..8b4457137c7ca7a451cad16e41fb274010a2d380 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -336,7 +336,7 @@ static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &tegra_dma_mask;
 	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = 0xffffffff;
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
 	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
 		ret = tegra_pcm_preallocate_dma_buffer(pcm,
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 4dd051bdf4fd1365498cc0740173d95b3b4bdc60..c6500d00053b21314086f9d88f8dcd72e91e4cc7 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -1112,17 +1112,7 @@ static struct spi_driver at73c213_driver = {
 	.remove		= __devexit_p(snd_at73c213_remove),
 };
 
-static int __init at73c213_init(void)
-{
-	return spi_register_driver(&at73c213_driver);
-}
-module_init(at73c213_init);
-
-static void __exit at73c213_exit(void)
-{
-	spi_unregister_driver(&at73c213_driver);
-}
-module_exit(at73c213_exit);
+module_spi_driver(at73c213_driver);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC");
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index 8af92e3e9c18f9557810f5b71a27ab27f3345c40..fc8cc823e4388ad15929d9b65f1fb065172fa2de 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -5,7 +5,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
@@ -29,7 +28,7 @@
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
-MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0");
+MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver");
 MODULE_LICENSE("GPL v2");
 MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
 
diff --git a/sound/usb/6fire/chip.h b/sound/usb/6fire/chip.h
index d11e5cb520f02c388460f2b41834152456f21619..bde02d105a515381ee185d99de78b6138bc88fab 100644
--- a/sound/usb/6fire/chip.h
+++ b/sound/usb/6fire/chip.h
@@ -3,7 +3,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
index c994daa57af2424a6f8fd8bef1f387ab19b017ac..6c3d531a250efdc265acaf6bced48ab82aa32d05 100644
--- a/sound/usb/6fire/comm.c
+++ b/sound/usb/6fire/comm.c
@@ -5,7 +5,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
index edc5dc84b8881f6bad21d0add5cf88c11bf0e719..d2af0a5ddcf355995087c1e111a0b447b412b6a4 100644
--- a/sound/usb/6fire/comm.h
+++ b/sound/usb/6fire/comm.h
@@ -3,7 +3,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/common.h b/sound/usb/6fire/common.h
index 7dbeb4a378316ae650be1360be735aea03123834..b6eb03ed1c2c8eedd28f9ce6a99f235159ad5558 100644
--- a/sound/usb/6fire/common.h
+++ b/sound/usb/6fire/common.h
@@ -3,7 +3,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
index ac828eff1a6347e080b74c78214b75a49fa9e663..07ed914d5e71a3c165287e88f2381fac98614726 100644
--- a/sound/usb/6fire/control.c
+++ b/sound/usb/6fire/control.c
@@ -5,9 +5,12 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
+ * Thanks to:
+ * - Holger Ruckdeschel: he found out how to control individual channel
+ *   volumes and introduced mute switch
+ *
  * 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
@@ -16,6 +19,7 @@
 
 #include <linux/interrupt.h>
 #include <sound/control.h>
+#include <sound/tlv.h>
 
 #include "control.h"
 #include "comm.h"
@@ -24,26 +28,6 @@
 static char *opt_coax_texts[2] = { "Optical", "Coax" };
 static char *line_phono_texts[2] = { "Line", "Phono" };
 
-/*
- * calculated with $value\[i\] = 128 \cdot sqrt[3]{\frac{i}{128}}$
- * this is done because the linear values cause rapid degredation
- * of volume in the uppermost region.
- */
-static const u8 log_volume_table[128] = {
-	0x00, 0x19, 0x20, 0x24, 0x28, 0x2b, 0x2e, 0x30, 0x32, 0x34,
-	0x36, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x43,
-	0x44, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
-	0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56,
-	0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
-	0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62,
-	0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
-	0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c,
-	0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
-	0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75,
-	0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79,
-	0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
-	0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f };
-
 /*
  * data that needs to be sent to device. sets up card internal stuff.
  * values dumped from windows driver and filtered by trial'n'error.
@@ -59,7 +43,7 @@ init_data[] = {
 	{ 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 },
 	{ 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 },
 	{ 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 },
-	{ 0x12, 0x0d, 0x78 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
+	{ 0x12, 0x0d, 0x38 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
 	{ 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 },
 	{ 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 },
 	{ 0 } /* TERMINATING ENTRY */
@@ -70,20 +54,47 @@ static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
 static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
 static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
 
+static DECLARE_TLV_DB_MINMAX(tlv_output, -9000, 0);
+static DECLARE_TLV_DB_MINMAX(tlv_input, -1500, 1500);
+
 enum {
 	DIGITAL_THRU_ONLY_SAMPLERATE = 3
 };
 
-static void usb6fire_control_master_vol_update(struct control_runtime *rt)
+static void usb6fire_control_output_vol_update(struct control_runtime *rt)
 {
 	struct comm_runtime *comm_rt = rt->chip->comm;
-	if (comm_rt) {
-		/* set volume */
-		comm_rt->write8(comm_rt, 0x12, 0x0f, 0x7f -
-				log_volume_table[rt->master_vol]);
-		 /* unmute */
-		comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00);
-	}
+	int i;
+
+	if (comm_rt)
+		for (i = 0; i < 6; i++)
+			if (!(rt->ovol_updated & (1 << i))) {
+				comm_rt->write8(comm_rt, 0x12, 0x0f + i,
+					180 - rt->output_vol[i]);
+				rt->ovol_updated |= 1 << i;
+			}
+}
+
+static void usb6fire_control_output_mute_update(struct control_runtime *rt)
+{
+	struct comm_runtime *comm_rt = rt->chip->comm;
+
+	if (comm_rt)
+		comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute);
+}
+
+static void usb6fire_control_input_vol_update(struct control_runtime *rt)
+{
+	struct comm_runtime *comm_rt = rt->chip->comm;
+	int i;
+
+	if (comm_rt)
+		for (i = 0; i < 2; i++)
+			if (!(rt->ivol_updated & (1 << i))) {
+				comm_rt->write8(comm_rt, 0x12, 0x1c + i,
+					rt->input_vol[i] & 0x3f);
+				rt->ivol_updated |= 1 << i;
+			}
 }
 
 static void usb6fire_control_line_phono_update(struct control_runtime *rt)
@@ -165,34 +176,147 @@ static int usb6fire_control_streaming_update(struct control_runtime *rt)
 	return -EINVAL;
 }
 
-static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_info(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_info *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
+	uinfo->count = 2;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 127;
+	uinfo->value.integer.max = 180;
 	return 0;
 }
 
-static int usb6fire_control_master_vol_put(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_put(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
 	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	unsigned int ch = kcontrol->private_value;
 	int changed = 0;
-	if (rt->master_vol != ucontrol->value.integer.value[0]) {
-		rt->master_vol = ucontrol->value.integer.value[0];
-		usb6fire_control_master_vol_update(rt);
+
+	if (ch > 4) {
+		snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+		return -EINVAL;
+	}
+
+	if (rt->output_vol[ch] != ucontrol->value.integer.value[0]) {
+		rt->output_vol[ch] = ucontrol->value.integer.value[0];
+		rt->ovol_updated &= ~(1 << ch);
 		changed = 1;
 	}
+	if (rt->output_vol[ch + 1] != ucontrol->value.integer.value[1]) {
+		rt->output_vol[ch + 1] = ucontrol->value.integer.value[1];
+		rt->ovol_updated &= ~(2 << ch);
+		changed = 1;
+	}
+
+	if (changed)
+		usb6fire_control_output_vol_update(rt);
+
 	return changed;
 }
 
-static int usb6fire_control_master_vol_get(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol,
 		struct snd_ctl_elem_value *ucontrol)
 {
 	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
-	ucontrol->value.integer.value[0] = rt->master_vol;
+	unsigned int ch = kcontrol->private_value;
+
+	if (ch > 4) {
+		snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] = rt->output_vol[ch];
+	ucontrol->value.integer.value[1] = rt->output_vol[ch + 1];
+	return 0;
+}
+
+static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	unsigned int ch = kcontrol->private_value;
+	u8 old = rt->output_mute;
+	u8 value = 0;
+
+	if (ch > 4) {
+		snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+		return -EINVAL;
+	}
+
+	rt->output_mute &= ~(3 << ch);
+	if (ucontrol->value.integer.value[0])
+		value |= 1;
+	if (ucontrol->value.integer.value[1])
+		value |= 2;
+	rt->output_mute |= value << ch;
+
+	if (rt->output_mute != old)
+		usb6fire_control_output_mute_update(rt);
+
+	return rt->output_mute != old;
+}
+
+static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	unsigned int ch = kcontrol->private_value;
+	u8 value = rt->output_mute >> ch;
+
+	if (ch > 4) {
+		snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] = 1 & value;
+	value >>= 1;
+	ucontrol->value.integer.value[1] = 1 & value;
+
+	return 0;
+}
+
+static int usb6fire_control_input_vol_info(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 30;
+	return 0;
+}
+
+static int usb6fire_control_input_vol_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+
+	if (rt->input_vol[0] != ucontrol->value.integer.value[0]) {
+		rt->input_vol[0] = ucontrol->value.integer.value[0] - 15;
+		rt->ivol_updated &= ~(1 << 0);
+		changed = 1;
+	}
+	if (rt->input_vol[1] != ucontrol->value.integer.value[1]) {
+		rt->input_vol[1] = ucontrol->value.integer.value[1] - 15;
+		rt->ivol_updated &= ~(1 << 1);
+		changed = 1;
+	}
+
+	if (changed)
+		usb6fire_control_input_vol_update(rt);
+
+	return changed;
+}
+
+static int usb6fire_control_input_vol_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = rt->input_vol[0] + 15;
+	ucontrol->value.integer.value[1] = rt->input_vol[1] + 15;
+
 	return 0;
 }
 
@@ -287,16 +411,81 @@ static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static struct __devinitdata snd_kcontrol_new elements[] = {
+static struct __devinitdata snd_kcontrol_new vol_elements[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Volume",
+		.name = "Analog Playback Volume",
 		.index = 0,
+		.private_value = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+		.info = usb6fire_control_output_vol_info,
+		.get = usb6fire_control_output_vol_get,
+		.put = usb6fire_control_output_vol_put,
+		.tlv = { .p = tlv_output }
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Playback Volume",
+		.index = 1,
+		.private_value = 2,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+		.info = usb6fire_control_output_vol_info,
+		.get = usb6fire_control_output_vol_get,
+		.put = usb6fire_control_output_vol_put,
+		.tlv = { .p = tlv_output }
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Playback Volume",
+		.index = 2,
+		.private_value = 4,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+		.info = usb6fire_control_output_vol_info,
+		.get = usb6fire_control_output_vol_get,
+		.put = usb6fire_control_output_vol_put,
+		.tlv = { .p = tlv_output }
+	},
+	{}
+};
+
+static struct __devinitdata snd_kcontrol_new mute_elements[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Playback Switch",
+		.index = 0,
+		.private_value = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = snd_ctl_boolean_stereo_info,
+		.get = usb6fire_control_output_mute_get,
+		.put = usb6fire_control_output_mute_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Playback Switch",
+		.index = 1,
+		.private_value = 2,
 		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-		.info = usb6fire_control_master_vol_info,
-		.get = usb6fire_control_master_vol_get,
-		.put = usb6fire_control_master_vol_put
+		.info = snd_ctl_boolean_stereo_info,
+		.get = usb6fire_control_output_mute_get,
+		.put = usb6fire_control_output_mute_put,
 	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Playback Switch",
+		.index = 2,
+		.private_value = 4,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = snd_ctl_boolean_stereo_info,
+		.get = usb6fire_control_output_mute_get,
+		.put = usb6fire_control_output_mute_put,
+	},
+	{}
+};
+
+static struct __devinitdata snd_kcontrol_new elements[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Line/Phono Capture Route",
@@ -324,9 +513,54 @@ static struct __devinitdata snd_kcontrol_new elements[] = {
 		.get = usb6fire_control_digital_thru_get,
 		.put = usb6fire_control_digital_thru_put
 	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Capture Volume",
+		.index = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+		.info = usb6fire_control_input_vol_info,
+		.get = usb6fire_control_input_vol_get,
+		.put = usb6fire_control_input_vol_put,
+		.tlv = { .p = tlv_input }
+	},
 	{}
 };
 
+static int usb6fire_control_add_virtual(
+	struct control_runtime *rt,
+	struct snd_card *card,
+	char *name,
+	struct snd_kcontrol_new *elems)
+{
+	int ret;
+	int i;
+	struct snd_kcontrol *vmaster =
+		snd_ctl_make_virtual_master(name, tlv_output);
+	struct snd_kcontrol *control;
+
+	if (!vmaster)
+		return -ENOMEM;
+	ret = snd_ctl_add(card, vmaster);
+	if (ret < 0)
+		return ret;
+
+	i = 0;
+	while (elems[i].name) {
+		control = snd_ctl_new1(&elems[i], rt);
+		if (!control)
+			return -ENOMEM;
+		ret = snd_ctl_add(card, control);
+		if (ret < 0)
+			return ret;
+		ret = snd_ctl_add_slave(vmaster, control);
+		if (ret < 0)
+			return ret;
+		i++;
+	}
+	return 0;
+}
+
 int __devinit usb6fire_control_init(struct sfire_chip *chip)
 {
 	int i;
@@ -352,9 +586,26 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
 
 	usb6fire_control_opt_coax_update(rt);
 	usb6fire_control_line_phono_update(rt);
-	usb6fire_control_master_vol_update(rt);
+	usb6fire_control_output_vol_update(rt);
+	usb6fire_control_output_mute_update(rt);
+	usb6fire_control_input_vol_update(rt);
 	usb6fire_control_streaming_update(rt);
 
+	ret = usb6fire_control_add_virtual(rt, chip->card,
+		"Master Playback Volume", vol_elements);
+	if (ret) {
+		snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+		kfree(rt);
+		return ret;
+	}
+	ret = usb6fire_control_add_virtual(rt, chip->card,
+		"Master Playback Switch", mute_elements);
+	if (ret) {
+		snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+		kfree(rt);
+		return ret;
+	}
+
 	i = 0;
 	while (elements[i].name) {
 		ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h
index 8f5aeead2e3d931938f41e98deaf857b0194fa2c..9a596d95474a997afbf4c5e2bdaa5534c061fa19 100644
--- a/sound/usb/6fire/control.h
+++ b/sound/usb/6fire/control.h
@@ -3,7 +3,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
@@ -44,7 +43,11 @@ struct control_runtime {
 	bool line_phono_switch;
 	bool digital_thru_switch;
 	bool usb_streaming;
-	u8 master_vol;
+	u8 output_vol[6];
+	u8 ovol_updated;
+	u8 output_mute;
+	s8 input_vol[2];
+	u8 ivol_updated;
 };
 
 int __devinit usb6fire_control_init(struct sfire_chip *chip);
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
index 3b5f517a3972a0ff375d3c98a0ac750dd8e40fb8..6f9715ab32fe77cc3fd39de42410efe1c2aa1006 100644
--- a/sound/usb/6fire/firmware.c
+++ b/sound/usb/6fire/firmware.c
@@ -5,7 +5,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
index 13f4509dce2b98939d4ba269fb8a47508b02666f..f0e5179b242bd48ce3c17314b96b3e27fdf5c85b 100644
--- a/sound/usb/6fire/midi.c
+++ b/sound/usb/6fire/midi.c
@@ -5,7 +5,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h
index 97a7bf669135024e2f7a30330907c3888de62357..5114eccc1d8ee972222ca57e8738cdfde450ec48 100644
--- a/sound/usb/6fire/midi.h
+++ b/sound/usb/6fire/midi.h
@@ -3,7 +3,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index d144cdb2f15909acefec2f0c45ea0cd1ff523030..c97d05f0e966e95b8fdc3d0778e509e360c127c1 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -5,7 +5,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h
index 2bee81374002f6e65eb532e797196dae6ac7712f..3104301b257df032a5047b3ea0dad5d4b7d43d3e 100644
--- a/sound/usb/6fire/pcm.h
+++ b/sound/usb/6fire/pcm.h
@@ -3,7 +3,6 @@
  *
  * Author:	Torsten Schenk <torsten.schenk@zoho.com>
  * Created:	Jan 01, 2011
- * Version:	0.3.0
  * Copyright:	(C) Torsten Schenk
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 3efc21c3d67c610250a1d6fe3705f03e2a27c58a..ff77b28f3da167fe0dd0788bfc110b52964c4b6f 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -106,6 +106,7 @@ config SND_USB_6FIRE
         select BITREVERSE
         select SND_RAWMIDI
         select SND_PCM
+        select SND_VMASTER
         help
           Say Y here to include support for TerraTec 6fire DMX USB interface.
 
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 0220b0f335b9ad230ebcb954ed78ab25731ca58e..0eed6115c2d444e166d770008238d5e11e4800fb 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -695,6 +695,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
 				  struct snd_usb_substream *subs)
 {
 	struct audioformat *fp;
+	int *rate_list;
 	int count = 0, needs_knot = 0;
 	int err;
 
@@ -708,7 +709,8 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
 	if (!needs_knot)
 		return 0;
 
-	subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL);
+	subs->rate_list.list = rate_list =
+		kmalloc(sizeof(int) * count, GFP_KERNEL);
 	if (!subs->rate_list.list)
 		return -ENOMEM;
 	subs->rate_list.count = count;
@@ -717,7 +719,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
 	list_for_each_entry(fp, &subs->fmt_list, list) {
 		int i;
 		for (i = 0; i < fp->nr_rates; i++)
-			subs->rate_list.list[count++] = fp->rate_table[i];
+			rate_list[count++] = fp->rate_table[i];
 	}
 	err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 					 &subs->rate_list);
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 6ffb3713b60cf812cec624c1c1050ff1be71e7e5..520ef96d7c75f14094c12ce4cc950e72c846c5d2 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -80,7 +80,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs)
 		cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 		if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
 			snd_printk(KERN_ERR "active frame status %i. "
-				   "Most propably some hardware problem.\n",
+				   "Most probably some hardware problem.\n",
 				   urb->iso_frame_desc[i].status);
 			return urb->iso_frame_desc[i].status;
 		}
@@ -300,7 +300,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
 {
 	snd_printk(KERN_ERR
 "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
-"Most propably some urb of usb-frame %i is still missing.\n"
+"Most probably some urb of usb-frame %i is still missing.\n"
 "Cause could be too long delays in usb-hcd interrupt handling.\n",
 		   usb_get_current_frame_number(usX2Y->dev),
 		   subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index a51340f6f2db8d936321fa77ff7350955034fb30..8e40b6e67e9eeeb7ea8a9dd53dd4c73fced97b5c 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -74,7 +74,7 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs)
 	}
 	for (i = 0; i < nr_of_packs(); i++) {
 		if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
-			snd_printk(KERN_ERR "activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status);
+			snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status);
 			return urb->iso_frame_desc[i].status;
 		}
 		lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride;