Merge branch 'for-3.1' into for-3.2
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 2 Oct 2011 18:57:19 +0000 (19:57 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 2 Oct 2011 18:57:19 +0000 (19:57 +0100)
183 files changed:
Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8510.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8523.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8580.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8711.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8728.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8731.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8737.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8741.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8750.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8753.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8770.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8776.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8804.txt [new file with mode: 0644]
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/simone.c
arch/arm/mach-ep93xx/snappercl15.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/plat-omap/devices.c
arch/mips/alchemy/devboards/db1200/platform.c
arch/mips/alchemy/devboards/db1x00/platform.c
drivers/base/regmap/regmap.c
drivers/input/misc/twl6040-vibra.c
drivers/mfd/twl6040-core.c
drivers/regulator/core.c
include/linux/mfd/twl6040.h
include/linux/mfd/wm8994/registers.h
include/linux/regmap.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/sound/adau1373.h [new file with mode: 0644]
include/sound/saif.h [new file with mode: 0644]
include/sound/soc-dai.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/tpa6130a2-plat.h
include/sound/wm1250-ev1.h [new file with mode: 0644]
include/sound/wm5100.h [new file with mode: 0644]
include/trace/events/asoc.h
sound/mips/Kconfig
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/atmel/playpaq_wm8510.c
sound/soc/au1x/Kconfig
sound/soc/au1x/Makefile
sound/soc/au1x/ac97c.c [new file with mode: 0644]
sound/soc/au1x/db1000.c [new file with mode: 0644]
sound/soc/au1x/db1200.c
sound/soc/au1x/dbdma2.c
sound/soc/au1x/dma.c [new file with mode: 0644]
sound/soc/au1x/i2sc.c [new file with mode: 0644]
sound/soc/au1x/psc-ac97.c
sound/soc/au1x/psc-i2s.c
sound/soc/au1x/psc.h
sound/soc/blackfin/Kconfig
sound/soc/blackfin/Makefile
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-i2s-pcm.c
sound/soc/blackfin/bfin-eval-adau1373.c [new file with mode: 0644]
sound/soc/codecs/88pm860x-codec.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ad193x.c
sound/soc/codecs/ad193x.h
sound/soc/codecs/ad1980.c
sound/soc/codecs/adau1373.c [new file with mode: 0644]
sound/soc/codecs/adau1373.h [new file with mode: 0644]
sound/soc/codecs/adau1701.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/ak4671.c
sound/soc/codecs/alc5623.c
sound/soc/codecs/cs4270.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/max98088.c
sound/soc/codecs/max98095.c
sound/soc/codecs/rt5631.c [new file with mode: 0644]
sound/soc/codecs/rt5631.h [new file with mode: 0644]
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sn95031.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/ssm2602.h
sound/soc/codecs/sta32x.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/tpa6130a2.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/twl6040.h
sound/soc/codecs/wl1273.c
sound/soc/codecs/wm1250-ev1.c
sound/soc/codecs/wm5100-tables.c [new file with mode: 0644]
sound/soc/codecs/wm5100.c [new file with mode: 0644]
sound/soc/codecs/wm5100.h [new file with mode: 0644]
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8737.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8804.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994-tables.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm8995.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9090.c
sound/soc/codecs/wm_hubs.c
sound/soc/codecs/wm_hubs.h
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-pcm.c
sound/soc/ep93xx/edb93xx.c
sound/soc/ep93xx/ep93xx-pcm.c
sound/soc/ep93xx/simone.c
sound/soc/ep93xx/snappercl15.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/fsl/p1022_ds.c
sound/soc/imx/imx-pcm-fiq.c
sound/soc/imx/imx-ssi.c
sound/soc/jz4740/jz4740-pcm.c
sound/soc/mid-x86/mfld_machine.c
sound/soc/mid-x86/sst_platform.c
sound/soc/mxs/Kconfig [new file with mode: 0644]
sound/soc/mxs/Makefile [new file with mode: 0644]
sound/soc/mxs/mxs-pcm.c [new file with mode: 0644]
sound/soc/mxs/mxs-pcm.h [new file with mode: 0644]
sound/soc/mxs/mxs-saif.c [new file with mode: 0644]
sound/soc/mxs/mxs-saif.h [new file with mode: 0644]
sound/soc/mxs/mxs-sgtl5000.c [new file with mode: 0644]
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/Makefile
sound/soc/omap/am3517evm.c
sound/soc/omap/igep0020.c
sound/soc/omap/mcpdm.c [deleted file]
sound/soc/omap/mcpdm.h [deleted file]
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-mcpdm.h [new file with mode: 0644]
sound/soc/omap/omap3evm.c
sound/soc/omap/omap3pandora.c
sound/soc/omap/osk5912.c
sound/soc/omap/overo.c
sound/soc/omap/rx51.c
sound/soc/omap/sdp3430.c
sound/soc/omap/sdp4430.c
sound/soc/omap/zoom2.c
sound/soc/pxa/raumfeld.c
sound/soc/pxa/spitz.c
sound/soc/pxa/z2.c
sound/soc/s6000/s6000-pcm.c
sound/soc/samsung/Kconfig
sound/soc/samsung/jive_wm8750.c
sound/soc/samsung/s3c2412-i2s.c
sound/soc/samsung/s3c24xx-i2s.c
sound/soc/samsung/s3c24xx_uda134x.c
sound/soc/samsung/smartq_wm8987.c
sound/soc/samsung/smdk_wm8580.c
sound/soc/samsung/smdk_wm8580pcm.c
sound/soc/samsung/speyside.c
sound/soc/samsung/speyside_wm8962.c
sound/soc/soc-cache.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-io.c
sound/soc/soc-pcm.c

diff --git a/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt
new file mode 100644 (file)
index 0000000..2c3cd41
--- /dev/null
@@ -0,0 +1,11 @@
+* Freescale SGTL5000 Stereo Codec
+
+Required properties:
+- compatible : "fsl,sgtl5000".
+
+Example:
+
+codec: sgtl5000@0a {
+       compatible = "fsl,sgtl5000";
+       reg = <0x0a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8510.txt b/Documentation/devicetree/bindings/sound/wm8510.txt
new file mode 100644 (file)
index 0000000..fa1a32b
--- /dev/null
@@ -0,0 +1,18 @@
+WM8510 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8510"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8510@1a {
+       compatible = "wlf,wm8510";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8523.txt b/Documentation/devicetree/bindings/sound/wm8523.txt
new file mode 100644 (file)
index 0000000..0474618
--- /dev/null
@@ -0,0 +1,16 @@
+WM8523 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "wlf,wm8523"
+
+  - reg : the I2C address of the device.
+
+Example:
+
+codec: wm8523@1a {
+       compatible = "wlf,wm8523";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8580.txt b/Documentation/devicetree/bindings/sound/wm8580.txt
new file mode 100644 (file)
index 0000000..7d9821f
--- /dev/null
@@ -0,0 +1,16 @@
+WM8580 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "wlf,wm8580"
+
+  - reg : the I2C address of the device.
+
+Example:
+
+codec: wm8580@1a {
+       compatible = "wlf,wm8580";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8711.txt b/Documentation/devicetree/bindings/sound/wm8711.txt
new file mode 100644 (file)
index 0000000..8ed9998
--- /dev/null
@@ -0,0 +1,18 @@
+WM8711 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8711"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8711@1a {
+       compatible = "wlf,wm8711";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8728.txt b/Documentation/devicetree/bindings/sound/wm8728.txt
new file mode 100644 (file)
index 0000000..a8b5c36
--- /dev/null
@@ -0,0 +1,18 @@
+WM8728 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8728"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8728@1a {
+       compatible = "wlf,wm8728";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8731.txt b/Documentation/devicetree/bindings/sound/wm8731.txt
new file mode 100644 (file)
index 0000000..15f7004
--- /dev/null
@@ -0,0 +1,18 @@
+WM8731 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8731"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8731@1a {
+       compatible = "wlf,wm8731";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8737.txt b/Documentation/devicetree/bindings/sound/wm8737.txt
new file mode 100644 (file)
index 0000000..4bc2cea
--- /dev/null
@@ -0,0 +1,18 @@
+WM8737 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8737"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8737@1a {
+       compatible = "wlf,wm8737";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8741.txt b/Documentation/devicetree/bindings/sound/wm8741.txt
new file mode 100644 (file)
index 0000000..74bda58
--- /dev/null
@@ -0,0 +1,18 @@
+WM8741 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8741"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8741@1a {
+       compatible = "wlf,wm8741";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8750.txt b/Documentation/devicetree/bindings/sound/wm8750.txt
new file mode 100644 (file)
index 0000000..8db239f
--- /dev/null
@@ -0,0 +1,18 @@
+WM8750 and WM8987 audio CODECs
+
+These devices support both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8750" or "wlf,wm8987"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8750@1a {
+       compatible = "wlf,wm8750";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8753.txt b/Documentation/devicetree/bindings/sound/wm8753.txt
new file mode 100644 (file)
index 0000000..e65277a
--- /dev/null
@@ -0,0 +1,18 @@
+WM8753 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8753"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8737@1a {
+       compatible = "wlf,wm8753";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8770.txt b/Documentation/devicetree/bindings/sound/wm8770.txt
new file mode 100644 (file)
index 0000000..866e00c
--- /dev/null
@@ -0,0 +1,16 @@
+WM8770 audio CODEC
+
+This device supports SPI.
+
+Required properties:
+
+  - compatible : "wlf,wm8770"
+
+  - reg : the chip select number.
+
+Example:
+
+codec: wm8770@1 {
+       compatible = "wlf,wm8770";
+       reg = <1>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8776.txt b/Documentation/devicetree/bindings/sound/wm8776.txt
new file mode 100644 (file)
index 0000000..3b9ca49
--- /dev/null
@@ -0,0 +1,18 @@
+WM8776 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8776"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8776@1a {
+       compatible = "wlf,wm8776";
+       reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8804.txt b/Documentation/devicetree/bindings/sound/wm8804.txt
new file mode 100644 (file)
index 0000000..4d3a56f
--- /dev/null
@@ -0,0 +1,18 @@
+WM8804 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+
+  - compatible : "wlf,wm8804"
+
+  - reg : the I2C address of the device for I2C, the chip select
+          number for SPI.
+
+Example:
+
+codec: wm8804@1a {
+       compatible = "wlf,wm8804";
+       reg = <0x1a>;
+};
index 9969bb115f602d915330b0ebdca3c683862d7269..8dc51e464a4e0f16536db3debe38023db0fd21d4 100644 (file)
@@ -159,6 +159,11 @@ static void __init edb93xx_register_spi(void)
 /*************************************************************************
  * EDB93xx I2S
  *************************************************************************/
+static struct platform_device edb93xx_audio_device = {
+       .name           = "edb93xx-audio",
+       .id             = -1,
+};
+
 static int __init edb93xx_has_audio(void)
 {
        return (machine_is_edb9301() || machine_is_edb9302() ||
@@ -170,6 +175,7 @@ static void __init edb93xx_register_i2s(void)
 {
        if (edb93xx_has_audio()) {
                ep93xx_register_i2s();
+               platform_device_register(&edb93xx_audio_device);
        }
 }
 
index 8392e95d7cea69ef8729570712ba88380f240b37..1445ce568cae5ab6fec471b4973d1d9e35d1a3fb 100644 (file)
@@ -53,6 +53,17 @@ static struct i2c_board_info __initdata simone_i2c_board_info[] = {
        },
 };
 
+static struct platform_device simone_audio_device = {
+       .name           = "simone-audio",
+       .id             = -1,
+};
+
+static void __init simone_register_audio(void)
+{
+       ep93xx_register_ac97();
+       platform_device_register(&simone_audio_device);
+}
+
 static void __init simone_init_machine(void)
 {
        ep93xx_init_devices();
@@ -61,7 +72,7 @@ static void __init simone_init_machine(void)
        ep93xx_register_fb(&simone_fb_info);
        ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
                            ARRAY_SIZE(simone_i2c_board_info));
-       ep93xx_register_ac97();
+       simone_register_audio();
 }
 
 MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
index 2e9c614757e40f08e44e3e6e90073bd45b7f64a9..edd75e37f4def0e182f0a6851e3d1d02437b380b 100644 (file)
@@ -150,6 +150,17 @@ static struct ep93xxfb_mach_info __initdata snappercl15_fb_info = {
        .bpp                    = 16,
 };
 
+static struct platform_device snappercl15_audio_device = {
+       .name           = "snappercl15-audio",
+       .id             = -1,
+};
+
+static void __init snappercl15_register_audio(void)
+{
+       ep93xx_register_i2s();
+       platform_device_register(&snappercl15_audio_device);
+}
+
 static void __init snappercl15_init_machine(void)
 {
        ep93xx_init_devices();
@@ -157,7 +168,7 @@ static void __init snappercl15_init_machine(void)
        ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
                            ARRAY_SIZE(snappercl15_i2c_data));
        ep93xx_register_fb(&snappercl15_fb_info);
-       ep93xx_register_i2s();
+       snappercl15_register_audio();
        platform_device_register(&snappercl15_nand_device);
 }
 
index 5a886cd2c598c408f3e007e01a5f5e2b0ae9ca94..ba1aa07bdb29d325841b74da3117e76e60e5b668 100644 (file)
@@ -900,7 +900,6 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
 };
 
 static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = {
-       .id                     = TPA6130A2,
        .power_gpio             = 98,
 };
 
index 1077ad663f936e5174f0f3c7a137bee3f57a2972..3f0b143cb37bc1f4d498d0c7ded62c1603e9d63c 100644 (file)
@@ -330,6 +330,38 @@ static void omap_init_audio(void)
 static inline void omap_init_audio(void) {}
 #endif
 
+#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
+               defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
+
+static struct omap_device_pm_latency omap_mcpdm_latency[] = {
+       {
+               .deactivate_func = omap_device_idle_hwmods,
+               .activate_func = omap_device_enable_hwmods,
+               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
+};
+
+static void omap_init_mcpdm(void)
+{
+       struct omap_hwmod *oh;
+       struct omap_device *od;
+
+       oh = omap_hwmod_lookup("mcpdm");
+       if (!oh) {
+               printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
+               return;
+       }
+
+       od = omap_device_build("omap-mcpdm", -1, oh, NULL, 0,
+                               omap_mcpdm_latency,
+                               ARRAY_SIZE(omap_mcpdm_latency), 0);
+       if (IS_ERR(od))
+               printk(KERN_ERR "Could not build omap_device for omap-mcpdm-dai\n");
+}
+#else
+static inline void omap_init_mcpdm(void) {}
+#endif
+
 #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
 
 #include <plat/mcspi.h>
@@ -683,6 +715,7 @@ static int __init omap2_init_devices(void)
         * in alphabetical order so they're easier to sort through.
         */
        omap_init_audio();
+       omap_init_mcpdm();
        omap_init_camera();
        omap_init_mbox();
        omap_init_mcspi();
index 6201422c0606b5103c01e563f67060134658774d..79325c65c23cbcef5196a43852c246185da793a1 100644 (file)
@@ -5430,7 +5430,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
        &omap44xx_mcbsp4_hwmod,
 
        /* mcpdm class */
-/*     &omap44xx_mcpdm_hwmod, */
+       &omap44xx_mcpdm_hwmod,
 
        /* mcspi class */
        &omap44xx_mcspi1_hwmod,
index ea28f98d5d6a63da2ab5ede0327ec9188f5caf97..40eca9b30d93194965785763e991aabe07afb92b 100644 (file)
@@ -74,41 +74,6 @@ void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
-               defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
-
-static struct resource mcpdm_resources[] = {
-       {
-               .name           = "mcpdm_mem",
-               .start          = OMAP44XX_MCPDM_BASE,
-               .end            = OMAP44XX_MCPDM_BASE + SZ_4K,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .name           = "mcpdm_irq",
-               .start          = OMAP44XX_IRQ_MCPDM,
-               .end            = OMAP44XX_IRQ_MCPDM,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device omap_mcpdm_device = {
-       .name           = "omap-mcpdm",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(mcpdm_resources),
-       .resource       = mcpdm_resources,
-};
-
-static void omap_init_mcpdm(void)
-{
-       (void) platform_device_register(&omap_mcpdm_device);
-}
-#else
-static inline void omap_init_mcpdm(void) {}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
        defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
@@ -291,7 +256,6 @@ static int __init omap_init_devices(void)
         * in alphabetical order so they're easier to sort through.
         */
        omap_init_rng();
-       omap_init_mcpdm();
        omap_init_uwire();
        return 0;
 }
index fbb55935b99e71ee3be1475657ca8fdfdf981ee5..dda090bf74e6bb1a9f47a8492324fd167b5b06ad 100644 (file)
@@ -422,6 +422,7 @@ static struct resource au1200_psc1_res[] = {
        },
 };
 
+/* AC97 or I2S device */
 static struct platform_device db1200_audio_dev = {
        /* name assigned later based on switch setting */
        .id             = 1,    /* PSC ID */
@@ -429,19 +430,32 @@ static struct platform_device db1200_audio_dev = {
        .resource       = au1200_psc1_res,
 };
 
+/* DB1200 ASoC card device */
+static struct platform_device db1200_sound_dev = {
+       /* name assigned later based on switch setting */
+       .id             = 1,    /* PSC ID */
+};
+
 static struct platform_device db1200_stac_dev = {
        .name           = "ac97-codec",
        .id             = 1,    /* on PSC1 */
 };
 
+static struct platform_device db1200_audiodma_dev = {
+       .name           = "au1xpsc-pcm",
+       .id             = 1,    /* PSC ID */
+};
+
 static struct platform_device *db1200_devs[] __initdata = {
        NULL,           /* PSC0, selected by S6.8 */
        &db1200_ide_dev,
        &db1200_eth_dev,
        &db1200_rtc_dev,
        &db1200_nand_dev,
+       &db1200_audiodma_dev,
        &db1200_audio_dev,
        &db1200_stac_dev,
+       &db1200_sound_dev,
 };
 
 static int __init db1200_dev_init(void)
@@ -501,10 +515,12 @@ static int __init db1200_dev_init(void)
        if (sw == BCSR_SWITCHES_DIP_8) {
                bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_PSC1MUX);
                db1200_audio_dev.name = "au1xpsc_i2s";
+               db1200_sound_dev.name = "db1200-i2s";
                printk(KERN_INFO " S6.7 ON : PSC1 mode I2S\n");
        } else {
                bcsr_mod(BCSR_RESETS, BCSR_RESETS_PSC1MUX, 0);
                db1200_audio_dev.name = "au1xpsc_ac97";
+               db1200_sound_dev.name = "db1200-ac97";
                printk(KERN_INFO " S6.7 OFF: PSC1 mode AC97\n");
        }
 
index 978d5ab3d6781781eb5cb2d5acb117b3c443a81c..7057d28f73016dffb4136fb7d5856c1e19f66dac 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
 #include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-db1x00/bcsr.h>
 #include "../platform.h"
 #endif
 #endif
 
+static struct resource alchemy_ac97c_res[] = {
+       [0] = {
+               .start  = AU1000_AC97_PHYS_ADDR,
+               .end    = AU1000_AC97_PHYS_ADDR + 0xfff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = DMA_ID_AC97C_TX,
+               .end    = DMA_ID_AC97C_TX,
+               .flags  = IORESOURCE_DMA,
+       },
+       [2] = {
+               .start  = DMA_ID_AC97C_RX,
+               .end    = DMA_ID_AC97C_RX,
+               .flags  = IORESOURCE_DMA,
+       },
+};
+
+static struct platform_device alchemy_ac97c_dev = {
+       .name           = "alchemy-ac97c",
+       .id             = -1,
+       .resource       = alchemy_ac97c_res,
+       .num_resources  = ARRAY_SIZE(alchemy_ac97c_res),
+};
+
+static struct platform_device alchemy_ac97c_dma_dev = {
+       .name           = "alchemy-pcm-dma",
+       .id             = 0,
+};
+
+static struct platform_device db1x00_codec_dev = {
+       .name           = "ac97-codec",
+       .id             = -1,
+};
+
+static struct platform_device db1x00_audio_dev = {
+       .name           = "db1000-audio",
+};
+
 static int __init db1xxx_dev_init(void)
 {
 #ifdef DB1XXX_HAS_PCMCIA
@@ -113,6 +155,12 @@ static int __init db1xxx_dev_init(void)
                                    1);
 #endif
        db1x_register_norflash(BOARD_FLASH_SIZE, BOARD_FLASH_WIDTH, F_SWAPPED);
+
+       platform_device_register(&db1x00_codec_dev);
+       platform_device_register(&alchemy_ac97c_dma_dev);
+       platform_device_register(&alchemy_ac97c_dev);
+       platform_device_register(&db1x00_audio_dev);
+
        return 0;
 }
 device_initcall(db1xxx_dev_init);
index cf3565cae93d951ee7c77ddd7775e5aa878521b7..2fa55c56897a901dade6633cbd092014c382ae0f 100644 (file)
@@ -37,6 +37,11 @@ struct regmap {
        void *work_buf;     /* Scratch buffer used to format I/O */
        struct regmap_format format;  /* Buffer format */
        const struct regmap_bus *bus;
+
+       unsigned int max_register;
+       bool (*writeable_reg)(struct device *dev, unsigned int reg);
+       bool (*readable_reg)(struct device *dev, unsigned int reg);
+       bool (*volatile_reg)(struct device *dev, unsigned int reg);
 };
 
 static void regmap_format_4_12_write(struct regmap *map,
@@ -116,6 +121,10 @@ struct regmap *regmap_init(struct device *dev,
        map->format.val_bytes = config->val_bits / 8;
        map->dev = dev;
        map->bus = bus;
+       map->max_register = config->max_register;
+       map->writeable_reg = config->writeable_reg;
+       map->readable_reg = config->readable_reg;
+       map->volatile_reg = config->volatile_reg;
 
        switch (config->reg_bits) {
        case 4:
index c43002e7ec7286bdf5650f3ce402210c5fefd2f0..154b7a324d671fa949bf49219b98c997cb3442d3 100644 (file)
@@ -97,7 +97,7 @@ static void twl6040_vibra_enable(struct vibra_info *info)
        }
 
        twl6040_power(info->twl6040, 1);
-       if (twl6040->rev <= TWL6040_REV_ES1_1) {
+       if (twl6040_get_revid(twl6040) <= TWL6040_REV_ES1_1) {
                /*
                 * ERRATA: Disable overcurrent protection for at least
                 * 3ms when enabling vibrator drivers to avoid false
index 24d436c2fe4ac85998f097480231ef0dc89ca22f..7dc8c47150017ba64c515038258c6fe02e098b36 100644 (file)
@@ -34,8 +34,6 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/twl6040.h>
 
-static struct platform_device *twl6040_dev;
-
 int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
 {
        int ret;
@@ -203,11 +201,11 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data)
        if (intid & TWL6040_THINT) {
                status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
                if (status & TWL6040_TSHUTDET) {
-                       dev_warn(&twl6040_dev->dev,
+                       dev_warn(twl6040->dev,
                                 "Thermal shutdown, powering-off");
                        twl6040_power(twl6040, 0);
                } else {
-                       dev_warn(&twl6040_dev->dev,
+                       dev_warn(twl6040->dev,
                                 "Leaving thermal shutdown, powering-on");
                        twl6040_power(twl6040, 1);
                }
@@ -227,7 +225,7 @@ static int twl6040_power_up_completion(struct twl6040 *twl6040,
        if (!time_left) {
                intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
                if (!(intid & TWL6040_READYINT)) {
-                       dev_err(&twl6040_dev->dev,
+                       dev_err(twl6040->dev,
                                "timeout waiting for READYINT\n");
                        return -ETIMEDOUT;
                }
@@ -255,7 +253,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                        /* wait for power-up completion */
                        ret = twl6040_power_up_completion(twl6040, naudint);
                        if (ret) {
-                               dev_err(&twl6040_dev->dev,
+                               dev_err(twl6040->dev,
                                        "automatic power-down failed\n");
                                twl6040->power_count = 0;
                                goto out;
@@ -264,7 +262,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                        /* use manual power-up sequence */
                        ret = twl6040_power_up(twl6040);
                        if (ret) {
-                               dev_err(&twl6040_dev->dev,
+                               dev_err(twl6040->dev,
                                        "manual power-up failed\n");
                                twl6040->power_count = 0;
                                goto out;
@@ -276,7 +274,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)
        } else {
                /* already powered-down */
                if (!twl6040->power_count) {
-                       dev_err(&twl6040_dev->dev,
+                       dev_err(twl6040->dev,
                                "device is already powered-off\n");
                        ret = -EPERM;
                        goto out;
@@ -326,7 +324,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
                        lppllctl &= ~TWL6040_LPLLFIN;
                        break;
                default:
-                       dev_err(&twl6040_dev->dev,
+                       dev_err(twl6040->dev,
                                "freq_out %d not supported\n", freq_out);
                        ret = -EINVAL;
                        goto pll_out;
@@ -347,7 +345,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
                                          hppllctl);
                        break;
                default:
-                       dev_err(&twl6040_dev->dev,
+                       dev_err(twl6040->dev,
                                "freq_in %d not supported\n", freq_in);
                        ret = -EINVAL;
                        goto pll_out;
@@ -356,7 +354,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
        case TWL6040_SYSCLK_SEL_HPPLL:
                /* high-performance PLL can provide only 19.2 MHz */
                if (freq_out != 19200000) {
-                       dev_err(&twl6040_dev->dev,
+                       dev_err(twl6040->dev,
                                "freq_out %d not supported\n", freq_out);
                        ret = -EINVAL;
                        goto pll_out;
@@ -389,7 +387,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
                                    TWL6040_HPLLENA;
                        break;
                default:
-                       dev_err(&twl6040_dev->dev,
+                       dev_err(twl6040->dev,
                                "freq_in %d not supported\n", freq_in);
                        ret = -EINVAL;
                        goto pll_out;
@@ -406,7 +404,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
                twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
                break;
        default:
-               dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id);
+               dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
                ret = -EINVAL;
                goto pll_out;
        }
@@ -471,9 +469,7 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, twl6040);
 
-       twl6040_dev = pdev;
        twl6040->dev = &pdev->dev;
-       twl6040->audpwron = pdata->audpwron_gpio;
        twl6040->irq = pdata->naudint_irq;
        twl6040->irq_base = pdata->irq_base;
 
@@ -483,6 +479,12 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
 
        twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
 
+       /* ERRATA: Automatic power-up is not possible in ES1.0 */
+       if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
+               twl6040->audpwron = pdata->audpwron_gpio;
+       else
+               twl6040->audpwron = -EINVAL;
+
        if (gpio_is_valid(twl6040->audpwron)) {
                ret = gpio_request(twl6040->audpwron, "audpwron");
                if (ret)
@@ -493,10 +495,6 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
                        goto gpio2_err;
        }
 
-       /* ERRATA: Automatic power-up is not possible in ES1.0 */
-       if (twl6040->rev == TWL6040_REV_ES1_0)
-               twl6040->audpwron = -EINVAL;
-
        /* codec interrupt */
        ret = twl6040_irq_init(twl6040);
        if (ret)
@@ -566,7 +564,6 @@ gpio2_err:
 gpio1_err:
        platform_set_drvdata(pdev, NULL);
        kfree(twl6040);
-       twl6040_dev = NULL;
        return ret;
 }
 
@@ -586,7 +583,6 @@ static int __devexit twl6040_remove(struct platform_device *pdev)
        mfd_remove_devices(&pdev->dev);
        platform_set_drvdata(pdev, NULL);
        kfree(twl6040);
-       twl6040_dev = NULL;
 
        return 0;
 }
index d8e6a429e8ba046027e9fa8550be6444f47ae971..d0bde70f346650993d3d95b60d1ccf5136c27913 100644 (file)
@@ -1552,6 +1552,63 @@ int regulator_force_disable(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_force_disable);
 
+static void regulator_disable_work(struct work_struct *work)
+{
+       struct regulator_dev *rdev = container_of(work, struct regulator_dev,
+                                                 disable_work.work);
+       int count, i, ret;
+
+       mutex_lock(&rdev->mutex);
+
+       BUG_ON(!rdev->deferred_disables);
+
+       count = rdev->deferred_disables;
+       rdev->deferred_disables = 0;
+
+       for (i = 0; i < count; i++) {
+               ret = _regulator_disable(rdev);
+               if (ret != 0)
+                       rdev_err(rdev, "Deferred disable failed: %d\n", ret);
+       }
+
+       mutex_unlock(&rdev->mutex);
+
+       if (rdev->supply) {
+               for (i = 0; i < count; i++) {
+                       ret = regulator_disable(rdev->supply);
+                       if (ret != 0) {
+                               rdev_err(rdev,
+                                        "Supply disable failed: %d\n", ret);
+                       }
+               }
+       }
+}
+
+/**
+ * regulator_disable_deferred - disable regulator output with delay
+ * @regulator: regulator source
+ * @ms: miliseconds until the regulator is disabled
+ *
+ * Execute regulator_disable() on the regulator after a delay.  This
+ * is intended for use with devices that require some time to quiesce.
+ *
+ * NOTE: this will only disable the regulator output if no other consumer
+ * devices have it enabled, the regulator device supports disabling and
+ * machine constraints permit this operation.
+ */
+int regulator_disable_deferred(struct regulator *regulator, int ms)
+{
+       struct regulator_dev *rdev = regulator->rdev;
+
+       mutex_lock(&rdev->mutex);
+       rdev->deferred_disables++;
+       mutex_unlock(&rdev->mutex);
+
+       return schedule_delayed_work(&rdev->disable_work,
+                                    msecs_to_jiffies(ms));
+}
+EXPORT_SYMBOL_GPL(regulator_disable_deferred);
+
 static int _regulator_is_enabled(struct regulator_dev *rdev)
 {
        /* If we don't know then assume that the regulator is always on */
@@ -2622,6 +2679,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        INIT_LIST_HEAD(&rdev->consumer_list);
        INIT_LIST_HEAD(&rdev->list);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
+       INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
 
        /* preform any regulator specific init */
        if (init_data->regulator_init) {
@@ -2729,6 +2787,7 @@ void regulator_unregister(struct regulator_dev *rdev)
 #ifdef CONFIG_DEBUG_FS
        debugfs_remove_recursive(rdev->debugfs);
 #endif
+       flush_work_sync(&rdev->disable_work.work);
        WARN_ON(rdev->open_count);
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
index 4c806f6d663e0d0f9cbc03d221577f4e7190dea9..d9e05eabef33a2104f9f268406a5843d3df8d16e 100644 (file)
 #define TWL6040_REG_ACCCTL             0x2D
 #define TWL6040_REG_STATUS             0x2E
 
-#define TWL6040_CACHEREGNUM            (TWL6040_REG_STATUS + 1)
-
-#define TWL6040_VIOREGNUM              18
-#define TWL6040_VDDREGNUM              21
-
 /* INTID (0x03) fields */
 
 #define TWL6040_THINT                  0x01
 #define TWL6040_LPLLFIN                        0x08
 #define TWL6040_HPLLSEL                        0x10
 
-/* HSLCTL (0x10) fields */
-
-#define TWL6040_HSDACMODEL             0x02
-#define TWL6040_HSDRVMODEL             0x08
+/* HSLCTL/R (0x10/0x11) fields */
 
-/* HSRCTL (0x11) fields */
-
-#define TWL6040_HSDACMODER             0x02
-#define TWL6040_HSDRVMODER             0x08
+#define TWL6040_HSDACMODE              (1 << 1)
+#define TWL6040_HSDRVMODE              (1 << 3)
 
 /* VIBCTLL (0x18) fields */
 
@@ -225,4 +215,9 @@ unsigned int twl6040_get_sysclk(struct twl6040 *twl6040);
 int twl6040_irq_init(struct twl6040 *twl6040);
 void twl6040_irq_exit(struct twl6040 *twl6040);
 
+static inline int twl6040_get_revid(struct twl6040 *twl6040)
+{
+       return twl6040->rev;
+}
+
 #endif  /* End of __TWL6040_CODEC_H__ */
index f3ee84284670f5e42fc4871cdfc18bc2f7171d87..83ecdcd8aaf90393e6044b76e9110ce61bada806 100644 (file)
@@ -72,6 +72,7 @@
 #define WM8994_DC_SERVO_2                       0x55
 #define WM8994_DC_SERVO_4                       0x57
 #define WM8994_DC_SERVO_READBACK                0x58
+#define WM8994_DC_SERVO_4E                     0x59
 #define WM8994_ANALOGUE_HP_1                    0x60
 #define WM8958_MIC_DETECT_1                     0xD0
 #define WM8958_MIC_DETECT_2                     0xD1
 #define WM8994_AIF1_DAC1_FILTERS_2              0x421
 #define WM8994_AIF1_DAC2_FILTERS_1              0x422
 #define WM8994_AIF1_DAC2_FILTERS_2              0x423
+#define WM8958_AIF1_DAC1_NOISE_GATE             0x430
+#define WM8958_AIF1_DAC2_NOISE_GATE             0x431
 #define WM8994_AIF1_DRC1_1                      0x440
 #define WM8994_AIF1_DRC1_2                      0x441
 #define WM8994_AIF1_DRC1_3                      0x442
 #define WM8994_AIF2_ADC_FILTERS                 0x510
 #define WM8994_AIF2_DAC_FILTERS_1               0x520
 #define WM8994_AIF2_DAC_FILTERS_2               0x521
+#define WM8958_AIF2_DAC_NOISE_GATE              0x530
 #define WM8994_AIF2_DRC_1                       0x540
 #define WM8994_AIF2_DRC_2                       0x541
 #define WM8994_AIF2_DRC_3                       0x542
 #define WM8994_LDO2_DISCH_SHIFT                      0  /* LDO2_DISCH */
 #define WM8994_LDO2_DISCH_WIDTH                      1  /* LDO2_DISCH */
 
+/*
+ * R61 (0x3D) - MICBIAS1
+ */
+#define WM8958_MICB1_RATE                       0x0020  /* MICB1_RATE */
+#define WM8958_MICB1_RATE_MASK                  0x0020  /* MICB1_RATE */
+#define WM8958_MICB1_RATE_SHIFT                      5  /* MICB1_RATE */
+#define WM8958_MICB1_RATE_WIDTH                      1  /* MICB1_RATE */
+#define WM8958_MICB1_MODE                       0x0010  /* MICB1_MODE */
+#define WM8958_MICB1_MODE_MASK                  0x0010  /* MICB1_MODE */
+#define WM8958_MICB1_MODE_SHIFT                      4  /* MICB1_MODE */
+#define WM8958_MICB1_MODE_WIDTH                      1  /* MICB1_MODE */
+#define WM8958_MICB1_LVL_MASK                   0x000E  /* MICB1_LVL - [3:1] */
+#define WM8958_MICB1_LVL_SHIFT                       1  /* MICB1_LVL - [3:1] */
+#define WM8958_MICB1_LVL_WIDTH                       3  /* MICB1_LVL - [3:1] */
+#define WM8958_MICB1_DISCH                      0x0001  /* MICB1_DISCH */
+#define WM8958_MICB1_DISCH_MASK                 0x0001  /* MICB1_DISCH */
+#define WM8958_MICB1_DISCH_SHIFT                     0  /* MICB1_DISCH */
+#define WM8958_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
+
+/*
+ * R62 (0x3E) - MICBIAS2
+ */
+#define WM8958_MICB2_RATE                       0x0020  /* MICB2_RATE */
+#define WM8958_MICB2_RATE_MASK                  0x0020  /* MICB2_RATE */
+#define WM8958_MICB2_RATE_SHIFT                      5  /* MICB2_RATE */
+#define WM8958_MICB2_RATE_WIDTH                      1  /* MICB2_RATE */
+#define WM8958_MICB2_MODE                       0x0010  /* MICB2_MODE */
+#define WM8958_MICB2_MODE_MASK                  0x0010  /* MICB2_MODE */
+#define WM8958_MICB2_MODE_SHIFT                      4  /* MICB2_MODE */
+#define WM8958_MICB2_MODE_WIDTH                      1  /* MICB2_MODE */
+#define WM8958_MICB2_LVL_MASK                   0x000E  /* MICB2_LVL - [3:1] */
+#define WM8958_MICB2_LVL_SHIFT                       1  /* MICB2_LVL - [3:1] */
+#define WM8958_MICB2_LVL_WIDTH                       3  /* MICB2_LVL - [3:1] */
+#define WM8958_MICB2_DISCH                      0x0001  /* MICB2_DISCH */
+#define WM8958_MICB2_DISCH_MASK                 0x0001  /* MICB2_DISCH */
+#define WM8958_MICB2_DISCH_SHIFT                     0  /* MICB2_DISCH */
+#define WM8958_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
+
 /*
  * R76 (0x4C) - Charge Pump (1)
  */
 #define WM8994_AIF1DAC2_3D_ENA_SHIFT                 8  /* AIF1DAC2_3D_ENA */
 #define WM8994_AIF1DAC2_3D_ENA_WIDTH                 1  /* AIF1DAC2_3D_ENA */
 
+/*
+ * R1072 (0x430) - AIF1 DAC1 Noise Gate
+ */
+#define WM8958_AIF1DAC1_NG_HLD_MASK             0x0060  /* AIF1DAC1_NG_HLD - [6:5] */
+#define WM8958_AIF1DAC1_NG_HLD_SHIFT                 5  /* AIF1DAC1_NG_HLD - [6:5] */
+#define WM8958_AIF1DAC1_NG_HLD_WIDTH                 2  /* AIF1DAC1_NG_HLD - [6:5] */
+#define WM8958_AIF1DAC1_NG_THR_MASK             0x000E  /* AIF1DAC1_NG_THR - [3:1] */
+#define WM8958_AIF1DAC1_NG_THR_SHIFT                 1  /* AIF1DAC1_NG_THR - [3:1] */
+#define WM8958_AIF1DAC1_NG_THR_WIDTH                 3  /* AIF1DAC1_NG_THR - [3:1] */
+#define WM8958_AIF1DAC1_NG_ENA                  0x0001  /* AIF1DAC1_NG_ENA */
+#define WM8958_AIF1DAC1_NG_ENA_MASK             0x0001  /* AIF1DAC1_NG_ENA */
+#define WM8958_AIF1DAC1_NG_ENA_SHIFT                 0  /* AIF1DAC1_NG_ENA */
+#define WM8958_AIF1DAC1_NG_ENA_WIDTH                 1  /* AIF1DAC1_NG_ENA */
+
+/*
+ * R1073 (0x431) - AIF1 DAC2 Noise Gate
+ */
+#define WM8958_AIF1DAC2_NG_HLD_MASK             0x0060  /* AIF1DAC2_NG_HLD - [6:5] */
+#define WM8958_AIF1DAC2_NG_HLD_SHIFT                 5  /* AIF1DAC2_NG_HLD - [6:5] */
+#define WM8958_AIF1DAC2_NG_HLD_WIDTH                 2  /* AIF1DAC2_NG_HLD - [6:5] */
+#define WM8958_AIF1DAC2_NG_THR_MASK             0x000E  /* AIF1DAC2_NG_THR - [3:1] */
+#define WM8958_AIF1DAC2_NG_THR_SHIFT                 1  /* AIF1DAC2_NG_THR - [3:1] */
+#define WM8958_AIF1DAC2_NG_THR_WIDTH                 3  /* AIF1DAC2_NG_THR - [3:1] */
+#define WM8958_AIF1DAC2_NG_ENA                  0x0001  /* AIF1DAC2_NG_ENA */
+#define WM8958_AIF1DAC2_NG_ENA_MASK             0x0001  /* AIF1DAC2_NG_ENA */
+#define WM8958_AIF1DAC2_NG_ENA_SHIFT                 0  /* AIF1DAC2_NG_ENA */
+#define WM8958_AIF1DAC2_NG_ENA_WIDTH                 1  /* AIF1DAC2_NG_ENA */
+
 /*
  * R1088 (0x440) - AIF1 DRC1 (1)
  */
 #define WM8994_AIF2DAC_3D_ENA_SHIFT                  8  /* AIF2DAC_3D_ENA */
 #define WM8994_AIF2DAC_3D_ENA_WIDTH                  1  /* AIF2DAC_3D_ENA */
 
+/*
+ * R1328 (0x530) - AIF2 DAC Noise Gate
+ */
+#define WM8958_AIF2DAC_NG_HLD_MASK              0x0060  /* AIF2DAC_NG_HLD - [6:5] */
+#define WM8958_AIF2DAC_NG_HLD_SHIFT                  5  /* AIF2DAC_NG_HLD - [6:5] */
+#define WM8958_AIF2DAC_NG_HLD_WIDTH                  2  /* AIF2DAC_NG_HLD - [6:5] */
+#define WM8958_AIF2DAC_NG_THR_MASK              0x000E  /* AIF2DAC_NG_THR - [3:1] */
+#define WM8958_AIF2DAC_NG_THR_SHIFT                  1  /* AIF2DAC_NG_THR - [3:1] */
+#define WM8958_AIF2DAC_NG_THR_WIDTH                  3  /* AIF2DAC_NG_THR - [3:1] */
+#define WM8958_AIF2DAC_NG_ENA                   0x0001  /* AIF2DAC_NG_ENA */
+#define WM8958_AIF2DAC_NG_ENA_MASK              0x0001  /* AIF2DAC_NG_ENA */
+#define WM8958_AIF2DAC_NG_ENA_SHIFT                  0  /* AIF2DAC_NG_ENA */
+#define WM8958_AIF2DAC_NG_ENA_WIDTH                  1  /* AIF2DAC_NG_ENA */
+
 /*
  * R1344 (0x540) - AIF2 DRC (1)
  */
index 60a65cd7e1a01baef9007e0c97d4aca1d6d04b7b..003c05349ae5ba452ac73ae85e49b69c0c16e2e8 100644 (file)
 struct i2c_client;
 struct spi_device;
 
+/**
+ * Default value for a register.  We use an array of structs rather
+ * than a simple array as many modern devices have very sparse
+ * register maps.
+ *
+ * @reg: Register address.
+ * @def: Register default value.
+ */
+struct reg_default {
+       unsigned int reg;
+       unsigned int def;
+};
+
+/**
+ * Configuration for the register map of a device.
+ *
+ * @reg_bits: Number of bits in a register address, mandatory.
+ * @val_bits: Number of bits in a register value, mandatory.
+ *
+ * @writeable_reg: Optional callback returning true if the register
+ *                 can be written to.
+ * @readable_reg: Optional callback returning true if the register
+ *                can be read from.
+ * @volatile_reg: Optional callback returning true if the register
+ *                value can't be cached.
+ * @precious_reg: Optional callback returning true if the rgister
+ *                should not be read outside of a call from the driver
+ *                (eg, a clear on read interrupt status register).
+ *
+ * @max_register: Optional, specifies the maximum valid register index.
+ * @reg_defaults: Power on reset values for registers (for use with
+ *                register cache support).
+ * @num_reg_defaults: Number of elements in reg_defaults.
+ *
+ * @read_flag_mask: Mask to be set in the top byte of the register when doing
+ *                  a read.
+ * @write_flag_mask: Mask to be set in the top byte of the register when doing
+ *                   a write. If both read_flag_mask and write_flag_mask are
+ *                   empty the regmap_bus default masks are used.
+ */
 struct regmap_config {
        int reg_bits;
        int val_bits;
+
+       bool (*writeable_reg)(struct device *dev, unsigned int reg);
+       bool (*readable_reg)(struct device *dev, unsigned int reg);
+       bool (*volatile_reg)(struct device *dev, unsigned int reg);
+       bool (*precious_reg)(struct device *dev, unsigned int reg);
+
+       unsigned int max_register;
+       struct reg_default *reg_defaults;
+       int num_reg_defaults;
+
+       u8 read_flag_mask;
+       u8 write_flag_mask;
 };
 
 typedef int (*regmap_hw_write)(struct device *dev, const void *data,
index 26f6ea4444e39fedda935b5505439a6de3301f41..6fae97a6ce7d55bf3b22d9e727b4e77b30ebc2b7 100644 (file)
@@ -141,6 +141,7 @@ int regulator_enable(struct regulator *regulator);
 int regulator_disable(struct regulator *regulator);
 int regulator_force_disable(struct regulator *regulator);
 int regulator_is_enabled(struct regulator *regulator);
+int regulator_disable_deferred(struct regulator *regulator, int ms);
 
 int regulator_bulk_get(struct device *dev, int num_consumers,
                       struct regulator_bulk_data *consumers);
@@ -211,6 +212,12 @@ static inline int regulator_disable(struct regulator *regulator)
        return 0;
 }
 
+static inline int regulator_disable_deferred(struct regulator *regulator,
+                                            int ms)
+{
+       return 0;
+}
+
 static inline int regulator_is_enabled(struct regulator *regulator)
 {
        return 1;
index 1a80bc77517d03870ea9f34a6d2c317953445bc4..12a1aa04b720cdb3491a2d35f32cb85a9bdcc6ff 100644 (file)
@@ -199,6 +199,9 @@ struct regulator_dev {
        struct regulation_constraints *constraints;
        struct regulator *supply;       /* for tree */
 
+       struct delayed_work disable_work;
+       int deferred_disables;
+
        void *reg_data;         /* regulator_dev data */
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/include/sound/adau1373.h b/include/sound/adau1373.h
new file mode 100644 (file)
index 0000000..1b19c76
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Analog Devices ADAU1373 Audio Codec drive
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __SOUND_ADAU1373_H__
+#define __SOUND_ADAU1373_H__
+
+enum adau1373_micbias_voltage {
+       ADAU1373_MICBIAS_2_9V = 0,
+       ADAU1373_MICBIAS_2_2V = 1,
+       ADAU1373_MICBIAS_2_6V = 2,
+       ADAU1373_MICBIAS_1_8V = 3,
+};
+
+#define ADAU1373_DRC_SIZE 13
+
+struct adau1373_platform_data {
+       bool input_differential[4];
+       bool lineout_differential;
+       bool lineout_ground_sense;
+
+       unsigned int num_drc;
+       uint8_t drc_setting[3][ADAU1373_DRC_SIZE];
+
+       enum adau1373_micbias_voltage micbias1;
+       enum adau1373_micbias_voltage micbias2;
+};
+
+#endif
diff --git a/include/sound/saif.h b/include/sound/saif.h
new file mode 100644 (file)
index 0000000..d0e0de7
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 __SOUND_SAIF_H__
+#define __SOUND_SAIF_H__
+
+struct mxs_saif_platform_data {
+       int (*init) (void);
+       int (*get_master_id) (unsigned int saif_id);
+};
+#endif
index 5ad5f3a50c68ec09122de85e2199c351f3ab9fd5..2413acc54883aad471cf0256b3fc2f8fc6d7ae11 100644 (file)
@@ -24,13 +24,13 @@ struct snd_pcm_substream;
  * Describes the physical PCM data formating and clocking. Add new formats
  * to the end.
  */
-#define SND_SOC_DAIFMT_I2S             0 /* I2S mode */
-#define SND_SOC_DAIFMT_RIGHT_J         1 /* Right Justified mode */
-#define SND_SOC_DAIFMT_LEFT_J          2 /* Left Justified mode */
-#define SND_SOC_DAIFMT_DSP_A           3 /* L data MSB after FRM LRC */
-#define SND_SOC_DAIFMT_DSP_B           4 /* L data MSB during FRM LRC */
-#define SND_SOC_DAIFMT_AC97            5 /* AC97 */
-#define SND_SOC_DAIFMT_PDM             6 /* Pulse density modulation */
+#define SND_SOC_DAIFMT_I2S             1 /* I2S mode */
+#define SND_SOC_DAIFMT_RIGHT_J         2 /* Right Justified mode */
+#define SND_SOC_DAIFMT_LEFT_J          3 /* Left Justified mode */
+#define SND_SOC_DAIFMT_DSP_A           4 /* L data MSB after FRM LRC */
+#define SND_SOC_DAIFMT_DSP_B           5 /* L data MSB during FRM LRC */
+#define SND_SOC_DAIFMT_AC97            6 /* AC97 */
+#define SND_SOC_DAIFMT_PDM             7 /* Pulse density modulation */
 
 /* left and right justified also known as MSB and LSB respectively */
 #define SND_SOC_DAIFMT_MSB             SND_SOC_DAIFMT_LEFT_J
@@ -42,8 +42,8 @@ struct snd_pcm_substream;
  * DAI bit clocks can be be gated (disabled) when the DAI is not
  * sending or receiving PCM data in a frame. This can be used to save power.
  */
-#define SND_SOC_DAIFMT_CONT            (0 << 4) /* continuous clock */
-#define SND_SOC_DAIFMT_GATED           (1 << 4) /* clock is gated */
+#define SND_SOC_DAIFMT_CONT            (1 << 4) /* continuous clock */
+#define SND_SOC_DAIFMT_GATED           (2 << 4) /* clock is gated */
 
 /*
  * DAI hardware signal inversions.
@@ -51,10 +51,10 @@ struct snd_pcm_substream;
  * Specifies whether the DAI can also support inverted clocks for the specified
  * format.
  */
-#define SND_SOC_DAIFMT_NB_NF           (0 << 8) /* normal bit clock + frame */
-#define SND_SOC_DAIFMT_NB_IF           (1 << 8) /* normal BCLK + inv FRM */
-#define SND_SOC_DAIFMT_IB_NF           (2 << 8) /* invert BCLK + nor FRM */
-#define SND_SOC_DAIFMT_IB_IF           (3 << 8) /* invert BCLK + FRM */
+#define SND_SOC_DAIFMT_NB_NF           (1 << 8) /* normal bit clock + frame */
+#define SND_SOC_DAIFMT_NB_IF           (2 << 8) /* normal BCLK + inv FRM */
+#define SND_SOC_DAIFMT_IB_NF           (3 << 8) /* invert BCLK + nor FRM */
+#define SND_SOC_DAIFMT_IB_IF           (4 << 8) /* invert BCLK + FRM */
 
 /*
  * DAI hardware clock masters.
@@ -63,10 +63,10 @@ struct snd_pcm_substream;
  * i.e. if the codec is clk and FRM master then the interface is
  * clk and frame slave.
  */
-#define SND_SOC_DAIFMT_CBM_CFM         (0 << 12) /* codec clk & FRM master */
-#define SND_SOC_DAIFMT_CBS_CFM         (1 << 12) /* codec clk slave & FRM master */
-#define SND_SOC_DAIFMT_CBM_CFS         (2 << 12) /* codec clk master & frame slave */
-#define SND_SOC_DAIFMT_CBS_CFS         (3 << 12) /* codec clk & FRM slave */
+#define SND_SOC_DAIFMT_CBM_CFM         (1 << 12) /* codec clk & FRM master */
+#define SND_SOC_DAIFMT_CBS_CFM         (2 << 12) /* codec clk slave & FRM master */
+#define SND_SOC_DAIFMT_CBM_CFS         (3 << 12) /* codec clk master & frame slave */
+#define SND_SOC_DAIFMT_CBS_CFS         (4 << 12) /* codec clk & FRM slave */
 
 #define SND_SOC_DAIFMT_FORMAT_MASK     0x000f
 #define SND_SOC_DAIFMT_CLOCK_MASK      0x00f0
@@ -242,6 +242,9 @@ struct snd_soc_dai {
        void *playback_dma_data;
        void *capture_dma_data;
 
+       /* Symmetry data - only valid if symmetry is being enforced */
+       unsigned int rate;
+
        /* parent platform/codec */
        union {
                struct snd_soc_platform *platform;
index e0583b7769cb505648f005be33f8b6c10f3c4049..bb5953219d0b342d6feecd97d0ad76ad25202297 100644 (file)
@@ -524,6 +524,8 @@ struct snd_soc_dapm_context {
        enum snd_soc_bias_level target_bias_level;
        struct list_head list;
 
+       int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
+
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_dapm;
 #endif
@@ -535,4 +537,10 @@ struct snd_soc_dapm_widget_list {
        struct snd_soc_dapm_widget *widgets[0];
 };
 
+struct snd_soc_dapm_stats {
+       int power_checks;
+       int path_checks;
+       int neighbour_checks;
+};
+
 #endif
index aa19f5a32ba8774a085a085d52866ede8d63fd3f..a4dc699d4801b21d99f42e2354b2b6cbbdea4197 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/regmap.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/control.h>
@@ -260,6 +261,7 @@ extern struct snd_ac97_bus_ops soc_ac97_ops;
 enum snd_soc_control_type {
        SND_SOC_I2C = 1,
        SND_SOC_SPI,
+       SND_SOC_REGMAP,
 };
 
 enum snd_soc_compress_type {
@@ -274,7 +276,7 @@ enum snd_soc_pcm_subclass {
 };
 
 int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
-                            unsigned int freq, int dir);
+                            int source, unsigned int freq, int dir);
 int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
                          unsigned int freq_in, unsigned int freq_out);
 
@@ -576,6 +578,7 @@ struct snd_soc_codec {
        const void *reg_def_copy;
        const struct snd_soc_cache_ops *cache_ops;
        struct mutex cache_rw_mutex;
+       int val_bytes;
 
        /* dapm */
        struct snd_soc_dapm_context dapm;
@@ -607,7 +610,7 @@ struct snd_soc_codec_driver {
 
        /* codec wide operations */
        int (*set_sysclk)(struct snd_soc_codec *codec,
-                         int clk_id, unsigned int freq, int dir);
+                         int clk_id, int source, unsigned int freq, int dir);
        int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
                unsigned int freq_in, unsigned int freq_out);
 
@@ -619,7 +622,7 @@ struct snd_soc_codec_driver {
        int (*volatile_register)(struct snd_soc_codec *, unsigned int);
        int (*readable_register)(struct snd_soc_codec *, unsigned int);
        int (*writable_register)(struct snd_soc_codec *, unsigned int);
-       short reg_cache_size;
+       unsigned int reg_cache_size;
        short reg_cache_step;
        short reg_word_size;
        const void *reg_cache_default;
@@ -630,10 +633,14 @@ struct snd_soc_codec_driver {
        /* codec bias level */
        int (*set_bias_level)(struct snd_soc_codec *,
                              enum snd_soc_bias_level level);
+       bool idle_bias_off;
 
        void (*seq_notifier)(struct snd_soc_dapm_context *,
                             enum snd_soc_dapm_type, int);
 
+       /* codec stream completion event */
+       int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
+
        /* probe ordering - for components with runtime dependencies */
        int probe_order;
        int remove_order;
@@ -669,6 +676,9 @@ struct snd_soc_platform_driver {
        /* platform stream ops */
        struct snd_pcm_ops *ops;
 
+       /* platform stream completion event */
+       int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
+
        /* probe ordering - for components with runtime dependencies */
        int probe_order;
        int remove_order;
@@ -703,6 +713,8 @@ struct snd_soc_dai_link {
        const char *cpu_dai_name;
        const char *codec_dai_name;
 
+       unsigned int dai_fmt;           /* format to set on init */
+
        /* Keep DAI active over suspend */
        unsigned int ignore_suspend:1;
 
@@ -818,6 +830,7 @@ struct snd_soc_card {
 
        /* Generic DAPM context for the card */
        struct snd_soc_dapm_context dapm;
+       struct snd_soc_dapm_stats dapm_stats;
 
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_card_root;
@@ -840,8 +853,6 @@ struct snd_soc_pcm_runtime  {
        unsigned int complete:1;
        unsigned int dev_registered:1;
 
-       /* Symmetry data - only valid if symmetry is being enforced */
-       unsigned int rate;
        long pmdown_time;
 
        /* runtime devices */
index 89beccb57edd578bfdf2f8d460204f71e4ea80b4..4cc1093844c8a8c319c4ade6e7d0e60b795c2642 100644 (file)
 #ifndef TPA6130A2_PLAT_H
 #define TPA6130A2_PLAT_H
 
-enum tpa_model {
-       TPA6130A2,
-       TPA6140A2,
-};
-
 struct tpa6130a2_platform_data {
-       enum tpa_model id;
        int power_gpio;
 };
 
diff --git a/include/sound/wm1250-ev1.h b/include/sound/wm1250-ev1.h
new file mode 100644 (file)
index 0000000..7dff828
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * linux/sound/wm1250-ev1.h - Platform data for WM1250-EV1
+ *
+ * Copyright 2011 Wolfson Microelectronics. PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_WM1250_EV1_H
+#define __LINUX_SND_WM1250_EV1_H
+
+#define WM1250_EV1_NUM_GPIOS 5
+
+#define WM1250_EV1_GPIO_CLK_ENA  0
+#define WM1250_EV1_GPIO_CLK_SEL0 1
+#define WM1250_EV1_GPIO_CLK_SEL1 2
+#define WM1250_EV1_GPIO_OSR      3
+#define WM1250_EV1_GPIO_MASTER   4
+
+
+struct wm1250_ev1_pdata {
+       int gpios[WM1250_EV1_NUM_GPIOS];
+};
+
+#endif
diff --git a/include/sound/wm5100.h b/include/sound/wm5100.h
new file mode 100644 (file)
index 0000000..617d0c4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * linux/sound/wm5100.h -- Platform data for WM5100
+ *
+ * Copyright 2011 Wolfson Microelectronics. PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_WM5100_H
+#define __LINUX_SND_WM5100_H
+
+enum wm5100_in_mode {
+       WM5100_IN_SE = 0,
+       WM5100_IN_DIFF = 1,
+       WM5100_IN_DMIC = 2,
+};
+
+enum wm5100_dmic_sup {
+       WM5100_DMIC_SUP_MICVDD = 0,
+       WM5100_DMIC_SUP_MICBIAS1 = 1,
+       WM5100_DMIC_SUP_MICBIAS2 = 2,
+       WM5100_DMIC_SUP_MICBIAS3 = 3,
+};
+
+enum wm5100_micdet_bias {
+       WM5100_MICDET_MICBIAS1 = 0,
+       WM5100_MICDET_MICBIAS2 = 1,
+       WM5100_MICDET_MICBIAS3 = 2,
+};
+
+struct wm5100_jack_mode {
+       enum wm5100_micdet_bias bias;
+       int hp_pol;
+       int micd_src;
+};
+
+#define WM5100_GPIO_SET 0x10000
+
+struct wm5100_pdata {
+       int reset;      /** GPIO controlling /RESET, if any */
+       int ldo_ena;    /** GPIO controlling LODENA, if any */
+       int hp_pol;     /** GPIO controlling headset polarity, if any */
+       int irq_flags;
+       int gpio_base;
+
+       struct wm5100_jack_mode jack_modes[2];
+
+       /* Input pin mode selection */
+       enum wm5100_in_mode in_mode[4];
+
+       /* DMIC supply selection */
+       enum wm5100_dmic_sup dmic_sup[4];
+
+       int gpio_defaults[6];
+};
+
+#endif
index 603f5a0f0365019eb758d2d2aec492a1b8f89b6c..ab26f8aa3c781819ca442268acf5b9f81ff8d6c7 100644 (file)
@@ -216,6 +216,31 @@ DEFINE_EVENT(snd_soc_dapm_widget, snd_soc_dapm_widget_event_done,
 
 );
 
+TRACE_EVENT(snd_soc_dapm_walk_done,
+
+       TP_PROTO(struct snd_soc_card *card),
+
+       TP_ARGS(card),
+
+       TP_STRUCT__entry(
+               __string(       name,   card->name              )
+               __field(        int,    power_checks            )
+               __field(        int,    path_checks             )
+               __field(        int,    neighbour_checks        )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, card->name);
+               __entry->power_checks = card->dapm_stats.power_checks;
+               __entry->path_checks = card->dapm_stats.path_checks;
+               __entry->neighbour_checks = card->dapm_stats.neighbour_checks;
+       ),
+
+       TP_printk("%s: checks %d power, %d path, %d neighbour",
+                 __get_str(name), (int)__entry->power_checks,
+                 (int)__entry->path_checks, (int)__entry->neighbour_checks)
+);
+
 TRACE_EVENT(snd_soc_jack_irq,
 
        TP_PROTO(const char *name),
index a9823fad85c2d9ecaf0bbc2bfd0ad13d3e254796..77dd0a13aecc40f59ac9361f241f376a61173934 100644 (file)
@@ -23,12 +23,15 @@ config SND_SGI_HAL2
 
 
 config SND_AU1X00
-       tristate "Au1x00 AC97 Port Driver"
+       tristate "Au1x00 AC97 Port Driver (DEPRECATED)"
        depends on SOC_AU1000 || SOC_AU1100 || SOC_AU1500
        select SND_PCM
        select SND_AC97_CODEC
        help
          ALSA Sound driver for the Au1x00's AC97 port.
 
+         Newer drivers for ASoC are available, please do not use
+         this driver as it will be removed in the future.
+
 endif  # SND_MIPS
 
index 8224db5f0434ffa7c16b93899f06401ae7c9ed3b..1381db853ef0f8b5d875c6ba220de0f90476add5 100644 (file)
@@ -7,6 +7,8 @@ menuconfig SND_SOC
        select SND_PCM
        select AC97_BUS if SND_SOC_AC97_BUS
        select SND_JACK if INPUT=y || INPUT=SND
+       select REGMAP_I2C if I2C
+       select REGMAP_SPI if SPI_MASTER
        ---help---
 
          If you want ASoC support, you should say Y here and also to the
@@ -51,6 +53,7 @@ source "sound/soc/nuc900/Kconfig"
 source "sound/soc/omap/Kconfig"
 source "sound/soc/kirkwood/Kconfig"
 source "sound/soc/mid-x86/Kconfig"
+source "sound/soc/mxs/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/s6000/Kconfig"
index 4f913876f3324e0e29fa297560cfce2ec3b84bd4..9ea8ac827adc37327d955acd30a7639b571030d3 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_SND_SOC) += fsl/
 obj-$(CONFIG_SND_SOC)   += imx/
 obj-$(CONFIG_SND_SOC)  += jz4740/
 obj-$(CONFIG_SND_SOC)  += mid-x86/
+obj-$(CONFIG_SND_SOC)  += mxs/
 obj-$(CONFIG_SND_SOC)  += nuc900/
 obj-$(CONFIG_SND_SOC)  += omap/
 obj-$(CONFIG_SND_SOC)  += kirkwood/
index 1aac2f4dbcf61b84b4700c5179b03e8bee995f54..2909bfaed265b5d1778cda8141ca3539f122a37b 100644 (file)
@@ -383,14 +383,17 @@ static int __init playpaq_asoc_init(void)
        _gclk0 = clk_get(NULL, "gclk0");
        if (IS_ERR(_gclk0)) {
                _gclk0 = NULL;
+               ret = PTR_ERR(_gclk0);
                goto err_gclk0;
        }
        _pll0 = clk_get(NULL, "pll0");
        if (IS_ERR(_pll0)) {
                _pll0 = NULL;
+               ret = PTR_ERR(_pll0);
                goto err_pll0;
        }
-       if (clk_set_parent(_gclk0, _pll0)) {
+       ret = clk_set_parent(_gclk0, _pll0);
+       if (ret) {
                pr_warning("snd-soc-playpaq: "
                           "Failed to set PLL0 as parent for DAC clock\n");
                goto err_set_clk;
index 4b67140fdec3cb8e98b8ecc39dc54c8e8160ea86..6d592546e8fcc2bd2a0ea343baf929f0a930762f 100644 (file)
@@ -18,10 +18,38 @@ config SND_SOC_AU1XPSC_AC97
        select SND_AC97_CODEC
        select SND_SOC_AC97_BUS
 
+##
+## Au1000/1500/1100 DMA + AC97C/I2SC
+##
+config SND_SOC_AU1XAUDIO
+       tristate "SoC Audio for Au1000/Au1500/Au1100"
+       depends on MIPS_ALCHEMY
+       help
+         This is a driver set for the AC97 unit and the
+         old DMA controller as found on the Au1000/Au1500/Au1100 chips.
+
+config SND_SOC_AU1XAC97C
+       tristate
+       select AC97_BUS
+       select SND_AC97_CODEC
+       select SND_SOC_AC97_BUS
+
+config SND_SOC_AU1XI2SC
+       tristate
+
 
 ##
 ## Boards
 ##
+config SND_SOC_DB1000
+       tristate "DB1000 Audio support"
+       depends on SND_SOC_AU1XAUDIO
+       select SND_SOC_AU1XAC97C
+       select SND_SOC_AC97_CODEC
+       help
+         Select this option to enable AC97 audio on the early DB1x00 series
+         of boards (DB1000/DB1500/DB1100).
+
 config SND_SOC_DB1200
        tristate "DB1200 AC97+I2S audio support"
        depends on SND_SOC_AU1XPSC
index 16873076e8c44044a803076eff2cfabcd53cc000..920710514ea07baaaa734fb55fefe1a96ca92215 100644 (file)
@@ -3,11 +3,21 @@ snd-soc-au1xpsc-dbdma-objs := dbdma2.o
 snd-soc-au1xpsc-i2s-objs := psc-i2s.o
 snd-soc-au1xpsc-ac97-objs := psc-ac97.o
 
+# Au1000/1500/1100 Audio units
+snd-soc-au1x-dma-objs := dma.o
+snd-soc-au1x-ac97c-objs := ac97c.o
+snd-soc-au1x-i2sc-objs := i2sc.o
+
 obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o
 obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o
 obj-$(CONFIG_SND_SOC_AU1XPSC_AC97) += snd-soc-au1xpsc-ac97.o
+obj-$(CONFIG_SND_SOC_AU1XAUDIO) += snd-soc-au1x-dma.o
+obj-$(CONFIG_SND_SOC_AU1XAC97C) += snd-soc-au1x-ac97c.o
+obj-$(CONFIG_SND_SOC_AU1XI2SC) += snd-soc-au1x-i2sc.o
 
 # Boards
+snd-soc-db1000-objs := db1000.o
 snd-soc-db1200-objs := db1200.o
 
+obj-$(CONFIG_SND_SOC_DB1000) += snd-soc-db1000.o
 obj-$(CONFIG_SND_SOC_DB1200) += snd-soc-db1200.o
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
new file mode 100644 (file)
index 0000000..13802ff
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Au1000/Au1500/Au1100 AC97C controller driver for ASoC
+ *
+ * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
+ *
+ * based on the old ALSA driver originally written by
+ *                     Charles Eidsness <charles@cooper-street.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#include "psc.h"
+
+/* register offsets and bits */
+#define AC97_CONFIG    0x00
+#define AC97_STATUS    0x04
+#define AC97_DATA      0x08
+#define AC97_CMDRESP   0x0c
+#define AC97_ENABLE    0x10
+
+#define CFG_RC(x)      (((x) & 0x3ff) << 13)   /* valid rx slots mask */
+#define CFG_XS(x)      (((x) & 0x3ff) << 3)    /* valid tx slots mask */
+#define CFG_SG         (1 << 2)        /* sync gate */
+#define CFG_SN         (1 << 1)        /* sync control */
+#define CFG_RS         (1 << 0)        /* acrst# control */
+#define STAT_XU                (1 << 11)       /* tx underflow */
+#define STAT_XO                (1 << 10)       /* tx overflow */
+#define STAT_RU                (1 << 9)        /* rx underflow */
+#define STAT_RO                (1 << 8)        /* rx overflow */
+#define STAT_RD                (1 << 7)        /* codec ready */
+#define STAT_CP                (1 << 6)        /* command pending */
+#define STAT_TE                (1 << 4)        /* tx fifo empty */
+#define STAT_TF                (1 << 3)        /* tx fifo full */
+#define STAT_RE                (1 << 1)        /* rx fifo empty */
+#define STAT_RF                (1 << 0)        /* rx fifo full */
+#define CMD_SET_DATA(x)        (((x) & 0xffff) << 16)
+#define CMD_GET_DATA(x)        ((x) & 0xffff)
+#define CMD_READ       (1 << 7)
+#define CMD_WRITE      (0 << 7)
+#define CMD_IDX(x)     ((x) & 0x7f)
+#define EN_D           (1 << 1)        /* DISable bit */
+#define EN_CE          (1 << 0)        /* clock enable bit */
+
+/* how often to retry failed codec register reads/writes */
+#define AC97_RW_RETRIES        5
+
+#define AC97_RATES     \
+       SNDRV_PCM_RATE_CONTINUOUS
+
+#define AC97_FMTS      \
+       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE)
+
+/* instance data. There can be only one, MacLeod!!!!, fortunately there IS only
+ * once AC97C on early Alchemy chips. The newer ones aren't so lucky.
+ */
+static struct au1xpsc_audio_data *ac97c_workdata;
+#define ac97_to_ctx(x)         ac97c_workdata
+
+static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg)
+{
+       return __raw_readl(ctx->mmio + reg);
+}
+
+static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v)
+{
+       __raw_writel(v, ctx->mmio + reg);
+       wmb();
+}
+
+static unsigned short au1xac97c_ac97_read(struct snd_ac97 *ac97,
+                                         unsigned short r)
+{
+       struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
+       unsigned int tmo, retry;
+       unsigned long data;
+
+       data = ~0;
+       retry = AC97_RW_RETRIES;
+       do {
+               mutex_lock(&ctx->lock);
+
+               tmo = 5;
+               while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--)
+                       udelay(21);     /* wait an ac97 frame time */
+               if (!tmo) {
+                       pr_debug("ac97rd timeout #1\n");
+                       goto next;
+               }
+
+               WR(ctx, AC97_CMDRESP, CMD_IDX(r) | CMD_READ);
+
+               /* stupid errata: data is only valid for 21us, so
+                * poll, Forrest, poll...
+                */
+               tmo = 0x10000;
+               while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--)
+                       asm volatile ("nop");
+               data = RD(ctx, AC97_CMDRESP);
+
+               if (!tmo)
+                       pr_debug("ac97rd timeout #2\n");
+
+next:
+               mutex_unlock(&ctx->lock);
+       } while (--retry && !tmo);
+
+       pr_debug("AC97RD %04x %04lx %d\n", r, data, retry);
+
+       return retry ? data & 0xffff : 0xffff;
+}
+
+static void au1xac97c_ac97_write(struct snd_ac97 *ac97, unsigned short r,
+                                unsigned short v)
+{
+       struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
+       unsigned int tmo, retry;
+
+       retry = AC97_RW_RETRIES;
+       do {
+               mutex_lock(&ctx->lock);
+
+               for (tmo = 5; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--)
+                       udelay(21);
+               if (!tmo) {
+                       pr_debug("ac97wr timeout #1\n");
+                       goto next;
+               }
+
+               WR(ctx, AC97_CMDRESP, CMD_WRITE | CMD_IDX(r) | CMD_SET_DATA(v));
+
+               for (tmo = 10; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--)
+                       udelay(21);
+               if (!tmo)
+                       pr_debug("ac97wr timeout #2\n");
+next:
+               mutex_unlock(&ctx->lock);
+       } while (--retry && !tmo);
+
+       pr_debug("AC97WR %04x %04x %d\n", r, v, retry);
+}
+
+static void au1xac97c_ac97_warm_reset(struct snd_ac97 *ac97)
+{
+       struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
+
+       WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG | CFG_SN);
+       msleep(20);
+       WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG);
+       WR(ctx, AC97_CONFIG, ctx->cfg);
+}
+
+static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97)
+{
+       struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
+       int i;
+
+       WR(ctx, AC97_CONFIG, ctx->cfg | CFG_RS);
+       msleep(500);
+       WR(ctx, AC97_CONFIG, ctx->cfg);
+
+       /* wait for codec ready */
+       i = 50;
+       while (((RD(ctx, AC97_STATUS) & STAT_RD) == 0) && --i)
+               msleep(20);
+       if (!i)
+               printk(KERN_ERR "ac97c: codec not ready after cold reset\n");
+}
+
+/* AC97 controller operations */
+struct snd_ac97_bus_ops soc_ac97_ops = {
+       .read           = au1xac97c_ac97_read,
+       .write          = au1xac97c_ac97_write,
+       .reset          = au1xac97c_ac97_cold_reset,
+       .warm_reset     = au1xac97c_ac97_warm_reset,
+};
+EXPORT_SYMBOL_GPL(soc_ac97_ops);       /* globals be gone! */
+
+static int alchemy_ac97c_startup(struct snd_pcm_substream *substream,
+                                struct snd_soc_dai *dai)
+{
+       struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
+       snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]);
+       return 0;
+}
+
+static struct snd_soc_dai_ops alchemy_ac97c_ops = {
+       .startup                = alchemy_ac97c_startup,
+};
+
+static int au1xac97c_dai_probe(struct snd_soc_dai *dai)
+{
+       return ac97c_workdata ? 0 : -ENODEV;
+}
+
+static struct snd_soc_dai_driver au1xac97c_dai_driver = {
+       .name                   = "alchemy-ac97c",
+       .ac97_control           = 1,
+       .probe                  = au1xac97c_dai_probe,
+       .playback = {
+               .rates          = AC97_RATES,
+               .formats        = AC97_FMTS,
+               .channels_min   = 2,
+               .channels_max   = 2,
+       },
+       .capture = {
+               .rates          = AC97_RATES,
+               .formats        = AC97_FMTS,
+               .channels_min   = 2,
+               .channels_max   = 2,
+       },
+       .ops                    = &alchemy_ac97c_ops,
+};
+
+static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
+{
+       int ret;
+       struct resource *r;
+       struct au1xpsc_audio_data *ctx;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       mutex_init(&ctx->lock);
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               ret = -ENODEV;
+               goto out0;
+       }
+
+       ret = -EBUSY;
+       if (!request_mem_region(r->start, resource_size(r), pdev->name))
+               goto out0;
+
+       ctx->mmio = ioremap_nocache(r->start, resource_size(r));
+       if (!ctx->mmio)
+               goto out1;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!r)
+               goto out1;
+       ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!r)
+               goto out1;
+       ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+
+       /* switch it on */
+       WR(ctx, AC97_ENABLE, EN_D | EN_CE);
+       WR(ctx, AC97_ENABLE, EN_CE);
+
+       ctx->cfg = CFG_RC(3) | CFG_XS(3);
+       WR(ctx, AC97_CONFIG, ctx->cfg);
+
+       platform_set_drvdata(pdev, ctx);
+
+       ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver);
+       if (ret)
+               goto out1;
+
+       ac97c_workdata = ctx;
+       return 0;
+
+out1:
+       release_mem_region(r->start, resource_size(r));
+out0:
+       kfree(ctx);
+       return ret;
+}
+
+static int __devexit au1xac97c_drvremove(struct platform_device *pdev)
+{
+       struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
+       struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       snd_soc_unregister_dai(&pdev->dev);
+
+       WR(ctx, AC97_ENABLE, EN_D);     /* clock off, disable */
+
+       iounmap(ctx->mmio);
+       release_mem_region(r->start, resource_size(r));
+       kfree(ctx);
+
+       ac97c_workdata = NULL;  /* MDEV */
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1xac97c_drvsuspend(struct device *dev)
+{
+       struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
+
+       WR(ctx, AC97_ENABLE, EN_D);     /* clock off, disable */
+
+       return 0;
+}
+
+static int au1xac97c_drvresume(struct device *dev)
+{
+       struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
+
+       WR(ctx, AC97_ENABLE, EN_D | EN_CE);
+       WR(ctx, AC97_ENABLE, EN_CE);
+       WR(ctx, AC97_CONFIG, ctx->cfg);
+
+       return 0;
+}
+
+static const struct dev_pm_ops au1xpscac97_pmops = {
+       .suspend        = au1xac97c_drvsuspend,
+       .resume         = au1xac97c_drvresume,
+};
+
+#define AU1XPSCAC97_PMOPS (&au1xpscac97_pmops)
+
+#else
+
+#define AU1XPSCAC97_PMOPS NULL
+
+#endif
+
+static struct platform_driver au1xac97c_driver = {
+       .driver = {
+               .name   = "alchemy-ac97c",
+               .owner  = THIS_MODULE,
+               .pm     = AU1XPSCAC97_PMOPS,
+       },
+       .probe          = au1xac97c_drvprobe,
+       .remove         = __devexit_p(au1xac97c_drvremove),
+};
+
+static int __init au1xac97c_load(void)
+{
+       ac97c_workdata = NULL;
+       return platform_driver_register(&au1xac97c_driver);
+}
+
+static void __exit au1xac97c_unload(void)
+{
+       platform_driver_unregister(&au1xac97c_driver);
+}
+
+module_init(au1xac97c_load);
+module_exit(au1xac97c_unload);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver");
+MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/db1000.c b/sound/soc/au1x/db1000.c
new file mode 100644 (file)
index 0000000..127477a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * DB1000/DB1500/DB1100 ASoC audio fabric support code.
+ *
+ * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-db1x00/bcsr.h>
+
+#include "psc.h"
+
+static struct snd_soc_dai_link db1000_ac97_dai = {
+       .name           = "AC97",
+       .stream_name    = "AC97 HiFi",
+       .codec_dai_name = "ac97-hifi",
+       .cpu_dai_name   = "alchemy-ac97c",
+       .platform_name  = "alchemy-pcm-dma.0",
+       .codec_name     = "ac97-codec",
+};
+
+static struct snd_soc_card db1000_ac97 = {
+       .name           = "DB1000_AC97",
+       .dai_link       = &db1000_ac97_dai,
+       .num_links      = 1,
+};
+
+static int __devinit db1000_audio_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &db1000_ac97;
+       card->dev = &pdev->dev;
+       return snd_soc_register_card(card);
+}
+
+static int __devexit db1000_audio_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 db1000_audio_driver = {
+       .driver = {
+               .name   = "db1000-audio",
+               .owner  = THIS_MODULE,
+               .pm     = &snd_soc_pm_ops,
+       },
+       .probe          = db1000_audio_probe,
+       .remove         = __devexit_p(db1000_audio_remove),
+};
+
+static int __init db1000_audio_load(void)
+{
+       return platform_driver_register(&db1000_audio_driver);
+}
+
+static void __exit db1000_audio_unload(void)
+{
+       platform_driver_unregister(&db1000_audio_driver);
+}
+
+module_init(db1000_audio_load);
+module_exit(db1000_audio_unload);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DB1000/DB1500/DB1100 ASoC audio");
+MODULE_AUTHOR("Manuel Lauss");
index 1d3e258c9ea8ec861cf19c88a9bd7c99e5384940..289312c14b99bf62d13355e7ae5e585bf297991f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DB1200 ASoC audio fabric support code.
  *
- * (c) 2008-9 Manuel Lauss <manuel.lauss@gmail.com>
+ * (c) 2008-2011 Manuel Lauss <manuel.lauss@googlemail.com>
  *
  */
 
 #include "../codecs/wm8731.h"
 #include "psc.h"
 
+static struct platform_device_id db1200_pids[] = {
+       {
+               .name           = "db1200-ac97",
+               .driver_data    = 0,
+       }, {
+               .name           = "db1200-i2s",
+               .driver_data    = 1,
+       },
+       {},
+};
+
 /*-------------------------  AC97 PART  ---------------------------*/
 
 static struct snd_soc_dai_link db1200_ac97_dai = {
@@ -89,36 +100,47 @@ static struct snd_soc_card db1200_i2s_machine = {
 
 /*-------------------------  COMMON PART  ---------------------------*/
 
-static struct platform_device *db1200_asoc_dev;
+static struct snd_soc_card *db1200_cards[] __devinitdata = {
+       &db1200_ac97_machine,
+       &db1200_i2s_machine,
+};
 
-static int __init db1200_audio_load(void)
+static int __devinit db1200_audio_probe(struct platform_device *pdev)
 {
-       int ret;
+       const struct platform_device_id *pid = platform_get_device_id(pdev);
+       struct snd_soc_card *card;
 
-       ret = -ENOMEM;
-       db1200_asoc_dev = platform_device_alloc("soc-audio", 1); /* PSC1 */
-       if (!db1200_asoc_dev)
-               goto out;
+       card = db1200_cards[pid->driver_data];
+       card->dev = &pdev->dev;
+       return snd_soc_register_card(card);
+}
 
-       /* DB1200 board setup set PSC1MUX to preferred audio device */
-       if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX)
-               platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine);
-       else
-               platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine);
+static int __devexit db1200_audio_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       snd_soc_unregister_card(card);
+       return 0;
+}
 
-       ret = platform_device_add(db1200_asoc_dev);
+static struct platform_driver db1200_audio_driver = {
+       .driver = {
+               .name   = "db1200-ac97",
+               .owner  = THIS_MODULE,
+               .pm     = &snd_soc_pm_ops,
+       },
+       .id_table       = db1200_pids,
+       .probe          = db1200_audio_probe,
+       .remove         = __devexit_p(db1200_audio_remove),
+};
 
-       if (ret) {
-               platform_device_put(db1200_asoc_dev);
-               db1200_asoc_dev = NULL;
-       }
-out:
-       return ret;
+static int __init db1200_audio_load(void)
+{
+       return platform_driver_register(&db1200_audio_driver);
 }
 
 static void __exit db1200_audio_unload(void)
 {
-       platform_device_unregister(db1200_asoc_dev);
+       platform_driver_unregister(&db1200_audio_driver);
 }
 
 module_init(db1200_audio_load);
index 20bb53a837b152b7e207dfc691d59a76222d221f..d7d04e26eee504524f7952c86825b44c5d7a4fa7 100644 (file)
@@ -169,7 +169,7 @@ static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd,
 
        au1x_pcm_dbdma_free(pcd);
 
-       if (stype == PCM_RX)
+       if (stype == SNDRV_PCM_STREAM_CAPTURE)
                pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id,
                                        DSCR_CMD0_ALWAYS,
                                        au1x_pcm_dmarx_cb, (void *)pcd);
@@ -198,7 +198,7 @@ static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream
        struct snd_soc_pcm_runtime *rtd = ss->private_data;
        struct au1xpsc_audio_dmadata *pcd =
                                snd_soc_platform_get_drvdata(rtd->platform);
-       return &pcd[SUBSTREAM_TYPE(ss)];
+       return &pcd[ss->stream];
 }
 
 static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -212,7 +212,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                goto out;
 
-       stype = SUBSTREAM_TYPE(substream);
+       stype = substream->stream;
        pcd = to_dmadata(substream);
 
        DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
@@ -255,7 +255,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
 
        au1xxx_dbdma_reset(pcd->ddma_chan);
 
-       if (SUBSTREAM_TYPE(substream) == PCM_RX) {
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
                au1x_pcm_queue_rx(pcd);
                au1x_pcm_queue_rx(pcd);
        } else {
@@ -293,6 +293,16 @@ au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
 
 static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
 {
+       struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream);
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int stype = substream->stream, *dmaids;
+
+       dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+       if (!dmaids)
+               return -ENODEV; /* whoa, has ordering changed? */
+
+       pcd->ddma_id = dmaids[stype];
+
        snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware);
        return 0;
 }
@@ -340,36 +350,18 @@ struct snd_soc_platform_driver au1xpsc_soc_platform = {
 static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
 {
        struct au1xpsc_audio_dmadata *dmadata;
-       struct resource *r;
        int ret;
 
        dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
        if (!dmadata)
                return -ENOMEM;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!r) {
-               ret = -ENODEV;
-               goto out1;
-       }
-       dmadata[PCM_TX].ddma_id = r->start;
-
-       /* RX DMA */
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (!r) {
-               ret = -ENODEV;
-               goto out1;
-       }
-       dmadata[PCM_RX].ddma_id = r->start;
-
        platform_set_drvdata(pdev, dmadata);
 
        ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
-       if (!ret)
-               return ret;
+       if (ret)
+               kfree(dmadata);
 
-out1:
-       kfree(dmadata);
        return ret;
 }
 
@@ -405,57 +397,6 @@ static void __exit au1xpsc_audio_dbdma_unload(void)
 module_init(au1xpsc_audio_dbdma_load);
 module_exit(au1xpsc_audio_dbdma_unload);
 
-
-struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
-{
-       struct resource *res, *r;
-       struct platform_device *pd;
-       int id[2];
-       int ret;
-
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!r)
-               return NULL;
-       id[0] = r->start;
-
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (!r)
-               return NULL;
-       id[1] = r->start;
-
-       res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-       if (!res)
-               return NULL;
-
-       res[0].start = res[0].end = id[0];
-       res[1].start = res[1].end = id[1];
-       res[0].flags = res[1].flags = IORESOURCE_DMA;
-
-       pd = platform_device_alloc("au1xpsc-pcm", pdev->id);
-       if (!pd)
-               goto out;
-
-       pd->resource = res;
-       pd->num_resources = 2;
-
-       ret = platform_device_add(pd);
-       if (!ret)
-               return pd;
-
-       platform_device_put(pd);
-out:
-       kfree(res);
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(au1xpsc_pcm_add);
-
-void au1xpsc_pcm_destroy(struct platform_device *dmapd)
-{
-       if (dmapd)
-               platform_device_unregister(dmapd);
-}
-EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy);
-
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
 MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c
new file mode 100644 (file)
index 0000000..7aa5b76
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * Au1000/Au1500/Au1100 Audio DMA support.
+ *
+ * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
+ *
+ * copied almost verbatim from the old ALSA driver, written by
+ *                     Charles Eidsness <charles@cooper-street.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
+
+#include "psc.h"
+
+#define ALCHEMY_PCM_FMTS                                       \
+       (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_U8 |        \
+        SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |    \
+        SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |    \
+        SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |    \
+        SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE |    \
+        0)
+
+struct pcm_period {
+       u32 start;
+       u32 relative_end;       /* relative to start of buffer */
+       struct pcm_period *next;
+};
+
+struct audio_stream {
+       struct snd_pcm_substream *substream;
+       int dma;
+       struct pcm_period *buffer;
+       unsigned int period_size;
+       unsigned int periods;
+};
+
+struct alchemy_pcm_ctx {
+       struct audio_stream stream[2];  /* playback & capture */
+};
+
+static void au1000_release_dma_link(struct audio_stream *stream)
+{
+       struct pcm_period *pointer;
+       struct pcm_period *pointer_next;
+
+       stream->period_size = 0;
+       stream->periods = 0;
+       pointer = stream->buffer;
+       if (!pointer)
+               return;
+       do {
+               pointer_next = pointer->next;
+               kfree(pointer);
+               pointer = pointer_next;
+       } while (pointer != stream->buffer);
+       stream->buffer = NULL;
+}
+
+static int au1000_setup_dma_link(struct audio_stream *stream,
+                                unsigned int period_bytes,
+                                unsigned int periods)
+{
+       struct snd_pcm_substream *substream = stream->substream;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct pcm_period *pointer;
+       unsigned long dma_start;
+       int i;
+
+       dma_start = virt_to_phys(runtime->dma_area);
+
+       if (stream->period_size == period_bytes &&
+           stream->periods == periods)
+               return 0; /* not changed */
+
+       au1000_release_dma_link(stream);
+
+       stream->period_size = period_bytes;
+       stream->periods = periods;
+
+       stream->buffer = kmalloc(sizeof(struct pcm_period), GFP_KERNEL);
+       if (!stream->buffer)
+               return -ENOMEM;
+       pointer = stream->buffer;
+       for (i = 0; i < periods; i++) {
+               pointer->start = (u32)(dma_start + (i * period_bytes));
+               pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1);
+               if (i < periods - 1) {
+                       pointer->next = kmalloc(sizeof(struct pcm_period),
+                                               GFP_KERNEL);
+                       if (!pointer->next) {
+                               au1000_release_dma_link(stream);
+                               return -ENOMEM;
+                       }
+                       pointer = pointer->next;
+               }
+       }
+       pointer->next = stream->buffer;
+       return 0;
+}
+
+static void au1000_dma_stop(struct audio_stream *stream)
+{
+       if (stream->buffer)
+               disable_dma(stream->dma);
+}
+
+static void au1000_dma_start(struct audio_stream *stream)
+{
+       if (!stream->buffer)
+               return;
+
+       init_dma(stream->dma);
+       if (get_dma_active_buffer(stream->dma) == 0) {
+               clear_dma_done0(stream->dma);
+               set_dma_addr0(stream->dma, stream->buffer->start);
+               set_dma_count0(stream->dma, stream->period_size >> 1);
+               set_dma_addr1(stream->dma, stream->buffer->next->start);
+               set_dma_count1(stream->dma, stream->period_size >> 1);
+       } else {
+               clear_dma_done1(stream->dma);
+               set_dma_addr1(stream->dma, stream->buffer->start);
+               set_dma_count1(stream->dma, stream->period_size >> 1);
+               set_dma_addr0(stream->dma, stream->buffer->next->start);
+               set_dma_count0(stream->dma, stream->period_size >> 1);
+       }
+       enable_dma_buffers(stream->dma);
+       start_dma(stream->dma);
+}
+
+static irqreturn_t au1000_dma_interrupt(int irq, void *ptr)
+{
+       struct audio_stream *stream = (struct audio_stream *)ptr;
+       struct snd_pcm_substream *substream = stream->substream;
+
+       switch (get_dma_buffer_done(stream->dma)) {
+       case DMA_D0:
+               stream->buffer = stream->buffer->next;
+               clear_dma_done0(stream->dma);
+               set_dma_addr0(stream->dma, stream->buffer->next->start);
+               set_dma_count0(stream->dma, stream->period_size >> 1);
+               enable_dma_buffer0(stream->dma);
+               break;
+       case DMA_D1:
+               stream->buffer = stream->buffer->next;
+               clear_dma_done1(stream->dma);
+               set_dma_addr1(stream->dma, stream->buffer->next->start);
+               set_dma_count1(stream->dma, stream->period_size >> 1);
+               enable_dma_buffer1(stream->dma);
+               break;
+       case (DMA_D0 | DMA_D1):
+               pr_debug("DMA %d missed interrupt.\n", stream->dma);
+               au1000_dma_stop(stream);
+               au1000_dma_start(stream);
+               break;
+       case (~DMA_D0 & ~DMA_D1):
+               pr_debug("DMA %d empty irq.\n", stream->dma);
+       }
+       snd_pcm_period_elapsed(substream);
+       return IRQ_HANDLED;
+}
+
+static const struct snd_pcm_hardware alchemy_pcm_hardware = {
+       .info             = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+                           SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH,
+       .formats          = ALCHEMY_PCM_FMTS,
+       .rates            = SNDRV_PCM_RATE_8000_192000,
+       .rate_min         = SNDRV_PCM_RATE_8000,
+       .rate_max         = SNDRV_PCM_RATE_192000,
+       .channels_min     = 2,
+       .channels_max     = 2,
+       .period_bytes_min = 1024,
+       .period_bytes_max = 16 * 1024 - 1,
+       .periods_min      = 4,
+       .periods_max      = 255,
+       .buffer_bytes_max = 128 * 1024,
+       .fifo_size        = 16,
+};
+
+static inline struct alchemy_pcm_ctx *ss_to_ctx(struct snd_pcm_substream *ss)
+{
+       struct snd_soc_pcm_runtime *rtd = ss->private_data;
+       return snd_soc_platform_get_drvdata(rtd->platform);
+}
+
+static inline struct audio_stream *ss_to_as(struct snd_pcm_substream *ss)
+{
+       struct alchemy_pcm_ctx *ctx = ss_to_ctx(ss);
+       return &(ctx->stream[ss->stream]);
+}
+
+static int alchemy_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream);
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int *dmaids, s = substream->stream;
+       char *name;
+
+       dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+       if (!dmaids)
+               return -ENODEV; /* whoa, has ordering changed? */
+
+       /* DMA setup */
+       name = (s == SNDRV_PCM_STREAM_PLAYBACK) ? "audio-tx" : "audio-rx";
+       ctx->stream[s].dma = request_au1000_dma(dmaids[s], name,
+                                       au1000_dma_interrupt, IRQF_DISABLED,
+                                       &ctx->stream[s]);
+       set_dma_mode(ctx->stream[s].dma,
+                    get_dma_mode(ctx->stream[s].dma) & ~DMA_NC);
+
+       ctx->stream[s].substream = substream;
+       ctx->stream[s].buffer = NULL;
+       snd_soc_set_runtime_hwparams(substream, &alchemy_pcm_hardware);
+
+       return 0;
+}
+
+static int alchemy_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream);
+       int stype = substream->stream;
+
+       ctx->stream[stype].substream = NULL;
+       free_au1000_dma(ctx->stream[stype].dma);
+
+       return 0;
+}
+
+static int alchemy_pcm_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *hw_params)
+{
+       struct audio_stream *stream = ss_to_as(substream);
+       int err;
+
+       err = snd_pcm_lib_malloc_pages(substream,
+                                      params_buffer_bytes(hw_params));
+       if (err < 0)
+               return err;
+       err = au1000_setup_dma_link(stream,
+                                   params_period_bytes(hw_params),
+                                   params_periods(hw_params));
+       if (err)
+               snd_pcm_lib_free_pages(substream);
+
+       return err;
+}
+
+static int alchemy_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct audio_stream *stream = ss_to_as(substream);
+       au1000_release_dma_link(stream);
+       return snd_pcm_lib_free_pages(substream);
+}
+
+static int alchemy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct audio_stream *stream = ss_to_as(substream);
+       int err = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               au1000_dma_start(stream);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               au1000_dma_stop(stream);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+       return err;
+}
+
+static snd_pcm_uframes_t alchemy_pcm_pointer(struct snd_pcm_substream *ss)
+{
+       struct audio_stream *stream = ss_to_as(ss);
+       long location;
+
+       location = get_dma_residue(stream->dma);
+       location = stream->buffer->relative_end - location;
+       if (location == -1)
+               location = 0;
+       return bytes_to_frames(ss->runtime, location);
+}
+
+static struct snd_pcm_ops alchemy_pcm_ops = {
+       .open                   = alchemy_pcm_open,
+       .close                  = alchemy_pcm_close,
+       .ioctl                  = snd_pcm_lib_ioctl,
+       .hw_params              = alchemy_pcm_hw_params,
+       .hw_free                = alchemy_pcm_hw_free,
+       .trigger                = alchemy_pcm_trigger,
+       .pointer                = alchemy_pcm_pointer,
+};
+
+static void alchemy_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+       snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_pcm *pcm = rtd->pcm;
+
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+               snd_dma_continuous_data(GFP_KERNEL), 65536, (4096 * 1024) - 1);
+
+       return 0;
+}
+
+struct snd_soc_platform_driver alchemy_pcm_soc_platform = {
+       .ops            = &alchemy_pcm_ops,
+       .pcm_new        = alchemy_pcm_new,
+       .pcm_free       = alchemy_pcm_free_dma_buffers,
+};
+
+static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev)
+{
+       struct alchemy_pcm_ctx *ctx;
+       int ret;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, ctx);
+
+       ret = snd_soc_register_platform(&pdev->dev, &alchemy_pcm_soc_platform);
+       if (ret)
+               kfree(ctx);
+
+       return ret;
+}
+
+static int __devexit alchemy_pcm_drvremove(struct platform_device *pdev)
+{
+       struct alchemy_pcm_ctx *ctx = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_platform(&pdev->dev);
+       kfree(ctx);
+
+       return 0;
+}
+
+static struct platform_driver alchemy_pcmdma_driver = {
+       .driver = {
+               .name   = "alchemy-pcm-dma",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = alchemy_pcm_drvprobe,
+       .remove         = __devexit_p(alchemy_pcm_drvremove),
+};
+
+static int __init alchemy_pcmdma_load(void)
+{
+       return platform_driver_register(&alchemy_pcmdma_driver);
+}
+
+static void __exit alchemy_pcmdma_unload(void)
+{
+       platform_driver_unregister(&alchemy_pcmdma_driver);
+}
+
+module_init(alchemy_pcmdma_load);
+module_exit(alchemy_pcmdma_unload);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au1000/Au1500/Au1100 Audio DMA driver");
+MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
new file mode 100644 (file)
index 0000000..19e0d2a
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Au1000/Au1500/Au1100 I2S controller driver for ASoC
+ *
+ * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
+ *
+ * Note: clock supplied to the I2S controller must be 256x samplerate.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#include "psc.h"
+
+#define I2S_RXTX       0x00
+#define I2S_CFG                0x04
+#define I2S_ENABLE     0x08
+
+#define CFG_XU         (1 << 25)       /* tx underflow */
+#define CFG_XO         (1 << 24)
+#define CFG_RU         (1 << 23)
+#define CFG_RO         (1 << 22)
+#define CFG_TR         (1 << 21)
+#define CFG_TE         (1 << 20)
+#define CFG_TF         (1 << 19)
+#define CFG_RR         (1 << 18)
+#define CFG_RF         (1 << 17)
+#define CFG_ICK                (1 << 12)       /* clock invert */
+#define CFG_PD         (1 << 11)       /* set to make I2SDIO INPUT */
+#define CFG_LB         (1 << 10)       /* loopback */
+#define CFG_IC         (1 << 9)        /* word select invert */
+#define CFG_FM_I2S     (0 << 7)        /* I2S format */
+#define CFG_FM_LJ      (1 << 7)        /* left-justified */
+#define CFG_FM_RJ      (2 << 7)        /* right-justified */
+#define CFG_FM_MASK    (3 << 7)
+#define CFG_TN         (1 << 6)        /* tx fifo en */
+#define CFG_RN         (1 << 5)        /* rx fifo en */
+#define CFG_SZ_8       (0x08)
+#define CFG_SZ_16      (0x10)
+#define CFG_SZ_18      (0x12)
+#define CFG_SZ_20      (0x14)
+#define CFG_SZ_24      (0x18)
+#define CFG_SZ_MASK    (0x1f)
+#define EN_D           (1 << 1)        /* DISable */
+#define EN_CE          (1 << 0)        /* clock enable */
+
+/* only limited by clock generator and board design */
+#define AU1XI2SC_RATES \
+       SNDRV_PCM_RATE_CONTINUOUS
+
+#define AU1XI2SC_FMTS \
+       (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |            \
+       SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |     \
+       SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |     \
+       SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE |   \
+       SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_U18_3BE |   \
+       SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE |   \
+       SNDRV_PCM_FMTBIT_S20_3BE | SNDRV_PCM_FMTBIT_U20_3BE |   \
+       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |     \
+       SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE |     \
+       0)
+
+static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg)
+{
+       return __raw_readl(ctx->mmio + reg);
+}
+
+static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v)
+{
+       __raw_writel(v, ctx->mmio + reg);
+       wmb();
+}
+
+static int au1xi2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+       struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(cpu_dai);
+       unsigned long c;
+       int ret;
+
+       ret = -EINVAL;
+       c = ctx->cfg;
+
+       c &= ~CFG_FM_MASK;
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               c |= CFG_FM_I2S;
+               break;
+       case SND_SOC_DAIFMT_MSB:
+               c |= CFG_FM_RJ;
+               break;
+       case SND_SOC_DAIFMT_LSB:
+               c |= CFG_FM_LJ;
+               break;
+       default:
+               goto out;
+       }
+
+       c &= ~(CFG_IC | CFG_ICK);               /* IB-IF */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               c |= CFG_IC | CFG_ICK;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               c |= CFG_IC;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               c |= CFG_ICK;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               break;
+       default:
+               goto out;
+       }
+
+       /* I2S controller only supports master */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:    /* CODEC slave */
+               break;
+       default:
+               goto out;
+       }
+
+       ret = 0;
+       ctx->cfg = c;
+out:
+       return ret;
+}
+
+static int au1xi2s_trigger(struct snd_pcm_substream *substream,
+                          int cmd, struct snd_soc_dai *dai)
+{
+       struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
+       int stype = SUBSTREAM_TYPE(substream);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               /* power up */
+               WR(ctx, I2S_ENABLE, EN_D | EN_CE);
+               WR(ctx, I2S_ENABLE, EN_CE);
+               ctx->cfg |= (stype == PCM_TX) ? CFG_TN : CFG_RN;
+               WR(ctx, I2S_CFG, ctx->cfg);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               ctx->cfg &= ~((stype == PCM_TX) ? CFG_TN : CFG_RN);
+               WR(ctx, I2S_CFG, ctx->cfg);
+               WR(ctx, I2S_ENABLE, EN_D);              /* power off */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static unsigned long msbits_to_reg(int msbits)
+{
+       switch (msbits) {
+       case 8:
+               return CFG_SZ_8;
+       case 16:
+               return CFG_SZ_16;
+       case 18:
+               return CFG_SZ_18;
+       case 20:
+               return CFG_SZ_20;
+       case 24:
+               return CFG_SZ_24;
+       }
+       return 0;
+}
+
+static int au1xi2s_hw_params(struct snd_pcm_substream *substream,
+                            struct snd_pcm_hw_params *params,
+                            struct snd_soc_dai *dai)
+{
+       struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
+       unsigned long v;
+
+       v = msbits_to_reg(params->msbits);
+       if (!v)
+               return -EINVAL;
+
+       ctx->cfg &= ~CFG_SZ_MASK;
+       ctx->cfg |= v;
+       return 0;
+}
+
+static int au1xi2s_startup(struct snd_pcm_substream *substream,
+                          struct snd_soc_dai *dai)
+{
+       struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
+       snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]);
+       return 0;
+}
+
+static const struct snd_soc_dai_ops au1xi2s_dai_ops = {
+       .startup        = au1xi2s_startup,
+       .trigger        = au1xi2s_trigger,
+       .hw_params      = au1xi2s_hw_params,
+       .set_fmt        = au1xi2s_set_fmt,
+};
+
+static struct snd_soc_dai_driver au1xi2s_dai_driver = {
+       .symmetric_rates        = 1,
+       .playback = {
+               .rates          = AU1XI2SC_RATES,
+               .formats        = AU1XI2SC_FMTS,
+               .channels_min   = 2,
+               .channels_max   = 2,
+       },
+       .capture = {
+               .rates          = AU1XI2SC_RATES,
+               .formats        = AU1XI2SC_FMTS,
+               .channels_min   = 2,
+               .channels_max   = 2,
+       },
+       .ops = &au1xi2s_dai_ops,
+};
+
+static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
+{
+       int ret;
+       struct resource *r;
+       struct au1xpsc_audio_data *ctx;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               ret = -ENODEV;
+               goto out0;
+       }
+
+       ret = -EBUSY;
+       if (!request_mem_region(r->start, resource_size(r), pdev->name))
+               goto out0;
+
+       ctx->mmio = ioremap_nocache(r->start, resource_size(r));
+       if (!ctx->mmio)
+               goto out1;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!r)
+               goto out1;
+       ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!r)
+               goto out1;
+       ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+
+       platform_set_drvdata(pdev, ctx);
+
+       ret = snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
+       if (ret)
+               goto out1;
+
+       return 0;
+
+out1:
+       release_mem_region(r->start, resource_size(r));
+out0:
+       kfree(ctx);
+       return ret;
+}
+
+static int __devexit au1xi2s_drvremove(struct platform_device *pdev)
+{
+       struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
+       struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       snd_soc_unregister_dai(&pdev->dev);
+
+       WR(ctx, I2S_ENABLE, EN_D);      /* clock off, disable */
+
+       iounmap(ctx->mmio);
+       release_mem_region(r->start, resource_size(r));
+       kfree(ctx);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1xi2s_drvsuspend(struct device *dev)
+{
+       struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
+
+       WR(ctx, I2S_ENABLE, EN_D);      /* clock off, disable */
+
+       return 0;
+}
+
+static int au1xi2s_drvresume(struct device *dev)
+{
+       return 0;
+}
+
+static const struct dev_pm_ops au1xi2sc_pmops = {
+       .suspend        = au1xi2s_drvsuspend,
+       .resume         = au1xi2s_drvresume,
+};
+
+#define AU1XI2SC_PMOPS (&au1xi2sc_pmops)
+
+#else
+
+#define AU1XI2SC_PMOPS NULL
+
+#endif
+
+static struct platform_driver au1xi2s_driver = {
+       .driver = {
+               .name   = "alchemy-i2sc",
+               .owner  = THIS_MODULE,
+               .pm     = AU1XI2SC_PMOPS,
+       },
+       .probe          = au1xi2s_drvprobe,
+       .remove         = __devexit_p(au1xi2s_drvremove),
+};
+
+static int __init au1xi2s_load(void)
+{
+       return platform_driver_register(&au1xi2s_driver);
+}
+
+static void __exit au1xi2s_unload(void)
+{
+       platform_driver_unregister(&au1xi2s_driver);
+}
+
+module_init(au1xi2s_load);
+module_exit(au1xi2s_unload);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au1000/1500/1100 I2S ASoC driver");
+MODULE_AUTHOR("Manuel Lauss");
index d0db66f24a00cc0ce68f622161bef3b4155a7c82..172eefd38b2d411008fa527d5f66f92ebd8a55da 100644 (file)
        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE)
 
 #define AC97PCR_START(stype)   \
-       ((stype) == PCM_TX ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
+       ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
 #define AC97PCR_STOP(stype)    \
-       ((stype) == PCM_TX ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
+       ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
 #define AC97PCR_CLRFIFO(stype) \
-       ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
+       ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
 
 #define AC97STAT_BUSY(stype)   \
-       ((stype) == PCM_TX ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
+       ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
 
 /* instance data. There can be only one, MacLeod!!!! */
 static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
@@ -215,7 +215,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
 {
        struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
        unsigned long r, ro, stat;
-       int chans, t, stype = SUBSTREAM_TYPE(substream);
+       int chans, t, stype = substream->stream;
 
        chans = params_channels(params);
 
@@ -235,7 +235,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
                r |= PSC_AC97CFG_SET_LEN(params->msbits);
 
                /* channels: enable slots for front L/R channel */
-               if (stype == PCM_TX) {
+               if (stype == SNDRV_PCM_STREAM_PLAYBACK) {
                        r &= ~PSC_AC97CFG_TXSLOT_MASK;
                        r |= PSC_AC97CFG_TXSLOT_ENA(3);
                        r |= PSC_AC97CFG_TXSLOT_ENA(4);
@@ -294,7 +294,7 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
        struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
-       int ret, stype = SUBSTREAM_TYPE(substream);
+       int ret, stype = substream->stream;
 
        ret = 0;
 
@@ -324,12 +324,21 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static int au1xpsc_ac97_startup(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+{
+       struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
+       snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
+       return 0;
+}
+
 static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
 {
        return au1xpsc_ac97_workdata ? 0 : -ENODEV;
 }
 
 static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
+       .startup        = au1xpsc_ac97_startup,
        .trigger        = au1xpsc_ac97_trigger,
        .hw_params      = au1xpsc_ac97_hw_params,
 };
@@ -379,6 +388,16 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
        if (!wd->mmio)
                goto out1;
 
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!r)
+               goto out2;
+       wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!r)
+               goto out2;
+       wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+
        /* configuration: max dma trigger threshold, enable ac97 */
        wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
                  PSC_AC97CFG_DE_ENABLE;
@@ -401,15 +420,13 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 
        ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
        if (ret)
-               goto out1;
+               goto out2;
 
-       wd->dmapd = au1xpsc_pcm_add(pdev);
-       if (wd->dmapd) {
-               au1xpsc_ac97_workdata = wd;
-               return 0;
-       }
+       au1xpsc_ac97_workdata = wd;
+       return 0;
 
-       snd_soc_unregister_dai(&pdev->dev);
+out2:
+       iounmap(wd->mmio);
 out1:
        release_mem_region(r->start, resource_size(r));
 out0:
@@ -422,9 +439,6 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
        struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
        struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       if (wd->dmapd)
-               au1xpsc_pcm_destroy(wd->dmapd);
-
        snd_soc_unregister_dai(&pdev->dev);
 
        /* disable PSC completely */
index fca091276320930e7f8abd230556dabbc392e2d7..7c5ae920544fd136b1620867ced48948021912ab 100644 (file)
        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 
 #define I2SSTAT_BUSY(stype)    \
-       ((stype) == PCM_TX ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB)
+       ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB)
 #define I2SPCR_START(stype)    \
-       ((stype) == PCM_TX ? PSC_I2SPCR_TS : PSC_I2SPCR_RS)
+       ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TS : PSC_I2SPCR_RS)
 #define I2SPCR_STOP(stype)     \
-       ((stype) == PCM_TX ? PSC_I2SPCR_TP : PSC_I2SPCR_RP)
+       ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TP : PSC_I2SPCR_RP)
 #define I2SPCR_CLRFIFO(stype)  \
-       ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
+       ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
 
 
 static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
@@ -240,7 +240,7 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                               struct snd_soc_dai *dai)
 {
        struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
-       int ret, stype = SUBSTREAM_TYPE(substream);
+       int ret, stype = substream->stream;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -257,7 +257,16 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
        return ret;
 }
 
+static int au1xpsc_i2s_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
+       snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
+       return 0;
+}
+
 static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
+       .startup        = au1xpsc_i2s_startup,
        .trigger        = au1xpsc_i2s_trigger,
        .hw_params      = au1xpsc_i2s_hw_params,
        .set_fmt        = au1xpsc_i2s_set_fmt,
@@ -304,6 +313,16 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
        if (!wd->mmio)
                goto out1;
 
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!r)
+               goto out2;
+       wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!r)
+               goto out2;
+       wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+
        /* preserve PSC clock source set up by platform (dev.platform_data
         * is already occupied by soc layer)
         */
@@ -330,15 +349,11 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
        platform_set_drvdata(pdev, wd);
 
        ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
-       if (ret)
-               goto out1;
-
-       /* finally add the DMA device for this PSC */
-       wd->dmapd = au1xpsc_pcm_add(pdev);
-       if (wd->dmapd)
+       if (!ret)
                return 0;
 
-       snd_soc_unregister_dai(&pdev->dev);
+out2:
+       iounmap(wd->mmio);
 out1:
        release_mem_region(r->start, resource_size(r));
 out0:
@@ -351,9 +366,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
        struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
        struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       if (wd->dmapd)
-               au1xpsc_pcm_destroy(wd->dmapd);
-
        snd_soc_unregister_dai(&pdev->dev);
 
        au_writel(0, I2S_CFG(wd));
index b30eadd422a7fb7aee4856e671d491d769d2c6ac..b16b2e02e0c9dec6dac5450ab922255059ee2283 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Au12x0/Au1550 PSC ALSA ASoC audio support.
+ * Alchemy ALSA ASoC audio support.
  *
- * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
+ * (c) 2007-2011 MSC Vertriebsges.m.b.H.,
  *     Manuel Lauss <manuel.lauss@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
 #ifndef _AU1X_PCM_H
 #define _AU1X_PCM_H
 
-/* DBDMA helpers */
-extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev);
-extern void au1xpsc_pcm_destroy(struct platform_device *dmapd);
-
 struct au1xpsc_audio_data {
        void __iomem *mmio;
 
@@ -27,15 +23,9 @@ struct au1xpsc_audio_data {
 
        unsigned long pm[2];
        struct mutex lock;
-       struct platform_device *dmapd;
+       int dmaids[2];
 };
 
-#define PCM_TX 0
-#define PCM_RX 1
-
-#define SUBSTREAM_TYPE(substream) \
-       ((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK ? PCM_TX : PCM_RX)
-
 /* easy access macros */
 #define PSC_CTRL(x)    ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET)
 #define PSC_SEL(x)     ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET)
index fe9d548a683705ae1627a7b4a005ca5adfb760cd..9f6bc55fc399301c60dd4603e17642cb92f26d9b 100644 (file)
@@ -27,6 +27,19 @@ config SND_SOC_BFIN_EVAL_ADAU1701
          board connected to one of the Blackfin evaluation boards like the
          BF5XX-STAMP or BF5XX-EZKIT.
 
+config SND_SOC_BFIN_EVAL_ADAU1373
+       tristate "Support for the EVAL-ADAU1373 board on Blackfin eval boards"
+       depends on SND_BF5XX_I2S && I2C
+       select SND_BF5XX_SOC_I2S
+       select SND_SOC_ADAU1373
+       help
+         Say Y if you want to add support for the Analog Devices EVAL-ADAU1373
+         board connected to one of the Blackfin evaluation boards like the
+         BF5XX-STAMP or BF5XX-EZKIT.
+
+         Note: This driver assumes that first ADAU1373 DAI is connected to the
+         first SPORT port on the BF5XX board.
+
 config SND_SOC_BFIN_EVAL_ADAV80X
        tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards"
        depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
index 6018bf52a234f9592ae1b00d34243c83e9d113f4..1bf86ccaa8de2071f0bcce1bdec796a870eaa3e6 100644 (file)
@@ -21,6 +21,7 @@ snd-ad1980-objs := bf5xx-ad1980.o
 snd-ssm2602-objs := bf5xx-ssm2602.o
 snd-ad73311-objs := bf5xx-ad73311.o
 snd-ad193x-objs := bf5xx-ad193x.o
+snd-soc-bfin-eval-adau1373-objs := bfin-eval-adau1373.o
 snd-soc-bfin-eval-adau1701-objs := bfin-eval-adau1701.o
 snd-soc-bfin-eval-adav80x-objs := bfin-eval-adav80x.o
 
@@ -29,5 +30,6 @@ obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
 obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
 obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
 obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o
+obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) += snd-soc-bfin-eval-adau1373.o
 obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) += snd-soc-bfin-eval-adau1701.o
 obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) += snd-soc-bfin-eval-adav80x.o
index 9e59f680bc197224e642b9b61339bf67eb75fba9..56815c1d47b3fdb36f278e05894fc54a6ace93d7 100644 (file)
@@ -418,7 +418,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
+static int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_soc_dai *dai = rtd->cpu_dai;
index 61ddf942fd4d0269c499c936d631d0959d261453..7565e1576ffa47a04ab165423cda019eb53c7375 100644 (file)
@@ -257,7 +257,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
+static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_soc_dai *dai = rtd->cpu_dai;
diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c
new file mode 100644 (file)
index 0000000..8df2a3b
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Machine driver for EVAL-ADAU1373 on Analog Devices bfin
+ * evaluation boards.
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#include "../codecs/adau1373.h"
+
+static const struct snd_soc_dapm_widget bfin_eval_adau1373_dapm_widgets[] = {
+       SND_SOC_DAPM_LINE("Line In1", NULL),
+       SND_SOC_DAPM_LINE("Line In2", NULL),
+       SND_SOC_DAPM_LINE("Line In3", NULL),
+       SND_SOC_DAPM_LINE("Line In4", NULL),
+
+       SND_SOC_DAPM_LINE("Line Out1", NULL),
+       SND_SOC_DAPM_LINE("Line Out2", NULL),
+       SND_SOC_DAPM_LINE("Stereo Out", NULL),
+       SND_SOC_DAPM_HP("Headphone", NULL),
+       SND_SOC_DAPM_HP("Earpiece", NULL),
+       SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+static const struct snd_soc_dapm_route bfin_eval_adau1373_dapm_routes[] = {
+       { "AIN1L", NULL, "Line In1" },
+       { "AIN1R", NULL, "Line In1" },
+       { "AIN2L", NULL, "Line In2" },
+       { "AIN2R", NULL, "Line In2" },
+       { "AIN3L", NULL, "Line In3" },
+       { "AIN3R", NULL, "Line In3" },
+       { "AIN4L", NULL, "Line In4" },
+       { "AIN4R", NULL, "Line In4" },
+
+       /* MICBIAS can be connected via a jumper to the line-in jack, since w
+          don't know which one is going to be used, just power both. */
+       { "Line In1", NULL, "MICBIAS1" },
+       { "Line In2", NULL, "MICBIAS1" },
+       { "Line In3", NULL, "MICBIAS1" },
+       { "Line In4", NULL, "MICBIAS1" },
+       { "Line In1", NULL, "MICBIAS2" },
+       { "Line In2", NULL, "MICBIAS2" },
+       { "Line In3", NULL, "MICBIAS2" },
+       { "Line In4", NULL, "MICBIAS2" },
+
+       { "Line Out1", NULL, "LOUT1L" },
+       { "Line Out1", NULL, "LOUT1R" },
+       { "Line Out2", NULL, "LOUT2L" },
+       { "Line Out2", NULL, "LOUT2R" },
+       { "Headphone", NULL, "HPL" },
+       { "Headphone", NULL, "HPR" },
+       { "Earpiece", NULL, "EP" },
+       { "Speaker", NULL, "SPKL" },
+       { "Stereo Out", NULL, "SPKR" },
+};
+
+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:
+       case 12000:
+       case 16000:
+       case 24000:
+       case 32000:
+               pll_rate = 48000 * 1024;
+               break;
+       case 44100:
+       case 7350:
+       case 11025:
+       case 14700:
+       case 22050:
+       case 29400:
+               pll_rate = 44100 * 1024;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = snd_soc_dai_set_pll(codec_dai, ADAU1373_PLL1,
+                       ADAU1373_PLL_SRC_MCLK1, 12288000, pll_rate);
+       if (ret)
+               return ret;
+
+       ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1373_CLK_SRC_PLL1, pll_rate,
+                       SND_SOC_CLOCK_IN);
+
+       return ret;
+}
+
+static int bfin_eval_adau1373_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       unsigned int pll_rate = 48000 * 1024;
+       int ret;
+
+       ret = snd_soc_dai_set_pll(codec_dai, ADAU1373_PLL1,
+                       ADAU1373_PLL_SRC_MCLK1, 12288000, pll_rate);
+       if (ret)
+               return ret;
+
+       ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1373_CLK_SRC_PLL1, pll_rate,
+                       SND_SOC_CLOCK_IN);
+
+       return ret;
+}
+static struct snd_soc_ops bfin_eval_adau1373_ops = {
+       .hw_params = bfin_eval_adau1373_hw_params,
+};
+
+static struct snd_soc_dai_link bfin_eval_adau1373_dai = {
+       .name = "adau1373",
+       .stream_name = "adau1373",
+       .cpu_dai_name = "bfin-i2s.0",
+       .codec_dai_name = "adau1373-aif1",
+       .platform_name = "bfin-i2s-pcm-audio",
+       .codec_name = "adau1373.0-001a",
+       .ops = &bfin_eval_adau1373_ops,
+       .init = bfin_eval_adau1373_codec_init,
+};
+
+static struct snd_soc_card bfin_eval_adau1373 = {
+       .name = "bfin-eval-adau1373",
+       .dai_link = &bfin_eval_adau1373_dai,
+       .num_links = 1,
+
+       .dapm_widgets           = bfin_eval_adau1373_dapm_widgets,
+       .num_dapm_widgets       = ARRAY_SIZE(bfin_eval_adau1373_dapm_widgets),
+       .dapm_routes            = bfin_eval_adau1373_dapm_routes,
+       .num_dapm_routes        = ARRAY_SIZE(bfin_eval_adau1373_dapm_routes),
+};
+
+static int bfin_eval_adau1373_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &bfin_eval_adau1373;
+
+       card->dev = &pdev->dev;
+
+       return snd_soc_register_card(&bfin_eval_adau1373);
+}
+
+static int __devexit bfin_eval_adau1373_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 bfin_eval_adau1373_driver = {
+       .driver = {
+               .name = "bfin-eval-adau1373",
+               .owner = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
+       },
+       .probe = bfin_eval_adau1373_probe,
+       .remove = __devexit_p(bfin_eval_adau1373_remove),
+};
+
+static int __init bfin_eval_adau1373_init(void)
+{
+       return platform_driver_register(&bfin_eval_adau1373_driver);
+}
+module_init(bfin_eval_adau1373_init);
+
+static void __exit bfin_eval_adau1373_exit(void)
+{
+       platform_driver_unregister(&bfin_eval_adau1373_driver);
+}
+module_exit(bfin_eval_adau1373_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ALSA SoC bfin adau1373 driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bfin-eval-adau1373");
index 19241576b6b590a9982b457fe405d0e245c7aca7..5ca122e51183a4531c612613c0bbf6c94da9f272 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -772,11 +773,12 @@ static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
 
 
        SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
-                           PM860X_DAC_EN_2, 0, 0),
+                           SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
-                           PM860X_DAC_EN_2, 0, 0),
+                           SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
                             PM860X_I2S_IFACE_3, 5, 1),
+       SND_SOC_DAPM_SUPPLY("I2S CLK", PM860X_DAC_EN_2, 0, 0, NULL, 0),
        SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
        SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
        SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
@@ -868,6 +870,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Left ADC", NULL, "Left ADC MOD"},
        {"Right ADC", NULL, "Right ADC MOD"},
 
+       /* I2S Clock */
+       {"I2S DIN", NULL, "I2S CLK"},
+       {"I2S DIN1", NULL, "I2S CLK"},
+       {"I2S DOUT", NULL, "I2S CLK"},
+
        /* PCM/AIF1 Inputs */
        {"PCM SDO", NULL, "ADC Left Mux"},
        {"PCM SDO", NULL, "ADCR EC Mux"},
@@ -1173,6 +1180,9 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
                        /* Enable Audio PLL & Audio section */
+                       data = AUDIO_PLL | AUDIO_SECTION_ON;
+                       pm860x_reg_write(codec->control_data, REG_MISC2, data);
+                       udelay(300);
                        data = AUDIO_PLL | AUDIO_SECTION_RESET
                                | AUDIO_SECTION_ON;
                        pm860x_reg_write(codec->control_data, REG_MISC2, data);
index 665d9240c4ae46e7005a46484598333052a752d3..34494315298889b03866668e473b1660c9601466 100644 (file)
@@ -17,6 +17,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
        select SND_SOC_AD1980 if SND_SOC_AC97_BUS
        select SND_SOC_AD73311
+       select SND_SOC_ADAU1373 if I2C
        select SND_SOC_ADAV80X
        select SND_SOC_ADS117X
        select SND_SOC_AK4104 if SPI_MASTER
@@ -39,6 +40,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_MAX9850 if I2C
        select SND_SOC_MAX9877 if I2C
        select SND_SOC_PCM3008
+       select SND_SOC_RT5631 if I2C
        select SND_SOC_SGTL5000 if I2C
        select SND_SOC_SN95031 if INTEL_SCU_IPC
        select SND_SOC_SPDIF
@@ -58,6 +60,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WL1273 if MFD_WL1273_CORE
        select SND_SOC_WM1250_EV1 if I2C
        select SND_SOC_WM2000 if I2C
+       select SND_SOC_WM5100 if I2C
        select SND_SOC_WM8350 if MFD_WM8350
        select SND_SOC_WM8400 if MFD_WM8400
        select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
@@ -139,6 +142,9 @@ config SND_SOC_ADAU1701
        select SIGMA
        tristate
 
+config SND_SOC_ADAU1373
+       tristate
+
 config SND_SOC_ADAV80X
        tristate
 
@@ -214,6 +220,9 @@ config SND_SOC_MAX9850
 config SND_SOC_PCM3008
        tristate
 
+config SND_SOC_RT5631
+       tristate
+
 #Freescale sgtl5000 codec
 config SND_SOC_SGTL5000
        tristate
@@ -269,6 +278,9 @@ config SND_SOC_WL1273
 config SND_SOC_WM1250_EV1
        tristate
 
+config SND_SOC_WM5100
+       tristate
+
 config SND_SOC_WM8350
        tristate
 
index 5119a7e2c1a843b438ebed2865723f836c60b152..787881b7c75075bab8753d4ebee030b058ac223e 100644 (file)
@@ -5,6 +5,7 @@ snd-soc-ad193x-objs := ad193x.o
 snd-soc-ad1980-objs := ad1980.o
 snd-soc-ad73311-objs := ad73311.o
 snd-soc-adau1701-objs := adau1701.o
+snd-soc-adau1373-objs := adau1373.o
 snd-soc-adav80x-objs := adav80x.o
 snd-soc-ads117x-objs := ads117x.o
 snd-soc-ak4104-objs := ak4104.o
@@ -25,6 +26,7 @@ snd-soc-max98088-objs := max98088.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-pcm3008-objs := pcm3008.o
+snd-soc-rt5631-objs := rt5631.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-sn95031-objs := sn95031.o
@@ -43,6 +45,7 @@ snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
+snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
 snd-soc-wm8510-objs := wm8510.o
@@ -100,6 +103,7 @@ obj-$(CONFIG_SND_SOC_AD1836)        += snd-soc-ad1836.o
 obj-$(CONFIG_SND_SOC_AD193X)   += snd-soc-ad193x.o
 obj-$(CONFIG_SND_SOC_AD1980)   += snd-soc-ad1980.o
 obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
+obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
 obj-$(CONFIG_SND_SOC_ADAU1701)  += snd-soc-adau1701.o
 obj-$(CONFIG_SND_SOC_ADAV80X)  += snd-soc-adav80x.o
 obj-$(CONFIG_SND_SOC_ADS117X)  += snd-soc-ads117x.o
@@ -123,6 +127,7 @@ obj-$(CONFIG_SND_SOC_MAX98088)      += snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
+obj-$(CONFIG_SND_SOC_RT5631)   += snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SN95031)  +=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif.o
@@ -140,6 +145,7 @@ obj-$(CONFIG_SND_SOC_UDA134X)       += snd-soc-uda134x.o
 obj-$(CONFIG_SND_SOC_UDA1380)  += snd-soc-uda1380.o
 obj-$(CONFIG_SND_SOC_WL1273)   += snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
+obj-$(CONFIG_SND_SOC_WM5100)   += snd-soc-wm5100.o
 obj-$(CONFIG_SND_SOC_WM8350)   += snd-soc-wm8350.o
 obj-$(CONFIG_SND_SOC_WM8400)   += snd-soc-wm8400.o
 obj-$(CONFIG_SND_SOC_WM8510)   += snd-soc-wm8510.o
index eedb6f5e5823499919e14611db21a747a2a023b6..f934670199a52af44be551c8f4fcbed79fa48d84 100644 (file)
@@ -23,7 +23,7 @@
 
 /* codec private data */
 struct ad193x_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        int sysclk;
 };
 
@@ -349,10 +349,8 @@ static int ad193x_probe(struct snd_soc_codec *codec)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret;
 
-       if (ad193x->control_type == SND_SOC_I2C)
-               ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->control_type);
-       else
-               ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->control_type);
+       codec->control_data = ad193x->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
                return ret;
@@ -388,6 +386,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
 };
 
 #if defined(CONFIG_SPI_MASTER)
+
+static const struct regmap_config ad193x_spi_regmap_config = {
+       .val_bits = 8,
+       .reg_bits = 16,
+       .read_flag_mask = 0x09,
+       .write_flag_mask = 0x08,
+};
+
 static int __devinit ad193x_spi_probe(struct spi_device *spi)
 {
        struct ad193x_priv *ad193x;
@@ -397,20 +403,36 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi)
        if (ad193x == NULL)
                return -ENOMEM;
 
+       ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config);
+       if (IS_ERR(ad193x->regmap)) {
+               ret = PTR_ERR(ad193x->regmap);
+               goto err_free;
+       }
+
        spi_set_drvdata(spi, ad193x);
-       ad193x->control_type = SND_SOC_SPI;
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_ad193x, &ad193x_dai, 1);
        if (ret < 0)
-               kfree(ad193x);
+               goto err_regmap_exit;
+
+       return 0;
+
+err_regmap_exit:
+       regmap_exit(ad193x->regmap);
+err_free:
+       kfree(ad193x);
+
        return ret;
 }
 
 static int __devexit ad193x_spi_remove(struct spi_device *spi)
 {
+       struct ad193x_priv *ad193x = spi_get_drvdata(spi);
+
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
+       regmap_exit(ad193x->regmap);
+       kfree(ad193x);
        return 0;
 }
 
@@ -425,6 +447,12 @@ static struct spi_driver ad193x_spi_driver = {
 #endif
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+static const struct regmap_config ad193x_i2c_regmap_config = {
+       .val_bits = 8,
+       .reg_bits = 8,
+};
+
 static const struct i2c_device_id ad193x_id[] = {
        { "ad1936", 0 },
        { "ad1937", 0 },
@@ -442,20 +470,35 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client,
        if (ad193x == NULL)
                return -ENOMEM;
 
+       ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config);
+       if (IS_ERR(ad193x->regmap)) {
+               ret = PTR_ERR(ad193x->regmap);
+               goto err_free;
+       }
+
        i2c_set_clientdata(client, ad193x);
-       ad193x->control_type = SND_SOC_I2C;
 
        ret =  snd_soc_register_codec(&client->dev,
                        &soc_codec_dev_ad193x, &ad193x_dai, 1);
        if (ret < 0)
-               kfree(ad193x);
+               goto err_regmap_exit;
+
+       return 0;
+
+err_regmap_exit:
+       regmap_exit(ad193x->regmap);
+err_free:
+       kfree(ad193x);
        return ret;
 }
 
 static int __devexit ad193x_i2c_remove(struct i2c_client *client)
 {
+       struct ad193x_priv *ad193x = i2c_get_clientdata(client);
+
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(ad193x->regmap);
+       kfree(ad193x);
        return 0;
 }
 
index cccc2e8e5fbd3e830a3a402ed565a2c981ad7f2b..536e5f2b136ea6e84471562c58ddb9ab02f3f543 100644 (file)
@@ -9,20 +9,20 @@
 #ifndef __AD193X_H__
 #define __AD193X_H__
 
-#define AD193X_PLL_CLK_CTRL0    0x800
+#define AD193X_PLL_CLK_CTRL0    0x00
 #define AD193X_PLL_POWERDOWN           0x01
 #define AD193X_PLL_INPUT_MASK   (~0x6)
 #define AD193X_PLL_INPUT_256    (0 << 1)
 #define AD193X_PLL_INPUT_384    (1 << 1)
 #define AD193X_PLL_INPUT_512    (2 << 1)
 #define AD193X_PLL_INPUT_768    (3 << 1)
-#define AD193X_PLL_CLK_CTRL1    0x801
-#define AD193X_DAC_CTRL0        0x802
+#define AD193X_PLL_CLK_CTRL1    0x01
+#define AD193X_DAC_CTRL0        0x02
 #define AD193X_DAC_POWERDOWN           0x01
 #define AD193X_DAC_SERFMT_MASK         0xC0
 #define AD193X_DAC_SERFMT_STEREO       (0 << 6)
 #define AD193X_DAC_SERFMT_TDM          (1 << 6)
-#define AD193X_DAC_CTRL1        0x803
+#define AD193X_DAC_CTRL1        0x03
 #define AD193X_DAC_2_CHANNELS   0
 #define AD193X_DAC_4_CHANNELS   1
 #define AD193X_DAC_8_CHANNELS   2
 #define AD193X_DAC_BCLK_MASTER  (1 << 5)
 #define AD193X_DAC_LEFT_HIGH    (1 << 3)
 #define AD193X_DAC_BCLK_INV     (1 << 7)
-#define AD193X_DAC_CTRL2        0x804
+#define AD193X_DAC_CTRL2        0x04
 #define AD193X_DAC_WORD_LEN_SHFT        3
 #define AD193X_DAC_WORD_LEN_MASK        0x18
 #define AD193X_DAC_MASTER_MUTE  1
-#define AD193X_DAC_CHNL_MUTE    0x805
+#define AD193X_DAC_CHNL_MUTE    0x05
 #define AD193X_DACL1_MUTE       0
 #define AD193X_DACR1_MUTE       1
 #define AD193X_DACL2_MUTE       2
 #define AD193X_DACR3_MUTE       5
 #define AD193X_DACL4_MUTE       6
 #define AD193X_DACR4_MUTE       7
-#define AD193X_DAC_L1_VOL       0x806
-#define AD193X_DAC_R1_VOL       0x807
-#define AD193X_DAC_L2_VOL       0x808
-#define AD193X_DAC_R2_VOL       0x809
-#define AD193X_DAC_L3_VOL       0x80a
-#define AD193X_DAC_R3_VOL       0x80b
-#define AD193X_DAC_L4_VOL       0x80c
-#define AD193X_DAC_R4_VOL       0x80d
-#define AD193X_ADC_CTRL0        0x80e
+#define AD193X_DAC_L1_VOL       0x06
+#define AD193X_DAC_R1_VOL       0x07
+#define AD193X_DAC_L2_VOL       0x08
+#define AD193X_DAC_R2_VOL       0x09
+#define AD193X_DAC_L3_VOL       0x0a
+#define AD193X_DAC_R3_VOL       0x0b
+#define AD193X_DAC_L4_VOL       0x0c
+#define AD193X_DAC_R4_VOL       0x0d
+#define AD193X_ADC_CTRL0        0x0e
 #define AD193X_ADC_POWERDOWN           0x01
 #define AD193X_ADC_HIGHPASS_FILTER     1
 #define AD193X_ADCL1_MUTE              2
 #define AD193X_ADCR1_MUTE              3
 #define AD193X_ADCL2_MUTE              4
 #define AD193X_ADCR2_MUTE              5
-#define AD193X_ADC_CTRL1        0x80f
+#define AD193X_ADC_CTRL1        0x0f
 #define AD193X_ADC_SERFMT_MASK         0x60
 #define AD193X_ADC_SERFMT_STEREO       (0 << 5)
 #define AD193X_ADC_SERFMT_TDM          (1 << 5)
 #define AD193X_ADC_SERFMT_AUX          (2 << 5)
 #define AD193X_ADC_WORD_LEN_MASK       0x3
-#define AD193X_ADC_CTRL2        0x810
+#define AD193X_ADC_CTRL2        0x10
 #define AD193X_ADC_2_CHANNELS   0
 #define AD193X_ADC_4_CHANNELS   1
 #define AD193X_ADC_8_CHANNELS   2
index 923b364a3e41926e88c99025c11326ab49236773..e3931cc5e66c6736d75fa053e7755acfda7a8b8e 100644 (file)
@@ -148,7 +148,6 @@ static struct snd_soc_dai_driver ad1980_dai = {
                .rates = SNDRV_PCM_RATE_48000,
                .formats = SND_SOC_STD_AC97_FMTS, },
 };
-EXPORT_SYMBOL_GPL(ad1980_dai);
 
 static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
 {
@@ -200,18 +199,22 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
        }
 
        /* Read out vendor ID to make sure it is ad1980 */
-       if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144)
+       if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) {
+               ret = -ENODEV;
                goto reset_err;
+       }
 
        vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2);
 
        if (vendor_id2 != 0x5370) {
-               if (vendor_id2 != 0x5374)
+               if (vendor_id2 != 0x5374) {
+                       ret = -ENODEV;
                        goto reset_err;
-               else
+               } else {
                        printk(KERN_WARNING "ad1980: "
                                "Found AD1981 - only 2/2 IN/OUT Channels "
                                "supported\n");
+               }
        }
 
        /* unmute captures and playbacks volume */
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
new file mode 100644 (file)
index 0000000..1ccf8dd
--- /dev/null
@@ -0,0 +1,1414 @@
+/*
+ * Analog Devices ADAU1373 Audio Codec drive
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/gcd.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/adau1373.h>
+
+#include "adau1373.h"
+
+struct adau1373_dai {
+       unsigned int clk_src;
+       unsigned int sysclk;
+       bool enable_src;
+       bool master;
+};
+
+struct adau1373 {
+       struct adau1373_dai dais[3];
+};
+
+#define ADAU1373_INPUT_MODE    0x00
+#define ADAU1373_AINL_CTRL(x)  (0x01 + (x) * 2)
+#define ADAU1373_AINR_CTRL(x)  (0x02 + (x) * 2)
+#define ADAU1373_LLINE_OUT(x)  (0x9 + (x) * 2)
+#define ADAU1373_RLINE_OUT(x)  (0xa + (x) * 2)
+#define ADAU1373_LSPK_OUT      0x0d
+#define ADAU1373_RSPK_OUT      0x0e
+#define ADAU1373_LHP_OUT       0x0f
+#define ADAU1373_RHP_OUT       0x10
+#define ADAU1373_ADC_GAIN      0x11
+#define ADAU1373_LADC_MIXER    0x12
+#define ADAU1373_RADC_MIXER    0x13
+#define ADAU1373_LLINE1_MIX    0x14
+#define ADAU1373_RLINE1_MIX    0x15
+#define ADAU1373_LLINE2_MIX    0x16
+#define ADAU1373_RLINE2_MIX    0x17
+#define ADAU1373_LSPK_MIX      0x18
+#define ADAU1373_RSPK_MIX      0x19
+#define ADAU1373_LHP_MIX       0x1a
+#define ADAU1373_RHP_MIX       0x1b
+#define ADAU1373_EP_MIX                0x1c
+#define ADAU1373_HP_CTRL       0x1d
+#define ADAU1373_HP_CTRL2      0x1e
+#define ADAU1373_LS_CTRL       0x1f
+#define ADAU1373_EP_CTRL       0x21
+#define ADAU1373_MICBIAS_CTRL1 0x22
+#define ADAU1373_MICBIAS_CTRL2 0x23
+#define ADAU1373_OUTPUT_CTRL   0x24
+#define ADAU1373_PWDN_CTRL1    0x25
+#define ADAU1373_PWDN_CTRL2    0x26
+#define ADAU1373_PWDN_CTRL3    0x27
+#define ADAU1373_DPLL_CTRL(x)  (0x28 + (x) * 7)
+#define ADAU1373_PLL_CTRL1(x)  (0x29 + (x) * 7)
+#define ADAU1373_PLL_CTRL2(x)  (0x2a + (x) * 7)
+#define ADAU1373_PLL_CTRL3(x)  (0x2b + (x) * 7)
+#define ADAU1373_PLL_CTRL4(x)  (0x2c + (x) * 7)
+#define ADAU1373_PLL_CTRL5(x)  (0x2d + (x) * 7)
+#define ADAU1373_PLL_CTRL6(x)  (0x2e + (x) * 7)
+#define ADAU1373_PLL_CTRL7(x)  (0x2f + (x) * 7)
+#define ADAU1373_HEADDECT      0x36
+#define ADAU1373_ADC_DAC_STATUS        0x37
+#define ADAU1373_ADC_CTRL      0x3c
+#define ADAU1373_DAI(x)                (0x44 + (x))
+#define ADAU1373_CLK_SRC_DIV(x)        (0x40 + (x) * 2)
+#define ADAU1373_BCLKDIV(x)    (0x47 + (x))
+#define ADAU1373_SRC_RATIOA(x) (0x4a + (x) * 2)
+#define ADAU1373_SRC_RATIOB(x) (0x4b + (x) * 2)
+#define ADAU1373_DEEMP_CTRL    0x50
+#define ADAU1373_SRC_DAI_CTRL(x) (0x51 + (x))
+#define ADAU1373_DIN_MIX_CTRL(x) (0x56 + (x))
+#define ADAU1373_DOUT_MIX_CTRL(x) (0x5b + (x))
+#define ADAU1373_DAI_PBL_VOL(x)        (0x62 + (x) * 2)
+#define ADAU1373_DAI_PBR_VOL(x)        (0x63 + (x) * 2)
+#define ADAU1373_DAI_RECL_VOL(x) (0x68 + (x) * 2)
+#define ADAU1373_DAI_RECR_VOL(x) (0x69 + (x) * 2)
+#define ADAU1373_DAC1_PBL_VOL  0x6e
+#define ADAU1373_DAC1_PBR_VOL  0x6f
+#define ADAU1373_DAC2_PBL_VOL  0x70
+#define ADAU1373_DAC2_PBR_VOL  0x71
+#define ADAU1373_ADC_RECL_VOL  0x72
+#define ADAU1373_ADC_RECR_VOL  0x73
+#define ADAU1373_DMIC_RECL_VOL 0x74
+#define ADAU1373_DMIC_RECR_VOL 0x75
+#define ADAU1373_VOL_GAIN1     0x76
+#define ADAU1373_VOL_GAIN2     0x77
+#define ADAU1373_VOL_GAIN3     0x78
+#define ADAU1373_HPF_CTRL      0x7d
+#define ADAU1373_BASS1         0x7e
+#define ADAU1373_BASS2         0x7f
+#define ADAU1373_DRC(x)                (0x80 + (x) * 0x10)
+#define ADAU1373_3D_CTRL1      0xc0
+#define ADAU1373_3D_CTRL2      0xc1
+#define ADAU1373_FDSP_SEL1     0xdc
+#define ADAU1373_FDSP_SEL2     0xdd
+#define ADAU1373_FDSP_SEL3     0xde
+#define ADAU1373_FDSP_SEL4     0xdf
+#define ADAU1373_DIGMICCTRL    0xe2
+#define ADAU1373_DIGEN         0xeb
+#define ADAU1373_SOFT_RESET    0xff
+
+
+#define ADAU1373_PLL_CTRL6_DPLL_BYPASS BIT(1)
+#define ADAU1373_PLL_CTRL6_PLL_EN      BIT(0)
+
+#define ADAU1373_DAI_INVERT_BCLK       BIT(7)
+#define ADAU1373_DAI_MASTER            BIT(6)
+#define ADAU1373_DAI_INVERT_LRCLK      BIT(4)
+#define ADAU1373_DAI_WLEN_16           0x0
+#define ADAU1373_DAI_WLEN_20           0x4
+#define ADAU1373_DAI_WLEN_24           0x8
+#define ADAU1373_DAI_WLEN_32           0xc
+#define ADAU1373_DAI_WLEN_MASK         0xc
+#define ADAU1373_DAI_FORMAT_RIGHT_J    0x0
+#define ADAU1373_DAI_FORMAT_LEFT_J     0x1
+#define ADAU1373_DAI_FORMAT_I2S                0x2
+#define ADAU1373_DAI_FORMAT_DSP                0x3
+
+#define ADAU1373_BCLKDIV_SOURCE                BIT(5)
+#define ADAU1373_BCLKDIV_32            0x03
+#define ADAU1373_BCLKDIV_64            0x02
+#define ADAU1373_BCLKDIV_128           0x01
+#define ADAU1373_BCLKDIV_256           0x00
+
+#define ADAU1373_ADC_CTRL_PEAK_DETECT  BIT(0)
+#define ADAU1373_ADC_CTRL_RESET                BIT(1)
+#define ADAU1373_ADC_CTRL_RESET_FORCE  BIT(2)
+
+#define ADAU1373_OUTPUT_CTRL_LDIFF     BIT(3)
+#define ADAU1373_OUTPUT_CTRL_LNFBEN    BIT(2)
+
+#define ADAU1373_PWDN_CTRL3_PWR_EN BIT(0)
+
+#define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4
+#define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2
+
+static const uint8_t adau1373_default_regs[] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */
+       0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */
+       0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
+       0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */
+       0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
+       0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */
+       0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
+       0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */
+       0x00, 0x1f, 0x0f, 0x00, 0x00,
+};
+
+static const unsigned int adau1373_out_tlv[] = {
+       TLV_DB_RANGE_HEAD(4),
+       0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
+       8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
+       16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
+       24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
+};
+
+static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0);
+static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1);
+static const DECLARE_TLV_DB_SCALE(adau1373_ep_tlv, -600, 600, 1);
+
+static const DECLARE_TLV_DB_SCALE(adau1373_input_boost_tlv, 0, 2000, 0);
+static const DECLARE_TLV_DB_SCALE(adau1373_gain_boost_tlv, 0, 600, 0);
+static const DECLARE_TLV_DB_SCALE(adau1373_speaker_boost_tlv, 1200, 600, 0);
+
+static const char *adau1373_fdsp_sel_text[] = {
+       "None",
+       "Channel 1",
+       "Channel 2",
+       "Channel 3",
+       "Channel 4",
+       "Channel 5",
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum,
+       ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum,
+       ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum,
+       ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum,
+       ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum,
+       ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text);
+
+static const char *adau1373_hpf_cutoff_text[] = {
+       "3.7Hz", "50Hz", "100Hz", "150Hz", "200Hz", "250Hz", "300Hz", "350Hz",
+       "400Hz", "450Hz", "500Hz", "550Hz", "600Hz", "650Hz", "700Hz", "750Hz",
+       "800Hz",
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum,
+       ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text);
+
+static const char *adau1373_bass_lpf_cutoff_text[] = {
+       "801Hz", "1001Hz",
+};
+
+static const char *adau1373_bass_clip_level_text[] = {
+       "0.125", "0.250", "0.370", "0.500", "0.625", "0.750", "0.875",
+};
+
+static const unsigned int adau1373_bass_clip_level_values[] = {
+       1, 2, 3, 4, 5, 6, 7,
+};
+
+static const char *adau1373_bass_hpf_cutoff_text[] = {
+       "158Hz", "232Hz", "347Hz", "520Hz",
+};
+
+static const unsigned int adau1373_bass_tlv[] = {
+       TLV_DB_RANGE_HEAD(4),
+       0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1),
+       3, 4, TLV_DB_SCALE_ITEM(950, 250, 0),
+       5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0),
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum,
+       ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text);
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum,
+       ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text,
+       adau1373_bass_clip_level_values);
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum,
+       ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text);
+
+static const char *adau1373_3d_level_text[] = {
+       "0%", "6.67%", "13.33%", "20%", "26.67%", "33.33%",
+       "40%", "46.67%", "53.33%", "60%", "66.67%", "73.33%",
+       "80%", "86.67", "99.33%", "100%"
+};
+
+static const char *adau1373_3d_cutoff_text[] = {
+       "No 3D", "0.03125 fs", "0.04583 fs", "0.075 fs", "0.11458 fs",
+       "0.16875 fs", "0.27083 fs"
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum,
+       ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum,
+       ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text);
+
+static const unsigned int adau1373_3d_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+       1, 7, TLV_DB_LINEAR_ITEM(-1800, -120),
+};
+
+static const char *adau1373_lr_mux_text[] = {
+       "Mute",
+       "Right Channel (L+R)",
+       "Left Channel (L+R)",
+       "Stereo",
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum,
+       ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum,
+       ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum,
+       ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text);
+
+static const struct snd_kcontrol_new adau1373_controls[] = {
+       SOC_DOUBLE_R_TLV("AIF1 Capture Volume", ADAU1373_DAI_RECL_VOL(0),
+               ADAU1373_DAI_RECR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv),
+       SOC_DOUBLE_R_TLV("AIF2 Capture Volume", ADAU1373_DAI_RECL_VOL(1),
+               ADAU1373_DAI_RECR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv),
+       SOC_DOUBLE_R_TLV("AIF3 Capture Volume", ADAU1373_DAI_RECL_VOL(2),
+               ADAU1373_DAI_RECR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv),
+
+       SOC_DOUBLE_R_TLV("ADC Capture Volume", ADAU1373_ADC_RECL_VOL,
+               ADAU1373_ADC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv),
+       SOC_DOUBLE_R_TLV("DMIC Capture Volume", ADAU1373_DMIC_RECL_VOL,
+               ADAU1373_DMIC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv),
+
+       SOC_DOUBLE_R_TLV("AIF1 Playback Volume", ADAU1373_DAI_PBL_VOL(0),
+               ADAU1373_DAI_PBR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv),
+       SOC_DOUBLE_R_TLV("AIF2 Playback Volume", ADAU1373_DAI_PBL_VOL(1),
+               ADAU1373_DAI_PBR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv),
+       SOC_DOUBLE_R_TLV("AIF3 Playback Volume", ADAU1373_DAI_PBL_VOL(2),
+               ADAU1373_DAI_PBR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv),
+
+       SOC_DOUBLE_R_TLV("DAC1 Playback Volume", ADAU1373_DAC1_PBL_VOL,
+               ADAU1373_DAC1_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv),
+       SOC_DOUBLE_R_TLV("DAC2 Playback Volume", ADAU1373_DAC2_PBL_VOL,
+               ADAU1373_DAC2_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv),
+
+       SOC_DOUBLE_R_TLV("Lineout1 Playback Volume", ADAU1373_LLINE_OUT(0),
+               ADAU1373_RLINE_OUT(0), 0, 0x1f, 0, adau1373_out_tlv),
+       SOC_DOUBLE_R_TLV("Speaker Playback Volume", ADAU1373_LSPK_OUT,
+               ADAU1373_RSPK_OUT, 0, 0x1f, 0, adau1373_out_tlv),
+       SOC_DOUBLE_R_TLV("Headphone Playback Volume", ADAU1373_LHP_OUT,
+               ADAU1373_RHP_OUT, 0, 0x1f, 0, adau1373_out_tlv),
+
+       SOC_DOUBLE_R_TLV("Input 1 Capture Volume", ADAU1373_AINL_CTRL(0),
+               ADAU1373_AINR_CTRL(0), 0, 0x1f, 0, adau1373_in_pga_tlv),
+       SOC_DOUBLE_R_TLV("Input 2 Capture Volume", ADAU1373_AINL_CTRL(1),
+               ADAU1373_AINR_CTRL(1), 0, 0x1f, 0, adau1373_in_pga_tlv),
+       SOC_DOUBLE_R_TLV("Input 3 Capture Volume", ADAU1373_AINL_CTRL(2),
+               ADAU1373_AINR_CTRL(2), 0, 0x1f, 0, adau1373_in_pga_tlv),
+       SOC_DOUBLE_R_TLV("Input 4 Capture Volume", ADAU1373_AINL_CTRL(3),
+               ADAU1373_AINR_CTRL(3), 0, 0x1f, 0, adau1373_in_pga_tlv),
+
+       SOC_SINGLE_TLV("Earpiece Playback Volume", ADAU1373_EP_CTRL, 0, 3, 0,
+               adau1373_ep_tlv),
+
+       SOC_DOUBLE_TLV("AIF3 Boost Playback Volume", ADAU1373_VOL_GAIN1, 4, 5,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("AIF2 Boost Playback Volume", ADAU1373_VOL_GAIN1, 2, 3,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("AIF1 Boost Playback Volume", ADAU1373_VOL_GAIN1, 0, 1,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("AIF3 Boost Capture Volume", ADAU1373_VOL_GAIN2, 4, 5,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("AIF2 Boost Capture Volume", ADAU1373_VOL_GAIN2, 2, 3,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("AIF1 Boost Capture Volume", ADAU1373_VOL_GAIN2, 0, 1,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("DMIC Boost Capture Volume", ADAU1373_VOL_GAIN3, 6, 7,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("ADC Boost Capture Volume", ADAU1373_VOL_GAIN3, 4, 5,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("DAC2 Boost Playback Volume", ADAU1373_VOL_GAIN3, 2, 3,
+               1, 0, adau1373_gain_boost_tlv),
+       SOC_DOUBLE_TLV("DAC1 Boost Playback Volume", ADAU1373_VOL_GAIN3, 0, 1,
+               1, 0, adau1373_gain_boost_tlv),
+
+       SOC_DOUBLE_TLV("Input 1 Boost Capture Volume", ADAU1373_ADC_GAIN, 0, 4,
+               1, 0, adau1373_input_boost_tlv),
+       SOC_DOUBLE_TLV("Input 2 Boost Capture Volume", ADAU1373_ADC_GAIN, 1, 5,
+               1, 0, adau1373_input_boost_tlv),
+       SOC_DOUBLE_TLV("Input 3 Boost Capture Volume", ADAU1373_ADC_GAIN, 2, 6,
+               1, 0, adau1373_input_boost_tlv),
+       SOC_DOUBLE_TLV("Input 4 Boost Capture Volume", ADAU1373_ADC_GAIN, 3, 7,
+               1, 0, adau1373_input_boost_tlv),
+
+       SOC_DOUBLE_TLV("Speaker Boost Playback Volume", ADAU1373_LS_CTRL, 2, 3,
+               1, 0, adau1373_speaker_boost_tlv),
+
+       SOC_ENUM("Lineout1 LR Mux", adau1373_lineout1_lr_mux_enum),
+       SOC_ENUM("Speaker LR Mux", adau1373_speaker_lr_mux_enum),
+
+       SOC_ENUM("HPF Cutoff", adau1373_hpf_cutoff_enum),
+       SOC_DOUBLE("HPF Switch", ADAU1373_HPF_CTRL, 1, 0, 1, 0),
+       SOC_ENUM("HPF Channel", adau1373_hpf_channel_enum),
+
+       SOC_ENUM("Bass HPF Cutoff", adau1373_bass_hpf_cutoff_enum),
+       SOC_VALUE_ENUM("Bass Clip Level Threshold",
+           adau1373_bass_clip_level_enum),
+       SOC_ENUM("Bass LPF Cutoff", adau1373_bass_lpf_cutoff_enum),
+       SOC_DOUBLE("Bass Playback Switch", ADAU1373_BASS2, 0, 1, 1, 0),
+       SOC_SINGLE_TLV("Bass Playback Volume", ADAU1373_BASS2, 2, 7, 0,
+           adau1373_bass_tlv),
+       SOC_ENUM("Bass Channel", adau1373_bass_channel_enum),
+
+       SOC_ENUM("3D Freq", adau1373_3d_cutoff_enum),
+       SOC_ENUM("3D Level", adau1373_3d_level_enum),
+       SOC_SINGLE("3D Playback Switch", ADAU1373_3D_CTRL2, 0, 1, 0),
+       SOC_SINGLE_TLV("3D Playback Volume", ADAU1373_3D_CTRL2, 2, 7, 0,
+               adau1373_3d_tlv),
+       SOC_ENUM("3D Channel", adau1373_bass_channel_enum),
+
+       SOC_SINGLE("Zero Cross Switch", ADAU1373_PWDN_CTRL3, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1373_lineout2_controls[] = {
+       SOC_DOUBLE_R_TLV("Lineout2 Playback Volume", ADAU1373_LLINE_OUT(1),
+               ADAU1373_RLINE_OUT(1), 0, 0x1f, 0, adau1373_out_tlv),
+       SOC_ENUM("Lineout2 LR Mux", adau1373_lineout2_lr_mux_enum),
+};
+
+static const struct snd_kcontrol_new adau1373_drc_controls[] = {
+       SOC_ENUM("DRC1 Channel", adau1373_drc1_channel_enum),
+       SOC_ENUM("DRC2 Channel", adau1373_drc2_channel_enum),
+       SOC_ENUM("DRC3 Channel", adau1373_drc3_channel_enum),
+};
+
+static int adau1373_pll_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       unsigned int pll_id = w->name[3] - '1';
+       unsigned int val;
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               val = ADAU1373_PLL_CTRL6_PLL_EN;
+       else
+               val = 0;
+
+       snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+               ADAU1373_PLL_CTRL6_PLL_EN, val);
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               mdelay(5);
+
+       return 0;
+}
+
+static const char *adau1373_decimator_text[] = {
+       "ADC",
+       "DMIC1",
+};
+
+static const struct soc_enum adau1373_decimator_enum =
+       SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text);
+
+static const struct snd_kcontrol_new adau1373_decimator_mux =
+       SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum);
+
+static const struct snd_kcontrol_new adau1373_left_adc_mixer_controls[] = {
+       SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_LADC_MIXER, 4, 1, 0),
+       SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_LADC_MIXER, 3, 1, 0),
+       SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_LADC_MIXER, 2, 1, 0),
+       SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_LADC_MIXER, 1, 1, 0),
+       SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_LADC_MIXER, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1373_right_adc_mixer_controls[] = {
+       SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_RADC_MIXER, 4, 1, 0),
+       SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_RADC_MIXER, 3, 1, 0),
+       SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_RADC_MIXER, 2, 1, 0),
+       SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_RADC_MIXER, 1, 1, 0),
+       SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_RADC_MIXER, 0, 1, 0),
+};
+
+#define DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(_name, _reg) \
+const struct snd_kcontrol_new _name[] = { \
+       SOC_DAPM_SINGLE("Left DAC2 Switch", _reg, 7, 1, 0), \
+       SOC_DAPM_SINGLE("Right DAC2 Switch", _reg, 6, 1, 0), \
+       SOC_DAPM_SINGLE("Left DAC1 Switch", _reg, 5, 1, 0), \
+       SOC_DAPM_SINGLE("Right DAC1 Switch", _reg, 4, 1, 0), \
+       SOC_DAPM_SINGLE("Input 4 Bypass Switch", _reg, 3, 1, 0), \
+       SOC_DAPM_SINGLE("Input 3 Bypass Switch", _reg, 2, 1, 0), \
+       SOC_DAPM_SINGLE("Input 2 Bypass Switch", _reg, 1, 1, 0), \
+       SOC_DAPM_SINGLE("Input 1 Bypass Switch", _reg, 0, 1, 0), \
+}
+
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line1_mixer_controls,
+       ADAU1373_LLINE1_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line1_mixer_controls,
+       ADAU1373_RLINE1_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line2_mixer_controls,
+       ADAU1373_LLINE2_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line2_mixer_controls,
+       ADAU1373_RLINE2_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_spk_mixer_controls,
+       ADAU1373_LSPK_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_spk_mixer_controls,
+       ADAU1373_RSPK_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_ep_mixer_controls,
+       ADAU1373_EP_MIX);
+
+static const struct snd_kcontrol_new adau1373_left_hp_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Left DAC1 Switch", ADAU1373_LHP_MIX, 5, 1, 0),
+       SOC_DAPM_SINGLE("Left DAC2 Switch", ADAU1373_LHP_MIX, 4, 1, 0),
+       SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_LHP_MIX, 3, 1, 0),
+       SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_LHP_MIX, 2, 1, 0),
+       SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_LHP_MIX, 1, 1, 0),
+       SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_LHP_MIX, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1373_right_hp_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Right DAC1 Switch", ADAU1373_RHP_MIX, 5, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC2 Switch", ADAU1373_RHP_MIX, 4, 1, 0),
+       SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_RHP_MIX, 3, 1, 0),
+       SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_RHP_MIX, 2, 1, 0),
+       SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_RHP_MIX, 1, 1, 0),
+       SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_RHP_MIX, 0, 1, 0),
+};
+
+#define DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(_name, _reg) \
+const struct snd_kcontrol_new _name[] = { \
+       SOC_DAPM_SINGLE("DMIC2 Swapped Switch", _reg, 6, 1, 0), \
+       SOC_DAPM_SINGLE("DMIC2 Switch", _reg, 5, 1, 0), \
+       SOC_DAPM_SINGLE("ADC/DMIC1 Swapped Switch", _reg, 4, 1, 0), \
+       SOC_DAPM_SINGLE("ADC/DMIC1 Switch", _reg, 3, 1, 0), \
+       SOC_DAPM_SINGLE("AIF3 Switch", _reg, 2, 1, 0), \
+       SOC_DAPM_SINGLE("AIF2 Switch", _reg, 1, 1, 0), \
+       SOC_DAPM_SINGLE("AIF1 Switch", _reg, 0, 1, 0), \
+}
+
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel1_mixer_controls,
+       ADAU1373_DIN_MIX_CTRL(0));
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel2_mixer_controls,
+       ADAU1373_DIN_MIX_CTRL(1));
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel3_mixer_controls,
+       ADAU1373_DIN_MIX_CTRL(2));
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel4_mixer_controls,
+       ADAU1373_DIN_MIX_CTRL(3));
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel5_mixer_controls,
+       ADAU1373_DIN_MIX_CTRL(4));
+
+#define DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(_name, _reg) \
+const struct snd_kcontrol_new _name[] = { \
+       SOC_DAPM_SINGLE("DSP Channel5 Switch", _reg, 4, 1, 0), \
+       SOC_DAPM_SINGLE("DSP Channel4 Switch", _reg, 3, 1, 0), \
+       SOC_DAPM_SINGLE("DSP Channel3 Switch", _reg, 2, 1, 0), \
+       SOC_DAPM_SINGLE("DSP Channel2 Switch", _reg, 1, 1, 0), \
+       SOC_DAPM_SINGLE("DSP Channel1 Switch", _reg, 0, 1, 0), \
+}
+
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif1_mixer_controls,
+       ADAU1373_DOUT_MIX_CTRL(0));
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif2_mixer_controls,
+       ADAU1373_DOUT_MIX_CTRL(1));
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif3_mixer_controls,
+       ADAU1373_DOUT_MIX_CTRL(2));
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac1_mixer_controls,
+       ADAU1373_DOUT_MIX_CTRL(3));
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac2_mixer_controls,
+       ADAU1373_DOUT_MIX_CTRL(4));
+
+static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = {
+       /* Datasheet claims Left ADC is bit 6 and Right ADC is bit 7, but that
+        * doesn't seem to be the case. */
+       SND_SOC_DAPM_ADC("Left ADC", NULL, ADAU1373_PWDN_CTRL1, 7, 0),
+       SND_SOC_DAPM_ADC("Right ADC", NULL, ADAU1373_PWDN_CTRL1, 6, 0),
+
+       SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1373_DIGMICCTRL, 0, 0),
+       SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1373_DIGMICCTRL, 2, 0),
+
+       SND_SOC_DAPM_VIRT_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0,
+               &adau1373_decimator_mux),
+
+       SND_SOC_DAPM_SUPPLY("MICBIAS2", ADAU1373_PWDN_CTRL1, 5, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("MICBIAS1", ADAU1373_PWDN_CTRL1, 4, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("IN4PGA", ADAU1373_PWDN_CTRL1, 3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("IN3PGA", ADAU1373_PWDN_CTRL1, 2, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("IN2PGA", ADAU1373_PWDN_CTRL1, 1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("IN1PGA", ADAU1373_PWDN_CTRL1, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_DAC("Left DAC2", NULL, ADAU1373_PWDN_CTRL2, 7, 0),
+       SND_SOC_DAPM_DAC("Right DAC2", NULL, ADAU1373_PWDN_CTRL2, 6, 0),
+       SND_SOC_DAPM_DAC("Left DAC1", NULL, ADAU1373_PWDN_CTRL2, 5, 0),
+       SND_SOC_DAPM_DAC("Right DAC1", NULL, ADAU1373_PWDN_CTRL2, 4, 0),
+
+       SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_left_adc_mixer_controls),
+       SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_right_adc_mixer_controls),
+
+       SOC_MIXER_ARRAY("Left Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 3, 0,
+               adau1373_left_line2_mixer_controls),
+       SOC_MIXER_ARRAY("Right Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 2, 0,
+               adau1373_right_line2_mixer_controls),
+       SOC_MIXER_ARRAY("Left Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 1, 0,
+               adau1373_left_line1_mixer_controls),
+       SOC_MIXER_ARRAY("Right Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 0, 0,
+               adau1373_right_line1_mixer_controls),
+
+       SOC_MIXER_ARRAY("Earpiece Mixer", ADAU1373_PWDN_CTRL3, 4, 0,
+               adau1373_ep_mixer_controls),
+       SOC_MIXER_ARRAY("Left Speaker Mixer", ADAU1373_PWDN_CTRL3, 3, 0,
+               adau1373_left_spk_mixer_controls),
+       SOC_MIXER_ARRAY("Right Speaker Mixer", ADAU1373_PWDN_CTRL3, 2, 0,
+               adau1373_right_spk_mixer_controls),
+       SOC_MIXER_ARRAY("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_left_hp_mixer_controls),
+       SOC_MIXER_ARRAY("Right Headphone Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_right_hp_mixer_controls),
+       SND_SOC_DAPM_SUPPLY("Headphone Enable", ADAU1373_PWDN_CTRL3, 1, 0,
+               NULL, 0),
+
+       SND_SOC_DAPM_SUPPLY("AIF1 CLK", ADAU1373_SRC_DAI_CTRL(0), 0, 0,
+           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("AIF2 CLK", ADAU1373_SRC_DAI_CTRL(1), 0, 0,
+           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("AIF3 CLK", ADAU1373_SRC_DAI_CTRL(2), 0, 0,
+           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("AIF1 IN SRC", ADAU1373_SRC_DAI_CTRL(0), 2, 0,
+           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("AIF1 OUT SRC", ADAU1373_SRC_DAI_CTRL(0), 1, 0,
+           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("AIF2 IN SRC", ADAU1373_SRC_DAI_CTRL(1), 2, 0,
+           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("AIF2 OUT SRC", ADAU1373_SRC_DAI_CTRL(1), 1, 0,
+           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("AIF3 IN SRC", ADAU1373_SRC_DAI_CTRL(2), 2, 0,
+           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("AIF3 OUT SRC", ADAU1373_SRC_DAI_CTRL(2), 1, 0,
+           NULL, 0),
+
+       SND_SOC_DAPM_AIF_IN("AIF1 IN", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("AIF1 OUT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_IN("AIF2 IN", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("AIF2 OUT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_IN("AIF3 IN", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("AIF3 OUT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+       SOC_MIXER_ARRAY("DSP Channel1 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_dsp_channel1_mixer_controls),
+       SOC_MIXER_ARRAY("DSP Channel2 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_dsp_channel2_mixer_controls),
+       SOC_MIXER_ARRAY("DSP Channel3 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_dsp_channel3_mixer_controls),
+       SOC_MIXER_ARRAY("DSP Channel4 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_dsp_channel4_mixer_controls),
+       SOC_MIXER_ARRAY("DSP Channel5 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_dsp_channel5_mixer_controls),
+
+       SOC_MIXER_ARRAY("AIF1 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_aif1_mixer_controls),
+       SOC_MIXER_ARRAY("AIF2 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_aif2_mixer_controls),
+       SOC_MIXER_ARRAY("AIF3 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_aif3_mixer_controls),
+       SOC_MIXER_ARRAY("DAC1 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_dac1_mixer_controls),
+       SOC_MIXER_ARRAY("DAC2 Mixer", SND_SOC_NOPM, 0, 0,
+               adau1373_dac2_mixer_controls),
+
+       SND_SOC_DAPM_SUPPLY("DSP", ADAU1373_DIGEN, 4, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Recording Engine B", ADAU1373_DIGEN, 3, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Recording Engine A", ADAU1373_DIGEN, 2, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Playback Engine B", ADAU1373_DIGEN, 1, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Playback Engine A", ADAU1373_DIGEN, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_SUPPLY("PLL1", SND_SOC_NOPM, 0, 0, adau1373_pll_event,
+               SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_SUPPLY("PLL2", SND_SOC_NOPM, 0, 0, adau1373_pll_event,
+               SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_SUPPLY("SYSCLK1", ADAU1373_CLK_SRC_DIV(0), 7, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("SYSCLK2", ADAU1373_CLK_SRC_DIV(1), 7, 0, NULL, 0),
+
+       SND_SOC_DAPM_INPUT("AIN1L"),
+       SND_SOC_DAPM_INPUT("AIN1R"),
+       SND_SOC_DAPM_INPUT("AIN2L"),
+       SND_SOC_DAPM_INPUT("AIN2R"),
+       SND_SOC_DAPM_INPUT("AIN3L"),
+       SND_SOC_DAPM_INPUT("AIN3R"),
+       SND_SOC_DAPM_INPUT("AIN4L"),
+       SND_SOC_DAPM_INPUT("AIN4R"),
+
+       SND_SOC_DAPM_INPUT("DMIC1DAT"),
+       SND_SOC_DAPM_INPUT("DMIC2DAT"),
+
+       SND_SOC_DAPM_OUTPUT("LOUT1L"),
+       SND_SOC_DAPM_OUTPUT("LOUT1R"),
+       SND_SOC_DAPM_OUTPUT("LOUT2L"),
+       SND_SOC_DAPM_OUTPUT("LOUT2R"),
+       SND_SOC_DAPM_OUTPUT("HPL"),
+       SND_SOC_DAPM_OUTPUT("HPR"),
+       SND_SOC_DAPM_OUTPUT("SPKL"),
+       SND_SOC_DAPM_OUTPUT("SPKR"),
+       SND_SOC_DAPM_OUTPUT("EP"),
+};
+
+static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source,
+       struct snd_soc_dapm_widget *sink)
+{
+       struct snd_soc_codec *codec = source->codec;
+       struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+       unsigned int dai;
+       const char *clk;
+
+       dai = sink->name[3] - '1';
+
+       if (!adau1373->dais[dai].master)
+               return 0;
+
+       if (adau1373->dais[dai].clk_src == ADAU1373_CLK_SRC_PLL1)
+               clk = "SYSCLK1";
+       else
+               clk = "SYSCLK2";
+
+       return strcmp(source->name, clk) == 0;
+}
+
+static int adau1373_check_src(struct snd_soc_dapm_widget *source,
+       struct snd_soc_dapm_widget *sink)
+{
+       struct snd_soc_codec *codec = source->codec;
+       struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+       unsigned int dai;
+
+       dai = sink->name[3] - '1';
+
+       return adau1373->dais[dai].enable_src;
+}
+
+#define DSP_CHANNEL_MIXER_ROUTES(_sink) \
+       { _sink, "DMIC2 Swapped Switch", "DMIC2" }, \
+       { _sink, "DMIC2 Switch", "DMIC2" }, \
+       { _sink, "ADC/DMIC1 Swapped Switch", "Decimator Mux" }, \
+       { _sink, "ADC/DMIC1 Switch", "Decimator Mux" }, \
+       { _sink, "AIF1 Switch", "AIF1 IN" }, \
+       { _sink, "AIF2 Switch", "AIF2 IN" }, \
+       { _sink, "AIF3 Switch", "AIF3 IN" }
+
+#define DSP_OUTPUT_MIXER_ROUTES(_sink) \
+       { _sink, "DSP Channel1 Switch", "DSP Channel1 Mixer" }, \
+       { _sink, "DSP Channel2 Switch", "DSP Channel2 Mixer" }, \
+       { _sink, "DSP Channel3 Switch", "DSP Channel3 Mixer" }, \
+       { _sink, "DSP Channel4 Switch", "DSP Channel4 Mixer" }, \
+       { _sink, "DSP Channel5 Switch", "DSP Channel5 Mixer" }
+
+#define LEFT_OUTPUT_MIXER_ROUTES(_sink) \
+       { _sink, "Right DAC2 Switch", "Right DAC2" }, \
+       { _sink, "Left DAC2 Switch", "Left DAC2" }, \
+       { _sink, "Right DAC1 Switch", "Right DAC1" }, \
+       { _sink, "Left DAC1 Switch", "Left DAC1" }, \
+       { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \
+       { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \
+       { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \
+       { _sink, "Input 4 Bypass Switch", "IN4PGA" }
+
+#define RIGHT_OUTPUT_MIXER_ROUTES(_sink) \
+       { _sink, "Right DAC2 Switch", "Right DAC2" }, \
+       { _sink, "Left DAC2 Switch", "Left DAC2" }, \
+       { _sink, "Right DAC1 Switch", "Right DAC1" }, \
+       { _sink, "Left DAC1 Switch", "Left DAC1" }, \
+       { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \
+       { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \
+       { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \
+       { _sink, "Input 4 Bypass Switch", "IN4PGA" }
+
+static const struct snd_soc_dapm_route adau1373_dapm_routes[] = {
+       { "Left ADC Mixer", "DAC1 Switch", "Left DAC1" },
+       { "Left ADC Mixer", "Input 1 Switch", "IN1PGA" },
+       { "Left ADC Mixer", "Input 2 Switch", "IN2PGA" },
+       { "Left ADC Mixer", "Input 3 Switch", "IN3PGA" },
+       { "Left ADC Mixer", "Input 4 Switch", "IN4PGA" },
+
+       { "Right ADC Mixer", "DAC1 Switch", "Right DAC1" },
+       { "Right ADC Mixer", "Input 1 Switch", "IN1PGA" },
+       { "Right ADC Mixer", "Input 2 Switch", "IN2PGA" },
+       { "Right ADC Mixer", "Input 3 Switch", "IN3PGA" },
+       { "Right ADC Mixer", "Input 4 Switch", "IN4PGA" },
+
+       { "Left ADC", NULL, "Left ADC Mixer" },
+       { "Right ADC", NULL, "Right ADC Mixer" },
+
+       { "Decimator Mux", "ADC", "Left ADC" },
+       { "Decimator Mux", "ADC", "Right ADC" },
+       { "Decimator Mux", "DMIC1", "DMIC1" },
+
+       DSP_CHANNEL_MIXER_ROUTES("DSP Channel1 Mixer"),
+       DSP_CHANNEL_MIXER_ROUTES("DSP Channel2 Mixer"),
+       DSP_CHANNEL_MIXER_ROUTES("DSP Channel3 Mixer"),
+       DSP_CHANNEL_MIXER_ROUTES("DSP Channel4 Mixer"),
+       DSP_CHANNEL_MIXER_ROUTES("DSP Channel5 Mixer"),
+
+       DSP_OUTPUT_MIXER_ROUTES("AIF1 Mixer"),
+       DSP_OUTPUT_MIXER_ROUTES("AIF2 Mixer"),
+       DSP_OUTPUT_MIXER_ROUTES("AIF3 Mixer"),
+       DSP_OUTPUT_MIXER_ROUTES("DAC1 Mixer"),
+       DSP_OUTPUT_MIXER_ROUTES("DAC2 Mixer"),
+
+       { "AIF1 OUT", NULL, "AIF1 Mixer" },
+       { "AIF2 OUT", NULL, "AIF2 Mixer" },
+       { "AIF3 OUT", NULL, "AIF3 Mixer" },
+       { "Left DAC1", NULL, "DAC1 Mixer" },
+       { "Right DAC1", NULL, "DAC1 Mixer" },
+       { "Left DAC2", NULL, "DAC2 Mixer" },
+       { "Right DAC2", NULL, "DAC2 Mixer" },
+
+       LEFT_OUTPUT_MIXER_ROUTES("Left Lineout1 Mixer"),
+       RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout1 Mixer"),
+       LEFT_OUTPUT_MIXER_ROUTES("Left Lineout2 Mixer"),
+       RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout2 Mixer"),
+       LEFT_OUTPUT_MIXER_ROUTES("Left Speaker Mixer"),
+       RIGHT_OUTPUT_MIXER_ROUTES("Right Speaker Mixer"),
+
+       { "Left Headphone Mixer", "Left DAC2 Switch", "Left DAC2" },
+       { "Left Headphone Mixer", "Left DAC1 Switch", "Left DAC1" },
+       { "Left Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" },
+       { "Left Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" },
+       { "Left Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" },
+       { "Left Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" },
+       { "Right Headphone Mixer", "Right DAC2 Switch", "Right DAC2" },
+       { "Right Headphone Mixer", "Right DAC1 Switch", "Right DAC1" },
+       { "Right Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" },
+       { "Right Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" },
+       { "Right Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" },
+       { "Right Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" },
+
+       { "Left Headphone Mixer", NULL, "Headphone Enable" },
+       { "Right Headphone Mixer", NULL, "Headphone Enable" },
+
+       { "Earpiece Mixer", "Right DAC2 Switch", "Right DAC2" },
+       { "Earpiece Mixer", "Left DAC2 Switch", "Left DAC2" },
+       { "Earpiece Mixer", "Right DAC1 Switch", "Right DAC1" },
+       { "Earpiece Mixer", "Left DAC1 Switch", "Left DAC1" },
+       { "Earpiece Mixer", "Input 1 Bypass Switch", "IN1PGA" },
+       { "Earpiece Mixer", "Input 2 Bypass Switch", "IN2PGA" },
+       { "Earpiece Mixer", "Input 3 Bypass Switch", "IN3PGA" },
+       { "Earpiece Mixer", "Input 4 Bypass Switch", "IN4PGA" },
+
+       { "LOUT1L", NULL, "Left Lineout1 Mixer" },
+       { "LOUT1R", NULL, "Right Lineout1 Mixer" },
+       { "LOUT2L", NULL, "Left Lineout2 Mixer" },
+       { "LOUT2R", NULL, "Right Lineout2 Mixer" },
+       { "SPKL", NULL, "Left Speaker Mixer" },
+       { "SPKR", NULL, "Right Speaker Mixer" },
+       { "HPL", NULL, "Left Headphone Mixer" },
+       { "HPR", NULL, "Right Headphone Mixer" },
+       { "EP", NULL, "Earpiece Mixer" },
+
+       { "IN1PGA", NULL, "AIN1L" },
+       { "IN2PGA", NULL, "AIN2L" },
+       { "IN3PGA", NULL, "AIN3L" },
+       { "IN4PGA", NULL, "AIN4L" },
+       { "IN1PGA", NULL, "AIN1R" },
+       { "IN2PGA", NULL, "AIN2R" },
+       { "IN3PGA", NULL, "AIN3R" },
+       { "IN4PGA", NULL, "AIN4R" },
+
+       { "SYSCLK1", NULL, "PLL1" },
+       { "SYSCLK2", NULL, "PLL2" },
+
+       { "Left DAC1", NULL, "SYSCLK1" },
+       { "Right DAC1", NULL, "SYSCLK1" },
+       { "Left DAC2", NULL, "SYSCLK1" },
+       { "Right DAC2", NULL, "SYSCLK1" },
+       { "Left ADC", NULL, "SYSCLK1" },
+       { "Right ADC", NULL, "SYSCLK1" },
+
+       { "DSP", NULL, "SYSCLK1" },
+
+       { "AIF1 Mixer", NULL, "DSP" },
+       { "AIF2 Mixer", NULL, "DSP" },
+       { "AIF3 Mixer", NULL, "DSP" },
+       { "DAC1 Mixer", NULL, "DSP" },
+       { "DAC2 Mixer", NULL, "DSP" },
+       { "DAC1 Mixer", NULL, "Playback Engine A" },
+       { "DAC2 Mixer", NULL, "Playback Engine B" },
+       { "Left ADC Mixer", NULL, "Recording Engine A" },
+       { "Right ADC Mixer", NULL, "Recording Engine A" },
+
+       { "AIF1 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk },
+       { "AIF2 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk },
+       { "AIF3 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk },
+       { "AIF1 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk },
+       { "AIF2 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk },
+       { "AIF3 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk },
+
+       { "AIF1 IN", NULL, "AIF1 CLK" },
+       { "AIF1 OUT", NULL, "AIF1 CLK" },
+       { "AIF2 IN", NULL, "AIF2 CLK" },
+       { "AIF2 OUT", NULL, "AIF2 CLK" },
+       { "AIF3 IN", NULL, "AIF3 CLK" },
+       { "AIF3 OUT", NULL, "AIF3 CLK" },
+       { "AIF1 IN", NULL, "AIF1 IN SRC", adau1373_check_src },
+       { "AIF1 OUT", NULL, "AIF1 OUT SRC", adau1373_check_src },
+       { "AIF2 IN", NULL, "AIF2 IN SRC", adau1373_check_src },
+       { "AIF2 OUT", NULL, "AIF2 OUT SRC", adau1373_check_src },
+       { "AIF3 IN", NULL, "AIF3 IN SRC", adau1373_check_src },
+       { "AIF3 OUT", NULL, "AIF3 OUT SRC", adau1373_check_src },
+
+       { "DMIC1", NULL, "DMIC1DAT" },
+       { "DMIC1", NULL, "SYSCLK1" },
+       { "DMIC1", NULL, "Recording Engine A" },
+       { "DMIC2", NULL, "DMIC2DAT" },
+       { "DMIC2", NULL, "SYSCLK1" },
+       { "DMIC2", NULL, "Recording Engine B" },
+};
+
+static int adau1373_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 adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+       struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id];
+       unsigned int div;
+       unsigned int freq;
+       unsigned int ctrl;
+
+       freq = adau1373_dai->sysclk;
+
+       if (freq % params_rate(params) != 0)
+               return -EINVAL;
+
+       switch (freq / params_rate(params)) {
+       case 1024: /* sysclk / 256 */
+               div = 0;
+               break;
+       case 1536: /* 2/3 sysclk / 256 */
+               div = 1;
+               break;
+       case 2048: /* 1/2 sysclk / 256 */
+               div = 2;
+               break;
+       case 3072: /* 1/3 sysclk / 256 */
+               div = 3;
+               break;
+       case 4096: /* 1/4 sysclk / 256 */
+               div = 4;
+               break;
+       case 6144: /* 1/6 sysclk / 256 */
+               div = 5;
+               break;
+       case 5632: /* 2/11 sysclk / 256 */
+               div = 6;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       adau1373_dai->enable_src = (div != 0);
+
+       snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
+               ~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64);
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               ctrl = ADAU1373_DAI_WLEN_16;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               ctrl = ADAU1373_DAI_WLEN_20;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               ctrl = ADAU1373_DAI_WLEN_24;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               ctrl = ADAU1373_DAI_WLEN_32;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
+                       ADAU1373_DAI_WLEN_MASK, ctrl);
+}
+
+static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+       struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id];
+       unsigned int ctrl;
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               ctrl = ADAU1373_DAI_MASTER;
+               adau1373_dai->master = true;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               ctrl = 0;
+               adau1373_dai->master = false;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               ctrl |= ADAU1373_DAI_FORMAT_I2S;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               ctrl |= ADAU1373_DAI_FORMAT_LEFT_J;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               ctrl |= ADAU1373_DAI_FORMAT_RIGHT_J;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               ctrl |= ADAU1373_DAI_FORMAT_DSP;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               ctrl |= ADAU1373_DAI_INVERT_BCLK;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               ctrl |= ADAU1373_DAI_INVERT_LRCLK;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               ctrl |= ADAU1373_DAI_INVERT_LRCLK | ADAU1373_DAI_INVERT_BCLK;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
+               ~ADAU1373_DAI_WLEN_MASK, ctrl);
+
+       return 0;
+}
+
+static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai,
+       int clk_id, unsigned int freq, int dir)
+{
+       struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(dai->codec);
+       struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id];
+
+       switch (clk_id) {
+       case ADAU1373_CLK_SRC_PLL1:
+       case ADAU1373_CLK_SRC_PLL2:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       adau1373_dai->sysclk = freq;
+       adau1373_dai->clk_src = clk_id;
+
+       snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id),
+               ADAU1373_BCLKDIV_SOURCE, clk_id << 5);
+
+       return 0;
+}
+
+static const struct snd_soc_dai_ops adau1373_dai_ops = {
+       .hw_params      = adau1373_hw_params,
+       .set_sysclk     = adau1373_set_dai_sysclk,
+       .set_fmt        = adau1373_set_dai_fmt,
+};
+
+#define ADAU1373_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 adau1373_dai_driver[] = {
+       {
+               .id = 0,
+               .name = "adau1373-aif1",
+               .playback = {
+                       .stream_name = "AIF1 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = SNDRV_PCM_RATE_8000_48000,
+                       .formats = ADAU1373_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "AIF1 Capture",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = SNDRV_PCM_RATE_8000_48000,
+                       .formats = ADAU1373_FORMATS,
+               },
+               .ops = &adau1373_dai_ops,
+               .symmetric_rates = 1,
+       },
+       {
+               .id = 1,
+               .name = "adau1373-aif2",
+               .playback = {
+                       .stream_name = "AIF2 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = SNDRV_PCM_RATE_8000_48000,
+                       .formats = ADAU1373_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "AIF2 Capture",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = SNDRV_PCM_RATE_8000_48000,
+                       .formats = ADAU1373_FORMATS,
+               },
+               .ops = &adau1373_dai_ops,
+               .symmetric_rates = 1,
+       },
+       {
+               .id = 2,
+               .name = "adau1373-aif3",
+               .playback = {
+                       .stream_name = "AIF3 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = SNDRV_PCM_RATE_8000_48000,
+                       .formats = ADAU1373_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "AIF3 Capture",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = SNDRV_PCM_RATE_8000_48000,
+                       .formats = ADAU1373_FORMATS,
+               },
+               .ops = &adau1373_dai_ops,
+               .symmetric_rates = 1,
+       },
+};
+
+static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
+       int source, unsigned int freq_in, unsigned int freq_out)
+{
+       unsigned int dpll_div = 0;
+       unsigned int x, r, n, m, i, j, mode;
+
+       switch (pll_id) {
+       case ADAU1373_PLL1:
+       case ADAU1373_PLL2:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (source) {
+       case ADAU1373_PLL_SRC_BCLK1:
+       case ADAU1373_PLL_SRC_BCLK2:
+       case ADAU1373_PLL_SRC_BCLK3:
+       case ADAU1373_PLL_SRC_LRCLK1:
+       case ADAU1373_PLL_SRC_LRCLK2:
+       case ADAU1373_PLL_SRC_LRCLK3:
+       case ADAU1373_PLL_SRC_MCLK1:
+       case ADAU1373_PLL_SRC_MCLK2:
+       case ADAU1373_PLL_SRC_GPIO1:
+       case ADAU1373_PLL_SRC_GPIO2:
+       case ADAU1373_PLL_SRC_GPIO3:
+       case ADAU1373_PLL_SRC_GPIO4:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (freq_in < 7813 || freq_in > 27000000)
+               return -EINVAL;
+
+       if (freq_out < 45158000 || freq_out > 49152000)
+               return -EINVAL;
+
+       /* APLL input needs to be >= 8Mhz, so in case freq_in is less we use the
+        * DPLL to get it there. DPLL_out = (DPLL_in / div) * 1024 */
+       while (freq_in < 8000000) {
+               freq_in *= 2;
+               dpll_div++;
+       }
+
+       if (freq_out % freq_in != 0) {
+               /* fout = fin * (r + (n/m)) / x */
+               x = DIV_ROUND_UP(freq_in, 13500000);
+               freq_in /= x;
+               r = freq_out / freq_in;
+               i = freq_out % freq_in;
+               j = gcd(i, freq_in);
+               n = i / j;
+               m = freq_in / j;
+               x--;
+               mode = 1;
+       } else {
+               /* fout = fin / r */
+               r = freq_out / freq_in;
+               n = 0;
+               m = 0;
+               x = 0;
+               mode = 0;
+       }
+
+       if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff)
+               return -EINVAL;
+
+       if (dpll_div) {
+               dpll_div = 11 - dpll_div;
+               snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+                       ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0);
+       } else {
+               snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+                       ADAU1373_PLL_CTRL6_DPLL_BYPASS,
+                       ADAU1373_PLL_CTRL6_DPLL_BYPASS);
+       }
+
+       snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id),
+               (source << 4) | dpll_div);
+       snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
+       snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
+       snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
+       snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
+       snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id),
+               (r << 3) | (x << 1) | mode);
+
+       /* Set sysclk to pll_rate / 4 */
+       snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);
+
+       return 0;
+}
+
+static void adau1373_load_drc_settings(struct snd_soc_codec *codec,
+       unsigned int nr, uint8_t *drc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ADAU1373_DRC_SIZE; ++i)
+               snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]);
+}
+
+static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias)
+{
+       switch (micbias) {
+       case ADAU1373_MICBIAS_2_9V:
+       case ADAU1373_MICBIAS_2_2V:
+       case ADAU1373_MICBIAS_2_6V:
+       case ADAU1373_MICBIAS_1_8V:
+               return true;
+       default:
+               break;
+       }
+       return false;
+}
+
+static int adau1373_probe(struct snd_soc_codec *codec)
+{
+       struct adau1373_platform_data *pdata = codec->dev->platform_data;
+       bool lineout_differential = false;
+       unsigned int val;
+       int ret;
+       int i;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+       if (ret) {
+               dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       codec->dapm.idle_bias_off = true;
+
+       if (pdata) {
+               if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting))
+                       return -EINVAL;
+
+               if (!adau1373_valid_micbias(pdata->micbias1) ||
+                       !adau1373_valid_micbias(pdata->micbias2))
+                       return -EINVAL;
+
+               for (i = 0; i < pdata->num_drc; ++i) {
+                       adau1373_load_drc_settings(codec, i,
+                               pdata->drc_setting[i]);
+               }
+
+               snd_soc_add_controls(codec, adau1373_drc_controls,
+                       pdata->num_drc);
+
+               val = 0;
+               for (i = 0; i < 4; ++i) {
+                       if (pdata->input_differential[i])
+                               val |= BIT(i);
+               }
+               snd_soc_write(codec, ADAU1373_INPUT_MODE, val);
+
+               val = 0;
+               if (pdata->lineout_differential)
+                       val |= ADAU1373_OUTPUT_CTRL_LDIFF;
+               if (pdata->lineout_ground_sense)
+                       val |= ADAU1373_OUTPUT_CTRL_LNFBEN;
+               snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val);
+
+               lineout_differential = pdata->lineout_differential;
+
+               snd_soc_write(codec, ADAU1373_EP_CTRL,
+                       (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) |
+                       (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET));
+       }
+
+       if (!lineout_differential) {
+               snd_soc_add_controls(codec, adau1373_lineout2_controls,
+                       ARRAY_SIZE(adau1373_lineout2_controls));
+       }
+
+       snd_soc_write(codec, ADAU1373_ADC_CTRL,
+           ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT);
+
+       return 0;
+}
+
+static int adau1373_set_bias_level(struct snd_soc_codec *codec,
+       enum snd_soc_bias_level level)
+{
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
+                       ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN);
+               break;
+       case SND_SOC_BIAS_OFF:
+               snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
+                       ADAU1373_PWDN_CTRL3_PWR_EN, 0);
+               break;
+       }
+       codec->dapm.bias_level = level;
+       return 0;
+}
+
+static int adau1373_remove(struct snd_soc_codec *codec)
+{
+       adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int adau1373_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+       return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static int adau1373_resume(struct snd_soc_codec *codec)
+{
+       adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       snd_soc_cache_sync(codec);
+
+       return 0;
+}
+
+static struct snd_soc_codec_driver adau1373_codec_driver = {
+       .probe =        adau1373_probe,
+       .remove =       adau1373_remove,
+       .suspend =      adau1373_suspend,
+       .resume =       adau1373_resume,
+       .set_bias_level = adau1373_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
+       .reg_cache_default = adau1373_default_regs,
+       .reg_word_size = sizeof(uint8_t),
+
+       .set_pll = adau1373_set_pll,
+
+       .controls = adau1373_controls,
+       .num_controls = ARRAY_SIZE(adau1373_controls),
+       .dapm_widgets = adau1373_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets),
+       .dapm_routes = adau1373_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes),
+};
+
+static int __devinit adau1373_i2c_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       struct adau1373 *adau1373;
+       int ret;
+
+       adau1373 = kzalloc(sizeof(*adau1373), GFP_KERNEL);
+       if (!adau1373)
+               return -ENOMEM;
+
+       dev_set_drvdata(&client->dev, adau1373);
+
+       ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver,
+                       adau1373_dai_driver, ARRAY_SIZE(adau1373_dai_driver));
+       if (ret < 0)
+               kfree(adau1373);
+
+       return ret;
+}
+
+static int __devexit adau1373_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(dev_get_drvdata(&client->dev));
+       return 0;
+}
+
+static const struct i2c_device_id adau1373_i2c_id[] = {
+       { "adau1373", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id);
+
+static struct i2c_driver adau1373_i2c_driver = {
+       .driver = {
+               .name = "adau1373",
+               .owner = THIS_MODULE,
+       },
+       .probe = adau1373_i2c_probe,
+       .remove = __devexit_p(adau1373_i2c_remove),
+       .id_table = adau1373_i2c_id,
+};
+
+static int __init adau1373_init(void)
+{
+       return i2c_add_driver(&adau1373_i2c_driver);
+}
+module_init(adau1373_init);
+
+static void __exit adau1373_exit(void)
+{
+       i2c_del_driver(&adau1373_i2c_driver);
+}
+module_exit(adau1373_exit);
+
+MODULE_DESCRIPTION("ASoC ADAU1373 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1373.h b/sound/soc/codecs/adau1373.h
new file mode 100644 (file)
index 0000000..c6ab553
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __ADAU1373_H__
+#define __ADAU1373_H__
+
+enum adau1373_pll_src {
+       ADAU1373_PLL_SRC_MCLK1 = 0,
+       ADAU1373_PLL_SRC_BCLK1 = 1,
+       ADAU1373_PLL_SRC_BCLK2 = 2,
+       ADAU1373_PLL_SRC_BCLK3 = 3,
+       ADAU1373_PLL_SRC_LRCLK1 = 4,
+       ADAU1373_PLL_SRC_LRCLK2 = 5,
+       ADAU1373_PLL_SRC_LRCLK3 = 6,
+       ADAU1373_PLL_SRC_GPIO1 = 7,
+       ADAU1373_PLL_SRC_GPIO2 = 8,
+       ADAU1373_PLL_SRC_GPIO3 = 9,
+       ADAU1373_PLL_SRC_GPIO4 = 10,
+       ADAU1373_PLL_SRC_MCLK2 = 11,
+};
+
+enum adau1373_pll {
+       ADAU1373_PLL1 = 0,
+       ADAU1373_PLL2 = 1,
+};
+
+enum adau1373_clk_src {
+       ADAU1373_CLK_SRC_PLL1 = 0,
+       ADAU1373_CLK_SRC_PLL2 = 1,
+};
+
+#endif
index 2758d5fc60d6555ed2709e43afa25a4fe02865d4..8b7e1c50d6e9df43d2a25956a698094eb2bb6738 100644 (file)
@@ -401,7 +401,7 @@ static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute)
 }
 
 static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
-       unsigned int freq, int dir)
+       int source, unsigned int freq, int dir)
 {
        unsigned int val;
 
@@ -458,6 +458,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
        int ret;
 
        codec->dapm.idle_bias_off = 1;
+       codec->control_data = to_i2c_client(codec->dev);
 
        ret = adau1701_load_firmware(codec);
        if (ret)
index 300c04b70e71ba3680a1f522451a94277682a059..f9f08948e5e878f12d40a1f337d6d40c7247119e 100644 (file)
@@ -523,7 +523,8 @@ static int adav80x_hw_params(struct snd_pcm_substream *substream,
 }
 
 static int adav80x_set_sysclk(struct snd_soc_codec *codec,
-               int clk_id, unsigned int freq, int dir)
+                             int clk_id, int source,
+                             unsigned int freq, int dir)
 {
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
index 88b29f8c748bf09a1908ecad84b088a6dd6c270f..2ecf1289ffa38782f1bf7a8577f03daa94765f17 100644 (file)
@@ -26,7 +26,6 @@
 /* codec private data */
 struct ak4671_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
 };
 
 /* ak4671 register cache & default register settings */
@@ -675,7 +674,6 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
                return -ENOMEM;
 
        i2c_set_clientdata(client, ak4671);
-       ak4671->control_data = client;
        ak4671->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&client->dev,
index eecffb5489476dff195d04a9061fae68d37af638..557b3af49b4c2a287c5ec1b65023c03f6b9d0565 100644 (file)
@@ -40,8 +40,6 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
 /* codec private data */
 struct alc5623_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
-       struct mutex mutex;
        u8 id;
        unsigned int sysclk;
        u16 reg_cache[ALC5623_VENDOR_ID2+2];
@@ -1050,9 +1048,7 @@ static int alc5623_i2c_probe(struct i2c_client *client,
        }
 
        i2c_set_clientdata(client, alc5623);
-       alc5623->control_data = client;
        alc5623->control_type = SND_SOC_I2C;
-       mutex_init(&alc5623->mutex);
 
        ret =  snd_soc_register_codec(&client->dev,
                &soc_codec_device_alc5623, &alc5623_dai, 1);
index 6cc8678f49f3b11d31453dcffd35b8ac8a430a8e..5830c934a1d139d38a5bf4e89df6fa14526900c3 100644 (file)
@@ -128,7 +128,6 @@ static const char *supply_names[] = {
 /* Private data for the CS4270 */
 struct cs4270_private {
        enum snd_soc_control_type control_type;
-       void *control_data;
        unsigned int mclk; /* Input frequency of the MCLK pin */
        unsigned int mode; /* The mode (I2S or left-justified) */
        unsigned int slave_mode;
@@ -490,8 +489,6 @@ static int cs4270_probe(struct snd_soc_codec *codec)
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
        int i, ret;
 
-       codec->control_data = cs4270->control_data;
-
        /* Tell ASoC what kind of I/O to use to read the registers.  ASoC will
         * then do the I2C transactions itself.
         */
@@ -604,7 +601,7 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
 static int cs4270_soc_resume(struct snd_soc_codec *codec)
 {
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c_client = codec->control_data;
+       struct i2c_client *i2c_client = to_i2c_client(codec->dev);
        int reg;
 
        regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
@@ -690,7 +687,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
        }
 
        i2c_set_clientdata(i2c_client, cs4270);
-       cs4270->control_data = i2c_client;
        cs4270->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c_client->dev,
index 083aab96ca80d33745aa651ac4438c872b9a2af8..23d1bd5dadda36185e2c56702e7fd17a739f9a1a 100644 (file)
@@ -156,7 +156,6 @@ static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = {
 struct cs4271_private {
        /* SND_SOC_I2C or SND_SOC_SPI */
        enum snd_soc_control_type       bus_type;
-       void                            *control_data;
        unsigned int                    mclk;
        bool                            master;
        bool                            deemph;
@@ -466,8 +465,6 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        int ret;
        int gpio_nreset = -EINVAL;
 
-       codec->control_data = cs4271->control_data;
-
        if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
                gpio_nreset = cs4271plat->gpio_nreset;
 
@@ -555,7 +552,6 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
                return -ENOMEM;
 
        spi_set_drvdata(spi, cs4271);
-       cs4271->control_data = spi;
        cs4271->bus_type = SND_SOC_SPI;
 
        return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
@@ -595,7 +591,6 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
                return -ENOMEM;
 
        i2c_set_clientdata(client, cs4271);
-       cs4271->control_data = client;
        cs4271->bus_type = SND_SOC_I2C;
 
        return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
index 8fb7070108dd8fddfd3b8d1998f3a3461730208e..286878d22b6adfbb930f32321625f98b7a4d2e31 100644 (file)
@@ -42,7 +42,6 @@ enum master_slave_mode {
 
 struct cs42l51_private {
        enum snd_soc_control_type control_type;
-       void *control_data;
        unsigned int mclk;
        unsigned int audio_mode;        /* The mode (I2S or left-justified) */
        enum master_slave_mode func;
@@ -57,7 +56,7 @@ struct cs42l51_private {
 static int cs42l51_fill_cache(struct snd_soc_codec *codec)
 {
        u8 *cache = codec->reg_cache + 1;
-       struct i2c_client *i2c_client = codec->control_data;
+       struct i2c_client *i2c_client = to_i2c_client(codec->dev);
        s32 length;
 
        length = i2c_smbus_read_i2c_block_data(i2c_client,
@@ -520,8 +519,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret, reg;
 
-       codec->control_data = cs42l51->control_data;
-
        ret = cs42l51_fill_cache(codec);
        if (ret < 0) {
                dev_err(codec->dev, "failed to fill register cache\n");
@@ -593,7 +590,6 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
        }
 
        i2c_set_clientdata(i2c_client, cs42l51);
-       cs42l51->control_data = i2c_client;
        cs42l51->control_type = SND_SOC_I2C;
 
        ret =  snd_soc_register_codec(&i2c_client->dev,
index ac65a2d3640860944f1d292f2fb482a5beccf2ca..587043b6f79f874faee4a0ff25f52f3ffd98b385 100644 (file)
@@ -40,7 +40,6 @@ struct max98088_cdata {
 
 struct max98088_priv {
        enum max98088_type devtype;
-       void *control_data;
        struct max98088_pdata *pdata;
        unsigned int sysclk;
        struct max98088_cdata dai[2];
@@ -2066,7 +2065,6 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
        max98088->devtype = id->driver_data;
 
        i2c_set_clientdata(i2c, max98088);
-       max98088->control_data = i2c;
        max98088->pdata = i2c->dev.platform_data;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 668434d44303ea6c84e748b9d6029ac8c6732977..8f8e2555cbeded03ca72b2ee140c15ff5b04a995 100644 (file)
@@ -40,7 +40,6 @@ struct max98095_cdata {
 
 struct max98095_priv {
        enum max98095_type devtype;
-       void *control_data;
        struct max98095_pdata *pdata;
        unsigned int sysclk;
        struct max98095_cdata dai[3];
@@ -2337,7 +2336,6 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
 
        max98095->devtype = id->driver_data;
        i2c_set_clientdata(i2c, max98095);
-       max98095->control_data = i2c;
        max98095->pdata = i2c->dev.platform_data;
 
        ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095,
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
new file mode 100644 (file)
index 0000000..86e69f4
--- /dev/null
@@ -0,0 +1,1775 @@
+/*
+ * rt5631.c  --  RT5631 ALSA Soc Audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ *
+ * Author: flove <flove@realtek.com>
+ *
+ * Based on WM8753.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "rt5631.h"
+
+struct rt5631_priv {
+       struct snd_soc_codec *codec;
+       int codec_version;
+       int master;
+       int sysclk;
+       int rx_rate;
+       int bclk_rate;
+       int dmic_used_flag;
+};
+
+static const u16 rt5631_reg[RT5631_VENDOR_ID2 + 1] = {
+       [RT5631_SPK_OUT_VOL] = 0x8888,
+       [RT5631_HP_OUT_VOL] = 0x8080,
+       [RT5631_MONO_AXO_1_2_VOL] = 0xa080,
+       [RT5631_AUX_IN_VOL] = 0x0808,
+       [RT5631_ADC_REC_MIXER] = 0xf0f0,
+       [RT5631_VDAC_DIG_VOL] = 0x0010,
+       [RT5631_OUTMIXER_L_CTRL] = 0xffc0,
+       [RT5631_OUTMIXER_R_CTRL] = 0xffc0,
+       [RT5631_AXO1MIXER_CTRL] = 0x88c0,
+       [RT5631_AXO2MIXER_CTRL] = 0x88c0,
+       [RT5631_DIG_MIC_CTRL] = 0x3000,
+       [RT5631_MONO_INPUT_VOL] = 0x8808,
+       [RT5631_SPK_MIXER_CTRL] = 0xf8f8,
+       [RT5631_SPK_MONO_OUT_CTRL] = 0xfc00,
+       [RT5631_SPK_MONO_HP_OUT_CTRL] = 0x4440,
+       [RT5631_SDP_CTRL] = 0x8000,
+       [RT5631_MONO_SDP_CTRL] = 0x8000,
+       [RT5631_STEREO_AD_DA_CLK_CTRL] = 0x2010,
+       [RT5631_GEN_PUR_CTRL_REG] = 0x0e00,
+       [RT5631_INT_ST_IRQ_CTRL_2] = 0x071a,
+       [RT5631_MISC_CTRL] = 0x2040,
+       [RT5631_DEPOP_FUN_CTRL_2] = 0x8000,
+       [RT5631_SOFT_VOL_CTRL] = 0x07e0,
+       [RT5631_ALC_CTRL_1] = 0x0206,
+       [RT5631_ALC_CTRL_3] = 0x2000,
+       [RT5631_PSEUDO_SPATL_CTRL] = 0x0553,
+};
+
+/**
+ * rt5631_write_index - write index register of 2nd layer
+ */
+static void rt5631_write_index(struct snd_soc_codec *codec,
+               unsigned int reg, unsigned int value)
+{
+       snd_soc_write(codec, RT5631_INDEX_ADD, reg);
+       snd_soc_write(codec, RT5631_INDEX_DATA, value);
+}
+
+/**
+ * rt5631_read_index - read index register of 2nd layer
+ */
+static unsigned int rt5631_read_index(struct snd_soc_codec *codec,
+                               unsigned int reg)
+{
+       unsigned int value;
+
+       snd_soc_write(codec, RT5631_INDEX_ADD, reg);
+       value = snd_soc_read(codec, RT5631_INDEX_DATA);
+
+       return value;
+}
+
+static int rt5631_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, RT5631_RESET, 0);
+}
+
+static int rt5631_volatile_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
+{
+       switch (reg) {
+       case RT5631_RESET:
+       case RT5631_INT_ST_IRQ_CTRL_2:
+       case RT5631_INDEX_ADD:
+       case RT5631_INDEX_DATA:
+       case RT5631_EQ_CTRL:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int rt5631_readable_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
+{
+       switch (reg) {
+       case RT5631_RESET:
+       case RT5631_SPK_OUT_VOL:
+       case RT5631_HP_OUT_VOL:
+       case RT5631_MONO_AXO_1_2_VOL:
+       case RT5631_AUX_IN_VOL:
+       case RT5631_STEREO_DAC_VOL_1:
+       case RT5631_MIC_CTRL_1:
+       case RT5631_STEREO_DAC_VOL_2:
+       case RT5631_ADC_CTRL_1:
+       case RT5631_ADC_REC_MIXER:
+       case RT5631_ADC_CTRL_2:
+       case RT5631_VDAC_DIG_VOL:
+       case RT5631_OUTMIXER_L_CTRL:
+       case RT5631_OUTMIXER_R_CTRL:
+       case RT5631_AXO1MIXER_CTRL:
+       case RT5631_AXO2MIXER_CTRL:
+       case RT5631_MIC_CTRL_2:
+       case RT5631_DIG_MIC_CTRL:
+       case RT5631_MONO_INPUT_VOL:
+       case RT5631_SPK_MIXER_CTRL:
+       case RT5631_SPK_MONO_OUT_CTRL:
+       case RT5631_SPK_MONO_HP_OUT_CTRL:
+       case RT5631_SDP_CTRL:
+       case RT5631_MONO_SDP_CTRL:
+       case RT5631_STEREO_AD_DA_CLK_CTRL:
+       case RT5631_PWR_MANAG_ADD1:
+       case RT5631_PWR_MANAG_ADD2:
+       case RT5631_PWR_MANAG_ADD3:
+       case RT5631_PWR_MANAG_ADD4:
+       case RT5631_GEN_PUR_CTRL_REG:
+       case RT5631_GLOBAL_CLK_CTRL:
+       case RT5631_PLL_CTRL:
+       case RT5631_INT_ST_IRQ_CTRL_1:
+       case RT5631_INT_ST_IRQ_CTRL_2:
+       case RT5631_GPIO_CTRL:
+       case RT5631_MISC_CTRL:
+       case RT5631_DEPOP_FUN_CTRL_1:
+       case RT5631_DEPOP_FUN_CTRL_2:
+       case RT5631_JACK_DET_CTRL:
+       case RT5631_SOFT_VOL_CTRL:
+       case RT5631_ALC_CTRL_1:
+       case RT5631_ALC_CTRL_2:
+       case RT5631_ALC_CTRL_3:
+       case RT5631_PSEUDO_SPATL_CTRL:
+       case RT5631_INDEX_ADD:
+       case RT5631_INDEX_DATA:
+       case RT5631_EQ_CTRL:
+       case RT5631_VENDOR_ID:
+       case RT5631_VENDOR_ID1:
+       case RT5631_VENDOR_ID2:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */
+static unsigned int mic_bst_tlv[] = {
+       TLV_DB_RANGE_HEAD(6),
+       0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+       1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+       2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+       3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+       6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+       7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+       8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = rt5631->dmic_used_flag;
+
+       return 0;
+}
+
+static int rt5631_dmic_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       rt5631->dmic_used_flag = ucontrol->value.integer.value[0];
+       return 0;
+}
+
+/* MIC Input Type */
+static const char *rt5631_input_mode[] = {
+       "Single ended", "Differential"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1,
+       RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1,
+       RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+/* MONO Input Type */
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL,
+       RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+/* SPK Ratio Gain Control */
+static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x",
+                       "1.56x", "1.68x", "1.99x", "2.34x"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
+       RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio);
+
+static const struct snd_kcontrol_new rt5631_snd_controls[] = {
+       /* MIC */
+       SOC_ENUM("MIC1 Mode Control",  rt5631_mic1_mode_enum),
+       SOC_SINGLE_TLV("MIC1 Boost", RT5631_MIC_CTRL_2,
+               RT5631_MIC1_BOOST_SHIFT, 8, 0, mic_bst_tlv),
+       SOC_ENUM("MIC2 Mode Control", rt5631_mic2_mode_enum),
+       SOC_SINGLE_TLV("MIC2 Boost", RT5631_MIC_CTRL_2,
+               RT5631_MIC2_BOOST_SHIFT, 8, 0, mic_bst_tlv),
+       /* MONO IN */
+       SOC_ENUM("MONOIN Mode Control", rt5631_monoin_mode_enum),
+       SOC_DOUBLE_TLV("MONOIN_RX Capture Volume", RT5631_MONO_INPUT_VOL,
+                       RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+                       RT5631_VOL_MASK, 1, in_vol_tlv),
+       /* AXI */
+       SOC_DOUBLE_TLV("AXI Capture Volume", RT5631_AUX_IN_VOL,
+                       RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+                       RT5631_VOL_MASK, 1, in_vol_tlv),
+       /* DAC */
+       SOC_DOUBLE_TLV("PCM Playback Volume", RT5631_STEREO_DAC_VOL_2,
+                       RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+                       RT5631_DAC_VOL_MASK, 1, dac_vol_tlv),
+       SOC_DOUBLE("PCM Playback Switch", RT5631_STEREO_DAC_VOL_1,
+                       RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+       /* AXO */
+       SOC_SINGLE("AXO1 Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+                               RT5631_L_MUTE_SHIFT, 1, 1),
+       SOC_SINGLE("AXO2 Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+                               RT5631_R_VOL_SHIFT, 1, 1),
+       /* OUTVOL */
+       SOC_DOUBLE("OUTVOL Channel Switch", RT5631_SPK_OUT_VOL,
+               RT5631_L_EN_SHIFT, RT5631_R_EN_SHIFT, 1, 0),
+
+       /* SPK */
+       SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL,
+               RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+       SOC_DOUBLE_TLV("Speaker Playback Volume", RT5631_SPK_OUT_VOL,
+               RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, 39, 1, out_vol_tlv),
+       /* MONO OUT */
+       SOC_SINGLE("MONO Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+                               RT5631_MUTE_MONO_SHIFT, 1, 1),
+       /* HP */
+       SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL,
+               RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+       SOC_DOUBLE_TLV("HP Playback Volume", RT5631_HP_OUT_VOL,
+               RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+               RT5631_VOL_MASK, 1, out_vol_tlv),
+       /* DMIC */
+       SOC_SINGLE_EXT("DMIC Switch", 0, 0, 1, 0,
+               rt5631_dmic_get, rt5631_dmic_put),
+       SOC_DOUBLE("DMIC Capture Switch", RT5631_DIG_MIC_CTRL,
+               RT5631_DMIC_L_CH_MUTE_SHIFT,
+               RT5631_DMIC_R_CH_MUTE_SHIFT, 1, 1),
+
+       /* SPK Ratio Gain Control */
+       SOC_ENUM("SPK Ratio Control", rt5631_spk_ratio_enum),
+};
+
+static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_GLOBAL_CLK_CTRL);
+       return reg & RT5631_SYSCLK_SOUR_SEL_PLL;
+}
+
+static int check_dmic_used(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(source->codec);
+       return rt5631->dmic_used_flag;
+}
+
+static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_OUTMIXER_L_CTRL);
+       return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L);
+}
+
+static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_OUTMIXER_R_CTRL);
+       return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R);
+}
+
+static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
+       return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L);
+}
+
+static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
+       return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R);
+}
+
+static int check_adcl_select(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
+       return !(reg & RT5631_M_MIC1_TO_RECMIXER_L);
+}
+
+static int check_adcr_select(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
+       return !(reg & RT5631_M_MIC2_TO_RECMIXER_R);
+}
+
+/**
+ * onebit_depop_power_stage - auto depop in power stage.
+ * @enable: power on/off
+ *
+ * When power on/off headphone, the depop sequence is done by hardware.
+ */
+static void onebit_depop_power_stage(struct snd_soc_codec *codec, int enable)
+{
+       unsigned int soft_vol, hp_zc;
+
+       /* enable one-bit depop function */
+       snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+                               RT5631_EN_ONE_BIT_DEPOP, 0);
+
+       /* keep soft volume and zero crossing setting */
+       soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+       hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+       if (enable) {
+               /* config one-bit depop parameter */
+               rt5631_write_index(codec, RT5631_TEST_MODE_CTRL, 0x84c0);
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x309f);
+               rt5631_write_index(codec, RT5631_CP_INTL_REG2, 0x6530);
+               /* power on capless block */
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2,
+                               RT5631_EN_CAP_FREE_DEPOP);
+       } else {
+               /* power off capless block */
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2, 0);
+               msleep(100);
+       }
+
+       /* recover soft volume and zero crossing setting */
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * onebit_depop_mute_stage - auto depop in mute stage.
+ * @enable: mute/unmute
+ *
+ * When mute/unmute headphone, the depop sequence is done by hardware.
+ */
+static void onebit_depop_mute_stage(struct snd_soc_codec *codec, int enable)
+{
+       unsigned int soft_vol, hp_zc;
+
+       /* enable one-bit depop function */
+       snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+                               RT5631_EN_ONE_BIT_DEPOP, 0);
+
+       /* keep soft volume and zero crossing setting */
+       soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+       hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+       if (enable) {
+               schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+               /* config one-bit depop parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x307f);
+               snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+                               RT5631_L_MUTE | RT5631_R_MUTE, 0);
+               msleep(300);
+       } else {
+               snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+                       RT5631_L_MUTE | RT5631_R_MUTE,
+                       RT5631_L_MUTE | RT5631_R_MUTE);
+               msleep(100);
+       }
+
+       /* recover soft volume and zero crossing setting */
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * onebit_depop_power_stage - step by step depop sequence in power stage.
+ * @enable: power on/off
+ *
+ * When power on/off headphone, the depop sequence is done in step by step.
+ */
+static void depop_seq_power_stage(struct snd_soc_codec *codec, int enable)
+{
+       unsigned int soft_vol, hp_zc;
+
+       /* depop control by register */
+       snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+               RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP);
+
+       /* keep soft volume and zero crossing setting */
+       soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+       hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+       if (enable) {
+               /* config depop sequence parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303e);
+
+               /* power on headphone and charge pump */
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+                       RT5631_PWR_HP_R_AMP,
+                       RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+                       RT5631_PWR_HP_R_AMP);
+
+               /* power on soft generator and depop mode2 */
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP);
+               msleep(100);
+
+               /* stop depop mode */
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_HP_DEPOP_DIS, RT5631_PWR_HP_DEPOP_DIS);
+       } else {
+               /* config depop sequence parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303F);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+                       RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP);
+               msleep(75);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_PD_HPAMP_L_ST_UP |
+                       RT5631_PD_HPAMP_R_ST_UP);
+
+               /* start depop mode */
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                               RT5631_PWR_HP_DEPOP_DIS, 0);
+
+               /* config depop sequence parameter */
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP |
+                       RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP);
+               msleep(80);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN);
+
+               /* power down headphone and charge pump */
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+                       RT5631_PWR_HP_R_AMP, 0);
+       }
+
+       /* recover soft volume and zero crossing setting */
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * depop_seq_mute_stage - step by step depop sequence in mute stage.
+ * @enable: mute/unmute
+ *
+ * When mute/unmute headphone, the depop sequence is done in step by step.
+ */
+static void depop_seq_mute_stage(struct snd_soc_codec *codec, int enable)
+{
+       unsigned int soft_vol, hp_zc;
+
+       /* depop control by register */
+       snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+               RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP);
+
+       /* keep soft volume and zero crossing setting */
+       soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+       hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+       if (enable) {
+               schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+
+               /* config depop sequence parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+                       RT5631_EN_HP_R_M_UN_MUTE_DEPOP |
+                       RT5631_EN_HP_L_M_UN_MUTE_DEPOP);
+
+               snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+                               RT5631_L_MUTE | RT5631_R_MUTE, 0);
+               msleep(160);
+       } else {
+               /* config depop sequence parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+                       RT5631_EN_HP_R_M_UN_MUTE_DEPOP |
+                       RT5631_EN_HP_L_M_UN_MUTE_DEPOP);
+
+               snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+                       RT5631_L_MUTE | RT5631_R_MUTE,
+                       RT5631_L_MUTE | RT5631_R_MUTE);
+               msleep(150);
+       }
+
+       /* recover soft volume and zero crossing setting */
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+static int hp_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMD:
+               if (rt5631->codec_version) {
+                       onebit_depop_mute_stage(codec, 0);
+                       onebit_depop_power_stage(codec, 0);
+               } else {
+                       depop_seq_mute_stage(codec, 0);
+                       depop_seq_power_stage(codec, 0);
+               }
+               break;
+
+       case SND_SOC_DAPM_POST_PMU:
+               if (rt5631->codec_version) {
+                       onebit_depop_power_stage(codec, 1);
+                       onebit_depop_mute_stage(codec, 1);
+               } else {
+                       depop_seq_power_stage(codec, 1);
+                       depop_seq_mute_stage(codec, 1);
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int set_dmic_params(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       switch (rt5631->rx_rate) {
+       case 44100:
+       case 48000:
+               snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+                       RT5631_DMIC_CLK_CTRL_MASK,
+                       RT5631_DMIC_CLK_CTRL_TO_32FS);
+               break;
+
+       case 32000:
+       case 22050:
+               snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+                       RT5631_DMIC_CLK_CTRL_MASK,
+                       RT5631_DMIC_CLK_CTRL_TO_64FS);
+               break;
+
+       case 16000:
+       case 11025:
+       case 8000:
+               snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+                       RT5631_DMIC_CLK_CTRL_MASK,
+                       RT5631_DMIC_CLK_CTRL_TO_128FS);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct snd_kcontrol_new rt5631_recmixl_mixer_controls[] = {
+       SOC_DAPM_SINGLE("OUTMIXL Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_OUTMIXL_RECMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC1_BST1 Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_MIC1_RECMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXILVOL Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_AXIL_RECMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_MONO_IN_RECMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_recmixr_mixer_controls[] = {
+       SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_MONO_IN_RECMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXIRVOL Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_AXIR_RECMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_MIC2_RECMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTMIXR Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_OUTMIXR_RECMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spkmixl_mixer_controls[] = {
+       SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_RECMIXL_SPKMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC1_P Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_MIC1P_SPKMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_DACL_SPKMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTMIXL Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_OUTMIXL_SPKMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spkmixr_mixer_controls[] = {
+       SOC_DAPM_SINGLE("OUTMIXR Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_OUTMIXR_SPKMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_DACR_SPKMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_P Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_MIC2P_SPKMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_RECMIXR_SPKMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_outmixl_mixer_controls[] = {
+       SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_RECMIXL_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_RECMIXR_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_DACL_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_MIC1_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_MIC2_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MONOIN_RXP Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_MONO_INP_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_AXIL_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_AXIR_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_VDAC_OUTMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_outmixr_mixer_controls[] = {
+       SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_VDAC_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_AXIR_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_AXIL_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MONOIN_RXN Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_MONO_INN_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_MIC2_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_MIC1_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_DACR_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_RECMIXR_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_RECMIXL_OUTMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_AXO1MIX_mixer_controls[] = {
+       SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO1MIXER_CTRL,
+                               RT5631_M_MIC1_AXO1MIX_BIT , 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO1MIXER_CTRL,
+                               RT5631_M_MIC2_AXO1MIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO1MIXER_CTRL,
+                               RT5631_M_OUTMIXL_AXO1MIX_BIT , 1 , 1),
+       SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO1MIXER_CTRL,
+                               RT5631_M_OUTMIXR_AXO1MIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_AXO2MIX_mixer_controls[] = {
+       SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO2MIXER_CTRL,
+                               RT5631_M_MIC1_AXO2MIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO2MIXER_CTRL,
+                               RT5631_M_MIC2_AXO2MIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO2MIXER_CTRL,
+                               RT5631_M_OUTMIXL_AXO2MIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO2MIXER_CTRL,
+                               RT5631_M_OUTMIXR_AXO2MIX_BIT, 1 , 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spolmix_mixer_controls[] = {
+       SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_SPKVOLL_SPOLMIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_SPKVOLR_SPOLMIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spormix_mixer_controls[] = {
+       SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_SPKVOLL_SPORMIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_SPKVOLR_SPORMIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = {
+       SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_OUTVOLL_MONOMIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_OUTVOLR_MONOMIX_BIT, 1, 1),
+};
+
+/* Left SPK Volume Input */
+static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL,
+       RT5631_L_EN_SHIFT, rt5631_spkvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_spkvoll_mux_control =
+       SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum);
+
+/* Left HP Volume Input */
+static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_hpvoll_enum, RT5631_HP_OUT_VOL,
+       RT5631_L_EN_SHIFT, rt5631_hpvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_hpvoll_mux_control =
+       SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum);
+
+/* Left Out Volume Input */
+static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL,
+       RT5631_L_EN_SHIFT, rt5631_outvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_outvoll_mux_control =
+       SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum);
+
+/* Right Out Volume Input */
+static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL,
+       RT5631_R_EN_SHIFT, rt5631_outvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_outvolr_mux_control =
+       SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum);
+
+/* Right HP Volume Input */
+static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_hpvolr_enum, RT5631_HP_OUT_VOL,
+       RT5631_R_EN_SHIFT, rt5631_hpvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_hpvolr_mux_control =
+       SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum);
+
+/* Right SPK Volume Input */
+static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL,
+       RT5631_R_EN_SHIFT, rt5631_spkvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_spkvolr_mux_control =
+       SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum);
+
+/* SPO Left Channel Input */
+static const char *rt5631_spol_src_sel[] = {
+       "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel);
+
+static const struct snd_kcontrol_new rt5631_spol_mux_control =
+       SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum);
+
+/* SPO Right Channel Input */
+static const char *rt5631_spor_src_sel[] = {
+       "SPORMIX", "MONOIN_RX", "VDAC", "DACR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel);
+
+static const struct snd_kcontrol_new rt5631_spor_mux_control =
+       SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum);
+
+/* MONO Input */
+static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel);
+
+static const struct snd_kcontrol_new rt5631_mono_mux_control =
+       SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum);
+
+/* Left HPO Input */
+static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel);
+
+static const struct snd_kcontrol_new rt5631_hpl_mux_control =
+       SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum);
+
+/* Right HPO Input */
+static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel);
+
+static const struct snd_kcontrol_new rt5631_hpr_mux_control =
+       SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum);
+
+static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = {
+       /* Vmid */
+       SND_SOC_DAPM_VMID("Vmid"),
+       /* PLL1 */
+       SND_SOC_DAPM_SUPPLY("PLL1", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_PLL1_BIT, 0, NULL, 0),
+
+       /* Input Side */
+       /* Input Lines */
+       SND_SOC_DAPM_INPUT("MIC1"),
+       SND_SOC_DAPM_INPUT("MIC2"),
+       SND_SOC_DAPM_INPUT("AXIL"),
+       SND_SOC_DAPM_INPUT("AXIR"),
+       SND_SOC_DAPM_INPUT("MONOIN_RXN"),
+       SND_SOC_DAPM_INPUT("MONOIN_RXP"),
+       SND_SOC_DAPM_INPUT("DMIC"),
+
+       /* MICBIAS */
+       SND_SOC_DAPM_MICBIAS("MIC Bias1", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MICBIAS1_VOL_BIT, 0),
+       SND_SOC_DAPM_MICBIAS("MIC Bias2", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MICBIAS2_VOL_BIT, 0),
+
+       /* Boost */
+       SND_SOC_DAPM_PGA("MIC1 Boost", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MIC1_BOOT_GAIN_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MIC2 Boost", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MIC2_BOOT_GAIN_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MONOIN_RXP Boost", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_MONO_IN_P_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MONOIN_RXN Boost", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_MONO_IN_N_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("AXIL Boost", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_AXIL_IN_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("AXIR Boost", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_AXIR_IN_VOL_BIT, 0, NULL, 0),
+
+       /* MONO In */
+       SND_SOC_DAPM_MIXER("MONO_IN", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* REC Mixer */
+       SND_SOC_DAPM_MIXER("RECMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+               RT5631_PWR_RECMIXER_L_BIT, 0,
+               &rt5631_recmixl_mixer_controls[0],
+               ARRAY_SIZE(rt5631_recmixl_mixer_controls)),
+       SND_SOC_DAPM_MIXER("RECMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+               RT5631_PWR_RECMIXER_R_BIT, 0,
+               &rt5631_recmixr_mixer_controls[0],
+               ARRAY_SIZE(rt5631_recmixr_mixer_controls)),
+       /* Because of record duplication for L/R channel,
+        * L/R ADCs need power up at the same time */
+       SND_SOC_DAPM_MIXER("ADC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* DMIC */
+       SND_SOC_DAPM_SUPPLY("DMIC Supply", RT5631_DIG_MIC_CTRL,
+               RT5631_DMIC_ENA_SHIFT, 0,
+               set_dmic_params, SND_SOC_DAPM_PRE_PMU),
+       /* ADC Data Srouce */
+       SND_SOC_DAPM_SUPPLY("Left ADC Select", RT5631_INT_ST_IRQ_CTRL_2,
+                       RT5631_ADC_DATA_SEL_MIC1_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Right ADC Select", RT5631_INT_ST_IRQ_CTRL_2,
+                       RT5631_ADC_DATA_SEL_MIC2_SHIFT, 0, NULL, 0),
+
+       /* ADCs */
+       SND_SOC_DAPM_ADC("Left ADC", "HIFI Capture",
+               RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_L_CLK_BIT, 0),
+       SND_SOC_DAPM_ADC("Right ADC", "HIFI Capture",
+               RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_R_CLK_BIT, 0),
+
+       /* DAC and ADC supply power */
+       SND_SOC_DAPM_SUPPLY("I2S", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_MAIN_I2S_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("DAC REF", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_DAC_REF_BIT, 0, NULL, 0),
+
+       /* Output Side */
+       /* DACs */
+       SND_SOC_DAPM_DAC("Left DAC", "HIFI Playback",
+               RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_L_CLK_BIT, 0),
+       SND_SOC_DAPM_DAC("Right DAC", "HIFI Playback",
+               RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_R_CLK_BIT, 0),
+       SND_SOC_DAPM_DAC("Voice DAC", "Voice DAC Mono Playback",
+                               SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_PGA("Voice DAC Boost", SND_SOC_NOPM, 0, 0, NULL, 0),
+       /* DAC supply power */
+       SND_SOC_DAPM_SUPPLY("Left DAC To Mixer", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_DAC_L_TO_MIXER_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Right DAC To Mixer", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_DAC_R_TO_MIXER_BIT, 0, NULL, 0),
+
+       /* Left SPK Mixer */
+       SND_SOC_DAPM_MIXER("SPKMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_SPKMIXER_L_BIT, 0,
+                       &rt5631_spkmixl_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_spkmixl_mixer_controls)),
+       /* Left Out Mixer */
+       SND_SOC_DAPM_MIXER("OUTMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_OUTMIXER_L_BIT, 0,
+                       &rt5631_outmixl_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_outmixl_mixer_controls)),
+       /* Right Out Mixer */
+       SND_SOC_DAPM_MIXER("OUTMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_OUTMIXER_R_BIT, 0,
+                       &rt5631_outmixr_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_outmixr_mixer_controls)),
+       /* Right SPK Mixer */
+       SND_SOC_DAPM_MIXER("SPKMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_SPKMIXER_R_BIT, 0,
+                       &rt5631_spkmixr_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_spkmixr_mixer_controls)),
+
+       /* Volume Mux */
+       SND_SOC_DAPM_MUX("Left SPKVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_SPK_L_VOL_BIT, 0,
+                       &rt5631_spkvoll_mux_control),
+       SND_SOC_DAPM_MUX("Left HPVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_HP_L_OUT_VOL_BIT, 0,
+                       &rt5631_hpvoll_mux_control),
+       SND_SOC_DAPM_MUX("Left OUTVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_LOUT_VOL_BIT, 0,
+                       &rt5631_outvoll_mux_control),
+       SND_SOC_DAPM_MUX("Right OUTVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_ROUT_VOL_BIT, 0,
+                       &rt5631_outvolr_mux_control),
+       SND_SOC_DAPM_MUX("Right HPVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_HP_R_OUT_VOL_BIT, 0,
+                       &rt5631_hpvolr_mux_control),
+       SND_SOC_DAPM_MUX("Right SPKVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_SPK_R_VOL_BIT, 0,
+                       &rt5631_spkvolr_mux_control),
+
+       /* DAC To HP */
+       SND_SOC_DAPM_PGA_S("Left DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("Right DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* HP Depop */
+       SND_SOC_DAPM_PGA_S("HP Depop", 1, SND_SOC_NOPM, 0, 0,
+               hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+       /* AXO1 Mixer */
+       SND_SOC_DAPM_MIXER("AXO1MIX Mixer", RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_AXO1MIXER_BIT, 0,
+                       &rt5631_AXO1MIX_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_AXO1MIX_mixer_controls)),
+       /* SPOL Mixer */
+       SND_SOC_DAPM_MIXER("SPOLMIX Mixer", SND_SOC_NOPM, 0, 0,
+                       &rt5631_spolmix_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_spolmix_mixer_controls)),
+       /* MONO Mixer */
+       SND_SOC_DAPM_MIXER("MONOMIX Mixer", RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_MONOMIXER_BIT, 0,
+                       &rt5631_monomix_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_monomix_mixer_controls)),
+       /* SPOR Mixer */
+       SND_SOC_DAPM_MIXER("SPORMIX Mixer", SND_SOC_NOPM, 0, 0,
+                       &rt5631_spormix_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_spormix_mixer_controls)),
+       /* AXO2 Mixer */
+       SND_SOC_DAPM_MIXER("AXO2MIX Mixer", RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_AXO2MIXER_BIT, 0,
+                       &rt5631_AXO2MIX_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_AXO2MIX_mixer_controls)),
+
+       /* Mux */
+       SND_SOC_DAPM_MUX("SPOL Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_spol_mux_control),
+       SND_SOC_DAPM_MUX("SPOR Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_spor_mux_control),
+       SND_SOC_DAPM_MUX("MONO Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_mono_mux_control),
+       SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_hpl_mux_control),
+       SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_hpr_mux_control),
+
+       /* AMP supply */
+       SND_SOC_DAPM_SUPPLY("MONO Depop", RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_MONO_DEPOP_DIS_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Class D", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_CLASS_D_BIT, 0, NULL, 0),
+
+       /* Output Lines */
+       SND_SOC_DAPM_OUTPUT("AUXO1"),
+       SND_SOC_DAPM_OUTPUT("AUXO2"),
+       SND_SOC_DAPM_OUTPUT("SPOL"),
+       SND_SOC_DAPM_OUTPUT("SPOR"),
+       SND_SOC_DAPM_OUTPUT("HPOL"),
+       SND_SOC_DAPM_OUTPUT("HPOR"),
+       SND_SOC_DAPM_OUTPUT("MONO"),
+};
+
+static const struct snd_soc_dapm_route rt5631_dapm_routes[] = {
+       {"MIC1 Boost", NULL, "MIC1"},
+       {"MIC2 Boost", NULL, "MIC2"},
+       {"MONOIN_RXP Boost", NULL, "MONOIN_RXP"},
+       {"MONOIN_RXN Boost", NULL, "MONOIN_RXN"},
+       {"AXIL Boost", NULL, "AXIL"},
+       {"AXIR Boost", NULL, "AXIR"},
+
+       {"MONO_IN", NULL, "MONOIN_RXP Boost"},
+       {"MONO_IN", NULL, "MONOIN_RXN Boost"},
+
+       {"RECMIXL Mixer", "OUTMIXL Capture Switch", "OUTMIXL Mixer"},
+       {"RECMIXL Mixer", "MIC1_BST1 Capture Switch", "MIC1 Boost"},
+       {"RECMIXL Mixer", "AXILVOL Capture Switch", "AXIL Boost"},
+       {"RECMIXL Mixer", "MONOIN_RX Capture Switch", "MONO_IN"},
+
+       {"RECMIXR Mixer", "OUTMIXR Capture Switch", "OUTMIXR Mixer"},
+       {"RECMIXR Mixer", "MIC2_BST2 Capture Switch", "MIC2 Boost"},
+       {"RECMIXR Mixer", "AXIRVOL Capture Switch", "AXIR Boost"},
+       {"RECMIXR Mixer", "MONOIN_RX Capture Switch", "MONO_IN"},
+
+       {"ADC Mixer", NULL, "RECMIXL Mixer"},
+       {"ADC Mixer", NULL, "RECMIXR Mixer"},
+
+       {"Left ADC", NULL, "ADC Mixer"},
+       {"Left ADC", NULL, "Left ADC Select", check_adcl_select},
+       {"Left ADC", NULL, "PLL1", check_sysclk1_source},
+       {"Left ADC", NULL, "I2S"},
+       {"Left ADC", NULL, "DAC REF"},
+
+       {"Right ADC", NULL, "ADC Mixer"},
+       {"Right ADC", NULL, "Right ADC Select", check_adcr_select},
+       {"Right ADC", NULL, "PLL1", check_sysclk1_source},
+       {"Right ADC", NULL, "I2S"},
+       {"Right ADC", NULL, "DAC REF"},
+
+       {"DMIC", NULL, "DMIC Supply", check_dmic_used},
+       {"Left ADC", NULL, "DMIC"},
+       {"Right ADC", NULL, "DMIC"},
+
+       {"Left DAC", NULL, "PLL1", check_sysclk1_source},
+       {"Left DAC", NULL, "I2S"},
+       {"Left DAC", NULL, "DAC REF"},
+       {"Right DAC", NULL, "PLL1", check_sysclk1_source},
+       {"Right DAC", NULL, "I2S"},
+       {"Right DAC", NULL, "DAC REF"},
+
+       {"Voice DAC Boost", NULL, "Voice DAC"},
+
+       {"SPKMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_spkmixl},
+       {"SPKMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+       {"SPKMIXL Mixer", "MIC1_P Playback Switch", "MIC1"},
+       {"SPKMIXL Mixer", "DACL Playback Switch", "Left DAC"},
+       {"SPKMIXL Mixer", "OUTMIXL Playback Switch", "OUTMIXL Mixer"},
+
+       {"SPKMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_spkmixr},
+       {"SPKMIXR Mixer", "OUTMIXR Playback Switch", "OUTMIXR Mixer"},
+       {"SPKMIXR Mixer", "DACR Playback Switch", "Right DAC"},
+       {"SPKMIXR Mixer", "MIC2_P Playback Switch", "MIC2"},
+       {"SPKMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+
+       {"OUTMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_outmixl},
+       {"OUTMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+       {"OUTMIXL Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+       {"OUTMIXL Mixer", "DACL Playback Switch", "Left DAC"},
+       {"OUTMIXL Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+       {"OUTMIXL Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+       {"OUTMIXL Mixer", "MONOIN_RXP Playback Switch", "MONOIN_RXP Boost"},
+       {"OUTMIXL Mixer", "AXILVOL Playback Switch", "AXIL Boost"},
+       {"OUTMIXL Mixer", "AXIRVOL Playback Switch", "AXIR Boost"},
+       {"OUTMIXL Mixer", "VDAC Playback Switch", "Voice DAC Boost"},
+
+       {"OUTMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_outmixr},
+       {"OUTMIXR Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+       {"OUTMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+       {"OUTMIXR Mixer", "DACR Playback Switch", "Right DAC"},
+       {"OUTMIXR Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+       {"OUTMIXR Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+       {"OUTMIXR Mixer", "MONOIN_RXN Playback Switch", "MONOIN_RXN Boost"},
+       {"OUTMIXR Mixer", "AXILVOL Playback Switch", "AXIL Boost"},
+       {"OUTMIXR Mixer", "AXIRVOL Playback Switch", "AXIR Boost"},
+       {"OUTMIXR Mixer", "VDAC Playback Switch", "Voice DAC Boost"},
+
+       {"Left SPKVOL Mux",  "SPKMIXL", "SPKMIXL Mixer"},
+       {"Left SPKVOL Mux",  "Vmid", "Vmid"},
+       {"Left HPVOL Mux",  "OUTMIXL", "OUTMIXL Mixer"},
+       {"Left HPVOL Mux",  "Vmid", "Vmid"},
+       {"Left OUTVOL Mux",  "OUTMIXL", "OUTMIXL Mixer"},
+       {"Left OUTVOL Mux",  "Vmid", "Vmid"},
+       {"Right OUTVOL Mux",  "OUTMIXR", "OUTMIXR Mixer"},
+       {"Right OUTVOL Mux",  "Vmid", "Vmid"},
+       {"Right HPVOL Mux",  "OUTMIXR", "OUTMIXR Mixer"},
+       {"Right HPVOL Mux",  "Vmid", "Vmid"},
+       {"Right SPKVOL Mux",  "SPKMIXR", "SPKMIXR Mixer"},
+       {"Right SPKVOL Mux",  "Vmid", "Vmid"},
+
+       {"AXO1MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+       {"AXO1MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+       {"AXO1MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+       {"AXO1MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+
+       {"AXO2MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+       {"AXO2MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+       {"AXO2MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+       {"AXO2MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+
+       {"SPOLMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"},
+       {"SPOLMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"},
+
+       {"SPORMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"},
+       {"SPORMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"},
+
+       {"MONOMIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+       {"MONOMIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+
+       {"SPOL Mux", "SPOLMIX", "SPOLMIX Mixer"},
+       {"SPOL Mux", "MONOIN_RX", "MONO_IN"},
+       {"SPOL Mux", "VDAC", "Voice DAC Boost"},
+       {"SPOL Mux", "DACL", "Left DAC"},
+
+       {"SPOR Mux", "SPORMIX", "SPORMIX Mixer"},
+       {"SPOR Mux", "MONOIN_RX", "MONO_IN"},
+       {"SPOR Mux", "VDAC", "Voice DAC Boost"},
+       {"SPOR Mux", "DACR", "Right DAC"},
+
+       {"MONO Mux", "MONOMIX", "MONOMIX Mixer"},
+       {"MONO Mux", "MONOIN_RX", "MONO_IN"},
+       {"MONO Mux", "VDAC", "Voice DAC Boost"},
+
+       {"Right DAC_HP", NULL, "Right DAC"},
+       {"Left DAC_HP", NULL, "Left DAC"},
+
+       {"HPL Mux", "Left HPVOL", "Left HPVOL Mux"},
+       {"HPL Mux", "Left DAC", "Left DAC_HP"},
+       {"HPR Mux", "Right HPVOL", "Right HPVOL Mux"},
+       {"HPR Mux", "Right DAC", "Right DAC_HP"},
+
+       {"HP Depop", NULL, "HPL Mux"},
+       {"HP Depop", NULL, "HPR Mux"},
+
+       {"AUXO1", NULL, "AXO1MIX Mixer"},
+       {"AUXO2", NULL, "AXO2MIX Mixer"},
+
+       {"SPOL", NULL, "Class D"},
+       {"SPOL", NULL, "SPOL Mux"},
+       {"SPOR", NULL, "Class D"},
+       {"SPOR", NULL, "SPOR Mux"},
+
+       {"HPOL", NULL, "HP Depop"},
+       {"HPOR", NULL, "HP Depop"},
+
+       {"MONO", NULL, "MONO Depop"},
+       {"MONO", NULL, "MONO Mux"},
+};
+
+struct coeff_clk_div {
+       u32 mclk;
+       u32 bclk;
+       u32 rate;
+       u16 reg_val;
+};
+
+/* PLL divisors */
+struct pll_div {
+       u32 pll_in;
+       u32 pll_out;
+       u16 reg_val;
+};
+
+static const struct pll_div codec_master_pll_div[] = {
+       {2048000,  8192000,  0x0ea0},
+       {3686400,  8192000,  0x4e27},
+       {12000000,  8192000,  0x456b},
+       {13000000,  8192000,  0x495f},
+       {13100000,  8192000,  0x0320},
+       {2048000,  11289600,  0xf637},
+       {3686400,  11289600,  0x2f22},
+       {12000000,  11289600,  0x3e2f},
+       {13000000,  11289600,  0x4d5b},
+       {13100000,  11289600,  0x363b},
+       {2048000,  16384000,  0x1ea0},
+       {3686400,  16384000,  0x9e27},
+       {12000000,  16384000,  0x452b},
+       {13000000,  16384000,  0x542f},
+       {13100000,  16384000,  0x03a0},
+       {2048000,  16934400,  0xe625},
+       {3686400,  16934400,  0x9126},
+       {12000000,  16934400,  0x4d2c},
+       {13000000,  16934400,  0x742f},
+       {13100000,  16934400,  0x3c27},
+       {2048000,  22579200,  0x2aa0},
+       {3686400,  22579200,  0x2f20},
+       {12000000,  22579200,  0x7e2f},
+       {13000000,  22579200,  0x742f},
+       {13100000,  22579200,  0x3c27},
+       {2048000,  24576000,  0x2ea0},
+       {3686400,  24576000,  0xee27},
+       {12000000,  24576000,  0x2915},
+       {13000000,  24576000,  0x772e},
+       {13100000,  24576000,  0x0d20},
+       {26000000,  24576000,  0x2027},
+       {26000000,  22579200,  0x392f},
+       {24576000,  22579200,  0x0921},
+       {24576000,  24576000,  0x02a0},
+};
+
+static const struct pll_div codec_slave_pll_div[] = {
+       {256000,  2048000,  0x46f0},
+       {256000,  4096000,  0x3ea0},
+       {352800,  5644800,  0x3ea0},
+       {512000,  8192000,  0x3ea0},
+       {1024000,  8192000,  0x46f0},
+       {705600,  11289600,  0x3ea0},
+       {1024000,  16384000,  0x3ea0},
+       {1411200,  22579200,  0x3ea0},
+       {1536000,  24576000,  0x3ea0},
+       {2048000,  16384000,  0x1ea0},
+       {2822400,  22579200,  0x1ea0},
+       {2822400,  45158400,  0x5ec0},
+       {5644800,  45158400,  0x46f0},
+       {3072000,  24576000,  0x1ea0},
+       {3072000,  49152000,  0x5ec0},
+       {6144000,  49152000,  0x46f0},
+       {705600,  11289600,  0x3ea0},
+       {705600,  8467200,  0x3ab0},
+       {24576000,  24576000,  0x02a0},
+       {1411200,  11289600,  0x1690},
+       {2822400,  11289600,  0x0a90},
+       {1536000,  12288000,  0x1690},
+       {3072000,  12288000,  0x0a90},
+};
+
+static struct coeff_clk_div coeff_div[] = {
+       /* sysclk is 256fs */
+       {2048000,  8000 * 32,  8000, 0x1000},
+       {2048000,  8000 * 64,  8000, 0x0000},
+       {2822400,  11025 * 32,  11025,  0x1000},
+       {2822400,  11025 * 64,  11025,  0x0000},
+       {4096000,  16000 * 32,  16000,  0x1000},
+       {4096000,  16000 * 64,  16000,  0x0000},
+       {5644800,  22050 * 32,  22050,  0x1000},
+       {5644800,  22050 * 64,  22050,  0x0000},
+       {8192000,  32000 * 32,  32000,  0x1000},
+       {8192000,  32000 * 64,  32000,  0x0000},
+       {11289600,  44100 * 32,  44100,  0x1000},
+       {11289600,  44100 * 64,  44100,  0x0000},
+       {12288000,  48000 * 32,  48000,  0x1000},
+       {12288000,  48000 * 64,  48000,  0x0000},
+       {22579200,  88200 * 32,  88200,  0x1000},
+       {22579200,  88200 * 64,  88200,  0x0000},
+       {24576000,  96000 * 32,  96000,  0x1000},
+       {24576000,  96000 * 64,  96000,  0x0000},
+       /* sysclk is 512fs */
+       {4096000,  8000 * 32,  8000, 0x3000},
+       {4096000,  8000 * 64,  8000, 0x2000},
+       {5644800,  11025 * 32,  11025, 0x3000},
+       {5644800,  11025 * 64,  11025, 0x2000},
+       {8192000,  16000 * 32,  16000, 0x3000},
+       {8192000,  16000 * 64,  16000, 0x2000},
+       {11289600,  22050 * 32,  22050, 0x3000},
+       {11289600,  22050 * 64,  22050, 0x2000},
+       {16384000,  32000 * 32,  32000, 0x3000},
+       {16384000,  32000 * 64,  32000, 0x2000},
+       {22579200,  44100 * 32,  44100, 0x3000},
+       {22579200,  44100 * 64,  44100, 0x2000},
+       {24576000,  48000 * 32,  48000, 0x3000},
+       {24576000,  48000 * 64,  48000, 0x2000},
+       {45158400,  88200 * 32,  88200, 0x3000},
+       {45158400,  88200 * 64,  88200, 0x2000},
+       {49152000,  96000 * 32,  96000, 0x3000},
+       {49152000,  96000 * 64,  96000, 0x2000},
+       /* sysclk is 24.576Mhz or 22.5792Mhz */
+       {24576000,  8000 * 32,  8000,  0x7080},
+       {24576000,  8000 * 64,  8000,  0x6080},
+       {24576000,  16000 * 32,  16000,  0x5080},
+       {24576000,  16000 * 64,  16000,  0x4080},
+       {24576000,  24000 * 32,  24000,  0x5000},
+       {24576000,  24000 * 64,  24000,  0x4000},
+       {24576000,  32000 * 32,  32000,  0x3080},
+       {24576000,  32000 * 64,  32000,  0x2080},
+       {22579200,  11025 * 32,  11025,  0x7000},
+       {22579200,  11025 * 64,  11025,  0x6000},
+       {22579200,  22050 * 32,  22050,  0x5000},
+       {22579200,  22050 * 64,  22050,  0x4000},
+};
+
+static int get_coeff(int mclk, int rate, int timesofbclk)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+               if (coeff_div[i].mclk == mclk && coeff_div[i].rate == rate &&
+                       (coeff_div[i].bclk / coeff_div[i].rate) == timesofbclk)
+                       return i;
+       }
+       return -EINVAL;
+}
+
+static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+       int timesofbclk = 32, coeff;
+       unsigned int iface = 0;
+
+       dev_dbg(codec->dev, "enter %s\n", __func__);
+
+       rt5631->bclk_rate = snd_soc_params_to_bclk(params);
+       if (rt5631->bclk_rate < 0) {
+               dev_err(codec->dev, "Fail to get BCLK rate\n");
+               return rt5631->bclk_rate;
+       }
+       rt5631->rx_rate = params_rate(params);
+
+       if (rt5631->master)
+               coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate,
+                       rt5631->bclk_rate / rt5631->rx_rate);
+       else
+               coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate,
+                                       timesofbclk);
+       if (coeff < 0) {
+               dev_err(codec->dev, "Fail to get coeff\n");
+               return -EINVAL;
+       }
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface |= RT5631_SDP_I2S_DL_20;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface |= RT5631_SDP_I2S_DL_24;
+               break;
+       case SNDRV_PCM_FORMAT_S8:
+               iface |= RT5631_SDP_I2S_DL_8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, RT5631_SDP_CTRL,
+               RT5631_SDP_I2S_DL_MASK, iface);
+       snd_soc_write(codec, RT5631_STEREO_AD_DA_CLK_CTRL,
+                                       coeff_div[coeff].reg_val);
+
+       return 0;
+}
+
+static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+       unsigned int iface = 0;
+
+       dev_dbg(codec->dev, "enter %s\n", __func__);
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               rt5631->master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               iface |= RT5631_SDP_MODE_SEL_SLAVE;
+               rt5631->master = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface |= RT5631_SDP_I2S_DF_LEFT;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               iface |= RT5631_SDP_I2S_DF_PCM_A;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               iface  |= RT5631_SDP_I2S_DF_PCM_B;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               iface |= RT5631_SDP_I2S_BCLK_POL_CTRL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_write(codec, RT5631_SDP_CTRL, iface);
+
+       return 0;
+}
+
+static int rt5631_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+                               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       dev_dbg(codec->dev, "enter %s, syclk=%d\n", __func__, freq);
+
+       if ((freq >= (256 * 8000)) && (freq <= (512 * 96000))) {
+               rt5631->sysclk = freq;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+               int source, unsigned int freq_in, unsigned int freq_out)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+       int i, ret = -EINVAL;
+
+       dev_dbg(codec->dev, "enter %s\n", __func__);
+
+       if (!freq_in || !freq_out) {
+               dev_dbg(codec->dev, "PLL disabled\n");
+
+               snd_soc_update_bits(codec, RT5631_GLOBAL_CLK_CTRL,
+                       RT5631_SYSCLK_SOUR_SEL_MASK,
+                       RT5631_SYSCLK_SOUR_SEL_MCLK);
+
+               return 0;
+       }
+
+       if (rt5631->master) {
+               for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++)
+                       if (freq_in == codec_master_pll_div[i].pll_in &&
+                       freq_out == codec_master_pll_div[i].pll_out) {
+                               dev_info(codec->dev,
+                                       "change PLL in master mode\n");
+                               snd_soc_write(codec, RT5631_PLL_CTRL,
+                                       codec_master_pll_div[i].reg_val);
+                               schedule_timeout_uninterruptible(
+                                       msecs_to_jiffies(20));
+                               snd_soc_update_bits(codec,
+                                       RT5631_GLOBAL_CLK_CTRL,
+                                       RT5631_SYSCLK_SOUR_SEL_MASK |
+                                       RT5631_PLLCLK_SOUR_SEL_MASK,
+                                       RT5631_SYSCLK_SOUR_SEL_PLL |
+                                       RT5631_PLLCLK_SOUR_SEL_MCLK);
+                               ret = 0;
+                               break;
+                       }
+       } else {
+               for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++)
+                       if (freq_in == codec_slave_pll_div[i].pll_in &&
+                       freq_out == codec_slave_pll_div[i].pll_out) {
+                               dev_info(codec->dev,
+                                       "change PLL in slave mode\n");
+                               snd_soc_write(codec, RT5631_PLL_CTRL,
+                                       codec_slave_pll_div[i].reg_val);
+                               schedule_timeout_uninterruptible(
+                                       msecs_to_jiffies(20));
+                               snd_soc_update_bits(codec,
+                                       RT5631_GLOBAL_CLK_CTRL,
+                                       RT5631_SYSCLK_SOUR_SEL_MASK |
+                                       RT5631_PLLCLK_SOUR_SEL_MASK,
+                                       RT5631_SYSCLK_SOUR_SEL_PLL |
+                                       RT5631_PLLCLK_SOUR_SEL_BCLK);
+                               ret = 0;
+                               break;
+                       }
+       }
+
+       return ret;
+}
+
+static int rt5631_set_bias_level(struct snd_soc_codec *codec,
+                       enum snd_soc_bias_level level)
+{
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+       case SND_SOC_BIAS_PREPARE:
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL,
+                       RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL);
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                               RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
+                               RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
+                       msleep(80);
+                       snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                               RT5631_PWR_FAST_VREF_CTRL,
+                               RT5631_PWR_FAST_VREF_CTRL);
+                       codec->cache_only = false;
+                       snd_soc_cache_sync(codec);
+               }
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               snd_soc_write(codec, RT5631_PWR_MANAG_ADD1, 0x0000);
+               snd_soc_write(codec, RT5631_PWR_MANAG_ADD2, 0x0000);
+               snd_soc_write(codec, RT5631_PWR_MANAG_ADD3, 0x0000);
+               snd_soc_write(codec, RT5631_PWR_MANAG_ADD4, 0x0000);
+               break;
+
+       default:
+               break;
+       }
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
+
+static int rt5631_probe(struct snd_soc_codec *codec)
+{
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+       unsigned int val;
+       int ret;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3);
+       if (val & 0x0002)
+               rt5631->codec_version = 1;
+       else
+               rt5631->codec_version = 0;
+
+       rt5631_reset(codec);
+       snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+               RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
+               RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
+       msleep(80);
+       snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+               RT5631_PWR_FAST_VREF_CTRL, RT5631_PWR_FAST_VREF_CTRL);
+       /* enable HP zero cross */
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0f18);
+       /* power off ClassD auto Recovery */
+       if (rt5631->codec_version)
+               snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2,
+                                       0x2000, 0x2000);
+       else
+               snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2,
+                                       0x2000, 0);
+       /* DMIC */
+       if (rt5631->dmic_used_flag) {
+               snd_soc_update_bits(codec, RT5631_GPIO_CTRL,
+                       RT5631_GPIO_PIN_FUN_SEL_MASK |
+                       RT5631_GPIO_DMIC_FUN_SEL_MASK,
+                       RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC |
+                       RT5631_GPIO_DMIC_FUN_SEL_DIMC);
+               snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+                       RT5631_DMIC_L_CH_LATCH_MASK |
+                       RT5631_DMIC_R_CH_LATCH_MASK,
+                       RT5631_DMIC_L_CH_LATCH_FALLING |
+                       RT5631_DMIC_R_CH_LATCH_RISING);
+       }
+
+       codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
+       rt5631->codec = codec;
+
+       return 0;
+}
+
+static int rt5631_remove(struct snd_soc_codec *codec)
+{
+       rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5631_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+       rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int rt5631_resume(struct snd_soc_codec *codec)
+{
+       rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+#else
+#define rt5631_suspend NULL
+#define rt5631_resume NULL
+#endif
+
+#define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5631_FORMAT  (SNDRV_PCM_FMTBIT_S16_LE | \
+                       SNDRV_PCM_FMTBIT_S20_3LE | \
+                       SNDRV_PCM_FMTBIT_S24_LE | \
+                       SNDRV_PCM_FMTBIT_S8)
+
+static struct snd_soc_dai_ops rt5631_ops = {
+       .hw_params = rt5631_hifi_pcm_params,
+       .set_fmt = rt5631_hifi_codec_set_dai_fmt,
+       .set_sysclk = rt5631_hifi_codec_set_dai_sysclk,
+       .set_pll = rt5631_codec_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver rt5631_dai[] = {
+       {
+               .name = "rt5631-hifi",
+               .id = 1,
+               .playback = {
+                       .stream_name = "HIFI Playback",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = RT5631_STEREO_RATES,
+                       .formats = RT5631_FORMAT,
+               },
+               .capture = {
+                       .stream_name = "HIFI Capture",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = RT5631_STEREO_RATES,
+                       .formats = RT5631_FORMAT,
+               },
+               .ops = &rt5631_ops,
+       },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5631 = {
+       .probe = rt5631_probe,
+       .remove = rt5631_remove,
+       .suspend = rt5631_suspend,
+       .resume = rt5631_resume,
+       .set_bias_level = rt5631_set_bias_level,
+       .reg_cache_size = RT5631_VENDOR_ID2 + 1,
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = rt5631_reg,
+       .volatile_register = rt5631_volatile_register,
+       .readable_register = rt5631_readable_register,
+       .reg_cache_step = 1,
+       .controls = rt5631_snd_controls,
+       .num_controls = ARRAY_SIZE(rt5631_snd_controls),
+       .dapm_widgets = rt5631_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets),
+       .dapm_routes = rt5631_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes),
+};
+
+static const struct i2c_device_id rt5631_i2c_id[] = {
+       { "rt5631", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id);
+
+static int rt5631_i2c_probe(struct i2c_client *i2c,
+                   const struct i2c_device_id *id)
+{
+       struct rt5631_priv *rt5631;
+       int ret;
+
+       rt5631 = kzalloc(sizeof(struct rt5631_priv), GFP_KERNEL);
+       if (NULL == rt5631)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, rt5631);
+
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5631,
+                       rt5631_dai, ARRAY_SIZE(rt5631_dai));
+       if (ret < 0)
+               kfree(rt5631);
+
+       return ret;
+}
+
+static __devexit int rt5631_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static struct i2c_driver rt5631_i2c_driver = {
+       .driver = {
+               .name = "rt5631",
+               .owner = THIS_MODULE,
+       },
+       .probe = rt5631_i2c_probe,
+       .remove   = __devexit_p(rt5631_i2c_remove),
+       .id_table = rt5631_i2c_id,
+};
+
+static int __init rt5631_modinit(void)
+{
+       return i2c_add_driver(&rt5631_i2c_driver);
+}
+module_init(rt5631_modinit);
+
+static void __exit rt5631_modexit(void)
+{
+       i2c_del_driver(&rt5631_i2c_driver);
+}
+module_exit(rt5631_modexit);
+
+MODULE_DESCRIPTION("ASoC RT5631 driver");
+MODULE_AUTHOR("flove <flove@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt5631.h b/sound/soc/codecs/rt5631.h
new file mode 100644 (file)
index 0000000..1340158
--- /dev/null
@@ -0,0 +1,701 @@
+#ifndef __RTCODEC5631_H__
+#define __RTCODEC5631_H__
+
+
+#define RT5631_RESET                           0x00
+#define RT5631_SPK_OUT_VOL                     0x02
+#define RT5631_HP_OUT_VOL                      0x04
+#define RT5631_MONO_AXO_1_2_VOL                0x06
+#define RT5631_AUX_IN_VOL                      0x0A
+#define RT5631_STEREO_DAC_VOL_1                0x0C
+#define RT5631_MIC_CTRL_1                      0x0E
+#define RT5631_STEREO_DAC_VOL_2                0x10
+#define RT5631_ADC_CTRL_1                      0x12
+#define RT5631_ADC_REC_MIXER                   0x14
+#define RT5631_ADC_CTRL_2                      0x16
+#define RT5631_VDAC_DIG_VOL                    0x18
+#define RT5631_OUTMIXER_L_CTRL                 0x1A
+#define RT5631_OUTMIXER_R_CTRL                 0x1C
+#define RT5631_AXO1MIXER_CTRL                  0x1E
+#define RT5631_AXO2MIXER_CTRL                  0x20
+#define RT5631_MIC_CTRL_2                      0x22
+#define RT5631_DIG_MIC_CTRL                    0x24
+#define RT5631_MONO_INPUT_VOL                  0x26
+#define RT5631_SPK_MIXER_CTRL                  0x28
+#define RT5631_SPK_MONO_OUT_CTRL               0x2A
+#define RT5631_SPK_MONO_HP_OUT_CTRL            0x2C
+#define RT5631_SDP_CTRL                                0x34
+#define RT5631_MONO_SDP_CTRL                   0x36
+#define RT5631_STEREO_AD_DA_CLK_CTRL           0x38
+#define RT5631_PWR_MANAG_ADD1          0x3A
+#define RT5631_PWR_MANAG_ADD2          0x3B
+#define RT5631_PWR_MANAG_ADD3          0x3C
+#define RT5631_PWR_MANAG_ADD4          0x3E
+#define RT5631_GEN_PUR_CTRL_REG                0x40
+#define RT5631_GLOBAL_CLK_CTRL                 0x42
+#define RT5631_PLL_CTRL                                0x44
+#define RT5631_INT_ST_IRQ_CTRL_1               0x48
+#define RT5631_INT_ST_IRQ_CTRL_2               0x4A
+#define RT5631_GPIO_CTRL                       0x4C
+#define RT5631_MISC_CTRL                       0x52
+#define RT5631_DEPOP_FUN_CTRL_1                0x54
+#define RT5631_DEPOP_FUN_CTRL_2                0x56
+#define RT5631_JACK_DET_CTRL                   0x5A
+#define RT5631_SOFT_VOL_CTRL                   0x5C
+#define RT5631_ALC_CTRL_1                      0x64
+#define RT5631_ALC_CTRL_2                      0x65
+#define RT5631_ALC_CTRL_3                      0x66
+#define RT5631_PSEUDO_SPATL_CTRL               0x68
+#define RT5631_INDEX_ADD                       0x6A
+#define RT5631_INDEX_DATA                      0x6C
+#define RT5631_EQ_CTRL                         0x6E
+#define RT5631_VENDOR_ID                       0x7A
+#define RT5631_VENDOR_ID1                      0x7C
+#define RT5631_VENDOR_ID2                      0x7E
+
+/* Index of Codec Private Register definition */
+#define RT5631_EQ_BW_LOP                       0x00
+#define RT5631_EQ_GAIN_LOP                     0x01
+#define RT5631_EQ_FC_BP1                       0x02
+#define RT5631_EQ_BW_BP1                       0x03
+#define RT5631_EQ_GAIN_BP1                     0x04
+#define RT5631_EQ_FC_BP2                       0x05
+#define RT5631_EQ_BW_BP2                       0x06
+#define RT5631_EQ_GAIN_BP2                     0x07
+#define RT5631_EQ_FC_BP3                       0x08
+#define RT5631_EQ_BW_BP3                       0x09
+#define RT5631_EQ_GAIN_BP3                     0x0a
+#define RT5631_EQ_BW_HIP                       0x0b
+#define RT5631_EQ_GAIN_HIP                     0x0c
+#define RT5631_EQ_HPF_A1                       0x0d
+#define RT5631_EQ_HPF_A2                       0x0e
+#define RT5631_EQ_HPF_GAIN                     0x0f
+#define RT5631_EQ_PRE_VOL_CTRL                 0x11
+#define RT5631_EQ_POST_VOL_CTRL                0x12
+#define RT5631_TEST_MODE_CTRL                  0x39
+#define RT5631_CP_INTL_REG2                    0x45
+#define RT5631_ADDA_MIXER_INTL_REG3            0x52
+#define RT5631_SPK_INTL_CTRL                   0x56
+
+
+/* global definition */
+#define RT5631_L_MUTE                                  (0x1 << 15)
+#define RT5631_L_MUTE_SHIFT                            15
+#define RT5631_L_EN                                    (0x1 << 14)
+#define RT5631_L_EN_SHIFT                              14
+#define RT5631_R_MUTE                                  (0x1 << 7)
+#define RT5631_R_MUTE_SHIFT                            7
+#define RT5631_R_EN                                    (0x1 << 6)
+#define RT5631_R_EN_SHIFT                              6
+#define RT5631_VOL_MASK                                0x1f
+#define RT5631_L_VOL_SHIFT                             8
+#define RT5631_R_VOL_SHIFT                             0
+
+/* Speaker Output Control(0x02) */
+#define RT5631_SPK_L_VOL_SEL_MASK                      (0x1 << 14)
+#define RT5631_SPK_L_VOL_SEL_VMID                      (0x0 << 14)
+#define RT5631_SPK_L_VOL_SEL_SPKMIX_L                  (0x1 << 14)
+#define RT5631_SPK_R_VOL_SEL_MASK                      (0x1 << 6)
+#define RT5631_SPK_R_VOL_SEL_VMID                      (0x0 << 6)
+#define RT5631_SPK_R_VOL_SEL_SPKMIX_R                  (0x1 << 6)
+
+/* Headphone Output Control(0x04) */
+#define RT5631_HP_L_VOL_SEL_MASK                       (0x1 << 14)
+#define RT5631_HP_L_VOL_SEL_VMID                       (0x0 << 14)
+#define RT5631_HP_L_VOL_SEL_OUTMIX_L                   (0x1 << 14)
+#define RT5631_HP_R_VOL_SEL_MASK                       (0x1 << 6)
+#define RT5631_HP_R_VOL_SEL_VMID                       (0x0 << 6)
+#define RT5631_HP_R_VOL_SEL_OUTMIX_R                   (0x1 << 6)
+
+/* Output Control for AUXOUT/MONO(0x06) */
+#define RT5631_AUXOUT_1_VOL_SEL_MASK                   (0x1 << 14)
+#define RT5631_AUXOUT_1_VOL_SEL_VMID                   (0x0 << 14)
+#define RT5631_AUXOUT_1_VOL_SEL_OUTMIX_L               (0x1 << 14)
+#define RT5631_MUTE_MONO                               (0x1 << 13)
+#define RT5631_MUTE_MONO_SHIFT                 13
+#define RT5631_AUXOUT_2_VOL_SEL_MASK                   (0x1 << 6)
+#define RT5631_AUXOUT_2_VOL_SEL_VMID                   (0x0 << 6)
+#define RT5631_AUXOUT_2_VOL_SEL_OUTMIX_R               (0x1 << 6)
+
+/* Microphone Input Control 1(0x0E) */
+#define RT5631_MIC1_DIFF_INPUT_CTRL                    (0x1 << 15)
+#define RT5631_MIC1_DIFF_INPUT_SHIFT                   15
+#define RT5631_MIC2_DIFF_INPUT_CTRL                    (0x1 << 7)
+#define RT5631_MIC2_DIFF_INPUT_SHIFT                   7
+
+/* Stereo DAC Digital Volume2(0x10) */
+#define RT5631_DAC_VOL_MASK                            0xff
+
+/* ADC Recording Mixer Control(0x14) */
+#define RT5631_M_OUTMIXER_L_TO_RECMIXER_L              (0x1 << 15)
+#define RT5631_M_OUTMIXL_RECMIXL_BIT                   15
+#define RT5631_M_MIC1_TO_RECMIXER_L                    (0x1 << 14)
+#define RT5631_M_MIC1_RECMIXL_BIT                      14
+#define RT5631_M_AXIL_TO_RECMIXER_L                    (0x1 << 13)
+#define RT5631_M_AXIL_RECMIXL_BIT                      13
+#define RT5631_M_MONO_IN_TO_RECMIXER_L         (0x1 << 12)
+#define RT5631_M_MONO_IN_RECMIXL_BIT                   12
+#define RT5631_M_OUTMIXER_R_TO_RECMIXER_R              (0x1 << 7)
+#define RT5631_M_OUTMIXR_RECMIXR_BIT                   7
+#define RT5631_M_MIC2_TO_RECMIXER_R                    (0x1 << 6)
+#define RT5631_M_MIC2_RECMIXR_BIT                      6
+#define RT5631_M_AXIR_TO_RECMIXER_R                    (0x1 << 5)
+#define RT5631_M_AXIR_RECMIXR_BIT                      5
+#define RT5631_M_MONO_IN_TO_RECMIXER_R         (0x1 << 4)
+#define RT5631_M_MONO_IN_RECMIXR_BIT                   4
+
+/* Left Output Mixer Control(0x1A) */
+#define RT5631_M_RECMIXER_L_TO_OUTMIXER_L              (0x1 << 15)
+#define RT5631_M_RECMIXL_OUTMIXL_BIT                   15
+#define RT5631_M_RECMIXER_R_TO_OUTMIXER_L              (0x1 << 14)
+#define RT5631_M_RECMIXR_OUTMIXL_BIT                   14
+#define RT5631_M_DAC_L_TO_OUTMIXER_L                   (0x1 << 13)
+#define RT5631_M_DACL_OUTMIXL_BIT                      13
+#define RT5631_M_MIC1_TO_OUTMIXER_L                    (0x1 << 12)
+#define RT5631_M_MIC1_OUTMIXL_BIT                      12
+#define RT5631_M_MIC2_TO_OUTMIXER_L                    (0x1 << 11)
+#define RT5631_M_MIC2_OUTMIXL_BIT                      11
+#define RT5631_M_MONO_IN_P_TO_OUTMIXER_L               (0x1 << 10)
+#define RT5631_M_MONO_INP_OUTMIXL_BIT          10
+#define RT5631_M_AXIL_TO_OUTMIXER_L                    (0x1 << 9)
+#define RT5631_M_AXIL_OUTMIXL_BIT                      9
+#define RT5631_M_AXIR_TO_OUTMIXER_L                    (0x1 << 8)
+#define RT5631_M_AXIR_OUTMIXL_BIT                      8
+#define RT5631_M_VDAC_TO_OUTMIXER_L                    (0x1 << 7)
+#define RT5631_M_VDAC_OUTMIXL_BIT                      7
+
+/* Right Output Mixer Control(0x1C) */
+#define RT5631_M_RECMIXER_L_TO_OUTMIXER_R              (0x1 << 15)
+#define RT5631_M_RECMIXL_OUTMIXR_BIT                   15
+#define RT5631_M_RECMIXER_R_TO_OUTMIXER_R              (0x1 << 14)
+#define RT5631_M_RECMIXR_OUTMIXR_BIT                   14
+#define RT5631_M_DAC_R_TO_OUTMIXER_R                   (0x1 << 13)
+#define RT5631_M_DACR_OUTMIXR_BIT                      13
+#define RT5631_M_MIC1_TO_OUTMIXER_R                    (0x1 << 12)
+#define RT5631_M_MIC1_OUTMIXR_BIT                      12
+#define RT5631_M_MIC2_TO_OUTMIXER_R                    (0x1 << 11)
+#define RT5631_M_MIC2_OUTMIXR_BIT                      11
+#define RT5631_M_MONO_IN_N_TO_OUTMIXER_R               (0x1 << 10)
+#define RT5631_M_MONO_INN_OUTMIXR_BIT          10
+#define RT5631_M_AXIL_TO_OUTMIXER_R                    (0x1 << 9)
+#define RT5631_M_AXIL_OUTMIXR_BIT                      9
+#define RT5631_M_AXIR_TO_OUTMIXER_R                    (0x1 << 8)
+#define RT5631_M_AXIR_OUTMIXR_BIT                      8
+#define RT5631_M_VDAC_TO_OUTMIXER_R                    (0x1 << 7)
+#define RT5631_M_VDAC_OUTMIXR_BIT                      7
+
+/* Lout Mixer Control(0x1E) */
+#define RT5631_M_MIC1_TO_AXO1MIXER                     (0x1 << 15)
+#define RT5631_M_MIC1_AXO1MIX_BIT                      15
+#define RT5631_M_MIC2_TO_AXO1MIXER                     (0x1 << 11)
+#define RT5631_M_MIC2_AXO1MIX_BIT                      11
+#define RT5631_M_OUTMIXER_L_TO_AXO1MIXER               (0x1 << 7)
+#define RT5631_M_OUTMIXL_AXO1MIX_BIT                   7
+#define RT5631_M_OUTMIXER_R_TO_AXO1MIXER               (0x1 << 6)
+#define RT5631_M_OUTMIXR_AXO1MIX_BIT                   6
+
+/* Rout Mixer Control(0x20) */
+#define RT5631_M_MIC1_TO_AXO2MIXER                     (0x1 << 15)
+#define RT5631_M_MIC1_AXO2MIX_BIT                      15
+#define RT5631_M_MIC2_TO_AXO2MIXER                     (0x1 << 11)
+#define RT5631_M_MIC2_AXO2MIX_BIT                      11
+#define RT5631_M_OUTMIXER_L_TO_AXO2MIXER               (0x1 << 7)
+#define RT5631_M_OUTMIXL_AXO2MIX_BIT                   7
+#define RT5631_M_OUTMIXER_R_TO_AXO2MIXER               (0x1 << 6)
+#define RT5631_M_OUTMIXR_AXO2MIX_BIT                   6
+
+/* Micphone Input Control 2(0x22) */
+#define RT5631_MIC_BIAS_90_PRECNET_AVDD 1
+#define RT5631_MIC_BIAS_75_PRECNET_AVDD 2
+
+#define RT5631_MIC1_BOOST_CTRL_MASK                    (0xf << 12)
+#define RT5631_MIC1_BOOST_CTRL_BYPASS          (0x0 << 12)
+#define RT5631_MIC1_BOOST_CTRL_20DB                    (0x1 << 12)
+#define RT5631_MIC1_BOOST_CTRL_24DB                    (0x2 << 12)
+#define RT5631_MIC1_BOOST_CTRL_30DB                    (0x3 << 12)
+#define RT5631_MIC1_BOOST_CTRL_35DB                    (0x4 << 12)
+#define RT5631_MIC1_BOOST_CTRL_40DB                    (0x5 << 12)
+#define RT5631_MIC1_BOOST_CTRL_34DB                    (0x6 << 12)
+#define RT5631_MIC1_BOOST_CTRL_50DB                    (0x7 << 12)
+#define RT5631_MIC1_BOOST_CTRL_52DB                    (0x8 << 12)
+#define RT5631_MIC1_BOOST_SHIFT                        12
+
+#define RT5631_MIC2_BOOST_CTRL_MASK                    (0xf << 8)
+#define RT5631_MIC2_BOOST_CTRL_BYPASS          (0x0 << 8)
+#define RT5631_MIC2_BOOST_CTRL_20DB                    (0x1 << 8)
+#define RT5631_MIC2_BOOST_CTRL_24DB                    (0x2 << 8)
+#define RT5631_MIC2_BOOST_CTRL_30DB                    (0x3 << 8)
+#define RT5631_MIC2_BOOST_CTRL_35DB                    (0x4 << 8)
+#define RT5631_MIC2_BOOST_CTRL_40DB                    (0x5 << 8)
+#define RT5631_MIC2_BOOST_CTRL_34DB                    (0x6 << 8)
+#define RT5631_MIC2_BOOST_CTRL_50DB                    (0x7 << 8)
+#define RT5631_MIC2_BOOST_CTRL_52DB                    (0x8 << 8)
+#define RT5631_MIC2_BOOST_SHIFT                        8
+
+#define RT5631_MICBIAS1_VOLT_CTRL_MASK         (0x1 << 7)
+#define RT5631_MICBIAS1_VOLT_CTRL_90P                  (0x0 << 7)
+#define RT5631_MICBIAS1_VOLT_CTRL_75P                  (0x1 << 7)
+
+#define RT5631_MICBIAS1_S_C_DET_MASK                   (0x1 << 6)
+#define RT5631_MICBIAS1_S_C_DET_DIS                    (0x0 << 6)
+#define RT5631_MICBIAS1_S_C_DET_ENA                    (0x1 << 6)
+
+#define RT5631_MICBIAS1_SHORT_CURR_DET_MASK            (0x3 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_600UA   (0x0 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_1500UA  (0x1 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_2000UA  (0x2 << 4)
+
+#define RT5631_MICBIAS2_VOLT_CTRL_MASK         (0x1 << 3)
+#define RT5631_MICBIAS2_VOLT_CTRL_90P                  (0x0 << 3)
+#define RT5631_MICBIAS2_VOLT_CTRL_75P                  (0x1 << 3)
+
+#define RT5631_MICBIAS2_S_C_DET_MASK                   (0x1 << 2)
+#define RT5631_MICBIAS2_S_C_DET_DIS                    (0x0 << 2)
+#define RT5631_MICBIAS2_S_C_DET_ENA                    (0x1 << 2)
+
+#define RT5631_MICBIAS2_SHORT_CURR_DET_MASK            (0x3)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_600UA   (0x0)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_1500UA  (0x1)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_2000UA  (0x2)
+
+
+/* Digital Microphone Control(0x24) */
+#define RT5631_DMIC_ENA_MASK                           (0x1 << 15)
+#define RT5631_DMIC_ENA_SHIFT                          15
+/* DMIC_ENA: DMIC to ADC Digital filter */
+#define RT5631_DMIC_ENA                                (0x1 << 15)
+/* DMIC_DIS: ADC mixer to ADC Digital filter */
+#define RT5631_DMIC_DIS                                        (0x0 << 15)
+#define RT5631_DMIC_L_CH_MUTE                          (0x1 << 13)
+#define RT5631_DMIC_L_CH_MUTE_SHIFT                    13
+#define RT5631_DMIC_R_CH_MUTE                          (0x1 << 12)
+#define RT5631_DMIC_R_CH_MUTE_SHIFT                    12
+#define RT5631_DMIC_L_CH_LATCH_MASK                    (0x1 << 9)
+#define RT5631_DMIC_L_CH_LATCH_RISING                  (0x1 << 9)
+#define RT5631_DMIC_L_CH_LATCH_FALLING         (0x0 << 9)
+#define RT5631_DMIC_R_CH_LATCH_MASK                    (0x1 << 8)
+#define RT5631_DMIC_R_CH_LATCH_RISING                  (0x1 << 8)
+#define RT5631_DMIC_R_CH_LATCH_FALLING         (0x0 << 8)
+#define RT5631_DMIC_CLK_CTRL_MASK                      (0x3 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_128FS                  (0x0 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_64FS                   (0x1 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_32FS                   (0x2 << 4)
+
+/* Microphone Input Volume(0x26) */
+#define RT5631_MONO_DIFF_INPUT_SHIFT                   15
+
+/* Speaker Mixer Control(0x28) */
+#define RT5631_M_RECMIXER_L_TO_SPKMIXER_L              (0x1 << 15)
+#define RT5631_M_RECMIXL_SPKMIXL_BIT                   15
+#define RT5631_M_MIC1_P_TO_SPKMIXER_L          (0x1 << 14)
+#define RT5631_M_MIC1P_SPKMIXL_BIT                     14
+#define RT5631_M_DAC_L_TO_SPKMIXER_L                   (0x1 << 13)
+#define RT5631_M_DACL_SPKMIXL_BIT                      13
+#define RT5631_M_OUTMIXER_L_TO_SPKMIXER_L              (0x1 << 12)
+#define RT5631_M_OUTMIXL_SPKMIXL_BIT                   12
+
+#define RT5631_M_RECMIXER_R_TO_SPKMIXER_R              (0x1 << 7)
+#define RT5631_M_RECMIXR_SPKMIXR_BIT                   7
+#define RT5631_M_MIC2_P_TO_SPKMIXER_R          (0x1 << 6)
+#define RT5631_M_MIC2P_SPKMIXR_BIT                     6
+#define RT5631_M_DAC_R_TO_SPKMIXER_R                   (0x1 << 5)
+#define RT5631_M_DACR_SPKMIXR_BIT                      5
+#define RT5631_M_OUTMIXER_R_TO_SPKMIXER_R              (0x1 << 4)
+#define RT5631_M_OUTMIXR_SPKMIXR_BIT                   4
+
+/* Speaker/Mono Output Control(0x2A) */
+#define RT5631_M_SPKVOL_L_TO_SPOL_MIXER                (0x1 << 15)
+#define RT5631_M_SPKVOLL_SPOLMIX_BIT                   15
+#define RT5631_M_SPKVOL_R_TO_SPOL_MIXER                (0x1 << 14)
+#define RT5631_M_SPKVOLR_SPOLMIX_BIT                   14
+#define RT5631_M_SPKVOL_L_TO_SPOR_MIXER                (0x1 << 13)
+#define RT5631_M_SPKVOLL_SPORMIX_BIT                   13
+#define RT5631_M_SPKVOL_R_TO_SPOR_MIXER                (0x1 << 12)
+#define RT5631_M_SPKVOLR_SPORMIX_BIT                   12
+#define RT5631_M_OUTVOL_L_TO_MONOMIXER         (0x1 << 11)
+#define RT5631_M_OUTVOLL_MONOMIX_BIT                   11
+#define RT5631_M_OUTVOL_R_TO_MONOMIXER         (0x1 << 10)
+#define RT5631_M_OUTVOLR_MONOMIX_BIT                   10
+
+/* Speaker/Mono/HP Output Control(0x2C) */
+#define RT5631_SPK_L_MUX_SEL_MASK                      (0x3 << 14)
+#define RT5631_SPK_L_MUX_SEL_SPKMIXER_L                (0x0 << 14)
+#define RT5631_SPK_L_MUX_SEL_MONO_IN                   (0x1 << 14)
+#define RT5631_SPK_L_MUX_SEL_DAC_L                     (0x3 << 14)
+#define RT5631_SPK_L_MUX_SEL_SHIFT                     14
+
+#define RT5631_SPK_R_MUX_SEL_MASK                      (0x3 << 10)
+#define RT5631_SPK_R_MUX_SEL_SPKMIXER_R                (0x0 << 10)
+#define RT5631_SPK_R_MUX_SEL_MONO_IN                   (0x1 << 10)
+#define RT5631_SPK_R_MUX_SEL_DAC_R                     (0x3 << 10)
+#define RT5631_SPK_R_MUX_SEL_SHIFT                     10
+
+#define RT5631_MONO_MUX_SEL_MASK                       (0x3 << 6)
+#define RT5631_MONO_MUX_SEL_MONOMIXER          (0x0 << 6)
+#define RT5631_MONO_MUX_SEL_MONO_IN                    (0x1 << 6)
+#define RT5631_MONO_MUX_SEL_SHIFT                      6
+
+#define RT5631_HP_L_MUX_SEL_MASK                       (0x1 << 3)
+#define RT5631_HP_L_MUX_SEL_HPVOL_L                    (0x0 << 3)
+#define RT5631_HP_L_MUX_SEL_DAC_L                      (0x1 << 3)
+#define RT5631_HP_L_MUX_SEL_SHIFT                      3
+
+#define RT5631_HP_R_MUX_SEL_MASK                       (0x1 << 2)
+#define RT5631_HP_R_MUX_SEL_HPVOL_R                    (0x0 << 2)
+#define RT5631_HP_R_MUX_SEL_DAC_R                      (0x1 << 2)
+#define RT5631_HP_R_MUX_SEL_SHIFT                      2
+
+/* Stereo I2S Serial Data Port Control(0x34) */
+#define RT5631_SDP_MODE_SEL_MASK                       (0x1 << 15)
+#define RT5631_SDP_MODE_SEL_MASTER                     (0x0 << 15)
+#define RT5631_SDP_MODE_SEL_SLAVE                      (0x1 << 15)
+
+#define RT5631_SDP_ADC_CPS_SEL_MASK                    (0x3 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_OFF                     (0x0 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_U_LAW                   (0x1 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_A_LAW                   (0x2 << 10)
+
+#define RT5631_SDP_DAC_CPS_SEL_MASK                    (0x3 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_OFF                     (0x0 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_U_LAW                   (0x1 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_A_LAW                   (0x2 << 8)
+/* 0:Normal 1:Invert */
+#define RT5631_SDP_I2S_BCLK_POL_CTRL                   (0x1 << 7)
+/* 0:Normal 1:Invert */
+#define RT5631_SDP_DAC_R_INV                           (0x1 << 6)
+/* 0:ADC data appear at left phase of LRCK
+ * 1:ADC data appear at right phase of LRCK
+ */
+#define RT5631_SDP_ADC_DATA_L_R_SWAP                   (0x1 << 5)
+/* 0:DAC data appear at left phase of LRCK
+ * 1:DAC data appear at right phase of LRCK
+ */
+#define RT5631_SDP_DAC_DATA_L_R_SWAP                   (0x1 << 4)
+
+/* Data Length Slection */
+#define RT5631_SDP_I2S_DL_MASK                         (0x3 << 2)
+#define RT5631_SDP_I2S_DL_16                           (0x0 << 2)
+#define RT5631_SDP_I2S_DL_20                           (0x1 << 2)
+#define RT5631_SDP_I2S_DL_24                           (0x2 << 2)
+#define RT5631_SDP_I2S_DL_8                            (0x3 << 2)
+
+/* PCM Data Format Selection */
+#define RT5631_SDP_I2S_DF_MASK                         (0x3)
+#define RT5631_SDP_I2S_DF_I2S                          (0x0)
+#define RT5631_SDP_I2S_DF_LEFT                         (0x1)
+#define RT5631_SDP_I2S_DF_PCM_A                        (0x2)
+#define RT5631_SDP_I2S_DF_PCM_B                        (0x3)
+
+/* Stereo AD/DA Clock Control(0x38h) */
+#define RT5631_I2S_PRE_DIV_MASK                        (0x7 << 13)
+#define RT5631_I2S_PRE_DIV_1                           (0x0 << 13)
+#define RT5631_I2S_PRE_DIV_2                           (0x1 << 13)
+#define RT5631_I2S_PRE_DIV_4                           (0x2 << 13)
+#define RT5631_I2S_PRE_DIV_8                           (0x3 << 13)
+#define RT5631_I2S_PRE_DIV_16                          (0x4 << 13)
+#define RT5631_I2S_PRE_DIV_32                          (0x5 << 13)
+/* CLOCK RELATIVE OF BCLK AND LCRK */
+#define RT5631_I2S_LRCK_SEL_N_BCLK_MASK                (0x1 << 12)
+#define RT5631_I2S_LRCK_SEL_64_BCLK                    (0x0 << 12) /* 64FS */
+#define RT5631_I2S_LRCK_SEL_32_BCLK                    (0x1 << 12) /* 32FS */
+
+#define RT5631_DAC_OSR_SEL_MASK                        (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_128FS                       (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_64FS                        (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_32FS                        (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_16FS                        (0x3 << 10)
+
+#define RT5631_ADC_OSR_SEL_MASK                        (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_128FS                       (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_64FS                        (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_32FS                        (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_16FS                        (0x3 << 8)
+
+#define RT5631_ADDA_FILTER_CLK_SEL_256FS               (0 << 7) /* 256FS */
+#define RT5631_ADDA_FILTER_CLK_SEL_384FS               (1 << 7) /* 384FS */
+
+/* Power managment addition 1 (0x3A) */
+#define RT5631_PWR_MAIN_I2S_EN                 (0x1 << 15)
+#define RT5631_PWR_MAIN_I2S_BIT                        15
+#define RT5631_PWR_CLASS_D                             (0x1 << 12)
+#define RT5631_PWR_CLASS_D_BIT                 12
+#define RT5631_PWR_ADC_L_CLK                           (0x1 << 11)
+#define RT5631_PWR_ADC_L_CLK_BIT                       11
+#define RT5631_PWR_ADC_R_CLK                           (0x1 << 10)
+#define RT5631_PWR_ADC_R_CLK_BIT                       10
+#define RT5631_PWR_DAC_L_CLK                           (0x1 << 9)
+#define RT5631_PWR_DAC_L_CLK_BIT                       9
+#define RT5631_PWR_DAC_R_CLK                           (0x1 << 8)
+#define RT5631_PWR_DAC_R_CLK_BIT                       8
+#define RT5631_PWR_DAC_REF                             (0x1 << 7)
+#define RT5631_PWR_DAC_REF_BIT                 7
+#define RT5631_PWR_DAC_L_TO_MIXER                      (0x1 << 6)
+#define RT5631_PWR_DAC_L_TO_MIXER_BIT          6
+#define RT5631_PWR_DAC_R_TO_MIXER                      (0x1 << 5)
+#define RT5631_PWR_DAC_R_TO_MIXER_BIT          5
+
+/* Power managment addition 2 (0x3B) */
+#define RT5631_PWR_OUTMIXER_L                          (0x1 << 15)
+#define RT5631_PWR_OUTMIXER_L_BIT                      15
+#define RT5631_PWR_OUTMIXER_R                          (0x1 << 14)
+#define RT5631_PWR_OUTMIXER_R_BIT                      14
+#define RT5631_PWR_SPKMIXER_L                          (0x1 << 13)
+#define RT5631_PWR_SPKMIXER_L_BIT                      13
+#define RT5631_PWR_SPKMIXER_R                          (0x1 << 12)
+#define RT5631_PWR_SPKMIXER_R_BIT                      12
+#define RT5631_PWR_RECMIXER_L                          (0x1 << 11)
+#define RT5631_PWR_RECMIXER_L_BIT                      11
+#define RT5631_PWR_RECMIXER_R                          (0x1 << 10)
+#define RT5631_PWR_RECMIXER_R_BIT                      10
+#define RT5631_PWR_MIC1_BOOT_GAIN                      (0x1 << 5)
+#define RT5631_PWR_MIC1_BOOT_GAIN_BIT          5
+#define RT5631_PWR_MIC2_BOOT_GAIN                      (0x1 << 4)
+#define RT5631_PWR_MIC2_BOOT_GAIN_BIT          4
+#define RT5631_PWR_MICBIAS1_VOL                        (0x1 << 3)
+#define RT5631_PWR_MICBIAS1_VOL_BIT                    3
+#define RT5631_PWR_MICBIAS2_VOL                        (0x1 << 2)
+#define RT5631_PWR_MICBIAS2_VOL_BIT                    2
+#define RT5631_PWR_PLL1                                (0x1 << 1)
+#define RT5631_PWR_PLL1_BIT                            1
+#define RT5631_PWR_PLL2                                (0x1 << 0)
+#define RT5631_PWR_PLL2_BIT                            0
+
+/* Power managment addition 3(0x3C) */
+#define RT5631_PWR_VREF                                (0x1 << 15)
+#define RT5631_PWR_VREF_BIT                            15
+#define RT5631_PWR_FAST_VREF_CTRL                      (0x1 << 14)
+#define RT5631_PWR_FAST_VREF_CTRL_BIT                  14
+#define RT5631_PWR_MAIN_BIAS                           (0x1 << 13)
+#define RT5631_PWR_MAIN_BIAS_BIT                       13
+#define RT5631_PWR_AXO1MIXER                           (0x1 << 11)
+#define RT5631_PWR_AXO1MIXER_BIT                       11
+#define RT5631_PWR_AXO2MIXER                           (0x1 << 10)
+#define RT5631_PWR_AXO2MIXER_BIT                       10
+#define RT5631_PWR_MONOMIXER                           (0x1 << 9)
+#define RT5631_PWR_MONOMIXER_BIT                       9
+#define RT5631_PWR_MONO_DEPOP_DIS                      (0x1 << 8)
+#define RT5631_PWR_MONO_DEPOP_DIS_BIT          8
+#define RT5631_PWR_MONO_AMP_EN                 (0x1 << 7)
+#define RT5631_PWR_MONO_AMP_EN_BIT                     7
+#define RT5631_PWR_CHARGE_PUMP                 (0x1 << 4)
+#define RT5631_PWR_CHARGE_PUMP_BIT                     4
+#define RT5631_PWR_HP_L_AMP                            (0x1 << 3)
+#define RT5631_PWR_HP_L_AMP_BIT                        3
+#define RT5631_PWR_HP_R_AMP                            (0x1 << 2)
+#define RT5631_PWR_HP_R_AMP_BIT                        2
+#define RT5631_PWR_HP_DEPOP_DIS                        (0x1 << 1)
+#define RT5631_PWR_HP_DEPOP_DIS_BIT                    1
+#define RT5631_PWR_HP_AMP_DRIVING                      (0x1 << 0)
+#define RT5631_PWR_HP_AMP_DRIVING_BIT          0
+
+/* Power managment addition 4(0x3E) */
+#define RT5631_PWR_SPK_L_VOL                           (0x1 << 15)
+#define RT5631_PWR_SPK_L_VOL_BIT                       15
+#define RT5631_PWR_SPK_R_VOL                           (0x1 << 14)
+#define RT5631_PWR_SPK_R_VOL_BIT                       14
+#define RT5631_PWR_LOUT_VOL                            (0x1 << 13)
+#define RT5631_PWR_LOUT_VOL_BIT                        13
+#define RT5631_PWR_ROUT_VOL                            (0x1 << 12)
+#define RT5631_PWR_ROUT_VOL_BIT                        12
+#define RT5631_PWR_HP_L_OUT_VOL                        (0x1 << 11)
+#define RT5631_PWR_HP_L_OUT_VOL_BIT                    11
+#define RT5631_PWR_HP_R_OUT_VOL                        (0x1 << 10)
+#define RT5631_PWR_HP_R_OUT_VOL_BIT                    10
+#define RT5631_PWR_AXIL_IN_VOL                         (0x1 << 9)
+#define RT5631_PWR_AXIL_IN_VOL_BIT                     9
+#define RT5631_PWR_AXIR_IN_VOL                 (0x1 << 8)
+#define RT5631_PWR_AXIR_IN_VOL_BIT                     8
+#define RT5631_PWR_MONO_IN_P_VOL                       (0x1 << 7)
+#define RT5631_PWR_MONO_IN_P_VOL_BIT                   7
+#define RT5631_PWR_MONO_IN_N_VOL                       (0x1 << 6)
+#define RT5631_PWR_MONO_IN_N_VOL_BIT                   6
+
+/* General Purpose Control Register(0x40) */
+#define RT5631_SPK_AMP_AUTO_RATIO_EN                   (0x1 << 15)
+
+#define RT5631_SPK_AMP_RATIO_CTRL_MASK         (0x7 << 12)
+#define RT5631_SPK_AMP_RATIO_CTRL_2_34         (0x0 << 12) /* 7.40DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_99         (0x1 << 12) /* 5.99DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_68         (0x2 << 12) /* 4.50DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_56         (0x3 << 12) /* 3.86DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_44         (0x4 << 12) /* 3.16DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_27         (0x5 << 12) /* 2.10DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_09         (0x6 << 12) /* 0.80DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_00         (0x7 << 12) /* 0.00DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_SHIFT                12
+
+#define RT5631_STEREO_DAC_HI_PASS_FILT_EN              (0x1 << 11)
+#define RT5631_STEREO_ADC_HI_PASS_FILT_EN              (0x1 << 10)
+/* Select ADC Wind Filter Clock type */
+#define RT5631_ADC_WIND_FILT_MASK                      (0x3 << 4)
+#define RT5631_ADC_WIND_FILT_8_16_32K                  (0x0 << 4) /*8/16/32k*/
+#define RT5631_ADC_WIND_FILT_11_22_44K         (0x1 << 4) /*11/22/44k*/
+#define RT5631_ADC_WIND_FILT_12_24_48K         (0x2 << 4) /*12/24/48k*/
+#define RT5631_ADC_WIND_FILT_EN                        (0x1 << 3)
+/* SelectADC Wind Filter Corner Frequency */
+#define RT5631_ADC_WIND_CNR_FREQ_MASK  (0x7 << 0)
+#define RT5631_ADC_WIND_CNR_FREQ_82_113_122    (0x0 << 0) /* 82/113/122 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_102_141_153 (0x1 << 0) /* 102/141/153 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_131_180_156 (0x2 << 0) /* 131/180/156 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_163_225_245 (0x3 << 0) /* 163/225/245 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_204_281_306 (0x4 << 0) /* 204/281/306 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_261_360_392 (0x5 << 0) /* 261/360/392 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_327_450_490 (0x6 << 0) /* 327/450/490 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_408_563_612 (0x7 << 0) /* 408/563/612 Hz */
+
+/* Global Clock Control Register(0x42) */
+#define RT5631_SYSCLK_SOUR_SEL_MASK                    (0x3 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_MCLK                    (0x0 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_PLL                     (0x1 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_PLL_TCK         (0x2 << 14)
+
+#define RT5631_PLLCLK_SOUR_SEL_MASK                    (0x3 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_MCLK                    (0x0 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_BCLK                    (0x1 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_VBCLK                   (0x2 << 12)
+
+#define RT5631_PLLCLK_PRE_DIV1                         (0x0 << 11)
+#define RT5631_PLLCLK_PRE_DIV2                         (0x1 << 11)
+
+/* PLL Control(0x44) */
+#define RT5631_PLL_CTRL_M_VAL(m)                       ((m)&0xf)
+#define RT5631_PLL_CTRL_K_VAL(k)                       (((k)&0x7) << 4)
+#define RT5631_PLL_CTRL_N_VAL(n)                       (((n)&0xff) << 8)
+
+/* Internal Status and IRQ Control2(0x4A) */
+#define RT5631_ADC_DATA_SEL_MASK                       (0x3 << 14)
+#define RT5631_ADC_DATA_SEL_Disable                    (0x0 << 14)
+#define RT5631_ADC_DATA_SEL_MIC1                       (0x1 << 14)
+#define RT5631_ADC_DATA_SEL_MIC1_SHIFT         14
+#define RT5631_ADC_DATA_SEL_MIC2                       (0x2 << 14)
+#define RT5631_ADC_DATA_SEL_MIC2_SHIFT         15
+#define RT5631_ADC_DATA_SEL_STO                        (0x3 << 14)
+#define RT5631_ADC_DATA_SEL_SHIFT                      14
+
+/* GPIO Pin Configuration(0x4C) */
+#define RT5631_GPIO_PIN_FUN_SEL_MASK                   (0x1 << 15)
+#define RT5631_GPIO_PIN_FUN_SEL_IRQ                    (0x1 << 15)
+#define RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC              (0x0 << 15)
+
+#define RT5631_GPIO_DMIC_FUN_SEL_MASK          (0x1 << 3)
+#define RT5631_GPIO_DMIC_FUN_SEL_DIMC          (0x1 << 3)
+#define RT5631_GPIO_DMIC_FUN_SEL_GPIO                  (0x0 << 3)
+
+#define RT5631_GPIO_PIN_CON_MASK                       (0x1 << 2)
+#define RT5631_GPIO_PIN_SET_INPUT                      (0x0 << 2)
+#define RT5631_GPIO_PIN_SET_OUTPUT                     (0x1 << 2)
+
+/* De-POP function Control 1(0x54) */
+#define RT5631_POW_ON_SOFT_GEN                 (0x1 << 15)
+#define RT5631_EN_MUTE_UNMUTE_DEPOP                    (0x1 << 14)
+#define RT5631_EN_DEPOP2_FOR_HP                        (0x1 << 7)
+/* Power Down HPAMP_L Starts Up Signal */
+#define RT5631_PD_HPAMP_L_ST_UP                        (0x1 << 5)
+/* Power Down HPAMP_R Starts Up Signal */
+#define RT5631_PD_HPAMP_R_ST_UP                        (0x1 << 4)
+/* Enable left HP mute/unmute depop */
+#define RT5631_EN_HP_L_M_UN_MUTE_DEPOP         (0x1 << 1)
+/* Enable right HP mute/unmute depop */
+#define RT5631_EN_HP_R_M_UN_MUTE_DEPOP         (0x1 << 0)
+
+/* De-POP Fnction Control(0x56) */
+#define RT5631_EN_ONE_BIT_DEPOP                        (0x1 << 15)
+#define RT5631_EN_CAP_FREE_DEPOP                       (0x1 << 14)
+
+/* Jack Detect Control Register(0x5A) */
+#define RT5631_JD_USE_MASK                             (0x3 << 14)
+#define RT5631_JD_USE_JD2                              (0x3 << 14)
+#define RT5631_JD_USE_JD1                              (0x2 << 14)
+#define RT5631_JD_USE_GPIO                             (0x1 << 14)
+#define RT5631_JD_OFF                                  (0x0 << 14)
+/* JD trigger enable for HP */
+#define RT5631_JD_HP_EN                                        (0x1 << 11)
+#define RT5631_JD_HP_TRI_MASK                          (0x1 << 10)
+#define RT5631_JD_HP_TRI_HI                            (0x1 << 10)
+#define RT5631_JD_HP_TRI_LO                            (0x1 << 10)
+/* JD trigger enable for speaker LP/LN */
+#define RT5631_JD_SPK_L_EN                             (0x1 << 9)
+#define RT5631_JD_SPK_L_TRI_MASK                       (0x1 << 8)
+#define RT5631_JD_SPK_L_TRI_HI                         (0x1 << 8)
+#define RT5631_JD_SPK_L_TRI_LO                         (0x0 << 8)
+/* JD trigger enable for speaker RP/RN */
+#define RT5631_JD_SPK_R_EN                             (0x1 << 7)
+#define RT5631_JD_SPK_R_TRI_MASK                       (0x1 << 6)
+#define RT5631_JD_SPK_R_TRI_HI                         (0x1 << 6)
+#define RT5631_JD_SPK_R_TRI_LO                         (0x0 << 6)
+/* JD trigger enable for monoout */
+#define RT5631_JD_MONO_EN                              (0x1 << 5)
+#define RT5631_JD_MONO_TRI_MASK                        (0x1 << 4)
+#define RT5631_JD_MONO_TRI_HI                          (0x1 << 4)
+#define RT5631_JD_MONO_TRI_LO                          (0x0 << 4)
+/* JD trigger enable for Lout */
+#define RT5631_JD_AUX_1_EN                             (0x1 << 3)
+#define RT5631_JD_AUX_1_MASK                           (0x1 << 2)
+#define RT5631_JD_AUX_1_TRI_HI                         (0x1 << 2)
+#define RT5631_JD_AUX_1_TRI_LO                         (0x0 << 2)
+/* JD trigger enable for Rout */
+#define RT5631_JD_AUX_2_EN                             (0x1 << 1)
+#define RT5631_JD_AUX_2_MASK                           (0x1 << 0)
+#define RT5631_JD_AUX_2_TRI_HI                         (0x1 << 0)
+#define RT5631_JD_AUX_2_TRI_LO                         (0x0 << 0)
+
+/* ALC CONTROL 1(0x64) */
+#define RT5631_ALC_ATTACK_RATE_MASK                    (0x1F << 8)
+#define RT5631_ALC_RECOVERY_RATE_MASK          (0x1F << 0)
+
+/* ALC CONTROL 2(0x65) */
+/* select Compensation gain for Noise gate function */
+#define RT5631_ALC_COM_NOISE_GATE_MASK         (0xF << 0)
+
+/* ALC CONTROL 3(0x66) */
+#define RT5631_ALC_FUN_MASK                            (0x3 << 14)
+#define RT5631_ALC_FUN_DIS                             (0x0 << 14)
+#define RT5631_ALC_ENA_DAC_PATH                        (0x1 << 14)
+#define RT5631_ALC_ENA_ADC_PATH                        (0x3 << 14)
+#define RT5631_ALC_PARA_UPDATE                 (0x1 << 13)
+#define RT5631_ALC_LIMIT_LEVEL_MASK                    (0x1F << 8)
+#define RT5631_ALC_NOISE_GATE_FUN_MASK         (0x1 << 7)
+#define RT5631_ALC_NOISE_GATE_FUN_DIS                  (0x0 << 7)
+#define RT5631_ALC_NOISE_GATE_FUN_ENA          (0x1 << 7)
+/* ALC noise gate hold data function */
+#define RT5631_ALC_NOISE_GATE_H_D_MASK         (0x1 << 6)
+#define RT5631_ALC_NOISE_GATE_H_D_DIS                  (0x0 << 6)
+#define RT5631_ALC_NOISE_GATE_H_D_ENA          (0x1 << 6)
+
+/* Psedueo Stereo & Spatial Effect Block Control(0x68) */
+#define RT5631_SPATIAL_CTRL_EN                         (0x1 << 15)
+#define RT5631_ALL_PASS_FILTER_EN                      (0x1 << 14)
+#define RT5631_PSEUDO_STEREO_EN                        (0x1 << 13)
+#define RT5631_STEREO_EXPENSION_EN                     (0x1 << 12)
+/* 3D gain parameter */
+#define RT5631_GAIN_3D_PARA_MASK               (0x3 << 6)
+#define RT5631_GAIN_3D_PARA_1_00               (0x0 << 6) /* 3D gain 1.0 */
+#define RT5631_GAIN_3D_PARA_1_50               (0x1 << 6) /* 3D gain 1.5 */
+#define RT5631_GAIN_3D_PARA_2_00               (0x2 << 6) /* 3D gain 2.0 */
+/* 3D ratio parameter */
+#define RT5631_RATIO_3D_MASK                   (0x3 << 4)
+#define RT5631_RATIO_3D_0_0                    (0x0 << 4) /* 3D ratio 0.0 */
+#define RT5631_RATIO_3D_0_66                   (0x1 << 4) /* 3D ratio 0.66 */
+#define RT5631_RATIO_3D_1_0                    (0x2 << 4) /* 3D ratio 1.0 */
+/* select samplerate for all pass filter */
+#define RT5631_APF_FUN_SLE_MASK                        (0x3 << 0)
+#define RT5631_APF_FUN_SEL_48K                         (0x3 << 0)
+#define RT5631_APF_FUN_SEL_44_1K                       (0x2 << 0)
+#define RT5631_APF_FUN_SEL_32K                         (0x1 << 0)
+#define RT5631_APF_FUN_DIS                             (0x0 << 0)
+
+/* EQ CONTROL 1(0x6E) */
+#define RT5631_HW_EQ_PATH_SEL_MASK                     (0x1 << 15)
+#define RT5631_HW_EQ_PATH_SEL_DAC                      (0x0 << 15)
+#define RT5631_HW_EQ_PATH_SEL_ADC                      (0x1 << 15)
+#define RT5631_HW_EQ_UPDATE_CTRL                       (0x1 << 14)
+
+#define RT5631_EN_HW_EQ_HPF2                           (0x1 << 5)
+#define RT5631_EN_HW_EQ_HPF1                           (0x1 << 4)
+#define RT5631_EN_HW_EQ_BP3                            (0x1 << 3)
+#define RT5631_EN_HW_EQ_BP2                            (0x1 << 2)
+#define RT5631_EN_HW_EQ_BP1                            (0x1 << 1)
+#define RT5631_EN_HW_EQ_LPF                            (0x1 << 0)
+
+
+#endif /* __RTCODEC5631_H__ */
index 7e4066e131e64ac95ed0eee06bb470a4ee23a6f2..91130fbc6913e534e37d188109eb03a1801acfae 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/tlv.h>
 #include <sound/pcm.h>
@@ -1436,10 +1437,17 @@ static const struct i2c_device_id sgtl5000_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
 
+static const struct of_device_id sgtl5000_dt_ids[] = {
+       { .compatible = "fsl,sgtl5000", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids);
+
 static struct i2c_driver sgtl5000_i2c_driver = {
        .driver = {
                   .name = "sgtl5000",
                   .owner = THIS_MODULE,
+                  .of_match_table = sgtl5000_dt_ids,
                   },
        .probe = sgtl5000_i2c_probe,
        .remove = __devexit_p(sgtl5000_i2c_remove),
index 84ffdebb8a8b9c937c9ffa1323f4de40f2874e81..5c5a4abfc001acd9113fba098abd3b73e97f2a30 100644 (file)
@@ -79,7 +79,7 @@ static void configure_adc(struct snd_soc_codec *sn95031_codec, int val)
  */
 static int find_free_channel(struct snd_soc_codec *sn95031_codec)
 {
-       int ret = 0, i, value;
+       int i, value;
 
        /* check whether ADC is enabled */
        value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1);
@@ -91,12 +91,10 @@ static int find_free_channel(struct snd_soc_codec *sn95031_codec)
        for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) {
                value = snd_soc_read(sn95031_codec,
                                SN95031_ADC_CHNL_START_ADDR + i);
-               if (value & SN95031_STOPBIT_MASK) {
-                       ret = i;
+               if (value & SN95031_STOPBIT_MASK)
                        break;
-               }
        }
-       return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret;
+       return (i == SN95031_ADC_CHANLS_MAX) ? (-EINVAL) : i;
 }
 
 /* Initialize the ADC for reading micbias values. Can sleep. */
@@ -104,7 +102,7 @@ static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec)
 {
        int base_addr, chnl_addr;
        int value;
-       static int channel_index;
+       int channel_index;
 
        /* Index of the first channel in which the stop bit is set */
        channel_index = find_free_channel(sn95031_codec);
@@ -163,7 +161,6 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
        pr_debug("mic bias = %dmV\n", mic_bias);
        return mic_bias;
 }
-EXPORT_SYMBOL_GPL(sn95031_get_mic_bias);
 /*end - adc helper functions */
 
 static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
@@ -660,7 +657,7 @@ static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute)
        return 0;
 }
 
-int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
+static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
                struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
        unsigned int format, rate;
@@ -718,7 +715,7 @@ static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
        .hw_params      = sn95031_pcm_hw_params,
 };
 
-struct snd_soc_dai_driver sn95031_dais[] = {
+static struct snd_soc_dai_driver sn95031_dais[] = {
 {
        .name = "SN95031 Headset",
        .playback = {
index 9801cd7cfcb55ca108c3689d504e7b78a7944a04..e149ec61e6be9482f3ab8888025c4d7081c49305 100644 (file)
@@ -59,6 +59,7 @@ struct ssm2602_priv {
        struct snd_pcm_substream *slave_substream;
 
        enum ssm2602_type type;
+       unsigned int clk_out_pwr;
 };
 
 /*
@@ -294,7 +295,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c = codec->control_data;
        struct snd_pcm_runtime *master_runtime;
 
        /* The DAI has shared clocks so if we already have a playback or
@@ -303,7 +303,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
         */
        if (ssm2602->master_substream) {
                master_runtime = ssm2602->master_substream->runtime;
-               dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n",
+               dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n",
                        master_runtime->sample_bits,
                        master_runtime->rate);
 
@@ -357,16 +357,46 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-       switch (freq) {
-       case 11289600:
-       case 12000000:
-       case 12288000:
-       case 16934400:
-       case 18432000:
-               ssm2602->sysclk = freq;
-               return 0;
+
+       if (dir == SND_SOC_CLOCK_IN) {
+               if (clk_id != SSM2602_SYSCLK)
+                       return -EINVAL;
+
+               switch (freq) {
+               case 11289600:
+               case 12000000:
+               case 12288000:
+               case 16934400:
+               case 18432000:
+                       ssm2602->sysclk = freq;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       } else {
+               unsigned int mask;
+
+               switch (clk_id) {
+               case SSM2602_CLK_CLKOUT:
+                       mask = PWR_CLK_OUT_PDN;
+                       break;
+               case SSM2602_CLK_XTO:
+                       mask = PWR_OSC_PDN;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               if (freq == 0)
+                       ssm2602->clk_out_pwr |= mask;
+               else
+                       ssm2602->clk_out_pwr &= ~mask;
+
+               snd_soc_update_bits(codec, SSM2602_PWR,
+                       PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
        }
-       return -EINVAL;
+
+       return 0;
 }
 
 static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -431,23 +461,27 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
 static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       u16 reg = snd_soc_read(codec, SSM2602_PWR);
-       reg &= ~(PWR_POWER_OFF | PWR_OSC_PDN);
+       struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               /* vref/mid, osc on, dac unmute */
-               snd_soc_write(codec, SSM2602_PWR, reg);
+               /* vref/mid on, osc and clkout on if enabled */
+               snd_soc_update_bits(codec, SSM2602_PWR,
+                       PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
+                       ssm2602->clk_out_pwr);
                break;
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
                /* everything off except vref/vmid, */
-               snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
+               snd_soc_update_bits(codec, SSM2602_PWR,
+                       PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
+                       PWR_CLK_OUT_PDN | PWR_OSC_PDN);
                break;
        case SND_SOC_BIAS_OFF:
-               /* everything off, dac mute, inactive */
-               snd_soc_write(codec, SSM2602_PWR, 0xffff);
+               /* everything off */
+               snd_soc_update_bits(codec, SSM2602_PWR,
+                       PWR_POWER_OFF, PWR_POWER_OFF);
                break;
 
        }
@@ -578,7 +612,12 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
                break;
        }
 
-       return ret;
+       if (ret)
+               return ret;
+
+       ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       return 0;
 }
 
 /* remove everything here */
index b98c69168036d5b84744e42621e8d0732de3796d..fbd07d7b73ca2ad7bfced7147de22cec746e7bc4 100644 (file)
 
 #define SSM2602_CACHEREGNUM    10
 
-#define SSM2602_SYSCLK 0
+enum ssm2602_clk {
+       SSM2602_SYSCLK,
+       SSM2602_CLK_CLKOUT,
+       SSM2602_CLK_XTO
+};
 
 #endif
index fbd7eb9e61ce197ae9c5bb22df308d618f9545eb..5c7def3979c0ad3d876e95cdbcf9bee65a85e4f2 100644 (file)
@@ -524,13 +524,17 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
        rate = params_rate(params);
        pr_debug("rate: %u\n", rate);
        for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++)
-               if (interpolation_ratios[i].fs == rate)
+               if (interpolation_ratios[i].fs == rate) {
                        ir = interpolation_ratios[i].ir;
+                       break;
+               }
        if (ir < 0)
                return -EINVAL;
        for (i = 0; mclk_ratios[ir][i].ratio; i++)
-               if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk)
+               if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) {
                        mcs = mclk_ratios[ir][i].mcs;
+                       break;
+               }
        if (mcs < 0)
                return -EINVAL;
 
@@ -808,6 +812,7 @@ static int sta32x_remove(struct snd_soc_codec *codec)
 {
        struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
 
+       sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
        regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
        regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
 
@@ -867,18 +872,8 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
 static __devexit int sta32x_i2c_remove(struct i2c_client *client)
 {
        struct sta32x_priv *sta32x = i2c_get_clientdata(client);
-       struct snd_soc_codec *codec = sta32x->codec;
-
-       if (codec)
-               sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
-
-       if (codec) {
-               snd_soc_unregister_codec(&client->dev);
-               snd_soc_codec_set_drvdata(codec, NULL);
-       }
 
+       snd_soc_unregister_codec(&client->dev);
        kfree(sta32x);
        return 0;
 }
index 0963c4c7a83f7bae464c4b2b7165d82d42370e5b..d877b39b50009ab4ed60f610085aa61f07f54b6c 100644 (file)
@@ -76,7 +76,6 @@ struct aic3x_priv {
        struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
        enum snd_soc_control_type control_type;
        struct aic3x_setup_data *setup;
-       void *control_data;
        unsigned int sysclk;
        struct list_head list;
        int master;
@@ -1383,7 +1382,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
        int ret, i;
 
        INIT_LIST_HEAD(&aic3x->list);
-       codec->control_data = aic3x->control_data;
        aic3x->codec = codec;
        codec->dapm.idle_bias_off = 1;
 
@@ -1495,9 +1493,9 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
  */
 
 static const struct i2c_device_id aic3x_i2c_id[] = {
-       [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
-       [AIC3X_MODEL_33] = { "tlv320aic33", 0 },
-       [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
+       { "tlv320aic3x", AIC3X_MODEL_3X },
+       { "tlv320aic33", AIC3X_MODEL_33 },
+       { "tlv320aic3007", AIC3X_MODEL_3007 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@@ -1512,7 +1510,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
        struct aic3x_pdata *pdata = i2c->dev.platform_data;
        struct aic3x_priv *aic3x;
        int ret;
-       const struct i2c_device_id *tbl;
 
        aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
        if (aic3x == NULL) {
@@ -1520,7 +1517,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
        }
 
-       aic3x->control_data = i2c;
        aic3x->control_type = SND_SOC_I2C;
 
        i2c_set_clientdata(i2c, aic3x);
@@ -1531,11 +1527,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
                aic3x->gpio_reset = -1;
        }
 
-       for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
-               if (!strcmp(tbl->name, id->name))
-                       break;
-       }
-       aic3x->model = tbl - aic3x_i2c_id;
+       aic3x->model = id->driver_data;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_aic3x, &aic3x_dai, 1);
index faa5e9fb1471de20e93a4fb108ffb884b0eb6f38..43ee3b1c757e44395a3918e9048d65b07756adaf 100644 (file)
 #define BURST_BASEFREQ_HZ      49152000
 
 #define SAMPLES_TO_US(rate, samples) \
-       (1000000000 / ((rate * 1000) / samples))
+       (1000000000 / (((rate) * 1000) / (samples)))
 
 #define US_TO_SAMPLES(rate, us) \
-       (rate / (1000000 / (us < 1000000 ? us : 1000000)))
+       ((rate) / (1000000 / ((us) < 1000000 ? (us) : 1000000)))
 
 #define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
-       ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
+       (((samples)*5000) / (((burstrate)*5000) / ((burstrate) - (playrate))))
 
 static void dac33_calculate_times(struct snd_pcm_substream *substream);
 static int dac33_prepare_chip(struct snd_pcm_substream *substream);
index 239e0c461068bebb2189a0d7aaff22f472fc8d78..7eeca79d738784e612a3cca65bb15faa67a0a4b8 100644 (file)
 
 #include "tpa6130a2.h"
 
+enum tpa_model {
+       TPA6130A2,
+       TPA6140A2,
+};
+
 static struct i2c_client *tpa6130a2_client;
 
 /* This struct is used to save the context */
@@ -383,7 +388,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
 
        pdata = client->dev.platform_data;
        data->power_gpio = pdata->power_gpio;
-       data->id = pdata->id;
+       data->id = id->driver_data;
 
        mutex_init(&data->mutex);
 
@@ -405,7 +410,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
        switch (data->id) {
        default:
                dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
-                        pdata->id);
+                        data->id);
        case TPA6130A2:
                regulator = "Vdd";
                break;
@@ -446,7 +451,6 @@ err_regulator:
                gpio_free(data->power_gpio);
 err_gpio:
        kfree(data);
-       i2c_set_clientdata(tpa6130a2_client, NULL);
        tpa6130a2_client = NULL;
 
        return ret;
@@ -470,7 +474,8 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id tpa6130a2_id[] = {
-       { "tpa6130a2", 0 },
+       { "tpa6130a2", TPA6130A2 },
+       { "tpa6140a2", TPA6140A2 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
index 443032b3b3296baca51be67e7660a3c3d937f2c3..d040905cfa9ba69df7fb08fa2f9082f59ca1a9a2 100644 (file)
 #define TWL6040_HF_VOL_MASK    0x1F
 #define TWL6040_HF_VOL_SHIFT   0
 
+/* Shadow register used by the driver */
+#define TWL6040_REG_SW_SHADOW  0x2F
+#define TWL6040_CACHEREGNUM    (TWL6040_REG_SW_SHADOW + 1)
+
+/* TWL6040_REG_SW_SHADOW (0x2F) fields */
+#define TWL6040_EAR_PATH_ENABLE        0x01
+
 struct twl6040_output {
        u16 active;
        u16 left_vol;
@@ -65,12 +72,13 @@ struct twl6040_output {
        u16 right_step;
        unsigned int step_delay;
        u16 ramp;
-       u16 mute;
+       struct delayed_work work;
        struct completion ramp_done;
 };
 
 struct twl6040_jack_data {
        struct snd_soc_jack *jack;
+       struct delayed_work work;
        int report;
 };
 
@@ -92,104 +100,68 @@ struct twl6040_data {
        struct twl6040_jack_data hs_jack;
        struct snd_soc_codec *codec;
        struct workqueue_struct *workqueue;
-       struct delayed_work delayed_work;
        struct mutex mutex;
        struct twl6040_output headset;
        struct twl6040_output handsfree;
-       struct workqueue_struct *hf_workqueue;
-       struct workqueue_struct *hs_workqueue;
-       struct delayed_work hs_delayed_work;
-       struct delayed_work hf_delayed_work;
 };
 
 /*
  * twl6040 register cache & default register settings
  */
 static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
-       0x00, /* not used               0x00    */
-       0x4B, /* TWL6040_ASICID (ro)    0x01    */
-       0x00, /* TWL6040_ASICREV (ro)   0x02    */
-       0x00, /* TWL6040_INTID          0x03    */
-       0x00, /* TWL6040_INTMR          0x04    */
-       0x00, /* TWL6040_NCPCTRL        0x05    */
-       0x00, /* TWL6040_LDOCTL         0x06    */
-       0x60, /* TWL6040_HPPLLCTL       0x07    */
-       0x00, /* TWL6040_LPPLLCTL       0x08    */
-       0x4A, /* TWL6040_LPPLLDIV       0x09    */
-       0x00, /* TWL6040_AMICBCTL       0x0A    */
-       0x00, /* TWL6040_DMICBCTL       0x0B    */
-       0x18, /* TWL6040_MICLCTL        0x0C    - No input selected on Left Mic */
-       0x18, /* TWL6040_MICRCTL        0x0D    - No input selected on Right Mic */
-       0x00, /* TWL6040_MICGAIN        0x0E    */
-       0x1B, /* TWL6040_LINEGAIN       0x0F    */
-       0x00, /* TWL6040_HSLCTL         0x10    */
-       0x00, /* TWL6040_HSRCTL         0x11    */
-       0x00, /* TWL6040_HSGAIN         0x12    */
-       0x00, /* TWL6040_EARCTL         0x13    */
-       0x00, /* TWL6040_HFLCTL         0x14    */
-       0x00, /* TWL6040_HFLGAIN        0x15    */
-       0x00, /* TWL6040_HFRCTL         0x16    */
-       0x00, /* TWL6040_HFRGAIN        0x17    */
-       0x00, /* TWL6040_VIBCTLL        0x18    */
-       0x00, /* TWL6040_VIBDATL        0x19    */
-       0x00, /* TWL6040_VIBCTLR        0x1A    */
-       0x00, /* TWL6040_VIBDATR        0x1B    */
-       0x00, /* TWL6040_HKCTL1         0x1C    */
-       0x00, /* TWL6040_HKCTL2         0x1D    */
-       0x00, /* TWL6040_GPOCTL         0x1E    */
-       0x00, /* TWL6040_ALB            0x1F    */
-       0x00, /* TWL6040_DLB            0x20    */
-       0x00, /* not used               0x21    */
-       0x00, /* not used               0x22    */
-       0x00, /* not used               0x23    */
-       0x00, /* not used               0x24    */
-       0x00, /* not used               0x25    */
-       0x00, /* not used               0x26    */
-       0x00, /* not used               0x27    */
-       0x00, /* TWL6040_TRIM1          0x28    */
-       0x00, /* TWL6040_TRIM2          0x29    */
-       0x00, /* TWL6040_TRIM3          0x2A    */
-       0x00, /* TWL6040_HSOTRIM        0x2B    */
-       0x00, /* TWL6040_HFOTRIM        0x2C    */
-       0x09, /* TWL6040_ACCCTL         0x2D    */
-       0x00, /* TWL6040_STATUS (ro)    0x2E    */
+       0x00, /* not used       0x00    */
+       0x4B, /* REG_ASICID     0x01 (ro) */
+       0x00, /* REG_ASICREV    0x02 (ro) */
+       0x00, /* REG_INTID      0x03    */
+       0x00, /* REG_INTMR      0x04    */
+       0x00, /* REG_NCPCTRL    0x05    */
+       0x00, /* REG_LDOCTL     0x06    */
+       0x60, /* REG_HPPLLCTL   0x07    */
+       0x00, /* REG_LPPLLCTL   0x08    */
+       0x4A, /* REG_LPPLLDIV   0x09    */
+       0x00, /* REG_AMICBCTL   0x0A    */
+       0x00, /* REG_DMICBCTL   0x0B    */
+       0x00, /* REG_MICLCTL    0x0C    */
+       0x00, /* REG_MICRCTL    0x0D    */
+       0x00, /* REG_MICGAIN    0x0E    */
+       0x1B, /* REG_LINEGAIN   0x0F    */
+       0x00, /* REG_HSLCTL     0x10    */
+       0x00, /* REG_HSRCTL     0x11    */
+       0x00, /* REG_HSGAIN     0x12    */
+       0x00, /* REG_EARCTL     0x13    */
+       0x00, /* REG_HFLCTL     0x14    */
+       0x00, /* REG_HFLGAIN    0x15    */
+       0x00, /* REG_HFRCTL     0x16    */
+       0x00, /* REG_HFRGAIN    0x17    */
+       0x00, /* REG_VIBCTLL    0x18    */
+       0x00, /* REG_VIBDATL    0x19    */
+       0x00, /* REG_VIBCTLR    0x1A    */
+       0x00, /* REG_VIBDATR    0x1B    */
+       0x00, /* REG_HKCTL1     0x1C    */
+       0x00, /* REG_HKCTL2     0x1D    */
+       0x00, /* REG_GPOCTL     0x1E    */
+       0x00, /* REG_ALB        0x1F    */
+       0x00, /* REG_DLB        0x20    */
+       0x00, /* not used       0x21    */
+       0x00, /* not used       0x22    */
+       0x00, /* not used       0x23    */
+       0x00, /* not used       0x24    */
+       0x00, /* not used       0x25    */
+       0x00, /* not used       0x26    */
+       0x00, /* not used       0x27    */
+       0x00, /* REG_TRIM1      0x28    */
+       0x00, /* REG_TRIM2      0x29    */
+       0x00, /* REG_TRIM3      0x2A    */
+       0x00, /* REG_HSOTRIM    0x2B    */
+       0x00, /* REG_HFOTRIM    0x2C    */
+       0x09, /* REG_ACCCTL     0x2D    */
+       0x00, /* REG_STATUS     0x2E (ro) */
+
+       0x00, /* REG_SW_SHADOW  0x2F - Shadow, non HW register */
 };
 
-/*
- * twl6040 vio/gnd registers:
- * registers under vio/gnd supply can be accessed
- * before the power-up sequence, after NRESPWRON goes high
- */
-static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = {
-       TWL6040_REG_ASICID,
-       TWL6040_REG_ASICREV,
-       TWL6040_REG_INTID,
-       TWL6040_REG_INTMR,
-       TWL6040_REG_NCPCTL,
-       TWL6040_REG_LDOCTL,
-       TWL6040_REG_AMICBCTL,
-       TWL6040_REG_DMICBCTL,
-       TWL6040_REG_HKCTL1,
-       TWL6040_REG_HKCTL2,
-       TWL6040_REG_GPOCTL,
-       TWL6040_REG_TRIM1,
-       TWL6040_REG_TRIM2,
-       TWL6040_REG_TRIM3,
-       TWL6040_REG_HSOTRIM,
-       TWL6040_REG_HFOTRIM,
-       TWL6040_REG_ACCCTL,
-       TWL6040_REG_STATUS,
-};
-
-/*
- * twl6040 vdd/vss registers:
- * registers under vdd/vss supplies can only be accessed
- * after the power-up sequence
- */
-static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
-       TWL6040_REG_HPPLLCTL,
-       TWL6040_REG_LPPLLCTL,
-       TWL6040_REG_LPPLLDIV,
+/* List of registers to be restored after power up */
+static const int twl6040_restore_list[] = {
        TWL6040_REG_MICLCTL,
        TWL6040_REG_MICRCTL,
        TWL6040_REG_MICGAIN,
@@ -202,12 +174,6 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
        TWL6040_REG_HFLGAIN,
        TWL6040_REG_HFRCTL,
        TWL6040_REG_HFRGAIN,
-       TWL6040_REG_VIBCTLL,
-       TWL6040_REG_VIBDATL,
-       TWL6040_REG_VIBCTLR,
-       TWL6040_REG_VIBDATR,
-       TWL6040_REG_ALB,
-       TWL6040_REG_DLB,
 };
 
 /* set of rates for each pll: low-power and high-performance */
@@ -275,8 +241,12 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
        if (reg >= TWL6040_CACHEREGNUM)
                return -EIO;
 
-       value = twl6040_reg_read(twl6040, reg);
-       twl6040_write_reg_cache(codec, reg, value);
+       if (likely(reg < TWL6040_REG_SW_SHADOW)) {
+               value = twl6040_reg_read(twl6040, reg);
+               twl6040_write_reg_cache(codec, reg, value);
+       } else {
+               value = twl6040_read_reg_cache(codec, reg);
+       }
 
        return value;
 }
@@ -293,59 +263,51 @@ static int twl6040_write(struct snd_soc_codec *codec,
                return -EIO;
 
        twl6040_write_reg_cache(codec, reg, value);
-       return twl6040_reg_write(twl6040, reg, value);
+       if (likely(reg < TWL6040_REG_SW_SHADOW))
+               return twl6040_reg_write(twl6040, reg, value);
+       else
+               return 0;
 }
 
-static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
+static void twl6040_init_chip(struct snd_soc_codec *codec)
 {
-       u8 *cache = codec->reg_cache;
-       int reg, i;
-
-       for (i = 0; i < TWL6040_VIOREGNUM; i++) {
-               reg = twl6040_vio_reg[i];
-               /*
-                * skip read-only registers (ASICID, ASICREV, STATUS)
-                * and registers shared among MFD children
-                */
-               switch (reg) {
-               case TWL6040_REG_ASICID:
-               case TWL6040_REG_ASICREV:
-               case TWL6040_REG_INTID:
-               case TWL6040_REG_INTMR:
-               case TWL6040_REG_NCPCTL:
-               case TWL6040_REG_LDOCTL:
-               case TWL6040_REG_GPOCTL:
-               case TWL6040_REG_ACCCTL:
-               case TWL6040_REG_STATUS:
-                       continue;
-               default:
-                       break;
-               }
-               twl6040_write(codec, reg, cache[reg]);
-       }
+       struct twl6040 *twl6040 = codec->control_data;
+       u8 val;
+
+       /* Update reg_cache: ASICREV, and TRIM values */
+       val = twl6040_get_revid(twl6040);
+       twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val);
+
+       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1);
+       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2);
+       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3);
+       twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM);
+       twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM);
+
+       /* Change chip defaults */
+       /* No imput selected for microphone amplifiers */
+       twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18);
+       twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18);
+
+       /*
+        * We need to lower the default gain values, so the ramp code
+        * can work correctly for the first playback.
+        * This reduces the pop noise heard at the first playback.
+        */
+       twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff);
+       twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e);
+       twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d);
+       twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d);
+       twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0);
 }
 
-static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
+static void twl6040_restore_regs(struct snd_soc_codec *codec)
 {
        u8 *cache = codec->reg_cache;
        int reg, i;
 
-       for (i = 0; i < TWL6040_VDDREGNUM; i++) {
-               reg = twl6040_vdd_reg[i];
-               /* skip vibra and PLL registers */
-               switch (reg) {
-               case TWL6040_REG_VIBCTLL:
-               case TWL6040_REG_VIBDATL:
-               case TWL6040_REG_VIBCTLR:
-               case TWL6040_REG_VIBDATR:
-               case TWL6040_REG_HPPLLCTL:
-               case TWL6040_REG_LPPLLCTL:
-               case TWL6040_REG_LPPLLDIV:
-                       continue;
-               default:
-                       break;
-               }
-
+       for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) {
+               reg = twl6040_restore_list[i];
                twl6040_write(codec, reg, cache[reg]);
        }
 }
@@ -524,18 +486,17 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
 static void twl6040_pga_hs_work(struct work_struct *work)
 {
        struct twl6040_data *priv =
-               container_of(work, struct twl6040_data, hs_delayed_work.work);
+               container_of(work, struct twl6040_data, headset.work.work);
        struct snd_soc_codec *codec = priv->codec;
        struct twl6040_output *headset = &priv->headset;
-       unsigned int delay = headset->step_delay;
        int i, headset_complete;
 
        /* do we need to ramp at all ? */
        if (headset->ramp == TWL6040_RAMP_NONE)
                return;
 
-       /* HS PGA volumes have 4 bits of resolution to ramp */
-       for (i = 0; i <= 16; i++) {
+       /* HS PGA gain range: 0x0 - 0xf (0 - 15) */
+       for (i = 0; i < 16; i++) {
                headset_complete = twl6040_hs_ramp_step(codec,
                                                headset->left_step,
                                                headset->right_step);
@@ -544,15 +505,8 @@ static void twl6040_pga_hs_work(struct work_struct *work)
                if (headset_complete)
                        break;
 
-               /*
-                * TODO: tune: delay is longer over 0dB
-                * as increases are larger.
-                */
-               if (i >= 8)
-                       schedule_timeout_interruptible(msecs_to_jiffies(delay +
-                                                       (delay >> 1)));
-               else
-                       schedule_timeout_interruptible(msecs_to_jiffies(delay));
+               schedule_timeout_interruptible(
+                               msecs_to_jiffies(headset->step_delay));
        }
 
        if (headset->ramp == TWL6040_RAMP_DOWN) {
@@ -567,18 +521,18 @@ static void twl6040_pga_hs_work(struct work_struct *work)
 static void twl6040_pga_hf_work(struct work_struct *work)
 {
        struct twl6040_data *priv =
-               container_of(work, struct twl6040_data, hf_delayed_work.work);
+               container_of(work, struct twl6040_data, handsfree.work.work);
        struct snd_soc_codec *codec = priv->codec;
        struct twl6040_output *handsfree = &priv->handsfree;
-       unsigned int delay = handsfree->step_delay;
        int i, handsfree_complete;
 
        /* do we need to ramp at all ? */
        if (handsfree->ramp == TWL6040_RAMP_NONE)
                return;
 
-       /* HF PGA volumes have 5 bits of resolution to ramp */
-       for (i = 0; i <= 32; i++) {
+       /*
+        * HF PGA gain range: 0x00 - 0x1d (0 - 29) */
+       for (i = 0; i < 30; i++) {
                handsfree_complete = twl6040_hf_ramp_step(codec,
                                                handsfree->left_step,
                                                handsfree->right_step);
@@ -587,15 +541,8 @@ static void twl6040_pga_hf_work(struct work_struct *work)
                if (handsfree_complete)
                        break;
 
-               /*
-                * TODO: tune: delay is longer over 0dB
-                * as increases are larger.
-                */
-               if (i >= 16)
-                       schedule_timeout_interruptible(msecs_to_jiffies(delay +
-                                                      (delay >> 1)));
-               else
-                       schedule_timeout_interruptible(msecs_to_jiffies(delay));
+               schedule_timeout_interruptible(
+                               msecs_to_jiffies(handsfree->step_delay));
        }
 
 
@@ -607,29 +554,37 @@ static void twl6040_pga_hf_work(struct work_struct *work)
        handsfree->ramp = TWL6040_RAMP_NONE;
 }
 
-static int pga_event(struct snd_soc_dapm_widget *w,
+static int out_drv_event(struct snd_soc_dapm_widget *w,
                        struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
        struct twl6040_output *out;
        struct delayed_work *work;
-       struct workqueue_struct *queue;
 
        switch (w->shift) {
-       case 2:
-       case 3:
+       case 2: /* Headset output driver */
                out = &priv->headset;
-               work = &priv->hs_delayed_work;
-               queue = priv->hs_workqueue;
+               work = &out->work;
+               /*
+                * Make sure, that we do not mess up variables for already
+                * executing work.
+                */
+               cancel_delayed_work_sync(work);
+
                out->left_step = priv->hs_left_step;
                out->right_step = priv->hs_right_step;
                out->step_delay = 5;    /* 5 ms between volume ramp steps */
                break;
-       case 4:
+       case 4: /* Handsfree output driver */
                out = &priv->handsfree;
-               work = &priv->hf_delayed_work;
-               queue = priv->hf_workqueue;
+               work = &out->work;
+               /*
+                * Make sure, that we do not mess up variables for already
+                * executing work.
+                */
+               cancel_delayed_work_sync(work);
+
                out->left_step = priv->hf_left_step;
                out->right_step = priv->hf_right_step;
                out->step_delay = 5;    /* 5 ms between volume ramp steps */
@@ -648,31 +603,25 @@ static int pga_event(struct snd_soc_dapm_widget *w,
                        break;
 
                /* don't use volume ramp for power-up */
+               out->ramp = TWL6040_RAMP_UP;
                out->left_step = out->left_vol;
                out->right_step = out->right_vol;
 
-               if (!delayed_work_pending(work)) {
-                       out->ramp = TWL6040_RAMP_UP;
-                       queue_delayed_work(queue, work,
-                                       msecs_to_jiffies(1));
-               }
+               queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
                if (!out->active)
                        break;
 
-               if (!delayed_work_pending(work)) {
-                       /* use volume ramp for power-down */
-                       out->ramp = TWL6040_RAMP_DOWN;
-                       INIT_COMPLETION(out->ramp_done);
+               /* use volume ramp for power-down */
+               out->ramp = TWL6040_RAMP_DOWN;
+               INIT_COMPLETION(out->ramp_done);
 
-                       queue_delayed_work(queue, work,
-                                       msecs_to_jiffies(1));
+               queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
 
-                       wait_for_completion_timeout(&out->ramp_done,
-                                       msecs_to_jiffies(2000));
-               }
+               wait_for_completion_timeout(&out->ramp_done,
+                                           msecs_to_jiffies(2000));
                break;
        }
 
@@ -683,7 +632,7 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 {
        int hslctl, hsrctl;
-       int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;
+       int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE;
 
        hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
        hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
@@ -770,7 +719,7 @@ EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
 static void twl6040_accessory_work(struct work_struct *work)
 {
        struct twl6040_data *priv = container_of(work,
-                                       struct twl6040_data, delayed_work.work);
+                                       struct twl6040_data, hs_jack.work.work);
        struct snd_soc_codec *codec = priv->codec;
        struct twl6040_jack_data *hs_jack = &priv->hs_jack;
 
@@ -781,15 +730,10 @@ static void twl6040_accessory_work(struct work_struct *work)
 static irqreturn_t twl6040_audio_handler(int irq, void *data)
 {
        struct snd_soc_codec *codec = data;
-       struct twl6040 *twl6040 = codec->control_data;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       u8 intid;
-
-       intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
 
-       if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
-               queue_delayed_work(priv->workqueue, &priv->delayed_work,
-                                                       msecs_to_jiffies(200));
+       queue_delayed_work(priv->workqueue, &priv->hs_jack.work,
+                          msecs_to_jiffies(200));
 
        return IRQ_HANDLED;
 }
@@ -803,15 +747,17 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
        int ret;
-       unsigned int reg = mc->reg;
 
        /* For HS and HF we shadow the values and only actually write
         * them out when active in order to ensure the amplifier comes on
         * as quietly as possible. */
-       switch (reg) {
+       switch (mc->reg) {
        case TWL6040_REG_HSGAIN:
                out = &twl6040_priv->headset;
                break;
+       case TWL6040_REG_HFLGAIN:
+               out = &twl6040_priv->handsfree;
+               break;
        default:
                break;
        }
@@ -823,7 +769,12 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
                        return 1;
        }
 
-       ret = snd_soc_put_volsw(kcontrol, ucontrol);
+       /* call the appropriate handler depending on the rreg */
+       if (mc->rreg)
+               ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+       else
+               ret = snd_soc_put_volsw(kcontrol, ucontrol);
+
        if (ret < 0)
                return ret;
 
@@ -838,39 +789,12 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
        struct twl6040_output *out = &twl6040_priv->headset;
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
-       unsigned int reg = mc->reg;
 
-       switch (reg) {
+       switch (mc->reg) {
        case TWL6040_REG_HSGAIN:
                out = &twl6040_priv->headset;
-               ucontrol->value.integer.value[0] = out->left_vol;
-               ucontrol->value.integer.value[1] = out->right_vol;
-               return 0;
-
-       default:
                break;
-       }
-
-       return snd_soc_get_volsw(kcontrol, ucontrol);
-}
-
-static int twl6040_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *out = NULL;
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       int ret;
-       unsigned int reg = mc->reg;
-
-       /* For HS and HF we shadow the values and only actually write
-        * them out when active in order to ensure the amplifier comes on
-        * as quietly as possible. */
-       switch (reg) {
        case TWL6040_REG_HFLGAIN:
-       case TWL6040_REG_HFRGAIN:
                out = &twl6040_priv->handsfree;
                break;
        default:
@@ -878,43 +802,16 @@ static int twl6040_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
        }
 
        if (out) {
-               out->left_vol = ucontrol->value.integer.value[0];
-               out->right_vol = ucontrol->value.integer.value[1];
-               if (!out->active)
-                       return 1;
-       }
-
-       ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
-       if (ret < 0)
-               return ret;
-
-       return 1;
-}
-
-static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *out = &twl6040_priv->handsfree;
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       unsigned int reg = mc->reg;
-
-       /* If these are cached registers use the cache */
-       switch (reg) {
-       case TWL6040_REG_HFLGAIN:
-       case TWL6040_REG_HFRGAIN:
-               out = &twl6040_priv->handsfree;
                ucontrol->value.integer.value[0] = out->left_vol;
                ucontrol->value.integer.value[1] = out->right_vol;
                return 0;
-
-       default:
-               break;
        }
 
-       return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+       /* call the appropriate handler depending on the rreg */
+       if (mc->rreg)
+               return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+       else
+               return snd_soc_get_volsw(kcontrol, ucontrol);
 }
 
 /* double control with volume update */
@@ -939,7 +836,7 @@ static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol,
                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
        .tlv.p = (tlv_array), \
        .info = snd_soc_info_volsw_2r, \
-       .get = twl6040_get_volsw_2r, .put = twl6040_put_volsw_2r_vu, \
+       .get = twl6040_get_volsw, .put = twl6040_put_volsw, \
        .private_value = (unsigned long)&(struct soc_mixer_control) \
                {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
                 .rshift = xshift, .max = xmax, .invert = xinvert}, }
@@ -1035,8 +932,14 @@ static const struct snd_kcontrol_new hfl_mux_controls =
 static const struct snd_kcontrol_new hfr_mux_controls =
        SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
 
-static const struct snd_kcontrol_new ep_driver_switch_controls =
-       SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
+static const struct snd_kcontrol_new ep_path_enable_control =
+       SOC_DAPM_SINGLE("Switch", TWL6040_REG_SW_SHADOW, 0, 1, 0);
+
+static const struct snd_kcontrol_new auxl_switch_control =
+       SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0);
+
+static const struct snd_kcontrol_new auxr_switch_control =
+       SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0);
 
 /* Headset power mode */
 static const char *twl6040_power_mode_texts[] = {
@@ -1105,6 +1008,15 @@ int twl6040_get_clk_id(struct snd_soc_codec *codec)
 }
 EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
 
+int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
+{
+       if (unlikely(trim >= TWL6040_TRIM_INVAL))
+               return -EINVAL;
+
+       return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim);
+}
+EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
+
 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
        /* Capture gains */
        SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1146,6 +1058,8 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("HFL"),
        SND_SOC_DAPM_OUTPUT("HFR"),
        SND_SOC_DAPM_OUTPUT("EP"),
+       SND_SOC_DAPM_OUTPUT("AUXL"),
+       SND_SOC_DAPM_OUTPUT("AUXR"),
 
        /* Analog input muxes for the capture amplifiers */
        SND_SOC_DAPM_MUX("Analog Left Capture Route",
@@ -1199,42 +1113,49 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
                        twl6040_power_mode_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
-       SND_SOC_DAPM_MUX("HF Left Playback",
+       SND_SOC_DAPM_MUX("Handsfree Left Playback",
                        SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
-       SND_SOC_DAPM_MUX("HF Right Playback",
+       SND_SOC_DAPM_MUX("Handsfree Right Playback",
                        SND_SOC_NOPM, 0, 0, &hfr_mux_controls),
        /* Analog playback Muxes */
-       SND_SOC_DAPM_MUX("HS Left Playback",
+       SND_SOC_DAPM_MUX("Headset Left Playback",
                        SND_SOC_NOPM, 0, 0, &hsl_mux_controls),
-       SND_SOC_DAPM_MUX("HS Right Playback",
+       SND_SOC_DAPM_MUX("Headset Right Playback",
                        SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
 
+       SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
+                       &ep_path_enable_control),
+       SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0,
+                       &auxl_switch_control),
+       SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0,
+                       &auxr_switch_control),
+
        /* Analog playback drivers */
-       SND_SOC_DAPM_OUT_DRV_E("Handsfree Left Driver",
+       SND_SOC_DAPM_OUT_DRV_E("HF Left Driver",
                        TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
-                       pga_event,
+                       out_drv_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("Handsfree Right Driver",
+       SND_SOC_DAPM_OUT_DRV_E("HF Right Driver",
                        TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
-                       pga_event,
+                       out_drv_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("Headset Left Driver",
+       SND_SOC_DAPM_OUT_DRV_E("HS Left Driver",
                        TWL6040_REG_HSLCTL, 2, 0, NULL, 0,
-                       pga_event,
+                       out_drv_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("Headset Right Driver",
+       SND_SOC_DAPM_OUT_DRV_E("HS Right Driver",
                        TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
-                       pga_event,
+                       out_drv_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_SWITCH_E("Earphone Driver",
-                       SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
+       SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
+                       TWL6040_REG_EARCTL, 0, 0, NULL, 0,
                        twl6040_power_mode_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
        /* Analog playback PGAs */
-       SND_SOC_DAPM_PGA("HFDAC Left PGA",
+       SND_SOC_DAPM_PGA("HF Left PGA",
                        TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("HFDAC Right PGA",
+       SND_SOC_DAPM_PGA("HF Right PGA",
                        TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
 
 };
@@ -1256,39 +1177,46 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"ADC Right", NULL, "MicAmpR"},
 
        /* AFM path */
-       {"AFMAmpL", "NULL", "AFML"},
-       {"AFMAmpR", "NULL", "AFMR"},
+       {"AFMAmpL", NULL, "AFML"},
+       {"AFMAmpR", NULL, "AFMR"},
 
-       {"HS Left Playback", "HS DAC", "HSDAC Left"},
-       {"HS Left Playback", "Line-In amp", "AFMAmpL"},
+       {"Headset Left Playback", "HS DAC", "HSDAC Left"},
+       {"Headset Left Playback", "Line-In amp", "AFMAmpL"},
 
-       {"HS Right Playback", "HS DAC", "HSDAC Right"},
-       {"HS Right Playback", "Line-In amp", "AFMAmpR"},
+       {"Headset Right Playback", "HS DAC", "HSDAC Right"},
+       {"Headset Right Playback", "Line-In amp", "AFMAmpR"},
 
-       {"Headset Left Driver", "NULL", "HS Left Playback"},
-       {"Headset Right Driver", "NULL", "HS Right Playback"},
+       {"HS Left Driver", NULL, "Headset Left Playback"},
+       {"HS Right Driver", NULL, "Headset Right Playback"},
 
-       {"HSOL", NULL, "Headset Left Driver"},
-       {"HSOR", NULL, "Headset Right Driver"},
+       {"HSOL", NULL, "HS Left Driver"},
+       {"HSOR", NULL, "HS Right Driver"},
 
        /* Earphone playback path */
-       {"Earphone Driver", "Switch", "HSDAC Left"},
+       {"Earphone Playback", "Switch", "HSDAC Left"},
+       {"Earphone Driver", NULL, "Earphone Playback"},
        {"EP", NULL, "Earphone Driver"},
 
-       {"HF Left Playback", "HF DAC", "HFDAC Left"},
-       {"HF Left Playback", "Line-In amp", "AFMAmpL"},
+       {"Handsfree Left Playback", "HF DAC", "HFDAC Left"},
+       {"Handsfree Left Playback", "Line-In amp", "AFMAmpL"},
+
+       {"Handsfree Right Playback", "HF DAC", "HFDAC Right"},
+       {"Handsfree Right Playback", "Line-In amp", "AFMAmpR"},
 
-       {"HF Right Playback", "HF DAC", "HFDAC Right"},
-       {"HF Right Playback", "Line-In amp", "AFMAmpR"},
+       {"HF Left PGA", NULL, "Handsfree Left Playback"},
+       {"HF Right PGA", NULL, "Handsfree Right Playback"},
 
-       {"HFDAC Left PGA", NULL, "HF Left Playback"},
-       {"HFDAC Right PGA", NULL, "HF Right Playback"},
+       {"HF Left Driver", NULL, "HF Left PGA"},
+       {"HF Right Driver", NULL, "HF Right PGA"},
 
-       {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
-       {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
+       {"HFL", NULL, "HF Left Driver"},
+       {"HFR", NULL, "HF Right Driver"},
 
-       {"HFL", NULL, "Handsfree Left Driver"},
-       {"HFR", NULL, "Handsfree Right Driver"},
+       {"AUXL Playback", "Switch", "HF Left PGA"},
+       {"AUXR Playback", "Switch", "HF Right PGA"},
+
+       {"AUXL", NULL, "AUXL Playback"},
+       {"AUXR", NULL, "AUXR Playback"},
 };
 
 static int twl6040_add_widgets(struct snd_soc_codec *codec)
@@ -1325,8 +1253,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
 
                priv->codec_powered = 1;
 
-               /* initialize vdd/vss registers with reg_cache */
-               twl6040_init_vdd_regs(codec);
+               twl6040_restore_regs(codec);
 
                /* Set external boost GPO */
                twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
@@ -1464,11 +1391,11 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
 
 static struct snd_soc_dai_driver twl6040_dai[] = {
 {
-       .name = "twl6040-hifi",
+       .name = "twl6040-legacy",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
-               .channels_max = 2,
+               .channels_max = 5,
                .rates = TWL6040_RATES,
                .formats = TWL6040_FORMATS,
        },
@@ -1518,8 +1445,8 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
        .name = "twl6040-vib",
        .playback = {
                .stream_name = "Vibra Playback",
-               .channels_min = 2,
-               .channels_max = 2,
+               .channels_min = 1,
+               .channels_max = 1,
                .rates = SNDRV_PCM_RATE_CONTINUOUS,
                .formats = TWL6040_FORMATS,
        },
@@ -1586,33 +1513,21 @@ static int twl6040_probe(struct snd_soc_codec *codec)
                goto work_err;
        }
 
-       priv->workqueue = create_singlethread_workqueue("twl6040-codec");
+       priv->workqueue = alloc_workqueue("twl6040-codec", 0, 0);
        if (!priv->workqueue) {
                ret = -ENOMEM;
                goto work_err;
        }
 
-       INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
+       INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
+       INIT_DELAYED_WORK(&priv->headset.work, twl6040_pga_hs_work);
+       INIT_DELAYED_WORK(&priv->handsfree.work, twl6040_pga_hf_work);
 
        mutex_init(&priv->mutex);
 
        init_completion(&priv->headset.ramp_done);
        init_completion(&priv->handsfree.ramp_done);
 
-       priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
-       if (priv->hf_workqueue == NULL) {
-               ret = -ENOMEM;
-               goto hfwq_err;
-       }
-       priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
-       if (priv->hs_workqueue == NULL) {
-               ret = -ENOMEM;
-               goto hswq_err;
-       }
-
-       INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
-       INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
-
        ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler,
                                   0, "twl6040_irq_plug", codec);
        if (ret) {
@@ -1620,8 +1535,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
                goto plugirq_err;
        }
 
-       /* init vio registers */
-       twl6040_init_vio_regs(codec);
+       twl6040_init_chip(codec);
 
        /* power on device */
        ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1637,10 +1551,6 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 bias_err:
        free_irq(priv->plug_irq, codec);
 plugirq_err:
-       destroy_workqueue(priv->hs_workqueue);
-hswq_err:
-       destroy_workqueue(priv->hf_workqueue);
-hfwq_err:
        destroy_workqueue(priv->workqueue);
 work_err:
        kfree(priv);
@@ -1654,8 +1564,6 @@ static int twl6040_remove(struct snd_soc_codec *codec)
        twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
        free_irq(priv->plug_irq, codec);
        destroy_workqueue(priv->workqueue);
-       destroy_workqueue(priv->hf_workqueue);
-       destroy_workqueue(priv->hs_workqueue);
        kfree(priv);
 
        return 0;
index d8de67869dd9340c31f040a755d8dae1d8591278..a83277bdb851129c5fb7a3db84e11e42d50dab0e 100644 (file)
 #ifndef __TWL6040_H__
 #define __TWL6040_H__
 
+enum twl6040_trim {
+       TWL6040_TRIM_TRIM1 = 0,
+       TWL6040_TRIM_TRIM2,
+       TWL6040_TRIM_TRIM3,
+       TWL6040_TRIM_HSOTRIM,
+       TWL6040_TRIM_HFOTRIM,
+       TWL6040_TRIM_INVAL,
+};
+
+#define TWL6040_HSF_TRIM_LEFT(x)       (x & 0x0f)
+#define TWL6040_HSF_TRIM_RIGHT(x)      ((x >> 4) & 0x0f)
+
 void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
                            struct snd_soc_jack *jack, int report);
 int twl6040_get_clk_id(struct snd_soc_codec *codec);
+int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim);
 
 #endif /* End of __TWL6040_H__ */
index 5836201834d97dcc769347ab98827841fce013ca..9fa14299cf2c1c4079fe5860f4b3ca793a3f4a1b 100644 (file)
@@ -462,7 +462,6 @@ static int wl1273_probe(struct snd_soc_codec *codec)
        wl1273->core = *core;
 
        snd_soc_codec_set_drvdata(codec, wl1273);
-       mutex_init(&codec->mutex);
 
        r = snd_soc_add_controls(codec, wl1273_controls,
                                 ARRAY_SIZE(wl1273_controls));
index bcc208967917f149956985e7c8f5c290a1506aad..cd0ec0fd1dbab536579b296884275cc14828326a 100644 (file)
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
 
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/wm1250-ev1.h>
+
+static const char *wm1250_gpio_names[WM1250_EV1_NUM_GPIOS] = {
+       "WM1250 CLK_ENA",
+       "WM1250 CLK_SEL0",
+       "WM1250 CLK_SEL1",
+       "WM1250 OSR",
+       "WM1250 MASTER",
+};
+
+struct wm1250_priv {
+       struct gpio gpios[WM1250_EV1_NUM_GPIOS];
+};
+
+static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec,
+                                    enum snd_soc_bias_level level)
+{
+       struct wm1250_priv *wm1250 = dev_get_drvdata(codec->dev);
+       int ena;
+
+       if (wm1250)
+               ena = wm1250->gpios[WM1250_EV1_GPIO_CLK_ENA].gpio;
+       else
+               ena = -1;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (ena >= 0)
+                       gpio_set_value_cansleep(ena, 1);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               if (ena >= 0)
+                       gpio_set_value_cansleep(ena, 0);
+               break;
+       }
+
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
 
 static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = {
 SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0),
@@ -53,18 +102,103 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
        .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets),
        .dapm_routes = wm1250_ev1_dapm_routes,
        .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes),
+
+       .set_bias_level = wm1250_ev1_set_bias_level,
+       .idle_bias_off = true,
 };
 
+static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
+{
+       struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
+       struct wm1250_priv *wm1250;
+       int i, ret;
+
+       if (!pdata)
+               return 0;
+
+       wm1250 = kzalloc(sizeof(*wm1250), GFP_KERNEL);
+       if (!wm1250) {
+               dev_err(&i2c->dev, "Unable to allocate private data\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm1250->gpios); i++) {
+               wm1250->gpios[i].gpio = pdata->gpios[i];
+               wm1250->gpios[i].label = wm1250_gpio_names[i];
+               wm1250->gpios[i].flags = GPIOF_OUT_INIT_LOW;
+       }
+       wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].flags = GPIOF_OUT_INIT_HIGH;
+       wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].flags = GPIOF_OUT_INIT_HIGH;
+
+       ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret);
+               goto err_alloc;
+       }
+
+       dev_set_drvdata(&i2c->dev, wm1250);
+
+       return ret;
+
+err_alloc:
+       kfree(wm1250);
+err:
+       return ret;
+}
+
+static void wm1250_ev1_free(struct i2c_client *i2c)
+{
+       struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev);
+
+       if (wm1250) {
+               gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+               kfree(wm1250);
+       }
+}
+
 static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+                                     const struct i2c_device_id *i2c_id)
 {
-       return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
-                                     &wm1250_ev1_dai, 1);
+       int id, board, rev, ret;
+
+       dev_set_drvdata(&i2c->dev, NULL);
+
+       board = i2c_smbus_read_byte_data(i2c, 0);
+       if (board < 0) {
+               dev_err(&i2c->dev, "Failed to read ID: %d\n", board);
+               return board;
+       }
+
+       id = (board & 0xfe) >> 2;
+       rev = board & 0x3;
+
+       if (id != 1) {
+               dev_err(&i2c->dev, "Unknown board ID %d\n", id);
+               return -ENODEV;
+       }
+
+       dev_info(&i2c->dev, "revision %d\n", rev + 1);
+
+       ret = wm1250_ev1_pdata(i2c);
+       if (ret != 0)
+               return ret;
+
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
+                                    &wm1250_ev1_dai, 1);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               wm1250_ev1_free(i2c);
+               return ret;
+       }
+
+       return 0;
 }
 
 static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
 {
        snd_soc_unregister_codec(&i2c->dev);
+       wm1250_ev1_free(i2c);
 
        return 0;
 }
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c
new file mode 100644 (file)
index 0000000..960617b
--- /dev/null
@@ -0,0 +1,1530 @@
+/*
+ * wm5100-tables.c  --  WM5100 ALSA SoC Audio driver data
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wm5100.h"
+
+int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+{
+       switch (reg) {
+       case WM5100_SOFTWARE_RESET:
+       case WM5100_DEVICE_REVISION:
+       case WM5100_FX_CTRL:
+       case WM5100_INTERRUPT_STATUS_1:
+       case WM5100_INTERRUPT_STATUS_2:
+       case WM5100_INTERRUPT_STATUS_3:
+       case WM5100_INTERRUPT_STATUS_4:
+       case WM5100_INTERRUPT_RAW_STATUS_2:
+       case WM5100_INTERRUPT_RAW_STATUS_3:
+       case WM5100_INTERRUPT_RAW_STATUS_4:
+       case WM5100_OUTPUT_STATUS_1:
+       case WM5100_OUTPUT_STATUS_2:
+       case WM5100_INPUT_ENABLES_STATUS:
+       case WM5100_MIC_DETECT_3:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg)
+{
+       switch (reg) {
+       case WM5100_SOFTWARE_RESET:
+       case WM5100_DEVICE_REVISION:
+       case WM5100_CTRL_IF_1:
+       case WM5100_TONE_GENERATOR_1:
+       case WM5100_PWM_DRIVE_1:
+       case WM5100_PWM_DRIVE_2:
+       case WM5100_PWM_DRIVE_3:
+       case WM5100_CLOCKING_1:
+       case WM5100_CLOCKING_3:
+       case WM5100_CLOCKING_4:
+       case WM5100_CLOCKING_5:
+       case WM5100_CLOCKING_6:
+       case WM5100_CLOCKING_7:
+       case WM5100_CLOCKING_8:
+       case WM5100_ASRC_ENABLE:
+       case WM5100_ASRC_STATUS:
+       case WM5100_ASRC_RATE1:
+       case WM5100_ISRC_1_CTRL_1:
+       case WM5100_ISRC_1_CTRL_2:
+       case WM5100_ISRC_2_CTRL1:
+       case WM5100_ISRC_2_CTRL_2:
+       case WM5100_FLL1_CONTROL_1:
+       case WM5100_FLL1_CONTROL_2:
+       case WM5100_FLL1_CONTROL_3:
+       case WM5100_FLL1_CONTROL_5:
+       case WM5100_FLL1_CONTROL_6:
+       case WM5100_FLL1_EFS_1:
+       case WM5100_FLL2_CONTROL_1:
+       case WM5100_FLL2_CONTROL_2:
+       case WM5100_FLL2_CONTROL_3:
+       case WM5100_FLL2_CONTROL_5:
+       case WM5100_FLL2_CONTROL_6:
+       case WM5100_FLL2_EFS_1:
+       case WM5100_MIC_CHARGE_PUMP_1:
+       case WM5100_MIC_CHARGE_PUMP_2:
+       case WM5100_HP_CHARGE_PUMP_1:
+       case WM5100_LDO1_CONTROL:
+       case WM5100_MIC_BIAS_CTRL_1:
+       case WM5100_MIC_BIAS_CTRL_2:
+       case WM5100_MIC_BIAS_CTRL_3:
+       case WM5100_ACCESSORY_DETECT_MODE_1:
+       case WM5100_HEADPHONE_DETECT_1:
+       case WM5100_HEADPHONE_DETECT_2:
+       case WM5100_MIC_DETECT_1:
+       case WM5100_MIC_DETECT_2:
+       case WM5100_MIC_DETECT_3:
+       case WM5100_INPUT_ENABLES:
+       case WM5100_INPUT_ENABLES_STATUS:
+       case WM5100_IN1L_CONTROL:
+       case WM5100_IN1R_CONTROL:
+       case WM5100_IN2L_CONTROL:
+       case WM5100_IN2R_CONTROL:
+       case WM5100_IN3L_CONTROL:
+       case WM5100_IN3R_CONTROL:
+       case WM5100_IN4L_CONTROL:
+       case WM5100_IN4R_CONTROL:
+       case WM5100_RXANC_SRC:
+       case WM5100_INPUT_VOLUME_RAMP:
+       case WM5100_ADC_DIGITAL_VOLUME_1L:
+       case WM5100_ADC_DIGITAL_VOLUME_1R:
+       case WM5100_ADC_DIGITAL_VOLUME_2L:
+       case WM5100_ADC_DIGITAL_VOLUME_2R:
+       case WM5100_ADC_DIGITAL_VOLUME_3L:
+       case WM5100_ADC_DIGITAL_VOLUME_3R:
+       case WM5100_ADC_DIGITAL_VOLUME_4L:
+       case WM5100_ADC_DIGITAL_VOLUME_4R:
+       case WM5100_OUTPUT_ENABLES_2:
+       case WM5100_OUTPUT_STATUS_1:
+       case WM5100_OUTPUT_STATUS_2:
+       case WM5100_CHANNEL_ENABLES_1:
+       case WM5100_OUT_VOLUME_1L:
+       case WM5100_OUT_VOLUME_1R:
+       case WM5100_DAC_VOLUME_LIMIT_1L:
+       case WM5100_DAC_VOLUME_LIMIT_1R:
+       case WM5100_OUT_VOLUME_2L:
+       case WM5100_OUT_VOLUME_2R:
+       case WM5100_DAC_VOLUME_LIMIT_2L:
+       case WM5100_DAC_VOLUME_LIMIT_2R:
+       case WM5100_OUT_VOLUME_3L:
+       case WM5100_OUT_VOLUME_3R:
+       case WM5100_DAC_VOLUME_LIMIT_3L:
+       case WM5100_DAC_VOLUME_LIMIT_3R:
+       case WM5100_OUT_VOLUME_4L:
+       case WM5100_OUT_VOLUME_4R:
+       case WM5100_DAC_VOLUME_LIMIT_5L:
+       case WM5100_DAC_VOLUME_LIMIT_5R:
+       case WM5100_DAC_VOLUME_LIMIT_6L:
+       case WM5100_DAC_VOLUME_LIMIT_6R:
+       case WM5100_DAC_AEC_CONTROL_1:
+       case WM5100_OUTPUT_VOLUME_RAMP:
+       case WM5100_DAC_DIGITAL_VOLUME_1L:
+       case WM5100_DAC_DIGITAL_VOLUME_1R:
+       case WM5100_DAC_DIGITAL_VOLUME_2L:
+       case WM5100_DAC_DIGITAL_VOLUME_2R:
+       case WM5100_DAC_DIGITAL_VOLUME_3L:
+       case WM5100_DAC_DIGITAL_VOLUME_3R:
+       case WM5100_DAC_DIGITAL_VOLUME_4L:
+       case WM5100_DAC_DIGITAL_VOLUME_4R:
+       case WM5100_DAC_DIGITAL_VOLUME_5L:
+       case WM5100_DAC_DIGITAL_VOLUME_5R:
+       case WM5100_DAC_DIGITAL_VOLUME_6L:
+       case WM5100_DAC_DIGITAL_VOLUME_6R:
+       case WM5100_PDM_SPK1_CTRL_1:
+       case WM5100_PDM_SPK1_CTRL_2:
+       case WM5100_PDM_SPK2_CTRL_1:
+       case WM5100_PDM_SPK2_CTRL_2:
+       case WM5100_AUDIO_IF_1_1:
+       case WM5100_AUDIO_IF_1_2:
+       case WM5100_AUDIO_IF_1_3:
+       case WM5100_AUDIO_IF_1_4:
+       case WM5100_AUDIO_IF_1_5:
+       case WM5100_AUDIO_IF_1_6:
+       case WM5100_AUDIO_IF_1_7:
+       case WM5100_AUDIO_IF_1_8:
+       case WM5100_AUDIO_IF_1_9:
+       case WM5100_AUDIO_IF_1_10:
+       case WM5100_AUDIO_IF_1_11:
+       case WM5100_AUDIO_IF_1_12:
+       case WM5100_AUDIO_IF_1_13:
+       case WM5100_AUDIO_IF_1_14:
+       case WM5100_AUDIO_IF_1_15:
+       case WM5100_AUDIO_IF_1_16:
+       case WM5100_AUDIO_IF_1_17:
+       case WM5100_AUDIO_IF_1_18:
+       case WM5100_AUDIO_IF_1_19:
+       case WM5100_AUDIO_IF_1_20:
+       case WM5100_AUDIO_IF_1_21:
+       case WM5100_AUDIO_IF_1_22:
+       case WM5100_AUDIO_IF_1_23:
+       case WM5100_AUDIO_IF_1_24:
+       case WM5100_AUDIO_IF_1_25:
+       case WM5100_AUDIO_IF_1_26:
+       case WM5100_AUDIO_IF_1_27:
+       case WM5100_AUDIO_IF_2_1:
+       case WM5100_AUDIO_IF_2_2:
+       case WM5100_AUDIO_IF_2_3:
+       case WM5100_AUDIO_IF_2_4:
+       case WM5100_AUDIO_IF_2_5:
+       case WM5100_AUDIO_IF_2_6:
+       case WM5100_AUDIO_IF_2_7:
+       case WM5100_AUDIO_IF_2_8:
+       case WM5100_AUDIO_IF_2_9:
+       case WM5100_AUDIO_IF_2_10:
+       case WM5100_AUDIO_IF_2_11:
+       case WM5100_AUDIO_IF_2_18:
+       case WM5100_AUDIO_IF_2_19:
+       case WM5100_AUDIO_IF_2_26:
+       case WM5100_AUDIO_IF_2_27:
+       case WM5100_AUDIO_IF_3_1:
+       case WM5100_AUDIO_IF_3_2:
+       case WM5100_AUDIO_IF_3_3:
+       case WM5100_AUDIO_IF_3_4:
+       case WM5100_AUDIO_IF_3_5:
+       case WM5100_AUDIO_IF_3_6:
+       case WM5100_AUDIO_IF_3_7:
+       case WM5100_AUDIO_IF_3_8:
+       case WM5100_AUDIO_IF_3_9:
+       case WM5100_AUDIO_IF_3_10:
+       case WM5100_AUDIO_IF_3_11:
+       case WM5100_AUDIO_IF_3_18:
+       case WM5100_AUDIO_IF_3_19:
+       case WM5100_AUDIO_IF_3_26:
+       case WM5100_AUDIO_IF_3_27:
+       case WM5100_PWM1MIX_INPUT_1_SOURCE:
+       case WM5100_PWM1MIX_INPUT_1_VOLUME:
+       case WM5100_PWM1MIX_INPUT_2_SOURCE:
+       case WM5100_PWM1MIX_INPUT_2_VOLUME:
+       case WM5100_PWM1MIX_INPUT_3_SOURCE:
+       case WM5100_PWM1MIX_INPUT_3_VOLUME:
+       case WM5100_PWM1MIX_INPUT_4_SOURCE:
+       case WM5100_PWM1MIX_INPUT_4_VOLUME:
+       case WM5100_PWM2MIX_INPUT_1_SOURCE:
+       case WM5100_PWM2MIX_INPUT_1_VOLUME:
+       case WM5100_PWM2MIX_INPUT_2_SOURCE:
+       case WM5100_PWM2MIX_INPUT_2_VOLUME:
+       case WM5100_PWM2MIX_INPUT_3_SOURCE:
+       case WM5100_PWM2MIX_INPUT_3_VOLUME:
+       case WM5100_PWM2MIX_INPUT_4_SOURCE:
+       case WM5100_PWM2MIX_INPUT_4_VOLUME:
+       case WM5100_OUT1LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT1LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT1LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT1LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT1LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT1LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT1LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT1LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT1RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT1RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT1RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT1RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT1RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT1RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT1RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT1RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT2LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT2LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT2LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT2LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT2LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT2LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT2LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT2LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT2RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT2RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT2RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT2RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT2RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT2RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT2RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT2RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT3LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT3LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT3LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT3LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT3LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT3LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT3LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT3LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT3RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT3RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT3RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT3RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT3RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT3RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT3RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT3RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT4LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT4LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT4LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT4LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT4LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT4LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT4LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT4LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT4RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT4RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT4RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT4RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT4RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT4RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT4RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT4RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT5LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT5LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT5LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT5LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT5LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT5LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT5LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT5LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT5RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT5RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT5RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT5RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT5RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT5RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT5RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT5RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT6LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT6LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT6LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT6LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT6LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT6LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT6LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT6LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT6RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT6RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT6RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT6RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT6RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT6RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT6RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT6RMIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX1MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX1MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX1MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX1MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX1MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX1MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX1MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX1MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX2MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX2MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX2MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX2MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX2MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX2MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX2MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX2MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX3MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX3MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX3MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX3MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX3MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX3MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX3MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX3MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX4MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX4MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX4MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX4MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX4MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX4MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX4MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX4MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX5MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX5MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX5MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX5MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX5MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX5MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX5MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX5MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX6MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX6MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX6MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX6MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX6MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX6MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX6MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX6MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX7MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX7MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX7MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX7MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX7MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX7MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX7MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX7MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX8MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX8MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX8MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX8MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX8MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX8MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX8MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX8MIX_INPUT_4_VOLUME:
+       case WM5100_AIF2TX1MIX_INPUT_1_SOURCE:
+       case WM5100_AIF2TX1MIX_INPUT_1_VOLUME:
+       case WM5100_AIF2TX1MIX_INPUT_2_SOURCE:
+       case WM5100_AIF2TX1MIX_INPUT_2_VOLUME:
+       case WM5100_AIF2TX1MIX_INPUT_3_SOURCE:
+       case WM5100_AIF2TX1MIX_INPUT_3_VOLUME:
+       case WM5100_AIF2TX1MIX_INPUT_4_SOURCE:
+       case WM5100_AIF2TX1MIX_INPUT_4_VOLUME:
+       case WM5100_AIF2TX2MIX_INPUT_1_SOURCE:
+       case WM5100_AIF2TX2MIX_INPUT_1_VOLUME:
+       case WM5100_AIF2TX2MIX_INPUT_2_SOURCE:
+       case WM5100_AIF2TX2MIX_INPUT_2_VOLUME:
+       case WM5100_AIF2TX2MIX_INPUT_3_SOURCE:
+       case WM5100_AIF2TX2MIX_INPUT_3_VOLUME:
+       case WM5100_AIF2TX2MIX_INPUT_4_SOURCE:
+       case WM5100_AIF2TX2MIX_INPUT_4_VOLUME:
+       case WM5100_AIF3TX1MIX_INPUT_1_SOURCE:
+       case WM5100_AIF3TX1MIX_INPUT_1_VOLUME:
+       case WM5100_AIF3TX1MIX_INPUT_2_SOURCE:
+       case WM5100_AIF3TX1MIX_INPUT_2_VOLUME:
+       case WM5100_AIF3TX1MIX_INPUT_3_SOURCE:
+       case WM5100_AIF3TX1MIX_INPUT_3_VOLUME:
+       case WM5100_AIF3TX1MIX_INPUT_4_SOURCE:
+       case WM5100_AIF3TX1MIX_INPUT_4_VOLUME:
+       case WM5100_AIF3TX2MIX_INPUT_1_SOURCE:
+       case WM5100_AIF3TX2MIX_INPUT_1_VOLUME:
+       case WM5100_AIF3TX2MIX_INPUT_2_SOURCE:
+       case WM5100_AIF3TX2MIX_INPUT_2_VOLUME:
+       case WM5100_AIF3TX2MIX_INPUT_3_SOURCE:
+       case WM5100_AIF3TX2MIX_INPUT_3_VOLUME:
+       case WM5100_AIF3TX2MIX_INPUT_4_SOURCE:
+       case WM5100_AIF3TX2MIX_INPUT_4_VOLUME:
+       case WM5100_EQ1MIX_INPUT_1_SOURCE:
+       case WM5100_EQ1MIX_INPUT_1_VOLUME:
+       case WM5100_EQ1MIX_INPUT_2_SOURCE:
+       case WM5100_EQ1MIX_INPUT_2_VOLUME:
+       case WM5100_EQ1MIX_INPUT_3_SOURCE:
+       case WM5100_EQ1MIX_INPUT_3_VOLUME:
+       case WM5100_EQ1MIX_INPUT_4_SOURCE:
+       case WM5100_EQ1MIX_INPUT_4_VOLUME:
+       case WM5100_EQ2MIX_INPUT_1_SOURCE:
+       case WM5100_EQ2MIX_INPUT_1_VOLUME:
+       case WM5100_EQ2MIX_INPUT_2_SOURCE:
+       case WM5100_EQ2MIX_INPUT_2_VOLUME:
+       case WM5100_EQ2MIX_INPUT_3_SOURCE:
+       case WM5100_EQ2MIX_INPUT_3_VOLUME:
+       case WM5100_EQ2MIX_INPUT_4_SOURCE:
+       case WM5100_EQ2MIX_INPUT_4_VOLUME:
+       case WM5100_EQ3MIX_INPUT_1_SOURCE:
+       case WM5100_EQ3MIX_INPUT_1_VOLUME:
+       case WM5100_EQ3MIX_INPUT_2_SOURCE:
+       case WM5100_EQ3MIX_INPUT_2_VOLUME:
+       case WM5100_EQ3MIX_INPUT_3_SOURCE:
+       case WM5100_EQ3MIX_INPUT_3_VOLUME:
+       case WM5100_EQ3MIX_INPUT_4_SOURCE:
+       case WM5100_EQ3MIX_INPUT_4_VOLUME:
+       case WM5100_EQ4MIX_INPUT_1_SOURCE:
+       case WM5100_EQ4MIX_INPUT_1_VOLUME:
+       case WM5100_EQ4MIX_INPUT_2_SOURCE:
+       case WM5100_EQ4MIX_INPUT_2_VOLUME:
+       case WM5100_EQ4MIX_INPUT_3_SOURCE:
+       case WM5100_EQ4MIX_INPUT_3_VOLUME:
+       case WM5100_EQ4MIX_INPUT_4_SOURCE:
+       case WM5100_EQ4MIX_INPUT_4_VOLUME:
+       case WM5100_DRC1LMIX_INPUT_1_SOURCE:
+       case WM5100_DRC1LMIX_INPUT_1_VOLUME:
+       case WM5100_DRC1LMIX_INPUT_2_SOURCE:
+       case WM5100_DRC1LMIX_INPUT_2_VOLUME:
+       case WM5100_DRC1LMIX_INPUT_3_SOURCE:
+       case WM5100_DRC1LMIX_INPUT_3_VOLUME:
+       case WM5100_DRC1LMIX_INPUT_4_SOURCE:
+       case WM5100_DRC1LMIX_INPUT_4_VOLUME:
+       case WM5100_DRC1RMIX_INPUT_1_SOURCE:
+       case WM5100_DRC1RMIX_INPUT_1_VOLUME:
+       case WM5100_DRC1RMIX_INPUT_2_SOURCE:
+       case WM5100_DRC1RMIX_INPUT_2_VOLUME:
+       case WM5100_DRC1RMIX_INPUT_3_SOURCE:
+       case WM5100_DRC1RMIX_INPUT_3_VOLUME:
+       case WM5100_DRC1RMIX_INPUT_4_SOURCE:
+       case WM5100_DRC1RMIX_INPUT_4_VOLUME:
+       case WM5100_HPLP1MIX_INPUT_1_SOURCE:
+       case WM5100_HPLP1MIX_INPUT_1_VOLUME:
+       case WM5100_HPLP1MIX_INPUT_2_SOURCE:
+       case WM5100_HPLP1MIX_INPUT_2_VOLUME:
+       case WM5100_HPLP1MIX_INPUT_3_SOURCE:
+       case WM5100_HPLP1MIX_INPUT_3_VOLUME:
+       case WM5100_HPLP1MIX_INPUT_4_SOURCE:
+       case WM5100_HPLP1MIX_INPUT_4_VOLUME:
+       case WM5100_HPLP2MIX_INPUT_1_SOURCE:
+       case WM5100_HPLP2MIX_INPUT_1_VOLUME:
+       case WM5100_HPLP2MIX_INPUT_2_SOURCE:
+       case WM5100_HPLP2MIX_INPUT_2_VOLUME:
+       case WM5100_HPLP2MIX_INPUT_3_SOURCE:
+       case WM5100_HPLP2MIX_INPUT_3_VOLUME:
+       case WM5100_HPLP2MIX_INPUT_4_SOURCE:
+       case WM5100_HPLP2MIX_INPUT_4_VOLUME:
+       case WM5100_HPLP3MIX_INPUT_1_SOURCE:
+       case WM5100_HPLP3MIX_INPUT_1_VOLUME:
+       case WM5100_HPLP3MIX_INPUT_2_SOURCE:
+       case WM5100_HPLP3MIX_INPUT_2_VOLUME:
+       case WM5100_HPLP3MIX_INPUT_3_SOURCE:
+       case WM5100_HPLP3MIX_INPUT_3_VOLUME:
+       case WM5100_HPLP3MIX_INPUT_4_SOURCE:
+       case WM5100_HPLP3MIX_INPUT_4_VOLUME:
+       case WM5100_HPLP4MIX_INPUT_1_SOURCE:
+       case WM5100_HPLP4MIX_INPUT_1_VOLUME:
+       case WM5100_HPLP4MIX_INPUT_2_SOURCE:
+       case WM5100_HPLP4MIX_INPUT_2_VOLUME:
+       case WM5100_HPLP4MIX_INPUT_3_SOURCE:
+       case WM5100_HPLP4MIX_INPUT_3_VOLUME:
+       case WM5100_HPLP4MIX_INPUT_4_SOURCE:
+       case WM5100_HPLP4MIX_INPUT_4_VOLUME:
+       case WM5100_DSP1LMIX_INPUT_1_SOURCE:
+       case WM5100_DSP1LMIX_INPUT_1_VOLUME:
+       case WM5100_DSP1LMIX_INPUT_2_SOURCE:
+       case WM5100_DSP1LMIX_INPUT_2_VOLUME:
+       case WM5100_DSP1LMIX_INPUT_3_SOURCE:
+       case WM5100_DSP1LMIX_INPUT_3_VOLUME:
+       case WM5100_DSP1LMIX_INPUT_4_SOURCE:
+       case WM5100_DSP1LMIX_INPUT_4_VOLUME:
+       case WM5100_DSP1RMIX_INPUT_1_SOURCE:
+       case WM5100_DSP1RMIX_INPUT_1_VOLUME:
+       case WM5100_DSP1RMIX_INPUT_2_SOURCE:
+       case WM5100_DSP1RMIX_INPUT_2_VOLUME:
+       case WM5100_DSP1RMIX_INPUT_3_SOURCE:
+       case WM5100_DSP1RMIX_INPUT_3_VOLUME:
+       case WM5100_DSP1RMIX_INPUT_4_SOURCE:
+       case WM5100_DSP1RMIX_INPUT_4_VOLUME:
+       case WM5100_DSP1AUX1MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX2MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX3MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX4MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX5MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX6MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_1_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_1_VOLUME:
+       case WM5100_DSP2LMIX_INPUT_2_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_2_VOLUME:
+       case WM5100_DSP2LMIX_INPUT_3_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_3_VOLUME:
+       case WM5100_DSP2LMIX_INPUT_4_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_4_VOLUME:
+       case WM5100_DSP2RMIX_INPUT_1_SOURCE:
+       case WM5100_DSP2RMIX_INPUT_1_VOLUME:
+       case WM5100_DSP2RMIX_INPUT_2_SOURCE:
+       case WM5100_DSP2RMIX_INPUT_2_VOLUME:
+       case WM5100_DSP2RMIX_INPUT_3_SOURCE:
+       case WM5100_DSP2RMIX_INPUT_3_VOLUME:
+       case WM5100_DSP2RMIX_INPUT_4_SOURCE:
+       case WM5100_DSP2RMIX_INPUT_4_VOLUME:
+       case WM5100_DSP2AUX1MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX2MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX3MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX4MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX5MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX6MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_1_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_1_VOLUME:
+       case WM5100_DSP3LMIX_INPUT_2_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_2_VOLUME:
+       case WM5100_DSP3LMIX_INPUT_3_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_3_VOLUME:
+       case WM5100_DSP3LMIX_INPUT_4_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_4_VOLUME:
+       case WM5100_DSP3RMIX_INPUT_1_SOURCE:
+       case WM5100_DSP3RMIX_INPUT_1_VOLUME:
+       case WM5100_DSP3RMIX_INPUT_2_SOURCE:
+       case WM5100_DSP3RMIX_INPUT_2_VOLUME:
+       case WM5100_DSP3RMIX_INPUT_3_SOURCE:
+       case WM5100_DSP3RMIX_INPUT_3_VOLUME:
+       case WM5100_DSP3RMIX_INPUT_4_SOURCE:
+       case WM5100_DSP3RMIX_INPUT_4_VOLUME:
+       case WM5100_DSP3AUX1MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX2MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX3MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX4MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX5MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX6MIX_INPUT_1_SOURCE:
+       case WM5100_ASRC1LMIX_INPUT_1_SOURCE:
+       case WM5100_ASRC1RMIX_INPUT_1_SOURCE:
+       case WM5100_ASRC2LMIX_INPUT_1_SOURCE:
+       case WM5100_ASRC2RMIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1INT1MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1INT2MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1INT3MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1INT4MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2INT1MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2INT2MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2INT3MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2INT4MIX_INPUT_1_SOURCE:
+       case WM5100_GPIO_CTRL_1:
+       case WM5100_GPIO_CTRL_2:
+       case WM5100_GPIO_CTRL_3:
+       case WM5100_GPIO_CTRL_4:
+       case WM5100_GPIO_CTRL_5:
+       case WM5100_GPIO_CTRL_6:
+       case WM5100_MISC_PAD_CTRL_1:
+       case WM5100_MISC_PAD_CTRL_2:
+       case WM5100_MISC_PAD_CTRL_3:
+       case WM5100_MISC_PAD_CTRL_4:
+       case WM5100_MISC_PAD_CTRL_5:
+       case WM5100_MISC_GPIO_1:
+       case WM5100_INTERRUPT_STATUS_1:
+       case WM5100_INTERRUPT_STATUS_2:
+       case WM5100_INTERRUPT_STATUS_3:
+       case WM5100_INTERRUPT_STATUS_4:
+       case WM5100_INTERRUPT_RAW_STATUS_2:
+       case WM5100_INTERRUPT_RAW_STATUS_3:
+       case WM5100_INTERRUPT_RAW_STATUS_4:
+       case WM5100_INTERRUPT_STATUS_1_MASK:
+       case WM5100_INTERRUPT_STATUS_2_MASK:
+       case WM5100_INTERRUPT_STATUS_3_MASK:
+       case WM5100_INTERRUPT_STATUS_4_MASK:
+       case WM5100_INTERRUPT_CONTROL:
+       case WM5100_IRQ_DEBOUNCE_1:
+       case WM5100_IRQ_DEBOUNCE_2:
+       case WM5100_FX_CTRL:
+       case WM5100_EQ1_1:
+       case WM5100_EQ1_2:
+       case WM5100_EQ1_3:
+       case WM5100_EQ1_4:
+       case WM5100_EQ1_5:
+       case WM5100_EQ1_6:
+       case WM5100_EQ1_7:
+       case WM5100_EQ1_8:
+       case WM5100_EQ1_9:
+       case WM5100_EQ1_10:
+       case WM5100_EQ1_11:
+       case WM5100_EQ1_12:
+       case WM5100_EQ1_13:
+       case WM5100_EQ1_14:
+       case WM5100_EQ1_15:
+       case WM5100_EQ1_16:
+       case WM5100_EQ1_17:
+       case WM5100_EQ1_18:
+       case WM5100_EQ1_19:
+       case WM5100_EQ1_20:
+       case WM5100_EQ2_1:
+       case WM5100_EQ2_2:
+       case WM5100_EQ2_3:
+       case WM5100_EQ2_4:
+       case WM5100_EQ2_5:
+       case WM5100_EQ2_6:
+       case WM5100_EQ2_7:
+       case WM5100_EQ2_8:
+       case WM5100_EQ2_9:
+       case WM5100_EQ2_10:
+       case WM5100_EQ2_11:
+       case WM5100_EQ2_12:
+       case WM5100_EQ2_13:
+       case WM5100_EQ2_14:
+       case WM5100_EQ2_15:
+       case WM5100_EQ2_16:
+       case WM5100_EQ2_17:
+       case WM5100_EQ2_18:
+       case WM5100_EQ2_19:
+       case WM5100_EQ2_20:
+       case WM5100_EQ3_1:
+       case WM5100_EQ3_2:
+       case WM5100_EQ3_3:
+       case WM5100_EQ3_4:
+       case WM5100_EQ3_5:
+       case WM5100_EQ3_6:
+       case WM5100_EQ3_7:
+       case WM5100_EQ3_8:
+       case WM5100_EQ3_9:
+       case WM5100_EQ3_10:
+       case WM5100_EQ3_11:
+       case WM5100_EQ3_12:
+       case WM5100_EQ3_13:
+       case WM5100_EQ3_14:
+       case WM5100_EQ3_15:
+       case WM5100_EQ3_16:
+       case WM5100_EQ3_17:
+       case WM5100_EQ3_18:
+       case WM5100_EQ3_19:
+       case WM5100_EQ3_20:
+       case WM5100_EQ4_1:
+       case WM5100_EQ4_2:
+       case WM5100_EQ4_3:
+       case WM5100_EQ4_4:
+       case WM5100_EQ4_5:
+       case WM5100_EQ4_6:
+       case WM5100_EQ4_7:
+       case WM5100_EQ4_8:
+       case WM5100_EQ4_9:
+       case WM5100_EQ4_10:
+       case WM5100_EQ4_11:
+       case WM5100_EQ4_12:
+       case WM5100_EQ4_13:
+       case WM5100_EQ4_14:
+       case WM5100_EQ4_15:
+       case WM5100_EQ4_16:
+       case WM5100_EQ4_17:
+       case WM5100_EQ4_18:
+       case WM5100_EQ4_19:
+       case WM5100_EQ4_20:
+       case WM5100_DRC1_CTRL1:
+       case WM5100_DRC1_CTRL2:
+       case WM5100_DRC1_CTRL3:
+       case WM5100_DRC1_CTRL4:
+       case WM5100_DRC1_CTRL5:
+       case WM5100_HPLPF1_1:
+       case WM5100_HPLPF1_2:
+       case WM5100_HPLPF2_1:
+       case WM5100_HPLPF2_2:
+       case WM5100_HPLPF3_1:
+       case WM5100_HPLPF3_2:
+       case WM5100_HPLPF4_1:
+       case WM5100_HPLPF4_2:
+       case WM5100_DSP1_DM_0:
+       case WM5100_DSP1_DM_1:
+       case WM5100_DSP1_DM_2:
+       case WM5100_DSP1_DM_3:
+       case WM5100_DSP1_DM_508:
+       case WM5100_DSP1_DM_509:
+       case WM5100_DSP1_DM_510:
+       case WM5100_DSP1_DM_511:
+       case WM5100_DSP1_PM_0:
+       case WM5100_DSP1_PM_1:
+       case WM5100_DSP1_PM_2:
+       case WM5100_DSP1_PM_3:
+       case WM5100_DSP1_PM_4:
+       case WM5100_DSP1_PM_5:
+       case WM5100_DSP1_PM_1530:
+       case WM5100_DSP1_PM_1531:
+       case WM5100_DSP1_PM_1532:
+       case WM5100_DSP1_PM_1533:
+       case WM5100_DSP1_PM_1534:
+       case WM5100_DSP1_PM_1535:
+       case WM5100_DSP1_ZM_0:
+       case WM5100_DSP1_ZM_1:
+       case WM5100_DSP1_ZM_2:
+       case WM5100_DSP1_ZM_3:
+       case WM5100_DSP1_ZM_2044:
+       case WM5100_DSP1_ZM_2045:
+       case WM5100_DSP1_ZM_2046:
+       case WM5100_DSP1_ZM_2047:
+       case WM5100_DSP2_DM_0:
+       case WM5100_DSP2_DM_1:
+       case WM5100_DSP2_DM_2:
+       case WM5100_DSP2_DM_3:
+       case WM5100_DSP2_DM_508:
+       case WM5100_DSP2_DM_509:
+       case WM5100_DSP2_DM_510:
+       case WM5100_DSP2_DM_511:
+       case WM5100_DSP2_PM_0:
+       case WM5100_DSP2_PM_1:
+       case WM5100_DSP2_PM_2:
+       case WM5100_DSP2_PM_3:
+       case WM5100_DSP2_PM_4:
+       case WM5100_DSP2_PM_5:
+       case WM5100_DSP2_PM_1530:
+       case WM5100_DSP2_PM_1531:
+       case WM5100_DSP2_PM_1532:
+       case WM5100_DSP2_PM_1533:
+       case WM5100_DSP2_PM_1534:
+       case WM5100_DSP2_PM_1535:
+       case WM5100_DSP2_ZM_0:
+       case WM5100_DSP2_ZM_1:
+       case WM5100_DSP2_ZM_2:
+       case WM5100_DSP2_ZM_3:
+       case WM5100_DSP2_ZM_2044:
+       case WM5100_DSP2_ZM_2045:
+       case WM5100_DSP2_ZM_2046:
+       case WM5100_DSP2_ZM_2047:
+       case WM5100_DSP3_DM_0:
+       case WM5100_DSP3_DM_1:
+       case WM5100_DSP3_DM_2:
+       case WM5100_DSP3_DM_3:
+       case WM5100_DSP3_DM_508:
+       case WM5100_DSP3_DM_509:
+       case WM5100_DSP3_DM_510:
+       case WM5100_DSP3_DM_511:
+       case WM5100_DSP3_PM_0:
+       case WM5100_DSP3_PM_1:
+       case WM5100_DSP3_PM_2:
+       case WM5100_DSP3_PM_3:
+       case WM5100_DSP3_PM_4:
+       case WM5100_DSP3_PM_5:
+       case WM5100_DSP3_PM_1530:
+       case WM5100_DSP3_PM_1531:
+       case WM5100_DSP3_PM_1532:
+       case WM5100_DSP3_PM_1533:
+       case WM5100_DSP3_PM_1534:
+       case WM5100_DSP3_PM_1535:
+       case WM5100_DSP3_ZM_0:
+       case WM5100_DSP3_ZM_1:
+       case WM5100_DSP3_ZM_2:
+       case WM5100_DSP3_ZM_3:
+       case WM5100_DSP3_ZM_2044:
+       case WM5100_DSP3_ZM_2045:
+       case WM5100_DSP3_ZM_2046:
+       case WM5100_DSP3_ZM_2047:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1] = {
+       [0x0000] = 0x0000,     /* R0     - software reset */
+       [0x0001] = 0x0000,     /* R1     - Device Revision */
+       [0x0010] = 0x0801,     /* R16    - Ctrl IF 1 */
+       [0x0020] = 0x0000,     /* R32    - Tone Generator 1 */
+       [0x0030] = 0x0000,     /* R48    - PWM Drive 1 */
+       [0x0031] = 0x0100,     /* R49    - PWM Drive 2 */
+       [0x0032] = 0x0100,     /* R50    - PWM Drive 3 */
+       [0x0101] = 0x0000,     /* R257   - Clocking 3 */
+       [0x0102] = 0x0011,     /* R258   - Clocking 4 */
+       [0x0103] = 0x0011,     /* R259   - Clocking 5 */
+       [0x0104] = 0x0011,     /* R260   - Clocking 6 */
+       [0x0107] = 0x0000,     /* R263   - Clocking 7 */
+       [0x0108] = 0x0000,     /* R264   - Clocking 8 */
+       [0x0120] = 0x0000,     /* R288   - ASRC_ENABLE */
+       [0x0121] = 0x0000,     /* R289   - ASRC_STATUS */
+       [0x0122] = 0x0000,     /* R290   - ASRC_RATE1 */
+       [0x0141] = 0x8000,     /* R321   - ISRC 1 CTRL 1 */
+       [0x0142] = 0x0000,     /* R322   - ISRC 1 CTRL 2 */
+       [0x0143] = 0x8000,     /* R323   - ISRC 2 CTRL1 */
+       [0x0144] = 0x0000,     /* R324   - ISRC 2 CTRL 2 */
+       [0x0182] = 0x0000,     /* R386   - FLL1 Control 1 */
+       [0x0183] = 0x0000,     /* R387   - FLL1 Control 2 */
+       [0x0184] = 0x0000,     /* R388   - FLL1 Control 3 */
+       [0x0186] = 0x0177,     /* R390   - FLL1 Control 5 */
+       [0x0187] = 0x0001,     /* R391   - FLL1 Control 6 */
+       [0x0188] = 0x0000,     /* R392   - FLL1 EFS 1 */
+       [0x01A2] = 0x0000,     /* R418   - FLL2 Control 1 */
+       [0x01A3] = 0x0000,     /* R419   - FLL2 Control 2 */
+       [0x01A4] = 0x0000,     /* R420   - FLL2 Control 3 */
+       [0x01A6] = 0x0177,     /* R422   - FLL2 Control 5 */
+       [0x01A7] = 0x0001,     /* R423   - FLL2 Control 6 */
+       [0x01A8] = 0x0000,     /* R424   - FLL2 EFS 1 */
+       [0x0200] = 0x0020,     /* R512   - Mic Charge Pump 1 */
+       [0x0201] = 0xB084,     /* R513   - Mic Charge Pump 2 */
+       [0x0202] = 0xBBDE,     /* R514   - HP Charge Pump 1 */
+       [0x0211] = 0x20D4,     /* R529   - LDO1 Control */
+       [0x0215] = 0x0062,     /* R533   - Mic Bias Ctrl 1 */
+       [0x0216] = 0x0062,     /* R534   - Mic Bias Ctrl 2 */
+       [0x0217] = 0x0062,     /* R535   - Mic Bias Ctrl 3 */
+       [0x0280] = 0x0004,     /* R640   - Accessory Detect Mode 1 */
+       [0x0288] = 0x0020,     /* R648   - Headphone Detect 1 */
+       [0x0289] = 0x0000,     /* R649   - Headphone Detect 2 */
+       [0x0290] = 0x1100,     /* R656   - Mic Detect 1 */
+       [0x0291] = 0x009F,     /* R657   - Mic Detect 2 */
+       [0x0292] = 0x0000,     /* R658   - Mic Detect 3 */
+       [0x0301] = 0x0000,     /* R769   - Input Enables */
+       [0x0302] = 0x0000,     /* R770   - Input Enables Status */
+       [0x0310] = 0x2280,     /* R784   - Status */
+       [0x0311] = 0x0080,     /* R785   - IN1R Control */
+       [0x0312] = 0x2280,     /* R786   - IN2L Control */
+       [0x0313] = 0x0080,     /* R787   - IN2R Control */
+       [0x0314] = 0x2280,     /* R788   - IN3L Control */
+       [0x0315] = 0x0080,     /* R789   - IN3R Control */
+       [0x0316] = 0x2280,     /* R790   - IN4L Control */
+       [0x0317] = 0x0080,     /* R791   - IN4R Control */
+       [0x0318] = 0x0000,     /* R792   - RXANC_SRC */
+       [0x0319] = 0x0022,     /* R793   - Input Volume Ramp */
+       [0x0320] = 0x0180,     /* R800   - ADC Digital Volume 1L */
+       [0x0321] = 0x0180,     /* R801   - ADC Digital Volume 1R */
+       [0x0322] = 0x0180,     /* R802   - ADC Digital Volume 2L */
+       [0x0323] = 0x0180,     /* R803   - ADC Digital Volume 2R */
+       [0x0324] = 0x0180,     /* R804   - ADC Digital Volume 3L */
+       [0x0325] = 0x0180,     /* R805   - ADC Digital Volume 3R */
+       [0x0326] = 0x0180,     /* R806   - ADC Digital Volume 4L */
+       [0x0327] = 0x0180,     /* R807   - ADC Digital Volume 4R */
+       [0x0401] = 0x0000,     /* R1025  - Output Enables 2 */
+       [0x0402] = 0x0000,     /* R1026  - Output Status 1 */
+       [0x0403] = 0x0000,     /* R1027  - Output Status 2 */
+       [0x0408] = 0x0000,     /* R1032  - Channel Enables 1 */
+       [0x0410] = 0x0080,     /* R1040  - Out Volume 1L */
+       [0x0411] = 0x0080,     /* R1041  - Out Volume 1R */
+       [0x0412] = 0x0080,     /* R1042  - DAC Volume Limit 1L */
+       [0x0413] = 0x0080,     /* R1043  - DAC Volume Limit 1R */
+       [0x0414] = 0x0080,     /* R1044  - Out Volume 2L */
+       [0x0415] = 0x0080,     /* R1045  - Out Volume 2R */
+       [0x0416] = 0x0080,     /* R1046  - DAC Volume Limit 2L */
+       [0x0417] = 0x0080,     /* R1047  - DAC Volume Limit 2R */
+       [0x0418] = 0x0080,     /* R1048  - Out Volume 3L */
+       [0x0419] = 0x0080,     /* R1049  - Out Volume 3R */
+       [0x041A] = 0x0080,     /* R1050  - DAC Volume Limit 3L */
+       [0x041B] = 0x0080,     /* R1051  - DAC Volume Limit 3R */
+       [0x041C] = 0x0080,     /* R1052  - Out Volume 4L */
+       [0x041D] = 0x0080,     /* R1053  - Out Volume 4R */
+       [0x041E] = 0x0080,     /* R1054  - DAC Volume Limit 5L */
+       [0x041F] = 0x0080,     /* R1055  - DAC Volume Limit 5R */
+       [0x0420] = 0x0080,     /* R1056  - DAC Volume Limit 6L */
+       [0x0421] = 0x0080,     /* R1057  - DAC Volume Limit 6R */
+       [0x0440] = 0x0000,     /* R1088  - DAC AEC Control 1 */
+       [0x0441] = 0x0022,     /* R1089  - Output Volume Ramp */
+       [0x0480] = 0x0180,     /* R1152  - DAC Digital Volume 1L */
+       [0x0481] = 0x0180,     /* R1153  - DAC Digital Volume 1R */
+       [0x0482] = 0x0180,     /* R1154  - DAC Digital Volume 2L */
+       [0x0483] = 0x0180,     /* R1155  - DAC Digital Volume 2R */
+       [0x0484] = 0x0180,     /* R1156  - DAC Digital Volume 3L */
+       [0x0485] = 0x0180,     /* R1157  - DAC Digital Volume 3R */
+       [0x0486] = 0x0180,     /* R1158  - DAC Digital Volume 4L */
+       [0x0487] = 0x0180,     /* R1159  - DAC Digital Volume 4R */
+       [0x0488] = 0x0180,     /* R1160  - DAC Digital Volume 5L */
+       [0x0489] = 0x0180,     /* R1161  - DAC Digital Volume 5R */
+       [0x048A] = 0x0180,     /* R1162  - DAC Digital Volume 6L */
+       [0x048B] = 0x0180,     /* R1163  - DAC Digital Volume 6R */
+       [0x04C0] = 0x0069,     /* R1216  - PDM SPK1 CTRL 1 */
+       [0x04C1] = 0x0000,     /* R1217  - PDM SPK1 CTRL 2 */
+       [0x04C2] = 0x0069,     /* R1218  - PDM SPK2 CTRL 1 */
+       [0x04C3] = 0x0000,     /* R1219  - PDM SPK2 CTRL 2 */
+       [0x0500] = 0x000C,     /* R1280  - Audio IF 1_1 */
+       [0x0501] = 0x0008,     /* R1281  - Audio IF 1_2 */
+       [0x0502] = 0x0000,     /* R1282  - Audio IF 1_3 */
+       [0x0503] = 0x0000,     /* R1283  - Audio IF 1_4 */
+       [0x0504] = 0x0000,     /* R1284  - Audio IF 1_5 */
+       [0x0505] = 0x0300,     /* R1285  - Audio IF 1_6 */
+       [0x0506] = 0x0300,     /* R1286  - Audio IF 1_7 */
+       [0x0507] = 0x1820,     /* R1287  - Audio IF 1_8 */
+       [0x0508] = 0x1820,     /* R1288  - Audio IF 1_9 */
+       [0x0509] = 0x0000,     /* R1289  - Audio IF 1_10 */
+       [0x050A] = 0x0001,     /* R1290  - Audio IF 1_11 */
+       [0x050B] = 0x0002,     /* R1291  - Audio IF 1_12 */
+       [0x050C] = 0x0003,     /* R1292  - Audio IF 1_13 */
+       [0x050D] = 0x0004,     /* R1293  - Audio IF 1_14 */
+       [0x050E] = 0x0005,     /* R1294  - Audio IF 1_15 */
+       [0x050F] = 0x0006,     /* R1295  - Audio IF 1_16 */
+       [0x0510] = 0x0007,     /* R1296  - Audio IF 1_17 */
+       [0x0511] = 0x0000,     /* R1297  - Audio IF 1_18 */
+       [0x0512] = 0x0001,     /* R1298  - Audio IF 1_19 */
+       [0x0513] = 0x0002,     /* R1299  - Audio IF 1_20 */
+       [0x0514] = 0x0003,     /* R1300  - Audio IF 1_21 */
+       [0x0515] = 0x0004,     /* R1301  - Audio IF 1_22 */
+       [0x0516] = 0x0005,     /* R1302  - Audio IF 1_23 */
+       [0x0517] = 0x0006,     /* R1303  - Audio IF 1_24 */
+       [0x0518] = 0x0007,     /* R1304  - Audio IF 1_25 */
+       [0x0519] = 0x0000,     /* R1305  - Audio IF 1_26 */
+       [0x051A] = 0x0000,     /* R1306  - Audio IF 1_27 */
+       [0x0540] = 0x000C,     /* R1344  - Audio IF 2_1 */
+       [0x0541] = 0x0008,     /* R1345  - Audio IF 2_2 */
+       [0x0542] = 0x0000,     /* R1346  - Audio IF 2_3 */
+       [0x0543] = 0x0000,     /* R1347  - Audio IF 2_4 */
+       [0x0544] = 0x0000,     /* R1348  - Audio IF 2_5 */
+       [0x0545] = 0x0300,     /* R1349  - Audio IF 2_6 */
+       [0x0546] = 0x0300,     /* R1350  - Audio IF 2_7 */
+       [0x0547] = 0x1820,     /* R1351  - Audio IF 2_8 */
+       [0x0548] = 0x1820,     /* R1352  - Audio IF 2_9 */
+       [0x0549] = 0x0000,     /* R1353  - Audio IF 2_10 */
+       [0x054A] = 0x0001,     /* R1354  - Audio IF 2_11 */
+       [0x0551] = 0x0000,     /* R1361  - Audio IF 2_18 */
+       [0x0552] = 0x0001,     /* R1362  - Audio IF 2_19 */
+       [0x0559] = 0x0000,     /* R1369  - Audio IF 2_26 */
+       [0x055A] = 0x0000,     /* R1370  - Audio IF 2_27 */
+       [0x0580] = 0x000C,     /* R1408  - Audio IF 3_1 */
+       [0x0581] = 0x0008,     /* R1409  - Audio IF 3_2 */
+       [0x0582] = 0x0000,     /* R1410  - Audio IF 3_3 */
+       [0x0583] = 0x0000,     /* R1411  - Audio IF 3_4 */
+       [0x0584] = 0x0000,     /* R1412  - Audio IF 3_5 */
+       [0x0585] = 0x0300,     /* R1413  - Audio IF 3_6 */
+       [0x0586] = 0x0300,     /* R1414  - Audio IF 3_7 */
+       [0x0587] = 0x1820,     /* R1415  - Audio IF 3_8 */
+       [0x0588] = 0x1820,     /* R1416  - Audio IF 3_9 */
+       [0x0589] = 0x0000,     /* R1417  - Audio IF 3_10 */
+       [0x058A] = 0x0001,     /* R1418  - Audio IF 3_11 */
+       [0x0591] = 0x0000,     /* R1425  - Audio IF 3_18 */
+       [0x0592] = 0x0001,     /* R1426  - Audio IF 3_19 */
+       [0x0599] = 0x0000,     /* R1433  - Audio IF 3_26 */
+       [0x059A] = 0x0000,     /* R1434  - Audio IF 3_27 */
+       [0x0640] = 0x0000,     /* R1600  - PWM1MIX Input 1 Source */
+       [0x0641] = 0x0080,     /* R1601  - PWM1MIX Input 1 Volume */
+       [0x0642] = 0x0000,     /* R1602  - PWM1MIX Input 2 Source */
+       [0x0643] = 0x0080,     /* R1603  - PWM1MIX Input 2 Volume */
+       [0x0644] = 0x0000,     /* R1604  - PWM1MIX Input 3 Source */
+       [0x0645] = 0x0080,     /* R1605  - PWM1MIX Input 3 Volume */
+       [0x0646] = 0x0000,     /* R1606  - PWM1MIX Input 4 Source */
+       [0x0647] = 0x0080,     /* R1607  - PWM1MIX Input 4 Volume */
+       [0x0648] = 0x0000,     /* R1608  - PWM2MIX Input 1 Source */
+       [0x0649] = 0x0080,     /* R1609  - PWM2MIX Input 1 Volume */
+       [0x064A] = 0x0000,     /* R1610  - PWM2MIX Input 2 Source */
+       [0x064B] = 0x0080,     /* R1611  - PWM2MIX Input 2 Volume */
+       [0x064C] = 0x0000,     /* R1612  - PWM2MIX Input 3 Source */
+       [0x064D] = 0x0080,     /* R1613  - PWM2MIX Input 3 Volume */
+       [0x064E] = 0x0000,     /* R1614  - PWM2MIX Input 4 Source */
+       [0x064F] = 0x0080,     /* R1615  - PWM2MIX Input 4 Volume */
+       [0x0680] = 0x0000,     /* R1664  - OUT1LMIX Input 1 Source */
+       [0x0681] = 0x0080,     /* R1665  - OUT1LMIX Input 1 Volume */
+       [0x0682] = 0x0000,     /* R1666  - OUT1LMIX Input 2 Source */
+       [0x0683] = 0x0080,     /* R1667  - OUT1LMIX Input 2 Volume */
+       [0x0684] = 0x0000,     /* R1668  - OUT1LMIX Input 3 Source */
+       [0x0685] = 0x0080,     /* R1669  - OUT1LMIX Input 3 Volume */
+       [0x0686] = 0x0000,     /* R1670  - OUT1LMIX Input 4 Source */
+       [0x0687] = 0x0080,     /* R1671  - OUT1LMIX Input 4 Volume */
+       [0x0688] = 0x0000,     /* R1672  - OUT1RMIX Input 1 Source */
+       [0x0689] = 0x0080,     /* R1673  - OUT1RMIX Input 1 Volume */
+       [0x068A] = 0x0000,     /* R1674  - OUT1RMIX Input 2 Source */
+       [0x068B] = 0x0080,     /* R1675  - OUT1RMIX Input 2 Volume */
+       [0x068C] = 0x0000,     /* R1676  - OUT1RMIX Input 3 Source */
+       [0x068D] = 0x0080,     /* R1677  - OUT1RMIX Input 3 Volume */
+       [0x068E] = 0x0000,     /* R1678  - OUT1RMIX Input 4 Source */
+       [0x068F] = 0x0080,     /* R1679  - OUT1RMIX Input 4 Volume */
+       [0x0690] = 0x0000,     /* R1680  - OUT2LMIX Input 1 Source */
+       [0x0691] = 0x0080,     /* R1681  - OUT2LMIX Input 1 Volume */
+       [0x0692] = 0x0000,     /* R1682  - OUT2LMIX Input 2 Source */
+       [0x0693] = 0x0080,     /* R1683  - OUT2LMIX Input 2 Volume */
+       [0x0694] = 0x0000,     /* R1684  - OUT2LMIX Input 3 Source */
+       [0x0695] = 0x0080,     /* R1685  - OUT2LMIX Input 3 Volume */
+       [0x0696] = 0x0000,     /* R1686  - OUT2LMIX Input 4 Source */
+       [0x0697] = 0x0080,     /* R1687  - OUT2LMIX Input 4 Volume */
+       [0x0698] = 0x0000,     /* R1688  - OUT2RMIX Input 1 Source */
+       [0x0699] = 0x0080,     /* R1689  - OUT2RMIX Input 1 Volume */
+       [0x069A] = 0x0000,     /* R1690  - OUT2RMIX Input 2 Source */
+       [0x069B] = 0x0080,     /* R1691  - OUT2RMIX Input 2 Volume */
+       [0x069C] = 0x0000,     /* R1692  - OUT2RMIX Input 3 Source */
+       [0x069D] = 0x0080,     /* R1693  - OUT2RMIX Input 3 Volume */
+       [0x069E] = 0x0000,     /* R1694  - OUT2RMIX Input 4 Source */
+       [0x069F] = 0x0080,     /* R1695  - OUT2RMIX Input 4 Volume */
+       [0x06A0] = 0x0000,     /* R1696  - OUT3LMIX Input 1 Source */
+       [0x06A1] = 0x0080,     /* R1697  - OUT3LMIX Input 1 Volume */
+       [0x06A2] = 0x0000,     /* R1698  - OUT3LMIX Input 2 Source */
+       [0x06A3] = 0x0080,     /* R1699  - OUT3LMIX Input 2 Volume */
+       [0x06A4] = 0x0000,     /* R1700  - OUT3LMIX Input 3 Source */
+       [0x06A5] = 0x0080,     /* R1701  - OUT3LMIX Input 3 Volume */
+       [0x06A6] = 0x0000,     /* R1702  - OUT3LMIX Input 4 Source */
+       [0x06A7] = 0x0080,     /* R1703  - OUT3LMIX Input 4 Volume */
+       [0x06A8] = 0x0000,     /* R1704  - OUT3RMIX Input 1 Source */
+       [0x06A9] = 0x0080,     /* R1705  - OUT3RMIX Input 1 Volume */
+       [0x06AA] = 0x0000,     /* R1706  - OUT3RMIX Input 2 Source */
+       [0x06AB] = 0x0080,     /* R1707  - OUT3RMIX Input 2 Volume */
+       [0x06AC] = 0x0000,     /* R1708  - OUT3RMIX Input 3 Source */
+       [0x06AD] = 0x0080,     /* R1709  - OUT3RMIX Input 3 Volume */
+       [0x06AE] = 0x0000,     /* R1710  - OUT3RMIX Input 4 Source */
+       [0x06AF] = 0x0080,     /* R1711  - OUT3RMIX Input 4 Volume */
+       [0x06B0] = 0x0000,     /* R1712  - OUT4LMIX Input 1 Source */
+       [0x06B1] = 0x0080,     /* R1713  - OUT4LMIX Input 1 Volume */
+       [0x06B2] = 0x0000,     /* R1714  - OUT4LMIX Input 2 Source */
+       [0x06B3] = 0x0080,     /* R1715  - OUT4LMIX Input 2 Volume */
+       [0x06B4] = 0x0000,     /* R1716  - OUT4LMIX Input 3 Source */
+       [0x06B5] = 0x0080,     /* R1717  - OUT4LMIX Input 3 Volume */
+       [0x06B6] = 0x0000,     /* R1718  - OUT4LMIX Input 4 Source */
+       [0x06B7] = 0x0080,     /* R1719  - OUT4LMIX Input 4 Volume */
+       [0x06B8] = 0x0000,     /* R1720  - OUT4RMIX Input 1 Source */
+       [0x06B9] = 0x0080,     /* R1721  - OUT4RMIX Input 1 Volume */
+       [0x06BA] = 0x0000,     /* R1722  - OUT4RMIX Input 2 Source */
+       [0x06BB] = 0x0080,     /* R1723  - OUT4RMIX Input 2 Volume */
+       [0x06BC] = 0x0000,     /* R1724  - OUT4RMIX Input 3 Source */
+       [0x06BD] = 0x0080,     /* R1725  - OUT4RMIX Input 3 Volume */
+       [0x06BE] = 0x0000,     /* R1726  - OUT4RMIX Input 4 Source */
+       [0x06BF] = 0x0080,     /* R1727  - OUT4RMIX Input 4 Volume */
+       [0x06C0] = 0x0000,     /* R1728  - OUT5LMIX Input 1 Source */
+       [0x06C1] = 0x0080,     /* R1729  - OUT5LMIX Input 1 Volume */
+       [0x06C2] = 0x0000,     /* R1730  - OUT5LMIX Input 2 Source */
+       [0x06C3] = 0x0080,     /* R1731  - OUT5LMIX Input 2 Volume */
+       [0x06C4] = 0x0000,     /* R1732  - OUT5LMIX Input 3 Source */
+       [0x06C5] = 0x0080,     /* R1733  - OUT5LMIX Input 3 Volume */
+       [0x06C6] = 0x0000,     /* R1734  - OUT5LMIX Input 4 Source */
+       [0x06C7] = 0x0080,     /* R1735  - OUT5LMIX Input 4 Volume */
+       [0x06C8] = 0x0000,     /* R1736  - OUT5RMIX Input 1 Source */
+       [0x06C9] = 0x0080,     /* R1737  - OUT5RMIX Input 1 Volume */
+       [0x06CA] = 0x0000,     /* R1738  - OUT5RMIX Input 2 Source */
+       [0x06CB] = 0x0080,     /* R1739  - OUT5RMIX Input 2 Volume */
+       [0x06CC] = 0x0000,     /* R1740  - OUT5RMIX Input 3 Source */
+       [0x06CD] = 0x0080,     /* R1741  - OUT5RMIX Input 3 Volume */
+       [0x06CE] = 0x0000,     /* R1742  - OUT5RMIX Input 4 Source */
+       [0x06CF] = 0x0080,     /* R1743  - OUT5RMIX Input 4 Volume */
+       [0x06D0] = 0x0000,     /* R1744  - OUT6LMIX Input 1 Source */
+       [0x06D1] = 0x0080,     /* R1745  - OUT6LMIX Input 1 Volume */
+       [0x06D2] = 0x0000,     /* R1746  - OUT6LMIX Input 2 Source */
+       [0x06D3] = 0x0080,     /* R1747  - OUT6LMIX Input 2 Volume */
+       [0x06D4] = 0x0000,     /* R1748  - OUT6LMIX Input 3 Source */
+       [0x06D5] = 0x0080,     /* R1749  - OUT6LMIX Input 3 Volume */
+       [0x06D6] = 0x0000,     /* R1750  - OUT6LMIX Input 4 Source */
+       [0x06D7] = 0x0080,     /* R1751  - OUT6LMIX Input 4 Volume */
+       [0x06D8] = 0x0000,     /* R1752  - OUT6RMIX Input 1 Source */
+       [0x06D9] = 0x0080,     /* R1753  - OUT6RMIX Input 1 Volume */
+       [0x06DA] = 0x0000,     /* R1754  - OUT6RMIX Input 2 Source */
+       [0x06DB] = 0x0080,     /* R1755  - OUT6RMIX Input 2 Volume */
+       [0x06DC] = 0x0000,     /* R1756  - OUT6RMIX Input 3 Source */
+       [0x06DD] = 0x0080,     /* R1757  - OUT6RMIX Input 3 Volume */
+       [0x06DE] = 0x0000,     /* R1758  - OUT6RMIX Input 4 Source */
+       [0x06DF] = 0x0080,     /* R1759  - OUT6RMIX Input 4 Volume */
+       [0x0700] = 0x0000,     /* R1792  - AIF1TX1MIX Input 1 Source */
+       [0x0701] = 0x0080,     /* R1793  - AIF1TX1MIX Input 1 Volume */
+       [0x0702] = 0x0000,     /* R1794  - AIF1TX1MIX Input 2 Source */
+       [0x0703] = 0x0080,     /* R1795  - AIF1TX1MIX Input 2 Volume */
+       [0x0704] = 0x0000,     /* R1796  - AIF1TX1MIX Input 3 Source */
+       [0x0705] = 0x0080,     /* R1797  - AIF1TX1MIX Input 3 Volume */
+       [0x0706] = 0x0000,     /* R1798  - AIF1TX1MIX Input 4 Source */
+       [0x0707] = 0x0080,     /* R1799  - AIF1TX1MIX Input 4 Volume */
+       [0x0708] = 0x0000,     /* R1800  - AIF1TX2MIX Input 1 Source */
+       [0x0709] = 0x0080,     /* R1801  - AIF1TX2MIX Input 1 Volume */
+       [0x070A] = 0x0000,     /* R1802  - AIF1TX2MIX Input 2 Source */
+       [0x070B] = 0x0080,     /* R1803  - AIF1TX2MIX Input 2 Volume */
+       [0x070C] = 0x0000,     /* R1804  - AIF1TX2MIX Input 3 Source */
+       [0x070D] = 0x0080,     /* R1805  - AIF1TX2MIX Input 3 Volume */
+       [0x070E] = 0x0000,     /* R1806  - AIF1TX2MIX Input 4 Source */
+       [0x070F] = 0x0080,     /* R1807  - AIF1TX2MIX Input 4 Volume */
+       [0x0710] = 0x0000,     /* R1808  - AIF1TX3MIX Input 1 Source */
+       [0x0711] = 0x0080,     /* R1809  - AIF1TX3MIX Input 1 Volume */
+       [0x0712] = 0x0000,     /* R1810  - AIF1TX3MIX Input 2 Source */
+       [0x0713] = 0x0080,     /* R1811  - AIF1TX3MIX Input 2 Volume */
+       [0x0714] = 0x0000,     /* R1812  - AIF1TX3MIX Input 3 Source */
+       [0x0715] = 0x0080,     /* R1813  - AIF1TX3MIX Input 3 Volume */
+       [0x0716] = 0x0000,     /* R1814  - AIF1TX3MIX Input 4 Source */
+       [0x0717] = 0x0080,     /* R1815  - AIF1TX3MIX Input 4 Volume */
+       [0x0718] = 0x0000,     /* R1816  - AIF1TX4MIX Input 1 Source */
+       [0x0719] = 0x0080,     /* R1817  - AIF1TX4MIX Input 1 Volume */
+       [0x071A] = 0x0000,     /* R1818  - AIF1TX4MIX Input 2 Source */
+       [0x071B] = 0x0080,     /* R1819  - AIF1TX4MIX Input 2 Volume */
+       [0x071C] = 0x0000,     /* R1820  - AIF1TX4MIX Input 3 Source */
+       [0x071D] = 0x0080,     /* R1821  - AIF1TX4MIX Input 3 Volume */
+       [0x071E] = 0x0000,     /* R1822  - AIF1TX4MIX Input 4 Source */
+       [0x071F] = 0x0080,     /* R1823  - AIF1TX4MIX Input 4 Volume */
+       [0x0720] = 0x0000,     /* R1824  - AIF1TX5MIX Input 1 Source */
+       [0x0721] = 0x0080,     /* R1825  - AIF1TX5MIX Input 1 Volume */
+       [0x0722] = 0x0000,     /* R1826  - AIF1TX5MIX Input 2 Source */
+       [0x0723] = 0x0080,     /* R1827  - AIF1TX5MIX Input 2 Volume */
+       [0x0724] = 0x0000,     /* R1828  - AIF1TX5MIX Input 3 Source */
+       [0x0725] = 0x0080,     /* R1829  - AIF1TX5MIX Input 3 Volume */
+       [0x0726] = 0x0000,     /* R1830  - AIF1TX5MIX Input 4 Source */
+       [0x0727] = 0x0080,     /* R1831  - AIF1TX5MIX Input 4 Volume */
+       [0x0728] = 0x0000,     /* R1832  - AIF1TX6MIX Input 1 Source */
+       [0x0729] = 0x0080,     /* R1833  - AIF1TX6MIX Input 1 Volume */
+       [0x072A] = 0x0000,     /* R1834  - AIF1TX6MIX Input 2 Source */
+       [0x072B] = 0x0080,     /* R1835  - AIF1TX6MIX Input 2 Volume */
+       [0x072C] = 0x0000,     /* R1836  - AIF1TX6MIX Input 3 Source */
+       [0x072D] = 0x0080,     /* R1837  - AIF1TX6MIX Input 3 Volume */
+       [0x072E] = 0x0000,     /* R1838  - AIF1TX6MIX Input 4 Source */
+       [0x072F] = 0x0080,     /* R1839  - AIF1TX6MIX Input 4 Volume */
+       [0x0730] = 0x0000,     /* R1840  - AIF1TX7MIX Input 1 Source */
+       [0x0731] = 0x0080,     /* R1841  - AIF1TX7MIX Input 1 Volume */
+       [0x0732] = 0x0000,     /* R1842  - AIF1TX7MIX Input 2 Source */
+       [0x0733] = 0x0080,     /* R1843  - AIF1TX7MIX Input 2 Volume */
+       [0x0734] = 0x0000,     /* R1844  - AIF1TX7MIX Input 3 Source */
+       [0x0735] = 0x0080,     /* R1845  - AIF1TX7MIX Input 3 Volume */
+       [0x0736] = 0x0000,     /* R1846  - AIF1TX7MIX Input 4 Source */
+       [0x0737] = 0x0080,     /* R1847  - AIF1TX7MIX Input 4 Volume */
+       [0x0738] = 0x0000,     /* R1848  - AIF1TX8MIX Input 1 Source */
+       [0x0739] = 0x0080,     /* R1849  - AIF1TX8MIX Input 1 Volume */
+       [0x073A] = 0x0000,     /* R1850  - AIF1TX8MIX Input 2 Source */
+       [0x073B] = 0x0080,     /* R1851  - AIF1TX8MIX Input 2 Volume */
+       [0x073C] = 0x0000,     /* R1852  - AIF1TX8MIX Input 3 Source */
+       [0x073D] = 0x0080,     /* R1853  - AIF1TX8MIX Input 3 Volume */
+       [0x073E] = 0x0000,     /* R1854  - AIF1TX8MIX Input 4 Source */
+       [0x073F] = 0x0080,     /* R1855  - AIF1TX8MIX Input 4 Volume */
+       [0x0740] = 0x0000,     /* R1856  - AIF2TX1MIX Input 1 Source */
+       [0x0741] = 0x0080,     /* R1857  - AIF2TX1MIX Input 1 Volume */
+       [0x0742] = 0x0000,     /* R1858  - AIF2TX1MIX Input 2 Source */
+       [0x0743] = 0x0080,     /* R1859  - AIF2TX1MIX Input 2 Volume */
+       [0x0744] = 0x0000,     /* R1860  - AIF2TX1MIX Input 3 Source */
+       [0x0745] = 0x0080,     /* R1861  - AIF2TX1MIX Input 3 Volume */
+       [0x0746] = 0x0000,     /* R1862  - AIF2TX1MIX Input 4 Source */
+       [0x0747] = 0x0080,     /* R1863  - AIF2TX1MIX Input 4 Volume */
+       [0x0748] = 0x0000,     /* R1864  - AIF2TX2MIX Input 1 Source */
+       [0x0749] = 0x0080,     /* R1865  - AIF2TX2MIX Input 1 Volume */
+       [0x074A] = 0x0000,     /* R1866  - AIF2TX2MIX Input 2 Source */
+       [0x074B] = 0x0080,     /* R1867  - AIF2TX2MIX Input 2 Volume */
+       [0x074C] = 0x0000,     /* R1868  - AIF2TX2MIX Input 3 Source */
+       [0x074D] = 0x0080,     /* R1869  - AIF2TX2MIX Input 3 Volume */
+       [0x074E] = 0x0000,     /* R1870  - AIF2TX2MIX Input 4 Source */
+       [0x074F] = 0x0080,     /* R1871  - AIF2TX2MIX Input 4 Volume */
+       [0x0780] = 0x0000,     /* R1920  - AIF3TX1MIX Input 1 Source */
+       [0x0781] = 0x0080,     /* R1921  - AIF3TX1MIX Input 1 Volume */
+       [0x0782] = 0x0000,     /* R1922  - AIF3TX1MIX Input 2 Source */
+       [0x0783] = 0x0080,     /* R1923  - AIF3TX1MIX Input 2 Volume */
+       [0x0784] = 0x0000,     /* R1924  - AIF3TX1MIX Input 3 Source */
+       [0x0785] = 0x0080,     /* R1925  - AIF3TX1MIX Input 3 Volume */
+       [0x0786] = 0x0000,     /* R1926  - AIF3TX1MIX Input 4 Source */
+       [0x0787] = 0x0080,     /* R1927  - AIF3TX1MIX Input 4 Volume */
+       [0x0788] = 0x0000,     /* R1928  - AIF3TX2MIX Input 1 Source */
+       [0x0789] = 0x0080,     /* R1929  - AIF3TX2MIX Input 1 Volume */
+       [0x078A] = 0x0000,     /* R1930  - AIF3TX2MIX Input 2 Source */
+       [0x078B] = 0x0080,     /* R1931  - AIF3TX2MIX Input 2 Volume */
+       [0x078C] = 0x0000,     /* R1932  - AIF3TX2MIX Input 3 Source */
+       [0x078D] = 0x0080,     /* R1933  - AIF3TX2MIX Input 3 Volume */
+       [0x078E] = 0x0000,     /* R1934  - AIF3TX2MIX Input 4 Source */
+       [0x078F] = 0x0080,     /* R1935  - AIF3TX2MIX Input 4 Volume */
+       [0x0880] = 0x0000,     /* R2176  - EQ1MIX Input 1 Source */
+       [0x0881] = 0x0080,     /* R2177  - EQ1MIX Input 1 Volume */
+       [0x0882] = 0x0000,     /* R2178  - EQ1MIX Input 2 Source */
+       [0x0883] = 0x0080,     /* R2179  - EQ1MIX Input 2 Volume */
+       [0x0884] = 0x0000,     /* R2180  - EQ1MIX Input 3 Source */
+       [0x0885] = 0x0080,     /* R2181  - EQ1MIX Input 3 Volume */
+       [0x0886] = 0x0000,     /* R2182  - EQ1MIX Input 4 Source */
+       [0x0887] = 0x0080,     /* R2183  - EQ1MIX Input 4 Volume */
+       [0x0888] = 0x0000,     /* R2184  - EQ2MIX Input 1 Source */
+       [0x0889] = 0x0080,     /* R2185  - EQ2MIX Input 1 Volume */
+       [0x088A] = 0x0000,     /* R2186  - EQ2MIX Input 2 Source */
+       [0x088B] = 0x0080,     /* R2187  - EQ2MIX Input 2 Volume */
+       [0x088C] = 0x0000,     /* R2188  - EQ2MIX Input 3 Source */
+       [0x088D] = 0x0080,     /* R2189  - EQ2MIX Input 3 Volume */
+       [0x088E] = 0x0000,     /* R2190  - EQ2MIX Input 4 Source */
+       [0x088F] = 0x0080,     /* R2191  - EQ2MIX Input 4 Volume */
+       [0x0890] = 0x0000,     /* R2192  - EQ3MIX Input 1 Source */
+       [0x0891] = 0x0080,     /* R2193  - EQ3MIX Input 1 Volume */
+       [0x0892] = 0x0000,     /* R2194  - EQ3MIX Input 2 Source */
+       [0x0893] = 0x0080,     /* R2195  - EQ3MIX Input 2 Volume */
+       [0x0894] = 0x0000,     /* R2196  - EQ3MIX Input 3 Source */
+       [0x0895] = 0x0080,     /* R2197  - EQ3MIX Input 3 Volume */
+       [0x0896] = 0x0000,     /* R2198  - EQ3MIX Input 4 Source */
+       [0x0897] = 0x0080,     /* R2199  - EQ3MIX Input 4 Volume */
+       [0x0898] = 0x0000,     /* R2200  - EQ4MIX Input 1 Source */
+       [0x0899] = 0x0080,     /* R2201  - EQ4MIX Input 1 Volume */
+       [0x089A] = 0x0000,     /* R2202  - EQ4MIX Input 2 Source */
+       [0x089B] = 0x0080,     /* R2203  - EQ4MIX Input 2 Volume */
+       [0x089C] = 0x0000,     /* R2204  - EQ4MIX Input 3 Source */
+       [0x089D] = 0x0080,     /* R2205  - EQ4MIX Input 3 Volume */
+       [0x089E] = 0x0000,     /* R2206  - EQ4MIX Input 4 Source */
+       [0x089F] = 0x0080,     /* R2207  - EQ4MIX Input 4 Volume */
+       [0x08C0] = 0x0000,     /* R2240  - DRC1LMIX Input 1 Source */
+       [0x08C1] = 0x0080,     /* R2241  - DRC1LMIX Input 1 Volume */
+       [0x08C2] = 0x0000,     /* R2242  - DRC1LMIX Input 2 Source */
+       [0x08C3] = 0x0080,     /* R2243  - DRC1LMIX Input 2 Volume */
+       [0x08C4] = 0x0000,     /* R2244  - DRC1LMIX Input 3 Source */
+       [0x08C5] = 0x0080,     /* R2245  - DRC1LMIX Input 3 Volume */
+       [0x08C6] = 0x0000,     /* R2246  - DRC1LMIX Input 4 Source */
+       [0x08C7] = 0x0080,     /* R2247  - DRC1LMIX Input 4 Volume */
+       [0x08C8] = 0x0000,     /* R2248  - DRC1RMIX Input 1 Source */
+       [0x08C9] = 0x0080,     /* R2249  - DRC1RMIX Input 1 Volume */
+       [0x08CA] = 0x0000,     /* R2250  - DRC1RMIX Input 2 Source */
+       [0x08CB] = 0x0080,     /* R2251  - DRC1RMIX Input 2 Volume */
+       [0x08CC] = 0x0000,     /* R2252  - DRC1RMIX Input 3 Source */
+       [0x08CD] = 0x0080,     /* R2253  - DRC1RMIX Input 3 Volume */
+       [0x08CE] = 0x0000,     /* R2254  - DRC1RMIX Input 4 Source */
+       [0x08CF] = 0x0080,     /* R2255  - DRC1RMIX Input 4 Volume */
+       [0x0900] = 0x0000,     /* R2304  - HPLP1MIX Input 1 Source */
+       [0x0901] = 0x0080,     /* R2305  - HPLP1MIX Input 1 Volume */
+       [0x0902] = 0x0000,     /* R2306  - HPLP1MIX Input 2 Source */
+       [0x0903] = 0x0080,     /* R2307  - HPLP1MIX Input 2 Volume */
+       [0x0904] = 0x0000,     /* R2308  - HPLP1MIX Input 3 Source */
+       [0x0905] = 0x0080,     /* R2309  - HPLP1MIX Input 3 Volume */
+       [0x0906] = 0x0000,     /* R2310  - HPLP1MIX Input 4 Source */
+       [0x0907] = 0x0080,     /* R2311  - HPLP1MIX Input 4 Volume */
+       [0x0908] = 0x0000,     /* R2312  - HPLP2MIX Input 1 Source */
+       [0x0909] = 0x0080,     /* R2313  - HPLP2MIX Input 1 Volume */
+       [0x090A] = 0x0000,     /* R2314  - HPLP2MIX Input 2 Source */
+       [0x090B] = 0x0080,     /* R2315  - HPLP2MIX Input 2 Volume */
+       [0x090C] = 0x0000,     /* R2316  - HPLP2MIX Input 3 Source */
+       [0x090D] = 0x0080,     /* R2317  - HPLP2MIX Input 3 Volume */
+       [0x090E] = 0x0000,     /* R2318  - HPLP2MIX Input 4 Source */
+       [0x090F] = 0x0080,     /* R2319  - HPLP2MIX Input 4 Volume */
+       [0x0910] = 0x0000,     /* R2320  - HPLP3MIX Input 1 Source */
+       [0x0911] = 0x0080,     /* R2321  - HPLP3MIX Input 1 Volume */
+       [0x0912] = 0x0000,     /* R2322  - HPLP3MIX Input 2 Source */
+       [0x0913] = 0x0080,     /* R2323  - HPLP3MIX Input 2 Volume */
+       [0x0914] = 0x0000,     /* R2324  - HPLP3MIX Input 3 Source */
+       [0x0915] = 0x0080,     /* R2325  - HPLP3MIX Input 3 Volume */
+       [0x0916] = 0x0000,     /* R2326  - HPLP3MIX Input 4 Source */
+       [0x0917] = 0x0080,     /* R2327  - HPLP3MIX Input 4 Volume */
+       [0x0918] = 0x0000,     /* R2328  - HPLP4MIX Input 1 Source */
+       [0x0919] = 0x0080,     /* R2329  - HPLP4MIX Input 1 Volume */
+       [0x091A] = 0x0000,     /* R2330  - HPLP4MIX Input 2 Source */
+       [0x091B] = 0x0080,     /* R2331  - HPLP4MIX Input 2 Volume */
+       [0x091C] = 0x0000,     /* R2332  - HPLP4MIX Input 3 Source */
+       [0x091D] = 0x0080,     /* R2333  - HPLP4MIX Input 3 Volume */
+       [0x091E] = 0x0000,     /* R2334  - HPLP4MIX Input 4 Source */
+       [0x091F] = 0x0080,     /* R2335  - HPLP4MIX Input 4 Volume */
+       [0x0940] = 0x0000,     /* R2368  - DSP1LMIX Input 1 Source */
+       [0x0941] = 0x0080,     /* R2369  - DSP1LMIX Input 1 Volume */
+       [0x0942] = 0x0000,     /* R2370  - DSP1LMIX Input 2 Source */
+       [0x0943] = 0x0080,     /* R2371  - DSP1LMIX Input 2 Volume */
+       [0x0944] = 0x0000,     /* R2372  - DSP1LMIX Input 3 Source */
+       [0x0945] = 0x0080,     /* R2373  - DSP1LMIX Input 3 Volume */
+       [0x0946] = 0x0000,     /* R2374  - DSP1LMIX Input 4 Source */
+       [0x0947] = 0x0080,     /* R2375  - DSP1LMIX Input 4 Volume */
+       [0x0948] = 0x0000,     /* R2376  - DSP1RMIX Input 1 Source */
+       [0x0949] = 0x0080,     /* R2377  - DSP1RMIX Input 1 Volume */
+       [0x094A] = 0x0000,     /* R2378  - DSP1RMIX Input 2 Source */
+       [0x094B] = 0x0080,     /* R2379  - DSP1RMIX Input 2 Volume */
+       [0x094C] = 0x0000,     /* R2380  - DSP1RMIX Input 3 Source */
+       [0x094D] = 0x0080,     /* R2381  - DSP1RMIX Input 3 Volume */
+       [0x094E] = 0x0000,     /* R2382  - DSP1RMIX Input 4 Source */
+       [0x094F] = 0x0080,     /* R2383  - DSP1RMIX Input 4 Volume */
+       [0x0950] = 0x0000,     /* R2384  - DSP1AUX1MIX Input 1 Source */
+       [0x0958] = 0x0000,     /* R2392  - DSP1AUX2MIX Input 1 Source */
+       [0x0960] = 0x0000,     /* R2400  - DSP1AUX3MIX Input 1 Source */
+       [0x0968] = 0x0000,     /* R2408  - DSP1AUX4MIX Input 1 Source */
+       [0x0970] = 0x0000,     /* R2416  - DSP1AUX5MIX Input 1 Source */
+       [0x0978] = 0x0000,     /* R2424  - DSP1AUX6MIX Input 1 Source */
+       [0x0980] = 0x0000,     /* R2432  - DSP2LMIX Input 1 Source */
+       [0x0981] = 0x0080,     /* R2433  - DSP2LMIX Input 1 Volume */
+       [0x0982] = 0x0000,     /* R2434  - DSP2LMIX Input 2 Source */
+       [0x0983] = 0x0080,     /* R2435  - DSP2LMIX Input 2 Volume */
+       [0x0984] = 0x0000,     /* R2436  - DSP2LMIX Input 3 Source */
+       [0x0985] = 0x0080,     /* R2437  - DSP2LMIX Input 3 Volume */
+       [0x0986] = 0x0000,     /* R2438  - DSP2LMIX Input 4 Source */
+       [0x0987] = 0x0080,     /* R2439  - DSP2LMIX Input 4 Volume */
+       [0x0988] = 0x0000,     /* R2440  - DSP2RMIX Input 1 Source */
+       [0x0989] = 0x0080,     /* R2441  - DSP2RMIX Input 1 Volume */
+       [0x098A] = 0x0000,     /* R2442  - DSP2RMIX Input 2 Source */
+       [0x098B] = 0x0080,     /* R2443  - DSP2RMIX Input 2 Volume */
+       [0x098C] = 0x0000,     /* R2444  - DSP2RMIX Input 3 Source */
+       [0x098D] = 0x0080,     /* R2445  - DSP2RMIX Input 3 Volume */
+       [0x098E] = 0x0000,     /* R2446  - DSP2RMIX Input 4 Source */
+       [0x098F] = 0x0080,     /* R2447  - DSP2RMIX Input 4 Volume */
+       [0x0990] = 0x0000,     /* R2448  - DSP2AUX1MIX Input 1 Source */
+       [0x0998] = 0x0000,     /* R2456  - DSP2AUX2MIX Input 1 Source */
+       [0x09A0] = 0x0000,     /* R2464  - DSP2AUX3MIX Input 1 Source */
+       [0x09A8] = 0x0000,     /* R2472  - DSP2AUX4MIX Input 1 Source */
+       [0x09B0] = 0x0000,     /* R2480  - DSP2AUX5MIX Input 1 Source */
+       [0x09B8] = 0x0000,     /* R2488  - DSP2AUX6MIX Input 1 Source */
+       [0x09C0] = 0x0000,     /* R2496  - DSP3LMIX Input 1 Source */
+       [0x09C1] = 0x0080,     /* R2497  - DSP3LMIX Input 1 Volume */
+       [0x09C2] = 0x0000,     /* R2498  - DSP3LMIX Input 2 Source */
+       [0x09C3] = 0x0080,     /* R2499  - DSP3LMIX Input 2 Volume */
+       [0x09C4] = 0x0000,     /* R2500  - DSP3LMIX Input 3 Source */
+       [0x09C5] = 0x0080,     /* R2501  - DSP3LMIX Input 3 Volume */
+       [0x09C6] = 0x0000,     /* R2502  - DSP3LMIX Input 4 Source */
+       [0x09C7] = 0x0080,     /* R2503  - DSP3LMIX Input 4 Volume */
+       [0x09C8] = 0x0000,     /* R2504  - DSP3RMIX Input 1 Source */
+       [0x09C9] = 0x0080,     /* R2505  - DSP3RMIX Input 1 Volume */
+       [0x09CA] = 0x0000,     /* R2506  - DSP3RMIX Input 2 Source */
+       [0x09CB] = 0x0080,     /* R2507  - DSP3RMIX Input 2 Volume */
+       [0x09CC] = 0x0000,     /* R2508  - DSP3RMIX Input 3 Source */
+       [0x09CD] = 0x0080,     /* R2509  - DSP3RMIX Input 3 Volume */
+       [0x09CE] = 0x0000,     /* R2510  - DSP3RMIX Input 4 Source */
+       [0x09CF] = 0x0080,     /* R2511  - DSP3RMIX Input 4 Volume */
+       [0x09D0] = 0x0000,     /* R2512  - DSP3AUX1MIX Input 1 Source */
+       [0x09D8] = 0x0000,     /* R2520  - DSP3AUX2MIX Input 1 Source */
+       [0x09E0] = 0x0000,     /* R2528  - DSP3AUX3MIX Input 1 Source */
+       [0x09E8] = 0x0000,     /* R2536  - DSP3AUX4MIX Input 1 Source */
+       [0x09F0] = 0x0000,     /* R2544  - DSP3AUX5MIX Input 1 Source */
+       [0x09F8] = 0x0000,     /* R2552  - DSP3AUX6MIX Input 1 Source */
+       [0x0A80] = 0x0000,     /* R2688  - ASRC1LMIX Input 1 Source */
+       [0x0A88] = 0x0000,     /* R2696  - ASRC1RMIX Input 1 Source */
+       [0x0A90] = 0x0000,     /* R2704  - ASRC2LMIX Input 1 Source */
+       [0x0A98] = 0x0000,     /* R2712  - ASRC2RMIX Input 1 Source */
+       [0x0B00] = 0x0000,     /* R2816  - ISRC1DEC1MIX Input 1 Source */
+       [0x0B08] = 0x0000,     /* R2824  - ISRC1DEC2MIX Input 1 Source */
+       [0x0B10] = 0x0000,     /* R2832  - ISRC1DEC3MIX Input 1 Source */
+       [0x0B18] = 0x0000,     /* R2840  - ISRC1DEC4MIX Input 1 Source */
+       [0x0B20] = 0x0000,     /* R2848  - ISRC1INT1MIX Input 1 Source */
+       [0x0B28] = 0x0000,     /* R2856  - ISRC1INT2MIX Input 1 Source */
+       [0x0B30] = 0x0000,     /* R2864  - ISRC1INT3MIX Input 1 Source */
+       [0x0B38] = 0x0000,     /* R2872  - ISRC1INT4MIX Input 1 Source */
+       [0x0B40] = 0x0000,     /* R2880  - ISRC2DEC1MIX Input 1 Source */
+       [0x0B48] = 0x0000,     /* R2888  - ISRC2DEC2MIX Input 1 Source */
+       [0x0B50] = 0x0000,     /* R2896  - ISRC2DEC3MIX Input 1 Source */
+       [0x0B58] = 0x0000,     /* R2904  - ISRC2DEC4MIX Input 1 Source */
+       [0x0B60] = 0x0000,     /* R2912  - ISRC2INT1MIX Input 1 Source */
+       [0x0B68] = 0x0000,     /* R2920  - ISRC2INT2MIX Input 1 Source */
+       [0x0B70] = 0x0000,     /* R2928  - ISRC2INT3MIX Input 1 Source */
+       [0x0B78] = 0x0000,     /* R2936  - ISRC2INT4MIX Input 1 Source */
+       [0x0C00] = 0xA001,     /* R3072  - GPIO CTRL 1 */
+       [0x0C01] = 0xA001,     /* R3073  - GPIO CTRL 2 */
+       [0x0C02] = 0xA001,     /* R3074  - GPIO CTRL 3 */
+       [0x0C03] = 0xA001,     /* R3075  - GPIO CTRL 4 */
+       [0x0C04] = 0xA001,     /* R3076  - GPIO CTRL 5 */
+       [0x0C05] = 0xA001,     /* R3077  - GPIO CTRL 6 */
+       [0x0C23] = 0x4003,     /* R3107  - Misc Pad Ctrl 1 */
+       [0x0C24] = 0x0000,     /* R3108  - Misc Pad Ctrl 2 */
+       [0x0C25] = 0x0000,     /* R3109  - Misc Pad Ctrl 3 */
+       [0x0C26] = 0x0000,     /* R3110  - Misc Pad Ctrl 4 */
+       [0x0C27] = 0x0000,     /* R3111  - Misc Pad Ctrl 5 */
+       [0x0C28] = 0x0000,     /* R3112  - Misc GPIO 1 */
+       [0x0D00] = 0x0000,     /* R3328  - Interrupt Status 1 */
+       [0x0D01] = 0x0000,     /* R3329  - Interrupt Status 2 */
+       [0x0D02] = 0x0000,     /* R3330  - Interrupt Status 3 */
+       [0x0D03] = 0x0000,     /* R3331  - Interrupt Status 4 */
+       [0x0D04] = 0x0000,     /* R3332  - Interrupt Raw Status 2 */
+       [0x0D05] = 0x0000,     /* R3333  - Interrupt Raw Status 3 */
+       [0x0D06] = 0x0000,     /* R3334  - Interrupt Raw Status 4 */
+       [0x0D07] = 0xFFFF,     /* R3335  - Interrupt Status 1 Mask */
+       [0x0D08] = 0xFFFF,     /* R3336  - Interrupt Status 2 Mask */
+       [0x0D09] = 0xFFFF,     /* R3337  - Interrupt Status 3 Mask */
+       [0x0D0A] = 0xFFFF,     /* R3338  - Interrupt Status 4 Mask */
+       [0x0D1F] = 0x0000,     /* R3359  - Interrupt Control */
+       [0x0D20] = 0xFFFF,     /* R3360  - IRQ Debounce 1 */
+       [0x0D21] = 0xFFFF,     /* R3361  - IRQ Debounce 2 */
+       [0x0E00] = 0x0000,     /* R3584  - FX_Ctrl */
+       [0x0E10] = 0x6318,     /* R3600  - EQ1_1 */
+       [0x0E11] = 0x6300,     /* R3601  - EQ1_2 */
+       [0x0E12] = 0x0FC8,     /* R3602  - EQ1_3 */
+       [0x0E13] = 0x03FE,     /* R3603  - EQ1_4 */
+       [0x0E14] = 0x00E0,     /* R3604  - EQ1_5 */
+       [0x0E15] = 0x1EC4,     /* R3605  - EQ1_6 */
+       [0x0E16] = 0xF136,     /* R3606  - EQ1_7 */
+       [0x0E17] = 0x0409,     /* R3607  - EQ1_8 */
+       [0x0E18] = 0x04CC,     /* R3608  - EQ1_9 */
+       [0x0E19] = 0x1C9B,     /* R3609  - EQ1_10 */
+       [0x0E1A] = 0xF337,     /* R3610  - EQ1_11 */
+       [0x0E1B] = 0x040B,     /* R3611  - EQ1_12 */
+       [0x0E1C] = 0x0CBB,     /* R3612  - EQ1_13 */
+       [0x0E1D] = 0x16F8,     /* R3613  - EQ1_14 */
+       [0x0E1E] = 0xF7D9,     /* R3614  - EQ1_15 */
+       [0x0E1F] = 0x040A,     /* R3615  - EQ1_16 */
+       [0x0E20] = 0x1F14,     /* R3616  - EQ1_17 */
+       [0x0E21] = 0x058C,     /* R3617  - EQ1_18 */
+       [0x0E22] = 0x0563,     /* R3618  - EQ1_19 */
+       [0x0E23] = 0x4000,     /* R3619  - EQ1_20 */
+       [0x0E26] = 0x6318,     /* R3622  - EQ2_1 */
+       [0x0E27] = 0x6300,     /* R3623  - EQ2_2 */
+       [0x0E28] = 0x0FC8,     /* R3624  - EQ2_3 */
+       [0x0E29] = 0x03FE,     /* R3625  - EQ2_4 */
+       [0x0E2A] = 0x00E0,     /* R3626  - EQ2_5 */
+       [0x0E2B] = 0x1EC4,     /* R3627  - EQ2_6 */
+       [0x0E2C] = 0xF136,     /* R3628  - EQ2_7 */
+       [0x0E2D] = 0x0409,     /* R3629  - EQ2_8 */
+       [0x0E2E] = 0x04CC,     /* R3630  - EQ2_9 */
+       [0x0E2F] = 0x1C9B,     /* R3631  - EQ2_10 */
+       [0x0E30] = 0xF337,     /* R3632  - EQ2_11 */
+       [0x0E31] = 0x040B,     /* R3633  - EQ2_12 */
+       [0x0E32] = 0x0CBB,     /* R3634  - EQ2_13 */
+       [0x0E33] = 0x16F8,     /* R3635  - EQ2_14 */
+       [0x0E34] = 0xF7D9,     /* R3636  - EQ2_15 */
+       [0x0E35] = 0x040A,     /* R3637  - EQ2_16 */
+       [0x0E36] = 0x1F14,     /* R3638  - EQ2_17 */
+       [0x0E37] = 0x058C,     /* R3639  - EQ2_18 */
+       [0x0E38] = 0x0563,     /* R3640  - EQ2_19 */
+       [0x0E39] = 0x4000,     /* R3641  - EQ2_20 */
+       [0x0E3C] = 0x6318,     /* R3644  - EQ3_1 */
+       [0x0E3D] = 0x6300,     /* R3645  - EQ3_2 */
+       [0x0E3E] = 0x0FC8,     /* R3646  - EQ3_3 */
+       [0x0E3F] = 0x03FE,     /* R3647  - EQ3_4 */
+       [0x0E40] = 0x00E0,     /* R3648  - EQ3_5 */
+       [0x0E41] = 0x1EC4,     /* R3649  - EQ3_6 */
+       [0x0E42] = 0xF136,     /* R3650  - EQ3_7 */
+       [0x0E43] = 0x0409,     /* R3651  - EQ3_8 */
+       [0x0E44] = 0x04CC,     /* R3652  - EQ3_9 */
+       [0x0E45] = 0x1C9B,     /* R3653  - EQ3_10 */
+       [0x0E46] = 0xF337,     /* R3654  - EQ3_11 */
+       [0x0E47] = 0x040B,     /* R3655  - EQ3_12 */
+       [0x0E48] = 0x0CBB,     /* R3656  - EQ3_13 */
+       [0x0E49] = 0x16F8,     /* R3657  - EQ3_14 */
+       [0x0E4A] = 0xF7D9,     /* R3658  - EQ3_15 */
+       [0x0E4B] = 0x040A,     /* R3659  - EQ3_16 */
+       [0x0E4C] = 0x1F14,     /* R3660  - EQ3_17 */
+       [0x0E4D] = 0x058C,     /* R3661  - EQ3_18 */
+       [0x0E4E] = 0x0563,     /* R3662  - EQ3_19 */
+       [0x0E4F] = 0x4000,     /* R3663  - EQ3_20 */
+       [0x0E52] = 0x6318,     /* R3666  - EQ4_1 */
+       [0x0E53] = 0x6300,     /* R3667  - EQ4_2 */
+       [0x0E54] = 0x0FC8,     /* R3668  - EQ4_3 */
+       [0x0E55] = 0x03FE,     /* R3669  - EQ4_4 */
+       [0x0E56] = 0x00E0,     /* R3670  - EQ4_5 */
+       [0x0E57] = 0x1EC4,     /* R3671  - EQ4_6 */
+       [0x0E58] = 0xF136,     /* R3672  - EQ4_7 */
+       [0x0E59] = 0x0409,     /* R3673  - EQ4_8 */
+       [0x0E5A] = 0x04CC,     /* R3674  - EQ4_9 */
+       [0x0E5B] = 0x1C9B,     /* R3675  - EQ4_10 */
+       [0x0E5C] = 0xF337,     /* R3676  - EQ4_11 */
+       [0x0E5D] = 0x040B,     /* R3677  - EQ4_12 */
+       [0x0E5E] = 0x0CBB,     /* R3678  - EQ4_13 */
+       [0x0E5F] = 0x16F8,     /* R3679  - EQ4_14 */
+       [0x0E60] = 0xF7D9,     /* R3680  - EQ4_15 */
+       [0x0E61] = 0x040A,     /* R3681  - EQ4_16 */
+       [0x0E62] = 0x1F14,     /* R3682  - EQ4_17 */
+       [0x0E63] = 0x058C,     /* R3683  - EQ4_18 */
+       [0x0E64] = 0x0563,     /* R3684  - EQ4_19 */
+       [0x0E65] = 0x4000,     /* R3685  - EQ4_20 */
+       [0x0E80] = 0x0018,     /* R3712  - DRC1 ctrl1 */
+       [0x0E81] = 0x0933,     /* R3713  - DRC1 ctrl2 */
+       [0x0E82] = 0x0018,     /* R3714  - DRC1 ctrl3 */
+       [0x0E83] = 0x0000,     /* R3715  - DRC1 ctrl4 */
+       [0x0E84] = 0x0000,     /* R3716  - DRC1 ctrl5 */
+       [0x0EC0] = 0x0000,     /* R3776  - HPLPF1_1 */
+       [0x0EC1] = 0x0000,     /* R3777  - HPLPF1_2 */
+       [0x0EC4] = 0x0000,     /* R3780  - HPLPF2_1 */
+       [0x0EC5] = 0x0000,     /* R3781  - HPLPF2_2 */
+       [0x0EC8] = 0x0000,     /* R3784  - HPLPF3_1 */
+       [0x0EC9] = 0x0000,     /* R3785  - HPLPF3_2 */
+       [0x0ECC] = 0x0000,     /* R3788  - HPLPF4_1 */
+       [0x0ECD] = 0x0000,     /* R3789  - HPLPF4_2 */
+       [0x4000] = 0x0000,     /* R16384 - DSP1 DM 0 */
+       [0x4001] = 0x0000,     /* R16385 - DSP1 DM 1 */
+       [0x4002] = 0x0000,     /* R16386 - DSP1 DM 2 */
+       [0x4003] = 0x0000,     /* R16387 - DSP1 DM 3 */
+       [0x41FC] = 0x0000,     /* R16892 - DSP1 DM 508 */
+       [0x41FD] = 0x0000,     /* R16893 - DSP1 DM 509 */
+       [0x41FE] = 0x0000,     /* R16894 - DSP1 DM 510 */
+       [0x41FF] = 0x0000,     /* R16895 - DSP1 DM 511 */
+       [0x4800] = 0x0000,     /* R18432 - DSP1 PM 0 */
+       [0x4801] = 0x0000,     /* R18433 - DSP1 PM 1 */
+       [0x4802] = 0x0000,     /* R18434 - DSP1 PM 2 */
+       [0x4803] = 0x0000,     /* R18435 - DSP1 PM 3 */
+       [0x4804] = 0x0000,     /* R18436 - DSP1 PM 4 */
+       [0x4805] = 0x0000,     /* R18437 - DSP1 PM 5 */
+       [0x4DFA] = 0x0000,     /* R19962 - DSP1 PM 1530 */
+       [0x4DFB] = 0x0000,     /* R19963 - DSP1 PM 1531 */
+       [0x4DFC] = 0x0000,     /* R19964 - DSP1 PM 1532 */
+       [0x4DFD] = 0x0000,     /* R19965 - DSP1 PM 1533 */
+       [0x4DFE] = 0x0000,     /* R19966 - DSP1 PM 1534 */
+       [0x4DFF] = 0x0000,     /* R19967 - DSP1 PM 1535 */
+       [0x5000] = 0x0000,     /* R20480 - DSP1 ZM 0 */
+       [0x5001] = 0x0000,     /* R20481 - DSP1 ZM 1 */
+       [0x5002] = 0x0000,     /* R20482 - DSP1 ZM 2 */
+       [0x5003] = 0x0000,     /* R20483 - DSP1 ZM 3 */
+       [0x57FC] = 0x0000,     /* R22524 - DSP1 ZM 2044 */
+       [0x57FD] = 0x0000,     /* R22525 - DSP1 ZM 2045 */
+       [0x57FE] = 0x0000,     /* R22526 - DSP1 ZM 2046 */
+       [0x57FF] = 0x0000,     /* R22527 - DSP1 ZM 2047 */
+       [0x6000] = 0x0000,     /* R24576 - DSP2 DM 0 */
+       [0x6001] = 0x0000,     /* R24577 - DSP2 DM 1 */
+       [0x6002] = 0x0000,     /* R24578 - DSP2 DM 2 */
+       [0x6003] = 0x0000,     /* R24579 - DSP2 DM 3 */
+       [0x61FC] = 0x0000,     /* R25084 - DSP2 DM 508 */
+       [0x61FD] = 0x0000,     /* R25085 - DSP2 DM 509 */
+       [0x61FE] = 0x0000,     /* R25086 - DSP2 DM 510 */
+       [0x61FF] = 0x0000,     /* R25087 - DSP2 DM 511 */
+       [0x6800] = 0x0000,     /* R26624 - DSP2 PM 0 */
+       [0x6801] = 0x0000,     /* R26625 - DSP2 PM 1 */
+       [0x6802] = 0x0000,     /* R26626 - DSP2 PM 2 */
+       [0x6803] = 0x0000,     /* R26627 - DSP2 PM 3 */
+       [0x6804] = 0x0000,     /* R26628 - DSP2 PM 4 */
+       [0x6805] = 0x0000,     /* R26629 - DSP2 PM 5 */
+       [0x6DFA] = 0x0000,     /* R28154 - DSP2 PM 1530 */
+       [0x6DFB] = 0x0000,     /* R28155 - DSP2 PM 1531 */
+       [0x6DFC] = 0x0000,     /* R28156 - DSP2 PM 1532 */
+       [0x6DFD] = 0x0000,     /* R28157 - DSP2 PM 1533 */
+       [0x6DFE] = 0x0000,     /* R28158 - DSP2 PM 1534 */
+       [0x6DFF] = 0x0000,     /* R28159 - DSP2 PM 1535 */
+       [0x7000] = 0x0000,     /* R28672 - DSP2 ZM 0 */
+       [0x7001] = 0x0000,     /* R28673 - DSP2 ZM 1 */
+       [0x7002] = 0x0000,     /* R28674 - DSP2 ZM 2 */
+       [0x7003] = 0x0000,     /* R28675 - DSP2 ZM 3 */
+       [0x77FC] = 0x0000,     /* R30716 - DSP2 ZM 2044 */
+       [0x77FD] = 0x0000,     /* R30717 - DSP2 ZM 2045 */
+       [0x77FE] = 0x0000,     /* R30718 - DSP2 ZM 2046 */
+       [0x77FF] = 0x0000,     /* R30719 - DSP2 ZM 2047 */
+       [0x8000] = 0x0000,     /* R32768 - DSP3 DM 0 */
+       [0x8001] = 0x0000,     /* R32769 - DSP3 DM 1 */
+       [0x8002] = 0x0000,     /* R32770 - DSP3 DM 2 */
+       [0x8003] = 0x0000,     /* R32771 - DSP3 DM 3 */
+       [0x81FC] = 0x0000,     /* R33276 - DSP3 DM 508 */
+       [0x81FD] = 0x0000,     /* R33277 - DSP3 DM 509 */
+       [0x81FE] = 0x0000,     /* R33278 - DSP3 DM 510 */
+       [0x81FF] = 0x0000,     /* R33279 - DSP3 DM 511 */
+       [0x8800] = 0x0000,     /* R34816 - DSP3 PM 0 */
+       [0x8801] = 0x0000,     /* R34817 - DSP3 PM 1 */
+       [0x8802] = 0x0000,     /* R34818 - DSP3 PM 2 */
+       [0x8803] = 0x0000,     /* R34819 - DSP3 PM 3 */
+       [0x8804] = 0x0000,     /* R34820 - DSP3 PM 4 */
+       [0x8805] = 0x0000,     /* R34821 - DSP3 PM 5 */
+       [0x8DFA] = 0x0000,     /* R36346 - DSP3 PM 1530 */
+       [0x8DFB] = 0x0000,     /* R36347 - DSP3 PM 1531 */
+       [0x8DFC] = 0x0000,     /* R36348 - DSP3 PM 1532 */
+       [0x8DFD] = 0x0000,     /* R36349 - DSP3 PM 1533 */
+       [0x8DFE] = 0x0000,     /* R36350 - DSP3 PM 1534 */
+       [0x8DFF] = 0x0000,     /* R36351 - DSP3 PM 1535 */
+       [0x9000] = 0x0000,     /* R36864 - DSP3 ZM 0 */
+       [0x9001] = 0x0000,     /* R36865 - DSP3 ZM 1 */
+       [0x9002] = 0x0000,     /* R36866 - DSP3 ZM 2 */
+       [0x9003] = 0x0000,     /* R36867 - DSP3 ZM 3 */
+       [0x97FC] = 0x0000,     /* R38908 - DSP3 ZM 2044 */
+       [0x97FD] = 0x0000,     /* R38909 - DSP3 ZM 2045 */
+       [0x97FE] = 0x0000,     /* R38910 - DSP3 ZM 2046 */
+       [0x97FF] = 0x0000      /* R38911 - DSP3 ZM 2047 */
+};
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
new file mode 100644 (file)
index 0000000..f603989
--- /dev/null
@@ -0,0 +1,2646 @@
+/*
+ * wm5100.c  --  WM5100 ALSA SoC Audio driver
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm5100.h>
+
+#include "wm5100.h"
+
+#define WM5100_NUM_CORE_SUPPLIES 2
+static const char *wm5100_core_supply_names[WM5100_NUM_CORE_SUPPLIES] = {
+       "DBVDD1",
+       "LDOVDD", /* If DCVDD is supplied externally specify as LDOVDD */
+};
+
+#define WM5100_AIFS     3
+#define WM5100_SYNC_SRS 3
+
+struct wm5100_fll {
+       int fref;
+       int fout;
+       int src;
+       struct completion lock;
+};
+
+/* codec private data */
+struct wm5100_priv {
+       struct snd_soc_codec *codec;
+
+       struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
+       struct regulator *cpvdd;
+       struct regulator *dbvdd2;
+       struct regulator *dbvdd3;
+
+       int rev;
+
+       int sysclk;
+       int asyncclk;
+
+       bool aif_async[WM5100_AIFS];
+       bool aif_symmetric[WM5100_AIFS];
+       int sr_ref[WM5100_SYNC_SRS];
+
+       bool out_ena[2];
+
+       struct wm5100_fll fll[2];
+
+       struct wm5100_pdata pdata;
+
+#ifdef CONFIG_GPIOLIB
+       struct gpio_chip gpio_chip;
+#endif
+};
+
+static int wm5100_sr_code[] = {
+       0,
+       12000,
+       24000,
+       48000,
+       96000,
+       192000,
+       384000,
+       768000,
+       0,
+       11025,
+       22050,
+       44100,
+       88200,
+       176400,
+       352800,
+       705600,
+       4000,
+       8000,
+       16000,
+       32000,
+       64000,
+       128000,
+       256000,
+       512000,
+};
+
+static int wm5100_sr_regs[WM5100_SYNC_SRS] = {
+       WM5100_CLOCKING_4,
+       WM5100_CLOCKING_5,
+       WM5100_CLOCKING_6,
+};
+
+static int wm5100_alloc_sr(struct snd_soc_codec *codec, int rate)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int sr_code, sr_free, i;
+
+       for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+               if (wm5100_sr_code[i] == rate)
+                       break;
+       if (i == ARRAY_SIZE(wm5100_sr_code)) {
+               dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
+               return -EINVAL;
+       }
+       sr_code = i;
+
+       if ((wm5100->sysclk % rate) == 0) {
+               /* Is this rate already in use? */
+               sr_free = -1;
+               for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
+                       if (!wm5100->sr_ref[i] && sr_free == -1) {
+                               sr_free = i;
+                               continue;
+                       }
+                       if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
+                            WM5100_SAMPLE_RATE_1_MASK) == sr_code)
+                               break;
+               }
+
+               if (i < ARRAY_SIZE(wm5100_sr_regs)) {
+                       wm5100->sr_ref[i]++;
+                       dev_dbg(codec->dev, "SR %dHz, slot %d, ref %d\n",
+                               rate, i, wm5100->sr_ref[i]);
+                       return i;
+               }
+
+               if (sr_free == -1) {
+                       dev_err(codec->dev, "All SR slots already in use\n");
+                       return -EBUSY;
+               }
+
+               dev_dbg(codec->dev, "Allocating SR slot %d for %dHz\n",
+                       sr_free, rate);
+               wm5100->sr_ref[sr_free]++;
+               snd_soc_update_bits(codec, wm5100_sr_regs[sr_free],
+                                   WM5100_SAMPLE_RATE_1_MASK,
+                                   sr_code);
+
+               return sr_free;
+
+       } else {
+               dev_err(codec->dev,
+                       "SR %dHz incompatible with %dHz SYSCLK and %dHz ASYNCCLK\n",
+                       rate, wm5100->sysclk, wm5100->asyncclk);
+               return -EINVAL;
+       }
+}
+
+static void wm5100_free_sr(struct snd_soc_codec *codec, int rate)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int i, sr_code;
+
+       for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+               if (wm5100_sr_code[i] == rate)
+                       break;
+       if (i == ARRAY_SIZE(wm5100_sr_code)) {
+               dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
+               return;
+       }
+       sr_code = wm5100_sr_code[i];
+
+       for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
+               if (!wm5100->sr_ref[i])
+                       continue;
+
+               if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
+                    WM5100_SAMPLE_RATE_1_MASK) == sr_code)
+                       break;
+       }
+       if (i < ARRAY_SIZE(wm5100_sr_regs)) {
+               wm5100->sr_ref[i]--;
+               dev_dbg(codec->dev, "Dereference SR %dHz, count now %d\n",
+                       rate, wm5100->sr_ref[i]);
+       } else {
+               dev_warn(codec->dev, "Freeing unreferenced sample rate %dHz\n",
+                        rate);
+       }
+}
+
+static int wm5100_reset(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+
+       if (wm5100->pdata.reset) {
+               gpio_set_value_cansleep(wm5100->pdata.reset, 0);
+               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+
+               return 0;
+       } else {
+               return snd_soc_write(codec, WM5100_SOFTWARE_RESET, 0);
+       }
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static DECLARE_TLV_DB_SCALE(mixer_tlv, -3200, 100, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+
+static const char *wm5100_mixer_texts[] = {
+       "None",
+       "Tone Generator 1",
+       "Tone Generator 2",
+       "AEC loopback",
+       "IN1L",
+       "IN1R",
+       "IN2L",
+       "IN2R",
+       "IN3L",
+       "IN3R",
+       "IN4L",
+       "IN4R",
+       "AIF1RX1",
+       "AIF1RX2",
+       "AIF1RX3",
+       "AIF1RX4",
+       "AIF1RX5",
+       "AIF1RX6",
+       "AIF1RX7",
+       "AIF1RX8",
+       "AIF2RX1",
+       "AIF2RX2",
+       "AIF3RX1",
+       "AIF3RX2",
+       "EQ1",
+       "EQ2",
+       "EQ3",
+       "EQ4",
+       "DRC1L",
+       "DRC1R",
+       "LHPF1",
+       "LHPF2",
+       "LHPF3",
+       "LHPF4",
+       "DSP1.1",
+       "DSP1.2",
+       "DSP1.3",
+       "DSP1.4",
+       "DSP1.5",
+       "DSP1.6",
+       "DSP2.1",
+       "DSP2.2",
+       "DSP2.3",
+       "DSP2.4",
+       "DSP2.5",
+       "DSP2.6",
+       "DSP3.1",
+       "DSP3.2",
+       "DSP3.3",
+       "DSP3.4",
+       "DSP3.5",
+       "DSP3.6",
+       "ASRC1L",
+       "ASRC1R",
+       "ASRC2L",
+       "ASRC2R",
+       "ISRC1INT1",
+       "ISRC1INT2",
+       "ISRC1INT3",
+       "ISRC1INT4",
+       "ISRC2INT1",
+       "ISRC2INT2",
+       "ISRC2INT3",
+       "ISRC2INT4",
+       "ISRC1DEC1",
+       "ISRC1DEC2",
+       "ISRC1DEC3",
+       "ISRC1DEC4",
+       "ISRC2DEC1",
+       "ISRC2DEC2",
+       "ISRC2DEC3",
+       "ISRC2DEC4",
+};
+
+static int wm5100_mixer_values[] = {
+       0x00,
+       0x04,   /* Tone */
+       0x05,
+       0x08,   /* AEC */
+       0x10,   /* Input */
+       0x11,
+       0x12,
+       0x13,
+       0x14,
+       0x15,
+       0x16,
+       0x17,
+       0x20,   /* AIF */
+       0x21,
+       0x22,
+       0x23,
+       0x24,
+       0x25,
+       0x26,
+       0x27,
+       0x28,
+       0x29,
+       0x30,   /* AIF3 - check */
+       0x31,
+       0x50,   /* EQ */
+       0x51,
+       0x52,
+       0x53,
+       0x54,
+       0x58,   /* DRC */
+       0x59,
+       0x60,   /* LHPF1 */
+       0x61,   /* LHPF2 */
+       0x62,   /* LHPF3 */
+       0x63,   /* LHPF4 */
+       0x68,   /* DSP1 */
+       0x69,
+       0x6a,
+       0x6b,
+       0x6c,
+       0x6d,
+       0x70,   /* DSP2 */
+       0x71,
+       0x72,
+       0x73,
+       0x74,
+       0x75,
+       0x78,   /* DSP3 */
+       0x79,
+       0x7a,
+       0x7b,
+       0x7c,
+       0x7d,
+       0x90,   /* ASRC1 */
+       0x91,
+       0x92,   /* ASRC2 */
+       0x93,
+       0xa0,   /* ISRC1DEC1 */
+       0xa1,
+       0xa2,
+       0xa3,
+       0xa4,   /* ISRC1INT1 */
+       0xa5,
+       0xa6,
+       0xa7,
+       0xa8,   /* ISRC2DEC1 */
+       0xa9,
+       0xaa,
+       0xab,
+       0xac,   /* ISRC2INT1 */
+       0xad,
+       0xae,
+       0xaf,
+};
+
+#define WM5100_MIXER_CONTROLS(name, base) \
+       SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+                      WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+                      WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+                      WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+                      WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM5100_MUX_ENUM_DECL(name, reg) \
+       SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff,                  \
+                                  wm5100_mixer_texts, wm5100_mixer_values)
+
+#define WM5100_MUX_CTL_DECL(name) \
+       const struct snd_kcontrol_new name##_mux =      \
+               SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM5100_MIXER_ENUMS(name, base_reg) \
+       static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg);      \
+       static WM5100_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
+       static WM5100_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
+       static WM5100_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
+       static WM5100_MUX_CTL_DECL(name##_in1); \
+       static WM5100_MUX_CTL_DECL(name##_in2); \
+       static WM5100_MUX_CTL_DECL(name##_in3); \
+       static WM5100_MUX_CTL_DECL(name##_in4) 
+
+WM5100_MIXER_ENUMS(HPOUT1L, WM5100_OUT1LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT1R, WM5100_OUT1RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT2L, WM5100_OUT2LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT2R, WM5100_OUT2RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT3L, WM5100_OUT3LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT3R, WM5100_OUT3RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(SPKOUTL, WM5100_OUT4LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKOUTR, WM5100_OUT4RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT1L, WM5100_OUT5LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT1R, WM5100_OUT5RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT2L, WM5100_OUT6LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT2R, WM5100_OUT6RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(PWM1, WM5100_PWM1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(PWM2, WM5100_PWM1MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF1TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX3, WM5100_AIF1TX3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX4, WM5100_AIF1TX4MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX5, WM5100_AIF1TX5MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX6, WM5100_AIF1TX6MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX7, WM5100_AIF1TX7MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX8, WM5100_AIF1TX8MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF2TX1, WM5100_AIF2TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF2TX2, WM5100_AIF2TX2MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF3TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF3TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(EQ1, WM5100_EQ1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ2, WM5100_EQ2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ3, WM5100_EQ3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ4, WM5100_EQ4MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(DRC1L, WM5100_DRC1LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(DRC1R, WM5100_DRC1RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(LHPF1, WM5100_HPLP1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF2, WM5100_HPLP2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE);
+
+#define WM5100_MUX(name, ctrl) \
+       SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM5100_MIXER_WIDGETS(name, name_str)   \
+       WM5100_MUX(name_str " Input 1", &name##_in1_mux), \
+       WM5100_MUX(name_str " Input 2", &name##_in2_mux), \
+       WM5100_MUX(name_str " Input 3", &name##_in3_mux), \
+       WM5100_MUX(name_str " Input 4", &name##_in4_mux), \
+       SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM5100_MIXER_INPUT_ROUTES(name)        \
+       { name, "Tone Generator 1", "Tone Generator 1" }, \
+        { name, "Tone Generator 2", "Tone Generator 2" }, \
+        { name, "IN1L", "IN1L PGA" }, \
+        { name, "IN1R", "IN1R PGA" }, \
+        { name, "IN2L", "IN2L PGA" }, \
+        { name, "IN2R", "IN2R PGA" }, \
+        { name, "IN3L", "IN3L PGA" }, \
+        { name, "IN3R", "IN3R PGA" }, \
+        { name, "IN4L", "IN4L PGA" }, \
+        { name, "IN4R", "IN4R PGA" }, \
+        { name, "AIF1RX1", "AIF1RX1" }, \
+        { name, "AIF1RX2", "AIF1RX2" }, \
+        { name, "AIF1RX3", "AIF1RX3" }, \
+        { name, "AIF1RX4", "AIF1RX4" }, \
+        { name, "AIF1RX5", "AIF1RX5" }, \
+        { name, "AIF1RX6", "AIF1RX6" }, \
+        { name, "AIF1RX7", "AIF1RX7" }, \
+        { name, "AIF1RX8", "AIF1RX8" }, \
+        { name, "AIF2RX1", "AIF2RX1" }, \
+        { name, "AIF2RX2", "AIF2RX2" }, \
+        { name, "AIF3RX1", "AIF3RX1" }, \
+        { name, "AIF3RX2", "AIF3RX2" }, \
+        { name, "EQ1", "EQ1" }, \
+        { name, "EQ2", "EQ2" }, \
+        { name, "EQ3", "EQ3" }, \
+        { name, "EQ4", "EQ4" }, \
+        { name, "DRC1L", "DRC1L" }, \
+        { name, "DRC1R", "DRC1R" }, \
+        { name, "LHPF1", "LHPF1" }, \
+        { name, "LHPF2", "LHPF2" }, \
+        { name, "LHPF3", "LHPF3" }, \
+        { name, "LHPF4", "LHPF4" }
+
+#define WM5100_MIXER_ROUTES(widget, name) \
+       { widget, NULL, name " Mixer" },         \
+       { name " Mixer", NULL, name " Input 1" }, \
+       { name " Mixer", NULL, name " Input 2" }, \
+       { name " Mixer", NULL, name " Input 3" }, \
+       { name " Mixer", NULL, name " Input 4" }, \
+       WM5100_MIXER_INPUT_ROUTES(name " Input 1"), \
+       WM5100_MIXER_INPUT_ROUTES(name " Input 2"), \
+       WM5100_MIXER_INPUT_ROUTES(name " Input 3"), \
+       WM5100_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const char *wm5100_lhpf_mode_text[] = {
+       "Low-pass", "High-pass"
+};
+
+static const struct soc_enum wm5100_lhpf1_mode =
+       SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2,
+                       wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf2_mode =
+       SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2,
+                       wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf3_mode =
+       SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2,
+                       wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf4_mode =
+       SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2,
+                       wm5100_lhpf_mode_text);
+
+static const struct snd_kcontrol_new wm5100_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL,
+          WM5100_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM5100_IN2L_CONTROL,
+          WM5100_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM5100_IN3L_CONTROL,
+          WM5100_IN3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN4 High Performance Switch", WM5100_IN4L_CONTROL,
+          WM5100_IN4_OSR_SHIFT, 1, 0),
+
+/* Only applicable for analogue inputs */
+SOC_DOUBLE_R_TLV("IN1 Volume", WM5100_IN1L_CONTROL, WM5100_IN1R_CONTROL,
+                WM5100_IN1L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM5100_IN2L_CONTROL, WM5100_IN2R_CONTROL,
+                WM5100_IN2L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM5100_IN3L_CONTROL, WM5100_IN3R_CONTROL,
+                WM5100_IN3L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN4 Volume", WM5100_IN4L_CONTROL, WM5100_IN4R_CONTROL,
+                WM5100_IN4L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_1L,
+                WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_VOL_SHIFT, 191,
+                0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_2L,
+                WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_VOL_SHIFT, 191,
+                0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_3L,
+                WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_VOL_SHIFT, 191,
+                0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN4 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_4L,
+                WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_VOL_SHIFT, 191,
+                0, digital_tlv),
+
+SOC_DOUBLE_R("IN1 Switch", WM5100_ADC_DIGITAL_VOLUME_1L,
+            WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Switch", WM5100_ADC_DIGITAL_VOLUME_2L,
+            WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Switch", WM5100_ADC_DIGITAL_VOLUME_3L,
+            WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN4 Switch", WM5100_ADC_DIGITAL_VOLUME_4L,
+            WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_MUTE_SHIFT, 1, 1),
+
+SOC_SINGLE("HPOUT1 High Performance Switch", WM5100_OUT_VOLUME_1L,
+          WM5100_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT2 High Performance Switch", WM5100_OUT_VOLUME_2L,
+          WM5100_OUT2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT3 High Performance Switch", WM5100_OUT_VOLUME_3L,
+          WM5100_OUT3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKOUT High Performance Switch", WM5100_OUT_VOLUME_4L,
+          WM5100_OUT4_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT1 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_5L,
+          WM5100_OUT5_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT2 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_6L,
+          WM5100_OUT6_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_1L,
+                WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_2L,
+                WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_3L,
+                WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("SPKOUT Digital Volume", WM5100_DAC_DIGITAL_VOLUME_4L,
+                WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_5L,
+                WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_6L,
+                WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+
+SOC_DOUBLE_R("HPOUT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_1L,
+            WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("HPOUT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_2L,
+            WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("HPOUT3 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_3L,
+            WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKOUT Digital Switch", WM5100_DAC_DIGITAL_VOLUME_4L,
+            WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_5L,
+            WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_6L,
+            WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_MUTE_SHIFT, 1, 1),
+
+/* FIXME: Only valid from -12dB to 0dB (52-64) */
+SOC_DOUBLE_R_TLV("HPOUT1 Volume", WM5100_OUT_VOLUME_1L, WM5100_OUT_VOLUME_1R,
+                WM5100_OUT1L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("HPOUT2 Volume", WM5100_OUT_VOLUME_2L, WM5100_OUT_VOLUME_2R,
+                WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("HPOUT3 Volume", WM5100_OUT_VOLUME_3L, WM5100_OUT_VOLUME_3R,
+                WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+
+SOC_DOUBLE("SPKDAT1 Switch", WM5100_PDM_SPK1_CTRL_1, WM5100_SPK1L_MUTE_SHIFT,
+          WM5100_SPK1R_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE("SPKDAT2 Switch", WM5100_PDM_SPK2_CTRL_1, WM5100_SPK2L_MUTE_SHIFT,
+          WM5100_SPK2R_MUTE_SHIFT, 1, 1),
+
+SOC_SINGLE_TLV("EQ1 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ1_B1_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 2 Volume", WM5100_EQ1_1, WM5100_EQ1_B2_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 3 Volume", WM5100_EQ1_1, WM5100_EQ1_B3_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 4 Volume", WM5100_EQ1_2, WM5100_EQ1_B4_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 5 Volume", WM5100_EQ1_2, WM5100_EQ1_B5_GAIN_SHIFT,
+              24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ2 Band 1 Volume", WM5100_EQ2_1, WM5100_EQ2_B1_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 2 Volume", WM5100_EQ2_1, WM5100_EQ2_B2_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 3 Volume", WM5100_EQ2_1, WM5100_EQ2_B3_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 4 Volume", WM5100_EQ2_2, WM5100_EQ2_B4_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 5 Volume", WM5100_EQ2_2, WM5100_EQ2_B5_GAIN_SHIFT,
+              24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ3 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ3_B1_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 2 Volume", WM5100_EQ3_1, WM5100_EQ3_B2_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 3 Volume", WM5100_EQ3_1, WM5100_EQ3_B3_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 4 Volume", WM5100_EQ3_2, WM5100_EQ3_B4_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 5 Volume", WM5100_EQ3_2, WM5100_EQ3_B5_GAIN_SHIFT,
+              24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ4 Band 1 Volume", WM5100_EQ4_1, WM5100_EQ4_B1_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 2 Volume", WM5100_EQ4_1, WM5100_EQ4_B2_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 3 Volume", WM5100_EQ4_1, WM5100_EQ4_B3_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 4 Volume", WM5100_EQ4_2, WM5100_EQ4_B4_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 5 Volume", WM5100_EQ4_2, WM5100_EQ4_B5_GAIN_SHIFT,
+              24, 0, eq_tlv),
+
+SOC_ENUM("LHPF1 Mode", wm5100_lhpf1_mode),
+SOC_ENUM("LHPF2 Mode", wm5100_lhpf2_mode),
+SOC_ENUM("LHPF3 Mode", wm5100_lhpf3_mode),
+SOC_ENUM("LHPF4 Mode", wm5100_lhpf4_mode),
+
+WM5100_MIXER_CONTROLS("HPOUT1L", WM5100_OUT1LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT1R", WM5100_OUT1RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT2L", WM5100_OUT2LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT2R", WM5100_OUT2RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT3L", WM5100_OUT3LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT3R", WM5100_OUT3RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("SPKOUTL", WM5100_OUT4LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKOUTR", WM5100_OUT4RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT1L", WM5100_OUT5LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT1R", WM5100_OUT5RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT2L", WM5100_OUT6LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT2R", WM5100_OUT6RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("PWM1", WM5100_PWM1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("PWM2", WM5100_PWM2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF1TX1", WM5100_AIF1TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX2", WM5100_AIF1TX2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX3", WM5100_AIF1TX3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX4", WM5100_AIF1TX4MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX5", WM5100_AIF1TX5MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX6", WM5100_AIF1TX6MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX7", WM5100_AIF1TX7MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX8", WM5100_AIF1TX8MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF2TX1", WM5100_AIF2TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF2TX2", WM5100_AIF2TX2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF3TX1", WM5100_AIF3TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF3TX2", WM5100_AIF3TX2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("EQ1", WM5100_EQ1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ2", WM5100_EQ2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ3", WM5100_EQ3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF3", WM5100_HPLP3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE),
+};
+
+static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm,
+                               enum snd_soc_dapm_type event, int subseq)
+{
+       struct snd_soc_codec *codec = container_of(dapm,
+                                                  struct snd_soc_codec, dapm);
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       u16 val, expect, i;
+
+       /* Wait for the outputs to flag themselves as enabled */
+       if (wm5100->out_ena[0]) {
+               expect = snd_soc_read(codec, WM5100_CHANNEL_ENABLES_1);
+               for (i = 0; i < 200; i++) {
+                       val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_1);
+                       if (val == expect) {
+                               wm5100->out_ena[0] = false;
+                               break;
+                       }
+               }
+               if (i == 200) {
+                       dev_err(codec->dev, "Timeout waiting for OUTPUT1 %x\n",
+                               expect);
+               }
+       }
+
+       if (wm5100->out_ena[1]) {
+               expect = snd_soc_read(codec, WM5100_OUTPUT_ENABLES_2);
+               for (i = 0; i < 200; i++) {
+                       val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_2);
+                       if (val == expect) {
+                               wm5100->out_ena[1] = false;
+                               break;
+                       }
+               }
+               if (i == 200) {
+                       dev_err(codec->dev, "Timeout waiting for OUTPUT2 %x\n",
+                               expect);
+               }
+       }
+}
+
+static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol,
+                        int event)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec);
+
+       switch (w->reg) {
+       case WM5100_CHANNEL_ENABLES_1:
+               wm5100->out_ena[0] = true;
+               break;
+       case WM5100_OUTPUT_ENABLES_2:
+               wm5100->out_ena[0] = true;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int wm5100_cp_ev(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *kcontrol,
+                       int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               ret = regulator_enable(wm5100->cpvdd);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
+                               ret);
+                       return ret;
+               }
+               return ret;
+
+       case SND_SOC_DAPM_POST_PMD:
+               ret = regulator_disable_deferred(wm5100->cpvdd, 20);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to disable CPVDD: %d\n",
+                               ret);
+                       return ret;
+               }
+               return ret;
+
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w,
+                          struct snd_kcontrol *kcontrol,
+                          int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct regulator *regulator;
+       int ret;
+
+       switch (w->shift) {
+       case 2:
+               regulator = wm5100->dbvdd2;
+               break;
+       case 3:
+               regulator = wm5100->dbvdd3;
+               break;
+       default:
+               BUG();
+               return 0;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               ret = regulator_enable(regulator);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
+                               w->shift, ret);
+                       return ret;
+               }
+               return ret;
+
+       case SND_SOC_DAPM_POST_PMD:
+               ret = regulator_disable(regulator);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
+                               w->shift, ret);
+                       return ret;
+               }
+               return ret;
+
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static void wm5100_log_status3(struct snd_soc_codec *codec, int val)
+{
+       if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
+               dev_crit(codec->dev, "Speaker shutdown warning\n");
+       if (val & WM5100_SPK_SHUTDOWN_EINT)
+               dev_crit(codec->dev, "Speaker shutdown\n");
+       if (val & WM5100_CLKGEN_ERR_EINT)
+               dev_crit(codec->dev, "SYSCLK underclocked\n");
+       if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
+               dev_crit(codec->dev, "ASYNCCLK underclocked\n");
+}
+
+static void wm5100_log_status4(struct snd_soc_codec *codec, int val)
+{
+       if (val & WM5100_AIF3_ERR_EINT)
+               dev_err(codec->dev, "AIF3 configuration error\n");
+       if (val & WM5100_AIF2_ERR_EINT)
+               dev_err(codec->dev, "AIF2 configuration error\n");
+       if (val & WM5100_AIF1_ERR_EINT)
+               dev_err(codec->dev, "AIF1 configuration error\n");
+       if (val & WM5100_CTRLIF_ERR_EINT)
+               dev_err(codec->dev, "Control interface error\n");
+       if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "ISRC2 underclocked\n");
+       if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "ISRC1 underclocked\n");
+       if (val & WM5100_FX_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "FX underclocked\n");
+       if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "AIF3 underclocked\n");
+       if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "AIF2 underclocked\n");
+       if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "AIF1 underclocked\n");
+       if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "ASRC underclocked\n");
+       if (val & WM5100_DAC_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "DAC underclocked\n");
+       if (val & WM5100_ADC_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "ADC underclocked\n");
+       if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "Mixer underclocked\n");
+}
+
+static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
+                         struct snd_kcontrol *kcontrol,
+                         int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       int ret;
+
+       ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
+       ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
+               WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
+               WM5100_CLKGEN_ERR_ASYNC_STS;
+       wm5100_log_status3(codec, ret);
+
+       ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
+       wm5100_log_status4(codec, ret);
+
+       return 0;
+}
+
+static const struct snd_soc_dapm_widget wm5100_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
+                   0, NULL, 0),
+
+SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
+                   wm5100_cp_ev,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
+                   WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
+                   0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM5100_MIC_BIAS_CTRL_2, WM5100_MICB2_ENA_SHIFT,
+                   0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS3", WM5100_MIC_BIAS_CTRL_3, WM5100_MICB3_ENA_SHIFT,
+                   0, NULL, 0),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+SND_SOC_DAPM_INPUT("IN4L"),
+SND_SOC_DAPM_INPUT("IN4R"),
+SND_SOC_DAPM_INPUT("TONE"),
+
+SND_SOC_DAPM_PGA_E("IN1L PGA", WM5100_INPUT_ENABLES, WM5100_IN1L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN1R PGA", WM5100_INPUT_ENABLES, WM5100_IN1R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2L PGA", WM5100_INPUT_ENABLES, WM5100_IN2L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2R PGA", WM5100_INPUT_ENABLES, WM5100_IN2R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3L PGA", WM5100_INPUT_ENABLES, WM5100_IN3L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3R PGA", WM5100_INPUT_ENABLES, WM5100_IN3R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4L PGA", WM5100_INPUT_ENABLES, WM5100_IN4L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4R PGA", WM5100_INPUT_ENABLES, WM5100_IN4R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("Tone Generator 1", WM5100_TONE_GENERATOR_1,
+                WM5100_TONE1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Tone Generator 2", WM5100_TONE_GENERATOR_1,
+                WM5100_TONE2_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 0,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 1,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 2,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 3,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 4,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "AIF1 Playback", 5,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX7", "AIF1 Playback", 6,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX8", "AIF1 Playback", 7,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
+                   WM5100_AUDIO_IF_2_27, WM5100_AIF2RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX2", "AIF2 Playback", 1,
+                   WM5100_AUDIO_IF_2_27, WM5100_AIF2RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF3RX1", "AIF3 Playback", 0,
+                   WM5100_AUDIO_IF_3_27, WM5100_AIF3RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF3RX2", "AIF3 Playback", 1,
+                   WM5100_AUDIO_IF_3_27, WM5100_AIF3RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 0,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 1,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 2,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 3,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 4,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "AIF1 Capture", 5,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX7", "AIF1 Capture", 6,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX8", "AIF1 Capture", 7,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
+                   WM5100_AUDIO_IF_2_26, WM5100_AIF2TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX2", "AIF2 Capture", 1,
+                   WM5100_AUDIO_IF_2_26, WM5100_AIF2TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF3TX1", "AIF3 Capture", 0,
+                   WM5100_AUDIO_IF_3_26, WM5100_AIF3TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3TX2", "AIF3 Capture", 1,
+                   WM5100_AUDIO_IF_3_26, WM5100_AIF3TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_E("OUT6L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT6R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3L", WM5100_CHANNEL_ENABLES_1, WM5100_HP3L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3R", WM5100_CHANNEL_ENABLES_1, WM5100_HP3R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2L", WM5100_CHANNEL_ENABLES_1, WM5100_HP2L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2R", WM5100_CHANNEL_ENABLES_1, WM5100_HP2R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1L", WM5100_CHANNEL_ENABLES_1, WM5100_HP1L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1R", WM5100_CHANNEL_ENABLES_1, WM5100_HP1R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("PWM1 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM1_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("PWM2 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM2_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("EQ1", WM5100_EQ1_1, WM5100_EQ1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ2", WM5100_EQ2_1, WM5100_EQ2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ3", WM5100_EQ3_1, WM5100_EQ3_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ4", WM5100_EQ4_1, WM5100_EQ4_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("DRC1L", WM5100_DRC1_CTRL1, WM5100_DRCL_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("DRC1R", WM5100_DRC1_CTRL1, WM5100_DRCR_ENA_SHIFT, 0,
+                NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM5100_HPLPF1_1, WM5100_LHPF1_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM5100_HPLPF2_1, WM5100_LHPF2_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LHPF3", WM5100_HPLPF3_1, WM5100_LHPF3_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LHPF4", WM5100_HPLPF4_1, WM5100_LHPF4_ENA_SHIFT, 0,
+                NULL, 0),
+
+WM5100_MIXER_WIDGETS(EQ1, "EQ1"),
+WM5100_MIXER_WIDGETS(EQ2, "EQ2"),
+WM5100_MIXER_WIDGETS(EQ3, "EQ3"),
+WM5100_MIXER_WIDGETS(EQ4, "EQ4"),
+
+WM5100_MIXER_WIDGETS(DRC1L, "DRC1L"),
+WM5100_MIXER_WIDGETS(DRC1R, "DRC1R"),
+
+WM5100_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM5100_MIXER_WIDGETS(LHPF2, "LHPF2"),
+WM5100_MIXER_WIDGETS(LHPF3, "LHPF3"),
+WM5100_MIXER_WIDGETS(LHPF4, "LHPF4"),
+
+WM5100_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM5100_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM5100_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM5100_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM5100_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM5100_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+WM5100_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
+WM5100_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
+
+WM5100_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
+WM5100_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+
+WM5100_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
+WM5100_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
+
+WM5100_MIXER_WIDGETS(HPOUT1L, "HPOUT1L"),
+WM5100_MIXER_WIDGETS(HPOUT1R, "HPOUT1R"),
+WM5100_MIXER_WIDGETS(HPOUT2L, "HPOUT2L"),
+WM5100_MIXER_WIDGETS(HPOUT2R, "HPOUT2R"),
+WM5100_MIXER_WIDGETS(HPOUT3L, "HPOUT3L"),
+WM5100_MIXER_WIDGETS(HPOUT3R, "HPOUT3R"),
+
+WM5100_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
+WM5100_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
+WM5100_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
+WM5100_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
+WM5100_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"),
+WM5100_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"),
+
+WM5100_MIXER_WIDGETS(PWM1, "PWM1"),
+WM5100_MIXER_WIDGETS(PWM2, "PWM2"),
+
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("HPOUT2L"),
+SND_SOC_DAPM_OUTPUT("HPOUT2R"),
+SND_SOC_DAPM_OUTPUT("HPOUT3L"),
+SND_SOC_DAPM_OUTPUT("HPOUT3R"),
+SND_SOC_DAPM_OUTPUT("SPKOUTL"),
+SND_SOC_DAPM_OUTPUT("SPKOUTR"),
+SND_SOC_DAPM_OUTPUT("SPKDAT1"),
+SND_SOC_DAPM_OUTPUT("SPKDAT2"),
+SND_SOC_DAPM_OUTPUT("PWM1"),
+SND_SOC_DAPM_OUTPUT("PWM2"),
+};
+
+/* We register a _POST event if we don't have IRQ support so we can
+ * look at the error status from the CODEC - if we've got the IRQ
+ * hooked up then we will get prompted to look by an interrupt.
+ */
+static const struct snd_soc_dapm_widget wm5100_dapm_widgets_noirq[] = {
+SND_SOC_DAPM_POST("Post", wm5100_post_ev),
+};
+
+static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+       { "IN1L", NULL, "SYSCLK" },
+       { "IN1R", NULL, "SYSCLK" },
+       { "IN2L", NULL, "SYSCLK" },
+       { "IN2R", NULL, "SYSCLK" },
+       { "IN3L", NULL, "SYSCLK" },
+       { "IN3R", NULL, "SYSCLK" },
+       { "IN4L", NULL, "SYSCLK" },
+       { "IN4R", NULL, "SYSCLK" },
+
+       { "OUT1L", NULL, "SYSCLK" },
+       { "OUT1R", NULL, "SYSCLK" },
+       { "OUT2L", NULL, "SYSCLK" },
+       { "OUT2R", NULL, "SYSCLK" },
+       { "OUT3L", NULL, "SYSCLK" },
+       { "OUT3R", NULL, "SYSCLK" },
+       { "OUT4L", NULL, "SYSCLK" },
+       { "OUT4R", NULL, "SYSCLK" },
+       { "OUT5L", NULL, "SYSCLK" },
+       { "OUT5R", NULL, "SYSCLK" },
+       { "OUT6L", NULL, "SYSCLK" },
+       { "OUT6R", NULL, "SYSCLK" },
+
+       { "AIF1RX1", NULL, "SYSCLK" },
+       { "AIF1RX2", NULL, "SYSCLK" },
+       { "AIF1RX3", NULL, "SYSCLK" },
+       { "AIF1RX4", NULL, "SYSCLK" },
+       { "AIF1RX5", NULL, "SYSCLK" },
+       { "AIF1RX6", NULL, "SYSCLK" },
+       { "AIF1RX7", NULL, "SYSCLK" },
+       { "AIF1RX8", NULL, "SYSCLK" },
+
+       { "AIF2RX1", NULL, "SYSCLK" },
+       { "AIF2RX1", NULL, "DBVDD2" },
+       { "AIF2RX2", NULL, "SYSCLK" },
+       { "AIF2RX2", NULL, "DBVDD2" },
+
+       { "AIF3RX1", NULL, "SYSCLK" },
+       { "AIF3RX1", NULL, "DBVDD3" },
+       { "AIF3RX2", NULL, "SYSCLK" },
+       { "AIF3RX2", NULL, "DBVDD3" },
+
+       { "AIF1TX1", NULL, "SYSCLK" },
+       { "AIF1TX2", NULL, "SYSCLK" },
+       { "AIF1TX3", NULL, "SYSCLK" },
+       { "AIF1TX4", NULL, "SYSCLK" },
+       { "AIF1TX5", NULL, "SYSCLK" },
+       { "AIF1TX6", NULL, "SYSCLK" },
+       { "AIF1TX7", NULL, "SYSCLK" },
+       { "AIF1TX8", NULL, "SYSCLK" },
+
+       { "AIF2TX1", NULL, "SYSCLK" },
+       { "AIF2TX1", NULL, "DBVDD2" },
+       { "AIF2TX2", NULL, "SYSCLK" },
+       { "AIF2TX2", NULL, "DBVDD2" },
+
+       { "AIF3TX1", NULL, "SYSCLK" },
+       { "AIF3TX1", NULL, "DBVDD3" },
+       { "AIF3TX2", NULL, "SYSCLK" },
+       { "AIF3TX2", NULL, "DBVDD3" },
+
+       { "MICBIAS1", NULL, "CP2" },
+       { "MICBIAS2", NULL, "CP2" },
+       { "MICBIAS3", NULL, "CP2" },
+
+       { "IN1L PGA", NULL, "CP2" },
+       { "IN1R PGA", NULL, "CP2" },
+       { "IN2L PGA", NULL, "CP2" },
+       { "IN2R PGA", NULL, "CP2" },
+       { "IN3L PGA", NULL, "CP2" },
+       { "IN3R PGA", NULL, "CP2" },
+       { "IN4L PGA", NULL, "CP2" },
+       { "IN4R PGA", NULL, "CP2" },
+
+       { "IN1L PGA", NULL, "CP2 Active" },
+       { "IN1R PGA", NULL, "CP2 Active" },
+       { "IN2L PGA", NULL, "CP2 Active" },
+       { "IN2R PGA", NULL, "CP2 Active" },
+       { "IN3L PGA", NULL, "CP2 Active" },
+       { "IN3R PGA", NULL, "CP2 Active" },
+       { "IN4L PGA", NULL, "CP2 Active" },
+       { "IN4R PGA", NULL, "CP2 Active" },
+
+       { "OUT1L", NULL, "CP1" },
+       { "OUT1R", NULL, "CP1" },
+       { "OUT2L", NULL, "CP1" },
+       { "OUT2R", NULL, "CP1" },
+       { "OUT3L", NULL, "CP1" },
+       { "OUT3R", NULL, "CP1" },
+
+       { "Tone Generator 1", NULL, "TONE" },
+       { "Tone Generator 2", NULL, "TONE" },
+
+       { "IN1L PGA", NULL, "IN1L" },
+       { "IN1R PGA", NULL, "IN1R" },
+       { "IN2L PGA", NULL, "IN2L" },
+       { "IN2R PGA", NULL, "IN2R" },
+       { "IN3L PGA", NULL, "IN3L" },
+       { "IN3R PGA", NULL, "IN3R" },
+       { "IN4L PGA", NULL, "IN4L" },
+       { "IN4R PGA", NULL, "IN4R" },
+
+       WM5100_MIXER_ROUTES("OUT1L", "HPOUT1L"),
+       WM5100_MIXER_ROUTES("OUT1R", "HPOUT1R"),
+       WM5100_MIXER_ROUTES("OUT2L", "HPOUT2L"),
+       WM5100_MIXER_ROUTES("OUT2R", "HPOUT2R"),
+       WM5100_MIXER_ROUTES("OUT3L", "HPOUT3L"),
+       WM5100_MIXER_ROUTES("OUT3R", "HPOUT3R"),
+
+       WM5100_MIXER_ROUTES("OUT4L", "SPKOUTL"),
+       WM5100_MIXER_ROUTES("OUT4R", "SPKOUTR"),
+       WM5100_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
+       WM5100_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
+       WM5100_MIXER_ROUTES("OUT6L", "SPKDAT2L"),
+       WM5100_MIXER_ROUTES("OUT6R", "SPKDAT2R"),
+
+       WM5100_MIXER_ROUTES("PWM1 Driver", "PWM1"),
+       WM5100_MIXER_ROUTES("PWM2 Driver", "PWM2"),
+
+       WM5100_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+       WM5100_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+       WM5100_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+       WM5100_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+       WM5100_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+       WM5100_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+       WM5100_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
+       WM5100_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
+
+       WM5100_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
+       WM5100_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+
+       WM5100_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
+       WM5100_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
+
+       WM5100_MIXER_ROUTES("EQ1", "EQ1"),
+       WM5100_MIXER_ROUTES("EQ2", "EQ2"),
+       WM5100_MIXER_ROUTES("EQ3", "EQ3"),
+       WM5100_MIXER_ROUTES("EQ4", "EQ4"),
+
+       WM5100_MIXER_ROUTES("DRC1L", "DRC1L"),
+       WM5100_MIXER_ROUTES("DRC1R", "DRC1R"),
+
+       WM5100_MIXER_ROUTES("LHPF1", "LHPF1"),
+       WM5100_MIXER_ROUTES("LHPF2", "LHPF2"),
+       WM5100_MIXER_ROUTES("LHPF3", "LHPF3"),
+       WM5100_MIXER_ROUTES("LHPF4", "LHPF4"),
+
+       { "HPOUT1L", NULL, "OUT1L" },
+       { "HPOUT1R", NULL, "OUT1R" },
+       { "HPOUT2L", NULL, "OUT2L" },
+       { "HPOUT2R", NULL, "OUT2R" },
+       { "HPOUT3L", NULL, "OUT3L" },
+       { "HPOUT3R", NULL, "OUT3R" },
+       { "SPKOUTL", NULL, "OUT4L" },
+       { "SPKOUTR", NULL, "OUT4R" },
+       { "SPKDAT1", NULL, "OUT5L" },
+       { "SPKDAT1", NULL, "OUT5R" },
+       { "SPKDAT2", NULL, "OUT6L" },
+       { "SPKDAT2", NULL, "OUT6R" },
+       { "PWM1", NULL, "PWM1 Driver" },
+       { "PWM2", NULL, "PWM2 Driver" },
+};
+
+static struct {
+       int reg;
+       int val;
+} wm5100_reva_patches[] = {
+       { WM5100_AUDIO_IF_1_10, 0 },
+       { WM5100_AUDIO_IF_1_11, 1 },
+       { WM5100_AUDIO_IF_1_12, 2 },
+       { WM5100_AUDIO_IF_1_13, 3 },
+       { WM5100_AUDIO_IF_1_14, 4 },
+       { WM5100_AUDIO_IF_1_15, 5 },
+       { WM5100_AUDIO_IF_1_16, 6 },
+       { WM5100_AUDIO_IF_1_17, 7 },
+
+       { WM5100_AUDIO_IF_1_18, 0 },
+       { WM5100_AUDIO_IF_1_19, 1 },
+       { WM5100_AUDIO_IF_1_20, 2 },
+       { WM5100_AUDIO_IF_1_21, 3 },
+       { WM5100_AUDIO_IF_1_22, 4 },
+       { WM5100_AUDIO_IF_1_23, 5 },
+       { WM5100_AUDIO_IF_1_24, 6 },
+       { WM5100_AUDIO_IF_1_25, 7 },
+
+       { WM5100_AUDIO_IF_2_10, 0 },
+       { WM5100_AUDIO_IF_2_11, 1 },
+
+       { WM5100_AUDIO_IF_2_18, 0 },
+       { WM5100_AUDIO_IF_2_19, 1 },
+
+       { WM5100_AUDIO_IF_3_10, 0 },
+       { WM5100_AUDIO_IF_3_11, 1 },
+
+       { WM5100_AUDIO_IF_3_18, 0 },
+       { WM5100_AUDIO_IF_3_19, 1 },
+};
+
+static int wm5100_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret, i;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+                                                   wm5100->core_supplies);
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "Failed to enable supplies: %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       if (wm5100->pdata.ldo_ena) {
+                               gpio_set_value_cansleep(wm5100->pdata.ldo_ena,
+                                                       1);
+                               msleep(2);
+                       }
+
+                       codec->cache_only = false;
+
+                       switch (wm5100->rev) {
+                       case 0:
+                               snd_soc_write(codec, 0x11, 0x3);
+                               snd_soc_write(codec, 0x203, 0xc);
+                               snd_soc_write(codec, 0x206, 0);
+                               snd_soc_write(codec, 0x207, 0xf0);
+                               snd_soc_write(codec, 0x208, 0x3c);
+                               snd_soc_write(codec, 0x209, 0);
+                               snd_soc_write(codec, 0x211, 0x20d8);
+                               snd_soc_write(codec, 0x11, 0);
+
+                               for (i = 0;
+                                    i < ARRAY_SIZE(wm5100_reva_patches);
+                                    i++)
+                                       snd_soc_write(codec,
+                                                     wm5100_reva_patches[i].reg,
+                                                     wm5100_reva_patches[i].val);
+                               break;
+                       default:
+                               break;
+                       }
+
+                       snd_soc_cache_sync(codec);
+               }
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               if (wm5100->pdata.ldo_ena)
+                       gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+               regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+                                      wm5100->core_supplies);
+               break;
+       }
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
+
+static int wm5100_dai_to_base(struct snd_soc_dai *dai)
+{
+       switch (dai->id) {
+       case 0:
+               return WM5100_AUDIO_IF_1_1 - 1;
+       case 1:
+               return WM5100_AUDIO_IF_2_1 - 1;
+       case 2:
+               return WM5100_AUDIO_IF_3_1 - 1;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+}
+
+static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int lrclk, bclk, mask, base;
+
+       base = wm5100_dai_to_base(dai);
+       if (base < 0)
+               return base;
+
+       lrclk = 0;
+       bclk = 0;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               mask = 0;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               mask = 1;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               mask = 2;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               mask = 3;
+               break;
+       default:
+               dev_err(codec->dev, "Unsupported DAI format %d\n",
+                       fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               bclk |= WM5100_AIF1_BCLK_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
+               bclk |= WM5100_AIF1_BCLK_MSTR;
+               break;
+       default:
+               dev_err(codec->dev, "Unsupported master mode %d\n",
+                       fmt & SND_SOC_DAIFMT_MASTER_MASK);
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               bclk |= WM5100_AIF1_BCLK_INV;
+               lrclk |= WM5100_AIF1TX_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               bclk |= WM5100_AIF1_BCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               lrclk |= WM5100_AIF1TX_LRCLK_INV;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_MSTR |
+                           WM5100_AIF1_BCLK_INV, bclk);
+       snd_soc_update_bits(codec, base + 2, WM5100_AIF1TX_LRCLK_MSTR |
+                           WM5100_AIF1TX_LRCLK_INV, lrclk);
+       snd_soc_update_bits(codec, base + 3, WM5100_AIF1TX_LRCLK_MSTR |
+                           WM5100_AIF1TX_LRCLK_INV, lrclk);
+       snd_soc_update_bits(codec, base + 5, WM5100_AIF1_FMT_MASK, mask);
+
+       return 0;
+}
+
+#define WM5100_NUM_BCLK_RATES 19
+
+static int wm5100_bclk_rates_dat[WM5100_NUM_BCLK_RATES] = {
+       32000,
+       48000,
+       64000,
+       96000,
+       128000,
+       192000,
+       256000,
+       384000,
+       512000,
+       768000,
+       1024000,
+       1536000,
+       2048000,
+       3072000,
+       4096000,
+       6144000,
+       8192000,
+       12288000,
+       24576000,
+};
+
+static int wm5100_bclk_rates_cd[WM5100_NUM_BCLK_RATES] = {
+       29400,
+       44100,
+       58800,
+       88200,
+       117600,
+       176400,
+       235200,
+       352800,
+       470400,
+       705600,
+       940800,
+       1411200,
+       1881600,
+       2882400,
+       3763200,
+       5644800,
+       7526400,
+       11289600,
+       22579600,
+};
+
+static int wm5100_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       bool async = wm5100->aif_async[dai->id];
+       int i, base, bclk, aif_rate, lrclk, wl, fl, sr;
+       int *bclk_rates;
+
+       base = wm5100_dai_to_base(dai);
+       if (base < 0)
+               return base;
+
+       /* Data sizes if not using TDM */
+       wl = snd_pcm_format_width(params_format(params));
+       if (wl < 0)
+               return wl;
+       fl = snd_soc_params_to_frame_size(params);
+       if (fl < 0)
+               return fl;
+
+       dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+               wl, fl);
+
+       /* Target BCLK rate */
+       bclk = snd_soc_params_to_bclk(params);
+       if (bclk < 0)
+               return bclk;
+
+       /* Root for BCLK depends on SYS/ASYNCCLK */
+       if (!async) {
+               aif_rate = wm5100->sysclk;
+               sr = wm5100_alloc_sr(codec, params_rate(params));
+               if (sr < 0)
+                       return sr;
+       } else {
+               /* If we're in ASYNCCLK set the ASYNC sample rate */
+               aif_rate = wm5100->asyncclk;
+               sr = 3;
+
+               for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+                       if (params_rate(params) == wm5100_sr_code[i])
+                               break;
+               if (i == ARRAY_SIZE(wm5100_sr_code)) {
+                       dev_err(codec->dev, "Invalid rate %dHzn",
+                               params_rate(params));
+                       return -EINVAL;
+               }
+
+               /* TODO: We should really check for symmetry */
+               snd_soc_update_bits(codec, WM5100_CLOCKING_8,
+                                   WM5100_ASYNC_SAMPLE_RATE_MASK, i);
+       }
+
+       if (!aif_rate) {
+               dev_err(codec->dev, "%s has no rate set\n",
+                       async ? "ASYNCCLK" : "SYSCLK");
+               return -EINVAL;
+       }
+
+       dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz %s\n",
+               bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
+
+       if (aif_rate % 4000)
+               bclk_rates = wm5100_bclk_rates_cd;
+       else
+               bclk_rates = wm5100_bclk_rates_dat;
+
+       for (i = 0; i < WM5100_NUM_BCLK_RATES; i++)
+               if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+                       break;
+       if (i == WM5100_NUM_BCLK_RATES) {
+               dev_err(codec->dev,
+                       "No valid BCLK for %dHz found from %dHz %s\n",
+                       bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
+               return -EINVAL;
+       }
+
+       bclk = i;
+       dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+       snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_FREQ_MASK, bclk);
+
+       lrclk = bclk_rates[bclk] / params_rate(params);
+       dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+           wm5100->aif_symmetric[dai->id])
+               snd_soc_update_bits(codec, base + 7,
+                                   WM5100_AIF1RX_BCPF_MASK, lrclk);
+       else
+               snd_soc_update_bits(codec, base + 6,
+                                   WM5100_AIF1TX_BCPF_MASK, lrclk);
+
+       i = (wl << WM5100_AIF1TX_WL_SHIFT) | fl;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               snd_soc_update_bits(codec, base + 9,
+                                   WM5100_AIF1RX_WL_MASK |
+                                   WM5100_AIF1RX_SLOT_LEN_MASK, i);
+       else
+               snd_soc_update_bits(codec, base + 8,
+                                   WM5100_AIF1TX_WL_MASK |
+                                   WM5100_AIF1TX_SLOT_LEN_MASK, i);
+
+       snd_soc_update_bits(codec, base + 4, WM5100_AIF1_RATE_MASK, sr);
+
+       return 0;
+}
+
+static struct snd_soc_dai_ops wm5100_dai_ops = {
+       .set_fmt = wm5100_set_fmt,
+       .hw_params = wm5100_hw_params,
+};
+
+static int wm5100_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+                            int source, unsigned int freq, int dir)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int *rate_store;
+       int fval, audio_rate, ret, reg;
+
+       switch (clk_id) {
+       case WM5100_CLK_SYSCLK:
+               reg = WM5100_CLOCKING_3;
+               rate_store = &wm5100->sysclk;
+               break;
+       case WM5100_CLK_ASYNCCLK:
+               reg = WM5100_CLOCKING_7;
+               rate_store = &wm5100->asyncclk;
+               break;
+       case WM5100_CLK_32KHZ:
+               /* The 32kHz clock is slightly different to the others */
+               switch (source) {
+               case WM5100_CLKSRC_MCLK1:
+               case WM5100_CLKSRC_MCLK2:
+               case WM5100_CLKSRC_SYSCLK:
+                       snd_soc_update_bits(codec, WM5100_CLOCKING_1,
+                                           WM5100_CLK_32K_SRC_MASK,
+                                           source);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               return 0;
+
+       case WM5100_CLK_AIF1:
+       case WM5100_CLK_AIF2:
+       case WM5100_CLK_AIF3:
+               /* Not real clocks, record which clock domain they're in */
+               switch (source) {
+               case WM5100_CLKSRC_SYSCLK:
+                       wm5100->aif_async[clk_id - 1] = false;
+                       break;
+               case WM5100_CLKSRC_ASYNCCLK:
+                       wm5100->aif_async[clk_id - 1] = true;
+                       break;
+               default:
+                       dev_err(codec->dev, "Invalid source %d\n", source);
+                       return -EINVAL;
+               }       
+               return 0;
+
+       case WM5100_CLK_OPCLK:
+               switch (freq) {
+               case 5644800:
+               case 6144000:
+                       snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+                                           WM5100_OPCLK_SEL_MASK, 0);
+                       break;
+               case 11289600:
+               case 12288000:
+                       snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+                                           WM5100_OPCLK_SEL_MASK, 0);
+                       break;
+               case 22579200:
+               case 24576000:
+                       snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+                                           WM5100_OPCLK_SEL_MASK, 0);
+                       break;
+               default:
+                       dev_err(codec->dev, "Unsupported OPCLK %dHz\n",
+                               freq);
+                       return -EINVAL;
+               }
+               return 0;
+
+       default:
+               dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+               return -EINVAL;
+       }
+
+       switch (source) {
+       case WM5100_CLKSRC_SYSCLK:
+       case WM5100_CLKSRC_ASYNCCLK:
+               dev_err(codec->dev, "Invalid source %d\n", source);
+               return -EINVAL;
+       }
+
+       switch (freq) {
+       case 5644800:
+       case 6144000:
+               fval = 0;
+               break;
+       case 11289600:
+       case 12288000:
+               fval = 1;
+               break;
+       case 22579200:
+       case 2457600:
+               fval = 2;
+               break;
+       default:
+               dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+               return -EINVAL;
+       }
+
+       switch (freq) {
+       case 5644800:
+       case 11289600:
+       case 22579200:
+               audio_rate = 44100;
+               break;
+
+       case 6144000:
+       case 12288000:
+       case 2457600:
+               audio_rate = 48000;
+               break;
+
+       default:
+               BUG();
+               audio_rate = 0;
+               break;
+       }
+
+       /* TODO: Check if MCLKs are in use and enable/disable pulls to
+        * match.
+        */
+
+       snd_soc_update_bits(codec, reg, WM5100_SYSCLK_FREQ_MASK |
+                           WM5100_SYSCLK_SRC_MASK,
+                           fval << WM5100_SYSCLK_FREQ_SHIFT | source);
+
+       /* If this is SYSCLK then configure the clock rate for the
+        * internal audio functions to the natural sample rate for
+        * this clock rate.
+        */
+       if (clk_id == WM5100_CLK_SYSCLK) {
+               dev_dbg(codec->dev, "Setting primary audio rate to %dHz",
+                       audio_rate);
+               if (0 && *rate_store)
+                       wm5100_free_sr(codec, audio_rate);
+               ret = wm5100_alloc_sr(codec, audio_rate);
+               if (ret != 0)
+                       dev_warn(codec->dev, "Primary audio slot is %d\n",
+                                ret);
+       }
+
+       *rate_store = freq;
+
+       return 0;
+}
+
+struct _fll_div {
+       u16 fll_fratio;
+       u16 fll_outdiv;
+       u16 fll_refclk_div;
+       u16 n;
+       u16 theta;
+       u16 lambda;
+};
+
+static struct {
+       unsigned int min;
+       unsigned int max;
+       u16 fll_fratio;
+       int ratio;
+} fll_fratios[] = {
+       {       0,    64000, 4, 16 },
+       {   64000,   128000, 3,  8 },
+       {  128000,   256000, 2,  4 },
+       {  256000,  1000000, 1,  2 },
+       { 1000000, 13500000, 0,  1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+                      unsigned int Fout)
+{
+       unsigned int target;
+       unsigned int div;
+       unsigned int fratio, gcd_fll;
+       int i;
+
+       /* Fref must be <=13.5MHz */
+       div = 1;
+       fll_div->fll_refclk_div = 0;
+       while ((Fref / div) > 13500000) {
+               div *= 2;
+               fll_div->fll_refclk_div++;
+
+               if (div > 8) {
+                       pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+                              Fref);
+                       return -EINVAL;
+               }
+       }
+
+       pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+       /* Apply the division for our remaining calculations */
+       Fref /= div;
+
+       /* Fvco should be 90-100MHz; don't check the upper bound */
+       div = 2;
+       while (Fout * div < 90000000) {
+               div++;
+               if (div > 64) {
+                       pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+                              Fout);
+                       return -EINVAL;
+               }
+       }
+       target = Fout * div;
+       fll_div->fll_outdiv = div - 1;
+
+       pr_debug("FLL Fvco=%dHz\n", target);
+
+       /* Find an appropraite FLL_FRATIO and factor it out of the target */
+       for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+               if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+                       fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+                       fratio = fll_fratios[i].ratio;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(fll_fratios)) {
+               pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+               return -EINVAL;
+       }
+
+       fll_div->n = target / (fratio * Fref);
+
+       if (target % Fref == 0) {
+               fll_div->theta = 0;
+               fll_div->lambda = 0;
+       } else {
+               gcd_fll = gcd(target, fratio * Fref);
+
+               fll_div->theta = (target - (fll_div->n * fratio * Fref))
+                       / gcd_fll;
+               fll_div->lambda = (fratio * Fref) / gcd_fll;
+       }
+
+       pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+                fll_div->n, fll_div->theta, fll_div->lambda);
+       pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+                fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+                fll_div->fll_refclk_div);
+
+       return 0;
+}
+
+static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+                         unsigned int Fref, unsigned int Fout)
+{
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct _fll_div factors;
+       struct wm5100_fll *fll;
+       int ret, base, lock, i, timeout;
+
+       switch (fll_id) {
+       case WM5100_FLL1:
+               fll = &wm5100->fll[0];
+               base = WM5100_FLL1_CONTROL_1 - 1;
+               lock = WM5100_FLL1_LOCK_STS;
+               break;
+       case WM5100_FLL2:
+               fll = &wm5100->fll[1];
+               base = WM5100_FLL2_CONTROL_2 - 1;
+               lock = WM5100_FLL2_LOCK_STS;
+               break;
+       default:
+               dev_err(codec->dev, "Unknown FLL %d\n",fll_id);
+               return -EINVAL;
+       }
+
+       if (!Fout) {
+               dev_dbg(codec->dev, "FLL%d disabled", fll_id);
+               fll->fout = 0;
+               snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
+               return 0;
+       }
+
+       switch (source) {
+       case WM5100_FLL_SRC_MCLK1:
+       case WM5100_FLL_SRC_MCLK2:
+       case WM5100_FLL_SRC_FLL1:
+       case WM5100_FLL_SRC_FLL2:
+       case WM5100_FLL_SRC_AIF1BCLK:
+       case WM5100_FLL_SRC_AIF2BCLK:
+       case WM5100_FLL_SRC_AIF3BCLK:
+               break;
+       default:
+               dev_err(codec->dev, "Invalid FLL source %d\n", source);
+               return -EINVAL;
+       }
+
+       ret = fll_factors(&factors, Fref, Fout);
+       if (ret < 0)
+               return ret;
+
+       /* Disable the FLL while we reconfigure */
+       snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
+
+       snd_soc_update_bits(codec, base + 2,
+                           WM5100_FLL1_OUTDIV_MASK | WM5100_FLL1_FRATIO_MASK,
+                           (factors.fll_outdiv << WM5100_FLL1_OUTDIV_SHIFT) |
+                           factors.fll_fratio);
+       snd_soc_update_bits(codec, base + 3, WM5100_FLL1_THETA_MASK,
+                           factors.theta);
+       snd_soc_update_bits(codec, base + 5, WM5100_FLL1_N_MASK, factors.n);
+       snd_soc_update_bits(codec, base + 6,
+                           WM5100_FLL1_REFCLK_DIV_MASK |
+                           WM5100_FLL1_REFCLK_SRC_MASK,
+                           (factors.fll_refclk_div
+                            << WM5100_FLL1_REFCLK_DIV_SHIFT) | source);
+       snd_soc_update_bits(codec, base + 7, WM5100_FLL1_LAMBDA_MASK,
+                           factors.lambda);
+
+       /* Clear any pending completions */
+       try_wait_for_completion(&fll->lock);
+
+       snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
+
+       if (i2c->irq)
+               timeout = 2;
+       else
+               timeout = 50;
+
+       /* Poll for the lock; will use interrupt when we can test */
+       for (i = 0; i < timeout; i++) {
+               if (i2c->irq) {
+                       ret = wait_for_completion_timeout(&fll->lock,
+                                                         msecs_to_jiffies(25));
+                       if (ret > 0)
+                               break;
+               } else {
+                       msleep(1);
+               }
+
+               ret = snd_soc_read(codec,
+                                  WM5100_INTERRUPT_RAW_STATUS_3);
+               if (ret < 0) {
+                       dev_err(codec->dev,
+                               "Failed to read FLL status: %d\n",
+                               ret);
+                       continue;
+               }
+               if (ret & lock)
+                       break;
+       }
+       if (i == timeout) {
+               dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
+               return -ETIMEDOUT;
+       }
+
+       fll->src = source;
+       fll->fref = Fref;
+       fll->fout = Fout;
+
+       dev_dbg(codec->dev, "FLL%d running %dHz->%dHz\n", fll_id,
+               Fref, Fout);
+
+       return 0;
+}
+
+/* Actually go much higher */
+#define WM5100_RATES SNDRV_PCM_RATE_8000_192000
+
+#define WM5100_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm5100_dai[] = {
+       {
+               .name = "wm5100-aif1",
+               .playback = {
+                       .stream_name = "AIF1 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = WM5100_RATES,
+                       .formats = WM5100_FORMATS,
+               },
+               .capture = {
+                        .stream_name = "AIF1 Capture",
+                        .channels_min = 2,
+                        .channels_max = 2,
+                        .rates = WM5100_RATES,
+                        .formats = WM5100_FORMATS,
+                },
+               .ops = &wm5100_dai_ops,
+       },
+       {
+               .name = "wm5100-aif2",
+               .id = 1,
+               .playback = {
+                       .stream_name = "AIF2 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = WM5100_RATES,
+                       .formats = WM5100_FORMATS,
+               },
+               .capture = {
+                        .stream_name = "AIF2 Capture",
+                        .channels_min = 2,
+                        .channels_max = 2,
+                        .rates = WM5100_RATES,
+                        .formats = WM5100_FORMATS,
+                },
+               .ops = &wm5100_dai_ops,
+       },
+       {
+               .name = "wm5100-aif3",
+               .id = 2,
+               .playback = {
+                       .stream_name = "AIF3 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = WM5100_RATES,
+                       .formats = WM5100_FORMATS,
+               },
+               .capture = {
+                        .stream_name = "AIF3 Capture",
+                        .channels_min = 2,
+                        .channels_max = 2,
+                        .rates = WM5100_RATES,
+                        .formats = WM5100_FORMATS,
+                },
+               .ops = &wm5100_dai_ops,
+       },
+};
+
+static int wm5100_dig_vu[] = {
+       WM5100_ADC_DIGITAL_VOLUME_1L,
+       WM5100_ADC_DIGITAL_VOLUME_1R,
+       WM5100_ADC_DIGITAL_VOLUME_2L,
+       WM5100_ADC_DIGITAL_VOLUME_2R,
+       WM5100_ADC_DIGITAL_VOLUME_3L,
+       WM5100_ADC_DIGITAL_VOLUME_3R,
+       WM5100_ADC_DIGITAL_VOLUME_4L,
+       WM5100_ADC_DIGITAL_VOLUME_4R,
+
+       WM5100_DAC_DIGITAL_VOLUME_1L,
+       WM5100_DAC_DIGITAL_VOLUME_1R,
+       WM5100_DAC_DIGITAL_VOLUME_2L,
+       WM5100_DAC_DIGITAL_VOLUME_2R,
+       WM5100_DAC_DIGITAL_VOLUME_3L,
+       WM5100_DAC_DIGITAL_VOLUME_3R,
+       WM5100_DAC_DIGITAL_VOLUME_4L,
+       WM5100_DAC_DIGITAL_VOLUME_4R,
+       WM5100_DAC_DIGITAL_VOLUME_5L,
+       WM5100_DAC_DIGITAL_VOLUME_5R,
+       WM5100_DAC_DIGITAL_VOLUME_6L,
+       WM5100_DAC_DIGITAL_VOLUME_6R,
+};
+
+static irqreturn_t wm5100_irq(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       irqreturn_t status = IRQ_NONE;
+       int irq_val;
+
+       irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3);
+       if (irq_val < 0) {
+               dev_err(codec->dev, "Failed to read IRQ status 3: %d\n",
+                       irq_val);
+               irq_val = 0;
+       }
+       irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK);
+
+       snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val);
+
+       if (irq_val)
+               status = IRQ_HANDLED;
+
+       wm5100_log_status3(codec, irq_val);
+
+       if (irq_val & WM5100_FLL1_LOCK_EINT) {
+               dev_dbg(codec->dev, "FLL1 locked\n");
+               complete(&wm5100->fll[0].lock);
+       }
+       if (irq_val & WM5100_FLL2_LOCK_EINT) {
+               dev_dbg(codec->dev, "FLL2 locked\n");
+               complete(&wm5100->fll[1].lock);
+       }
+
+       irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4);
+       if (irq_val < 0) {
+               dev_err(codec->dev, "Failed to read IRQ status 4: %d\n",
+                       irq_val);
+               irq_val = 0;
+       }
+       irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK);
+
+       if (irq_val)
+               status = IRQ_HANDLED;
+
+       snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val);
+
+       wm5100_log_status4(codec, irq_val);
+
+       return status;
+}
+
+static irqreturn_t wm5100_edge_irq(int irq, void *data)
+{
+       irqreturn_t ret = IRQ_NONE;
+       irqreturn_t val;
+
+       do {
+               val = wm5100_irq(irq, data);
+               if (val != IRQ_NONE)
+                       ret = val;
+       } while (val != IRQ_NONE);
+
+       return ret;
+}
+
+#ifdef CONFIG_GPIOLIB
+static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip)
+{
+       return container_of(chip, struct wm5100_priv, gpio_chip);
+}
+
+static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+       struct snd_soc_codec *codec = wm5100->codec;
+
+       snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+                           WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT);
+}
+
+static int wm5100_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value)
+{
+       struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+       struct snd_soc_codec *codec = wm5100->codec;
+       int val;
+
+       val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT);
+
+       return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+                                  WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
+                                  WM5100_GP1_LVL, val);
+}
+
+static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+       struct snd_soc_codec *codec = wm5100->codec;
+       int ret;
+
+       ret = snd_soc_read(codec, WM5100_GPIO_CTRL_1 + offset);
+       if (ret < 0)
+               return ret;
+
+       return (ret & WM5100_GP1_LVL) != 0;
+}
+
+static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+       struct snd_soc_codec *codec = wm5100->codec;
+
+       return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+                                  WM5100_GP1_FN_MASK | WM5100_GP1_DIR,
+                                  (1 << WM5100_GP1_FN_SHIFT) |
+                                  (1 << WM5100_GP1_DIR_SHIFT));
+}
+
+static struct gpio_chip wm5100_template_chip = {
+       .label                  = "wm5100",
+       .owner                  = THIS_MODULE,
+       .direction_output       = wm5100_gpio_direction_out,
+       .set                    = wm5100_gpio_set,
+       .direction_input        = wm5100_gpio_direction_in,
+       .get                    = wm5100_gpio_get,
+       .can_sleep              = 1,
+};
+
+static void wm5100_init_gpio(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       wm5100->gpio_chip = wm5100_template_chip;
+       wm5100->gpio_chip.ngpio = 6;
+       wm5100->gpio_chip.dev = codec->dev;
+
+       if (wm5100->pdata.gpio_base)
+               wm5100->gpio_chip.base = wm5100->pdata.gpio_base;
+       else
+               wm5100->gpio_chip.base = -1;
+
+       ret = gpiochip_add(&wm5100->gpio_chip);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+}
+
+static void wm5100_free_gpio(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       ret = gpiochip_remove(&wm5100->gpio_chip);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+}
+#else
+static void wm5100_init_gpio(struct snd_soc_codec *codec)
+{
+}
+
+static void wm5100_free_gpio(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+static int wm5100_probe(struct snd_soc_codec *codec)
+{
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret, i, irq_flags;
+
+       wm5100->codec = codec;
+
+       codec->dapm.bias_level = SND_SOC_BIAS_OFF;
+
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
+               wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
+
+       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies),
+                                wm5100->core_supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request core supplies: %d\n",
+                       ret);
+               return ret;
+       }
+
+       wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD");
+       if (IS_ERR(wm5100->cpvdd)) {
+               ret = PTR_ERR(wm5100->cpvdd);
+               dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
+               goto err_core;
+       }
+
+       wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2");
+       if (IS_ERR(wm5100->dbvdd2)) {
+               ret = PTR_ERR(wm5100->dbvdd2);
+               dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
+               goto err_cpvdd;
+       }
+
+       wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3");
+       if (IS_ERR(wm5100->dbvdd3)) {
+               ret = PTR_ERR(wm5100->dbvdd3);
+               dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
+               goto err_dbvdd2;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+                                   wm5100->core_supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable core supplies: %d\n",
+                       ret);
+               goto err_dbvdd3;
+       }
+
+       if (wm5100->pdata.ldo_ena) {
+               ret = gpio_request_one(wm5100->pdata.ldo_ena,
+                                      GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+                               wm5100->pdata.ldo_ena, ret);
+                       goto err_enable;
+               }
+               msleep(2);
+       }
+
+       if (wm5100->pdata.reset) {
+               ret = gpio_request_one(wm5100->pdata.reset,
+                                      GPIOF_OUT_INIT_HIGH, "WM5100 /RESET");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+                               wm5100->pdata.reset, ret);
+                       goto err_ldo;
+               }
+       }
+
+       ret = snd_soc_read(codec, WM5100_SOFTWARE_RESET);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read ID register\n");
+               goto err_reset;
+       }
+       switch (ret) {
+       case 0x8997:
+       case 0x5100:
+               break;
+
+       default:
+               dev_err(codec->dev, "Device is not a WM5100, ID is %x\n", ret);
+               ret = -EINVAL;
+               goto err_reset;
+       }
+
+       ret = snd_soc_read(codec, WM5100_DEVICE_REVISION);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read revision register\n");
+               goto err_reset;
+       }
+       wm5100->rev = ret & WM5100_DEVICE_REVISION_MASK;
+
+       dev_info(codec->dev, "revision %c\n", wm5100->rev + 'A');
+
+       ret = wm5100_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset\n");
+               goto err_reset;
+       }
+
+       codec->cache_only = true;
+
+       wm5100_init_gpio(codec);
+
+       for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
+               snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
+                                   WM5100_OUT_VU);
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
+               snd_soc_update_bits(codec, WM5100_IN1L_CONTROL,
+                                   WM5100_IN1_MODE_MASK |
+                                   WM5100_IN1_DMIC_SUP_MASK,
+                                   (wm5100->pdata.in_mode[i] <<
+                                    WM5100_IN1_MODE_SHIFT) |
+                                   (wm5100->pdata.dmic_sup[i] <<
+                                    WM5100_IN1_DMIC_SUP_SHIFT));
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
+               if (!wm5100->pdata.gpio_defaults[i])
+                       continue;
+
+               snd_soc_write(codec, WM5100_GPIO_CTRL_1 + i,
+                             wm5100->pdata.gpio_defaults[i]);
+       }
+
+       /* Don't debounce interrupts to support use of SYSCLK only */
+       snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_1, 0);
+       snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_2, 0);
+
+       /* TODO: check if we're symmetric */
+
+       if (i2c->irq) {
+               if (wm5100->pdata.irq_flags)
+                       irq_flags = wm5100->pdata.irq_flags;
+               else
+                       irq_flags = IRQF_TRIGGER_LOW;
+
+               irq_flags |= IRQF_ONESHOT;
+
+               if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+                       ret = request_threaded_irq(i2c->irq, NULL,
+                                                  wm5100_edge_irq,
+                                                  irq_flags, "wm5100", codec);
+               else
+                       ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
+                                                  irq_flags, "wm5100", codec);
+
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
+                               i2c->irq, ret);
+               } else {
+                       /* Enable default interrupts */
+                       snd_soc_update_bits(codec,
+                                           WM5100_INTERRUPT_STATUS_3_MASK,
+                                           WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
+                                           WM5100_IM_SPK_SHUTDOWN_EINT |
+                                           WM5100_IM_ASRC2_LOCK_EINT |
+                                           WM5100_IM_ASRC1_LOCK_EINT |
+                                           WM5100_IM_FLL2_LOCK_EINT |
+                                           WM5100_IM_FLL1_LOCK_EINT |
+                                           WM5100_CLKGEN_ERR_EINT |
+                                           WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
+
+                       snd_soc_update_bits(codec,
+                                           WM5100_INTERRUPT_STATUS_4_MASK,
+                                           WM5100_AIF3_ERR_EINT |
+                                           WM5100_AIF2_ERR_EINT |
+                                           WM5100_AIF1_ERR_EINT |
+                                           WM5100_CTRLIF_ERR_EINT |
+                                           WM5100_ISRC2_UNDERCLOCKED_EINT |
+                                           WM5100_ISRC1_UNDERCLOCKED_EINT |
+                                           WM5100_FX_UNDERCLOCKED_EINT |
+                                           WM5100_AIF3_UNDERCLOCKED_EINT |
+                                           WM5100_AIF2_UNDERCLOCKED_EINT |
+                                           WM5100_AIF1_UNDERCLOCKED_EINT |
+                                           WM5100_ASRC_UNDERCLOCKED_EINT |
+                                           WM5100_DAC_UNDERCLOCKED_EINT |
+                                           WM5100_ADC_UNDERCLOCKED_EINT |
+                                           WM5100_MIXER_UNDERCLOCKED_EINT, 0);
+               }
+       } else {
+               snd_soc_dapm_new_controls(&codec->dapm,
+                                         wm5100_dapm_widgets_noirq,
+                                         ARRAY_SIZE(wm5100_dapm_widgets_noirq));
+       }
+
+       if (wm5100->pdata.hp_pol) {
+               ret = gpio_request_one(wm5100->pdata.hp_pol,
+                                      GPIOF_OUT_INIT_HIGH, "WM5100 HP_POL");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request HP_POL %d: %d\n",
+                               wm5100->pdata.hp_pol, ret);
+                       goto err_gpio;
+               }
+       }
+
+       /* We'll get woken up again when the system has something useful
+        * for us to do.
+        */
+       if (wm5100->pdata.ldo_ena)
+               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+       regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+                              wm5100->core_supplies);
+
+       return 0;
+
+err_gpio:
+       if (i2c->irq)
+               free_irq(i2c->irq, codec);
+       wm5100_free_gpio(codec);
+err_reset:
+       if (wm5100->pdata.reset) {
+               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+               gpio_free(wm5100->pdata.reset);
+       }
+err_ldo:
+       if (wm5100->pdata.ldo_ena) {
+               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+               gpio_free(wm5100->pdata.ldo_ena);
+       }
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+                              wm5100->core_supplies);
+err_dbvdd3:
+       regulator_put(wm5100->dbvdd3);
+err_dbvdd2:
+       regulator_put(wm5100->dbvdd2);
+err_cpvdd:
+       regulator_put(wm5100->cpvdd);
+err_core:
+       regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
+                           wm5100->core_supplies);
+
+       return ret;
+}
+
+static int wm5100_remove(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+
+       wm5100_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       if (wm5100->pdata.hp_pol) {
+               gpio_free(wm5100->pdata.hp_pol);
+       }
+       if (i2c->irq)
+               free_irq(i2c->irq, codec);
+       wm5100_free_gpio(codec);
+       if (wm5100->pdata.reset) {
+               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+               gpio_free(wm5100->pdata.reset);
+       }
+       if (wm5100->pdata.ldo_ena) {
+               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+               gpio_free(wm5100->pdata.ldo_ena);
+       }
+       regulator_put(wm5100->dbvdd3);
+       regulator_put(wm5100->dbvdd2);
+       regulator_put(wm5100->cpvdd);
+       regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
+                           wm5100->core_supplies);
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
+       .probe =        wm5100_probe,
+       .remove =       wm5100_remove,
+
+       .set_sysclk = wm5100_set_sysclk,
+       .set_pll = wm5100_set_fll,
+       .set_bias_level = wm5100_set_bias_level,
+       .idle_bias_off = 1,
+
+       .seq_notifier = wm5100_seq_notifier,
+       .controls = wm5100_snd_controls,
+       .num_controls = ARRAY_SIZE(wm5100_snd_controls),
+       .dapm_widgets = wm5100_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets),
+       .dapm_routes = wm5100_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes),
+
+       .reg_cache_size = ARRAY_SIZE(wm5100_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .compress_type = SND_SOC_RBTREE_COMPRESSION,
+       .reg_cache_default = wm5100_reg_defaults,
+
+       .volatile_register = wm5100_volatile_register,
+       .readable_register = wm5100_readable_register,
+};
+
+static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
+       struct wm5100_priv *wm5100;
+       int ret, i;
+
+       wm5100 = kzalloc(sizeof(struct wm5100_priv), GFP_KERNEL);
+       if (wm5100 == NULL)
+               return -ENOMEM;
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->fll); i++)
+               init_completion(&wm5100->fll[i].lock);
+
+       if (pdata)
+               wm5100->pdata = *pdata;
+
+       i2c_set_clientdata(i2c, wm5100);
+
+       ret = snd_soc_register_codec(&i2c->dev,
+                                    &soc_codec_dev_wm5100, wm5100_dai,
+                                    ARRAY_SIZE(wm5100_dai));
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret);
+               kfree(wm5100);
+       }
+
+       return ret;
+}
+
+static __devexit int wm5100_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static const struct i2c_device_id wm5100_i2c_id[] = {
+       { "wm5100", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id);
+
+static struct i2c_driver wm5100_i2c_driver = {
+       .driver = {
+               .name = "wm5100",
+               .owner = THIS_MODULE,
+       },
+       .probe =    wm5100_i2c_probe,
+       .remove =   __devexit_p(wm5100_i2c_remove),
+       .id_table = wm5100_i2c_id,
+};
+
+static int __init wm5100_modinit(void)
+{
+       return i2c_add_driver(&wm5100_i2c_driver);
+}
+module_init(wm5100_modinit);
+
+static void __exit wm5100_exit(void)
+{
+       i2c_del_driver(&wm5100_i2c_driver);
+}
+module_exit(wm5100_exit);
+
+MODULE_DESCRIPTION("ASoC WM5100 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm5100.h b/sound/soc/codecs/wm5100.h
new file mode 100644 (file)
index 0000000..345b3cf
--- /dev/null
@@ -0,0 +1,5146 @@
+/*
+ * wm5100.h  --  WM5100 ALSA SoC Audio driver
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef WM5100_ASOC_H
+#define WM5100_ASOC_H
+
+#include <sound/soc.h>
+
+#define WM5100_CLK_AIF1     1
+#define WM5100_CLK_AIF2     2
+#define WM5100_CLK_AIF3     3
+#define WM5100_CLK_SYSCLK   4
+#define WM5100_CLK_ASYNCCLK 5
+#define WM5100_CLK_32KHZ    6
+#define WM5100_CLK_OPCLK    7
+
+#define WM5100_CLKSRC_MCLK1    0
+#define WM5100_CLKSRC_MCLK2    1
+#define WM5100_CLKSRC_SYSCLK   2
+#define WM5100_CLKSRC_FLL1     4
+#define WM5100_CLKSRC_FLL2     5
+#define WM5100_CLKSRC_AIF1BCLK 8
+#define WM5100_CLKSRC_AIF2BCLK 9
+#define WM5100_CLKSRC_AIF3BCLK 10
+#define WM5100_CLKSRC_ASYNCCLK 0x100
+
+#define WM5100_FLL1 1
+#define WM5100_FLL2 2
+
+#define WM5100_FLL_SRC_MCLK1    0x0
+#define WM5100_FLL_SRC_MCLK2    0x1
+#define WM5100_FLL_SRC_FLL1     0x4
+#define WM5100_FLL_SRC_FLL2     0x5
+#define WM5100_FLL_SRC_AIF1BCLK 0x8
+#define WM5100_FLL_SRC_AIF2BCLK 0x9
+#define WM5100_FLL_SRC_AIF3BCLK 0xa
+
+/*
+ * Register values.
+ */
+#define WM5100_SOFTWARE_RESET                   0x00
+#define WM5100_DEVICE_REVISION                  0x01
+#define WM5100_CTRL_IF_1                        0x10
+#define WM5100_TONE_GENERATOR_1                 0x20
+#define WM5100_PWM_DRIVE_1                      0x30
+#define WM5100_PWM_DRIVE_2                      0x31
+#define WM5100_PWM_DRIVE_3                      0x32
+#define WM5100_CLOCKING_1                       0x100
+#define WM5100_CLOCKING_3                       0x101
+#define WM5100_CLOCKING_4                       0x102
+#define WM5100_CLOCKING_5                       0x103
+#define WM5100_CLOCKING_6                       0x104
+#define WM5100_CLOCKING_7                       0x107
+#define WM5100_CLOCKING_8                       0x108
+#define WM5100_ASRC_ENABLE                      0x120
+#define WM5100_ASRC_STATUS                      0x121
+#define WM5100_ASRC_RATE1                       0x122
+#define WM5100_ISRC_1_CTRL_1                    0x141
+#define WM5100_ISRC_1_CTRL_2                    0x142
+#define WM5100_ISRC_2_CTRL1                     0x143
+#define WM5100_ISRC_2_CTRL_2                    0x144
+#define WM5100_FLL1_CONTROL_1                   0x182
+#define WM5100_FLL1_CONTROL_2                   0x183
+#define WM5100_FLL1_CONTROL_3                   0x184
+#define WM5100_FLL1_CONTROL_5                   0x186
+#define WM5100_FLL1_CONTROL_6                   0x187
+#define WM5100_FLL1_EFS_1                       0x188
+#define WM5100_FLL2_CONTROL_1                   0x1A2
+#define WM5100_FLL2_CONTROL_2                   0x1A3
+#define WM5100_FLL2_CONTROL_3                   0x1A4
+#define WM5100_FLL2_CONTROL_5                   0x1A6
+#define WM5100_FLL2_CONTROL_6                   0x1A7
+#define WM5100_FLL2_EFS_1                       0x1A8
+#define WM5100_MIC_CHARGE_PUMP_1                0x200
+#define WM5100_MIC_CHARGE_PUMP_2                0x201
+#define WM5100_HP_CHARGE_PUMP_1                 0x202
+#define WM5100_LDO1_CONTROL                     0x211
+#define WM5100_MIC_BIAS_CTRL_1                  0x215
+#define WM5100_MIC_BIAS_CTRL_2                  0x216
+#define WM5100_MIC_BIAS_CTRL_3                  0x217
+#define WM5100_ACCESSORY_DETECT_MODE_1          0x280
+#define WM5100_HEADPHONE_DETECT_1               0x288
+#define WM5100_HEADPHONE_DETECT_2               0x289
+#define WM5100_MIC_DETECT_1                     0x290
+#define WM5100_MIC_DETECT_2                     0x291
+#define WM5100_MIC_DETECT_3                     0x292
+#define WM5100_INPUT_ENABLES                    0x301
+#define WM5100_INPUT_ENABLES_STATUS             0x302
+#define WM5100_IN1L_CONTROL                     0x310
+#define WM5100_IN1R_CONTROL                     0x311
+#define WM5100_IN2L_CONTROL                     0x312
+#define WM5100_IN2R_CONTROL                     0x313
+#define WM5100_IN3L_CONTROL                     0x314
+#define WM5100_IN3R_CONTROL                     0x315
+#define WM5100_IN4L_CONTROL                     0x316
+#define WM5100_IN4R_CONTROL                     0x317
+#define WM5100_RXANC_SRC                        0x318
+#define WM5100_INPUT_VOLUME_RAMP                0x319
+#define WM5100_ADC_DIGITAL_VOLUME_1L            0x320
+#define WM5100_ADC_DIGITAL_VOLUME_1R            0x321
+#define WM5100_ADC_DIGITAL_VOLUME_2L            0x322
+#define WM5100_ADC_DIGITAL_VOLUME_2R            0x323
+#define WM5100_ADC_DIGITAL_VOLUME_3L            0x324
+#define WM5100_ADC_DIGITAL_VOLUME_3R            0x325
+#define WM5100_ADC_DIGITAL_VOLUME_4L            0x326
+#define WM5100_ADC_DIGITAL_VOLUME_4R            0x327
+#define WM5100_OUTPUT_ENABLES_2                 0x401
+#define WM5100_OUTPUT_STATUS_1                  0x402
+#define WM5100_OUTPUT_STATUS_2                  0x403
+#define WM5100_CHANNEL_ENABLES_1                0x408
+#define WM5100_OUT_VOLUME_1L                    0x410
+#define WM5100_OUT_VOLUME_1R                    0x411
+#define WM5100_DAC_VOLUME_LIMIT_1L              0x412
+#define WM5100_DAC_VOLUME_LIMIT_1R              0x413
+#define WM5100_OUT_VOLUME_2L                    0x414
+#define WM5100_OUT_VOLUME_2R                    0x415
+#define WM5100_DAC_VOLUME_LIMIT_2L              0x416
+#define WM5100_DAC_VOLUME_LIMIT_2R              0x417
+#define WM5100_OUT_VOLUME_3L                    0x418
+#define WM5100_OUT_VOLUME_3R                    0x419
+#define WM5100_DAC_VOLUME_LIMIT_3L              0x41A
+#define WM5100_DAC_VOLUME_LIMIT_3R              0x41B
+#define WM5100_OUT_VOLUME_4L                    0x41C
+#define WM5100_OUT_VOLUME_4R                    0x41D
+#define WM5100_DAC_VOLUME_LIMIT_5L              0x41E
+#define WM5100_DAC_VOLUME_LIMIT_5R              0x41F
+#define WM5100_DAC_VOLUME_LIMIT_6L              0x420
+#define WM5100_DAC_VOLUME_LIMIT_6R              0x421
+#define WM5100_DAC_AEC_CONTROL_1                0x440
+#define WM5100_OUTPUT_VOLUME_RAMP               0x441
+#define WM5100_DAC_DIGITAL_VOLUME_1L            0x480
+#define WM5100_DAC_DIGITAL_VOLUME_1R            0x481
+#define WM5100_DAC_DIGITAL_VOLUME_2L            0x482
+#define WM5100_DAC_DIGITAL_VOLUME_2R            0x483
+#define WM5100_DAC_DIGITAL_VOLUME_3L            0x484
+#define WM5100_DAC_DIGITAL_VOLUME_3R            0x485
+#define WM5100_DAC_DIGITAL_VOLUME_4L            0x486
+#define WM5100_DAC_DIGITAL_VOLUME_4R            0x487
+#define WM5100_DAC_DIGITAL_VOLUME_5L            0x488
+#define WM5100_DAC_DIGITAL_VOLUME_5R            0x489
+#define WM5100_DAC_DIGITAL_VOLUME_6L            0x48A
+#define WM5100_DAC_DIGITAL_VOLUME_6R            0x48B
+#define WM5100_PDM_SPK1_CTRL_1                  0x4C0
+#define WM5100_PDM_SPK1_CTRL_2                  0x4C1
+#define WM5100_PDM_SPK2_CTRL_1                  0x4C2
+#define WM5100_PDM_SPK2_CTRL_2                  0x4C3
+#define WM5100_AUDIO_IF_1_1                     0x500
+#define WM5100_AUDIO_IF_1_2                     0x501
+#define WM5100_AUDIO_IF_1_3                     0x502
+#define WM5100_AUDIO_IF_1_4                     0x503
+#define WM5100_AUDIO_IF_1_5                     0x504
+#define WM5100_AUDIO_IF_1_6                     0x505
+#define WM5100_AUDIO_IF_1_7                     0x506
+#define WM5100_AUDIO_IF_1_8                     0x507
+#define WM5100_AUDIO_IF_1_9                     0x508
+#define WM5100_AUDIO_IF_1_10                    0x509
+#define WM5100_AUDIO_IF_1_11                    0x50A
+#define WM5100_AUDIO_IF_1_12                    0x50B
+#define WM5100_AUDIO_IF_1_13                    0x50C
+#define WM5100_AUDIO_IF_1_14                    0x50D
+#define WM5100_AUDIO_IF_1_15                    0x50E
+#define WM5100_AUDIO_IF_1_16                    0x50F
+#define WM5100_AUDIO_IF_1_17                    0x510
+#define WM5100_AUDIO_IF_1_18                    0x511
+#define WM5100_AUDIO_IF_1_19                    0x512
+#define WM5100_AUDIO_IF_1_20                    0x513
+#define WM5100_AUDIO_IF_1_21                    0x514
+#define WM5100_AUDIO_IF_1_22                    0x515
+#define WM5100_AUDIO_IF_1_23                    0x516
+#define WM5100_AUDIO_IF_1_24                    0x517
+#define WM5100_AUDIO_IF_1_25                    0x518
+#define WM5100_AUDIO_IF_1_26                    0x519
+#define WM5100_AUDIO_IF_1_27                    0x51A
+#define WM5100_AUDIO_IF_2_1                     0x540
+#define WM5100_AUDIO_IF_2_2                     0x541
+#define WM5100_AUDIO_IF_2_3                     0x542
+#define WM5100_AUDIO_IF_2_4                     0x543
+#define WM5100_AUDIO_IF_2_5                     0x544
+#define WM5100_AUDIO_IF_2_6                     0x545
+#define WM5100_AUDIO_IF_2_7                     0x546
+#define WM5100_AUDIO_IF_2_8                     0x547
+#define WM5100_AUDIO_IF_2_9                     0x548
+#define WM5100_AUDIO_IF_2_10                    0x549
+#define WM5100_AUDIO_IF_2_11                    0x54A
+#define WM5100_AUDIO_IF_2_18                    0x551
+#define WM5100_AUDIO_IF_2_19                    0x552
+#define WM5100_AUDIO_IF_2_26                    0x559
+#define WM5100_AUDIO_IF_2_27                    0x55A
+#define WM5100_AUDIO_IF_3_1                     0x580
+#define WM5100_AUDIO_IF_3_2                     0x581
+#define WM5100_AUDIO_IF_3_3                     0x582
+#define WM5100_AUDIO_IF_3_4                     0x583
+#define WM5100_AUDIO_IF_3_5                     0x584
+#define WM5100_AUDIO_IF_3_6                     0x585
+#define WM5100_AUDIO_IF_3_7                     0x586
+#define WM5100_AUDIO_IF_3_8                     0x587
+#define WM5100_AUDIO_IF_3_9                     0x588
+#define WM5100_AUDIO_IF_3_10                    0x589
+#define WM5100_AUDIO_IF_3_11                    0x58A
+#define WM5100_AUDIO_IF_3_18                    0x591
+#define WM5100_AUDIO_IF_3_19                    0x592
+#define WM5100_AUDIO_IF_3_26                    0x599
+#define WM5100_AUDIO_IF_3_27                    0x59A
+#define WM5100_PWM1MIX_INPUT_1_SOURCE           0x640
+#define WM5100_PWM1MIX_INPUT_1_VOLUME           0x641
+#define WM5100_PWM1MIX_INPUT_2_SOURCE           0x642
+#define WM5100_PWM1MIX_INPUT_2_VOLUME           0x643
+#define WM5100_PWM1MIX_INPUT_3_SOURCE           0x644
+#define WM5100_PWM1MIX_INPUT_3_VOLUME           0x645
+#define WM5100_PWM1MIX_INPUT_4_SOURCE           0x646
+#define WM5100_PWM1MIX_INPUT_4_VOLUME           0x647
+#define WM5100_PWM2MIX_INPUT_1_SOURCE           0x648
+#define WM5100_PWM2MIX_INPUT_1_VOLUME           0x649
+#define WM5100_PWM2MIX_INPUT_2_SOURCE           0x64A
+#define WM5100_PWM2MIX_INPUT_2_VOLUME           0x64B
+#define WM5100_PWM2MIX_INPUT_3_SOURCE           0x64C
+#define WM5100_PWM2MIX_INPUT_3_VOLUME           0x64D
+#define WM5100_PWM2MIX_INPUT_4_SOURCE           0x64E
+#define WM5100_PWM2MIX_INPUT_4_VOLUME           0x64F
+#define WM5100_OUT1LMIX_INPUT_1_SOURCE          0x680
+#define WM5100_OUT1LMIX_INPUT_1_VOLUME          0x681
+#define WM5100_OUT1LMIX_INPUT_2_SOURCE          0x682
+#define WM5100_OUT1LMIX_INPUT_2_VOLUME          0x683
+#define WM5100_OUT1LMIX_INPUT_3_SOURCE          0x684
+#define WM5100_OUT1LMIX_INPUT_3_VOLUME          0x685
+#define WM5100_OUT1LMIX_INPUT_4_SOURCE          0x686
+#define WM5100_OUT1LMIX_INPUT_4_VOLUME          0x687
+#define WM5100_OUT1RMIX_INPUT_1_SOURCE          0x688
+#define WM5100_OUT1RMIX_INPUT_1_VOLUME          0x689
+#define WM5100_OUT1RMIX_INPUT_2_SOURCE          0x68A
+#define WM5100_OUT1RMIX_INPUT_2_VOLUME          0x68B
+#define WM5100_OUT1RMIX_INPUT_3_SOURCE          0x68C
+#define WM5100_OUT1RMIX_INPUT_3_VOLUME          0x68D
+#define WM5100_OUT1RMIX_INPUT_4_SOURCE          0x68E
+#define WM5100_OUT1RMIX_INPUT_4_VOLUME          0x68F
+#define WM5100_OUT2LMIX_INPUT_1_SOURCE          0x690
+#define WM5100_OUT2LMIX_INPUT_1_VOLUME          0x691
+#define WM5100_OUT2LMIX_INPUT_2_SOURCE          0x692
+#define WM5100_OUT2LMIX_INPUT_2_VOLUME          0x693
+#define WM5100_OUT2LMIX_INPUT_3_SOURCE          0x694
+#define WM5100_OUT2LMIX_INPUT_3_VOLUME          0x695
+#define WM5100_OUT2LMIX_INPUT_4_SOURCE          0x696
+#define WM5100_OUT2LMIX_INPUT_4_VOLUME          0x697
+#define WM5100_OUT2RMIX_INPUT_1_SOURCE          0x698
+#define WM5100_OUT2RMIX_INPUT_1_VOLUME          0x699
+#define WM5100_OUT2RMIX_INPUT_2_SOURCE          0x69A
+#define WM5100_OUT2RMIX_INPUT_2_VOLUME          0x69B
+#define WM5100_OUT2RMIX_INPUT_3_SOURCE          0x69C
+#define WM5100_OUT2RMIX_INPUT_3_VOLUME          0x69D
+#define WM5100_OUT2RMIX_INPUT_4_SOURCE          0x69E
+#define WM5100_OUT2RMIX_INPUT_4_VOLUME          0x69F
+#define WM5100_OUT3LMIX_INPUT_1_SOURCE          0x6A0
+#define WM5100_OUT3LMIX_INPUT_1_VOLUME          0x6A1
+#define WM5100_OUT3LMIX_INPUT_2_SOURCE          0x6A2
+#define WM5100_OUT3LMIX_INPUT_2_VOLUME          0x6A3
+#define WM5100_OUT3LMIX_INPUT_3_SOURCE          0x6A4
+#define WM5100_OUT3LMIX_INPUT_3_VOLUME          0x6A5
+#define WM5100_OUT3LMIX_INPUT_4_SOURCE          0x6A6
+#define WM5100_OUT3LMIX_INPUT_4_VOLUME          0x6A7
+#define WM5100_OUT3RMIX_INPUT_1_SOURCE          0x6A8
+#define WM5100_OUT3RMIX_INPUT_1_VOLUME          0x6A9
+#define WM5100_OUT3RMIX_INPUT_2_SOURCE          0x6AA
+#define WM5100_OUT3RMIX_INPUT_2_VOLUME          0x6AB
+#define WM5100_OUT3RMIX_INPUT_3_SOURCE          0x6AC
+#define WM5100_OUT3RMIX_INPUT_3_VOLUME          0x6AD
+#define WM5100_OUT3RMIX_INPUT_4_SOURCE          0x6AE
+#define WM5100_OUT3RMIX_INPUT_4_VOLUME          0x6AF
+#define WM5100_OUT4LMIX_INPUT_1_SOURCE          0x6B0
+#define WM5100_OUT4LMIX_INPUT_1_VOLUME          0x6B1
+#define WM5100_OUT4LMIX_INPUT_2_SOURCE          0x6B2
+#define WM5100_OUT4LMIX_INPUT_2_VOLUME          0x6B3
+#define WM5100_OUT4LMIX_INPUT_3_SOURCE          0x6B4
+#define WM5100_OUT4LMIX_INPUT_3_VOLUME          0x6B5
+#define WM5100_OUT4LMIX_INPUT_4_SOURCE          0x6B6
+#define WM5100_OUT4LMIX_INPUT_4_VOLUME          0x6B7
+#define WM5100_OUT4RMIX_INPUT_1_SOURCE          0x6B8
+#define WM5100_OUT4RMIX_INPUT_1_VOLUME          0x6B9
+#define WM5100_OUT4RMIX_INPUT_2_SOURCE          0x6BA
+#define WM5100_OUT4RMIX_INPUT_2_VOLUME          0x6BB
+#define WM5100_OUT4RMIX_INPUT_3_SOURCE          0x6BC
+#define WM5100_OUT4RMIX_INPUT_3_VOLUME          0x6BD
+#define WM5100_OUT4RMIX_INPUT_4_SOURCE          0x6BE
+#define WM5100_OUT4RMIX_INPUT_4_VOLUME          0x6BF
+#define WM5100_OUT5LMIX_INPUT_1_SOURCE          0x6C0
+#define WM5100_OUT5LMIX_INPUT_1_VOLUME          0x6C1
+#define WM5100_OUT5LMIX_INPUT_2_SOURCE          0x6C2
+#define WM5100_OUT5LMIX_INPUT_2_VOLUME          0x6C3
+#define WM5100_OUT5LMIX_INPUT_3_SOURCE          0x6C4
+#define WM5100_OUT5LMIX_INPUT_3_VOLUME          0x6C5
+#define WM5100_OUT5LMIX_INPUT_4_SOURCE          0x6C6
+#define WM5100_OUT5LMIX_INPUT_4_VOLUME          0x6C7
+#define WM5100_OUT5RMIX_INPUT_1_SOURCE          0x6C8
+#define WM5100_OUT5RMIX_INPUT_1_VOLUME          0x6C9
+#define WM5100_OUT5RMIX_INPUT_2_SOURCE          0x6CA
+#define WM5100_OUT5RMIX_INPUT_2_VOLUME          0x6CB
+#define WM5100_OUT5RMIX_INPUT_3_SOURCE          0x6CC
+#define WM5100_OUT5RMIX_INPUT_3_VOLUME          0x6CD
+#define WM5100_OUT5RMIX_INPUT_4_SOURCE          0x6CE
+#define WM5100_OUT5RMIX_INPUT_4_VOLUME          0x6CF
+#define WM5100_OUT6LMIX_INPUT_1_SOURCE          0x6D0
+#define WM5100_OUT6LMIX_INPUT_1_VOLUME          0x6D1
+#define WM5100_OUT6LMIX_INPUT_2_SOURCE          0x6D2
+#define WM5100_OUT6LMIX_INPUT_2_VOLUME          0x6D3
+#define WM5100_OUT6LMIX_INPUT_3_SOURCE          0x6D4
+#define WM5100_OUT6LMIX_INPUT_3_VOLUME          0x6D5
+#define WM5100_OUT6LMIX_INPUT_4_SOURCE          0x6D6
+#define WM5100_OUT6LMIX_INPUT_4_VOLUME          0x6D7
+#define WM5100_OUT6RMIX_INPUT_1_SOURCE          0x6D8
+#define WM5100_OUT6RMIX_INPUT_1_VOLUME          0x6D9
+#define WM5100_OUT6RMIX_INPUT_2_SOURCE          0x6DA
+#define WM5100_OUT6RMIX_INPUT_2_VOLUME          0x6DB
+#define WM5100_OUT6RMIX_INPUT_3_SOURCE          0x6DC
+#define WM5100_OUT6RMIX_INPUT_3_VOLUME          0x6DD
+#define WM5100_OUT6RMIX_INPUT_4_SOURCE          0x6DE
+#define WM5100_OUT6RMIX_INPUT_4_VOLUME          0x6DF
+#define WM5100_AIF1TX1MIX_INPUT_1_SOURCE        0x700
+#define WM5100_AIF1TX1MIX_INPUT_1_VOLUME        0x701
+#define WM5100_AIF1TX1MIX_INPUT_2_SOURCE        0x702
+#define WM5100_AIF1TX1MIX_INPUT_2_VOLUME        0x703
+#define WM5100_AIF1TX1MIX_INPUT_3_SOURCE        0x704
+#define WM5100_AIF1TX1MIX_INPUT_3_VOLUME        0x705
+#define WM5100_AIF1TX1MIX_INPUT_4_SOURCE        0x706
+#define WM5100_AIF1TX1MIX_INPUT_4_VOLUME        0x707
+#define WM5100_AIF1TX2MIX_INPUT_1_SOURCE        0x708
+#define WM5100_AIF1TX2MIX_INPUT_1_VOLUME        0x709
+#define WM5100_AIF1TX2MIX_INPUT_2_SOURCE        0x70A
+#define WM5100_AIF1TX2MIX_INPUT_2_VOLUME        0x70B
+#define WM5100_AIF1TX2MIX_INPUT_3_SOURCE        0x70C
+#define WM5100_AIF1TX2MIX_INPUT_3_VOLUME        0x70D
+#define WM5100_AIF1TX2MIX_INPUT_4_SOURCE        0x70E
+#define WM5100_AIF1TX2MIX_INPUT_4_VOLUME        0x70F
+#define WM5100_AIF1TX3MIX_INPUT_1_SOURCE        0x710
+#define WM5100_AIF1TX3MIX_INPUT_1_VOLUME        0x711
+#define WM5100_AIF1TX3MIX_INPUT_2_SOURCE        0x712
+#define WM5100_AIF1TX3MIX_INPUT_2_VOLUME        0x713
+#define WM5100_AIF1TX3MIX_INPUT_3_SOURCE        0x714
+#define WM5100_AIF1TX3MIX_INPUT_3_VOLUME        0x715
+#define WM5100_AIF1TX3MIX_INPUT_4_SOURCE        0x716
+#define WM5100_AIF1TX3MIX_INPUT_4_VOLUME        0x717
+#define WM5100_AIF1TX4MIX_INPUT_1_SOURCE        0x718
+#define WM5100_AIF1TX4MIX_INPUT_1_VOLUME        0x719
+#define WM5100_AIF1TX4MIX_INPUT_2_SOURCE        0x71A
+#define WM5100_AIF1TX4MIX_INPUT_2_VOLUME        0x71B
+#define WM5100_AIF1TX4MIX_INPUT_3_SOURCE        0x71C
+#define WM5100_AIF1TX4MIX_INPUT_3_VOLUME        0x71D
+#define WM5100_AIF1TX4MIX_INPUT_4_SOURCE        0x71E
+#define WM5100_AIF1TX4MIX_INPUT_4_VOLUME        0x71F
+#define WM5100_AIF1TX5MIX_INPUT_1_SOURCE        0x720
+#define WM5100_AIF1TX5MIX_INPUT_1_VOLUME        0x721
+#define WM5100_AIF1TX5MIX_INPUT_2_SOURCE        0x722
+#define WM5100_AIF1TX5MIX_INPUT_2_VOLUME        0x723
+#define WM5100_AIF1TX5MIX_INPUT_3_SOURCE        0x724
+#define WM5100_AIF1TX5MIX_INPUT_3_VOLUME        0x725
+#define WM5100_AIF1TX5MIX_INPUT_4_SOURCE        0x726
+#define WM5100_AIF1TX5MIX_INPUT_4_VOLUME        0x727
+#define WM5100_AIF1TX6MIX_INPUT_1_SOURCE        0x728
+#define WM5100_AIF1TX6MIX_INPUT_1_VOLUME        0x729
+#define WM5100_AIF1TX6MIX_INPUT_2_SOURCE        0x72A
+#define WM5100_AIF1TX6MIX_INPUT_2_VOLUME        0x72B
+#define WM5100_AIF1TX6MIX_INPUT_3_SOURCE        0x72C
+#define WM5100_AIF1TX6MIX_INPUT_3_VOLUME        0x72D
+#define WM5100_AIF1TX6MIX_INPUT_4_SOURCE        0x72E
+#define WM5100_AIF1TX6MIX_INPUT_4_VOLUME        0x72F
+#define WM5100_AIF1TX7MIX_INPUT_1_SOURCE        0x730
+#define WM5100_AIF1TX7MIX_INPUT_1_VOLUME        0x731
+#define WM5100_AIF1TX7MIX_INPUT_2_SOURCE        0x732
+#define WM5100_AIF1TX7MIX_INPUT_2_VOLUME        0x733
+#define WM5100_AIF1TX7MIX_INPUT_3_SOURCE        0x734
+#define WM5100_AIF1TX7MIX_INPUT_3_VOLUME        0x735
+#define WM5100_AIF1TX7MIX_INPUT_4_SOURCE        0x736
+#define WM5100_AIF1TX7MIX_INPUT_4_VOLUME        0x737
+#define WM5100_AIF1TX8MIX_INPUT_1_SOURCE        0x738
+#define WM5100_AIF1TX8MIX_INPUT_1_VOLUME        0x739
+#define WM5100_AIF1TX8MIX_INPUT_2_SOURCE        0x73A
+#define WM5100_AIF1TX8MIX_INPUT_2_VOLUME        0x73B
+#define WM5100_AIF1TX8MIX_INPUT_3_SOURCE        0x73C
+#define WM5100_AIF1TX8MIX_INPUT_3_VOLUME        0x73D
+#define WM5100_AIF1TX8MIX_INPUT_4_SOURCE        0x73E
+#define WM5100_AIF1TX8MIX_INPUT_4_VOLUME        0x73F
+#define WM5100_AIF2TX1MIX_INPUT_1_SOURCE        0x740
+#define WM5100_AIF2TX1MIX_INPUT_1_VOLUME        0x741
+#define WM5100_AIF2TX1MIX_INPUT_2_SOURCE        0x742
+#define WM5100_AIF2TX1MIX_INPUT_2_VOLUME        0x743
+#define WM5100_AIF2TX1MIX_INPUT_3_SOURCE        0x744
+#define WM5100_AIF2TX1MIX_INPUT_3_VOLUME        0x745
+#define WM5100_AIF2TX1MIX_INPUT_4_SOURCE        0x746
+#define WM5100_AIF2TX1MIX_INPUT_4_VOLUME        0x747
+#define WM5100_AIF2TX2MIX_INPUT_1_SOURCE        0x748
+#define WM5100_AIF2TX2MIX_INPUT_1_VOLUME        0x749
+#define WM5100_AIF2TX2MIX_INPUT_2_SOURCE        0x74A
+#define WM5100_AIF2TX2MIX_INPUT_2_VOLUME        0x74B
+#define WM5100_AIF2TX2MIX_INPUT_3_SOURCE        0x74C
+#define WM5100_AIF2TX2MIX_INPUT_3_VOLUME        0x74D
+#define WM5100_AIF2TX2MIX_INPUT_4_SOURCE        0x74E
+#define WM5100_AIF2TX2MIX_INPUT_4_VOLUME        0x74F
+#define WM5100_AIF3TX1MIX_INPUT_1_SOURCE        0x780
+#define WM5100_AIF3TX1MIX_INPUT_1_VOLUME        0x781
+#define WM5100_AIF3TX1MIX_INPUT_2_SOURCE        0x782
+#define WM5100_AIF3TX1MIX_INPUT_2_VOLUME        0x783
+#define WM5100_AIF3TX1MIX_INPUT_3_SOURCE        0x784
+#define WM5100_AIF3TX1MIX_INPUT_3_VOLUME        0x785
+#define WM5100_AIF3TX1MIX_INPUT_4_SOURCE        0x786
+#define WM5100_AIF3TX1MIX_INPUT_4_VOLUME        0x787
+#define WM5100_AIF3TX2MIX_INPUT_1_SOURCE        0x788
+#define WM5100_AIF3TX2MIX_INPUT_1_VOLUME        0x789
+#define WM5100_AIF3TX2MIX_INPUT_2_SOURCE        0x78A
+#define WM5100_AIF3TX2MIX_INPUT_2_VOLUME        0x78B
+#define WM5100_AIF3TX2MIX_INPUT_3_SOURCE        0x78C
+#define WM5100_AIF3TX2MIX_INPUT_3_VOLUME        0x78D
+#define WM5100_AIF3TX2MIX_INPUT_4_SOURCE        0x78E
+#define WM5100_AIF3TX2MIX_INPUT_4_VOLUME        0x78F
+#define WM5100_EQ1MIX_INPUT_1_SOURCE            0x880
+#define WM5100_EQ1MIX_INPUT_1_VOLUME            0x881
+#define WM5100_EQ1MIX_INPUT_2_SOURCE            0x882
+#define WM5100_EQ1MIX_INPUT_2_VOLUME            0x883
+#define WM5100_EQ1MIX_INPUT_3_SOURCE            0x884
+#define WM5100_EQ1MIX_INPUT_3_VOLUME            0x885
+#define WM5100_EQ1MIX_INPUT_4_SOURCE            0x886
+#define WM5100_EQ1MIX_INPUT_4_VOLUME            0x887
+#define WM5100_EQ2MIX_INPUT_1_SOURCE            0x888
+#define WM5100_EQ2MIX_INPUT_1_VOLUME            0x889
+#define WM5100_EQ2MIX_INPUT_2_SOURCE            0x88A
+#define WM5100_EQ2MIX_INPUT_2_VOLUME            0x88B
+#define WM5100_EQ2MIX_INPUT_3_SOURCE            0x88C
+#define WM5100_EQ2MIX_INPUT_3_VOLUME            0x88D
+#define WM5100_EQ2MIX_INPUT_4_SOURCE            0x88E
+#define WM5100_EQ2MIX_INPUT_4_VOLUME            0x88F
+#define WM5100_EQ3MIX_INPUT_1_SOURCE            0x890
+#define WM5100_EQ3MIX_INPUT_1_VOLUME            0x891
+#define WM5100_EQ3MIX_INPUT_2_SOURCE            0x892
+#define WM5100_EQ3MIX_INPUT_2_VOLUME            0x893
+#define WM5100_EQ3MIX_INPUT_3_SOURCE            0x894
+#define WM5100_EQ3MIX_INPUT_3_VOLUME            0x895
+#define WM5100_EQ3MIX_INPUT_4_SOURCE            0x896
+#define WM5100_EQ3MIX_INPUT_4_VOLUME            0x897
+#define WM5100_EQ4MIX_INPUT_1_SOURCE            0x898
+#define WM5100_EQ4MIX_INPUT_1_VOLUME            0x899
+#define WM5100_EQ4MIX_INPUT_2_SOURCE            0x89A
+#define WM5100_EQ4MIX_INPUT_2_VOLUME            0x89B
+#define WM5100_EQ4MIX_INPUT_3_SOURCE            0x89C
+#define WM5100_EQ4MIX_INPUT_3_VOLUME            0x89D
+#define WM5100_EQ4MIX_INPUT_4_SOURCE            0x89E
+#define WM5100_EQ4MIX_INPUT_4_VOLUME            0x89F
+#define WM5100_DRC1LMIX_INPUT_1_SOURCE          0x8C0
+#define WM5100_DRC1LMIX_INPUT_1_VOLUME          0x8C1
+#define WM5100_DRC1LMIX_INPUT_2_SOURCE          0x8C2
+#define WM5100_DRC1LMIX_INPUT_2_VOLUME          0x8C3
+#define WM5100_DRC1LMIX_INPUT_3_SOURCE          0x8C4
+#define WM5100_DRC1LMIX_INPUT_3_VOLUME          0x8C5
+#define WM5100_DRC1LMIX_INPUT_4_SOURCE          0x8C6
+#define WM5100_DRC1LMIX_INPUT_4_VOLUME          0x8C7
+#define WM5100_DRC1RMIX_INPUT_1_SOURCE          0x8C8
+#define WM5100_DRC1RMIX_INPUT_1_VOLUME          0x8C9
+#define WM5100_DRC1RMIX_INPUT_2_SOURCE          0x8CA
+#define WM5100_DRC1RMIX_INPUT_2_VOLUME          0x8CB
+#define WM5100_DRC1RMIX_INPUT_3_SOURCE          0x8CC
+#define WM5100_DRC1RMIX_INPUT_3_VOLUME          0x8CD
+#define WM5100_DRC1RMIX_INPUT_4_SOURCE          0x8CE
+#define WM5100_DRC1RMIX_INPUT_4_VOLUME          0x8CF
+#define WM5100_HPLP1MIX_INPUT_1_SOURCE          0x900
+#define WM5100_HPLP1MIX_INPUT_1_VOLUME          0x901
+#define WM5100_HPLP1MIX_INPUT_2_SOURCE          0x902
+#define WM5100_HPLP1MIX_INPUT_2_VOLUME          0x903
+#define WM5100_HPLP1MIX_INPUT_3_SOURCE          0x904
+#define WM5100_HPLP1MIX_INPUT_3_VOLUME          0x905
+#define WM5100_HPLP1MIX_INPUT_4_SOURCE          0x906
+#define WM5100_HPLP1MIX_INPUT_4_VOLUME          0x907
+#define WM5100_HPLP2MIX_INPUT_1_SOURCE          0x908
+#define WM5100_HPLP2MIX_INPUT_1_VOLUME          0x909
+#define WM5100_HPLP2MIX_INPUT_2_SOURCE          0x90A
+#define WM5100_HPLP2MIX_INPUT_2_VOLUME          0x90B
+#define WM5100_HPLP2MIX_INPUT_3_SOURCE          0x90C
+#define WM5100_HPLP2MIX_INPUT_3_VOLUME          0x90D
+#define WM5100_HPLP2MIX_INPUT_4_SOURCE          0x90E
+#define WM5100_HPLP2MIX_INPUT_4_VOLUME          0x90F
+#define WM5100_HPLP3MIX_INPUT_1_SOURCE          0x910
+#define WM5100_HPLP3MIX_INPUT_1_VOLUME          0x911
+#define WM5100_HPLP3MIX_INPUT_2_SOURCE          0x912
+#define WM5100_HPLP3MIX_INPUT_2_VOLUME          0x913
+#define WM5100_HPLP3MIX_INPUT_3_SOURCE          0x914
+#define WM5100_HPLP3MIX_INPUT_3_VOLUME          0x915
+#define WM5100_HPLP3MIX_INPUT_4_SOURCE          0x916
+#define WM5100_HPLP3MIX_INPUT_4_VOLUME          0x917
+#define WM5100_HPLP4MIX_INPUT_1_SOURCE          0x918
+#define WM5100_HPLP4MIX_INPUT_1_VOLUME          0x919
+#define WM5100_HPLP4MIX_INPUT_2_SOURCE          0x91A
+#define WM5100_HPLP4MIX_INPUT_2_VOLUME          0x91B
+#define WM5100_HPLP4MIX_INPUT_3_SOURCE          0x91C
+#define WM5100_HPLP4MIX_INPUT_3_VOLUME          0x91D
+#define WM5100_HPLP4MIX_INPUT_4_SOURCE          0x91E
+#define WM5100_HPLP4MIX_INPUT_4_VOLUME          0x91F
+#define WM5100_DSP1LMIX_INPUT_1_SOURCE          0x940
+#define WM5100_DSP1LMIX_INPUT_1_VOLUME          0x941
+#define WM5100_DSP1LMIX_INPUT_2_SOURCE          0x942
+#define WM5100_DSP1LMIX_INPUT_2_VOLUME          0x943
+#define WM5100_DSP1LMIX_INPUT_3_SOURCE          0x944
+#define WM5100_DSP1LMIX_INPUT_3_VOLUME          0x945
+#define WM5100_DSP1LMIX_INPUT_4_SOURCE          0x946
+#define WM5100_DSP1LMIX_INPUT_4_VOLUME          0x947
+#define WM5100_DSP1RMIX_INPUT_1_SOURCE          0x948
+#define WM5100_DSP1RMIX_INPUT_1_VOLUME          0x949
+#define WM5100_DSP1RMIX_INPUT_2_SOURCE          0x94A
+#define WM5100_DSP1RMIX_INPUT_2_VOLUME          0x94B
+#define WM5100_DSP1RMIX_INPUT_3_SOURCE          0x94C
+#define WM5100_DSP1RMIX_INPUT_3_VOLUME          0x94D
+#define WM5100_DSP1RMIX_INPUT_4_SOURCE          0x94E
+#define WM5100_DSP1RMIX_INPUT_4_VOLUME          0x94F
+#define WM5100_DSP1AUX1MIX_INPUT_1_SOURCE       0x950
+#define WM5100_DSP1AUX2MIX_INPUT_1_SOURCE       0x958
+#define WM5100_DSP1AUX3MIX_INPUT_1_SOURCE       0x960
+#define WM5100_DSP1AUX4MIX_INPUT_1_SOURCE       0x968
+#define WM5100_DSP1AUX5MIX_INPUT_1_SOURCE       0x970
+#define WM5100_DSP1AUX6MIX_INPUT_1_SOURCE       0x978
+#define WM5100_DSP2LMIX_INPUT_1_SOURCE          0x980
+#define WM5100_DSP2LMIX_INPUT_1_VOLUME          0x981
+#define WM5100_DSP2LMIX_INPUT_2_SOURCE          0x982
+#define WM5100_DSP2LMIX_INPUT_2_VOLUME          0x983
+#define WM5100_DSP2LMIX_INPUT_3_SOURCE          0x984
+#define WM5100_DSP2LMIX_INPUT_3_VOLUME          0x985
+#define WM5100_DSP2LMIX_INPUT_4_SOURCE          0x986
+#define WM5100_DSP2LMIX_INPUT_4_VOLUME          0x987
+#define WM5100_DSP2RMIX_INPUT_1_SOURCE          0x988
+#define WM5100_DSP2RMIX_INPUT_1_VOLUME          0x989
+#define WM5100_DSP2RMIX_INPUT_2_SOURCE          0x98A
+#define WM5100_DSP2RMIX_INPUT_2_VOLUME          0x98B
+#define WM5100_DSP2RMIX_INPUT_3_SOURCE          0x98C
+#define WM5100_DSP2RMIX_INPUT_3_VOLUME          0x98D
+#define WM5100_DSP2RMIX_INPUT_4_SOURCE          0x98E
+#define WM5100_DSP2RMIX_INPUT_4_VOLUME          0x98F
+#define WM5100_DSP2AUX1MIX_INPUT_1_SOURCE       0x990
+#define WM5100_DSP2AUX2MIX_INPUT_1_SOURCE       0x998
+#define WM5100_DSP2AUX3MIX_INPUT_1_SOURCE       0x9A0
+#define WM5100_DSP2AUX4MIX_INPUT_1_SOURCE       0x9A8
+#define WM5100_DSP2AUX5MIX_INPUT_1_SOURCE       0x9B0
+#define WM5100_DSP2AUX6MIX_INPUT_1_SOURCE       0x9B8
+#define WM5100_DSP3LMIX_INPUT_1_SOURCE          0x9C0
+#define WM5100_DSP3LMIX_INPUT_1_VOLUME          0x9C1
+#define WM5100_DSP3LMIX_INPUT_2_SOURCE          0x9C2
+#define WM5100_DSP3LMIX_INPUT_2_VOLUME          0x9C3
+#define WM5100_DSP3LMIX_INPUT_3_SOURCE          0x9C4
+#define WM5100_DSP3LMIX_INPUT_3_VOLUME          0x9C5
+#define WM5100_DSP3LMIX_INPUT_4_SOURCE          0x9C6
+#define WM5100_DSP3LMIX_INPUT_4_VOLUME          0x9C7
+#define WM5100_DSP3RMIX_INPUT_1_SOURCE          0x9C8
+#define WM5100_DSP3RMIX_INPUT_1_VOLUME          0x9C9
+#define WM5100_DSP3RMIX_INPUT_2_SOURCE          0x9CA
+#define WM5100_DSP3RMIX_INPUT_2_VOLUME          0x9CB
+#define WM5100_DSP3RMIX_INPUT_3_SOURCE          0x9CC
+#define WM5100_DSP3RMIX_INPUT_3_VOLUME          0x9CD
+#define WM5100_DSP3RMIX_INPUT_4_SOURCE          0x9CE
+#define WM5100_DSP3RMIX_INPUT_4_VOLUME          0x9CF
+#define WM5100_DSP3AUX1MIX_INPUT_1_SOURCE       0x9D0
+#define WM5100_DSP3AUX2MIX_INPUT_1_SOURCE       0x9D8
+#define WM5100_DSP3AUX3MIX_INPUT_1_SOURCE       0x9E0
+#define WM5100_DSP3AUX4MIX_INPUT_1_SOURCE       0x9E8
+#define WM5100_DSP3AUX5MIX_INPUT_1_SOURCE       0x9F0
+#define WM5100_DSP3AUX6MIX_INPUT_1_SOURCE       0x9F8
+#define WM5100_ASRC1LMIX_INPUT_1_SOURCE         0xA80
+#define WM5100_ASRC1RMIX_INPUT_1_SOURCE         0xA88
+#define WM5100_ASRC2LMIX_INPUT_1_SOURCE         0xA90
+#define WM5100_ASRC2RMIX_INPUT_1_SOURCE         0xA98
+#define WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE      0xB00
+#define WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE      0xB08
+#define WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE      0xB10
+#define WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE      0xB18
+#define WM5100_ISRC1INT1MIX_INPUT_1_SOURCE      0xB20
+#define WM5100_ISRC1INT2MIX_INPUT_1_SOURCE      0xB28
+#define WM5100_ISRC1INT3MIX_INPUT_1_SOURCE      0xB30
+#define WM5100_ISRC1INT4MIX_INPUT_1_SOURCE      0xB38
+#define WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE      0xB40
+#define WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE      0xB48
+#define WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE      0xB50
+#define WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE      0xB58
+#define WM5100_ISRC2INT1MIX_INPUT_1_SOURCE      0xB60
+#define WM5100_ISRC2INT2MIX_INPUT_1_SOURCE      0xB68
+#define WM5100_ISRC2INT3MIX_INPUT_1_SOURCE      0xB70
+#define WM5100_ISRC2INT4MIX_INPUT_1_SOURCE      0xB78
+#define WM5100_GPIO_CTRL_1                      0xC00
+#define WM5100_GPIO_CTRL_2                      0xC01
+#define WM5100_GPIO_CTRL_3                      0xC02
+#define WM5100_GPIO_CTRL_4                      0xC03
+#define WM5100_GPIO_CTRL_5                      0xC04
+#define WM5100_GPIO_CTRL_6                      0xC05
+#define WM5100_MISC_PAD_CTRL_1                  0xC23
+#define WM5100_MISC_PAD_CTRL_2                  0xC24
+#define WM5100_MISC_PAD_CTRL_3                  0xC25
+#define WM5100_MISC_PAD_CTRL_4                  0xC26
+#define WM5100_MISC_PAD_CTRL_5                  0xC27
+#define WM5100_MISC_GPIO_1                      0xC28
+#define WM5100_INTERRUPT_STATUS_1               0xD00
+#define WM5100_INTERRUPT_STATUS_2               0xD01
+#define WM5100_INTERRUPT_STATUS_3               0xD02
+#define WM5100_INTERRUPT_STATUS_4               0xD03
+#define WM5100_INTERRUPT_RAW_STATUS_2           0xD04
+#define WM5100_INTERRUPT_RAW_STATUS_3           0xD05
+#define WM5100_INTERRUPT_RAW_STATUS_4           0xD06
+#define WM5100_INTERRUPT_STATUS_1_MASK          0xD07
+#define WM5100_INTERRUPT_STATUS_2_MASK          0xD08
+#define WM5100_INTERRUPT_STATUS_3_MASK          0xD09
+#define WM5100_INTERRUPT_STATUS_4_MASK          0xD0A
+#define WM5100_INTERRUPT_CONTROL                0xD1F
+#define WM5100_IRQ_DEBOUNCE_1                   0xD20
+#define WM5100_IRQ_DEBOUNCE_2                   0xD21
+#define WM5100_FX_CTRL                          0xE00
+#define WM5100_EQ1_1                            0xE10
+#define WM5100_EQ1_2                            0xE11
+#define WM5100_EQ1_3                            0xE12
+#define WM5100_EQ1_4                            0xE13
+#define WM5100_EQ1_5                            0xE14
+#define WM5100_EQ1_6                            0xE15
+#define WM5100_EQ1_7                            0xE16
+#define WM5100_EQ1_8                            0xE17
+#define WM5100_EQ1_9                            0xE18
+#define WM5100_EQ1_10                           0xE19
+#define WM5100_EQ1_11                           0xE1A
+#define WM5100_EQ1_12                           0xE1B
+#define WM5100_EQ1_13                           0xE1C
+#define WM5100_EQ1_14                           0xE1D
+#define WM5100_EQ1_15                           0xE1E
+#define WM5100_EQ1_16                           0xE1F
+#define WM5100_EQ1_17                           0xE20
+#define WM5100_EQ1_18                           0xE21
+#define WM5100_EQ1_19                           0xE22
+#define WM5100_EQ1_20                           0xE23
+#define WM5100_EQ2_1                            0xE26
+#define WM5100_EQ2_2                            0xE27
+#define WM5100_EQ2_3                            0xE28
+#define WM5100_EQ2_4                            0xE29
+#define WM5100_EQ2_5                            0xE2A
+#define WM5100_EQ2_6                            0xE2B
+#define WM5100_EQ2_7                            0xE2C
+#define WM5100_EQ2_8                            0xE2D
+#define WM5100_EQ2_9                            0xE2E
+#define WM5100_EQ2_10                           0xE2F
+#define WM5100_EQ2_11                           0xE30
+#define WM5100_EQ2_12                           0xE31
+#define WM5100_EQ2_13                           0xE32
+#define WM5100_EQ2_14                           0xE33
+#define WM5100_EQ2_15                           0xE34
+#define WM5100_EQ2_16                           0xE35
+#define WM5100_EQ2_17                           0xE36
+#define WM5100_EQ2_18                           0xE37
+#define WM5100_EQ2_19                           0xE38
+#define WM5100_EQ2_20                           0xE39
+#define WM5100_EQ3_1                            0xE3C
+#define WM5100_EQ3_2                            0xE3D
+#define WM5100_EQ3_3                            0xE3E
+#define WM5100_EQ3_4                            0xE3F
+#define WM5100_EQ3_5                            0xE40
+#define WM5100_EQ3_6                            0xE41
+#define WM5100_EQ3_7                            0xE42
+#define WM5100_EQ3_8                            0xE43
+#define WM5100_EQ3_9                            0xE44
+#define WM5100_EQ3_10                           0xE45
+#define WM5100_EQ3_11                           0xE46
+#define WM5100_EQ3_12                           0xE47
+#define WM5100_EQ3_13                           0xE48
+#define WM5100_EQ3_14                           0xE49
+#define WM5100_EQ3_15                           0xE4A
+#define WM5100_EQ3_16                           0xE4B
+#define WM5100_EQ3_17                           0xE4C
+#define WM5100_EQ3_18                           0xE4D
+#define WM5100_EQ3_19                           0xE4E
+#define WM5100_EQ3_20                           0xE4F
+#define WM5100_EQ4_1                            0xE52
+#define WM5100_EQ4_2                            0xE53
+#define WM5100_EQ4_3                            0xE54
+#define WM5100_EQ4_4                            0xE55
+#define WM5100_EQ4_5                            0xE56
+#define WM5100_EQ4_6                            0xE57
+#define WM5100_EQ4_7                            0xE58
+#define WM5100_EQ4_8                            0xE59
+#define WM5100_EQ4_9                            0xE5A
+#define WM5100_EQ4_10                           0xE5B
+#define WM5100_EQ4_11                           0xE5C
+#define WM5100_EQ4_12                           0xE5D
+#define WM5100_EQ4_13                           0xE5E
+#define WM5100_EQ4_14                           0xE5F
+#define WM5100_EQ4_15                           0xE60
+#define WM5100_EQ4_16                           0xE61
+#define WM5100_EQ4_17                           0xE62
+#define WM5100_EQ4_18                           0xE63
+#define WM5100_EQ4_19                           0xE64
+#define WM5100_EQ4_20                           0xE65
+#define WM5100_DRC1_CTRL1                       0xE80
+#define WM5100_DRC1_CTRL2                       0xE81
+#define WM5100_DRC1_CTRL3                       0xE82
+#define WM5100_DRC1_CTRL4                       0xE83
+#define WM5100_DRC1_CTRL5                       0xE84
+#define WM5100_HPLPF1_1                         0xEC0
+#define WM5100_HPLPF1_2                         0xEC1
+#define WM5100_HPLPF2_1                         0xEC4
+#define WM5100_HPLPF2_2                         0xEC5
+#define WM5100_HPLPF3_1                         0xEC8
+#define WM5100_HPLPF3_2                         0xEC9
+#define WM5100_HPLPF4_1                         0xECC
+#define WM5100_HPLPF4_2                         0xECD
+#define WM5100_DSP1_DM_0                        0x4000
+#define WM5100_DSP1_DM_1                        0x4001
+#define WM5100_DSP1_DM_2                        0x4002
+#define WM5100_DSP1_DM_3                        0x4003
+#define WM5100_DSP1_DM_508                      0x41FC
+#define WM5100_DSP1_DM_509                      0x41FD
+#define WM5100_DSP1_DM_510                      0x41FE
+#define WM5100_DSP1_DM_511                      0x41FF
+#define WM5100_DSP1_PM_0                        0x4800
+#define WM5100_DSP1_PM_1                        0x4801
+#define WM5100_DSP1_PM_2                        0x4802
+#define WM5100_DSP1_PM_3                        0x4803
+#define WM5100_DSP1_PM_4                        0x4804
+#define WM5100_DSP1_PM_5                        0x4805
+#define WM5100_DSP1_PM_1530                     0x4DFA
+#define WM5100_DSP1_PM_1531                     0x4DFB
+#define WM5100_DSP1_PM_1532                     0x4DFC
+#define WM5100_DSP1_PM_1533                     0x4DFD
+#define WM5100_DSP1_PM_1534                     0x4DFE
+#define WM5100_DSP1_PM_1535                     0x4DFF
+#define WM5100_DSP1_ZM_0                        0x5000
+#define WM5100_DSP1_ZM_1                        0x5001
+#define WM5100_DSP1_ZM_2                        0x5002
+#define WM5100_DSP1_ZM_3                        0x5003
+#define WM5100_DSP1_ZM_2044                     0x57FC
+#define WM5100_DSP1_ZM_2045                     0x57FD
+#define WM5100_DSP1_ZM_2046                     0x57FE
+#define WM5100_DSP1_ZM_2047                     0x57FF
+#define WM5100_DSP2_DM_0                        0x6000
+#define WM5100_DSP2_DM_1                        0x6001
+#define WM5100_DSP2_DM_2                        0x6002
+#define WM5100_DSP2_DM_3                        0x6003
+#define WM5100_DSP2_DM_508                      0x61FC
+#define WM5100_DSP2_DM_509                      0x61FD
+#define WM5100_DSP2_DM_510                      0x61FE
+#define WM5100_DSP2_DM_511                      0x61FF
+#define WM5100_DSP2_PM_0                        0x6800
+#define WM5100_DSP2_PM_1                        0x6801
+#define WM5100_DSP2_PM_2                        0x6802
+#define WM5100_DSP2_PM_3                        0x6803
+#define WM5100_DSP2_PM_4                        0x6804
+#define WM5100_DSP2_PM_5                        0x6805
+#define WM5100_DSP2_PM_1530                     0x6DFA
+#define WM5100_DSP2_PM_1531                     0x6DFB
+#define WM5100_DSP2_PM_1532                     0x6DFC
+#define WM5100_DSP2_PM_1533                     0x6DFD
+#define WM5100_DSP2_PM_1534                     0x6DFE
+#define WM5100_DSP2_PM_1535                     0x6DFF
+#define WM5100_DSP2_ZM_0                        0x7000
+#define WM5100_DSP2_ZM_1                        0x7001
+#define WM5100_DSP2_ZM_2                        0x7002
+#define WM5100_DSP2_ZM_3                        0x7003
+#define WM5100_DSP2_ZM_2044                     0x77FC
+#define WM5100_DSP2_ZM_2045                     0x77FD
+#define WM5100_DSP2_ZM_2046                     0x77FE
+#define WM5100_DSP2_ZM_2047                     0x77FF
+#define WM5100_DSP3_DM_0                        0x8000
+#define WM5100_DSP3_DM_1                        0x8001
+#define WM5100_DSP3_DM_2                        0x8002
+#define WM5100_DSP3_DM_3                        0x8003
+#define WM5100_DSP3_DM_508                      0x81FC
+#define WM5100_DSP3_DM_509                      0x81FD
+#define WM5100_DSP3_DM_510                      0x81FE
+#define WM5100_DSP3_DM_511                      0x81FF
+#define WM5100_DSP3_PM_0                        0x8800
+#define WM5100_DSP3_PM_1                        0x8801
+#define WM5100_DSP3_PM_2                        0x8802
+#define WM5100_DSP3_PM_3                        0x8803
+#define WM5100_DSP3_PM_4                        0x8804
+#define WM5100_DSP3_PM_5                        0x8805
+#define WM5100_DSP3_PM_1530                     0x8DFA
+#define WM5100_DSP3_PM_1531                     0x8DFB
+#define WM5100_DSP3_PM_1532                     0x8DFC
+#define WM5100_DSP3_PM_1533                     0x8DFD
+#define WM5100_DSP3_PM_1534                     0x8DFE
+#define WM5100_DSP3_PM_1535                     0x8DFF
+#define WM5100_DSP3_ZM_0                        0x9000
+#define WM5100_DSP3_ZM_1                        0x9001
+#define WM5100_DSP3_ZM_2                        0x9002
+#define WM5100_DSP3_ZM_3                        0x9003
+#define WM5100_DSP3_ZM_2044                     0x97FC
+#define WM5100_DSP3_ZM_2045                     0x97FD
+#define WM5100_DSP3_ZM_2046                     0x97FE
+#define WM5100_DSP3_ZM_2047                     0x97FF
+
+#define WM5100_REGISTER_COUNT                   1435
+#define WM5100_MAX_REGISTER                     0x97FF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM5100_SW_RST_DEV_ID1_MASK              0xFFFF  /* SW_RST_DEV_ID1 - [15:0] */
+#define WM5100_SW_RST_DEV_ID1_SHIFT                  0  /* SW_RST_DEV_ID1 - [15:0] */
+#define WM5100_SW_RST_DEV_ID1_WIDTH                 16  /* SW_RST_DEV_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM5100_DEVICE_REVISION_MASK             0x000F  /* DEVICE_REVISION - [3:0] */
+#define WM5100_DEVICE_REVISION_SHIFT                 0  /* DEVICE_REVISION - [3:0] */
+#define WM5100_DEVICE_REVISION_WIDTH                 4  /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R16 (0x10) - Ctrl IF 1
+ */
+#define WM5100_AUTO_INC                         0x0001  /* AUTO_INC */
+#define WM5100_AUTO_INC_MASK                    0x0001  /* AUTO_INC */
+#define WM5100_AUTO_INC_SHIFT                        0  /* AUTO_INC */
+#define WM5100_AUTO_INC_WIDTH                        1  /* AUTO_INC */
+
+/*
+ * R32 (0x20) - Tone Generator 1
+ */
+#define WM5100_TONE_RATE_MASK                   0x3000  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_RATE_SHIFT                      12  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_RATE_WIDTH                       2  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_OFFSET_MASK                 0x0300  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE_OFFSET_SHIFT                     8  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE_OFFSET_WIDTH                     2  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE2_ENA                        0x0002  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_MASK                   0x0002  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_SHIFT                       1  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_WIDTH                       1  /* TONE2_ENA */
+#define WM5100_TONE1_ENA                        0x0001  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_MASK                   0x0001  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_SHIFT                       0  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_WIDTH                       1  /* TONE1_ENA */
+
+/*
+ * R48 (0x30) - PWM Drive 1
+ */
+#define WM5100_PWM_RATE_MASK                    0x3000  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_RATE_SHIFT                       12  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_RATE_WIDTH                        2  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_CLK_SEL_MASK                 0x0300  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM_CLK_SEL_SHIFT                     8  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM_CLK_SEL_WIDTH                     2  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM2_OVD                         0x0020  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_MASK                    0x0020  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_SHIFT                        5  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_WIDTH                        1  /* PWM2_OVD */
+#define WM5100_PWM1_OVD                         0x0010  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_MASK                    0x0010  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_SHIFT                        4  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_WIDTH                        1  /* PWM1_OVD */
+#define WM5100_PWM2_ENA                         0x0002  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_MASK                    0x0002  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_SHIFT                        1  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_WIDTH                        1  /* PWM2_ENA */
+#define WM5100_PWM1_ENA                         0x0001  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_MASK                    0x0001  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_SHIFT                        0  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_WIDTH                        1  /* PWM1_ENA */
+
+/*
+ * R49 (0x31) - PWM Drive 2
+ */
+#define WM5100_PWM1_LVL_MASK                    0x03FF  /* PWM1_LVL - [9:0] */
+#define WM5100_PWM1_LVL_SHIFT                        0  /* PWM1_LVL - [9:0] */
+#define WM5100_PWM1_LVL_WIDTH                       10  /* PWM1_LVL - [9:0] */
+
+/*
+ * R50 (0x32) - PWM Drive 3
+ */
+#define WM5100_PWM2_LVL_MASK                    0x03FF  /* PWM2_LVL - [9:0] */
+#define WM5100_PWM2_LVL_SHIFT                        0  /* PWM2_LVL - [9:0] */
+#define WM5100_PWM2_LVL_WIDTH                       10  /* PWM2_LVL - [9:0] */
+
+/*
+ * R256 (0x100) - Clocking 1
+ */
+#define WM5100_CLK_32K_SRC_MASK                 0x000F  /* CLK_32K_SRC - [3:0] */
+#define WM5100_CLK_32K_SRC_SHIFT                     0  /* CLK_32K_SRC - [3:0] */
+#define WM5100_CLK_32K_SRC_WIDTH                     4  /* CLK_32K_SRC - [3:0] */
+
+/*
+ * R257 (0x101) - Clocking 3
+ */
+#define WM5100_SYSCLK_FREQ_MASK                 0x0700  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_FREQ_SHIFT                     8  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_FREQ_WIDTH                     3  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_ENA                       0x0040  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_MASK                  0x0040  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_SHIFT                      6  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_SRC_MASK                  0x000F  /* SYSCLK_SRC - [3:0] */
+#define WM5100_SYSCLK_SRC_SHIFT                      0  /* SYSCLK_SRC - [3:0] */
+#define WM5100_SYSCLK_SRC_WIDTH                      4  /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R258 (0x102) - Clocking 4
+ */
+#define WM5100_SAMPLE_RATE_1_MASK               0x001F  /* SAMPLE_RATE_1 - [4:0] */
+#define WM5100_SAMPLE_RATE_1_SHIFT                   0  /* SAMPLE_RATE_1 - [4:0] */
+#define WM5100_SAMPLE_RATE_1_WIDTH                   5  /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R259 (0x103) - Clocking 5
+ */
+#define WM5100_SAMPLE_RATE_2_MASK               0x001F  /* SAMPLE_RATE_2 - [4:0] */
+#define WM5100_SAMPLE_RATE_2_SHIFT                   0  /* SAMPLE_RATE_2 - [4:0] */
+#define WM5100_SAMPLE_RATE_2_WIDTH                   5  /* SAMPLE_RATE_2 - [4:0] */
+
+/*
+ * R260 (0x104) - Clocking 6
+ */
+#define WM5100_SAMPLE_RATE_3_MASK               0x001F  /* SAMPLE_RATE_3 - [4:0] */
+#define WM5100_SAMPLE_RATE_3_SHIFT                   0  /* SAMPLE_RATE_3 - [4:0] */
+#define WM5100_SAMPLE_RATE_3_WIDTH                   5  /* SAMPLE_RATE_3 - [4:0] */
+
+/*
+ * R263 (0x107) - Clocking 7
+ */
+#define WM5100_ASYNC_CLK_FREQ_MASK              0x0700  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_FREQ_SHIFT                  8  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_FREQ_WIDTH                  3  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_ENA                    0x0040  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_MASK               0x0040  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_SHIFT                   6  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_WIDTH                   1  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_SRC_MASK               0x000F  /* ASYNC_CLK_SRC - [3:0] */
+#define WM5100_ASYNC_CLK_SRC_SHIFT                   0  /* ASYNC_CLK_SRC - [3:0] */
+#define WM5100_ASYNC_CLK_SRC_WIDTH                   4  /* ASYNC_CLK_SRC - [3:0] */
+
+/*
+ * R264 (0x108) - Clocking 8
+ */
+#define WM5100_ASYNC_SAMPLE_RATE_MASK           0x001F  /* ASYNC_SAMPLE_RATE - [4:0] */
+#define WM5100_ASYNC_SAMPLE_RATE_SHIFT               0  /* ASYNC_SAMPLE_RATE - [4:0] */
+#define WM5100_ASYNC_SAMPLE_RATE_WIDTH               5  /* ASYNC_SAMPLE_RATE - [4:0] */
+
+/*
+ * R288 (0x120) - ASRC_ENABLE
+ */
+#define WM5100_ASRC2L_ENA                       0x0008  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_MASK                  0x0008  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_SHIFT                      3  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_WIDTH                      1  /* ASRC2L_ENA */
+#define WM5100_ASRC2R_ENA                       0x0004  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_MASK                  0x0004  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_SHIFT                      2  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_WIDTH                      1  /* ASRC2R_ENA */
+#define WM5100_ASRC1L_ENA                       0x0002  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_MASK                  0x0002  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_SHIFT                      1  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_WIDTH                      1  /* ASRC1L_ENA */
+#define WM5100_ASRC1R_ENA                       0x0001  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_MASK                  0x0001  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_SHIFT                      0  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_WIDTH                      1  /* ASRC1R_ENA */
+
+/*
+ * R289 (0x121) - ASRC_STATUS
+ */
+#define WM5100_ASRC2L_ENA_STS                   0x0008  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_MASK              0x0008  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_SHIFT                  3  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_WIDTH                  1  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS                   0x0004  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_MASK              0x0004  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_SHIFT                  2  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_WIDTH                  1  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS                   0x0002  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_MASK              0x0002  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_SHIFT                  1  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_WIDTH                  1  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS                   0x0001  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_MASK              0x0001  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_SHIFT                  0  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_WIDTH                  1  /* ASRC1R_ENA_STS */
+
+/*
+ * R290 (0x122) - ASRC_RATE1
+ */
+#define WM5100_ASRC_RATE1_MASK                  0x0006  /* ASRC_RATE1 - [2:1] */
+#define WM5100_ASRC_RATE1_SHIFT                      1  /* ASRC_RATE1 - [2:1] */
+#define WM5100_ASRC_RATE1_WIDTH                      2  /* ASRC_RATE1 - [2:1] */
+
+/*
+ * R321 (0x141) - ISRC 1 CTRL 1
+ */
+#define WM5100_ISRC1_DFS_ENA                    0x2000  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_MASK               0x2000  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_SHIFT                  13  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_WIDTH                   1  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_CLK_SEL_MASK               0x0300  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_CLK_SEL_SHIFT                   8  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_CLK_SEL_WIDTH                   2  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_FSH_MASK                   0x000C  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSH_SHIFT                       2  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSH_WIDTH                       2  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSL_MASK                   0x0003  /* ISRC1_FSL - [1:0] */
+#define WM5100_ISRC1_FSL_SHIFT                       0  /* ISRC1_FSL - [1:0] */
+#define WM5100_ISRC1_FSL_WIDTH                       2  /* ISRC1_FSL - [1:0] */
+
+/*
+ * R322 (0x142) - ISRC 1 CTRL 2
+ */
+#define WM5100_ISRC1_INT1_ENA                   0x8000  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_MASK              0x8000  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_SHIFT                 15  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_WIDTH                  1  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT2_ENA                   0x4000  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_MASK              0x4000  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_SHIFT                 14  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_WIDTH                  1  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT3_ENA                   0x2000  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_MASK              0x2000  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_SHIFT                 13  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_WIDTH                  1  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT4_ENA                   0x1000  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_MASK              0x1000  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_SHIFT                 12  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_WIDTH                  1  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_DEC1_ENA                   0x0200  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_MASK              0x0200  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_SHIFT                  9  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_WIDTH                  1  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC2_ENA                   0x0100  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_MASK              0x0100  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_SHIFT                  8  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_WIDTH                  1  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC3_ENA                   0x0080  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_MASK              0x0080  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_SHIFT                  7  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_WIDTH                  1  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC4_ENA                   0x0040  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_MASK              0x0040  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_SHIFT                  6  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_WIDTH                  1  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_NOTCH_ENA                  0x0001  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_MASK             0x0001  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_SHIFT                 0  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_WIDTH                 1  /* ISRC1_NOTCH_ENA */
+
+/*
+ * R323 (0x143) - ISRC 2 CTRL1
+ */
+#define WM5100_ISRC2_DFS_ENA                    0x2000  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_MASK               0x2000  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_SHIFT                  13  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_WIDTH                   1  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_CLK_SEL_MASK               0x0300  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_CLK_SEL_SHIFT                   8  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_CLK_SEL_WIDTH                   2  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_FSH_MASK                   0x000C  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSH_SHIFT                       2  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSH_WIDTH                       2  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSL_MASK                   0x0003  /* ISRC2_FSL - [1:0] */
+#define WM5100_ISRC2_FSL_SHIFT                       0  /* ISRC2_FSL - [1:0] */
+#define WM5100_ISRC2_FSL_WIDTH                       2  /* ISRC2_FSL - [1:0] */
+
+/*
+ * R324 (0x144) - ISRC 2 CTRL 2
+ */
+#define WM5100_ISRC2_INT1_ENA                   0x8000  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_MASK              0x8000  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_SHIFT                 15  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_WIDTH                  1  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT2_ENA                   0x4000  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_MASK              0x4000  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_SHIFT                 14  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_WIDTH                  1  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT3_ENA                   0x2000  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_MASK              0x2000  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_SHIFT                 13  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_WIDTH                  1  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT4_ENA                   0x1000  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_MASK              0x1000  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_SHIFT                 12  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_WIDTH                  1  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_DEC1_ENA                   0x0200  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_MASK              0x0200  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_SHIFT                  9  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_WIDTH                  1  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC2_ENA                   0x0100  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_MASK              0x0100  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_SHIFT                  8  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_WIDTH                  1  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC3_ENA                   0x0080  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_MASK              0x0080  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_SHIFT                  7  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_WIDTH                  1  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC4_ENA                   0x0040  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_MASK              0x0040  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_SHIFT                  6  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_WIDTH                  1  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_NOTCH_ENA                  0x0001  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_MASK             0x0001  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_SHIFT                 0  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_WIDTH                 1  /* ISRC2_NOTCH_ENA */
+
+/*
+ * R386 (0x182) - FLL1 Control 1
+ */
+#define WM5100_FLL1_ENA                         0x0001  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_MASK                    0x0001  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_SHIFT                        0  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_WIDTH                        1  /* FLL1_ENA */
+
+/*
+ * R387 (0x183) - FLL1 Control 2
+ */
+#define WM5100_FLL1_OUTDIV_MASK                 0x3F00  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_OUTDIV_SHIFT                     8  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_OUTDIV_WIDTH                     6  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_FRATIO_MASK                 0x0007  /* FLL1_FRATIO - [2:0] */
+#define WM5100_FLL1_FRATIO_SHIFT                     0  /* FLL1_FRATIO - [2:0] */
+#define WM5100_FLL1_FRATIO_WIDTH                     3  /* FLL1_FRATIO - [2:0] */
+
+/*
+ * R388 (0x184) - FLL1 Control 3
+ */
+#define WM5100_FLL1_THETA_MASK                  0xFFFF  /* FLL1_THETA - [15:0] */
+#define WM5100_FLL1_THETA_SHIFT                      0  /* FLL1_THETA - [15:0] */
+#define WM5100_FLL1_THETA_WIDTH                     16  /* FLL1_THETA - [15:0] */
+
+/*
+ * R390 (0x186) - FLL1 Control 5
+ */
+#define WM5100_FLL1_N_MASK                      0x03FF  /* FLL1_N - [9:0] */
+#define WM5100_FLL1_N_SHIFT                          0  /* FLL1_N - [9:0] */
+#define WM5100_FLL1_N_WIDTH                         10  /* FLL1_N - [9:0] */
+
+/*
+ * R391 (0x187) - FLL1 Control 6
+ */
+#define WM5100_FLL1_REFCLK_DIV_MASK             0x00C0  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_DIV_SHIFT                 6  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_DIV_WIDTH                 2  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_SRC_MASK             0x000F  /* FLL1_REFCLK_SRC - [3:0] */
+#define WM5100_FLL1_REFCLK_SRC_SHIFT                 0  /* FLL1_REFCLK_SRC - [3:0] */
+#define WM5100_FLL1_REFCLK_SRC_WIDTH                 4  /* FLL1_REFCLK_SRC - [3:0] */
+
+/*
+ * R392 (0x188) - FLL1 EFS 1
+ */
+#define WM5100_FLL1_LAMBDA_MASK                 0xFFFF  /* FLL1_LAMBDA - [15:0] */
+#define WM5100_FLL1_LAMBDA_SHIFT                     0  /* FLL1_LAMBDA - [15:0] */
+#define WM5100_FLL1_LAMBDA_WIDTH                    16  /* FLL1_LAMBDA - [15:0] */
+
+/*
+ * R418 (0x1A2) - FLL2 Control 1
+ */
+#define WM5100_FLL2_ENA                         0x0001  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_MASK                    0x0001  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_SHIFT                        0  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_WIDTH                        1  /* FLL2_ENA */
+
+/*
+ * R419 (0x1A3) - FLL2 Control 2
+ */
+#define WM5100_FLL2_OUTDIV_MASK                 0x3F00  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_OUTDIV_SHIFT                     8  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_OUTDIV_WIDTH                     6  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_FRATIO_MASK                 0x0007  /* FLL2_FRATIO - [2:0] */
+#define WM5100_FLL2_FRATIO_SHIFT                     0  /* FLL2_FRATIO - [2:0] */
+#define WM5100_FLL2_FRATIO_WIDTH                     3  /* FLL2_FRATIO - [2:0] */
+
+/*
+ * R420 (0x1A4) - FLL2 Control 3
+ */
+#define WM5100_FLL2_THETA_MASK                  0xFFFF  /* FLL2_THETA - [15:0] */
+#define WM5100_FLL2_THETA_SHIFT                      0  /* FLL2_THETA - [15:0] */
+#define WM5100_FLL2_THETA_WIDTH                     16  /* FLL2_THETA - [15:0] */
+
+/*
+ * R422 (0x1A6) - FLL2 Control 5
+ */
+#define WM5100_FLL2_N_MASK                      0x03FF  /* FLL2_N - [9:0] */
+#define WM5100_FLL2_N_SHIFT                          0  /* FLL2_N - [9:0] */
+#define WM5100_FLL2_N_WIDTH                         10  /* FLL2_N - [9:0] */
+
+/*
+ * R423 (0x1A7) - FLL2 Control 6
+ */
+#define WM5100_FLL2_REFCLK_DIV_MASK             0x00C0  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_DIV_SHIFT                 6  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_DIV_WIDTH                 2  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_SRC_MASK             0x000F  /* FLL2_REFCLK_SRC - [3:0] */
+#define WM5100_FLL2_REFCLK_SRC_SHIFT                 0  /* FLL2_REFCLK_SRC - [3:0] */
+#define WM5100_FLL2_REFCLK_SRC_WIDTH                 4  /* FLL2_REFCLK_SRC - [3:0] */
+
+/*
+ * R424 (0x1A8) - FLL2 EFS 1
+ */
+#define WM5100_FLL2_LAMBDA_MASK                 0xFFFF  /* FLL2_LAMBDA - [15:0] */
+#define WM5100_FLL2_LAMBDA_SHIFT                     0  /* FLL2_LAMBDA - [15:0] */
+#define WM5100_FLL2_LAMBDA_WIDTH                    16  /* FLL2_LAMBDA - [15:0] */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM5100_CP2_BYPASS                       0x0020  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_MASK                  0x0020  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_SHIFT                      5  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_WIDTH                      1  /* CP2_BYPASS */
+#define WM5100_CP2_ENA                          0x0001  /* CP2_ENA */
+#define WM5100_CP2_ENA_MASK                     0x0001  /* CP2_ENA */
+#define WM5100_CP2_ENA_SHIFT                         0  /* CP2_ENA */
+#define WM5100_CP2_ENA_WIDTH                         1  /* CP2_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM5100_LDO2_VSEL_MASK                   0xF800  /* LDO2_VSEL - [15:11] */
+#define WM5100_LDO2_VSEL_SHIFT                      11  /* LDO2_VSEL - [15:11] */
+#define WM5100_LDO2_VSEL_WIDTH                       5  /* LDO2_VSEL - [15:11] */
+
+/*
+ * R514 (0x202) - HP Charge Pump 1
+ */
+#define WM5100_CP1_ENA                          0x0001  /* CP1_ENA */
+#define WM5100_CP1_ENA_MASK                     0x0001  /* CP1_ENA */
+#define WM5100_CP1_ENA_SHIFT                         0  /* CP1_ENA */
+#define WM5100_CP1_ENA_WIDTH                         1  /* CP1_ENA */
+
+/*
+ * R529 (0x211) - LDO1 Control
+ */
+#define WM5100_LDO1_BYPASS                      0x0002  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_MASK                 0x0002  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_SHIFT                     1  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_WIDTH                     1  /* LDO1_BYPASS */
+
+/*
+ * R533 (0x215) - Mic Bias Ctrl 1
+ */
+#define WM5100_MICB1_DISCH                      0x0040  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_MASK                 0x0040  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_SHIFT                     6  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
+#define WM5100_MICB1_RATE                       0x0020  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_MASK                  0x0020  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_SHIFT                      5  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_WIDTH                      1  /* MICB1_RATE */
+#define WM5100_MICB1_LVL_MASK                   0x001C  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_LVL_SHIFT                       2  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_LVL_WIDTH                       3  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_BYPASS                     0x0002  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_MASK                0x0002  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_SHIFT                    1  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_WIDTH                    1  /* MICB1_BYPASS */
+#define WM5100_MICB1_ENA                        0x0001  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_MASK                   0x0001  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_SHIFT                       0  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
+
+/*
+ * R534 (0x216) - Mic Bias Ctrl 2
+ */
+#define WM5100_MICB2_DISCH                      0x0040  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_MASK                 0x0040  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_SHIFT                     6  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
+#define WM5100_MICB2_RATE                       0x0020  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_MASK                  0x0020  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_SHIFT                      5  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_WIDTH                      1  /* MICB2_RATE */
+#define WM5100_MICB2_LVL_MASK                   0x001C  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_LVL_SHIFT                       2  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_LVL_WIDTH                       3  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_BYPASS                     0x0002  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_MASK                0x0002  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_SHIFT                    1  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_WIDTH                    1  /* MICB2_BYPASS */
+#define WM5100_MICB2_ENA                        0x0001  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_MASK                   0x0001  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_SHIFT                       0  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
+
+/*
+ * R535 (0x217) - Mic Bias Ctrl 3
+ */
+#define WM5100_MICB3_DISCH                      0x0040  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_MASK                 0x0040  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_SHIFT                     6  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_WIDTH                     1  /* MICB3_DISCH */
+#define WM5100_MICB3_RATE                       0x0020  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_MASK                  0x0020  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_SHIFT                      5  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_WIDTH                      1  /* MICB3_RATE */
+#define WM5100_MICB3_LVL_MASK                   0x001C  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_LVL_SHIFT                       2  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_LVL_WIDTH                       3  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_BYPASS                     0x0002  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_MASK                0x0002  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_SHIFT                    1  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_WIDTH                    1  /* MICB3_BYPASS */
+#define WM5100_MICB3_ENA                        0x0001  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_MASK                   0x0001  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_SHIFT                       0  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_WIDTH                       1  /* MICB3_ENA */
+
+/*
+ * R640 (0x280) - Accessory Detect Mode 1
+ */
+#define WM5100_ACCDET_BIAS_SRC_MASK             0xC000  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_BIAS_SRC_SHIFT                14  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_BIAS_SRC_WIDTH                 2  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_SRC                       0x2000  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_MASK                  0x2000  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_SHIFT                     13  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_WIDTH                      1  /* ACCDET_SRC */
+#define WM5100_ACCDET_MODE_MASK                 0x0003  /* ACCDET_MODE - [1:0] */
+#define WM5100_ACCDET_MODE_SHIFT                     0  /* ACCDET_MODE - [1:0] */
+#define WM5100_ACCDET_MODE_WIDTH                     2  /* ACCDET_MODE - [1:0] */
+
+/*
+ * R648 (0x288) - Headphone Detect 1
+ */
+#define WM5100_HP_HOLDTIME_MASK                 0x00E0  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_HOLDTIME_SHIFT                     5  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_HOLDTIME_WIDTH                     3  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_CLK_DIV_MASK                  0x0018  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_CLK_DIV_SHIFT                      3  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_CLK_DIV_WIDTH                      2  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_STEP_SIZE                     0x0002  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_MASK                0x0002  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_SHIFT                    1  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_WIDTH                    1  /* HP_STEP_SIZE */
+#define WM5100_HP_POLL                          0x0001  /* HP_POLL */
+#define WM5100_HP_POLL_MASK                     0x0001  /* HP_POLL */
+#define WM5100_HP_POLL_SHIFT                         0  /* HP_POLL */
+#define WM5100_HP_POLL_WIDTH                         1  /* HP_POLL */
+
+/*
+ * R649 (0x289) - Headphone Detect 2
+ */
+#define WM5100_HP_DONE                          0x0080  /* HP_DONE */
+#define WM5100_HP_DONE_MASK                     0x0080  /* HP_DONE */
+#define WM5100_HP_DONE_SHIFT                         7  /* HP_DONE */
+#define WM5100_HP_DONE_WIDTH                         1  /* HP_DONE */
+#define WM5100_HP_LVL_MASK                      0x007F  /* HP_LVL - [6:0] */
+#define WM5100_HP_LVL_SHIFT                          0  /* HP_LVL - [6:0] */
+#define WM5100_HP_LVL_WIDTH                          7  /* HP_LVL - [6:0] */
+
+/*
+ * R656 (0x290) - Mic Detect 1
+ */
+#define WM5100_ACCDET_BIAS_STARTTIME_MASK       0xF000  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_BIAS_STARTTIME_SHIFT          12  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_BIAS_STARTTIME_WIDTH           4  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_RATE_MASK                 0x0F00  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_RATE_SHIFT                     8  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_RATE_WIDTH                     4  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_DBTIME                    0x0002  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_MASK               0x0002  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_SHIFT                   1  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_WIDTH                   1  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_ENA                       0x0001  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_MASK                  0x0001  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_SHIFT                      0  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_WIDTH                      1  /* ACCDET_ENA */
+
+/*
+ * R657 (0x291) - Mic Detect 2
+ */
+#define WM5100_ACCDET_LVL_SEL_MASK              0x00FF  /* ACCDET_LVL_SEL - [7:0] */
+#define WM5100_ACCDET_LVL_SEL_SHIFT                  0  /* ACCDET_LVL_SEL - [7:0] */
+#define WM5100_ACCDET_LVL_SEL_WIDTH                  8  /* ACCDET_LVL_SEL - [7:0] */
+
+/*
+ * R658 (0x292) - Mic Detect 3
+ */
+#define WM5100_ACCDET_LVL_MASK                  0x07FC  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_LVL_SHIFT                      2  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_LVL_WIDTH                      9  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_VALID                     0x0002  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_MASK                0x0002  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_SHIFT                    1  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_WIDTH                    1  /* ACCDET_VALID */
+#define WM5100_ACCDET_STS                       0x0001  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_MASK                  0x0001  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_SHIFT                      0  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_WIDTH                      1  /* ACCDET_STS */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM5100_IN4L_ENA                         0x0080  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_MASK                    0x0080  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_SHIFT                        7  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_WIDTH                        1  /* IN4L_ENA */
+#define WM5100_IN4R_ENA                         0x0040  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_MASK                    0x0040  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_SHIFT                        6  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_WIDTH                        1  /* IN4R_ENA */
+#define WM5100_IN3L_ENA                         0x0020  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_MASK                    0x0020  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_SHIFT                        5  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_WIDTH                        1  /* IN3L_ENA */
+#define WM5100_IN3R_ENA                         0x0010  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_MASK                    0x0010  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_SHIFT                        4  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_WIDTH                        1  /* IN3R_ENA */
+#define WM5100_IN2L_ENA                         0x0008  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_MASK                    0x0008  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_SHIFT                        3  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_WIDTH                        1  /* IN2L_ENA */
+#define WM5100_IN2R_ENA                         0x0004  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_MASK                    0x0004  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_SHIFT                        2  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_WIDTH                        1  /* IN2R_ENA */
+#define WM5100_IN1L_ENA                         0x0002  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_MASK                    0x0002  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_SHIFT                        1  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_WIDTH                        1  /* IN1L_ENA */
+#define WM5100_IN1R_ENA                         0x0001  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_MASK                    0x0001  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_SHIFT                        0  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_WIDTH                        1  /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - Input Enables Status
+ */
+#define WM5100_IN4L_ENA_STS                     0x0080  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_MASK                0x0080  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_SHIFT                    7  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_WIDTH                    1  /* IN4L_ENA_STS */
+#define WM5100_IN4R_ENA_STS                     0x0040  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_MASK                0x0040  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_SHIFT                    6  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_WIDTH                    1  /* IN4R_ENA_STS */
+#define WM5100_IN3L_ENA_STS                     0x0020  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_MASK                0x0020  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_SHIFT                    5  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_WIDTH                    1  /* IN3L_ENA_STS */
+#define WM5100_IN3R_ENA_STS                     0x0010  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_MASK                0x0010  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_SHIFT                    4  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_WIDTH                    1  /* IN3R_ENA_STS */
+#define WM5100_IN2L_ENA_STS                     0x0008  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_MASK                0x0008  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_SHIFT                    3  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_WIDTH                    1  /* IN2L_ENA_STS */
+#define WM5100_IN2R_ENA_STS                     0x0004  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_MASK                0x0004  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_SHIFT                    2  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_WIDTH                    1  /* IN2R_ENA_STS */
+#define WM5100_IN1L_ENA_STS                     0x0002  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_MASK                0x0002  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_SHIFT                    1  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_WIDTH                    1  /* IN1L_ENA_STS */
+#define WM5100_IN1R_ENA_STS                     0x0001  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_MASK                0x0001  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_SHIFT                    0  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_WIDTH                    1  /* IN1R_ENA_STS */
+
+/*
+ * R784 (0x310) - IN1L Control
+ */
+#define WM5100_IN_RATE_MASK                     0xC000  /* IN_RATE - [15:14] */
+#define WM5100_IN_RATE_SHIFT                        14  /* IN_RATE - [15:14] */
+#define WM5100_IN_RATE_WIDTH                         2  /* IN_RATE - [15:14] */
+#define WM5100_IN1_OSR                          0x2000  /* IN1_OSR */
+#define WM5100_IN1_OSR_MASK                     0x2000  /* IN1_OSR */
+#define WM5100_IN1_OSR_SHIFT                        13  /* IN1_OSR */
+#define WM5100_IN1_OSR_WIDTH                         1  /* IN1_OSR */
+#define WM5100_IN1_DMIC_SUP_MASK                0x1800  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_DMIC_SUP_SHIFT                   11  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_DMIC_SUP_WIDTH                    2  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_MODE_MASK                    0x0600  /* IN1_MODE - [10:9] */
+#define WM5100_IN1_MODE_SHIFT                        9  /* IN1_MODE - [10:9] */
+#define WM5100_IN1_MODE_WIDTH                        2  /* IN1_MODE - [10:9] */
+#define WM5100_IN1L_PGA_VOL_MASK                0x00FE  /* IN1L_PGA_VOL - [7:1] */
+#define WM5100_IN1L_PGA_VOL_SHIFT                    1  /* IN1L_PGA_VOL - [7:1] */
+#define WM5100_IN1L_PGA_VOL_WIDTH                    7  /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R785 (0x311) - IN1R Control
+ */
+#define WM5100_IN1R_PGA_VOL_MASK                0x00FE  /* IN1R_PGA_VOL - [7:1] */
+#define WM5100_IN1R_PGA_VOL_SHIFT                    1  /* IN1R_PGA_VOL - [7:1] */
+#define WM5100_IN1R_PGA_VOL_WIDTH                    7  /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R786 (0x312) - IN2L Control
+ */
+#define WM5100_IN2_OSR                          0x2000  /* IN2_OSR */
+#define WM5100_IN2_OSR_MASK                     0x2000  /* IN2_OSR */
+#define WM5100_IN2_OSR_SHIFT                        13  /* IN2_OSR */
+#define WM5100_IN2_OSR_WIDTH                         1  /* IN2_OSR */
+#define WM5100_IN2_DMIC_SUP_MASK                0x1800  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_DMIC_SUP_SHIFT                   11  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_DMIC_SUP_WIDTH                    2  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_MODE_MASK                    0x0600  /* IN2_MODE - [10:9] */
+#define WM5100_IN2_MODE_SHIFT                        9  /* IN2_MODE - [10:9] */
+#define WM5100_IN2_MODE_WIDTH                        2  /* IN2_MODE - [10:9] */
+#define WM5100_IN2L_PGA_VOL_MASK                0x00FE  /* IN2L_PGA_VOL - [7:1] */
+#define WM5100_IN2L_PGA_VOL_SHIFT                    1  /* IN2L_PGA_VOL - [7:1] */
+#define WM5100_IN2L_PGA_VOL_WIDTH                    7  /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R787 (0x313) - IN2R Control
+ */
+#define WM5100_IN2R_PGA_VOL_MASK                0x00FE  /* IN2R_PGA_VOL - [7:1] */
+#define WM5100_IN2R_PGA_VOL_SHIFT                    1  /* IN2R_PGA_VOL - [7:1] */
+#define WM5100_IN2R_PGA_VOL_WIDTH                    7  /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R788 (0x314) - IN3L Control
+ */
+#define WM5100_IN3_OSR                          0x2000  /* IN3_OSR */
+#define WM5100_IN3_OSR_MASK                     0x2000  /* IN3_OSR */
+#define WM5100_IN3_OSR_SHIFT                        13  /* IN3_OSR */
+#define WM5100_IN3_OSR_WIDTH                         1  /* IN3_OSR */
+#define WM5100_IN3_DMIC_SUP_MASK                0x1800  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_DMIC_SUP_SHIFT                   11  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_DMIC_SUP_WIDTH                    2  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_MODE_MASK                    0x0600  /* IN3_MODE - [10:9] */
+#define WM5100_IN3_MODE_SHIFT                        9  /* IN3_MODE - [10:9] */
+#define WM5100_IN3_MODE_WIDTH                        2  /* IN3_MODE - [10:9] */
+#define WM5100_IN3L_PGA_VOL_MASK                0x00FE  /* IN3L_PGA_VOL - [7:1] */
+#define WM5100_IN3L_PGA_VOL_SHIFT                    1  /* IN3L_PGA_VOL - [7:1] */
+#define WM5100_IN3L_PGA_VOL_WIDTH                    7  /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R789 (0x315) - IN3R Control
+ */
+#define WM5100_IN3R_PGA_VOL_MASK                0x00FE  /* IN3R_PGA_VOL - [7:1] */
+#define WM5100_IN3R_PGA_VOL_SHIFT                    1  /* IN3R_PGA_VOL - [7:1] */
+#define WM5100_IN3R_PGA_VOL_WIDTH                    7  /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R790 (0x316) - IN4L Control
+ */
+#define WM5100_IN4_OSR                          0x2000  /* IN4_OSR */
+#define WM5100_IN4_OSR_MASK                     0x2000  /* IN4_OSR */
+#define WM5100_IN4_OSR_SHIFT                        13  /* IN4_OSR */
+#define WM5100_IN4_OSR_WIDTH                         1  /* IN4_OSR */
+#define WM5100_IN4_DMIC_SUP_MASK                0x1800  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_DMIC_SUP_SHIFT                   11  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_DMIC_SUP_WIDTH                    2  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_MODE_MASK                    0x0600  /* IN4_MODE - [10:9] */
+#define WM5100_IN4_MODE_SHIFT                        9  /* IN4_MODE - [10:9] */
+#define WM5100_IN4_MODE_WIDTH                        2  /* IN4_MODE - [10:9] */
+#define WM5100_IN4L_PGA_VOL_MASK                0x00FE  /* IN4L_PGA_VOL - [7:1] */
+#define WM5100_IN4L_PGA_VOL_SHIFT                    1  /* IN4L_PGA_VOL - [7:1] */
+#define WM5100_IN4L_PGA_VOL_WIDTH                    7  /* IN4L_PGA_VOL - [7:1] */
+
+/*
+ * R791 (0x317) - IN4R Control
+ */
+#define WM5100_IN4R_PGA_VOL_MASK                0x00FE  /* IN4R_PGA_VOL - [7:1] */
+#define WM5100_IN4R_PGA_VOL_SHIFT                    1  /* IN4R_PGA_VOL - [7:1] */
+#define WM5100_IN4R_PGA_VOL_WIDTH                    7  /* IN4R_PGA_VOL - [7:1] */
+
+/*
+ * R792 (0x318) - RXANC_SRC
+ */
+#define WM5100_IN_RXANC_SEL_MASK                0x0007  /* IN_RXANC_SEL - [2:0] */
+#define WM5100_IN_RXANC_SEL_SHIFT                    0  /* IN_RXANC_SEL - [2:0] */
+#define WM5100_IN_RXANC_SEL_WIDTH                    3  /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R793 (0x319) - Input Volume Ramp
+ */
+#define WM5100_IN_VD_RAMP_MASK                  0x0070  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VD_RAMP_SHIFT                      4  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VD_RAMP_WIDTH                      3  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VI_RAMP_MASK                  0x0007  /* IN_VI_RAMP - [2:0] */
+#define WM5100_IN_VI_RAMP_SHIFT                      0  /* IN_VI_RAMP - [2:0] */
+#define WM5100_IN_VI_RAMP_WIDTH                      3  /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R800 (0x320) - ADC Digital Volume 1L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN1L_MUTE                        0x0100  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_MASK                   0x0100  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_SHIFT                       8  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_WIDTH                       1  /* IN1L_MUTE */
+#define WM5100_IN1L_VOL_MASK                    0x00FF  /* IN1L_VOL - [7:0] */
+#define WM5100_IN1L_VOL_SHIFT                        0  /* IN1L_VOL - [7:0] */
+#define WM5100_IN1L_VOL_WIDTH                        8  /* IN1L_VOL - [7:0] */
+
+/*
+ * R801 (0x321) - ADC Digital Volume 1R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN1R_MUTE                        0x0100  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_MASK                   0x0100  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_SHIFT                       8  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_WIDTH                       1  /* IN1R_MUTE */
+#define WM5100_IN1R_VOL_MASK                    0x00FF  /* IN1R_VOL - [7:0] */
+#define WM5100_IN1R_VOL_SHIFT                        0  /* IN1R_VOL - [7:0] */
+#define WM5100_IN1R_VOL_WIDTH                        8  /* IN1R_VOL - [7:0] */
+
+/*
+ * R802 (0x322) - ADC Digital Volume 2L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN2L_MUTE                        0x0100  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_MASK                   0x0100  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_SHIFT                       8  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_WIDTH                       1  /* IN2L_MUTE */
+#define WM5100_IN2L_VOL_MASK                    0x00FF  /* IN2L_VOL - [7:0] */
+#define WM5100_IN2L_VOL_SHIFT                        0  /* IN2L_VOL - [7:0] */
+#define WM5100_IN2L_VOL_WIDTH                        8  /* IN2L_VOL - [7:0] */
+
+/*
+ * R803 (0x323) - ADC Digital Volume 2R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN2R_MUTE                        0x0100  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_MASK                   0x0100  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_SHIFT                       8  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_WIDTH                       1  /* IN2R_MUTE */
+#define WM5100_IN2R_VOL_MASK                    0x00FF  /* IN2R_VOL - [7:0] */
+#define WM5100_IN2R_VOL_SHIFT                        0  /* IN2R_VOL - [7:0] */
+#define WM5100_IN2R_VOL_WIDTH                        8  /* IN2R_VOL - [7:0] */
+
+/*
+ * R804 (0x324) - ADC Digital Volume 3L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN3L_MUTE                        0x0100  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_MASK                   0x0100  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_SHIFT                       8  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_WIDTH                       1  /* IN3L_MUTE */
+#define WM5100_IN3L_VOL_MASK                    0x00FF  /* IN3L_VOL - [7:0] */
+#define WM5100_IN3L_VOL_SHIFT                        0  /* IN3L_VOL - [7:0] */
+#define WM5100_IN3L_VOL_WIDTH                        8  /* IN3L_VOL - [7:0] */
+
+/*
+ * R805 (0x325) - ADC Digital Volume 3R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN3R_MUTE                        0x0100  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_MASK                   0x0100  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_SHIFT                       8  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_WIDTH                       1  /* IN3R_MUTE */
+#define WM5100_IN3R_VOL_MASK                    0x00FF  /* IN3R_VOL - [7:0] */
+#define WM5100_IN3R_VOL_SHIFT                        0  /* IN3R_VOL - [7:0] */
+#define WM5100_IN3R_VOL_WIDTH                        8  /* IN3R_VOL - [7:0] */
+
+/*
+ * R806 (0x326) - ADC Digital Volume 4L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN4L_MUTE                        0x0100  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_MASK                   0x0100  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_SHIFT                       8  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_WIDTH                       1  /* IN4L_MUTE */
+#define WM5100_IN4L_VOL_MASK                    0x00FF  /* IN4L_VOL - [7:0] */
+#define WM5100_IN4L_VOL_SHIFT                        0  /* IN4L_VOL - [7:0] */
+#define WM5100_IN4L_VOL_WIDTH                        8  /* IN4L_VOL - [7:0] */
+
+/*
+ * R807 (0x327) - ADC Digital Volume 4R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN4R_MUTE                        0x0100  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_MASK                   0x0100  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_SHIFT                       8  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_WIDTH                       1  /* IN4R_MUTE */
+#define WM5100_IN4R_VOL_MASK                    0x00FF  /* IN4R_VOL - [7:0] */
+#define WM5100_IN4R_VOL_SHIFT                        0  /* IN4R_VOL - [7:0] */
+#define WM5100_IN4R_VOL_WIDTH                        8  /* IN4R_VOL - [7:0] */
+
+/*
+ * R1025 (0x401) - Output Enables 2
+ */
+#define WM5100_OUT6L_ENA                        0x0800  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_MASK                   0x0800  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_SHIFT                      11  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_WIDTH                       1  /* OUT6L_ENA */
+#define WM5100_OUT6R_ENA                        0x0400  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_MASK                   0x0400  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_SHIFT                      10  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_WIDTH                       1  /* OUT6R_ENA */
+#define WM5100_OUT5L_ENA                        0x0200  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_MASK                   0x0200  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_SHIFT                       9  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_WIDTH                       1  /* OUT5L_ENA */
+#define WM5100_OUT5R_ENA                        0x0100  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_MASK                   0x0100  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_SHIFT                       8  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_WIDTH                       1  /* OUT5R_ENA */
+#define WM5100_OUT4L_ENA                        0x0080  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_MASK                   0x0080  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_SHIFT                       7  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_WIDTH                       1  /* OUT4L_ENA */
+#define WM5100_OUT4R_ENA                        0x0040  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_MASK                   0x0040  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_SHIFT                       6  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_WIDTH                       1  /* OUT4R_ENA */
+
+/*
+ * R1026 (0x402) - Output Status 1
+ */
+#define WM5100_OUT3L_ENA_STS                    0x0020  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_MASK               0x0020  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_SHIFT                   5  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_WIDTH                   1  /* OUT3L_ENA_STS */
+#define WM5100_OUT3R_ENA_STS                    0x0010  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_MASK               0x0010  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_SHIFT                   4  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_WIDTH                   1  /* OUT3R_ENA_STS */
+#define WM5100_OUT2L_ENA_STS                    0x0008  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_MASK               0x0008  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_SHIFT                   3  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_WIDTH                   1  /* OUT2L_ENA_STS */
+#define WM5100_OUT2R_ENA_STS                    0x0004  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_MASK               0x0004  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_SHIFT                   2  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_WIDTH                   1  /* OUT2R_ENA_STS */
+#define WM5100_OUT1L_ENA_STS                    0x0002  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_MASK               0x0002  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_SHIFT                   1  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_WIDTH                   1  /* OUT1L_ENA_STS */
+#define WM5100_OUT1R_ENA_STS                    0x0001  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_MASK               0x0001  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_SHIFT                   0  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_WIDTH                   1  /* OUT1R_ENA_STS */
+
+/*
+ * R1027 (0x403) - Output Status 2
+ */
+#define WM5100_OUT6L_ENA_STS                    0x0800  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_MASK               0x0800  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_SHIFT                  11  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_WIDTH                   1  /* OUT6L_ENA_STS */
+#define WM5100_OUT6R_ENA_STS                    0x0400  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_MASK               0x0400  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_SHIFT                  10  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_WIDTH                   1  /* OUT6R_ENA_STS */
+#define WM5100_OUT5L_ENA_STS                    0x0200  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_MASK               0x0200  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_SHIFT                   9  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_WIDTH                   1  /* OUT5L_ENA_STS */
+#define WM5100_OUT5R_ENA_STS                    0x0100  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_MASK               0x0100  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_SHIFT                   8  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_WIDTH                   1  /* OUT5R_ENA_STS */
+#define WM5100_OUT4L_ENA_STS                    0x0080  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_MASK               0x0080  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_SHIFT                   7  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_WIDTH                   1  /* OUT4L_ENA_STS */
+#define WM5100_OUT4R_ENA_STS                    0x0040  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_MASK               0x0040  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_SHIFT                   6  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_WIDTH                   1  /* OUT4R_ENA_STS */
+
+/*
+ * R1032 (0x408) - Channel Enables 1
+ */
+#define WM5100_HP3L_ENA                         0x0020  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_MASK                    0x0020  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_SHIFT                        5  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_WIDTH                        1  /* HP3L_ENA */
+#define WM5100_HP3R_ENA                         0x0010  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_MASK                    0x0010  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_SHIFT                        4  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_WIDTH                        1  /* HP3R_ENA */
+#define WM5100_HP2L_ENA                         0x0008  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_MASK                    0x0008  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_SHIFT                        3  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_WIDTH                        1  /* HP2L_ENA */
+#define WM5100_HP2R_ENA                         0x0004  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_MASK                    0x0004  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_SHIFT                        2  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_WIDTH                        1  /* HP2R_ENA */
+#define WM5100_HP1L_ENA                         0x0002  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_MASK                    0x0002  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_SHIFT                        1  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_WIDTH                        1  /* HP1L_ENA */
+#define WM5100_HP1R_ENA                         0x0001  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_MASK                    0x0001  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_SHIFT                        0  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_WIDTH                        1  /* HP1R_ENA */
+
+/*
+ * R1040 (0x410) - Out Volume 1L
+ */
+#define WM5100_OUT_RATE_MASK                    0xC000  /* OUT_RATE - [15:14] */
+#define WM5100_OUT_RATE_SHIFT                       14  /* OUT_RATE - [15:14] */
+#define WM5100_OUT_RATE_WIDTH                        2  /* OUT_RATE - [15:14] */
+#define WM5100_OUT1_OSR                         0x2000  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_MASK                    0x2000  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_SHIFT                       13  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_WIDTH                        1  /* OUT1_OSR */
+#define WM5100_OUT1_MONO                        0x1000  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_MASK                   0x1000  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_SHIFT                      12  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_WIDTH                       1  /* OUT1_MONO */
+#define WM5100_OUT1L_ANC_SRC                    0x0800  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_MASK               0x0800  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_SHIFT                  11  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_WIDTH                   1  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_PGA_VOL_MASK               0x00FE  /* OUT1L_PGA_VOL - [7:1] */
+#define WM5100_OUT1L_PGA_VOL_SHIFT                   1  /* OUT1L_PGA_VOL - [7:1] */
+#define WM5100_OUT1L_PGA_VOL_WIDTH                   7  /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1041 (0x411) - Out Volume 1R
+ */
+#define WM5100_OUT1R_ANC_SRC                    0x0800  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_MASK               0x0800  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_SHIFT                  11  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_WIDTH                   1  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_PGA_VOL_MASK               0x00FE  /* OUT1R_PGA_VOL - [7:1] */
+#define WM5100_OUT1R_PGA_VOL_SHIFT                   1  /* OUT1R_PGA_VOL - [7:1] */
+#define WM5100_OUT1R_PGA_VOL_WIDTH                   7  /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1042 (0x412) - DAC Volume Limit 1L
+ */
+#define WM5100_OUT1L_VOL_LIM_MASK               0x00FF  /* OUT1L_VOL_LIM - [7:0] */
+#define WM5100_OUT1L_VOL_LIM_SHIFT                   0  /* OUT1L_VOL_LIM - [7:0] */
+#define WM5100_OUT1L_VOL_LIM_WIDTH                   8  /* OUT1L_VOL_LIM - [7:0] */
+
+/*
+ * R1043 (0x413) - DAC Volume Limit 1R
+ */
+#define WM5100_OUT1R_VOL_LIM_MASK               0x00FF  /* OUT1R_VOL_LIM - [7:0] */
+#define WM5100_OUT1R_VOL_LIM_SHIFT                   0  /* OUT1R_VOL_LIM - [7:0] */
+#define WM5100_OUT1R_VOL_LIM_WIDTH                   8  /* OUT1R_VOL_LIM - [7:0] */
+
+/*
+ * R1044 (0x414) - Out Volume 2L
+ */
+#define WM5100_OUT2_OSR                         0x2000  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_MASK                    0x2000  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_SHIFT                       13  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_WIDTH                        1  /* OUT2_OSR */
+#define WM5100_OUT2_MONO                        0x1000  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_MASK                   0x1000  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_SHIFT                      12  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_WIDTH                       1  /* OUT2_MONO */
+#define WM5100_OUT2L_ANC_SRC                    0x0800  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_MASK               0x0800  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_SHIFT                  11  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_WIDTH                   1  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_PGA_VOL_MASK               0x00FE  /* OUT2L_PGA_VOL - [7:1] */
+#define WM5100_OUT2L_PGA_VOL_SHIFT                   1  /* OUT2L_PGA_VOL - [7:1] */
+#define WM5100_OUT2L_PGA_VOL_WIDTH                   7  /* OUT2L_PGA_VOL - [7:1] */
+
+/*
+ * R1045 (0x415) - Out Volume 2R
+ */
+#define WM5100_OUT2R_ANC_SRC                    0x0800  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_MASK               0x0800  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_SHIFT                  11  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_WIDTH                   1  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_PGA_VOL_MASK               0x00FE  /* OUT2R_PGA_VOL - [7:1] */
+#define WM5100_OUT2R_PGA_VOL_SHIFT                   1  /* OUT2R_PGA_VOL - [7:1] */
+#define WM5100_OUT2R_PGA_VOL_WIDTH                   7  /* OUT2R_PGA_VOL - [7:1] */
+
+/*
+ * R1046 (0x416) - DAC Volume Limit 2L
+ */
+#define WM5100_OUT2L_VOL_LIM_MASK               0x00FF  /* OUT2L_VOL_LIM - [7:0] */
+#define WM5100_OUT2L_VOL_LIM_SHIFT                   0  /* OUT2L_VOL_LIM - [7:0] */
+#define WM5100_OUT2L_VOL_LIM_WIDTH                   8  /* OUT2L_VOL_LIM - [7:0] */
+
+/*
+ * R1047 (0x417) - DAC Volume Limit 2R
+ */
+#define WM5100_OUT2R_VOL_LIM_MASK               0x00FF  /* OUT2R_VOL_LIM - [7:0] */
+#define WM5100_OUT2R_VOL_LIM_SHIFT                   0  /* OUT2R_VOL_LIM - [7:0] */
+#define WM5100_OUT2R_VOL_LIM_WIDTH                   8  /* OUT2R_VOL_LIM - [7:0] */
+
+/*
+ * R1048 (0x418) - Out Volume 3L
+ */
+#define WM5100_OUT3_OSR                         0x2000  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_MASK                    0x2000  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_SHIFT                       13  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_WIDTH                        1  /* OUT3_OSR */
+#define WM5100_OUT3_MONO                        0x1000  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_MASK                   0x1000  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_SHIFT                      12  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_WIDTH                       1  /* OUT3_MONO */
+#define WM5100_OUT3L_ANC_SRC                    0x0800  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_MASK               0x0800  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_SHIFT                  11  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_WIDTH                   1  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_PGA_VOL_MASK               0x00FE  /* OUT3L_PGA_VOL - [7:1] */
+#define WM5100_OUT3L_PGA_VOL_SHIFT                   1  /* OUT3L_PGA_VOL - [7:1] */
+#define WM5100_OUT3L_PGA_VOL_WIDTH                   7  /* OUT3L_PGA_VOL - [7:1] */
+
+/*
+ * R1049 (0x419) - Out Volume 3R
+ */
+#define WM5100_OUT3R_ANC_SRC                    0x0800  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_MASK               0x0800  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_SHIFT                  11  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_WIDTH                   1  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_PGA_VOL_MASK               0x00FE  /* OUT3R_PGA_VOL - [7:1] */
+#define WM5100_OUT3R_PGA_VOL_SHIFT                   1  /* OUT3R_PGA_VOL - [7:1] */
+#define WM5100_OUT3R_PGA_VOL_WIDTH                   7  /* OUT3R_PGA_VOL - [7:1] */
+
+/*
+ * R1050 (0x41A) - DAC Volume Limit 3L
+ */
+#define WM5100_OUT3L_VOL_LIM_MASK               0x00FF  /* OUT3L_VOL_LIM - [7:0] */
+#define WM5100_OUT3L_VOL_LIM_SHIFT                   0  /* OUT3L_VOL_LIM - [7:0] */
+#define WM5100_OUT3L_VOL_LIM_WIDTH                   8  /* OUT3L_VOL_LIM - [7:0] */
+
+/*
+ * R1051 (0x41B) - DAC Volume Limit 3R
+ */
+#define WM5100_OUT3R_VOL_LIM_MASK               0x00FF  /* OUT3R_VOL_LIM - [7:0] */
+#define WM5100_OUT3R_VOL_LIM_SHIFT                   0  /* OUT3R_VOL_LIM - [7:0] */
+#define WM5100_OUT3R_VOL_LIM_WIDTH                   8  /* OUT3R_VOL_LIM - [7:0] */
+
+/*
+ * R1052 (0x41C) - Out Volume 4L
+ */
+#define WM5100_OUT4_OSR                         0x2000  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_MASK                    0x2000  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_SHIFT                       13  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_WIDTH                        1  /* OUT4_OSR */
+#define WM5100_OUT4L_ANC_SRC                    0x0800  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_MASK               0x0800  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_SHIFT                  11  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_WIDTH                   1  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_VOL_LIM_MASK               0x00FF  /* OUT4L_VOL_LIM - [7:0] */
+#define WM5100_OUT4L_VOL_LIM_SHIFT                   0  /* OUT4L_VOL_LIM - [7:0] */
+#define WM5100_OUT4L_VOL_LIM_WIDTH                   8  /* OUT4L_VOL_LIM - [7:0] */
+
+/*
+ * R1053 (0x41D) - Out Volume 4R
+ */
+#define WM5100_OUT4R_ANC_SRC                    0x0800  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_MASK               0x0800  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_SHIFT                  11  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_WIDTH                   1  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_VOL_LIM_MASK               0x00FF  /* OUT4R_VOL_LIM - [7:0] */
+#define WM5100_OUT4R_VOL_LIM_SHIFT                   0  /* OUT4R_VOL_LIM - [7:0] */
+#define WM5100_OUT4R_VOL_LIM_WIDTH                   8  /* OUT4R_VOL_LIM - [7:0] */
+
+/*
+ * R1054 (0x41E) - DAC Volume Limit 5L
+ */
+#define WM5100_OUT5_OSR                         0x2000  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_MASK                    0x2000  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_SHIFT                       13  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_WIDTH                        1  /* OUT5_OSR */
+#define WM5100_OUT5L_ANC_SRC                    0x0800  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_MASK               0x0800  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_SHIFT                  11  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_WIDTH                   1  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_VOL_LIM_MASK               0x00FF  /* OUT5L_VOL_LIM - [7:0] */
+#define WM5100_OUT5L_VOL_LIM_SHIFT                   0  /* OUT5L_VOL_LIM - [7:0] */
+#define WM5100_OUT5L_VOL_LIM_WIDTH                   8  /* OUT5L_VOL_LIM - [7:0] */
+
+/*
+ * R1055 (0x41F) - DAC Volume Limit 5R
+ */
+#define WM5100_OUT5R_ANC_SRC                    0x0800  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_MASK               0x0800  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_SHIFT                  11  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_WIDTH                   1  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_VOL_LIM_MASK               0x00FF  /* OUT5R_VOL_LIM - [7:0] */
+#define WM5100_OUT5R_VOL_LIM_SHIFT                   0  /* OUT5R_VOL_LIM - [7:0] */
+#define WM5100_OUT5R_VOL_LIM_WIDTH                   8  /* OUT5R_VOL_LIM - [7:0] */
+
+/*
+ * R1056 (0x420) - DAC Volume Limit 6L
+ */
+#define WM5100_OUT6_OSR                         0x2000  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_MASK                    0x2000  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_SHIFT                       13  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_WIDTH                        1  /* OUT6_OSR */
+#define WM5100_OUT6L_ANC_SRC                    0x0800  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_MASK               0x0800  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_SHIFT                  11  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_WIDTH                   1  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_VOL_LIM_MASK               0x00FF  /* OUT6L_VOL_LIM - [7:0] */
+#define WM5100_OUT6L_VOL_LIM_SHIFT                   0  /* OUT6L_VOL_LIM - [7:0] */
+#define WM5100_OUT6L_VOL_LIM_WIDTH                   8  /* OUT6L_VOL_LIM - [7:0] */
+
+/*
+ * R1057 (0x421) - DAC Volume Limit 6R
+ */
+#define WM5100_OUT6R_ANC_SRC                    0x0800  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_MASK               0x0800  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_SHIFT                  11  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_WIDTH                   1  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_VOL_LIM_MASK               0x00FF  /* OUT6R_VOL_LIM - [7:0] */
+#define WM5100_OUT6R_VOL_LIM_SHIFT                   0  /* OUT6R_VOL_LIM - [7:0] */
+#define WM5100_OUT6R_VOL_LIM_WIDTH                   8  /* OUT6R_VOL_LIM - [7:0] */
+
+/*
+ * R1088 (0x440) - DAC AEC Control 1
+ */
+#define WM5100_AEC_LOOPBACK_SRC_MASK            0x003C  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_LOOPBACK_SRC_SHIFT                2  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_LOOPBACK_SRC_WIDTH                4  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_ENA_STS                      0x0002  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_MASK                 0x0002  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_SHIFT                     1  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_WIDTH                     1  /* AEC_ENA_STS */
+#define WM5100_AEC_LOOPBACK_ENA                 0x0001  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_MASK            0x0001  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_SHIFT                0  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_WIDTH                1  /* AEC_LOOPBACK_ENA */
+
+/*
+ * R1089 (0x441) - Output Volume Ramp
+ */
+#define WM5100_OUT_VD_RAMP_MASK                 0x0070  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VD_RAMP_SHIFT                     4  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VD_RAMP_WIDTH                     3  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VI_RAMP_MASK                 0x0007  /* OUT_VI_RAMP - [2:0] */
+#define WM5100_OUT_VI_RAMP_SHIFT                     0  /* OUT_VI_RAMP - [2:0] */
+#define WM5100_OUT_VI_RAMP_WIDTH                     3  /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1152 (0x480) - DAC Digital Volume 1L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT1L_MUTE                       0x0100  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_MASK                  0x0100  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_SHIFT                      8  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_WIDTH                      1  /* OUT1L_MUTE */
+#define WM5100_OUT1L_VOL_MASK                   0x00FF  /* OUT1L_VOL - [7:0] */
+#define WM5100_OUT1L_VOL_SHIFT                       0  /* OUT1L_VOL - [7:0] */
+#define WM5100_OUT1L_VOL_WIDTH                       8  /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1153 (0x481) - DAC Digital Volume 1R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT1R_MUTE                       0x0100  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_MASK                  0x0100  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_SHIFT                      8  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_WIDTH                      1  /* OUT1R_MUTE */
+#define WM5100_OUT1R_VOL_MASK                   0x00FF  /* OUT1R_VOL - [7:0] */
+#define WM5100_OUT1R_VOL_SHIFT                       0  /* OUT1R_VOL - [7:0] */
+#define WM5100_OUT1R_VOL_WIDTH                       8  /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1154 (0x482) - DAC Digital Volume 2L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT2L_MUTE                       0x0100  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_MASK                  0x0100  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_SHIFT                      8  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_WIDTH                      1  /* OUT2L_MUTE */
+#define WM5100_OUT2L_VOL_MASK                   0x00FF  /* OUT2L_VOL - [7:0] */
+#define WM5100_OUT2L_VOL_SHIFT                       0  /* OUT2L_VOL - [7:0] */
+#define WM5100_OUT2L_VOL_WIDTH                       8  /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1155 (0x483) - DAC Digital Volume 2R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT2R_MUTE                       0x0100  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_MASK                  0x0100  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_SHIFT                      8  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_WIDTH                      1  /* OUT2R_MUTE */
+#define WM5100_OUT2R_VOL_MASK                   0x00FF  /* OUT2R_VOL - [7:0] */
+#define WM5100_OUT2R_VOL_SHIFT                       0  /* OUT2R_VOL - [7:0] */
+#define WM5100_OUT2R_VOL_WIDTH                       8  /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1156 (0x484) - DAC Digital Volume 3L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT3L_MUTE                       0x0100  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_MASK                  0x0100  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_SHIFT                      8  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_WIDTH                      1  /* OUT3L_MUTE */
+#define WM5100_OUT3L_VOL_MASK                   0x00FF  /* OUT3L_VOL - [7:0] */
+#define WM5100_OUT3L_VOL_SHIFT                       0  /* OUT3L_VOL - [7:0] */
+#define WM5100_OUT3L_VOL_WIDTH                       8  /* OUT3L_VOL - [7:0] */
+
+/*
+ * R1157 (0x485) - DAC Digital Volume 3R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT3R_MUTE                       0x0100  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_MASK                  0x0100  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_SHIFT                      8  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_WIDTH                      1  /* OUT3R_MUTE */
+#define WM5100_OUT3R_VOL_MASK                   0x00FF  /* OUT3R_VOL - [7:0] */
+#define WM5100_OUT3R_VOL_SHIFT                       0  /* OUT3R_VOL - [7:0] */
+#define WM5100_OUT3R_VOL_WIDTH                       8  /* OUT3R_VOL - [7:0] */
+
+/*
+ * R1158 (0x486) - DAC Digital Volume 4L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT4L_MUTE                       0x0100  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_MASK                  0x0100  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_SHIFT                      8  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_WIDTH                      1  /* OUT4L_MUTE */
+#define WM5100_OUT4L_VOL_MASK                   0x00FF  /* OUT4L_VOL - [7:0] */
+#define WM5100_OUT4L_VOL_SHIFT                       0  /* OUT4L_VOL - [7:0] */
+#define WM5100_OUT4L_VOL_WIDTH                       8  /* OUT4L_VOL - [7:0] */
+
+/*
+ * R1159 (0x487) - DAC Digital Volume 4R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT4R_MUTE                       0x0100  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_MASK                  0x0100  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_SHIFT                      8  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_WIDTH                      1  /* OUT4R_MUTE */
+#define WM5100_OUT4R_VOL_MASK                   0x00FF  /* OUT4R_VOL - [7:0] */
+#define WM5100_OUT4R_VOL_SHIFT                       0  /* OUT4R_VOL - [7:0] */
+#define WM5100_OUT4R_VOL_WIDTH                       8  /* OUT4R_VOL - [7:0] */
+
+/*
+ * R1160 (0x488) - DAC Digital Volume 5L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT5L_MUTE                       0x0100  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_MASK                  0x0100  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_SHIFT                      8  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_WIDTH                      1  /* OUT5L_MUTE */
+#define WM5100_OUT5L_VOL_MASK                   0x00FF  /* OUT5L_VOL - [7:0] */
+#define WM5100_OUT5L_VOL_SHIFT                       0  /* OUT5L_VOL - [7:0] */
+#define WM5100_OUT5L_VOL_WIDTH                       8  /* OUT5L_VOL - [7:0] */
+
+/*
+ * R1161 (0x489) - DAC Digital Volume 5R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT5R_MUTE                       0x0100  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_MASK                  0x0100  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_SHIFT                      8  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_WIDTH                      1  /* OUT5R_MUTE */
+#define WM5100_OUT5R_VOL_MASK                   0x00FF  /* OUT5R_VOL - [7:0] */
+#define WM5100_OUT5R_VOL_SHIFT                       0  /* OUT5R_VOL - [7:0] */
+#define WM5100_OUT5R_VOL_WIDTH                       8  /* OUT5R_VOL - [7:0] */
+
+/*
+ * R1162 (0x48A) - DAC Digital Volume 6L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT6L_MUTE                       0x0100  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_MASK                  0x0100  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_SHIFT                      8  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_WIDTH                      1  /* OUT6L_MUTE */
+#define WM5100_OUT6L_VOL_MASK                   0x00FF  /* OUT6L_VOL - [7:0] */
+#define WM5100_OUT6L_VOL_SHIFT                       0  /* OUT6L_VOL - [7:0] */
+#define WM5100_OUT6L_VOL_WIDTH                       8  /* OUT6L_VOL - [7:0] */
+
+/*
+ * R1163 (0x48B) - DAC Digital Volume 6R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT6R_MUTE                       0x0100  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_MASK                  0x0100  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_SHIFT                      8  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_WIDTH                      1  /* OUT6R_MUTE */
+#define WM5100_OUT6R_VOL_MASK                   0x00FF  /* OUT6R_VOL - [7:0] */
+#define WM5100_OUT6R_VOL_SHIFT                       0  /* OUT6R_VOL - [7:0] */
+#define WM5100_OUT6R_VOL_WIDTH                       8  /* OUT6R_VOL - [7:0] */
+
+/*
+ * R1216 (0x4C0) - PDM SPK1 CTRL 1
+ */
+#define WM5100_SPK1R_MUTE                       0x2000  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_MASK                  0x2000  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_SHIFT                     13  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_WIDTH                      1  /* SPK1R_MUTE */
+#define WM5100_SPK1L_MUTE                       0x1000  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_MASK                  0x1000  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_SHIFT                     12  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_WIDTH                      1  /* SPK1L_MUTE */
+#define WM5100_SPK1_MUTE_ENDIAN                 0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_MASK            0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_SHIFT                8  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_WIDTH                1  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_SEQ1_MASK              0x00FF  /* SPK1_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK1_MUTE_SEQ1_SHIFT                  0  /* SPK1_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK1_MUTE_SEQ1_WIDTH                  8  /* SPK1_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R1217 (0x4C1) - PDM SPK1 CTRL 2
+ */
+#define WM5100_SPK1_FMT                         0x0001  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_MASK                    0x0001  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_SHIFT                        0  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_WIDTH                        1  /* SPK1_FMT */
+
+/*
+ * R1218 (0x4C2) - PDM SPK2 CTRL 1
+ */
+#define WM5100_SPK2R_MUTE                       0x2000  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_MASK                  0x2000  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_SHIFT                     13  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_WIDTH                      1  /* SPK2R_MUTE */
+#define WM5100_SPK2L_MUTE                       0x1000  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_MASK                  0x1000  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_SHIFT                     12  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_WIDTH                      1  /* SPK2L_MUTE */
+#define WM5100_SPK2_MUTE_ENDIAN                 0x0100  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_MASK            0x0100  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_SHIFT                8  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_WIDTH                1  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_SEQ1_MASK              0x00FF  /* SPK2_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK2_MUTE_SEQ1_SHIFT                  0  /* SPK2_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK2_MUTE_SEQ1_WIDTH                  8  /* SPK2_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R1219 (0x4C3) - PDM SPK2 CTRL 2
+ */
+#define WM5100_SPK2_FMT                         0x0001  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_MASK                    0x0001  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_SHIFT                        0  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_WIDTH                        1  /* SPK2_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM5100_AIF1_BCLK_INV                    0x0080  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_MASK               0x0080  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_SHIFT                   7  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_WIDTH                   1  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_FRC                    0x0040  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_MASK               0x0040  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_SHIFT                   6  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_WIDTH                   1  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_MSTR                   0x0020  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_MASK              0x0020  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_SHIFT                  5  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_WIDTH                  1  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_FREQ_MASK              0x001F  /* AIF1_BCLK_FREQ - [4:0] */
+#define WM5100_AIF1_BCLK_FREQ_SHIFT                  0  /* AIF1_BCLK_FREQ - [4:0] */
+#define WM5100_AIF1_BCLK_FREQ_WIDTH                  5  /* AIF1_BCLK_FREQ - [4:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM5100_AIF1TX_DAT_TRI                   0x0020  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_MASK              0x0020  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_SHIFT                  5  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_WIDTH                  1  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_LRCLK_SRC                 0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_MASK            0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_SHIFT                3  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_WIDTH                1  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_INV                 0x0004  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_MASK            0x0004  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_SHIFT                2  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_WIDTH                1  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_FRC                 0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_MASK            0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_SHIFT                1  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_WIDTH                1  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_MSTR                0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_MASK           0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_SHIFT               0  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_WIDTH               1  /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM5100_AIF1RX_LRCLK_INV                 0x0004  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_MASK            0x0004  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_SHIFT                2  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_WIDTH                1  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_FRC                 0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_MASK            0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_SHIFT                1  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_WIDTH                1  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_MSTR                0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_MASK           0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_SHIFT               0  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_WIDTH               1  /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM5100_AIF1_TRI                         0x0040  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_MASK                    0x0040  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_SHIFT                        6  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_WIDTH                        1  /* AIF1_TRI */
+#define WM5100_AIF1_RATE_MASK                   0x0003  /* AIF1_RATE - [1:0] */
+#define WM5100_AIF1_RATE_SHIFT                       0  /* AIF1_RATE - [1:0] */
+#define WM5100_AIF1_RATE_WIDTH                       2  /* AIF1_RATE - [1:0] */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM5100_AIF1_FMT_MASK                    0x0007  /* AIF1_FMT - [2:0] */
+#define WM5100_AIF1_FMT_SHIFT                        0  /* AIF1_FMT - [2:0] */
+#define WM5100_AIF1_FMT_WIDTH                        3  /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM5100_AIF1TX_BCPF_MASK                 0x1FFF  /* AIF1TX_BCPF - [12:0] */
+#define WM5100_AIF1TX_BCPF_SHIFT                     0  /* AIF1TX_BCPF - [12:0] */
+#define WM5100_AIF1TX_BCPF_WIDTH                    13  /* AIF1TX_BCPF - [12:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM5100_AIF1RX_BCPF_MASK                 0x1FFF  /* AIF1RX_BCPF - [12:0] */
+#define WM5100_AIF1RX_BCPF_SHIFT                     0  /* AIF1RX_BCPF - [12:0] */
+#define WM5100_AIF1RX_BCPF_WIDTH                    13  /* AIF1RX_BCPF - [12:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM5100_AIF1TX_WL_MASK                   0x3F00  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_WL_SHIFT                       8  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_WL_WIDTH                       6  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_SLOT_LEN_MASK             0x00FF  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1TX_SLOT_LEN_SHIFT                 0  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1TX_SLOT_LEN_WIDTH                 8  /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM5100_AIF1RX_WL_MASK                   0x3F00  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_WL_SHIFT                       8  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_WL_WIDTH                       6  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_SLOT_LEN_MASK             0x00FF  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1RX_SLOT_LEN_SHIFT                 0  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1RX_SLOT_LEN_WIDTH                 8  /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM5100_AIF1TX1_SLOT_MASK                0x003F  /* AIF1TX1_SLOT - [5:0] */
+#define WM5100_AIF1TX1_SLOT_SHIFT                    0  /* AIF1TX1_SLOT - [5:0] */
+#define WM5100_AIF1TX1_SLOT_WIDTH                    6  /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM5100_AIF1TX2_SLOT_MASK                0x003F  /* AIF1TX2_SLOT - [5:0] */
+#define WM5100_AIF1TX2_SLOT_SHIFT                    0  /* AIF1TX2_SLOT - [5:0] */
+#define WM5100_AIF1TX2_SLOT_WIDTH                    6  /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM5100_AIF1TX3_SLOT_MASK                0x003F  /* AIF1TX3_SLOT - [5:0] */
+#define WM5100_AIF1TX3_SLOT_SHIFT                    0  /* AIF1TX3_SLOT - [5:0] */
+#define WM5100_AIF1TX3_SLOT_WIDTH                    6  /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM5100_AIF1TX4_SLOT_MASK                0x003F  /* AIF1TX4_SLOT - [5:0] */
+#define WM5100_AIF1TX4_SLOT_SHIFT                    0  /* AIF1TX4_SLOT - [5:0] */
+#define WM5100_AIF1TX4_SLOT_WIDTH                    6  /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM5100_AIF1TX5_SLOT_MASK                0x003F  /* AIF1TX5_SLOT - [5:0] */
+#define WM5100_AIF1TX5_SLOT_SHIFT                    0  /* AIF1TX5_SLOT - [5:0] */
+#define WM5100_AIF1TX5_SLOT_WIDTH                    6  /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM5100_AIF1TX6_SLOT_MASK                0x003F  /* AIF1TX6_SLOT - [5:0] */
+#define WM5100_AIF1TX6_SLOT_SHIFT                    0  /* AIF1TX6_SLOT - [5:0] */
+#define WM5100_AIF1TX6_SLOT_WIDTH                    6  /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM5100_AIF1TX7_SLOT_MASK                0x003F  /* AIF1TX7_SLOT - [5:0] */
+#define WM5100_AIF1TX7_SLOT_SHIFT                    0  /* AIF1TX7_SLOT - [5:0] */
+#define WM5100_AIF1TX7_SLOT_WIDTH                    6  /* AIF1TX7_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM5100_AIF1TX8_SLOT_MASK                0x003F  /* AIF1TX8_SLOT - [5:0] */
+#define WM5100_AIF1TX8_SLOT_SHIFT                    0  /* AIF1TX8_SLOT - [5:0] */
+#define WM5100_AIF1TX8_SLOT_WIDTH                    6  /* AIF1TX8_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM5100_AIF1RX1_SLOT_MASK                0x003F  /* AIF1RX1_SLOT - [5:0] */
+#define WM5100_AIF1RX1_SLOT_SHIFT                    0  /* AIF1RX1_SLOT - [5:0] */
+#define WM5100_AIF1RX1_SLOT_WIDTH                    6  /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM5100_AIF1RX2_SLOT_MASK                0x003F  /* AIF1RX2_SLOT - [5:0] */
+#define WM5100_AIF1RX2_SLOT_SHIFT                    0  /* AIF1RX2_SLOT - [5:0] */
+#define WM5100_AIF1RX2_SLOT_WIDTH                    6  /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM5100_AIF1RX3_SLOT_MASK                0x003F  /* AIF1RX3_SLOT - [5:0] */
+#define WM5100_AIF1RX3_SLOT_SHIFT                    0  /* AIF1RX3_SLOT - [5:0] */
+#define WM5100_AIF1RX3_SLOT_WIDTH                    6  /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM5100_AIF1RX4_SLOT_MASK                0x003F  /* AIF1RX4_SLOT - [5:0] */
+#define WM5100_AIF1RX4_SLOT_SHIFT                    0  /* AIF1RX4_SLOT - [5:0] */
+#define WM5100_AIF1RX4_SLOT_WIDTH                    6  /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM5100_AIF1RX5_SLOT_MASK                0x003F  /* AIF1RX5_SLOT - [5:0] */
+#define WM5100_AIF1RX5_SLOT_SHIFT                    0  /* AIF1RX5_SLOT - [5:0] */
+#define WM5100_AIF1RX5_SLOT_WIDTH                    6  /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1302 (0x516) - Audio IF 1_23
+ */
+#define WM5100_AIF1RX6_SLOT_MASK                0x003F  /* AIF1RX6_SLOT - [5:0] */
+#define WM5100_AIF1RX6_SLOT_SHIFT                    0  /* AIF1RX6_SLOT - [5:0] */
+#define WM5100_AIF1RX6_SLOT_WIDTH                    6  /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1303 (0x517) - Audio IF 1_24
+ */
+#define WM5100_AIF1RX7_SLOT_MASK                0x003F  /* AIF1RX7_SLOT - [5:0] */
+#define WM5100_AIF1RX7_SLOT_SHIFT                    0  /* AIF1RX7_SLOT - [5:0] */
+#define WM5100_AIF1RX7_SLOT_WIDTH                    6  /* AIF1RX7_SLOT - [5:0] */
+
+/*
+ * R1304 (0x518) - Audio IF 1_25
+ */
+#define WM5100_AIF1RX8_SLOT_MASK                0x003F  /* AIF1RX8_SLOT - [5:0] */
+#define WM5100_AIF1RX8_SLOT_SHIFT                    0  /* AIF1RX8_SLOT - [5:0] */
+#define WM5100_AIF1RX8_SLOT_WIDTH                    6  /* AIF1RX8_SLOT - [5:0] */
+
+/*
+ * R1305 (0x519) - Audio IF 1_26
+ */
+#define WM5100_AIF1TX8_ENA                      0x0080  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_MASK                 0x0080  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_SHIFT                     7  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_WIDTH                     1  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX7_ENA                      0x0040  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_MASK                 0x0040  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_SHIFT                     6  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_WIDTH                     1  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX6_ENA                      0x0020  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_MASK                 0x0020  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_SHIFT                     5  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_WIDTH                     1  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX5_ENA                      0x0010  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_MASK                 0x0010  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_SHIFT                     4  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_WIDTH                     1  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX4_ENA                      0x0008  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_MASK                 0x0008  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_SHIFT                     3  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_WIDTH                     1  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX3_ENA                      0x0004  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_MASK                 0x0004  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_SHIFT                     2  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_WIDTH                     1  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX2_ENA                      0x0002  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_MASK                 0x0002  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_SHIFT                     1  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_WIDTH                     1  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX1_ENA                      0x0001  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_MASK                 0x0001  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_SHIFT                     0  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_WIDTH                     1  /* AIF1TX1_ENA */
+
+/*
+ * R1306 (0x51A) - Audio IF 1_27
+ */
+#define WM5100_AIF1RX8_ENA                      0x0080  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_MASK                 0x0080  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_SHIFT                     7  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_WIDTH                     1  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX7_ENA                      0x0040  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_MASK                 0x0040  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_SHIFT                     6  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_WIDTH                     1  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX6_ENA                      0x0020  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_MASK                 0x0020  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_SHIFT                     5  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_WIDTH                     1  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX5_ENA                      0x0010  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_MASK                 0x0010  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_SHIFT                     4  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_WIDTH                     1  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX4_ENA                      0x0008  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_MASK                 0x0008  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_SHIFT                     3  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_WIDTH                     1  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX3_ENA                      0x0004  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_MASK                 0x0004  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_SHIFT                     2  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_WIDTH                     1  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX2_ENA                      0x0002  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_MASK                 0x0002  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_SHIFT                     1  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_WIDTH                     1  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX1_ENA                      0x0001  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_MASK                 0x0001  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_SHIFT                     0  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_WIDTH                     1  /* AIF1RX1_ENA */
+
+/*
+ * R1344 (0x540) - Audio IF 2_1
+ */
+#define WM5100_AIF2_BCLK_INV                    0x0080  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_MASK               0x0080  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_SHIFT                   7  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_WIDTH                   1  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_FRC                    0x0040  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_MASK               0x0040  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_SHIFT                   6  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_WIDTH                   1  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_MSTR                   0x0020  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_MASK              0x0020  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_SHIFT                  5  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_WIDTH                  1  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_FREQ_MASK              0x001F  /* AIF2_BCLK_FREQ - [4:0] */
+#define WM5100_AIF2_BCLK_FREQ_SHIFT                  0  /* AIF2_BCLK_FREQ - [4:0] */
+#define WM5100_AIF2_BCLK_FREQ_WIDTH                  5  /* AIF2_BCLK_FREQ - [4:0] */
+
+/*
+ * R1345 (0x541) - Audio IF 2_2
+ */
+#define WM5100_AIF2TX_DAT_TRI                   0x0020  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_MASK              0x0020  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_SHIFT                  5  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_WIDTH                  1  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_LRCLK_SRC                 0x0008  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_MASK            0x0008  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_SHIFT                3  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_WIDTH                1  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_INV                 0x0004  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_MASK            0x0004  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_SHIFT                2  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_WIDTH                1  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_FRC                 0x0002  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_MASK            0x0002  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_SHIFT                1  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_WIDTH                1  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_MSTR                0x0001  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_MASK           0x0001  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_SHIFT               0  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_WIDTH               1  /* AIF2TX_LRCLK_MSTR */
+
+/*
+ * R1346 (0x542) - Audio IF 2_3
+ */
+#define WM5100_AIF2RX_LRCLK_INV                 0x0004  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_MASK            0x0004  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_SHIFT                2  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_WIDTH                1  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_FRC                 0x0002  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_MASK            0x0002  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_SHIFT                1  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_WIDTH                1  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_MSTR                0x0001  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_MASK           0x0001  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_SHIFT               0  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_WIDTH               1  /* AIF2RX_LRCLK_MSTR */
+
+/*
+ * R1347 (0x543) - Audio IF 2_4
+ */
+#define WM5100_AIF2_TRI                         0x0040  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_MASK                    0x0040  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_SHIFT                        6  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_WIDTH                        1  /* AIF2_TRI */
+#define WM5100_AIF2_RATE_MASK                   0x0003  /* AIF2_RATE - [1:0] */
+#define WM5100_AIF2_RATE_SHIFT                       0  /* AIF2_RATE - [1:0] */
+#define WM5100_AIF2_RATE_WIDTH                       2  /* AIF2_RATE - [1:0] */
+
+/*
+ * R1348 (0x544) - Audio IF 2_5
+ */
+#define WM5100_AIF2_FMT_MASK                    0x0007  /* AIF2_FMT - [2:0] */
+#define WM5100_AIF2_FMT_SHIFT                        0  /* AIF2_FMT - [2:0] */
+#define WM5100_AIF2_FMT_WIDTH                        3  /* AIF2_FMT - [2:0] */
+
+/*
+ * R1349 (0x545) - Audio IF 2_6
+ */
+#define WM5100_AIF2TX_BCPF_MASK                 0x1FFF  /* AIF2TX_BCPF - [12:0] */
+#define WM5100_AIF2TX_BCPF_SHIFT                     0  /* AIF2TX_BCPF - [12:0] */
+#define WM5100_AIF2TX_BCPF_WIDTH                    13  /* AIF2TX_BCPF - [12:0] */
+
+/*
+ * R1350 (0x546) - Audio IF 2_7
+ */
+#define WM5100_AIF2RX_BCPF_MASK                 0x1FFF  /* AIF2RX_BCPF - [12:0] */
+#define WM5100_AIF2RX_BCPF_SHIFT                     0  /* AIF2RX_BCPF - [12:0] */
+#define WM5100_AIF2RX_BCPF_WIDTH                    13  /* AIF2RX_BCPF - [12:0] */
+
+/*
+ * R1351 (0x547) - Audio IF 2_8
+ */
+#define WM5100_AIF2TX_WL_MASK                   0x3F00  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_WL_SHIFT                       8  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_WL_WIDTH                       6  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_SLOT_LEN_MASK             0x00FF  /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2TX_SLOT_LEN_SHIFT                 0  /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2TX_SLOT_LEN_WIDTH                 8  /* AIF2TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1352 (0x548) - Audio IF 2_9
+ */
+#define WM5100_AIF2RX_WL_MASK                   0x3F00  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_WL_SHIFT                       8  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_WL_WIDTH                       6  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_SLOT_LEN_MASK             0x00FF  /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2RX_SLOT_LEN_SHIFT                 0  /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2RX_SLOT_LEN_WIDTH                 8  /* AIF2RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1353 (0x549) - Audio IF 2_10
+ */
+#define WM5100_AIF2TX1_SLOT_MASK                0x003F  /* AIF2TX1_SLOT - [5:0] */
+#define WM5100_AIF2TX1_SLOT_SHIFT                    0  /* AIF2TX1_SLOT - [5:0] */
+#define WM5100_AIF2TX1_SLOT_WIDTH                    6  /* AIF2TX1_SLOT - [5:0] */
+
+/*
+ * R1354 (0x54A) - Audio IF 2_11
+ */
+#define WM5100_AIF2TX2_SLOT_MASK                0x003F  /* AIF2TX2_SLOT - [5:0] */
+#define WM5100_AIF2TX2_SLOT_SHIFT                    0  /* AIF2TX2_SLOT - [5:0] */
+#define WM5100_AIF2TX2_SLOT_WIDTH                    6  /* AIF2TX2_SLOT - [5:0] */
+
+/*
+ * R1361 (0x551) - Audio IF 2_18
+ */
+#define WM5100_AIF2RX1_SLOT_MASK                0x003F  /* AIF2RX1_SLOT - [5:0] */
+#define WM5100_AIF2RX1_SLOT_SHIFT                    0  /* AIF2RX1_SLOT - [5:0] */
+#define WM5100_AIF2RX1_SLOT_WIDTH                    6  /* AIF2RX1_SLOT - [5:0] */
+
+/*
+ * R1362 (0x552) - Audio IF 2_19
+ */
+#define WM5100_AIF2RX2_SLOT_MASK                0x003F  /* AIF2RX2_SLOT - [5:0] */
+#define WM5100_AIF2RX2_SLOT_SHIFT                    0  /* AIF2RX2_SLOT - [5:0] */
+#define WM5100_AIF2RX2_SLOT_WIDTH                    6  /* AIF2RX2_SLOT - [5:0] */
+
+/*
+ * R1369 (0x559) - Audio IF 2_26
+ */
+#define WM5100_AIF2TX2_ENA                      0x0002  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_MASK                 0x0002  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_SHIFT                     1  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_WIDTH                     1  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX1_ENA                      0x0001  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_MASK                 0x0001  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_SHIFT                     0  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_WIDTH                     1  /* AIF2TX1_ENA */
+
+/*
+ * R1370 (0x55A) - Audio IF 2_27
+ */
+#define WM5100_AIF2RX2_ENA                      0x0002  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_MASK                 0x0002  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_SHIFT                     1  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_WIDTH                     1  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX1_ENA                      0x0001  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_MASK                 0x0001  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_SHIFT                     0  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_WIDTH                     1  /* AIF2RX1_ENA */
+
+/*
+ * R1408 (0x580) - Audio IF 3_1
+ */
+#define WM5100_AIF3_BCLK_INV                    0x0080  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_MASK               0x0080  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_SHIFT                   7  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_WIDTH                   1  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_FRC                    0x0040  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_MASK               0x0040  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_SHIFT                   6  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_WIDTH                   1  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_MSTR                   0x0020  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_MASK              0x0020  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_SHIFT                  5  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_WIDTH                  1  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_FREQ_MASK              0x001F  /* AIF3_BCLK_FREQ - [4:0] */
+#define WM5100_AIF3_BCLK_FREQ_SHIFT                  0  /* AIF3_BCLK_FREQ - [4:0] */
+#define WM5100_AIF3_BCLK_FREQ_WIDTH                  5  /* AIF3_BCLK_FREQ - [4:0] */
+
+/*
+ * R1409 (0x581) - Audio IF 3_2
+ */
+#define WM5100_AIF3TX_DAT_TRI                   0x0020  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_MASK              0x0020  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_SHIFT                  5  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_WIDTH                  1  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_LRCLK_SRC                 0x0008  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_MASK            0x0008  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_SHIFT                3  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_WIDTH                1  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_INV                 0x0004  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_MASK            0x0004  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_SHIFT                2  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_WIDTH                1  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_FRC                 0x0002  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_MASK            0x0002  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_SHIFT                1  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_WIDTH                1  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_MSTR                0x0001  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_MASK           0x0001  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_SHIFT               0  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_WIDTH               1  /* AIF3TX_LRCLK_MSTR */
+
+/*
+ * R1410 (0x582) - Audio IF 3_3
+ */
+#define WM5100_AIF3RX_LRCLK_INV                 0x0004  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_MASK            0x0004  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_SHIFT                2  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_WIDTH                1  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_FRC                 0x0002  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_MASK            0x0002  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_SHIFT                1  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_WIDTH                1  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_MSTR                0x0001  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_MASK           0x0001  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_SHIFT               0  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_WIDTH               1  /* AIF3RX_LRCLK_MSTR */
+
+/*
+ * R1411 (0x583) - Audio IF 3_4
+ */
+#define WM5100_AIF3_TRI                         0x0040  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_MASK                    0x0040  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_SHIFT                        6  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_WIDTH                        1  /* AIF3_TRI */
+#define WM5100_AIF3_RATE_MASK                   0x0003  /* AIF3_RATE - [1:0] */
+#define WM5100_AIF3_RATE_SHIFT                       0  /* AIF3_RATE - [1:0] */
+#define WM5100_AIF3_RATE_WIDTH                       2  /* AIF3_RATE - [1:0] */
+
+/*
+ * R1412 (0x584) - Audio IF 3_5
+ */
+#define WM5100_AIF3_FMT_MASK                    0x0007  /* AIF3_FMT - [2:0] */
+#define WM5100_AIF3_FMT_SHIFT                        0  /* AIF3_FMT - [2:0] */
+#define WM5100_AIF3_FMT_WIDTH                        3  /* AIF3_FMT - [2:0] */
+
+/*
+ * R1413 (0x585) - Audio IF 3_6
+ */
+#define WM5100_AIF3TX_BCPF_MASK                 0x1FFF  /* AIF3TX_BCPF - [12:0] */
+#define WM5100_AIF3TX_BCPF_SHIFT                     0  /* AIF3TX_BCPF - [12:0] */
+#define WM5100_AIF3TX_BCPF_WIDTH                    13  /* AIF3TX_BCPF - [12:0] */
+
+/*
+ * R1414 (0x586) - Audio IF 3_7
+ */
+#define WM5100_AIF3RX_BCPF_MASK                 0x1FFF  /* AIF3RX_BCPF - [12:0] */
+#define WM5100_AIF3RX_BCPF_SHIFT                     0  /* AIF3RX_BCPF - [12:0] */
+#define WM5100_AIF3RX_BCPF_WIDTH                    13  /* AIF3RX_BCPF - [12:0] */
+
+/*
+ * R1415 (0x587) - Audio IF 3_8
+ */
+#define WM5100_AIF3TX_WL_MASK                   0x3F00  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_WL_SHIFT                       8  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_WL_WIDTH                       6  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_SLOT_LEN_MASK             0x00FF  /* AIF3TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3TX_SLOT_LEN_SHIFT                 0  /* AIF3TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3TX_SLOT_LEN_WIDTH                 8  /* AIF3TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1416 (0x588) - Audio IF 3_9
+ */
+#define WM5100_AIF3RX_WL_MASK                   0x3F00  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_WL_SHIFT                       8  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_WL_WIDTH                       6  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_SLOT_LEN_MASK             0x00FF  /* AIF3RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3RX_SLOT_LEN_SHIFT                 0  /* AIF3RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3RX_SLOT_LEN_WIDTH                 8  /* AIF3RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1417 (0x589) - Audio IF 3_10
+ */
+#define WM5100_AIF3TX1_SLOT_MASK                0x003F  /* AIF3TX1_SLOT - [5:0] */
+#define WM5100_AIF3TX1_SLOT_SHIFT                    0  /* AIF3TX1_SLOT - [5:0] */
+#define WM5100_AIF3TX1_SLOT_WIDTH                    6  /* AIF3TX1_SLOT - [5:0] */
+
+/*
+ * R1418 (0x58A) - Audio IF 3_11
+ */
+#define WM5100_AIF3TX2_SLOT_MASK                0x003F  /* AIF3TX2_SLOT - [5:0] */
+#define WM5100_AIF3TX2_SLOT_SHIFT                    0  /* AIF3TX2_SLOT - [5:0] */
+#define WM5100_AIF3TX2_SLOT_WIDTH                    6  /* AIF3TX2_SLOT - [5:0] */
+
+/*
+ * R1425 (0x591) - Audio IF 3_18
+ */
+#define WM5100_AIF3RX1_SLOT_MASK                0x003F  /* AIF3RX1_SLOT - [5:0] */
+#define WM5100_AIF3RX1_SLOT_SHIFT                    0  /* AIF3RX1_SLOT - [5:0] */
+#define WM5100_AIF3RX1_SLOT_WIDTH                    6  /* AIF3RX1_SLOT - [5:0] */
+
+/*
+ * R1426 (0x592) - Audio IF 3_19
+ */
+#define WM5100_AIF3RX2_SLOT_MASK                0x003F  /* AIF3RX2_SLOT - [5:0] */
+#define WM5100_AIF3RX2_SLOT_SHIFT                    0  /* AIF3RX2_SLOT - [5:0] */
+#define WM5100_AIF3RX2_SLOT_WIDTH                    6  /* AIF3RX2_SLOT - [5:0] */
+
+/*
+ * R1433 (0x599) - Audio IF 3_26
+ */
+#define WM5100_AIF3TX2_ENA                      0x0002  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_MASK                 0x0002  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_SHIFT                     1  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_WIDTH                     1  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX1_ENA                      0x0001  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_MASK                 0x0001  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_SHIFT                     0  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_WIDTH                     1  /* AIF3TX1_ENA */
+
+/*
+ * R1434 (0x59A) - Audio IF 3_27
+ */
+#define WM5100_AIF3RX2_ENA                      0x0002  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_MASK                 0x0002  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_SHIFT                     1  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_WIDTH                     1  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX1_ENA                      0x0001  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_MASK                 0x0001  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_SHIFT                     0  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_WIDTH                     1  /* AIF3RX1_ENA */
+
+#define WM5100_MIXER_VOL_MASK                0x00FE  /* MIXER_VOL - [7:1] */
+#define WM5100_MIXER_VOL_SHIFT                    1  /* MIXER_VOL - [7:1] */
+#define WM5100_MIXER_VOL_WIDTH                    7  /* MIXER_VOL - [7:1] */
+
+/*
+ * R3072 (0xC00) - GPIO CTRL 1
+ */
+#define WM5100_GP1_DIR                          0x8000  /* GP1_DIR */
+#define WM5100_GP1_DIR_MASK                     0x8000  /* GP1_DIR */
+#define WM5100_GP1_DIR_SHIFT                        15  /* GP1_DIR */
+#define WM5100_GP1_DIR_WIDTH                         1  /* GP1_DIR */
+#define WM5100_GP1_PU                           0x4000  /* GP1_PU */
+#define WM5100_GP1_PU_MASK                      0x4000  /* GP1_PU */
+#define WM5100_GP1_PU_SHIFT                         14  /* GP1_PU */
+#define WM5100_GP1_PU_WIDTH                          1  /* GP1_PU */
+#define WM5100_GP1_PD                           0x2000  /* GP1_PD */
+#define WM5100_GP1_PD_MASK                      0x2000  /* GP1_PD */
+#define WM5100_GP1_PD_SHIFT                         13  /* GP1_PD */
+#define WM5100_GP1_PD_WIDTH                          1  /* GP1_PD */
+#define WM5100_GP1_POL                          0x0400  /* GP1_POL */
+#define WM5100_GP1_POL_MASK                     0x0400  /* GP1_POL */
+#define WM5100_GP1_POL_SHIFT                        10  /* GP1_POL */
+#define WM5100_GP1_POL_WIDTH                         1  /* GP1_POL */
+#define WM5100_GP1_OP_CFG                       0x0200  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_MASK                  0x0200  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_SHIFT                      9  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_WIDTH                      1  /* GP1_OP_CFG */
+#define WM5100_GP1_DB                           0x0100  /* GP1_DB */
+#define WM5100_GP1_DB_MASK                      0x0100  /* GP1_DB */
+#define WM5100_GP1_DB_SHIFT                          8  /* GP1_DB */
+#define WM5100_GP1_DB_WIDTH                          1  /* GP1_DB */
+#define WM5100_GP1_LVL                          0x0040  /* GP1_LVL */
+#define WM5100_GP1_LVL_MASK                     0x0040  /* GP1_LVL */
+#define WM5100_GP1_LVL_SHIFT                         6  /* GP1_LVL */
+#define WM5100_GP1_LVL_WIDTH                         1  /* GP1_LVL */
+#define WM5100_GP1_FN_MASK                      0x003F  /* GP1_FN - [5:0] */
+#define WM5100_GP1_FN_SHIFT                          0  /* GP1_FN - [5:0] */
+#define WM5100_GP1_FN_WIDTH                          6  /* GP1_FN - [5:0] */
+
+/*
+ * R3073 (0xC01) - GPIO CTRL 2
+ */
+#define WM5100_GP2_DIR                          0x8000  /* GP2_DIR */
+#define WM5100_GP2_DIR_MASK                     0x8000  /* GP2_DIR */
+#define WM5100_GP2_DIR_SHIFT                        15  /* GP2_DIR */
+#define WM5100_GP2_DIR_WIDTH                         1  /* GP2_DIR */
+#define WM5100_GP2_PU                           0x4000  /* GP2_PU */
+#define WM5100_GP2_PU_MASK                      0x4000  /* GP2_PU */
+#define WM5100_GP2_PU_SHIFT                         14  /* GP2_PU */
+#define WM5100_GP2_PU_WIDTH                          1  /* GP2_PU */
+#define WM5100_GP2_PD                           0x2000  /* GP2_PD */
+#define WM5100_GP2_PD_MASK                      0x2000  /* GP2_PD */
+#define WM5100_GP2_PD_SHIFT                         13  /* GP2_PD */
+#define WM5100_GP2_PD_WIDTH                          1  /* GP2_PD */
+#define WM5100_GP2_POL                          0x0400  /* GP2_POL */
+#define WM5100_GP2_POL_MASK                     0x0400  /* GP2_POL */
+#define WM5100_GP2_POL_SHIFT                        10  /* GP2_POL */
+#define WM5100_GP2_POL_WIDTH                         1  /* GP2_POL */
+#define WM5100_GP2_OP_CFG                       0x0200  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_MASK                  0x0200  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_SHIFT                      9  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_WIDTH                      1  /* GP2_OP_CFG */
+#define WM5100_GP2_DB                           0x0100  /* GP2_DB */
+#define WM5100_GP2_DB_MASK                      0x0100  /* GP2_DB */
+#define WM5100_GP2_DB_SHIFT                          8  /* GP2_DB */
+#define WM5100_GP2_DB_WIDTH                          1  /* GP2_DB */
+#define WM5100_GP2_LVL                          0x0040  /* GP2_LVL */
+#define WM5100_GP2_LVL_MASK                     0x0040  /* GP2_LVL */
+#define WM5100_GP2_LVL_SHIFT                         6  /* GP2_LVL */
+#define WM5100_GP2_LVL_WIDTH                         1  /* GP2_LVL */
+#define WM5100_GP2_FN_MASK                      0x003F  /* GP2_FN - [5:0] */
+#define WM5100_GP2_FN_SHIFT                          0  /* GP2_FN - [5:0] */
+#define WM5100_GP2_FN_WIDTH                          6  /* GP2_FN - [5:0] */
+
+/*
+ * R3074 (0xC02) - GPIO CTRL 3
+ */
+#define WM5100_GP3_DIR                          0x8000  /* GP3_DIR */
+#define WM5100_GP3_DIR_MASK                     0x8000  /* GP3_DIR */
+#define WM5100_GP3_DIR_SHIFT                        15  /* GP3_DIR */
+#define WM5100_GP3_DIR_WIDTH                         1  /* GP3_DIR */
+#define WM5100_GP3_PU                           0x4000  /* GP3_PU */
+#define WM5100_GP3_PU_MASK                      0x4000  /* GP3_PU */
+#define WM5100_GP3_PU_SHIFT                         14  /* GP3_PU */
+#define WM5100_GP3_PU_WIDTH                          1  /* GP3_PU */
+#define WM5100_GP3_PD                           0x2000  /* GP3_PD */
+#define WM5100_GP3_PD_MASK                      0x2000  /* GP3_PD */
+#define WM5100_GP3_PD_SHIFT                         13  /* GP3_PD */
+#define WM5100_GP3_PD_WIDTH                          1  /* GP3_PD */
+#define WM5100_GP3_POL                          0x0400  /* GP3_POL */
+#define WM5100_GP3_POL_MASK                     0x0400  /* GP3_POL */
+#define WM5100_GP3_POL_SHIFT                        10  /* GP3_POL */
+#define WM5100_GP3_POL_WIDTH                         1  /* GP3_POL */
+#define WM5100_GP3_OP_CFG                       0x0200  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_MASK                  0x0200  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_SHIFT                      9  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_WIDTH                      1  /* GP3_OP_CFG */
+#define WM5100_GP3_DB                           0x0100  /* GP3_DB */
+#define WM5100_GP3_DB_MASK                      0x0100  /* GP3_DB */
+#define WM5100_GP3_DB_SHIFT                          8  /* GP3_DB */
+#define WM5100_GP3_DB_WIDTH                          1  /* GP3_DB */
+#define WM5100_GP3_LVL                          0x0040  /* GP3_LVL */
+#define WM5100_GP3_LVL_MASK                     0x0040  /* GP3_LVL */
+#define WM5100_GP3_LVL_SHIFT                         6  /* GP3_LVL */
+#define WM5100_GP3_LVL_WIDTH                         1  /* GP3_LVL */
+#define WM5100_GP3_FN_MASK                      0x003F  /* GP3_FN - [5:0] */
+#define WM5100_GP3_FN_SHIFT                          0  /* GP3_FN - [5:0] */
+#define WM5100_GP3_FN_WIDTH                          6  /* GP3_FN - [5:0] */
+
+/*
+ * R3075 (0xC03) - GPIO CTRL 4
+ */
+#define WM5100_GP4_DIR                          0x8000  /* GP4_DIR */
+#define WM5100_GP4_DIR_MASK                     0x8000  /* GP4_DIR */
+#define WM5100_GP4_DIR_SHIFT                        15  /* GP4_DIR */
+#define WM5100_GP4_DIR_WIDTH                         1  /* GP4_DIR */
+#define WM5100_GP4_PU                           0x4000  /* GP4_PU */
+#define WM5100_GP4_PU_MASK                      0x4000  /* GP4_PU */
+#define WM5100_GP4_PU_SHIFT                         14  /* GP4_PU */
+#define WM5100_GP4_PU_WIDTH                          1  /* GP4_PU */
+#define WM5100_GP4_PD                           0x2000  /* GP4_PD */
+#define WM5100_GP4_PD_MASK                      0x2000  /* GP4_PD */
+#define WM5100_GP4_PD_SHIFT                         13  /* GP4_PD */
+#define WM5100_GP4_PD_WIDTH                          1  /* GP4_PD */
+#define WM5100_GP4_POL                          0x0400  /* GP4_POL */
+#define WM5100_GP4_POL_MASK                     0x0400  /* GP4_POL */
+#define WM5100_GP4_POL_SHIFT                        10  /* GP4_POL */
+#define WM5100_GP4_POL_WIDTH                         1  /* GP4_POL */
+#define WM5100_GP4_OP_CFG                       0x0200  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_MASK                  0x0200  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_SHIFT                      9  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_WIDTH                      1  /* GP4_OP_CFG */
+#define WM5100_GP4_DB                           0x0100  /* GP4_DB */
+#define WM5100_GP4_DB_MASK                      0x0100  /* GP4_DB */
+#define WM5100_GP4_DB_SHIFT                          8  /* GP4_DB */
+#define WM5100_GP4_DB_WIDTH                          1  /* GP4_DB */
+#define WM5100_GP4_LVL                          0x0040  /* GP4_LVL */
+#define WM5100_GP4_LVL_MASK                     0x0040  /* GP4_LVL */
+#define WM5100_GP4_LVL_SHIFT                         6  /* GP4_LVL */
+#define WM5100_GP4_LVL_WIDTH                         1  /* GP4_LVL */
+#define WM5100_GP4_FN_MASK                      0x003F  /* GP4_FN - [5:0] */
+#define WM5100_GP4_FN_SHIFT                          0  /* GP4_FN - [5:0] */
+#define WM5100_GP4_FN_WIDTH                          6  /* GP4_FN - [5:0] */
+
+/*
+ * R3076 (0xC04) - GPIO CTRL 5
+ */
+#define WM5100_GP5_DIR                          0x8000  /* GP5_DIR */
+#define WM5100_GP5_DIR_MASK                     0x8000  /* GP5_DIR */
+#define WM5100_GP5_DIR_SHIFT                        15  /* GP5_DIR */
+#define WM5100_GP5_DIR_WIDTH                         1  /* GP5_DIR */
+#define WM5100_GP5_PU                           0x4000  /* GP5_PU */
+#define WM5100_GP5_PU_MASK                      0x4000  /* GP5_PU */
+#define WM5100_GP5_PU_SHIFT                         14  /* GP5_PU */
+#define WM5100_GP5_PU_WIDTH                          1  /* GP5_PU */
+#define WM5100_GP5_PD                           0x2000  /* GP5_PD */
+#define WM5100_GP5_PD_MASK                      0x2000  /* GP5_PD */
+#define WM5100_GP5_PD_SHIFT                         13  /* GP5_PD */
+#define WM5100_GP5_PD_WIDTH                          1  /* GP5_PD */
+#define WM5100_GP5_POL                          0x0400  /* GP5_POL */
+#define WM5100_GP5_POL_MASK                     0x0400  /* GP5_POL */
+#define WM5100_GP5_POL_SHIFT                        10  /* GP5_POL */
+#define WM5100_GP5_POL_WIDTH                         1  /* GP5_POL */
+#define WM5100_GP5_OP_CFG                       0x0200  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_MASK                  0x0200  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_SHIFT                      9  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_WIDTH                      1  /* GP5_OP_CFG */
+#define WM5100_GP5_DB                           0x0100  /* GP5_DB */
+#define WM5100_GP5_DB_MASK                      0x0100  /* GP5_DB */
+#define WM5100_GP5_DB_SHIFT                          8  /* GP5_DB */
+#define WM5100_GP5_DB_WIDTH                          1  /* GP5_DB */
+#define WM5100_GP5_LVL                          0x0040  /* GP5_LVL */
+#define WM5100_GP5_LVL_MASK                     0x0040  /* GP5_LVL */
+#define WM5100_GP5_LVL_SHIFT                         6  /* GP5_LVL */
+#define WM5100_GP5_LVL_WIDTH                         1  /* GP5_LVL */
+#define WM5100_GP5_FN_MASK                      0x003F  /* GP5_FN - [5:0] */
+#define WM5100_GP5_FN_SHIFT                          0  /* GP5_FN - [5:0] */
+#define WM5100_GP5_FN_WIDTH                          6  /* GP5_FN - [5:0] */
+
+/*
+ * R3077 (0xC05) - GPIO CTRL 6
+ */
+#define WM5100_GP6_DIR                          0x8000  /* GP6_DIR */
+#define WM5100_GP6_DIR_MASK                     0x8000  /* GP6_DIR */
+#define WM5100_GP6_DIR_SHIFT                        15  /* GP6_DIR */
+#define WM5100_GP6_DIR_WIDTH                         1  /* GP6_DIR */
+#define WM5100_GP6_PU                           0x4000  /* GP6_PU */
+#define WM5100_GP6_PU_MASK                      0x4000  /* GP6_PU */
+#define WM5100_GP6_PU_SHIFT                         14  /* GP6_PU */
+#define WM5100_GP6_PU_WIDTH                          1  /* GP6_PU */
+#define WM5100_GP6_PD                           0x2000  /* GP6_PD */
+#define WM5100_GP6_PD_MASK                      0x2000  /* GP6_PD */
+#define WM5100_GP6_PD_SHIFT                         13  /* GP6_PD */
+#define WM5100_GP6_PD_WIDTH                          1  /* GP6_PD */
+#define WM5100_GP6_POL                          0x0400  /* GP6_POL */
+#define WM5100_GP6_POL_MASK                     0x0400  /* GP6_POL */
+#define WM5100_GP6_POL_SHIFT                        10  /* GP6_POL */
+#define WM5100_GP6_POL_WIDTH                         1  /* GP6_POL */
+#define WM5100_GP6_OP_CFG                       0x0200  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_MASK                  0x0200  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_SHIFT                      9  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_WIDTH                      1  /* GP6_OP_CFG */
+#define WM5100_GP6_DB                           0x0100  /* GP6_DB */
+#define WM5100_GP6_DB_MASK                      0x0100  /* GP6_DB */
+#define WM5100_GP6_DB_SHIFT                          8  /* GP6_DB */
+#define WM5100_GP6_DB_WIDTH                          1  /* GP6_DB */
+#define WM5100_GP6_LVL                          0x0040  /* GP6_LVL */
+#define WM5100_GP6_LVL_MASK                     0x0040  /* GP6_LVL */
+#define WM5100_GP6_LVL_SHIFT                         6  /* GP6_LVL */
+#define WM5100_GP6_LVL_WIDTH                         1  /* GP6_LVL */
+#define WM5100_GP6_FN_MASK                      0x003F  /* GP6_FN - [5:0] */
+#define WM5100_GP6_FN_SHIFT                          0  /* GP6_FN - [5:0] */
+#define WM5100_GP6_FN_WIDTH                          6  /* GP6_FN - [5:0] */
+
+/*
+ * R3107 (0xC23) - Misc Pad Ctrl 1
+ */
+#define WM5100_LDO1ENA_PD                       0x8000  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_MASK                  0x8000  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_SHIFT                     15  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_WIDTH                      1  /* LDO1ENA_PD */
+#define WM5100_MCLK2_PD                         0x2000  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_MASK                    0x2000  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_SHIFT                       13  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_WIDTH                        1  /* MCLK2_PD */
+#define WM5100_MCLK1_PD                         0x1000  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_MASK                    0x1000  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_SHIFT                       12  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_WIDTH                        1  /* MCLK1_PD */
+#define WM5100_RESET_PU                         0x0002  /* RESET_PU */
+#define WM5100_RESET_PU_MASK                    0x0002  /* RESET_PU */
+#define WM5100_RESET_PU_SHIFT                        1  /* RESET_PU */
+#define WM5100_RESET_PU_WIDTH                        1  /* RESET_PU */
+#define WM5100_ADDR_PD                          0x0001  /* ADDR_PD */
+#define WM5100_ADDR_PD_MASK                     0x0001  /* ADDR_PD */
+#define WM5100_ADDR_PD_SHIFT                         0  /* ADDR_PD */
+#define WM5100_ADDR_PD_WIDTH                         1  /* ADDR_PD */
+
+/*
+ * R3108 (0xC24) - Misc Pad Ctrl 2
+ */
+#define WM5100_DMICDAT4_PD                      0x0008  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_MASK                 0x0008  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_SHIFT                     3  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_WIDTH                     1  /* DMICDAT4_PD */
+#define WM5100_DMICDAT3_PD                      0x0004  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_MASK                 0x0004  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_SHIFT                     2  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_WIDTH                     1  /* DMICDAT3_PD */
+#define WM5100_DMICDAT2_PD                      0x0002  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_MASK                 0x0002  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_SHIFT                     1  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_WIDTH                     1  /* DMICDAT2_PD */
+#define WM5100_DMICDAT1_PD                      0x0001  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_MASK                 0x0001  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_SHIFT                     0  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_WIDTH                     1  /* DMICDAT1_PD */
+
+/*
+ * R3109 (0xC25) - Misc Pad Ctrl 3
+ */
+#define WM5100_AIF1RXLRCLK_PU                   0x0020  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_MASK              0x0020  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_SHIFT                  5  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_WIDTH                  1  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PD                   0x0010  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_MASK              0x0010  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_SHIFT                  4  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_WIDTH                  1  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1BCLK_PU                      0x0008  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_MASK                 0x0008  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_SHIFT                     3  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_WIDTH                     1  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PD                      0x0004  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_MASK                 0x0004  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_SHIFT                     2  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_WIDTH                     1  /* AIF1BCLK_PD */
+#define WM5100_AIF1RXDAT_PU                     0x0002  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_MASK                0x0002  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_SHIFT                    1  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_WIDTH                    1  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PD                     0x0001  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_MASK                0x0001  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_SHIFT                    0  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_WIDTH                    1  /* AIF1RXDAT_PD */
+
+/*
+ * R3110 (0xC26) - Misc Pad Ctrl 4
+ */
+#define WM5100_AIF2RXLRCLK_PU                   0x0020  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_MASK              0x0020  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_SHIFT                  5  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_WIDTH                  1  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PD                   0x0010  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_MASK              0x0010  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_SHIFT                  4  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_WIDTH                  1  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2BCLK_PU                      0x0008  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_MASK                 0x0008  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_SHIFT                     3  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_WIDTH                     1  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PD                      0x0004  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_MASK                 0x0004  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_SHIFT                     2  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_WIDTH                     1  /* AIF2BCLK_PD */
+#define WM5100_AIF2RXDAT_PU                     0x0002  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_MASK                0x0002  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_SHIFT                    1  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_WIDTH                    1  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PD                     0x0001  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_MASK                0x0001  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_SHIFT                    0  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_WIDTH                    1  /* AIF2RXDAT_PD */
+
+/*
+ * R3111 (0xC27) - Misc Pad Ctrl 5
+ */
+#define WM5100_AIF3RXLRCLK_PU                   0x0020  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_MASK              0x0020  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_SHIFT                  5  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_WIDTH                  1  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PD                   0x0010  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_MASK              0x0010  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_SHIFT                  4  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_WIDTH                  1  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3BCLK_PU                      0x0008  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_MASK                 0x0008  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_SHIFT                     3  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_WIDTH                     1  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PD                      0x0004  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_MASK                 0x0004  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_SHIFT                     2  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_WIDTH                     1  /* AIF3BCLK_PD */
+#define WM5100_AIF3RXDAT_PU                     0x0002  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_MASK                0x0002  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_SHIFT                    1  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_WIDTH                    1  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PD                     0x0001  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_MASK                0x0001  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_SHIFT                    0  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_WIDTH                    1  /* AIF3RXDAT_PD */
+
+/*
+ * R3112 (0xC28) - Misc GPIO 1
+ */
+#define WM5100_OPCLK_SEL_MASK                   0x0003  /* OPCLK_SEL - [1:0] */
+#define WM5100_OPCLK_SEL_SHIFT                       0  /* OPCLK_SEL - [1:0] */
+#define WM5100_OPCLK_SEL_WIDTH                       2  /* OPCLK_SEL - [1:0] */
+
+/*
+ * R3328 (0xD00) - Interrupt Status 1
+ */
+#define WM5100_GP6_EINT                         0x0020  /* GP6_EINT */
+#define WM5100_GP6_EINT_MASK                    0x0020  /* GP6_EINT */
+#define WM5100_GP6_EINT_SHIFT                        5  /* GP6_EINT */
+#define WM5100_GP6_EINT_WIDTH                        1  /* GP6_EINT */
+#define WM5100_GP5_EINT                         0x0010  /* GP5_EINT */
+#define WM5100_GP5_EINT_MASK                    0x0010  /* GP5_EINT */
+#define WM5100_GP5_EINT_SHIFT                        4  /* GP5_EINT */
+#define WM5100_GP5_EINT_WIDTH                        1  /* GP5_EINT */
+#define WM5100_GP4_EINT                         0x0008  /* GP4_EINT */
+#define WM5100_GP4_EINT_MASK                    0x0008  /* GP4_EINT */
+#define WM5100_GP4_EINT_SHIFT                        3  /* GP4_EINT */
+#define WM5100_GP4_EINT_WIDTH                        1  /* GP4_EINT */
+#define WM5100_GP3_EINT                         0x0004  /* GP3_EINT */
+#define WM5100_GP3_EINT_MASK                    0x0004  /* GP3_EINT */
+#define WM5100_GP3_EINT_SHIFT                        2  /* GP3_EINT */
+#define WM5100_GP3_EINT_WIDTH                        1  /* GP3_EINT */
+#define WM5100_GP2_EINT                         0x0002  /* GP2_EINT */
+#define WM5100_GP2_EINT_MASK                    0x0002  /* GP2_EINT */
+#define WM5100_GP2_EINT_SHIFT                        1  /* GP2_EINT */
+#define WM5100_GP2_EINT_WIDTH                        1  /* GP2_EINT */
+#define WM5100_GP1_EINT                         0x0001  /* GP1_EINT */
+#define WM5100_GP1_EINT_MASK                    0x0001  /* GP1_EINT */
+#define WM5100_GP1_EINT_SHIFT                        0  /* GP1_EINT */
+#define WM5100_GP1_EINT_WIDTH                        1  /* GP1_EINT */
+
+/*
+ * R3329 (0xD01) - Interrupt Status 2
+ */
+#define WM5100_DSP_IRQ6_EINT                    0x0020  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_MASK               0x0020  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_SHIFT                   5  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_WIDTH                   1  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ5_EINT                    0x0010  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_MASK               0x0010  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_SHIFT                   4  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_WIDTH                   1  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ4_EINT                    0x0008  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_MASK               0x0008  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_SHIFT                   3  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_WIDTH                   1  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ3_EINT                    0x0004  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_MASK               0x0004  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_SHIFT                   2  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_WIDTH                   1  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ2_EINT                    0x0002  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_MASK               0x0002  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_SHIFT                   1  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_WIDTH                   1  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ1_EINT                    0x0001  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_MASK               0x0001  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_SHIFT                   0  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_WIDTH                   1  /* DSP_IRQ1_EINT */
+
+/*
+ * R3330 (0xD02) - Interrupt Status 3
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT           0x8000  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_MASK      0x8000  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_SHIFT         15  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_WIDTH          1  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT                0x4000  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_MASK           0x4000  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_SHIFT              14  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_WIDTH               1  /* SPK_SHUTDOWN_EINT */
+#define WM5100_HPDET_EINT                       0x2000  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_MASK                  0x2000  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_SHIFT                     13  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_WIDTH                      1  /* HPDET_EINT */
+#define WM5100_ACCDET_EINT                      0x1000  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_MASK                 0x1000  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_SHIFT                    12  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_WIDTH                     1  /* ACCDET_EINT */
+#define WM5100_DRC_SIG_DET_EINT                 0x0200  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_MASK            0x0200  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_SHIFT                9  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_WIDTH                1  /* DRC_SIG_DET_EINT */
+#define WM5100_ASRC2_LOCK_EINT                  0x0100  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_MASK             0x0100  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_SHIFT                 8  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_WIDTH                 1  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT                  0x0080  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_MASK             0x0080  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_SHIFT                 7  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_WIDTH                 1  /* ASRC1_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT                   0x0008  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_MASK              0x0008  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_SHIFT                  3  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_WIDTH                  1  /* FLL2_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT                   0x0004  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_MASK              0x0004  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_SHIFT                  2  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_WIDTH                  1  /* FLL1_LOCK_EINT */
+#define WM5100_CLKGEN_ERR_EINT                  0x0002  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_MASK             0x0002  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_SHIFT                 1  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_WIDTH                 1  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT            0x0001  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_MASK       0x0001  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_SHIFT           0  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_WIDTH           1  /* CLKGEN_ERR_ASYNC_EINT */
+
+/*
+ * R3331 (0xD03) - Interrupt Status 4
+ */
+#define WM5100_AIF3_ERR_EINT                    0x2000  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_MASK               0x2000  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_SHIFT                  13  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_WIDTH                   1  /* AIF3_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT                    0x1000  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_MASK               0x1000  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_SHIFT                  12  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_WIDTH                   1  /* AIF2_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT                    0x0800  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_MASK               0x0800  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_SHIFT                  11  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_WIDTH                   1  /* AIF1_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT                  0x0400  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_MASK             0x0400  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_SHIFT                10  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_WIDTH                 1  /* CTRLIF_ERR_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT          0x0200  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_MASK     0x0200  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_SHIFT         9  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_WIDTH         1  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT          0x0100  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_MASK     0x0100  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_SHIFT         8  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_WIDTH         1  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT             0x0080  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_MASK        0x0080  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_SHIFT            7  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_WIDTH            1  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT           0x0040  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_MASK      0x0040  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_SHIFT          6  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_WIDTH          1  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT           0x0020  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_MASK      0x0020  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_SHIFT          5  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_WIDTH          1  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT           0x0010  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_MASK      0x0010  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_SHIFT          4  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_WIDTH          1  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT           0x0008  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_MASK      0x0008  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_SHIFT          3  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_WIDTH          1  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT            0x0004  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_MASK       0x0004  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_SHIFT           2  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_WIDTH           1  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT            0x0002  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_MASK       0x0002  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_SHIFT           1  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_WIDTH           1  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT          0x0001  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_MASK     0x0001  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_SHIFT         0  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_WIDTH         1  /* MIXER_UNDERCLOCKED_EINT */
+
+/*
+ * R3332 (0xD04) - Interrupt Raw Status 2
+ */
+#define WM5100_DSP_IRQ6_STS                     0x0020  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_MASK                0x0020  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_SHIFT                    5  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_WIDTH                    1  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ5_STS                     0x0010  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_MASK                0x0010  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_SHIFT                    4  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_WIDTH                    1  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ4_STS                     0x0008  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_MASK                0x0008  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_SHIFT                    3  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_WIDTH                    1  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ3_STS                     0x0004  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_MASK                0x0004  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_SHIFT                    2  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_WIDTH                    1  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ2_STS                     0x0002  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_MASK                0x0002  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_SHIFT                    1  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_WIDTH                    1  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ1_STS                     0x0001  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_MASK                0x0001  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_SHIFT                    0  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_WIDTH                    1  /* DSP_IRQ1_STS */
+
+/*
+ * R3333 (0xD05) - Interrupt Raw Status 3
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_STS            0x8000  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_MASK       0x8000  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_SHIFT          15  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_WIDTH           1  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_STS                 0x4000  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_MASK            0x4000  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_SHIFT               14  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_WIDTH                1  /* SPK_SHUTDOWN_STS */
+#define WM5100_HPDET_STS                        0x2000  /* HPDET_STS */
+#define WM5100_HPDET_STS_MASK                   0x2000  /* HPDET_STS */
+#define WM5100_HPDET_STS_SHIFT                      13  /* HPDET_STS */
+#define WM5100_HPDET_STS_WIDTH                       1  /* HPDET_STS */
+#define WM5100_DRC_SID_DET_STS                  0x0200  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_MASK             0x0200  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_SHIFT                 9  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_WIDTH                 1  /* DRC_SID_DET_STS */
+#define WM5100_ASRC2_LOCK_STS                   0x0100  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_MASK              0x0100  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_SHIFT                  8  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_WIDTH                  1  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS                   0x0080  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_MASK              0x0080  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_SHIFT                  7  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_WIDTH                  1  /* ASRC1_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS                    0x0008  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_MASK               0x0008  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_SHIFT                   3  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_WIDTH                   1  /* FLL2_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS                    0x0004  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_MASK               0x0004  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_SHIFT                   2  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_WIDTH                   1  /* FLL1_LOCK_STS */
+#define WM5100_CLKGEN_ERR_STS                   0x0002  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_MASK              0x0002  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_SHIFT                  1  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_WIDTH                  1  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS             0x0001  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_MASK        0x0001  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_SHIFT            0  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_WIDTH            1  /* CLKGEN_ERR_ASYNC_STS */
+
+/*
+ * R3334 (0xD06) - Interrupt Raw Status 4
+ */
+#define WM5100_AIF3_ERR_STS                     0x2000  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_MASK                0x2000  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_SHIFT                   13  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_WIDTH                    1  /* AIF3_ERR_STS */
+#define WM5100_AIF2_ERR_STS                     0x1000  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_MASK                0x1000  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_SHIFT                   12  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_WIDTH                    1  /* AIF2_ERR_STS */
+#define WM5100_AIF1_ERR_STS                     0x0800  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_MASK                0x0800  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_SHIFT                   11  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_WIDTH                    1  /* AIF1_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS                   0x0400  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_MASK              0x0400  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_SHIFT                 10  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_WIDTH                  1  /* CTRLIF_ERR_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS           0x0200  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_MASK      0x0200  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_SHIFT          9  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_WIDTH          1  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS           0x0100  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_MASK      0x0100  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_SHIFT          8  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_WIDTH          1  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS              0x0080  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_MASK         0x0080  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_SHIFT             7  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_WIDTH             1  /* FX_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS            0x0040  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_MASK       0x0040  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_SHIFT           6  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_WIDTH           1  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS            0x0020  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_MASK       0x0020  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_SHIFT           5  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_WIDTH           1  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS            0x0010  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_MASK       0x0010  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_SHIFT           4  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_WIDTH           1  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS            0x0008  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_MASK       0x0008  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_SHIFT           3  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_WIDTH           1  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS             0x0004  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_MASK        0x0004  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_SHIFT            2  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_WIDTH            1  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS             0x0002  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_MASK        0x0002  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_SHIFT            1  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_WIDTH            1  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS           0x0001  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_MASK      0x0001  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_SHIFT          0  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_WIDTH          1  /* MIXER_UNDERCLOCKED_STS */
+
+/*
+ * R3335 (0xD07) - Interrupt Status 1 Mask
+ */
+#define WM5100_IM_GP6_EINT                      0x0020  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_MASK                 0x0020  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_SHIFT                     5  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_WIDTH                     1  /* IM_GP6_EINT */
+#define WM5100_IM_GP5_EINT                      0x0010  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_MASK                 0x0010  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_SHIFT                     4  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_WIDTH                     1  /* IM_GP5_EINT */
+#define WM5100_IM_GP4_EINT                      0x0008  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_MASK                 0x0008  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_SHIFT                     3  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_WIDTH                     1  /* IM_GP4_EINT */
+#define WM5100_IM_GP3_EINT                      0x0004  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_MASK                 0x0004  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_SHIFT                     2  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_WIDTH                     1  /* IM_GP3_EINT */
+#define WM5100_IM_GP2_EINT                      0x0002  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_MASK                 0x0002  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_SHIFT                     1  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_WIDTH                     1  /* IM_GP2_EINT */
+#define WM5100_IM_GP1_EINT                      0x0001  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_MASK                 0x0001  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_SHIFT                     0  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_WIDTH                     1  /* IM_GP1_EINT */
+
+/*
+ * R3336 (0xD08) - Interrupt Status 2 Mask
+ */
+#define WM5100_IM_DSP_IRQ6_EINT                 0x0020  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_MASK            0x0020  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_SHIFT                5  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_WIDTH                1  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT                 0x0010  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_MASK            0x0010  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_SHIFT                4  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_WIDTH                1  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT                 0x0008  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_MASK            0x0008  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_SHIFT                3  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_WIDTH                1  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT                 0x0004  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_MASK            0x0004  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_SHIFT                2  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_WIDTH                1  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT                 0x0002  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_MASK            0x0002  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_SHIFT                1  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_WIDTH                1  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT                 0x0001  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_MASK            0x0001  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_SHIFT                0  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_WIDTH                1  /* IM_DSP_IRQ1_EINT */
+
+/*
+ * R3337 (0xD09) - Interrupt Status 3 Mask
+ */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT        0x8000  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_MASK   0x8000  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_SHIFT      15  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_WIDTH       1  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT             0x4000  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_MASK        0x4000  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_SHIFT           14  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_WIDTH            1  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_HPDET_EINT                    0x2000  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_MASK               0x2000  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_SHIFT                  13  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_WIDTH                   1  /* IM_HPDET_EINT */
+#define WM5100_IM_ACCDET_EINT                   0x1000  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_MASK              0x1000  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_SHIFT                 12  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_WIDTH                  1  /* IM_ACCDET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT              0x0200  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_MASK         0x0200  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_SHIFT             9  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_WIDTH             1  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT               0x0100  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_MASK          0x0100  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_SHIFT              8  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_WIDTH              1  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT               0x0080  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_MASK          0x0080  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_SHIFT              7  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_WIDTH              1  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT                0x0008  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_MASK           0x0008  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_SHIFT               3  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_WIDTH               1  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT                0x0004  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_MASK           0x0004  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_SHIFT               2  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_WIDTH               1  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT               0x0002  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_MASK          0x0002  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_SHIFT              1  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_WIDTH              1  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT         0x0001  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_MASK    0x0001  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_SHIFT        0  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_WIDTH        1  /* IM_CLKGEN_ERR_ASYNC_EINT */
+
+/*
+ * R3338 (0xD0A) - Interrupt Status 4 Mask
+ */
+#define WM5100_IM_AIF3_ERR_EINT                 0x2000  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_MASK            0x2000  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_SHIFT               13  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_WIDTH                1  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT                 0x1000  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_MASK            0x1000  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_SHIFT               12  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_WIDTH                1  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT                 0x0800  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_MASK            0x0800  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_SHIFT               11  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_WIDTH                1  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT               0x0400  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_MASK          0x0400  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_SHIFT             10  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_WIDTH              1  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT       0x0200  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_MASK  0x0200  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_SHIFT      9  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_WIDTH      1  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT       0x0100  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_MASK  0x0100  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_SHIFT      8  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_WIDTH      1  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT          0x0080  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_MASK     0x0080  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_SHIFT         7  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_WIDTH         1  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT        0x0040  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_MASK   0x0040  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_SHIFT       6  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT        0x0020  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_MASK   0x0020  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_SHIFT       5  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT        0x0010  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_MASK   0x0010  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_SHIFT       4  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT        0x0008  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_MASK   0x0008  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_SHIFT       3  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_WIDTH       1  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT         0x0004  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_MASK    0x0004  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_SHIFT        2  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_WIDTH        1  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT         0x0002  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_MASK    0x0002  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_SHIFT        1  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_WIDTH        1  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT       0x0001  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_MASK  0x0001  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_SHIFT      0  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_WIDTH      1  /* IM_MIXER_UNDERCLOCKED_EINT */
+
+/*
+ * R3359 (0xD1F) - Interrupt Control
+ */
+#define WM5100_IM_IRQ                           0x0001  /* IM_IRQ */
+#define WM5100_IM_IRQ_MASK                      0x0001  /* IM_IRQ */
+#define WM5100_IM_IRQ_SHIFT                          0  /* IM_IRQ */
+#define WM5100_IM_IRQ_WIDTH                          1  /* IM_IRQ */
+
+/*
+ * R3360 (0xD20) - IRQ Debounce 1
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_DB             0x0200  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_MASK        0x0200  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_SHIFT            9  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_WIDTH            1  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_DB                  0x0100  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_MASK             0x0100  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_SHIFT                 8  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_WIDTH                 1  /* SPK_SHUTDOWN_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB                 0x0008  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_MASK            0x0008  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_SHIFT                3  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_WIDTH                1  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB                 0x0004  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_MASK            0x0004  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_SHIFT                2  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_WIDTH                1  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB                0x0002  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_MASK           0x0002  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_SHIFT               1  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_WIDTH               1  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB          0x0001  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_MASK     0x0001  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_SHIFT         0  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_WIDTH         1  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+
+/*
+ * R3361 (0xD21) - IRQ Debounce 2
+ */
+#define WM5100_AIF_ERR_DB                       0x0001  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_MASK                  0x0001  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_SHIFT                      0  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_WIDTH                      1  /* AIF_ERR_DB */
+
+/*
+ * R3584 (0xE00) - FX_Ctrl
+ */
+#define WM5100_FX_STS_MASK                      0xFFC0  /* FX_STS - [15:6] */
+#define WM5100_FX_STS_SHIFT                          6  /* FX_STS - [15:6] */
+#define WM5100_FX_STS_WIDTH                         10  /* FX_STS - [15:6] */
+#define WM5100_FX_RATE_MASK                     0x0003  /* FX_RATE - [1:0] */
+#define WM5100_FX_RATE_SHIFT                         0  /* FX_RATE - [1:0] */
+#define WM5100_FX_RATE_WIDTH                         2  /* FX_RATE - [1:0] */
+
+/*
+ * R3600 (0xE10) - EQ1_1
+ */
+#define WM5100_EQ1_B1_GAIN_MASK                 0xF800  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B1_GAIN_SHIFT                    11  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B1_GAIN_WIDTH                     5  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B2_GAIN_MASK                 0x07C0  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B2_GAIN_SHIFT                     6  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B2_GAIN_WIDTH                     5  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B3_GAIN_MASK                 0x003E  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_B3_GAIN_SHIFT                     1  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_B3_GAIN_WIDTH                     5  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_ENA                          0x0001  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_MASK                     0x0001  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_SHIFT                         0  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_WIDTH                         1  /* EQ1_ENA */
+
+/*
+ * R3601 (0xE11) - EQ1_2
+ */
+#define WM5100_EQ1_B4_GAIN_MASK                 0xF800  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B4_GAIN_SHIFT                    11  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B4_GAIN_WIDTH                     5  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B5_GAIN_MASK                 0x07C0  /* EQ1_B5_GAIN - [10:6] */
+#define WM5100_EQ1_B5_GAIN_SHIFT                     6  /* EQ1_B5_GAIN - [10:6] */
+#define WM5100_EQ1_B5_GAIN_WIDTH                     5  /* EQ1_B5_GAIN - [10:6] */
+
+/*
+ * R3602 (0xE12) - EQ1_3
+ */
+#define WM5100_EQ1_B1_A_MASK                    0xFFFF  /* EQ1_B1_A - [15:0] */
+#define WM5100_EQ1_B1_A_SHIFT                        0  /* EQ1_B1_A - [15:0] */
+#define WM5100_EQ1_B1_A_WIDTH                       16  /* EQ1_B1_A - [15:0] */
+
+/*
+ * R3603 (0xE13) - EQ1_4
+ */
+#define WM5100_EQ1_B1_B_MASK                    0xFFFF  /* EQ1_B1_B - [15:0] */
+#define WM5100_EQ1_B1_B_SHIFT                        0  /* EQ1_B1_B - [15:0] */
+#define WM5100_EQ1_B1_B_WIDTH                       16  /* EQ1_B1_B - [15:0] */
+
+/*
+ * R3604 (0xE14) - EQ1_5
+ */
+#define WM5100_EQ1_B1_PG_MASK                   0xFFFF  /* EQ1_B1_PG - [15:0] */
+#define WM5100_EQ1_B1_PG_SHIFT                       0  /* EQ1_B1_PG - [15:0] */
+#define WM5100_EQ1_B1_PG_WIDTH                      16  /* EQ1_B1_PG - [15:0] */
+
+/*
+ * R3605 (0xE15) - EQ1_6
+ */
+#define WM5100_EQ1_B2_A_MASK                    0xFFFF  /* EQ1_B2_A - [15:0] */
+#define WM5100_EQ1_B2_A_SHIFT                        0  /* EQ1_B2_A - [15:0] */
+#define WM5100_EQ1_B2_A_WIDTH                       16  /* EQ1_B2_A - [15:0] */
+
+/*
+ * R3606 (0xE16) - EQ1_7
+ */
+#define WM5100_EQ1_B2_B_MASK                    0xFFFF  /* EQ1_B2_B - [15:0] */
+#define WM5100_EQ1_B2_B_SHIFT                        0  /* EQ1_B2_B - [15:0] */
+#define WM5100_EQ1_B2_B_WIDTH                       16  /* EQ1_B2_B - [15:0] */
+
+/*
+ * R3607 (0xE17) - EQ1_8
+ */
+#define WM5100_EQ1_B2_C_MASK                    0xFFFF  /* EQ1_B2_C - [15:0] */
+#define WM5100_EQ1_B2_C_SHIFT                        0  /* EQ1_B2_C - [15:0] */
+#define WM5100_EQ1_B2_C_WIDTH                       16  /* EQ1_B2_C - [15:0] */
+
+/*
+ * R3608 (0xE18) - EQ1_9
+ */
+#define WM5100_EQ1_B2_PG_MASK                   0xFFFF  /* EQ1_B2_PG - [15:0] */
+#define WM5100_EQ1_B2_PG_SHIFT                       0  /* EQ1_B2_PG - [15:0] */
+#define WM5100_EQ1_B2_PG_WIDTH                      16  /* EQ1_B2_PG - [15:0] */
+
+/*
+ * R3609 (0xE19) - EQ1_10
+ */
+#define WM5100_EQ1_B3_A_MASK                    0xFFFF  /* EQ1_B3_A - [15:0] */
+#define WM5100_EQ1_B3_A_SHIFT                        0  /* EQ1_B3_A - [15:0] */
+#define WM5100_EQ1_B3_A_WIDTH                       16  /* EQ1_B3_A - [15:0] */
+
+/*
+ * R3610 (0xE1A) - EQ1_11
+ */
+#define WM5100_EQ1_B3_B_MASK                    0xFFFF  /* EQ1_B3_B - [15:0] */
+#define WM5100_EQ1_B3_B_SHIFT                        0  /* EQ1_B3_B - [15:0] */
+#define WM5100_EQ1_B3_B_WIDTH                       16  /* EQ1_B3_B - [15:0] */
+
+/*
+ * R3611 (0xE1B) - EQ1_12
+ */
+#define WM5100_EQ1_B3_C_MASK                    0xFFFF  /* EQ1_B3_C - [15:0] */
+#define WM5100_EQ1_B3_C_SHIFT                        0  /* EQ1_B3_C - [15:0] */
+#define WM5100_EQ1_B3_C_WIDTH                       16  /* EQ1_B3_C - [15:0] */
+
+/*
+ * R3612 (0xE1C) - EQ1_13
+ */
+#define WM5100_EQ1_B3_PG_MASK                   0xFFFF  /* EQ1_B3_PG - [15:0] */
+#define WM5100_EQ1_B3_PG_SHIFT                       0  /* EQ1_B3_PG - [15:0] */
+#define WM5100_EQ1_B3_PG_WIDTH                      16  /* EQ1_B3_PG - [15:0] */
+
+/*
+ * R3613 (0xE1D) - EQ1_14
+ */
+#define WM5100_EQ1_B4_A_MASK                    0xFFFF  /* EQ1_B4_A - [15:0] */
+#define WM5100_EQ1_B4_A_SHIFT                        0  /* EQ1_B4_A - [15:0] */
+#define WM5100_EQ1_B4_A_WIDTH                       16  /* EQ1_B4_A - [15:0] */
+
+/*
+ * R3614 (0xE1E) - EQ1_15
+ */
+#define WM5100_EQ1_B4_B_MASK                    0xFFFF  /* EQ1_B4_B - [15:0] */
+#define WM5100_EQ1_B4_B_SHIFT                        0  /* EQ1_B4_B - [15:0] */
+#define WM5100_EQ1_B4_B_WIDTH                       16  /* EQ1_B4_B - [15:0] */
+
+/*
+ * R3615 (0xE1F) - EQ1_16
+ */
+#define WM5100_EQ1_B4_C_MASK                    0xFFFF  /* EQ1_B4_C - [15:0] */
+#define WM5100_EQ1_B4_C_SHIFT                        0  /* EQ1_B4_C - [15:0] */
+#define WM5100_EQ1_B4_C_WIDTH                       16  /* EQ1_B4_C - [15:0] */
+
+/*
+ * R3616 (0xE20) - EQ1_17
+ */
+#define WM5100_EQ1_B4_PG_MASK                   0xFFFF  /* EQ1_B4_PG - [15:0] */
+#define WM5100_EQ1_B4_PG_SHIFT                       0  /* EQ1_B4_PG - [15:0] */
+#define WM5100_EQ1_B4_PG_WIDTH                      16  /* EQ1_B4_PG - [15:0] */
+
+/*
+ * R3617 (0xE21) - EQ1_18
+ */
+#define WM5100_EQ1_B5_A_MASK                    0xFFFF  /* EQ1_B5_A - [15:0] */
+#define WM5100_EQ1_B5_A_SHIFT                        0  /* EQ1_B5_A - [15:0] */
+#define WM5100_EQ1_B5_A_WIDTH                       16  /* EQ1_B5_A - [15:0] */
+
+/*
+ * R3618 (0xE22) - EQ1_19
+ */
+#define WM5100_EQ1_B5_B_MASK                    0xFFFF  /* EQ1_B5_B - [15:0] */
+#define WM5100_EQ1_B5_B_SHIFT                        0  /* EQ1_B5_B - [15:0] */
+#define WM5100_EQ1_B5_B_WIDTH                       16  /* EQ1_B5_B - [15:0] */
+
+/*
+ * R3619 (0xE23) - EQ1_20
+ */
+#define WM5100_EQ1_B5_PG_MASK                   0xFFFF  /* EQ1_B5_PG - [15:0] */
+#define WM5100_EQ1_B5_PG_SHIFT                       0  /* EQ1_B5_PG - [15:0] */
+#define WM5100_EQ1_B5_PG_WIDTH                      16  /* EQ1_B5_PG - [15:0] */
+
+/*
+ * R3622 (0xE26) - EQ2_1
+ */
+#define WM5100_EQ2_B1_GAIN_MASK                 0xF800  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B1_GAIN_SHIFT                    11  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B1_GAIN_WIDTH                     5  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B2_GAIN_MASK                 0x07C0  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B2_GAIN_SHIFT                     6  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B2_GAIN_WIDTH                     5  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B3_GAIN_MASK                 0x003E  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_B3_GAIN_SHIFT                     1  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_B3_GAIN_WIDTH                     5  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_ENA                          0x0001  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_MASK                     0x0001  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_SHIFT                         0  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_WIDTH                         1  /* EQ2_ENA */
+
+/*
+ * R3623 (0xE27) - EQ2_2
+ */
+#define WM5100_EQ2_B4_GAIN_MASK                 0xF800  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B4_GAIN_SHIFT                    11  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B4_GAIN_WIDTH                     5  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B5_GAIN_MASK                 0x07C0  /* EQ2_B5_GAIN - [10:6] */
+#define WM5100_EQ2_B5_GAIN_SHIFT                     6  /* EQ2_B5_GAIN - [10:6] */
+#define WM5100_EQ2_B5_GAIN_WIDTH                     5  /* EQ2_B5_GAIN - [10:6] */
+
+/*
+ * R3624 (0xE28) - EQ2_3
+ */
+#define WM5100_EQ2_B1_A_MASK                    0xFFFF  /* EQ2_B1_A - [15:0] */
+#define WM5100_EQ2_B1_A_SHIFT                        0  /* EQ2_B1_A - [15:0] */
+#define WM5100_EQ2_B1_A_WIDTH                       16  /* EQ2_B1_A - [15:0] */
+
+/*
+ * R3625 (0xE29) - EQ2_4
+ */
+#define WM5100_EQ2_B1_B_MASK                    0xFFFF  /* EQ2_B1_B - [15:0] */
+#define WM5100_EQ2_B1_B_SHIFT                        0  /* EQ2_B1_B - [15:0] */
+#define WM5100_EQ2_B1_B_WIDTH                       16  /* EQ2_B1_B - [15:0] */
+
+/*
+ * R3626 (0xE2A) - EQ2_5
+ */
+#define WM5100_EQ2_B1_PG_MASK                   0xFFFF  /* EQ2_B1_PG - [15:0] */
+#define WM5100_EQ2_B1_PG_SHIFT                       0  /* EQ2_B1_PG - [15:0] */
+#define WM5100_EQ2_B1_PG_WIDTH                      16  /* EQ2_B1_PG - [15:0] */
+
+/*
+ * R3627 (0xE2B) - EQ2_6
+ */
+#define WM5100_EQ2_B2_A_MASK                    0xFFFF  /* EQ2_B2_A - [15:0] */
+#define WM5100_EQ2_B2_A_SHIFT                        0  /* EQ2_B2_A - [15:0] */
+#define WM5100_EQ2_B2_A_WIDTH                       16  /* EQ2_B2_A - [15:0] */
+
+/*
+ * R3628 (0xE2C) - EQ2_7
+ */
+#define WM5100_EQ2_B2_B_MASK                    0xFFFF  /* EQ2_B2_B - [15:0] */
+#define WM5100_EQ2_B2_B_SHIFT                        0  /* EQ2_B2_B - [15:0] */
+#define WM5100_EQ2_B2_B_WIDTH                       16  /* EQ2_B2_B - [15:0] */
+
+/*
+ * R3629 (0xE2D) - EQ2_8
+ */
+#define WM5100_EQ2_B2_C_MASK                    0xFFFF  /* EQ2_B2_C - [15:0] */
+#define WM5100_EQ2_B2_C_SHIFT                        0  /* EQ2_B2_C - [15:0] */
+#define WM5100_EQ2_B2_C_WIDTH                       16  /* EQ2_B2_C - [15:0] */
+
+/*
+ * R3630 (0xE2E) - EQ2_9
+ */
+#define WM5100_EQ2_B2_PG_MASK                   0xFFFF  /* EQ2_B2_PG - [15:0] */
+#define WM5100_EQ2_B2_PG_SHIFT                       0  /* EQ2_B2_PG - [15:0] */
+#define WM5100_EQ2_B2_PG_WIDTH                      16  /* EQ2_B2_PG - [15:0] */
+
+/*
+ * R3631 (0xE2F) - EQ2_10
+ */
+#define WM5100_EQ2_B3_A_MASK                    0xFFFF  /* EQ2_B3_A - [15:0] */
+#define WM5100_EQ2_B3_A_SHIFT                        0  /* EQ2_B3_A - [15:0] */
+#define WM5100_EQ2_B3_A_WIDTH                       16  /* EQ2_B3_A - [15:0] */
+
+/*
+ * R3632 (0xE30) - EQ2_11
+ */
+#define WM5100_EQ2_B3_B_MASK                    0xFFFF  /* EQ2_B3_B - [15:0] */
+#define WM5100_EQ2_B3_B_SHIFT                        0  /* EQ2_B3_B - [15:0] */
+#define WM5100_EQ2_B3_B_WIDTH                       16  /* EQ2_B3_B - [15:0] */
+
+/*
+ * R3633 (0xE31) - EQ2_12
+ */
+#define WM5100_EQ2_B3_C_MASK                    0xFFFF  /* EQ2_B3_C - [15:0] */
+#define WM5100_EQ2_B3_C_SHIFT                        0  /* EQ2_B3_C - [15:0] */
+#define WM5100_EQ2_B3_C_WIDTH                       16  /* EQ2_B3_C - [15:0] */
+
+/*
+ * R3634 (0xE32) - EQ2_13
+ */
+#define WM5100_EQ2_B3_PG_MASK                   0xFFFF  /* EQ2_B3_PG - [15:0] */
+#define WM5100_EQ2_B3_PG_SHIFT                       0  /* EQ2_B3_PG - [15:0] */
+#define WM5100_EQ2_B3_PG_WIDTH                      16  /* EQ2_B3_PG - [15:0] */
+
+/*
+ * R3635 (0xE33) - EQ2_14
+ */
+#define WM5100_EQ2_B4_A_MASK                    0xFFFF  /* EQ2_B4_A - [15:0] */
+#define WM5100_EQ2_B4_A_SHIFT                        0  /* EQ2_B4_A - [15:0] */
+#define WM5100_EQ2_B4_A_WIDTH                       16  /* EQ2_B4_A - [15:0] */
+
+/*
+ * R3636 (0xE34) - EQ2_15
+ */
+#define WM5100_EQ2_B4_B_MASK                    0xFFFF  /* EQ2_B4_B - [15:0] */
+#define WM5100_EQ2_B4_B_SHIFT                        0  /* EQ2_B4_B - [15:0] */
+#define WM5100_EQ2_B4_B_WIDTH                       16  /* EQ2_B4_B - [15:0] */
+
+/*
+ * R3637 (0xE35) - EQ2_16
+ */
+#define WM5100_EQ2_B4_C_MASK                    0xFFFF  /* EQ2_B4_C - [15:0] */
+#define WM5100_EQ2_B4_C_SHIFT                        0  /* EQ2_B4_C - [15:0] */
+#define WM5100_EQ2_B4_C_WIDTH                       16  /* EQ2_B4_C - [15:0] */
+
+/*
+ * R3638 (0xE36) - EQ2_17
+ */
+#define WM5100_EQ2_B4_PG_MASK                   0xFFFF  /* EQ2_B4_PG - [15:0] */
+#define WM5100_EQ2_B4_PG_SHIFT                       0  /* EQ2_B4_PG - [15:0] */
+#define WM5100_EQ2_B4_PG_WIDTH                      16  /* EQ2_B4_PG - [15:0] */
+
+/*
+ * R3639 (0xE37) - EQ2_18
+ */
+#define WM5100_EQ2_B5_A_MASK                    0xFFFF  /* EQ2_B5_A - [15:0] */
+#define WM5100_EQ2_B5_A_SHIFT                        0  /* EQ2_B5_A - [15:0] */
+#define WM5100_EQ2_B5_A_WIDTH                       16  /* EQ2_B5_A - [15:0] */
+
+/*
+ * R3640 (0xE38) - EQ2_19
+ */
+#define WM5100_EQ2_B5_B_MASK                    0xFFFF  /* EQ2_B5_B - [15:0] */
+#define WM5100_EQ2_B5_B_SHIFT                        0  /* EQ2_B5_B - [15:0] */
+#define WM5100_EQ2_B5_B_WIDTH                       16  /* EQ2_B5_B - [15:0] */
+
+/*
+ * R3641 (0xE39) - EQ2_20
+ */
+#define WM5100_EQ2_B5_PG_MASK                   0xFFFF  /* EQ2_B5_PG - [15:0] */
+#define WM5100_EQ2_B5_PG_SHIFT                       0  /* EQ2_B5_PG - [15:0] */
+#define WM5100_EQ2_B5_PG_WIDTH                      16  /* EQ2_B5_PG - [15:0] */
+
+/*
+ * R3644 (0xE3C) - EQ3_1
+ */
+#define WM5100_EQ3_B1_GAIN_MASK                 0xF800  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B1_GAIN_SHIFT                    11  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B1_GAIN_WIDTH                     5  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B2_GAIN_MASK                 0x07C0  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B2_GAIN_SHIFT                     6  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B2_GAIN_WIDTH                     5  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B3_GAIN_MASK                 0x003E  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_B3_GAIN_SHIFT                     1  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_B3_GAIN_WIDTH                     5  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_ENA                          0x0001  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_MASK                     0x0001  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_SHIFT                         0  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_WIDTH                         1  /* EQ3_ENA */
+
+/*
+ * R3645 (0xE3D) - EQ3_2
+ */
+#define WM5100_EQ3_B4_GAIN_MASK                 0xF800  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B4_GAIN_SHIFT                    11  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B4_GAIN_WIDTH                     5  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B5_GAIN_MASK                 0x07C0  /* EQ3_B5_GAIN - [10:6] */
+#define WM5100_EQ3_B5_GAIN_SHIFT                     6  /* EQ3_B5_GAIN - [10:6] */
+#define WM5100_EQ3_B5_GAIN_WIDTH                     5  /* EQ3_B5_GAIN - [10:6] */
+
+/*
+ * R3646 (0xE3E) - EQ3_3
+ */
+#define WM5100_EQ3_B1_A_MASK                    0xFFFF  /* EQ3_B1_A - [15:0] */
+#define WM5100_EQ3_B1_A_SHIFT                        0  /* EQ3_B1_A - [15:0] */
+#define WM5100_EQ3_B1_A_WIDTH                       16  /* EQ3_B1_A - [15:0] */
+
+/*
+ * R3647 (0xE3F) - EQ3_4
+ */
+#define WM5100_EQ3_B1_B_MASK                    0xFFFF  /* EQ3_B1_B - [15:0] */
+#define WM5100_EQ3_B1_B_SHIFT                        0  /* EQ3_B1_B - [15:0] */
+#define WM5100_EQ3_B1_B_WIDTH                       16  /* EQ3_B1_B - [15:0] */
+
+/*
+ * R3648 (0xE40) - EQ3_5
+ */
+#define WM5100_EQ3_B1_PG_MASK                   0xFFFF  /* EQ3_B1_PG - [15:0] */
+#define WM5100_EQ3_B1_PG_SHIFT                       0  /* EQ3_B1_PG - [15:0] */
+#define WM5100_EQ3_B1_PG_WIDTH                      16  /* EQ3_B1_PG - [15:0] */
+
+/*
+ * R3649 (0xE41) - EQ3_6
+ */
+#define WM5100_EQ3_B2_A_MASK                    0xFFFF  /* EQ3_B2_A - [15:0] */
+#define WM5100_EQ3_B2_A_SHIFT                        0  /* EQ3_B2_A - [15:0] */
+#define WM5100_EQ3_B2_A_WIDTH                       16  /* EQ3_B2_A - [15:0] */
+
+/*
+ * R3650 (0xE42) - EQ3_7
+ */
+#define WM5100_EQ3_B2_B_MASK                    0xFFFF  /* EQ3_B2_B - [15:0] */
+#define WM5100_EQ3_B2_B_SHIFT                        0  /* EQ3_B2_B - [15:0] */
+#define WM5100_EQ3_B2_B_WIDTH                       16  /* EQ3_B2_B - [15:0] */
+
+/*
+ * R3651 (0xE43) - EQ3_8
+ */
+#define WM5100_EQ3_B2_C_MASK                    0xFFFF  /* EQ3_B2_C - [15:0] */
+#define WM5100_EQ3_B2_C_SHIFT                        0  /* EQ3_B2_C - [15:0] */
+#define WM5100_EQ3_B2_C_WIDTH                       16  /* EQ3_B2_C - [15:0] */
+
+/*
+ * R3652 (0xE44) - EQ3_9
+ */
+#define WM5100_EQ3_B2_PG_MASK                   0xFFFF  /* EQ3_B2_PG - [15:0] */
+#define WM5100_EQ3_B2_PG_SHIFT                       0  /* EQ3_B2_PG - [15:0] */
+#define WM5100_EQ3_B2_PG_WIDTH                      16  /* EQ3_B2_PG - [15:0] */
+
+/*
+ * R3653 (0xE45) - EQ3_10
+ */
+#define WM5100_EQ3_B3_A_MASK                    0xFFFF  /* EQ3_B3_A - [15:0] */
+#define WM5100_EQ3_B3_A_SHIFT                        0  /* EQ3_B3_A - [15:0] */
+#define WM5100_EQ3_B3_A_WIDTH                       16  /* EQ3_B3_A - [15:0] */
+
+/*
+ * R3654 (0xE46) - EQ3_11
+ */
+#define WM5100_EQ3_B3_B_MASK                    0xFFFF  /* EQ3_B3_B - [15:0] */
+#define WM5100_EQ3_B3_B_SHIFT                        0  /* EQ3_B3_B - [15:0] */
+#define WM5100_EQ3_B3_B_WIDTH                       16  /* EQ3_B3_B - [15:0] */
+
+/*
+ * R3655 (0xE47) - EQ3_12
+ */
+#define WM5100_EQ3_B3_C_MASK                    0xFFFF  /* EQ3_B3_C - [15:0] */
+#define WM5100_EQ3_B3_C_SHIFT                        0  /* EQ3_B3_C - [15:0] */
+#define WM5100_EQ3_B3_C_WIDTH                       16  /* EQ3_B3_C - [15:0] */
+
+/*
+ * R3656 (0xE48) - EQ3_13
+ */
+#define WM5100_EQ3_B3_PG_MASK                   0xFFFF  /* EQ3_B3_PG - [15:0] */
+#define WM5100_EQ3_B3_PG_SHIFT                       0  /* EQ3_B3_PG - [15:0] */
+#define WM5100_EQ3_B3_PG_WIDTH                      16  /* EQ3_B3_PG - [15:0] */
+
+/*
+ * R3657 (0xE49) - EQ3_14
+ */
+#define WM5100_EQ3_B4_A_MASK                    0xFFFF  /* EQ3_B4_A - [15:0] */
+#define WM5100_EQ3_B4_A_SHIFT                        0  /* EQ3_B4_A - [15:0] */
+#define WM5100_EQ3_B4_A_WIDTH                       16  /* EQ3_B4_A - [15:0] */
+
+/*
+ * R3658 (0xE4A) - EQ3_15
+ */
+#define WM5100_EQ3_B4_B_MASK                    0xFFFF  /* EQ3_B4_B - [15:0] */
+#define WM5100_EQ3_B4_B_SHIFT                        0  /* EQ3_B4_B - [15:0] */
+#define WM5100_EQ3_B4_B_WIDTH                       16  /* EQ3_B4_B - [15:0] */
+
+/*
+ * R3659 (0xE4B) - EQ3_16
+ */
+#define WM5100_EQ3_B4_C_MASK                    0xFFFF  /* EQ3_B4_C - [15:0] */
+#define WM5100_EQ3_B4_C_SHIFT                        0  /* EQ3_B4_C - [15:0] */
+#define WM5100_EQ3_B4_C_WIDTH                       16  /* EQ3_B4_C - [15:0] */
+
+/*
+ * R3660 (0xE4C) - EQ3_17
+ */
+#define WM5100_EQ3_B4_PG_MASK                   0xFFFF  /* EQ3_B4_PG - [15:0] */
+#define WM5100_EQ3_B4_PG_SHIFT                       0  /* EQ3_B4_PG - [15:0] */
+#define WM5100_EQ3_B4_PG_WIDTH                      16  /* EQ3_B4_PG - [15:0] */
+
+/*
+ * R3661 (0xE4D) - EQ3_18
+ */
+#define WM5100_EQ3_B5_A_MASK                    0xFFFF  /* EQ3_B5_A - [15:0] */
+#define WM5100_EQ3_B5_A_SHIFT                        0  /* EQ3_B5_A - [15:0] */
+#define WM5100_EQ3_B5_A_WIDTH                       16  /* EQ3_B5_A - [15:0] */
+
+/*
+ * R3662 (0xE4E) - EQ3_19
+ */
+#define WM5100_EQ3_B5_B_MASK                    0xFFFF  /* EQ3_B5_B - [15:0] */
+#define WM5100_EQ3_B5_B_SHIFT                        0  /* EQ3_B5_B - [15:0] */
+#define WM5100_EQ3_B5_B_WIDTH                       16  /* EQ3_B5_B - [15:0] */
+
+/*
+ * R3663 (0xE4F) - EQ3_20
+ */
+#define WM5100_EQ3_B5_PG_MASK                   0xFFFF  /* EQ3_B5_PG - [15:0] */
+#define WM5100_EQ3_B5_PG_SHIFT                       0  /* EQ3_B5_PG - [15:0] */
+#define WM5100_EQ3_B5_PG_WIDTH                      16  /* EQ3_B5_PG - [15:0] */
+
+/*
+ * R3666 (0xE52) - EQ4_1
+ */
+#define WM5100_EQ4_B1_GAIN_MASK                 0xF800  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B1_GAIN_SHIFT                    11  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B1_GAIN_WIDTH                     5  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B2_GAIN_MASK                 0x07C0  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B2_GAIN_SHIFT                     6  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B2_GAIN_WIDTH                     5  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B3_GAIN_MASK                 0x003E  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_B3_GAIN_SHIFT                     1  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_B3_GAIN_WIDTH                     5  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_ENA                          0x0001  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_MASK                     0x0001  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_SHIFT                         0  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_WIDTH                         1  /* EQ4_ENA */
+
+/*
+ * R3667 (0xE53) - EQ4_2
+ */
+#define WM5100_EQ4_B4_GAIN_MASK                 0xF800  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B4_GAIN_SHIFT                    11  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B4_GAIN_WIDTH                     5  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B5_GAIN_MASK                 0x07C0  /* EQ4_B5_GAIN - [10:6] */
+#define WM5100_EQ4_B5_GAIN_SHIFT                     6  /* EQ4_B5_GAIN - [10:6] */
+#define WM5100_EQ4_B5_GAIN_WIDTH                     5  /* EQ4_B5_GAIN - [10:6] */
+
+/*
+ * R3668 (0xE54) - EQ4_3
+ */
+#define WM5100_EQ4_B1_A_MASK                    0xFFFF  /* EQ4_B1_A - [15:0] */
+#define WM5100_EQ4_B1_A_SHIFT                        0  /* EQ4_B1_A - [15:0] */
+#define WM5100_EQ4_B1_A_WIDTH                       16  /* EQ4_B1_A - [15:0] */
+
+/*
+ * R3669 (0xE55) - EQ4_4
+ */
+#define WM5100_EQ4_B1_B_MASK                    0xFFFF  /* EQ4_B1_B - [15:0] */
+#define WM5100_EQ4_B1_B_SHIFT                        0  /* EQ4_B1_B - [15:0] */
+#define WM5100_EQ4_B1_B_WIDTH                       16  /* EQ4_B1_B - [15:0] */
+
+/*
+ * R3670 (0xE56) - EQ4_5
+ */
+#define WM5100_EQ4_B1_PG_MASK                   0xFFFF  /* EQ4_B1_PG - [15:0] */
+#define WM5100_EQ4_B1_PG_SHIFT                       0  /* EQ4_B1_PG - [15:0] */
+#define WM5100_EQ4_B1_PG_WIDTH                      16  /* EQ4_B1_PG - [15:0] */
+
+/*
+ * R3671 (0xE57) - EQ4_6
+ */
+#define WM5100_EQ4_B2_A_MASK                    0xFFFF  /* EQ4_B2_A - [15:0] */
+#define WM5100_EQ4_B2_A_SHIFT                        0  /* EQ4_B2_A - [15:0] */
+#define WM5100_EQ4_B2_A_WIDTH                       16  /* EQ4_B2_A - [15:0] */
+
+/*
+ * R3672 (0xE58) - EQ4_7
+ */
+#define WM5100_EQ4_B2_B_MASK                    0xFFFF  /* EQ4_B2_B - [15:0] */
+#define WM5100_EQ4_B2_B_SHIFT                        0  /* EQ4_B2_B - [15:0] */
+#define WM5100_EQ4_B2_B_WIDTH                       16  /* EQ4_B2_B - [15:0] */
+
+/*
+ * R3673 (0xE59) - EQ4_8
+ */
+#define WM5100_EQ4_B2_C_MASK                    0xFFFF  /* EQ4_B2_C - [15:0] */
+#define WM5100_EQ4_B2_C_SHIFT                        0  /* EQ4_B2_C - [15:0] */
+#define WM5100_EQ4_B2_C_WIDTH                       16  /* EQ4_B2_C - [15:0] */
+
+/*
+ * R3674 (0xE5A) - EQ4_9
+ */
+#define WM5100_EQ4_B2_PG_MASK                   0xFFFF  /* EQ4_B2_PG - [15:0] */
+#define WM5100_EQ4_B2_PG_SHIFT                       0  /* EQ4_B2_PG - [15:0] */
+#define WM5100_EQ4_B2_PG_WIDTH                      16  /* EQ4_B2_PG - [15:0] */
+
+/*
+ * R3675 (0xE5B) - EQ4_10
+ */
+#define WM5100_EQ4_B3_A_MASK                    0xFFFF  /* EQ4_B3_A - [15:0] */
+#define WM5100_EQ4_B3_A_SHIFT                        0  /* EQ4_B3_A - [15:0] */
+#define WM5100_EQ4_B3_A_WIDTH                       16  /* EQ4_B3_A - [15:0] */
+
+/*
+ * R3676 (0xE5C) - EQ4_11
+ */
+#define WM5100_EQ4_B3_B_MASK                    0xFFFF  /* EQ4_B3_B - [15:0] */
+#define WM5100_EQ4_B3_B_SHIFT                        0  /* EQ4_B3_B - [15:0] */
+#define WM5100_EQ4_B3_B_WIDTH                       16  /* EQ4_B3_B - [15:0] */
+
+/*
+ * R3677 (0xE5D) - EQ4_12
+ */
+#define WM5100_EQ4_B3_C_MASK                    0xFFFF  /* EQ4_B3_C - [15:0] */
+#define WM5100_EQ4_B3_C_SHIFT                        0  /* EQ4_B3_C - [15:0] */
+#define WM5100_EQ4_B3_C_WIDTH                       16  /* EQ4_B3_C - [15:0] */
+
+/*
+ * R3678 (0xE5E) - EQ4_13
+ */
+#define WM5100_EQ4_B3_PG_MASK                   0xFFFF  /* EQ4_B3_PG - [15:0] */
+#define WM5100_EQ4_B3_PG_SHIFT                       0  /* EQ4_B3_PG - [15:0] */
+#define WM5100_EQ4_B3_PG_WIDTH                      16  /* EQ4_B3_PG - [15:0] */
+
+/*
+ * R3679 (0xE5F) - EQ4_14
+ */
+#define WM5100_EQ4_B4_A_MASK                    0xFFFF  /* EQ4_B4_A - [15:0] */
+#define WM5100_EQ4_B4_A_SHIFT                        0  /* EQ4_B4_A - [15:0] */
+#define WM5100_EQ4_B4_A_WIDTH                       16  /* EQ4_B4_A - [15:0] */
+
+/*
+ * R3680 (0xE60) - EQ4_15
+ */
+#define WM5100_EQ4_B4_B_MASK                    0xFFFF  /* EQ4_B4_B - [15:0] */
+#define WM5100_EQ4_B4_B_SHIFT                        0  /* EQ4_B4_B - [15:0] */
+#define WM5100_EQ4_B4_B_WIDTH                       16  /* EQ4_B4_B - [15:0] */
+
+/*
+ * R3681 (0xE61) - EQ4_16
+ */
+#define WM5100_EQ4_B4_C_MASK                    0xFFFF  /* EQ4_B4_C - [15:0] */
+#define WM5100_EQ4_B4_C_SHIFT                        0  /* EQ4_B4_C - [15:0] */
+#define WM5100_EQ4_B4_C_WIDTH                       16  /* EQ4_B4_C - [15:0] */
+
+/*
+ * R3682 (0xE62) - EQ4_17
+ */
+#define WM5100_EQ4_B4_PG_MASK                   0xFFFF  /* EQ4_B4_PG - [15:0] */
+#define WM5100_EQ4_B4_PG_SHIFT                       0  /* EQ4_B4_PG - [15:0] */
+#define WM5100_EQ4_B4_PG_WIDTH                      16  /* EQ4_B4_PG - [15:0] */
+
+/*
+ * R3683 (0xE63) - EQ4_18
+ */
+#define WM5100_EQ4_B5_A_MASK                    0xFFFF  /* EQ4_B5_A - [15:0] */
+#define WM5100_EQ4_B5_A_SHIFT                        0  /* EQ4_B5_A - [15:0] */
+#define WM5100_EQ4_B5_A_WIDTH                       16  /* EQ4_B5_A - [15:0] */
+
+/*
+ * R3684 (0xE64) - EQ4_19
+ */
+#define WM5100_EQ4_B5_B_MASK                    0xFFFF  /* EQ4_B5_B - [15:0] */
+#define WM5100_EQ4_B5_B_SHIFT                        0  /* EQ4_B5_B - [15:0] */
+#define WM5100_EQ4_B5_B_WIDTH                       16  /* EQ4_B5_B - [15:0] */
+
+/*
+ * R3685 (0xE65) - EQ4_20
+ */
+#define WM5100_EQ4_B5_PG_MASK                   0xFFFF  /* EQ4_B5_PG - [15:0] */
+#define WM5100_EQ4_B5_PG_SHIFT                       0  /* EQ4_B5_PG - [15:0] */
+#define WM5100_EQ4_B5_PG_WIDTH                      16  /* EQ4_B5_PG - [15:0] */
+
+/*
+ * R3712 (0xE80) - DRC1 ctrl1
+ */
+#define WM5100_DRC_SIG_DET_RMS_MASK             0xF800  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_RMS_SHIFT                11  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_RMS_WIDTH                 5  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_PK_MASK              0x0600  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_SIG_DET_PK_SHIFT                  9  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_SIG_DET_PK_WIDTH                  2  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_NG_ENA                       0x0100  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_MASK                  0x0100  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_SHIFT                      8  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_WIDTH                      1  /* DRC_NG_ENA */
+#define WM5100_DRC_SIG_DET_MODE                 0x0080  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_MASK            0x0080  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_SHIFT                7  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_WIDTH                1  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET                      0x0040  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_MASK                 0x0040  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_SHIFT                     6  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_WIDTH                     1  /* DRC_SIG_DET */
+#define WM5100_DRC_KNEE2_OP_ENA                 0x0020  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_MASK            0x0020  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_SHIFT                5  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_WIDTH                1  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_QR                           0x0010  /* DRC_QR */
+#define WM5100_DRC_QR_MASK                      0x0010  /* DRC_QR */
+#define WM5100_DRC_QR_SHIFT                          4  /* DRC_QR */
+#define WM5100_DRC_QR_WIDTH                          1  /* DRC_QR */
+#define WM5100_DRC_ANTICLIP                     0x0008  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_MASK                0x0008  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_SHIFT                    3  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_WIDTH                    1  /* DRC_ANTICLIP */
+#define WM5100_DRCL_ENA                         0x0002  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_MASK                    0x0002  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_SHIFT                        1  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_WIDTH                        1  /* DRCL_ENA */
+#define WM5100_DRCR_ENA                         0x0001  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_MASK                    0x0001  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_SHIFT                        0  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_WIDTH                        1  /* DRCR_ENA */
+
+/*
+ * R3713 (0xE81) - DRC1 ctrl2
+ */
+#define WM5100_DRC_ATK_MASK                     0x1E00  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_ATK_SHIFT                         9  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_ATK_WIDTH                         4  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_DCY_MASK                     0x01E0  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_DCY_SHIFT                         5  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_DCY_WIDTH                         4  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_MINGAIN_MASK                 0x001C  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MINGAIN_SHIFT                     2  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MINGAIN_WIDTH                     3  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MAXGAIN_MASK                 0x0003  /* DRC_MAXGAIN - [1:0] */
+#define WM5100_DRC_MAXGAIN_SHIFT                     0  /* DRC_MAXGAIN - [1:0] */
+#define WM5100_DRC_MAXGAIN_WIDTH                     2  /* DRC_MAXGAIN - [1:0] */
+
+/*
+ * R3714 (0xE82) - DRC1 ctrl3
+ */
+#define WM5100_DRC_NG_MINGAIN_MASK              0xF000  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_MINGAIN_SHIFT                 12  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_MINGAIN_WIDTH                  4  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_EXP_MASK                  0x0C00  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_NG_EXP_SHIFT                     10  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_NG_EXP_WIDTH                      2  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_QR_THR_MASK                  0x0300  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_THR_SHIFT                      8  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_THR_WIDTH                      2  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_DCY_MASK                  0x00C0  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_QR_DCY_SHIFT                      6  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_QR_DCY_WIDTH                      2  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_HI_COMP_MASK                 0x0038  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_HI_COMP_SHIFT                     3  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_HI_COMP_WIDTH                     3  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_LO_COMP_MASK                 0x0007  /* DRC_LO_COMP - [2:0] */
+#define WM5100_DRC_LO_COMP_SHIFT                     0  /* DRC_LO_COMP - [2:0] */
+#define WM5100_DRC_LO_COMP_WIDTH                     3  /* DRC_LO_COMP - [2:0] */
+
+/*
+ * R3715 (0xE83) - DRC1 ctrl4
+ */
+#define WM5100_DRC_KNEE_IP_MASK                 0x07E0  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_IP_SHIFT                     5  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_IP_WIDTH                     6  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_OP_MASK                 0x001F  /* DRC_KNEE_OP - [4:0] */
+#define WM5100_DRC_KNEE_OP_SHIFT                     0  /* DRC_KNEE_OP - [4:0] */
+#define WM5100_DRC_KNEE_OP_WIDTH                     5  /* DRC_KNEE_OP - [4:0] */
+
+/*
+ * R3716 (0xE84) - DRC1 ctrl5
+ */
+#define WM5100_DRC_KNEE2_IP_MASK                0x03E0  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_IP_SHIFT                    5  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_IP_WIDTH                    5  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_OP_MASK                0x001F  /* DRC_KNEE2_OP - [4:0] */
+#define WM5100_DRC_KNEE2_OP_SHIFT                    0  /* DRC_KNEE2_OP - [4:0] */
+#define WM5100_DRC_KNEE2_OP_WIDTH                    5  /* DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R3776 (0xEC0) - HPLPF1_1
+ */
+#define WM5100_LHPF1_MODE                       0x0002  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_MASK                  0x0002  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_SHIFT                      1  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_WIDTH                      1  /* LHPF1_MODE */
+#define WM5100_LHPF1_ENA                        0x0001  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_MASK                   0x0001  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_SHIFT                       0  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_WIDTH                       1  /* LHPF1_ENA */
+
+/*
+ * R3777 (0xEC1) - HPLPF1_2
+ */
+#define WM5100_LHPF1_COEFF_MASK                 0xFFFF  /* LHPF1_COEFF - [15:0] */
+#define WM5100_LHPF1_COEFF_SHIFT                     0  /* LHPF1_COEFF - [15:0] */
+#define WM5100_LHPF1_COEFF_WIDTH                    16  /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R3780 (0xEC4) - HPLPF2_1
+ */
+#define WM5100_LHPF2_MODE                       0x0002  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_MASK                  0x0002  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_SHIFT                      1  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_WIDTH                      1  /* LHPF2_MODE */
+#define WM5100_LHPF2_ENA                        0x0001  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_MASK                   0x0001  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_SHIFT                       0  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_WIDTH                       1  /* LHPF2_ENA */
+
+/*
+ * R3781 (0xEC5) - HPLPF2_2
+ */
+#define WM5100_LHPF2_COEFF_MASK                 0xFFFF  /* LHPF2_COEFF - [15:0] */
+#define WM5100_LHPF2_COEFF_SHIFT                     0  /* LHPF2_COEFF - [15:0] */
+#define WM5100_LHPF2_COEFF_WIDTH                    16  /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R3784 (0xEC8) - HPLPF3_1
+ */
+#define WM5100_LHPF3_MODE                       0x0002  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_MASK                  0x0002  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_SHIFT                      1  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_WIDTH                      1  /* LHPF3_MODE */
+#define WM5100_LHPF3_ENA                        0x0001  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_MASK                   0x0001  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_SHIFT                       0  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_WIDTH                       1  /* LHPF3_ENA */
+
+/*
+ * R3785 (0xEC9) - HPLPF3_2
+ */
+#define WM5100_LHPF3_COEFF_MASK                 0xFFFF  /* LHPF3_COEFF - [15:0] */
+#define WM5100_LHPF3_COEFF_SHIFT                     0  /* LHPF3_COEFF - [15:0] */
+#define WM5100_LHPF3_COEFF_WIDTH                    16  /* LHPF3_COEFF - [15:0] */
+
+/*
+ * R3788 (0xECC) - HPLPF4_1
+ */
+#define WM5100_LHPF4_MODE                       0x0002  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_MASK                  0x0002  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_SHIFT                      1  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_WIDTH                      1  /* LHPF4_MODE */
+#define WM5100_LHPF4_ENA                        0x0001  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_MASK                   0x0001  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_SHIFT                       0  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_WIDTH                       1  /* LHPF4_ENA */
+
+/*
+ * R3789 (0xECD) - HPLPF4_2
+ */
+#define WM5100_LHPF4_COEFF_MASK                 0xFFFF  /* LHPF4_COEFF - [15:0] */
+#define WM5100_LHPF4_COEFF_SHIFT                     0  /* LHPF4_COEFF - [15:0] */
+#define WM5100_LHPF4_COEFF_WIDTH                    16  /* LHPF4_COEFF - [15:0] */
+
+/*
+ * R16384 (0x4000) - DSP1 DM 0
+ */
+#define WM5100_DSP1_DM_START_1_MASK             0x00FF  /* DSP1_DM_START - [7:0] */
+#define WM5100_DSP1_DM_START_1_SHIFT                 0  /* DSP1_DM_START - [7:0] */
+#define WM5100_DSP1_DM_START_1_WIDTH                 8  /* DSP1_DM_START - [7:0] */
+
+/*
+ * R16385 (0x4001) - DSP1 DM 1
+ */
+#define WM5100_DSP1_DM_START_MASK               0xFFFF  /* DSP1_DM_START - [15:0] */
+#define WM5100_DSP1_DM_START_SHIFT                   0  /* DSP1_DM_START - [15:0] */
+#define WM5100_DSP1_DM_START_WIDTH                  16  /* DSP1_DM_START - [15:0] */
+
+/*
+ * R16386 (0x4002) - DSP1 DM 2
+ */
+#define WM5100_DSP1_DM_1_1_MASK                 0x00FF  /* DSP1_DM_1 - [7:0] */
+#define WM5100_DSP1_DM_1_1_SHIFT                     0  /* DSP1_DM_1 - [7:0] */
+#define WM5100_DSP1_DM_1_1_WIDTH                     8  /* DSP1_DM_1 - [7:0] */
+
+/*
+ * R16387 (0x4003) - DSP1 DM 3
+ */
+#define WM5100_DSP1_DM_1_MASK                   0xFFFF  /* DSP1_DM_1 - [15:0] */
+#define WM5100_DSP1_DM_1_SHIFT                       0  /* DSP1_DM_1 - [15:0] */
+#define WM5100_DSP1_DM_1_WIDTH                      16  /* DSP1_DM_1 - [15:0] */
+
+/*
+ * R16892 (0x41FC) - DSP1 DM 508
+ */
+#define WM5100_DSP1_DM_254_1_MASK               0x00FF  /* DSP1_DM_254 - [7:0] */
+#define WM5100_DSP1_DM_254_1_SHIFT                   0  /* DSP1_DM_254 - [7:0] */
+#define WM5100_DSP1_DM_254_1_WIDTH                   8  /* DSP1_DM_254 - [7:0] */
+
+/*
+ * R16893 (0x41FD) - DSP1 DM 509
+ */
+#define WM5100_DSP1_DM_254_MASK                 0xFFFF  /* DSP1_DM_254 - [15:0] */
+#define WM5100_DSP1_DM_254_SHIFT                     0  /* DSP1_DM_254 - [15:0] */
+#define WM5100_DSP1_DM_254_WIDTH                    16  /* DSP1_DM_254 - [15:0] */
+
+/*
+ * R16894 (0x41FE) - DSP1 DM 510
+ */
+#define WM5100_DSP1_DM_END_1_MASK               0x00FF  /* DSP1_DM_END - [7:0] */
+#define WM5100_DSP1_DM_END_1_SHIFT                   0  /* DSP1_DM_END - [7:0] */
+#define WM5100_DSP1_DM_END_1_WIDTH                   8  /* DSP1_DM_END - [7:0] */
+
+/*
+ * R16895 (0x41FF) - DSP1 DM 511
+ */
+#define WM5100_DSP1_DM_END_MASK                 0xFFFF  /* DSP1_DM_END - [15:0] */
+#define WM5100_DSP1_DM_END_SHIFT                     0  /* DSP1_DM_END - [15:0] */
+#define WM5100_DSP1_DM_END_WIDTH                    16  /* DSP1_DM_END - [15:0] */
+
+/*
+ * R18432 (0x4800) - DSP1 PM 0
+ */
+#define WM5100_DSP1_PM_START_2_MASK             0x00FF  /* DSP1_PM_START - [7:0] */
+#define WM5100_DSP1_PM_START_2_SHIFT                 0  /* DSP1_PM_START - [7:0] */
+#define WM5100_DSP1_PM_START_2_WIDTH                 8  /* DSP1_PM_START - [7:0] */
+
+/*
+ * R18433 (0x4801) - DSP1 PM 1
+ */
+#define WM5100_DSP1_PM_START_1_MASK             0xFFFF  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_1_SHIFT                 0  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_1_WIDTH                16  /* DSP1_PM_START - [15:0] */
+
+/*
+ * R18434 (0x4802) - DSP1 PM 2
+ */
+#define WM5100_DSP1_PM_START_MASK               0xFFFF  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_SHIFT                   0  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_WIDTH                  16  /* DSP1_PM_START - [15:0] */
+
+/*
+ * R18435 (0x4803) - DSP1 PM 3
+ */
+#define WM5100_DSP1_PM_1_2_MASK                 0x00FF  /* DSP1_PM_1 - [7:0] */
+#define WM5100_DSP1_PM_1_2_SHIFT                     0  /* DSP1_PM_1 - [7:0] */
+#define WM5100_DSP1_PM_1_2_WIDTH                     8  /* DSP1_PM_1 - [7:0] */
+
+/*
+ * R18436 (0x4804) - DSP1 PM 4
+ */
+#define WM5100_DSP1_PM_1_1_MASK                 0xFFFF  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_1_SHIFT                     0  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_1_WIDTH                    16  /* DSP1_PM_1 - [15:0] */
+
+/*
+ * R18437 (0x4805) - DSP1 PM 5
+ */
+#define WM5100_DSP1_PM_1_MASK                   0xFFFF  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_SHIFT                       0  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_WIDTH                      16  /* DSP1_PM_1 - [15:0] */
+
+/*
+ * R19962 (0x4DFA) - DSP1 PM 1530
+ */
+#define WM5100_DSP1_PM_510_2_MASK               0x00FF  /* DSP1_PM_510 - [7:0] */
+#define WM5100_DSP1_PM_510_2_SHIFT                   0  /* DSP1_PM_510 - [7:0] */
+#define WM5100_DSP1_PM_510_2_WIDTH                   8  /* DSP1_PM_510 - [7:0] */
+
+/*
+ * R19963 (0x4DFB) - DSP1 PM 1531
+ */
+#define WM5100_DSP1_PM_510_1_MASK               0xFFFF  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_1_SHIFT                   0  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_1_WIDTH                  16  /* DSP1_PM_510 - [15:0] */
+
+/*
+ * R19964 (0x4DFC) - DSP1 PM 1532
+ */
+#define WM5100_DSP1_PM_510_MASK                 0xFFFF  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_SHIFT                     0  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_WIDTH                    16  /* DSP1_PM_510 - [15:0] */
+
+/*
+ * R19965 (0x4DFD) - DSP1 PM 1533
+ */
+#define WM5100_DSP1_PM_END_2_MASK               0x00FF  /* DSP1_PM_END - [7:0] */
+#define WM5100_DSP1_PM_END_2_SHIFT                   0  /* DSP1_PM_END - [7:0] */
+#define WM5100_DSP1_PM_END_2_WIDTH                   8  /* DSP1_PM_END - [7:0] */
+
+/*
+ * R19966 (0x4DFE) - DSP1 PM 1534
+ */
+#define WM5100_DSP1_PM_END_1_MASK               0xFFFF  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_1_SHIFT                   0  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_1_WIDTH                  16  /* DSP1_PM_END - [15:0] */
+
+/*
+ * R19967 (0x4DFF) - DSP1 PM 1535
+ */
+#define WM5100_DSP1_PM_END_MASK                 0xFFFF  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_SHIFT                     0  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_WIDTH                    16  /* DSP1_PM_END - [15:0] */
+
+/*
+ * R20480 (0x5000) - DSP1 ZM 0
+ */
+#define WM5100_DSP1_ZM_START_1_MASK             0x00FF  /* DSP1_ZM_START - [7:0] */
+#define WM5100_DSP1_ZM_START_1_SHIFT                 0  /* DSP1_ZM_START - [7:0] */
+#define WM5100_DSP1_ZM_START_1_WIDTH                 8  /* DSP1_ZM_START - [7:0] */
+
+/*
+ * R20481 (0x5001) - DSP1 ZM 1
+ */
+#define WM5100_DSP1_ZM_START_MASK               0xFFFF  /* DSP1_ZM_START - [15:0] */
+#define WM5100_DSP1_ZM_START_SHIFT                   0  /* DSP1_ZM_START - [15:0] */
+#define WM5100_DSP1_ZM_START_WIDTH                  16  /* DSP1_ZM_START - [15:0] */
+
+/*
+ * R20482 (0x5002) - DSP1 ZM 2
+ */
+#define WM5100_DSP1_ZM_1_1_MASK                 0x00FF  /* DSP1_ZM_1 - [7:0] */
+#define WM5100_DSP1_ZM_1_1_SHIFT                     0  /* DSP1_ZM_1 - [7:0] */
+#define WM5100_DSP1_ZM_1_1_WIDTH                     8  /* DSP1_ZM_1 - [7:0] */
+
+/*
+ * R20483 (0x5003) - DSP1 ZM 3
+ */
+#define WM5100_DSP1_ZM_1_MASK                   0xFFFF  /* DSP1_ZM_1 - [15:0] */
+#define WM5100_DSP1_ZM_1_SHIFT                       0  /* DSP1_ZM_1 - [15:0] */
+#define WM5100_DSP1_ZM_1_WIDTH                      16  /* DSP1_ZM_1 - [15:0] */
+
+/*
+ * R22524 (0x57FC) - DSP1 ZM 2044
+ */
+#define WM5100_DSP1_ZM_1022_1_MASK              0x00FF  /* DSP1_ZM_1022 - [7:0] */
+#define WM5100_DSP1_ZM_1022_1_SHIFT                  0  /* DSP1_ZM_1022 - [7:0] */
+#define WM5100_DSP1_ZM_1022_1_WIDTH                  8  /* DSP1_ZM_1022 - [7:0] */
+
+/*
+ * R22525 (0x57FD) - DSP1 ZM 2045
+ */
+#define WM5100_DSP1_ZM_1022_MASK                0xFFFF  /* DSP1_ZM_1022 - [15:0] */
+#define WM5100_DSP1_ZM_1022_SHIFT                    0  /* DSP1_ZM_1022 - [15:0] */
+#define WM5100_DSP1_ZM_1022_WIDTH                   16  /* DSP1_ZM_1022 - [15:0] */
+
+/*
+ * R22526 (0x57FE) - DSP1 ZM 2046
+ */
+#define WM5100_DSP1_ZM_END_1_MASK               0x00FF  /* DSP1_ZM_END - [7:0] */
+#define WM5100_DSP1_ZM_END_1_SHIFT                   0  /* DSP1_ZM_END - [7:0] */
+#define WM5100_DSP1_ZM_END_1_WIDTH                   8  /* DSP1_ZM_END - [7:0] */
+
+/*
+ * R22527 (0x57FF) - DSP1 ZM 2047
+ */
+#define WM5100_DSP1_ZM_END_MASK                 0xFFFF  /* DSP1_ZM_END - [15:0] */
+#define WM5100_DSP1_ZM_END_SHIFT                     0  /* DSP1_ZM_END - [15:0] */
+#define WM5100_DSP1_ZM_END_WIDTH                    16  /* DSP1_ZM_END - [15:0] */
+
+/*
+ * R24576 (0x6000) - DSP2 DM 0
+ */
+#define WM5100_DSP2_DM_START_1_MASK             0x00FF  /* DSP2_DM_START - [7:0] */
+#define WM5100_DSP2_DM_START_1_SHIFT                 0  /* DSP2_DM_START - [7:0] */
+#define WM5100_DSP2_DM_START_1_WIDTH                 8  /* DSP2_DM_START - [7:0] */
+
+/*
+ * R24577 (0x6001) - DSP2 DM 1
+ */
+#define WM5100_DSP2_DM_START_MASK               0xFFFF  /* DSP2_DM_START - [15:0] */
+#define WM5100_DSP2_DM_START_SHIFT                   0  /* DSP2_DM_START - [15:0] */
+#define WM5100_DSP2_DM_START_WIDTH                  16  /* DSP2_DM_START - [15:0] */
+
+/*
+ * R24578 (0x6002) - DSP2 DM 2
+ */
+#define WM5100_DSP2_DM_1_1_MASK                 0x00FF  /* DSP2_DM_1 - [7:0] */
+#define WM5100_DSP2_DM_1_1_SHIFT                     0  /* DSP2_DM_1 - [7:0] */
+#define WM5100_DSP2_DM_1_1_WIDTH                     8  /* DSP2_DM_1 - [7:0] */
+
+/*
+ * R24579 (0x6003) - DSP2 DM 3
+ */
+#define WM5100_DSP2_DM_1_MASK                   0xFFFF  /* DSP2_DM_1 - [15:0] */
+#define WM5100_DSP2_DM_1_SHIFT                       0  /* DSP2_DM_1 - [15:0] */
+#define WM5100_DSP2_DM_1_WIDTH                      16  /* DSP2_DM_1 - [15:0] */
+
+/*
+ * R25084 (0x61FC) - DSP2 DM 508
+ */
+#define WM5100_DSP2_DM_254_1_MASK               0x00FF  /* DSP2_DM_254 - [7:0] */
+#define WM5100_DSP2_DM_254_1_SHIFT                   0  /* DSP2_DM_254 - [7:0] */
+#define WM5100_DSP2_DM_254_1_WIDTH                   8  /* DSP2_DM_254 - [7:0] */
+
+/*
+ * R25085 (0x61FD) - DSP2 DM 509
+ */
+#define WM5100_DSP2_DM_254_MASK                 0xFFFF  /* DSP2_DM_254 - [15:0] */
+#define WM5100_DSP2_DM_254_SHIFT                     0  /* DSP2_DM_254 - [15:0] */
+#define WM5100_DSP2_DM_254_WIDTH                    16  /* DSP2_DM_254 - [15:0] */
+
+/*
+ * R25086 (0x61FE) - DSP2 DM 510
+ */
+#define WM5100_DSP2_DM_END_1_MASK               0x00FF  /* DSP2_DM_END - [7:0] */
+#define WM5100_DSP2_DM_END_1_SHIFT                   0  /* DSP2_DM_END - [7:0] */
+#define WM5100_DSP2_DM_END_1_WIDTH                   8  /* DSP2_DM_END - [7:0] */
+
+/*
+ * R25087 (0x61FF) - DSP2 DM 511
+ */
+#define WM5100_DSP2_DM_END_MASK                 0xFFFF  /* DSP2_DM_END - [15:0] */
+#define WM5100_DSP2_DM_END_SHIFT                     0  /* DSP2_DM_END - [15:0] */
+#define WM5100_DSP2_DM_END_WIDTH                    16  /* DSP2_DM_END - [15:0] */
+
+/*
+ * R26624 (0x6800) - DSP2 PM 0
+ */
+#define WM5100_DSP2_PM_START_2_MASK             0x00FF  /* DSP2_PM_START - [7:0] */
+#define WM5100_DSP2_PM_START_2_SHIFT                 0  /* DSP2_PM_START - [7:0] */
+#define WM5100_DSP2_PM_START_2_WIDTH                 8  /* DSP2_PM_START - [7:0] */
+
+/*
+ * R26625 (0x6801) - DSP2 PM 1
+ */
+#define WM5100_DSP2_PM_START_1_MASK             0xFFFF  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_1_SHIFT                 0  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_1_WIDTH                16  /* DSP2_PM_START - [15:0] */
+
+/*
+ * R26626 (0x6802) - DSP2 PM 2
+ */
+#define WM5100_DSP2_PM_START_MASK               0xFFFF  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_SHIFT                   0  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_WIDTH                  16  /* DSP2_PM_START - [15:0] */
+
+/*
+ * R26627 (0x6803) - DSP2 PM 3
+ */
+#define WM5100_DSP2_PM_1_2_MASK                 0x00FF  /* DSP2_PM_1 - [7:0] */
+#define WM5100_DSP2_PM_1_2_SHIFT                     0  /* DSP2_PM_1 - [7:0] */
+#define WM5100_DSP2_PM_1_2_WIDTH                     8  /* DSP2_PM_1 - [7:0] */
+
+/*
+ * R26628 (0x6804) - DSP2 PM 4
+ */
+#define WM5100_DSP2_PM_1_1_MASK                 0xFFFF  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_1_SHIFT                     0  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_1_WIDTH                    16  /* DSP2_PM_1 - [15:0] */
+
+/*
+ * R26629 (0x6805) - DSP2 PM 5
+ */
+#define WM5100_DSP2_PM_1_MASK                   0xFFFF  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_SHIFT                       0  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_WIDTH                      16  /* DSP2_PM_1 - [15:0] */
+
+/*
+ * R28154 (0x6DFA) - DSP2 PM 1530
+ */
+#define WM5100_DSP2_PM_510_2_MASK               0x00FF  /* DSP2_PM_510 - [7:0] */
+#define WM5100_DSP2_PM_510_2_SHIFT                   0  /* DSP2_PM_510 - [7:0] */
+#define WM5100_DSP2_PM_510_2_WIDTH                   8  /* DSP2_PM_510 - [7:0] */
+
+/*
+ * R28155 (0x6DFB) - DSP2 PM 1531
+ */
+#define WM5100_DSP2_PM_510_1_MASK               0xFFFF  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_1_SHIFT                   0  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_1_WIDTH                  16  /* DSP2_PM_510 - [15:0] */
+
+/*
+ * R28156 (0x6DFC) - DSP2 PM 1532
+ */
+#define WM5100_DSP2_PM_510_MASK                 0xFFFF  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_SHIFT                     0  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_WIDTH                    16  /* DSP2_PM_510 - [15:0] */
+
+/*
+ * R28157 (0x6DFD) - DSP2 PM 1533
+ */
+#define WM5100_DSP2_PM_END_2_MASK               0x00FF  /* DSP2_PM_END - [7:0] */
+#define WM5100_DSP2_PM_END_2_SHIFT                   0  /* DSP2_PM_END - [7:0] */
+#define WM5100_DSP2_PM_END_2_WIDTH                   8  /* DSP2_PM_END - [7:0] */
+
+/*
+ * R28158 (0x6DFE) - DSP2 PM 1534
+ */
+#define WM5100_DSP2_PM_END_1_MASK               0xFFFF  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_1_SHIFT                   0  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_1_WIDTH                  16  /* DSP2_PM_END - [15:0] */
+
+/*
+ * R28159 (0x6DFF) - DSP2 PM 1535
+ */
+#define WM5100_DSP2_PM_END_MASK                 0xFFFF  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_SHIFT                     0  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_WIDTH                    16  /* DSP2_PM_END - [15:0] */
+
+/*
+ * R28672 (0x7000) - DSP2 ZM 0
+ */
+#define WM5100_DSP2_ZM_START_1_MASK             0x00FF  /* DSP2_ZM_START - [7:0] */
+#define WM5100_DSP2_ZM_START_1_SHIFT                 0  /* DSP2_ZM_START - [7:0] */
+#define WM5100_DSP2_ZM_START_1_WIDTH                 8  /* DSP2_ZM_START - [7:0] */
+
+/*
+ * R28673 (0x7001) - DSP2 ZM 1
+ */
+#define WM5100_DSP2_ZM_START_MASK               0xFFFF  /* DSP2_ZM_START - [15:0] */
+#define WM5100_DSP2_ZM_START_SHIFT                   0  /* DSP2_ZM_START - [15:0] */
+#define WM5100_DSP2_ZM_START_WIDTH                  16  /* DSP2_ZM_START - [15:0] */
+
+/*
+ * R28674 (0x7002) - DSP2 ZM 2
+ */
+#define WM5100_DSP2_ZM_1_1_MASK                 0x00FF  /* DSP2_ZM_1 - [7:0] */
+#define WM5100_DSP2_ZM_1_1_SHIFT                     0  /* DSP2_ZM_1 - [7:0] */
+#define WM5100_DSP2_ZM_1_1_WIDTH                     8  /* DSP2_ZM_1 - [7:0] */
+
+/*
+ * R28675 (0x7003) - DSP2 ZM 3
+ */
+#define WM5100_DSP2_ZM_1_MASK                   0xFFFF  /* DSP2_ZM_1 - [15:0] */
+#define WM5100_DSP2_ZM_1_SHIFT                       0  /* DSP2_ZM_1 - [15:0] */
+#define WM5100_DSP2_ZM_1_WIDTH                      16  /* DSP2_ZM_1 - [15:0] */
+
+/*
+ * R30716 (0x77FC) - DSP2 ZM 2044
+ */
+#define WM5100_DSP2_ZM_1022_1_MASK              0x00FF  /* DSP2_ZM_1022 - [7:0] */
+#define WM5100_DSP2_ZM_1022_1_SHIFT                  0  /* DSP2_ZM_1022 - [7:0] */
+#define WM5100_DSP2_ZM_1022_1_WIDTH                  8  /* DSP2_ZM_1022 - [7:0] */
+
+/*
+ * R30717 (0x77FD) - DSP2 ZM 2045
+ */
+#define WM5100_DSP2_ZM_1022_MASK                0xFFFF  /* DSP2_ZM_1022 - [15:0] */
+#define WM5100_DSP2_ZM_1022_SHIFT                    0  /* DSP2_ZM_1022 - [15:0] */
+#define WM5100_DSP2_ZM_1022_WIDTH                   16  /* DSP2_ZM_1022 - [15:0] */
+
+/*
+ * R30718 (0x77FE) - DSP2 ZM 2046
+ */
+#define WM5100_DSP2_ZM_END_1_MASK               0x00FF  /* DSP2_ZM_END - [7:0] */
+#define WM5100_DSP2_ZM_END_1_SHIFT                   0  /* DSP2_ZM_END - [7:0] */
+#define WM5100_DSP2_ZM_END_1_WIDTH                   8  /* DSP2_ZM_END - [7:0] */
+
+/*
+ * R30719 (0x77FF) - DSP2 ZM 2047
+ */
+#define WM5100_DSP2_ZM_END_MASK                 0xFFFF  /* DSP2_ZM_END - [15:0] */
+#define WM5100_DSP2_ZM_END_SHIFT                     0  /* DSP2_ZM_END - [15:0] */
+#define WM5100_DSP2_ZM_END_WIDTH                    16  /* DSP2_ZM_END - [15:0] */
+
+/*
+ * R32768 (0x8000) - DSP3 DM 0
+ */
+#define WM5100_DSP3_DM_START_1_MASK             0x00FF  /* DSP3_DM_START - [7:0] */
+#define WM5100_DSP3_DM_START_1_SHIFT                 0  /* DSP3_DM_START - [7:0] */
+#define WM5100_DSP3_DM_START_1_WIDTH                 8  /* DSP3_DM_START - [7:0] */
+
+/*
+ * R32769 (0x8001) - DSP3 DM 1
+ */
+#define WM5100_DSP3_DM_START_MASK               0xFFFF  /* DSP3_DM_START - [15:0] */
+#define WM5100_DSP3_DM_START_SHIFT                   0  /* DSP3_DM_START - [15:0] */
+#define WM5100_DSP3_DM_START_WIDTH                  16  /* DSP3_DM_START - [15:0] */
+
+/*
+ * R32770 (0x8002) - DSP3 DM 2
+ */
+#define WM5100_DSP3_DM_1_1_MASK                 0x00FF  /* DSP3_DM_1 - [7:0] */
+#define WM5100_DSP3_DM_1_1_SHIFT                     0  /* DSP3_DM_1 - [7:0] */
+#define WM5100_DSP3_DM_1_1_WIDTH                     8  /* DSP3_DM_1 - [7:0] */
+
+/*
+ * R32771 (0x8003) - DSP3 DM 3
+ */
+#define WM5100_DSP3_DM_1_MASK                   0xFFFF  /* DSP3_DM_1 - [15:0] */
+#define WM5100_DSP3_DM_1_SHIFT                       0  /* DSP3_DM_1 - [15:0] */
+#define WM5100_DSP3_DM_1_WIDTH                      16  /* DSP3_DM_1 - [15:0] */
+
+/*
+ * R33276 (0x81FC) - DSP3 DM 508
+ */
+#define WM5100_DSP3_DM_254_1_MASK               0x00FF  /* DSP3_DM_254 - [7:0] */
+#define WM5100_DSP3_DM_254_1_SHIFT                   0  /* DSP3_DM_254 - [7:0] */
+#define WM5100_DSP3_DM_254_1_WIDTH                   8  /* DSP3_DM_254 - [7:0] */
+
+/*
+ * R33277 (0x81FD) - DSP3 DM 509
+ */
+#define WM5100_DSP3_DM_254_MASK                 0xFFFF  /* DSP3_DM_254 - [15:0] */
+#define WM5100_DSP3_DM_254_SHIFT                     0  /* DSP3_DM_254 - [15:0] */
+#define WM5100_DSP3_DM_254_WIDTH                    16  /* DSP3_DM_254 - [15:0] */
+
+/*
+ * R33278 (0x81FE) - DSP3 DM 510
+ */
+#define WM5100_DSP3_DM_END_1_MASK               0x00FF  /* DSP3_DM_END - [7:0] */
+#define WM5100_DSP3_DM_END_1_SHIFT                   0  /* DSP3_DM_END - [7:0] */
+#define WM5100_DSP3_DM_END_1_WIDTH                   8  /* DSP3_DM_END - [7:0] */
+
+/*
+ * R33279 (0x81FF) - DSP3 DM 511
+ */
+#define WM5100_DSP3_DM_END_MASK                 0xFFFF  /* DSP3_DM_END - [15:0] */
+#define WM5100_DSP3_DM_END_SHIFT                     0  /* DSP3_DM_END - [15:0] */
+#define WM5100_DSP3_DM_END_WIDTH                    16  /* DSP3_DM_END - [15:0] */
+
+/*
+ * R34816 (0x8800) - DSP3 PM 0
+ */
+#define WM5100_DSP3_PM_START_2_MASK             0x00FF  /* DSP3_PM_START - [7:0] */
+#define WM5100_DSP3_PM_START_2_SHIFT                 0  /* DSP3_PM_START - [7:0] */
+#define WM5100_DSP3_PM_START_2_WIDTH                 8  /* DSP3_PM_START - [7:0] */
+
+/*
+ * R34817 (0x8801) - DSP3 PM 1
+ */
+#define WM5100_DSP3_PM_START_1_MASK             0xFFFF  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_1_SHIFT                 0  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_1_WIDTH                16  /* DSP3_PM_START - [15:0] */
+
+/*
+ * R34818 (0x8802) - DSP3 PM 2
+ */
+#define WM5100_DSP3_PM_START_MASK               0xFFFF  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_SHIFT                   0  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_WIDTH                  16  /* DSP3_PM_START - [15:0] */
+
+/*
+ * R34819 (0x8803) - DSP3 PM 3
+ */
+#define WM5100_DSP3_PM_1_2_MASK                 0x00FF  /* DSP3_PM_1 - [7:0] */
+#define WM5100_DSP3_PM_1_2_SHIFT                     0  /* DSP3_PM_1 - [7:0] */
+#define WM5100_DSP3_PM_1_2_WIDTH                     8  /* DSP3_PM_1 - [7:0] */
+
+/*
+ * R34820 (0x8804) - DSP3 PM 4
+ */
+#define WM5100_DSP3_PM_1_1_MASK                 0xFFFF  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_1_SHIFT                     0  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_1_WIDTH                    16  /* DSP3_PM_1 - [15:0] */
+
+/*
+ * R34821 (0x8805) - DSP3 PM 5
+ */
+#define WM5100_DSP3_PM_1_MASK                   0xFFFF  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_SHIFT                       0  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_WIDTH                      16  /* DSP3_PM_1 - [15:0] */
+
+/*
+ * R36346 (0x8DFA) - DSP3 PM 1530
+ */
+#define WM5100_DSP3_PM_510_2_MASK               0x00FF  /* DSP3_PM_510 - [7:0] */
+#define WM5100_DSP3_PM_510_2_SHIFT                   0  /* DSP3_PM_510 - [7:0] */
+#define WM5100_DSP3_PM_510_2_WIDTH                   8  /* DSP3_PM_510 - [7:0] */
+
+/*
+ * R36347 (0x8DFB) - DSP3 PM 1531
+ */
+#define WM5100_DSP3_PM_510_1_MASK               0xFFFF  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_1_SHIFT                   0  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_1_WIDTH                  16  /* DSP3_PM_510 - [15:0] */
+
+/*
+ * R36348 (0x8DFC) - DSP3 PM 1532
+ */
+#define WM5100_DSP3_PM_510_MASK                 0xFFFF  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_SHIFT                     0  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_WIDTH                    16  /* DSP3_PM_510 - [15:0] */
+
+/*
+ * R36349 (0x8DFD) - DSP3 PM 1533
+ */
+#define WM5100_DSP3_PM_END_2_MASK               0x00FF  /* DSP3_PM_END - [7:0] */
+#define WM5100_DSP3_PM_END_2_SHIFT                   0  /* DSP3_PM_END - [7:0] */
+#define WM5100_DSP3_PM_END_2_WIDTH                   8  /* DSP3_PM_END - [7:0] */
+
+/*
+ * R36350 (0x8DFE) - DSP3 PM 1534
+ */
+#define WM5100_DSP3_PM_END_1_MASK               0xFFFF  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_1_SHIFT                   0  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_1_WIDTH                  16  /* DSP3_PM_END - [15:0] */
+
+/*
+ * R36351 (0x8DFF) - DSP3 PM 1535
+ */
+#define WM5100_DSP3_PM_END_MASK                 0xFFFF  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_SHIFT                     0  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_WIDTH                    16  /* DSP3_PM_END - [15:0] */
+
+/*
+ * R36864 (0x9000) - DSP3 ZM 0
+ */
+#define WM5100_DSP3_ZM_START_1_MASK             0x00FF  /* DSP3_ZM_START - [7:0] */
+#define WM5100_DSP3_ZM_START_1_SHIFT                 0  /* DSP3_ZM_START - [7:0] */
+#define WM5100_DSP3_ZM_START_1_WIDTH                 8  /* DSP3_ZM_START - [7:0] */
+
+/*
+ * R36865 (0x9001) - DSP3 ZM 1
+ */
+#define WM5100_DSP3_ZM_START_MASK               0xFFFF  /* DSP3_ZM_START - [15:0] */
+#define WM5100_DSP3_ZM_START_SHIFT                   0  /* DSP3_ZM_START - [15:0] */
+#define WM5100_DSP3_ZM_START_WIDTH                  16  /* DSP3_ZM_START - [15:0] */
+
+/*
+ * R36866 (0x9002) - DSP3 ZM 2
+ */
+#define WM5100_DSP3_ZM_1_1_MASK                 0x00FF  /* DSP3_ZM_1 - [7:0] */
+#define WM5100_DSP3_ZM_1_1_SHIFT                     0  /* DSP3_ZM_1 - [7:0] */
+#define WM5100_DSP3_ZM_1_1_WIDTH                     8  /* DSP3_ZM_1 - [7:0] */
+
+/*
+ * R36867 (0x9003) - DSP3 ZM 3
+ */
+#define WM5100_DSP3_ZM_1_MASK                   0xFFFF  /* DSP3_ZM_1 - [15:0] */
+#define WM5100_DSP3_ZM_1_SHIFT                       0  /* DSP3_ZM_1 - [15:0] */
+#define WM5100_DSP3_ZM_1_WIDTH                      16  /* DSP3_ZM_1 - [15:0] */
+
+/*
+ * R38908 (0x97FC) - DSP3 ZM 2044
+ */
+#define WM5100_DSP3_ZM_1022_1_MASK              0x00FF  /* DSP3_ZM_1022 - [7:0] */
+#define WM5100_DSP3_ZM_1022_1_SHIFT                  0  /* DSP3_ZM_1022 - [7:0] */
+#define WM5100_DSP3_ZM_1022_1_WIDTH                  8  /* DSP3_ZM_1022 - [7:0] */
+
+/*
+ * R38909 (0x97FD) - DSP3 ZM 2045
+ */
+#define WM5100_DSP3_ZM_1022_MASK                0xFFFF  /* DSP3_ZM_1022 - [15:0] */
+#define WM5100_DSP3_ZM_1022_SHIFT                    0  /* DSP3_ZM_1022 - [15:0] */
+#define WM5100_DSP3_ZM_1022_WIDTH                   16  /* DSP3_ZM_1022 - [15:0] */
+
+/*
+ * R38910 (0x97FE) - DSP3 ZM 2046
+ */
+#define WM5100_DSP3_ZM_END_1_MASK               0x00FF  /* DSP3_ZM_END - [7:0] */
+#define WM5100_DSP3_ZM_END_1_SHIFT                   0  /* DSP3_ZM_END - [7:0] */
+#define WM5100_DSP3_ZM_END_1_WIDTH                   8  /* DSP3_ZM_END - [7:0] */
+
+/*
+ * R38911 (0x97FF) - DSP3 ZM 2047
+ */
+#define WM5100_DSP3_ZM_END_MASK                 0xFFFF  /* DSP3_ZM_END - [15:0] */
+#define WM5100_DSP3_ZM_END_SHIFT                     0  /* DSP3_ZM_END - [15:0] */
+#define WM5100_DSP3_ZM_END_WIDTH                    16  /* DSP3_ZM_END - [15:0] */
+
+int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg);
+int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg);
+
+extern u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1];
+
+#endif
index db0dced7484384637f910efeaeb200211e4ce60b..55a4c830e111372f7e67768076debf56275fc3cd 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -598,6 +599,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = {
        .reg_cache_default =wm8510_reg,
 };
 
+static const struct of_device_id wm8510_of_match[] = {
+       { .compatible = "wlf,wm8510" },
+       { },
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8510_spi_probe(struct spi_device *spi)
 {
@@ -628,6 +634,7 @@ static struct spi_driver wm8510_spi_driver = {
        .driver = {
                .name   = "wm8510",
                .owner  = THIS_MODULE,
+               .of_match_table = wm8510_of_match,
        },
        .probe          = wm8510_spi_probe,
        .remove         = __devexit_p(wm8510_spi_remove),
@@ -671,6 +678,7 @@ static struct i2c_driver wm8510_i2c_driver = {
        .driver = {
                .name = "wm8510-codec",
                .owner = THIS_MODULE,
+               .of_match_table = wm8510_of_match,
        },
        .probe =    wm8510_i2c_probe,
        .remove =   __devexit_p(wm8510_i2c_remove),
index 4fd4d8dca0fc0af31439371fbab9040794162095..5355a7a944f7cd3f0b3217e4c8ffb824dbe43029 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -84,7 +85,7 @@ static const char *wm8523_zd_count_text[] = {
 static const struct soc_enum wm8523_zc_count =
        SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text);
 
-static const struct snd_kcontrol_new wm8523_snd_controls[] = {
+static const struct snd_kcontrol_new wm8523_controls[] = {
 SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
                 0, 448, 0, dac_tlv),
 SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0),
@@ -101,22 +102,11 @@ SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
 SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
 };
 
-static const struct snd_soc_dapm_route intercon[] = {
+static const struct snd_soc_dapm_route wm8523_dapm_routes[] = {
        { "LINEVOUTL", NULL, "DAC" },
        { "LINEVOUTR", NULL, "DAC" },
 };
 
-static int wm8523_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8523_dapm_widgets,
-                                 ARRAY_SIZE(wm8523_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
-       return 0;
-}
-
 static struct {
        int value;
        int ratio;
@@ -479,10 +469,6 @@ static int wm8523_probe(struct snd_soc_codec *codec)
        /* Bias level configuration will have done an extra enable */
        regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
 
-       snd_soc_add_controls(codec, wm8523_snd_controls,
-                            ARRAY_SIZE(wm8523_snd_controls));
-       wm8523_add_widgets(codec);
-
        return 0;
 
 err_enable:
@@ -512,6 +498,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = {
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8523_reg,
        .volatile_register = wm8523_volatile_register,
+
+       .controls = wm8523_controls,
+       .num_controls = ARRAY_SIZE(wm8523_controls),
+       .dapm_widgets = wm8523_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets),
+       .dapm_routes = wm8523_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes),
+};
+
+static const struct of_device_id wm8523_of_match[] = {
+       { .compatible = "wlf,wm8523" },
+       { },
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -551,8 +549,9 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
 
 static struct i2c_driver wm8523_i2c_driver = {
        .driver = {
-               .name = "wm8523-codec",
+               .name = "wm8523",
                .owner = THIS_MODULE,
+               .of_match_table = wm8523_of_match,
        },
        .probe =    wm8523_i2c_probe,
        .remove =   __devexit_p(wm8523_i2c_remove),
index 4bbc0a79f01edf0139f6c1d10c587a82ff778fa9..4664c3a76c78967daf05cdb6c8bb0d67d91aad9e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -907,6 +908,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
        .reg_cache_default = wm8580_reg,
 };
 
+static const struct of_device_id wm8580_of_match[] = {
+       { .compatible = "wlf,wm8580" },
+       { },
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static int wm8580_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
@@ -943,8 +949,9 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
 
 static struct i2c_driver wm8580_i2c_driver = {
        .driver = {
-               .name = "wm8580-codec",
+               .name = "wm8580",
                .owner = THIS_MODULE,
+               .of_match_table = wm8580_of_match,
        },
        .probe =    wm8580_i2c_probe,
        .remove =   wm8580_i2c_remove,
index a537e4af6ae74efe7950d6a1806ee3942118a834..8457d3cb59622555a46c7af944ac844a56eaa24c 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -414,6 +415,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = {
        .num_dapm_routes = ARRAY_SIZE(wm8711_intercon),
 };
 
+static const struct of_device_id wm8711_of_match[] = {
+       { .compatible = "wlf,wm8711", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, wm8711_of_match);
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8711_spi_probe(struct spi_device *spi)
 {
@@ -443,8 +450,9 @@ static int __devexit wm8711_spi_remove(struct spi_device *spi)
 
 static struct spi_driver wm8711_spi_driver = {
        .driver = {
-               .name   = "wm8711-codec",
+               .name   = "wm8711",
                .owner  = THIS_MODULE,
+               .of_match_table = wm8711_of_match,
        },
        .probe          = wm8711_spi_probe,
        .remove         = __devexit_p(wm8711_spi_remove),
@@ -487,8 +495,9 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
 
 static struct i2c_driver wm8711_i2c_driver = {
        .driver = {
-               .name = "wm8711-codec",
+               .name = "wm8711",
                .owner = THIS_MODULE,
+               .of_match_table = wm8711_of_match,
        },
        .probe =    wm8711_i2c_probe,
        .remove =   __devexit_p(wm8711_i2c_remove),
index 86d4718d3a76055e46c1982e526855905c871ac9..04b027efd5c003df25769eb92e3ff7a74317a975 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -269,6 +270,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = {
        .num_dapm_routes = ARRAY_SIZE(wm8728_intercon),
 };
 
+static const struct of_device_id wm8728_of_match[] = {
+       { .compatible = "wlf,wm8728", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, wm8728_of_match);
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8728_spi_probe(struct spi_device *spi)
 {
@@ -298,8 +305,9 @@ static int __devexit wm8728_spi_remove(struct spi_device *spi)
 
 static struct spi_driver wm8728_spi_driver = {
        .driver = {
-               .name   = "wm8728-codec",
+               .name   = "wm8728",
                .owner  = THIS_MODULE,
+               .of_match_table = wm8728_of_match,
        },
        .probe          = wm8728_spi_probe,
        .remove         = __devexit_p(wm8728_spi_remove),
@@ -342,8 +350,9 @@ MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
 
 static struct i2c_driver wm8728_i2c_driver = {
        .driver = {
-               .name = "wm8728-codec",
+               .name = "wm8728",
                .owner = THIS_MODULE,
+               .of_match_table = wm8728_of_match,
        },
        .probe =    wm8728_i2c_probe,
        .remove =   __devexit_p(wm8728_i2c_remove),
index 76b4361e9b8042c112a32b14b290304e17761604..f76b6fc6766a1f6e8e855801823ffb7c2c8221f0 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -607,6 +608,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
        .num_dapm_routes = ARRAY_SIZE(wm8731_intercon),
 };
 
+static const struct of_device_id wm8731_of_match[] = {
+       { .compatible = "wlf,wm8731", },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, wm8731_of_match);
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8731_spi_probe(struct spi_device *spi)
 {
@@ -638,6 +646,7 @@ static struct spi_driver wm8731_spi_driver = {
        .driver = {
                .name   = "wm8731",
                .owner  = THIS_MODULE,
+               .of_match_table = wm8731_of_match,
        },
        .probe          = wm8731_spi_probe,
        .remove         = __devexit_p(wm8731_spi_remove),
@@ -682,6 +691,7 @@ static struct i2c_driver wm8731_i2c_driver = {
        .driver = {
                .name = "wm8731",
                .owner = THIS_MODULE,
+               .of_match_table = wm8731_of_match,
        },
        .probe =    wm8731_i2c_probe,
        .remove =   __devexit_p(wm8731_i2c_remove),
index 30c67d06a9043988f1a84ed6f4780b7c2502dbc3..f6aef58845c2dc31880529cdaa9510a96735e334 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -634,6 +635,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = {
        .reg_cache_default = wm8737_reg,
 };
 
+static const struct of_device_id wm8737_of_match[] = {
+       { .compatible = "wlf,wm8737", },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, wm8737_of_match);
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
@@ -673,6 +681,7 @@ static struct i2c_driver wm8737_i2c_driver = {
        .driver = {
                .name = "wm8737",
                .owner = THIS_MODULE,
+               .of_match_table = wm8737_of_match,
        },
        .probe =    wm8737_i2c_probe,
        .remove =   __devexit_p(wm8737_i2c_remove),
@@ -711,6 +720,7 @@ static struct spi_driver wm8737_spi_driver = {
        .driver = {
                .name   = "wm8737",
                .owner  = THIS_MODULE,
+               .of_match_table = wm8737_of_match,
        },
        .probe          = wm8737_spi_probe,
        .remove         = __devexit_p(wm8737_spi_remove),
index 25af901fe8133029e7efe35914c07e02105e4085..78c9e5ab3fa54cf35c20e23b2218ccae1ccbe69b 100644 (file)
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -422,17 +424,35 @@ static int wm8741_probe(struct snd_soc_codec *codec)
 {
        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
+               wm8741->supplies[i].supply = wm8741_supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies),
+                                wm8741->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               goto err;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
+                                   wm8741->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_get;
+       }
 
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               return ret;
+               goto err_enable;
        }
 
        ret = wm8741_reset(codec);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset\n");
-               return ret;
+               goto err_enable;
        }
 
        /* Change some default settings - latch VU */
@@ -451,58 +471,61 @@ static int wm8741_probe(struct snd_soc_codec *codec)
 
        dev_dbg(codec->dev, "Successful registration\n");
        return ret;
+
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+err_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+err:
+       return ret;
+}
+
+static int wm8741_remove(struct snd_soc_codec *codec)
+{
+       struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
+
+       regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+       regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+
+       return 0;
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {
        .probe =        wm8741_probe,
+       .remove =       wm8741_remove,
        .resume =       wm8741_resume,
        .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8741_reg_defaults,
 };
 
+static const struct of_device_id wm8741_of_match[] = {
+       { .compatible = "wlf,wm8741", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, wm8741_of_match);
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static int wm8741_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm8741_priv *wm8741;
-       int ret, i;
+       int ret;
 
        wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
        if (wm8741 == NULL)
                return -ENOMEM;
 
-       for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
-               wm8741->supplies[i].supply = wm8741_supply_names[i];
-
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies),
-                                wm8741->supplies);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
-       }
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
-                                   wm8741->supplies);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_get;
-       }
-
        i2c_set_clientdata(i2c, wm8741);
        wm8741->control_type = SND_SOC_I2C;
 
-       ret =  snd_soc_register_codec(&i2c->dev,
-                       &soc_codec_dev_wm8741, &wm8741_dai, 1);
-       if (ret < 0)
-               goto err_enable;
-       return ret;
+       ret = snd_soc_register_codec(&i2c->dev,
+                                    &soc_codec_dev_wm8741, &wm8741_dai, 1);
+       if (ret != 0)
+               goto err;
 
-err_enable:
-       regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+       return ret;
 
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
 err:
        kfree(wm8741);
        return ret;
@@ -510,10 +533,7 @@ err:
 
 static int wm8741_i2c_remove(struct i2c_client *client)
 {
-       struct wm8741_priv *wm8741 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
        kfree(i2c_get_clientdata(client));
        return 0;
 }
@@ -526,8 +546,9 @@ MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
 
 static struct i2c_driver wm8741_i2c_driver = {
        .driver = {
-               .name = "wm8741-codec",
+               .name = "wm8741",
                .owner = THIS_MODULE,
+               .of_match_table = wm8741_of_match,
        },
        .probe =    wm8741_i2c_probe,
        .remove =   wm8741_i2c_remove,
@@ -535,6 +556,44 @@ static struct i2c_driver wm8741_i2c_driver = {
 };
 #endif
 
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8741_spi_probe(struct spi_device *spi)
+{
+       struct wm8741_priv *wm8741;
+       int ret;
+
+       wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
+       if (wm8741 == NULL)
+               return -ENOMEM;
+
+       wm8741->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8741);
+
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8741, &wm8741_dai, 1);
+       if (ret < 0)
+               kfree(wm8741);
+       return ret;
+}
+
+static int __devexit wm8741_spi_remove(struct spi_device *spi)
+{
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
+       return 0;
+}
+
+static struct spi_driver wm8741_spi_driver = {
+       .driver = {
+               .name   = "wm8741",
+               .owner  = THIS_MODULE,
+               .of_match_table = wm8741_of_match,
+       },
+       .probe          = wm8741_spi_probe,
+       .remove         = __devexit_p(wm8741_spi_remove),
+};
+#endif /* CONFIG_SPI_MASTER */
+
 static int __init wm8741_modinit(void)
 {
        int ret = 0;
@@ -544,6 +603,13 @@ static int __init wm8741_modinit(void)
        if (ret != 0)
                pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
 #endif
+#if defined(CONFIG_SPI_MASTER)
+       ret = spi_register_driver(&wm8741_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n",
+                      ret);
+       }
+#endif
 
        return ret;
 }
@@ -551,6 +617,9 @@ module_init(wm8741_modinit);
 
 static void __exit wm8741_exit(void)
 {
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8741_spi_driver);
+#endif
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8741_i2c_driver);
 #endif
index d0003cc3bcd66cf16336bec69cc0f75b4de97a56..15f03721ec6ff3fd23da9117cd40453e328e0d9b 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -751,6 +752,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
        .reg_cache_default = wm8750_reg,
 };
 
+static const struct of_device_id wm8750_of_match[] = {
+       { .compatible = "wlf,wm8750", },
+       { .compatible = "wlf,wm8987", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, wm8750_of_match);
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8750_spi_probe(struct spi_device *spi)
 {
@@ -787,8 +795,9 @@ MODULE_DEVICE_TABLE(spi, wm8750_spi_ids);
 
 static struct spi_driver wm8750_spi_driver = {
        .driver = {
-               .name   = "wm8750-codec",
+               .name   = "wm8750",
                .owner  = THIS_MODULE,
+               .of_match_table = wm8750_of_match,
        },
        .id_table       = wm8750_spi_ids,
        .probe          = wm8750_spi_probe,
@@ -833,8 +842,9 @@ MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
 
 static struct i2c_driver wm8750_i2c_driver = {
        .driver = {
-               .name = "wm8750-codec",
+               .name = "wm8750",
                .owner = THIS_MODULE,
+               .of_match_table = wm8750_of_match,
        },
        .probe =    wm8750_i2c_probe,
        .remove =   __devexit_p(wm8750_i2c_remove),
index aa091a0d81873b9f09ceeb30bf7dcd46f6d05cd1..a9504710bb692e806655e785e5f35121ecf4afc1 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
@@ -1490,6 +1491,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
        .reg_cache_default = wm8753_reg,
 };
 
+static const struct of_device_id wm8753_of_match[] = {
+       { .compatible = "wlf,wm8753", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, wm8753_of_match);
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8753_spi_probe(struct spi_device *spi)
 {
@@ -1519,8 +1526,9 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi)
 
 static struct spi_driver wm8753_spi_driver = {
        .driver = {
-               .name   = "wm8753-codec",
+               .name   = "wm8753",
                .owner  = THIS_MODULE,
+               .of_match_table = wm8753_of_match,
        },
        .probe          = wm8753_spi_probe,
        .remove         = __devexit_p(wm8753_spi_remove),
@@ -1563,8 +1571,9 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
 
 static struct i2c_driver wm8753_i2c_driver = {
        .driver = {
-               .name = "wm8753-codec",
+               .name = "wm8753",
                .owner = THIS_MODULE,
+               .of_match_table = wm8753_of_match,
        },
        .probe =    wm8753_i2c_probe,
        .remove =   __devexit_p(wm8753_i2c_remove),
index 19b92baa9e8c480c7a07b479c95d0f94f62ef4ae..aa05e6507f844a2ac90c970e939a92efc9de0ff7 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/of_device.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
@@ -684,6 +685,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
        .reg_cache_default = wm8770_reg_defs
 };
 
+static const struct of_device_id wm8770_of_match[] = {
+       { .compatible = "wlf,wm8770", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, wm8770_of_match);
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8770_spi_probe(struct spi_device *spi)
 {
@@ -715,6 +722,7 @@ static struct spi_driver wm8770_spi_driver = {
        .driver = {
                .name = "wm8770",
                .owner = THIS_MODULE,
+               .of_match_table = wm8770_of_match,
        },
        .probe = wm8770_spi_probe,
        .remove = __devexit_p(wm8770_spi_remove)
index 8e7953b1b790161a8a394b0b10a7b7d8a160487a..00d8846fae8ae67de92be460d4233fb4b4a431d5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
@@ -215,8 +216,6 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
        int ratio_shift, master;
        int i;
 
-       iface = 0;
-
        switch (dai->driver->id) {
        case WM8776_DAI_DAC:
                iface_reg = WM8776_DACIFCTRL;
@@ -232,20 +231,23 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-
        /* Set word length */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (snd_pcm_format_width(params_format(params))) {
+       case 16:
+               iface = 0;
+       case 20:
+               iface = 0x10;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
-               iface |= 0x10;
+       case 24:
+               iface = 0x20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-               iface |= 0x20;
-               break;
-       case SNDRV_PCM_FORMAT_S32_LE:
-               iface |= 0x30;
+       case 32:
+               iface = 0x30;
                break;
+       default:
+               dev_err(codec->dev, "Unsupported sample size: %i\n",
+                       snd_pcm_format_width(params_format(params)));
+               return -EINVAL;
        }
 
        /* Only need to set MCLK/LRCLK ratio if we're master */
@@ -320,11 +322,6 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
-                     SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
-                     SNDRV_PCM_RATE_96000)
-
-
 #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
@@ -349,7 +346,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = {
                        .stream_name = "Playback",
                        .channels_min = 2,
                        .channels_max = 2,
-                       .rates = WM8776_RATES,
+                       .rates = SNDRV_PCM_RATE_CONTINUOUS,
+                       .rate_min = 32000,
+                       .rate_max = 192000,
                        .formats = WM8776_FORMATS,
                },
                .ops = &wm8776_dac_ops,
@@ -361,7 +360,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = {
                        .stream_name = "Capture",
                        .channels_min = 2,
                        .channels_max = 2,
-                       .rates = WM8776_RATES,
+                       .rates = SNDRV_PCM_RATE_CONTINUOUS,
+                       .rate_min = 32000,
+                       .rate_max = 96000,
                        .formats = WM8776_FORMATS,
                },
                .ops = &wm8776_adc_ops,
@@ -452,6 +453,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = {
        .reg_cache_default = wm8776_reg,
 };
 
+static const struct of_device_id wm8776_of_match[] = {
+       { .compatible = "wlf,wm8776", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, wm8776_of_match);
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8776_spi_probe(struct spi_device *spi)
 {
@@ -481,8 +488,9 @@ static int __devexit wm8776_spi_remove(struct spi_device *spi)
 
 static struct spi_driver wm8776_spi_driver = {
        .driver = {
-               .name   = "wm8776-codec",
+               .name   = "wm8776",
                .owner  = THIS_MODULE,
+               .of_match_table = wm8776_of_match,
        },
        .probe          = wm8776_spi_probe,
        .remove         = __devexit_p(wm8776_spi_remove),
@@ -525,8 +533,9 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
 
 static struct i2c_driver wm8776_i2c_driver = {
        .driver = {
-               .name = "wm8776-codec",
+               .name = "wm8776",
                .owner = THIS_MODULE,
+               .of_match_table = wm8776_of_match,
        },
        .probe =    wm8776_i2c_probe,
        .remove =   __devexit_p(wm8776_i2c_remove),
index 9a5e67c5a6bdf9f2cc7fc5a23b49a8c76a0f462e..9ee072b859751ac16b3163c0f5a33833e5eb878a 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/of_device.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -717,6 +718,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
        .volatile_register = wm8804_volatile
 };
 
+static const struct of_device_id wm8804_of_match[] = {
+       { .compatible = "wlf,wm8804", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, wm8804_of_match);
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8804_spi_probe(struct spi_device *spi)
 {
@@ -748,6 +755,7 @@ static struct spi_driver wm8804_spi_driver = {
        .driver = {
                .name = "wm8804",
                .owner = THIS_MODULE,
+               .of_match_table = wm8804_of_match,
        },
        .probe = wm8804_spi_probe,
        .remove = __devexit_p(wm8804_spi_remove)
@@ -792,6 +800,7 @@ static struct i2c_driver wm8804_i2c_driver = {
        .driver = {
                .name = "wm8804",
                .owner = THIS_MODULE,
+               .of_match_table = wm8804_of_match,
        },
        .probe = wm8804_i2c_probe,
        .remove = __devexit_p(wm8804_i2c_remove),
index b085575d4aa542ac0cc8bf9c4a1b908c2eafdfe9..9fc8f4c0a9a91acbe52f5321f60008d90371ef51 100644 (file)
@@ -50,7 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
 struct wm8904_priv {
 
        enum wm8904_type devtype;
-       void *control_data;
 
        struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
 
@@ -2540,7 +2539,6 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
 
        wm8904->devtype = id->driver_data;
        i2c_set_clientdata(i2c, wm8904);
-       wm8904->control_data = i2c;
        wm8904->pdata = i2c->dev.platform_data;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 056daa0010f99238ce4edc1f34d0a6bfe959f655..7e0f54c60d26369a0657a94bbdf5230fb4a6fc81 100644 (file)
@@ -43,7 +43,6 @@
 struct wm8940_priv {
        unsigned int sysclk;
        enum snd_soc_control_type control_type;
-       void *control_data;
 };
 
 static u16 wm8940_reg_defaults[] = {
@@ -693,7 +692,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
        int ret;
        u16 reg;
 
-       codec->control_data = wm8940->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -758,7 +756,6 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8940);
-       wm8940->control_data = i2c;
        wm8940->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 4393394b7bc14bc1eaf5c724ddce602779fc8c9c..831c20f897780dca25e7ce6e70fcf7405d2a8112 100644 (file)
@@ -72,7 +72,6 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
 
 struct wm8960_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
        int (*set_bias_level)(struct snd_soc_codec *,
                              enum snd_soc_bias_level level);
        struct snd_soc_dapm_widget *lout1;
@@ -925,7 +924,6 @@ static int wm8960_probe(struct snd_soc_codec *codec)
        u16 reg;
 
        wm8960->set_bias_level = wm8960_set_bias_level_out3;
-       codec->control_data = wm8960->control_data;
 
        if (!pdata) {
                dev_warn(codec->dev, "No platform data supplied\n");
@@ -1015,7 +1013,6 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm8960);
        wm8960->control_type = SND_SOC_I2C;
-       wm8960->control_data = i2c;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8960, &wm8960_dai, 1);
index d2c315fa1b9b8b8ed379dcce84a85511a45116f8..74ebbfa89a3074633938e289bd6d29f00c8d0f8d 100644 (file)
@@ -63,6 +63,8 @@ struct wm8962_priv {
        int fll_fref;
        int fll_fout;
 
+       u16 dsp2_ena;
+
        struct delayed_work mic_work;
        struct snd_soc_jack *jack;
 
@@ -837,7 +839,7 @@ static const struct wm8962_reg_access {
        [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40    - SPKOUTL volume */
        [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41    - SPKOUTR volume */
 
-       [47] = { 0x000F, 0x0000, 0x0000 }, /* R47    - Thermal Shutdown Status */
+       [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 */
@@ -965,7 +967,7 @@ static const struct wm8962_reg_access {
        [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, 0x0000 }, /* R1037  - DSP2_ExecControl */
+       [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 */
@@ -1986,6 +1988,122 @@ static const unsigned int classd_tlv[] = {
 };
 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 
+static int wm8962_dsp2_write_config(struct snd_soc_codec *codec)
+{
+       return 0;
+}
+
+static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val)
+{
+       u16 adcl = snd_soc_read(codec, WM8962_LEFT_ADC_VOLUME);
+       u16 adcr = snd_soc_read(codec, WM8962_RIGHT_ADC_VOLUME);
+       u16 dac = snd_soc_read(codec, WM8962_ADC_DAC_CONTROL_1);
+
+       /* Mute the ADCs and DACs */
+       snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, 0);
+       snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, WM8962_ADC_VU);
+       snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
+                           WM8962_DAC_MUTE, WM8962_DAC_MUTE);
+
+       snd_soc_write(codec, WM8962_SOUNDSTAGE_ENABLES_0, val);
+
+       /* Restore the ADCs and DACs */
+       snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, adcl);
+       snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, adcr);
+       snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
+                           WM8962_DAC_MUTE, dac);
+
+       return 0;
+}
+
+static int wm8962_dsp2_start(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+       wm8962_dsp2_write_config(codec);
+
+       snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_RUNR);
+
+       wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena);
+
+       return 0;
+}
+
+static int wm8962_dsp2_stop(struct snd_soc_codec *codec)
+{
+       wm8962_dsp2_set_enable(codec, 0);
+
+       snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_STOP);
+
+       return 0;
+}
+
+#define WM8962_DSP2_ENABLE(xname, xshift) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .info = wm8962_dsp2_ena_info, \
+       .get = wm8962_dsp2_ena_get, .put = wm8962_dsp2_ena_put, \
+       .private_value = xshift }
+
+static int wm8962_dsp2_ena_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+
+       return 0;
+}
+
+static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       int shift = kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift);
+
+       return 0;
+}
+
+static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       int shift = kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int old = wm8962->dsp2_ena;
+       int ret = 0;
+       int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) &
+               WM8962_DSP2_ENA;
+
+       mutex_lock(&codec->mutex);
+
+       if (ucontrol->value.integer.value[0])
+               wm8962->dsp2_ena |= 1 << shift;
+       else
+               wm8962->dsp2_ena &= ~(1 << shift);
+
+       if (wm8962->dsp2_ena == old)
+               goto out;
+
+       ret = 1;
+
+       if (dsp2_running) {
+               if (wm8962->dsp2_ena)
+                       wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena);
+               else
+                       wm8962_dsp2_stop(codec);
+       }
+
+out:
+       mutex_unlock(&codec->mutex);
+
+       return ret;
+}
+
 /* The VU bits for the headphones are in a different register to the mute
  * bits and only take effect on the PGA if it is actually powered.
  */
@@ -2049,6 +2167,14 @@ static const char *cap_hpf_mode_text[] = {
 static const struct soc_enum cap_hpf_mode =
        SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text);
 
+
+static const char *cap_lhpf_mode_text[] = {
+       "LPF", "HPF"
+};
+
+static const struct soc_enum cap_lhpf_mode =
+       SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text);
+
 static const struct snd_kcontrol_new wm8962_snd_controls[] = {
 SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1),
 
@@ -2077,6 +2203,8 @@ SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME,
 SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1),
 SOC_ENUM("Capture HPF Mode", cap_hpf_mode),
 SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0),
+SOC_SINGLE("Capture LHPF Switch", WM8962_LHPF1, 0, 1, 0),
+SOC_ENUM("Capture LHPF Mode", cap_lhpf_mode),
 
 SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
                 WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv),
@@ -2134,6 +2262,11 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23,
                 WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv),
 SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23,
                 WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv),
+
+WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT),
+WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT),
+WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT),
+WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT),
 };
 
 static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
@@ -2395,6 +2528,31 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
        }
 }
 
+static int dsp2_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);
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               if (wm8962->dsp2_ena)
+                       wm8962_dsp2_start(codec);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               if (wm8962->dsp2_ena)
+                       wm8962_dsp2_stop(codec);
+               break;
+
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static const char *st_text[] = { "None", "Right", "Left" };
 
 static const struct soc_enum str_enum =
@@ -2509,7 +2667,7 @@ SND_SOC_DAPM_INPUT("IN4R"),
 SND_SOC_DAPM_INPUT("Beep"),
 SND_SOC_DAPM_INPUT("DMICDAT"),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
 SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
@@ -2517,6 +2675,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
 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),
+SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT,
+                     WM8962_DSP2_ENA_SHIFT, 0, dsp2_event,
+                     SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
 SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
                   inpgal, ARRAY_SIZE(inpgal)),
@@ -2527,7 +2688,7 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0,
 SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0,
                   mixinr, ARRAY_SIZE(mixinr)),
 
-SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
+SND_SOC_DAPM_AIF_IN("DMIC_ENA", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
 
 SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0),
 SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0),
@@ -2606,17 +2767,19 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
 
        { "MICBIAS", NULL, "SYSCLK" },
 
-       { "DMIC", NULL, "DMICDAT" },
+       { "DMIC_ENA", NULL, "DMICDAT" },
 
        { "ADCL", NULL, "SYSCLK" },
        { "ADCL", NULL, "TOCLK" },
        { "ADCL", NULL, "MIXINL" },
-       { "ADCL", NULL, "DMIC" },
+       { "ADCL", NULL, "DMIC_ENA" },
+       { "ADCL", NULL, "DSP2" },
 
        { "ADCR", NULL, "SYSCLK" },
        { "ADCR", NULL, "TOCLK" },
        { "ADCR", NULL, "MIXINR" },
-       { "ADCR", NULL, "DMIC" },
+       { "ADCR", NULL, "DMIC_ENA" },
+       { "ADCR", NULL, "DSP2" },
 
        { "STL", "Left", "ADCL" },
        { "STL", "Right", "ADCR" },
@@ -2628,11 +2791,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
        { "DACL", NULL, "TOCLK" },
        { "DACL", NULL, "Beep" },
        { "DACL", NULL, "STL" },
+       { "DACL", NULL, "DSP2" },
 
        { "DACR", NULL, "SYSCLK" },
        { "DACR", NULL, "TOCLK" },
        { "DACR", NULL, "Beep" },
        { "DACR", NULL, "STR" },
+       { "DACR", NULL, "DSP2" },
 
        { "HPMIXL", "IN4L Switch", "IN4L" },
        { "HPMIXL", "IN4R Switch", "IN4R" },
@@ -3058,9 +3223,9 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        int aif0 = 0;
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-       case SND_SOC_DAIFMT_DSP_A:
-               aif0 |= WM8962_LRCLK_INV;
        case SND_SOC_DAIFMT_DSP_B:
+               aif0 |= WM8962_LRCLK_INV | 3;
+       case SND_SOC_DAIFMT_DSP_A:
                aif0 |= 3;
 
                switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -3403,12 +3568,16 @@ static irqreturn_t wm8962_irq(int irq, void *data)
        struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
        int mask;
        int active;
+       int reg;
 
        mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
 
        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);
 
@@ -3420,9 +3589,21 @@ static irqreturn_t wm8962_irq(int irq, void *data)
        if (active & WM8962_FIFOS_ERR_EINT)
                dev_err(codec->dev, "FIFO error\n");
 
-       if (active & WM8962_TEMP_SHUT_EINT)
+       if (active & WM8962_TEMP_SHUT_EINT) {
                dev_crit(codec->dev, "Thermal shutdown\n");
 
+               reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS);
+
+               if (reg & WM8962_TEMP_ERR_HP)
+                       dev_crit(codec->dev, "Headphone thermal error\n");
+               if (reg & WM8962_TEMP_WARN_HP)
+                       dev_crit(codec->dev, "Headphone thermal warning\n");
+               if (reg & WM8962_TEMP_ERR_SPK)
+                       dev_crit(codec->dev, "Speaker thermal error\n");
+               if (reg & WM8962_TEMP_WARN_SPK)
+                       dev_crit(codec->dev, "Speaker thermal warning\n");
+       }
+
        if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
                dev_dbg(codec->dev, "Microphone event detected\n");
 
index 85e3e630e763ca841ecd51e40cd66ab7733bcf8d..41ca4d9ac20c0dff5aeb5d2666cae916237a0144 100644 (file)
@@ -52,7 +52,6 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
 /* codec private data */
 struct wm8978_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
        unsigned int f_pllout;
        unsigned int f_mclk;
        unsigned int f_256fs;
@@ -955,7 +954,6 @@ static int wm8978_probe(struct snd_soc_codec *codec)
         * default hardware setting
         */
        wm8978->sysclk = WM8978_PLL;
-       codec->control_data = wm8978->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -1016,7 +1014,6 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8978);
-       wm8978->control_data = i2c;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8978, &wm8978_dai, 1);
index 6e85b8869af7171882d5476137ed63004402bef1..eec8e143511665a538c6950a4f679ad217aad827 100644 (file)
@@ -847,6 +847,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event,
                    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, NULL, 0),
 
 SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0),
 SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0),
@@ -880,6 +881,9 @@ SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route routes[] = {
+       { "MICBIAS1", NULL, "VMID" },
+       { "MICBIAS2", NULL, "VMID" },
+
        { "ADCL", NULL, "CLK_SYS" },
        { "ADCL", NULL, "CLK_DSP" },
        { "ADCR", NULL, "CLK_SYS" },
@@ -1433,7 +1437,8 @@ static int wm8993_probe(struct snd_soc_codec *codec)
        int ret, i, val;
 
        wm8993->hubs_data.hp_startup_mode = 1;
-       wm8993->hubs_data.dcs_codes = -2;
+       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);
index a87adbd05ee11151535bb3231122655c0c226525..df5a8b9a250f47362cc8e03a0f65e8486d5fe188 100644 (file)
@@ -1073,8 +1073,8 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = {
        { 0x0000, 0x0000 }, /* R1069 */
        { 0x0000, 0x0000 }, /* R1070 */
        { 0x0000, 0x0000 }, /* R1071 */
-       { 0x0000, 0x0000 }, /* R1072 */
-       { 0x0000, 0x0000 }, /* R1073 */
+       { 0x006F, 0x006F }, /* R1072  - AIF1 DAC1 Noise Gate */
+       { 0x006F, 0x006F }, /* R1073  - AIF1 DAC2 Noise Gate */
        { 0x0000, 0x0000 }, /* R1074 */
        { 0x0000, 0x0000 }, /* R1075 */
        { 0x0000, 0x0000 }, /* R1076 */
@@ -1329,7 +1329,7 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = {
        { 0x0000, 0x0000 }, /* R1325 */
        { 0x0000, 0x0000 }, /* R1326 */
        { 0x0000, 0x0000 }, /* R1327 */
-       { 0x0000, 0x0000 }, /* R1328 */
+       { 0x006F, 0x006F }, /* R1328  - AIF2 DAC Noise Gate */
        { 0x0000, 0x0000 }, /* R1329 */
        { 0x0000, 0x0000 }, /* R1330 */
        { 0x0000, 0x0000 }, /* R1331 */
@@ -1635,8 +1635,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
        0x0000,     /* R58    - MICBIAS */
        0x000D,     /* R59    - LDO 1 */
        0x0003,     /* R60    - LDO 2 */
-       0x0000,     /* R61 */
-       0x0000,     /* R62 */
+       0x0039,     /* R61    - MICBIAS1 */
+       0x0039,     /* R62    - MICBIAS2 */
        0x0000,     /* R63 */
        0x0000,     /* R64 */
        0x0000,     /* R65 */
@@ -2646,8 +2646,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
        0x0000,     /* R1069 */
        0x0000,     /* R1070 */
        0x0000,     /* R1071 */
-       0x0000,     /* R1072 */
-       0x0000,     /* R1073 */
+       0x0068,     /* R1072  - AIF1 DAC1 Noise Gate */
+       0x0068,     /* R1073  - AIF1 DAC2 Noise Gate */
        0x0000,     /* R1074 */
        0x0000,     /* R1075 */
        0x0000,     /* R1076 */
@@ -2902,7 +2902,7 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
        0x0000,     /* R1325 */
        0x0000,     /* R1326 */
        0x0000,     /* R1327 */
-       0x0000,     /* R1328 */
+       0x0068,     /* R1328  - AIF2 DAC Noise Gate */
        0x0000,     /* R1329 */
        0x0000,     /* R1330 */
        0x0000,     /* R1331 */
index b393f9fac97a5e75a8bc1b44cb3c6f898482cad3..e5372675123d32ea070b3edc91a2a8fd0e626cfd 100644 (file)
@@ -107,6 +107,7 @@ static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg)
        case WM8994_LDO_2:
        case WM8958_DSP2_EXECCONTROL:
        case WM8958_MIC_DETECT_3:
+       case WM8994_DC_SERVO_4E:
                return 1;
        default:
                return 0;
@@ -281,6 +282,7 @@ static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
 static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
 static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0);
 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
 
 #define WM8994_DRC_SWITCH(xname, reg, shift) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -660,8 +662,45 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0,
               eq_tlv),
 };
 
+static const char *wm8958_ng_text[] = {
+       "30ms", "125ms", "250ms", "500ms",
+};
+
+static const struct soc_enum wm8958_aif1dac1_ng_hold =
+       SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE,
+                       WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text);
+
+static const struct soc_enum wm8958_aif1dac2_ng_hold =
+       SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE,
+                       WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text);
+
+static const struct soc_enum wm8958_aif2dac_ng_hold =
+       SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE,
+                       WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text);
+
 static const struct snd_kcontrol_new wm8958_snd_controls[] = {
 SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv),
+
+SOC_SINGLE("AIF1DAC1 Noise Gate Switch", WM8958_AIF1_DAC1_NOISE_GATE,
+          WM8958_AIF1DAC1_NG_ENA_SHIFT, 1, 0),
+SOC_ENUM("AIF1DAC1 Noise Gate Hold Time", wm8958_aif1dac1_ng_hold),
+SOC_SINGLE_TLV("AIF1DAC1 Noise Gate Threshold Volume",
+              WM8958_AIF1_DAC1_NOISE_GATE, WM8958_AIF1DAC1_NG_THR_SHIFT,
+              7, 1, ng_tlv),
+
+SOC_SINGLE("AIF1DAC2 Noise Gate Switch", WM8958_AIF1_DAC2_NOISE_GATE,
+          WM8958_AIF1DAC2_NG_ENA_SHIFT, 1, 0),
+SOC_ENUM("AIF1DAC2 Noise Gate Hold Time", wm8958_aif1dac2_ng_hold),
+SOC_SINGLE_TLV("AIF1DAC2 Noise Gate Threshold Volume",
+              WM8958_AIF1_DAC2_NOISE_GATE, WM8958_AIF1DAC2_NG_THR_SHIFT,
+              7, 1, ng_tlv),
+
+SOC_SINGLE("AIF2DAC Noise Gate Switch", WM8958_AIF2_DAC_NOISE_GATE,
+          WM8958_AIF2DAC_NG_ENA_SHIFT, 1, 0),
+SOC_ENUM("AIF2DAC Noise Gate Hold Time", wm8958_aif2dac_ng_hold),
+SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume",
+              WM8958_AIF2_DAC_NOISE_GATE, WM8958_AIF2DAC_NG_THR_SHIFT,
+              7, 1, ng_tlv),
 };
 
 static int clk_sys_event(struct snd_soc_dapm_widget *w,
@@ -681,6 +720,97 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static void vmid_reference(struct snd_soc_codec *codec)
+{
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+       wm8994->vmid_refcount++;
+
+       dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n",
+               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 |
+                                   (0x11 << 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(20);
+       }
+}
+
+static void vmid_dereference(struct snd_soc_codec *codec)
+{
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+       wm8994->vmid_refcount--;
+
+       dev_dbg(codec->dev, "Dereferencing VMID, refcount is now %d\n",
+               wm8994->vmid_refcount);
+
+       if (wm8994->vmid_refcount == 0) {
+               /* Switch over to startup biases */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM8994_BIAS_SRC |
+                                   WM8994_STARTUP_BIAS_ENA |
+                                   WM8994_VMID_BUF_ENA |
+                                   WM8994_VMID_RAMP_MASK,
+                                   WM8994_BIAS_SRC |
+                                   WM8994_STARTUP_BIAS_ENA |
+                                   WM8994_VMID_BUF_ENA |
+                                   (1 << WM8994_VMID_RAMP_SHIFT));
+
+               /* Disable main biases */
+               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+                                   WM8994_BIAS_ENA |
+                                   WM8994_VMID_SEL_MASK, 0);
+
+               /* Discharge line */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+                                   WM8994_LINEOUT1_DISCH |
+                                   WM8994_LINEOUT2_DISCH,
+                                   WM8994_LINEOUT1_DISCH |
+                                   WM8994_LINEOUT2_DISCH);
+
+               msleep(5);
+
+               /* Switch off startup biases */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM8994_BIAS_SRC |
+                                   WM8994_STARTUP_BIAS_ENA |
+                                   WM8994_VMID_BUF_ENA |
+                                   WM8994_VMID_RAMP_MASK, 0);
+       }
+}
+
+static int vmid_event(struct snd_soc_dapm_widget *w,
+                     struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               vmid_reference(codec);
+               break;
+
+       case SND_SOC_DAPM_POST_PMD:
+               vmid_dereference(codec);
+               break;
+       }
+
+       return 0;
+}
+
 static void wm8994_update_class_w(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
@@ -1208,6 +1338,8 @@ SND_SOC_DAPM_INPUT("Clock"),
 
 SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev,
                      SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event,
                    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1525,6 +1657,8 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = {
 static const struct snd_soc_dapm_route wm8994_intercon[] = {
        { "AIF2DACL", NULL, "AIF2DAC Mux" },
        { "AIF2DACR", NULL, "AIF2DAC Mux" },
+       { "MICBIAS1", NULL, "VMID" },
+       { "MICBIAS2", NULL, "VMID" },
 };
 
 static const struct snd_soc_dapm_route wm8958_intercon[] = {
@@ -1629,10 +1763,12 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
                          unsigned int freq_in, unsigned int freq_out)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = codec->control_data;
        int reg_offset, ret;
        struct fll_div fll;
        u16 reg, aif1, aif2;
        unsigned long timeout;
+       bool was_enabled;
 
        aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1)
                & WM8994_AIF1CLK_ENA;
@@ -1653,6 +1789,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
                return -EINVAL;
        }
 
+       reg = snd_soc_read(codec, WM8994_FLL1_CONTROL_1 + reg_offset);
+       was_enabled = reg & WM8994_FLL1_ENA;
+
        switch (src) {
        case 0:
                /* Allow no source specification when stopping */
@@ -1719,6 +1858,21 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
 
        /* Enable (with fractional mode if required) */
        if (freq_out) {
+               /* Enable VMID if we need it */
+               if (!was_enabled) {
+                       switch (control->type) {
+                       case WM8994:
+                               vmid_reference(codec);
+                               break;
+                       case WM8958:
+                               if (wm8994->revision < 1)
+                                       vmid_reference(codec);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
                if (fll.k)
                        reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC;
                else
@@ -1736,6 +1890,20 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
                } else {
                        msleep(5);
                }
+       } else {
+               if (was_enabled) {
+                       switch (control->type) {
+                       case WM8994:
+                               vmid_dereference(codec);
+                               break;
+                       case WM8958:
+                               if (wm8994->revision < 1)
+                                       vmid_dereference(codec);
+                               break;
+                       default:
+                               break;
+                       }
+               }
        }
 
        wm8994->fll[id].in = freq_in;
@@ -1852,9 +2020,6 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                break;
 
        case SND_SOC_BIAS_PREPARE:
-               /* VMID=2x40k */
-               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                   WM8994_VMID_SEL_MASK, 0x2);
                break;
 
        case SND_SOC_BIAS_STANDBY:
@@ -1896,65 +2061,13 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                                            WM8994_LINEOUT2_DISCH,
                                            WM8994_LINEOUT1_DISCH |
                                            WM8994_LINEOUT2_DISCH);
-
-                       /* 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 |
-                                           (0x11 << 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(20);
                }
 
-               /* VMID=2x500k */
-               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                   WM8994_VMID_SEL_MASK, 0x4);
 
                break;
 
        case SND_SOC_BIAS_OFF:
                if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
-                       /* Switch over to startup biases */
-                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                           WM8994_BIAS_SRC |
-                                           WM8994_STARTUP_BIAS_ENA |
-                                           WM8994_VMID_BUF_ENA |
-                                           WM8994_VMID_RAMP_MASK,
-                                           WM8994_BIAS_SRC |
-                                           WM8994_STARTUP_BIAS_ENA |
-                                           WM8994_VMID_BUF_ENA |
-                                           (1 << WM8994_VMID_RAMP_SHIFT));
-
-                       /* Disable main biases */
-                       snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                           WM8994_BIAS_ENA |
-                                           WM8994_VMID_SEL_MASK, 0);
-
-                       /* Discharge line */
-                       snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
-                                           WM8994_LINEOUT1_DISCH |
-                                           WM8994_LINEOUT2_DISCH,
-                                           WM8994_LINEOUT1_DISCH |
-                                           WM8994_LINEOUT2_DISCH);
-
-                       msleep(5);
-
-                       /* Switch off startup biases */
-                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                           WM8994_BIAS_SRC |
-                                           WM8994_STARTUP_BIAS_ENA |
-                                           WM8994_VMID_BUF_ENA |
-                                           WM8994_VMID_RAMP_MASK, 0);
-
                        wm8994->cur_fw = NULL;
 
                        pm_runtime_put(codec->dev);
@@ -2384,6 +2497,21 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate)
        return snd_soc_update_bits(codec, reg, mask, val);
 }
 
+static int wm8994_aif2_probe(struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+
+       /* Disable the pulls on the AIF if we're using it to save power. */
+       snd_soc_update_bits(codec, WM8994_GPIO_3,
+                           WM8994_GPN_PU | WM8994_GPN_PD, 0);
+       snd_soc_update_bits(codec, WM8994_GPIO_4,
+                           WM8994_GPN_PU | WM8994_GPN_PD, 0);
+       snd_soc_update_bits(codec, WM8994_GPIO_5,
+                           WM8994_GPN_PU | WM8994_GPN_PD, 0);
+
+       return 0;
+}
+
 #define WM8994_RATES SNDRV_PCM_RATE_8000_96000
 
 #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
@@ -2451,6 +2579,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
                },
+               .probe = wm8994_aif2_probe,
                .ops = &wm8994_aif2_dai_ops,
        },
        {
@@ -2916,6 +3045,24 @@ static irqreturn_t wm8994_fifo_error(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t wm8994_temp_warn(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+
+       dev_err(codec->dev, "Thermal warning\n");
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t wm8994_temp_shut(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+
+       dev_crit(codec->dev, "Thermal shutdown\n");
+
+       return IRQ_HANDLED;
+}
+
 static int wm8994_codec_probe(struct snd_soc_codec *codec)
 {
        struct wm8994 *control;
@@ -2972,13 +3119,14 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                switch (wm8994->revision) {
                case 2:
                case 3:
-                       wm8994->hubs.dcs_codes = -5;
+                       wm8994->hubs.dcs_codes_l = -5;
+                       wm8994->hubs.dcs_codes_r = -5;
                        wm8994->hubs.hp_startup_mode = 1;
                        wm8994->hubs.dcs_readback_mode = 1;
                        wm8994->hubs.series_startup = 1;
                        break;
                default:
-                       wm8994->hubs.dcs_readback_mode = 1;
+                       wm8994->hubs.dcs_readback_mode = 2;
                        break;
                }
                break;
@@ -2993,6 +3141,10 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
        wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
                           wm8994_fifo_error, "FIFO error", codec);
+       wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_WARN,
+                          wm8994_temp_warn, "Thermal warning", codec);
+       wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_SHUT,
+                          wm8994_temp_shut, "Thermal shutdown", codec);
 
        ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
                                 wm_hubs_dcs_done, "DC servo done",
@@ -3257,6 +3409,8 @@ err_irq:
        wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
                        &wm8994->hubs);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec);
 err:
        kfree(wm8994);
        return ret;
@@ -3279,6 +3433,8 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
        wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
                        &wm8994->hubs);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec);
+       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec);
 
        switch (control->type) {
        case WM8994:
index 1ab2266039f7ca80b023f212888c1c7f8398bf94..f4f1355efc82ec9708e24993525d65aad9b54e1b 100644 (file)
@@ -83,6 +83,8 @@ struct wm8994_priv {
        struct completion fll_locked[2];
        bool fll_locked_irq;
 
+       int vmid_refcount;
+
        int dac_rates[2];
        int lrclk_shared[2];
 
index 5ad873fda814d9e20502684c2db87ebc13407b34..e05ee79691138e314a6fc674c07607a07d71b73a 100644 (file)
@@ -1573,11 +1573,16 @@ static int wm8995_resume(struct snd_soc_codec *codec)
 static int wm8995_remove(struct snd_soc_codec *codec)
 {
        struct wm8995_priv *wm8995;
-       struct i2c_client *i2c;
+       int i;
 
-       i2c = container_of(codec->dev, struct i2c_client, dev);
        wm8995 = snd_soc_codec_get_drvdata(codec);
        wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i)
+               regulator_unregister_notifier(wm8995->supplies[i].consumer,
+                                             &wm8995->disable_nb[i]);
+
+       regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
        return 0;
 }
 
@@ -1642,6 +1647,7 @@ static int wm8995_probe(struct snd_soc_codec *codec)
 
        if (ret != 0x8995) {
                dev_err(codec->dev, "Invalid device ID: %#x\n", ret);
+               ret = -EINVAL;
                goto err_reg_enable;
        }
 
index 0cdb9d1056712df48689c47eba7fa440fb73debe..b98a8f8525d9e292609875f0aeb295270220bd7c 100644 (file)
 #define HPOUT2L 4
 #define HPOUT2R 8
 
-#define WM8996_NUM_SUPPLIES 4
+#define WM8996_NUM_SUPPLIES 3
 static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = {
        "DBVDD",
        "AVDD1",
        "AVDD2",
-       "CPVDD",
 };
 
 struct wm8996_priv {
@@ -71,6 +70,8 @@ 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;
 
@@ -112,7 +113,6 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \
 WM8996_REGULATOR_EVENT(0)
 WM8996_REGULATOR_EVENT(1)
 WM8996_REGULATOR_EVENT(2)
-WM8996_REGULATOR_EVENT(3)
 
 static const u16 wm8996_reg[WM8996_MAX_REGISTER] = {
        [WM8996_SOFTWARE_RESET] = 0x8996,
@@ -414,6 +414,7 @@ static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0);
 static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0);
 static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0);
 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(threedstereo_tlv, -1600, 183, 1);
 
 static const char *sidetone_hpf_text[] = {
        "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz"
@@ -608,6 +609,14 @@ SOC_SINGLE("DAC High Performance Switch", WM8996_OVERSAMPLING, 0, 1, 0),
 SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0),
 SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0),
 
+SOC_SINGLE("DSP1 3D Stereo Switch", WM8996_DSP1_RX_FILTERS_2, 8, 1, 0),
+SOC_SINGLE("DSP2 3D Stereo Switch", WM8996_DSP2_RX_FILTERS_2, 8, 1, 0),
+
+SOC_SINGLE_TLV("DSP1 3D Stereo Volume", WM8996_DSP1_RX_FILTERS_2, 10, 15,
+               0, threedstereo_tlv),
+SOC_SINGLE_TLV("DSP2 3D Stereo Volume", WM8996_DSP2_RX_FILTERS_2, 10, 15,
+               0, threedstereo_tlv),
+
 SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4,
               8, 0, out_digital_tlv),
 SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4,
@@ -632,6 +641,14 @@ SOC_DOUBLE_R("Speaker ZC Switch", WM8996_LEFT_PDM_SPEAKER,
 
 SOC_SINGLE("DSP1 EQ Switch", WM8996_DSP1_RX_EQ_GAINS_1, 0, 1, 0),
 SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
+
+SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0),
+SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0),
+SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0),
+
+SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0),
+SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0),
+SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0),
 };
 
 static const struct snd_kcontrol_new wm8996_eq_controls[] = {
@@ -658,19 +675,75 @@ SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 6, 31, 0,
               eq_tlv),
 };
 
+static void wm8996_bg_enable(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+
+       wm8996->bg_ena++;
+       if (wm8996->bg_ena == 1) {
+               snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
+                                   WM8996_BG_ENA, WM8996_BG_ENA);
+               msleep(2);
+       }
+}
+
+static void wm8996_bg_disable(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+
+       wm8996->bg_ena--;
+       if (!wm8996->bg_ena)
+               snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
+                                   WM8996_BG_ENA, 0);
+}
+
+static int bg_event(struct snd_soc_dapm_widget *w,
+                   struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       int ret = 0;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               wm8996_bg_enable(codec);
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               wm8996_bg_disable(codec);
+               break;
+       default:
+               BUG();
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
 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();
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
-       return 0;
+       return ret;
 }
 
 static int rmv_short_event(struct snd_soc_dapm_widget *w,
@@ -698,7 +771,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask)
 {
        struct i2c_client *i2c = to_i2c_client(codec->dev);
        struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
-       int i, ret;
+       int ret;
        unsigned long timeout = 200;
 
        snd_soc_write(codec, WM8996_DC_SERVO_2, mask);
@@ -713,15 +786,12 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask)
 
                } else {
                        msleep(1);
-                       if (--i) {
-                               timeout = 0;
-                               break;
-                       }
+                       timeout--;
                }
 
                ret = snd_soc_read(codec, WM8996_DC_SERVO_2);
                dev_dbg(codec->dev, "DC servo state: %x\n", ret);
-       } while (ret & mask);
+       } while (timeout && ret & mask);
 
        if (timeout == 0)
                dev_err(codec->dev, "DC servo timed out for %x\n", mask);
@@ -979,9 +1049,12 @@ 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_POST_PMU),
-
+                     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+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),
+SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0),
 SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0),
 SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0),
 
@@ -1035,14 +1108,14 @@ 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", 1,
+SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
                    WM8996_POWER_MANAGEMENT_4, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 2,
+SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1,
                    WM8996_POWER_MANAGEMENT_4, 8, 0),
 
-SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 1,
+SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 0,
                    WM8996_POWER_MANAGEMENT_6, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 2,
+SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 1,
                    WM8996_POWER_MANAGEMENT_6, 8, 0),
 
 SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
@@ -1137,17 +1210,23 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
        { "Charge Pump", NULL, "SYSCLK" },
 
        { "MICB1", NULL, "LDO2" },
+       { "MICB1", NULL, "MICB1 Audio" },
+       { "MICB1", NULL, "Bandgap" },
        { "MICB2", NULL, "LDO2" },
+       { "MICB2", NULL, "MICB2 Audio" },
+       { "MICB2", NULL, "Bandgap" },
 
        { "IN1L PGA", NULL, "IN2LN" },
        { "IN1L PGA", NULL, "IN2LP" },
        { "IN1L PGA", NULL, "IN1LN" },
        { "IN1L PGA", NULL, "IN1LP" },
+       { "IN1L PGA", NULL, "Bandgap" },
 
        { "IN1R PGA", NULL, "IN2RN" },
        { "IN1R PGA", NULL, "IN2RP" },
        { "IN1R PGA", NULL, "IN1RN" },
        { "IN1R PGA", NULL, "IN1RP" },
+       { "IN1R PGA", NULL, "Bandgap" },
 
        { "ADCL", NULL, "IN1L PGA" },
 
@@ -1281,6 +1360,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
        { "DAC2R", NULL, "DAC2R Mixer" },
 
        { "HPOUT2L PGA", NULL, "Charge Pump" },
+       { "HPOUT2L PGA", NULL, "Bandgap" },
        { "HPOUT2L PGA", NULL, "DAC2L" },
        { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" },
        { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" },
@@ -1288,6 +1368,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
        { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" },
 
        { "HPOUT2R PGA", NULL, "Charge Pump" },
+       { "HPOUT2R PGA", NULL, "Bandgap" },
        { "HPOUT2R PGA", NULL, "DAC2R" },
        { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" },
        { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" },
@@ -1295,6 +1376,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
        { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" },
 
        { "HPOUT1L PGA", NULL, "Charge Pump" },
+       { "HPOUT1L PGA", NULL, "Bandgap" },
        { "HPOUT1L PGA", NULL, "DAC1L" },
        { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" },
        { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" },
@@ -1302,6 +1384,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
        { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" },
 
        { "HPOUT1R PGA", NULL, "Charge Pump" },
+       { "HPOUT1R PGA", NULL, "Bandgap" },
        { "HPOUT1R PGA", NULL, "DAC1R" },
        { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" },
        { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" },
@@ -1620,14 +1703,7 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               break;
-
        case SND_SOC_BIAS_PREPARE:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
-                       snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
-                                           WM8996_BG_ENA, WM8996_BG_ENA);
-                       msleep(2);
-               }
                break;
 
        case SND_SOC_BIAS_STANDBY:
@@ -1650,9 +1726,6 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
                        codec->cache_only = false;
                        snd_soc_cache_sync(codec);
                }
-
-               snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
-                                   WM8996_BG_ENA, 0);
                break;
 
        case SND_SOC_BIAS_OFF:
@@ -2041,7 +2114,7 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        struct i2c_client *i2c = to_i2c_client(codec->dev);
        struct _fll_div fll_div;
        unsigned long timeout;
-       int ret, reg;
+       int ret, reg, retry;
 
        /* Any change? */
        if (source == wm8996->fll_src && Fref == wm8996->fll_fref &&
@@ -2057,6 +2130,8 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
                snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1,
                                    WM8996_FLL_ENA, 0);
 
+               wm8996_bg_disable(codec);
+
                return 0;
        }
 
@@ -2111,6 +2186,11 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 
        snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda);
 
+       /* Enable the bandgap if it's not already enabled */
+       ret = snd_soc_read(codec, WM8996_FLL_CONTROL_1);
+       if (!(ret & WM8996_FLL_ENA))
+               wm8996_bg_enable(codec);
+
        /* Clear any pending completions (eg, from failed startups) */
        try_wait_for_completion(&wm8996->fll_lock);
 
@@ -2128,17 +2208,29 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        else
                timeout = msecs_to_jiffies(2);
 
-       /* Allow substantially longer if we've actually got the IRQ */
+       /* Allow substantially longer if we've actually got the IRQ, poll
+        * at a slightly higher rate if we don't.
+        */
        if (i2c->irq)
-               timeout *= 1000;
+               timeout *= 10;
+       else
+               timeout /= 2;
 
-       ret = wait_for_completion_timeout(&wm8996->fll_lock, timeout);
+       for (retry = 0; retry < 10; retry++) {
+               ret = wait_for_completion_timeout(&wm8996->fll_lock,
+                                                 timeout);
+               if (ret != 0) {
+                       WARN_ON(!i2c->irq);
+                       break;
+               }
 
-       if (ret == 0 && i2c->irq) {
+               ret = snd_soc_read(codec, WM8996_INTERRUPT_RAW_STATUS_2);
+               if (ret & WM8996_FLL_LOCK_STS)
+                       break;
+       }
+       if (retry == 10) {
                dev_err(codec->dev, "Timed out waiting for FLL\n");
                ret = -ETIMEDOUT;
-       } else {
-               ret = 0;
        }
 
        dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
@@ -2297,12 +2389,94 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 
        /* Enable interrupts and we're off */
        snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK,
-                           WM8996_IM_MICD_EINT, 0);
+                           WM8996_IM_MICD_EINT | WM8996_HP_DONE_EINT, 0);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(wm8996_detect);
 
+static void wm8996_hpdet_irq(struct snd_soc_codec *codec)
+{
+       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+       int val, reg, report;
+
+       /* Assume headphone in error conditions; we need to report
+        * something or we stall our state machine.
+        */
+       report = SND_JACK_HEADPHONE;
+
+       reg = snd_soc_read(codec, WM8996_HEADPHONE_DETECT_2);
+       if (reg < 0) {
+               dev_err(codec->dev, "Failed to read HPDET status\n");
+               goto out;
+       }
+
+       if (!(reg & WM8996_HP_DONE)) {
+               dev_err(codec->dev, "Got HPDET IRQ but HPDET is busy\n");
+               goto out;
+       }
+
+       val = reg & WM8996_HP_LVL_MASK;
+
+       dev_dbg(codec->dev, "HPDET measured %d ohms\n", val);
+
+       /* If we've got high enough impedence then report as line,
+        * otherwise assume headphone.
+        */
+       if (val >= 126)
+               report = SND_JACK_LINEOUT;
+       else
+               report = SND_JACK_HEADPHONE;
+
+out:
+       if (wm8996->jack_mic)
+               report |= SND_JACK_MICROPHONE;
+
+       snd_soc_jack_report(wm8996->jack, report,
+                           SND_JACK_LINEOUT | SND_JACK_HEADSET);
+
+       wm8996->detecting = false;
+
+       /* If the output isn't running re-clamp it */
+       if (!(snd_soc_read(codec, WM8996_POWER_MANAGEMENT_1) &
+             (WM8996_HPOUT1L_ENA | WM8996_HPOUT1R_RMV_SHORT)))
+               snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1,
+                                   WM8996_HPOUT1L_RMV_SHORT |
+                                   WM8996_HPOUT1R_RMV_SHORT, 0);
+
+       /* Go back to looking at the microphone */
+       snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1,
+                           WM8996_JD_MODE_MASK, 0);
+       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA,
+                           WM8996_MICD_ENA);
+
+       snd_soc_dapm_disable_pin(&codec->dapm, "Bandgap");
+       snd_soc_dapm_sync(&codec->dapm);
+}
+
+static void wm8996_hpdet_start(struct snd_soc_codec *codec)
+{
+       /* Unclamp the output, we can't measure while we're shorting it */
+       snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1,
+                           WM8996_HPOUT1L_RMV_SHORT |
+                           WM8996_HPOUT1R_RMV_SHORT,
+                           WM8996_HPOUT1L_RMV_SHORT |
+                           WM8996_HPOUT1R_RMV_SHORT);
+
+       /* We need bandgap for HPDET */
+       snd_soc_dapm_force_enable_pin(&codec->dapm, "Bandgap");
+       snd_soc_dapm_sync(&codec->dapm);
+
+       /* Go into headphone detect left mode */
+       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, 0);
+       snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1,
+                           WM8996_JD_MODE_MASK, 1);
+
+       /* Trigger a measurement */
+       snd_soc_update_bits(codec, WM8996_HEADPHONE_DETECT_1,
+                           WM8996_HP_POLL, WM8996_HP_POLL);
+}
+
 static void wm8996_micd(struct snd_soc_codec *codec)
 {
        struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
@@ -2323,28 +2497,36 @@ static void wm8996_micd(struct snd_soc_codec *codec)
                wm8996->jack_mic = false;
                wm8996->detecting = true;
                snd_soc_jack_report(wm8996->jack, 0,
-                                   SND_JACK_HEADSET | SND_JACK_BTN_0);
+                                   SND_JACK_LINEOUT | SND_JACK_HEADSET |
+                                   SND_JACK_BTN_0);
+
                snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
                                    WM8996_MICD_RATE_MASK,
                                    WM8996_MICD_RATE_MASK);
                return;
        }
 
-       /* If the measurement is very high we've got a microphone but
-        * do a little debounce to account for mechanical issues.
+       /* If the measurement is very high we've got a microphone,
+        * either we just detected one or if we already reported then
+        * we've got a button release event.
         */
        if (val & 0x400) {
-               dev_dbg(codec->dev, "Microphone detected\n");
-               snd_soc_jack_report(wm8996->jack, SND_JACK_HEADSET,
-                                   SND_JACK_HEADSET | SND_JACK_BTN_0);
-               wm8996->jack_mic = true;
-               wm8996->detecting = false;
-
-               /* Increase poll rate to give better responsiveness
-                * for buttons */
-               snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
-                                   WM8996_MICD_RATE_MASK,
-                                   5 << WM8996_MICD_RATE_SHIFT);
+               if (wm8996->detecting) {
+                       dev_dbg(codec->dev, "Microphone detected\n");
+                       wm8996->jack_mic = true;
+                       wm8996_hpdet_start(codec);
+
+                       /* Increase poll rate to give better responsiveness
+                        * for buttons */
+                       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+                                           WM8996_MICD_RATE_MASK,
+                                           5 << WM8996_MICD_RATE_SHIFT);
+               } else {
+                       dev_dbg(codec->dev, "Mic button up\n");
+                       snd_soc_jack_report(wm8996->jack, 0, SND_JACK_BTN_0);
+               }
+
+               return;
        }
 
        /* If we detected a lower impedence during initial startup
@@ -2376,15 +2558,11 @@ static void wm8996_micd(struct snd_soc_codec *codec)
        if (val & 0x3fc) {
                if (wm8996->jack_mic) {
                        dev_dbg(codec->dev, "Mic button detected\n");
-                       snd_soc_jack_report(wm8996->jack,
-                                           SND_JACK_HEADSET | SND_JACK_BTN_0,
-                                           SND_JACK_HEADSET | SND_JACK_BTN_0);
-               } else {
-                       dev_dbg(codec->dev, "Headphone detected\n");
-                       snd_soc_jack_report(wm8996->jack,
-                                           SND_JACK_HEADPHONE,
-                                           SND_JACK_HEADSET |
+                       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.
@@ -2392,8 +2570,6 @@ static void wm8996_micd(struct snd_soc_codec *codec)
                        snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
                                            WM8996_MICD_RATE_MASK,
                                            7 << WM8996_MICD_RATE_SHIFT);
-
-                       wm8996->detecting = false;
                }
        }
 }
@@ -2412,6 +2588,9 @@ static irqreturn_t wm8996_irq(int irq, void *data)
        }
        irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK);
 
+       if (!irq_val)
+               return IRQ_NONE;
+
        snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val);
 
        if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) {
@@ -2430,10 +2609,10 @@ static irqreturn_t wm8996_irq(int irq, void *data)
        if (irq_val & WM8996_MICD_EINT)
                wm8996_micd(codec);
 
-       if (irq_val)
-               return IRQ_HANDLED;
-       else
-               return IRQ_NONE;
+       if (irq_val & WM8996_HP_DONE_EINT)
+               wm8996_hpdet_irq(codec);
+
+       return IRQ_HANDLED;
 }
 
 static irqreturn_t wm8996_edge_irq(int irq, void *data)
@@ -2548,7 +2727,13 @@ static int wm8996_probe(struct snd_soc_codec *codec)
        wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0;
        wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
        wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
-       wm8996->disable_nb[3].notifier_call = wm8996_regulator_event_3;
+
+       wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD");
+       if (IS_ERR(wm8996->cpvdd)) {
+               ret = PTR_ERR(wm8996->cpvdd);
+               dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
+               goto err_get;
+       }
 
        /* This should really be moved into the regulator core */
        for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
@@ -2565,7 +2750,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
                                    wm8996->supplies);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_get;
+               goto err_cpvdd;
        }
 
        if (wm8996->pdata.ldo_ena >= 0) {
@@ -2808,6 +2993,8 @@ err_enable:
                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:
@@ -2831,6 +3018,7 @@ 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;
index a4691321f9b33887e4601e9634da5e15db0b081e..b2d34483a6a41c50c043956bac1da49d8abb83f8 100644 (file)
@@ -157,7 +157,6 @@ static struct {
 
 struct wm9081_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
        int sysclk_source;
        int mclk_rate;
        int sysclk_rate;
@@ -1120,8 +1119,8 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
        return 0;
 }
 
-static int wm9081_set_sysclk(struct snd_soc_codec *codec,
-                            int clk_id, unsigned int freq, int dir)
+static int wm9081_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+                            int source, unsigned int freq, int dir)
 {
        struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
 
@@ -1213,7 +1212,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
        int ret;
        u16 reg;
 
-       codec->control_data = wm9081->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -1330,7 +1328,6 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm9081);
        wm9081->control_type = SND_SOC_I2C;
-       wm9081->control_data = i2c;
 
        if (dev_get_platdata(&i2c->dev))
                memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
index 4de12203e6113508712731c1060ed4e8d39cc743..228d782ccded19cf64b60f9480c810450c377953 100644 (file)
@@ -139,9 +139,7 @@ static const u16 wm9090_reg_defaults[] = {
 
 /* This struct is used to save the context */
 struct wm9090_priv {
-       struct mutex mutex;
        struct wm9090_platform_data pdata;
-       void *control_data;
 };
 
 static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
@@ -553,7 +551,6 @@ static int wm9090_probe(struct snd_soc_codec *codec)
        struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       codec->control_data = wm9090->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -662,8 +659,6 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
                       sizeof(wm9090->pdata));
 
        i2c_set_clientdata(i2c, wm9090);
-       wm9090->control_data = i2c;
-       mutex_init(&wm9090->mutex);
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm9090,  NULL, 0);
@@ -684,6 +679,7 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
 
 static const struct i2c_device_id wm9090_id[] = {
        { "wm9090", 0 },
+       { "wm9093", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, wm9090_id);
index e763c54c55dc32d5e2b97da5c9bfcd364558adaa..ca8ce03510f4ee460da84d12596c6f54ca1e5522 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/wm8994/registers.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -116,14 +117,23 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
 {
        struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
        s8 offset;
-       u16 reg, reg_l, reg_r, dcs_cfg;
+       u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg;
+
+       switch (hubs->dcs_readback_mode) {
+       case 2:
+               dcs_reg = WM8994_DC_SERVO_4E;
+               break;
+       default:
+               dcs_reg = WM8993_DC_SERVO_3;
+               break;
+       }
 
        /* If we're using a digital only path and have a previously
         * callibrated DC servo offset stored then use that. */
        if (hubs->class_w && hubs->class_w_dcs) {
                dev_dbg(codec->dev, "Using cached DC servo offset %x\n",
                        hubs->class_w_dcs);
-               snd_soc_write(codec, WM8993_DC_SERVO_3, hubs->class_w_dcs);
+               snd_soc_write(codec, dcs_reg, hubs->class_w_dcs);
                wait_for_dc_servo(codec,
                                  WM8993_DCS_TRIG_DAC_WR_0 |
                                  WM8993_DCS_TRIG_DAC_WR_1);
@@ -154,8 +164,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
                reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2)
                        & WM8993_DCS_INTEG_CHAN_1_MASK;
                break;
+       case 2:
        case 1:
-               reg = snd_soc_read(codec, WM8993_DC_SERVO_3);
+               reg = snd_soc_read(codec, dcs_reg);
                reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
                        >> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
                reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
@@ -168,24 +179,25 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
        dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r);
 
        /* Apply correction to DC servo result */
-       if (hubs->dcs_codes) {
-               dev_dbg(codec->dev, "Applying %d code DC servo correction\n",
-                       hubs->dcs_codes);
+       if (hubs->dcs_codes_l || hubs->dcs_codes_r) {
+               dev_dbg(codec->dev,
+                       "Applying %d/%d code DC servo correction\n",
+                       hubs->dcs_codes_l, hubs->dcs_codes_r);
 
                /* HPOUT1R */
                offset = reg_r;
-               offset += hubs->dcs_codes;
+               offset += hubs->dcs_codes_r;
                dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
 
                /* HPOUT1L */
                offset = reg_l;
-               offset += hubs->dcs_codes;
+               offset += hubs->dcs_codes_l;
                dcs_cfg |= (u8)offset;
 
                dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg);
 
                /* Do it */
-               snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg);
+               snd_soc_write(codec, dcs_reg, dcs_cfg);
                wait_for_dc_servo(codec,
                                  WM8993_DCS_TRIG_DAC_WR_0 |
                                  WM8993_DCS_TRIG_DAC_WR_1);
@@ -217,7 +229,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
 
        /* If we're applying an offset correction then updating the
         * callibration would be likely to introduce further offsets. */
-       if (hubs->dcs_codes || hubs->no_series_update)
+       if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update)
                return ret;
 
        /* Only need to do this if the outputs are active */
@@ -699,6 +711,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
        { "IN1L PGA", "IN1LP Switch", "IN1LP" },
        { "IN1L PGA", "IN1LN Switch", "IN1LN" },
 
+       { "IN1L PGA", NULL, "VMID" },
+       { "IN1R PGA", NULL, "VMID" },
+       { "IN2L PGA", NULL, "VMID" },
+       { "IN2R PGA", NULL, "VMID" },
+
        { "IN1R PGA", "IN1RP Switch", "IN1RP" },
        { "IN1R PGA", "IN1RN Switch", "IN1RN" },
 
@@ -716,12 +733,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
        { "MIXINL", NULL, "Direct Voice" },
        { "MIXINL", NULL, "IN1LP" },
        { "MIXINL", NULL, "Left Output Mixer" },
+       { "MIXINL", NULL, "VMID" },
 
        { "MIXINR", "IN1R Switch", "IN1R PGA" },
        { "MIXINR", "IN2R Switch", "IN2R PGA" },
        { "MIXINR", NULL, "Direct Voice" },
        { "MIXINR", NULL, "IN1RP" },
        { "MIXINR", NULL, "Right Output Mixer" },
+       { "MIXINR", NULL, "VMID" },
 
        { "ADCL", NULL, "MIXINL" },
        { "ADCR", NULL, "MIXINR" },
@@ -752,6 +771,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
        { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" },
        { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" },
 
+       { "Earpiece Driver", NULL, "VMID" },
        { "Earpiece Driver", NULL, "Earpiece Mixer" },
        { "HPOUT2N", NULL, "Earpiece Driver" },
        { "HPOUT2P", NULL, "Earpiece Driver" },
@@ -774,9 +794,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
        { "SPKR Boost", "SPKR Switch", "SPKR" },
        { "SPKR Boost", "SPKL Switch", "SPKL" },
 
+       { "SPKL Driver", NULL, "VMID" },
        { "SPKL Driver", NULL, "SPKL Boost" },
        { "SPKL Driver", NULL, "CLK_SYS" },
 
+       { "SPKR Driver", NULL, "VMID" },
        { "SPKR Driver", NULL, "SPKR Boost" },
        { "SPKR Driver", NULL, "CLK_SYS" },
 
@@ -790,12 +812,18 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
 
        { "Headphone PGA", NULL, "Left Headphone Mux" },
        { "Headphone PGA", NULL, "Right Headphone Mux" },
+       { "Headphone PGA", NULL, "VMID" },
        { "Headphone PGA", NULL, "CLK_SYS" },
        { "Headphone PGA", NULL, "Headphone Supply" },
 
        { "HPOUT1L", NULL, "Headphone PGA" },
        { "HPOUT1R", NULL, "Headphone PGA" },
 
+       { "LINEOUT1N Driver", NULL, "VMID" },
+       { "LINEOUT1P Driver", NULL, "VMID" },
+       { "LINEOUT2N Driver", NULL, "VMID" },
+       { "LINEOUT2P Driver", NULL, "VMID" },
+
        { "LINEOUT1N", NULL, "LINEOUT1N Driver" },
        { "LINEOUT1P", NULL, "LINEOUT1P Driver" },
        { "LINEOUT2N", NULL, "LINEOUT2N Driver" },
index 676b1252ab910559a07bc3738051a67e60e765c8..c674c7a502a64e1d02889edfa839522686afdf9b 100644 (file)
@@ -23,7 +23,8 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
 
 /* This *must* be the first element of the codec->private_data struct */
 struct wm_hubs_data {
-       int dcs_codes;
+       int dcs_codes_l;
+       int dcs_codes_r;
        int dcs_readback_mode;
        int hp_startup_mode;
        int series_startup;
index d0d60b8a54d4b7573841b297c8d07b78434af6a9..300e12118c0093722f1e2b5f527b8627cdbab116 100644 (file)
@@ -265,6 +265,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned int pcr;
        unsigned int srgr;
+       bool inv_fs = false;
        /* Attention srgr is updated by hw_params! */
        srgr = DAVINCI_MCBSP_SRGR_FSGM |
                DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
@@ -330,7 +331,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                 * more empty bit clock slots between channels as the sample
                 * rate is lowered.
                 */
-               fmt ^= SND_SOC_DAIFMT_NB_IF;
+               inv_fs = true;
        case SND_SOC_DAIFMT_DSP_A:
                dev->mode = MOD_DSP_A;
                break;
@@ -394,6 +395,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        default:
                return -EINVAL;
        }
+       if (inv_fs == true)
+               pcr ^= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
        davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
        dev->pcr = pcr;
        davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
index 8566238db2a5ea7a3f807f2cb341826703167bec..7173df254a9150b0f69d527f7cd2f6ab02cfc7e3 100644 (file)
@@ -732,16 +732,19 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                davinci_hw_param(dev, substream->stream);
 
        switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_U8:
        case SNDRV_PCM_FORMAT_S8:
                dma_params->data_type = 1;
                word_length = DAVINCI_AUDIO_WORD_8;
                break;
 
+       case SNDRV_PCM_FORMAT_U16_LE:
        case SNDRV_PCM_FORMAT_S16_LE:
                dma_params->data_type = 2;
                word_length = DAVINCI_AUDIO_WORD_16;
                break;
 
+       case SNDRV_PCM_FORMAT_U32_LE:
        case SNDRV_PCM_FORMAT_S32_LE:
                dma_params->data_type = 4;
                word_length = DAVINCI_AUDIO_WORD_32;
@@ -818,6 +821,13 @@ static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
 
 };
 
+#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
+                               SNDRV_PCM_FMTBIT_U8 | \
+                               SNDRV_PCM_FMTBIT_S16_LE | \
+                               SNDRV_PCM_FMTBIT_U16_LE | \
+                               SNDRV_PCM_FMTBIT_S32_LE | \
+                               SNDRV_PCM_FMTBIT_U32_LE)
+
 static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
        {
                .name           = "davinci-mcasp.0",
@@ -825,17 +835,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
                        .channels_min   = 2,
                        .channels_max   = 2,
                        .rates          = DAVINCI_MCASP_RATES,
-                       .formats        = SNDRV_PCM_FMTBIT_S8 |
-                                               SNDRV_PCM_FMTBIT_S16_LE |
-                                               SNDRV_PCM_FMTBIT_S32_LE,
+                       .formats        = DAVINCI_MCASP_PCM_FMTS,
                },
                .capture        = {
                        .channels_min   = 2,
                        .channels_max   = 2,
                        .rates          = DAVINCI_MCASP_RATES,
-                       .formats        = SNDRV_PCM_FMTBIT_S8 |
-                                               SNDRV_PCM_FMTBIT_S16_LE |
-                                               SNDRV_PCM_FMTBIT_S32_LE,
+                       .formats        = DAVINCI_MCASP_PCM_FMTS,
                },
                .ops            = &davinci_mcasp_dai_ops,
 
@@ -846,7 +852,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
                        .channels_min   = 1,
                        .channels_max   = 384,
                        .rates          = DAVINCI_MCASP_RATES,
-                       .formats        = SNDRV_PCM_FMTBIT_S16_LE,
+                       .formats        = DAVINCI_MCASP_PCM_FMTS,
                },
                .ops            = &davinci_mcasp_dai_ops,
        },
index a49e667373bcf7542854696e4c2ee63fc38249ab..d5fe08cc5db7ec83efbfcb2b8b13d6094c2bf986 100644 (file)
@@ -180,7 +180,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
 {
        struct davinci_runtime_data *prtd = substream->runtime->private_data;
        struct snd_pcm_runtime *runtime = substream->runtime;
-       int link = prtd->asp_link[0];
        unsigned int period_size;
        unsigned int dma_offset;
        dma_addr_t dma_pos;
@@ -198,7 +197,8 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
        fifo_level = prtd->params->fifo_level;
 
        pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
-               "dma_ptr = %x period_size=%x\n", link, dma_pos, period_size);
+               "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos,
+               period_size);
 
        data_type = prtd->params->data_type;
        count = period_size / data_type;
@@ -222,17 +222,19 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
        }
 
        acnt = prtd->params->acnt;
-       edma_set_src(link, src, INCR, W8BIT);
-       edma_set_dest(link, dst, INCR, W8BIT);
+       edma_set_src(prtd->asp_link[0], src, INCR, W8BIT);
+       edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT);
 
-       edma_set_src_index(link, src_bidx, src_cidx);
-       edma_set_dest_index(link, dst_bidx, dst_cidx);
+       edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx);
+       edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx);
 
        if (!fifo_level)
-               edma_set_transfer_params(link, acnt, count, 1, 0, ASYNC);
+               edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
+                                                       ASYNC);
        else
-               edma_set_transfer_params(link, acnt, fifo_level, count,
-                                                       fifo_level, ABSYNC);
+               edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
+                                                       count, fifo_level,
+                                                       ABSYNC);
 }
 
 static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
@@ -305,7 +307,6 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
        unsigned int acnt = params->acnt;
        /* divide by 2 for ping/pong */
        unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1;
-       int link = prtd->asp_link[1];
        unsigned int fifo_level = prtd->params->fifo_level;
        unsigned int count;
        if ((data_type == 0) || (data_type > 4)) {
@@ -316,28 +317,26 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
                dma_addr_t asp_src_pong = iram_dma->addr + ping_size;
                ram_src_cidx = ping_size;
                ram_dst_cidx = -ping_size;
-               edma_set_src(link, asp_src_pong, INCR, W8BIT);
+               edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT);
 
-               link = prtd->asp_link[0];
-               edma_set_src_index(link, data_type, data_type * fifo_level);
-               link = prtd->asp_link[1];
-               edma_set_src_index(link, data_type, data_type * fifo_level);
+               edma_set_src_index(prtd->asp_link[0], data_type,
+                               data_type * fifo_level);
+               edma_set_src_index(prtd->asp_link[1], data_type,
+                               data_type * fifo_level);
 
-               link = prtd->ram_link;
-               edma_set_src(link, runtime->dma_addr, INCR, W32BIT);
+               edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
        } else {
                dma_addr_t asp_dst_pong = iram_dma->addr + ping_size;
                ram_src_cidx = -ping_size;
                ram_dst_cidx = ping_size;
-               edma_set_dest(link, asp_dst_pong, INCR, W8BIT);
+               edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT);
 
-               link = prtd->asp_link[0];
-               edma_set_dest_index(link, data_type, data_type * fifo_level);
-               link = prtd->asp_link[1];
-               edma_set_dest_index(link, data_type, data_type * fifo_level);
+               edma_set_dest_index(prtd->asp_link[0], data_type,
+                               data_type * fifo_level);
+               edma_set_dest_index(prtd->asp_link[1], data_type,
+                               data_type * fifo_level);
 
-               link = prtd->ram_link;
-               edma_set_dest(link, runtime->dma_addr, INCR, W32BIT);
+               edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
        }
 
        if (!fifo_level) {
@@ -354,10 +353,9 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
                                count, fifo_level, ABSYNC);
        }
 
-       link = prtd->ram_link;
-       edma_set_src_index(link, ping_size, ram_src_cidx);
-       edma_set_dest_index(link, ping_size, ram_dst_cidx);
-       edma_set_transfer_params(link, ping_size, 2,
+       edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx);
+       edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx);
+       edma_set_transfer_params(prtd->ram_link, ping_size, 2,
                        runtime->periods, 2, ASYNC);
 
        /* init master params */
@@ -406,32 +404,32 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
 {
        dma_addr_t asp_src_ping;
        dma_addr_t asp_dst_ping;
-       int link;
+       int ret;
        struct davinci_pcm_dma_params *params = prtd->params;
 
        /* Request ram master channel */
-       link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
+       ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
                                  davinci_pcm_dma_irq, substream,
                                  prtd->params->ram_chan_q);
-       if (link < 0)
+       if (ret < 0)
                goto exit1;
 
        /* Request ram link channel */
-       link = prtd->ram_link = edma_alloc_slot(
+       ret = prtd->ram_link = edma_alloc_slot(
                        EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
-       if (link < 0)
+       if (ret < 0)
                goto exit2;
 
-       link = prtd->asp_link[1] = edma_alloc_slot(
+       ret = prtd->asp_link[1] = edma_alloc_slot(
                        EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
-       if (link < 0)
+       if (ret < 0)
                goto exit3;
 
        prtd->ram_link2 = -1;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               link = prtd->ram_link2 = edma_alloc_slot(
+               ret = prtd->ram_link2 = edma_alloc_slot(
                        EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
-               if (link < 0)
+               if (ret < 0)
                        goto exit4;
        }
        /* circle ping-pong buffers */
@@ -448,36 +446,33 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
                asp_dst_ping = iram_dma->addr;
        }
        /* ping */
-       link = prtd->asp_link[0];
-       edma_set_src(link, asp_src_ping, INCR, W16BIT);
-       edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
-       edma_set_src_index(link, 0, 0);
-       edma_set_dest_index(link, 0, 0);
+       edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT);
+       edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT);
+       edma_set_src_index(prtd->asp_link[0], 0, 0);
+       edma_set_dest_index(prtd->asp_link[0], 0, 0);
 
-       edma_read_slot(link, &prtd->asp_params);
+       edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
        prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
        prtd->asp_params.opt |= TCCHEN |
                EDMA_TCC(prtd->ram_channel & 0x3f);
-       edma_write_slot(link, &prtd->asp_params);
+       edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
 
        /* pong */
-       link = prtd->asp_link[1];
-       edma_set_src(link, asp_src_ping, INCR, W16BIT);
-       edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
-       edma_set_src_index(link, 0, 0);
-       edma_set_dest_index(link, 0, 0);
+       edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT);
+       edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT);
+       edma_set_src_index(prtd->asp_link[1], 0, 0);
+       edma_set_dest_index(prtd->asp_link[1], 0, 0);
 
-       edma_read_slot(link, &prtd->asp_params);
+       edma_read_slot(prtd->asp_link[1], &prtd->asp_params);
        prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
        /* interrupt after every pong completion */
        prtd->asp_params.opt |= TCINTEN | TCCHEN |
                EDMA_TCC(prtd->ram_channel & 0x3f);
-       edma_write_slot(link, &prtd->asp_params);
+       edma_write_slot(prtd->asp_link[1], &prtd->asp_params);
 
        /* ram */
-       link = prtd->ram_link;
-       edma_set_src(link, iram_dma->addr, INCR, W32BIT);
-       edma_set_dest(link, iram_dma->addr, INCR, W32BIT);
+       edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
+       edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
        pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u,"
                "for asp:%u %u %u\n", __func__,
                prtd->ram_channel, prtd->ram_link, prtd->ram_link2,
@@ -494,7 +489,7 @@ exit2:
        edma_free_channel(prtd->ram_channel);
        prtd->ram_channel = -1;
 exit1:
-       return link;
+       return ret;
 }
 
 static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
@@ -502,22 +497,22 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
        struct snd_dma_buffer *iram_dma;
        struct davinci_runtime_data *prtd = substream->runtime->private_data;
        struct davinci_pcm_dma_params *params = prtd->params;
-       int link;
+       int ret;
 
        if (!params)
                return -ENODEV;
 
        /* Request asp master DMA channel */
-       link = prtd->asp_channel = edma_alloc_channel(params->channel,
+       ret = prtd->asp_channel = edma_alloc_channel(params->channel,
                        davinci_pcm_dma_irq, substream,
                        prtd->params->asp_chan_q);
-       if (link < 0)
+       if (ret < 0)
                goto exit1;
 
        /* Request asp link channels */
-       link = prtd->asp_link[0] = edma_alloc_slot(
+       ret = prtd->asp_link[0] = edma_alloc_slot(
                        EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
-       if (link < 0)
+       if (ret < 0)
                goto exit2;
 
        iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data;
@@ -537,17 +532,17 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
         * the buffer and its length (ccnt) ... use it as a template
         * so davinci_pcm_enqueue_dma() takes less time in IRQ.
         */
-       edma_read_slot(link, &prtd->asp_params);
+       edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
        prtd->asp_params.opt |= TCINTEN |
                EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel));
-       prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(link) << 5;
-       edma_write_slot(link, &prtd->asp_params);
+       prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5;
+       edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
        return 0;
 exit2:
        edma_free_channel(prtd->asp_channel);
        prtd->asp_channel = -1;
 exit1:
-       return link;
+       return ret;
 }
 
 static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
index d3aa15119d265414fdbd179c9c9f97997d28dde5..0134d4e9131c9dddff7b298eed13da3cd9b948bb 100644 (file)
 #include <mach/hardware.h>
 #include "ep93xx-pcm.h"
 
-#define edb93xx_has_audio() (machine_is_edb9301() ||   \
-                            machine_is_edb9302() ||    \
-                            machine_is_edb9302a() ||   \
-                            machine_is_edb9307a() ||   \
-                            machine_is_edb9315a())
-
 static int edb93xx_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
@@ -94,49 +88,61 @@ static struct snd_soc_card snd_soc_edb93xx = {
        .num_links      = 1,
 };
 
-static struct platform_device *edb93xx_snd_device;
-
-static int __init edb93xx_init(void)
+static int __devinit edb93xx_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = &snd_soc_edb93xx;
        int ret;
 
-       if (!edb93xx_has_audio())
-               return -ENODEV;
-
        ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
                                 EP93XX_SYSCON_I2SCLKDIV_ORIDE |
                                 EP93XX_SYSCON_I2SCLKDIV_SPOL);
        if (ret)
                return ret;
 
-       edb93xx_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!edb93xx_snd_device) {
-               ret = -ENOMEM;
-               goto free_i2s;
+       card->dev = &pdev->dev;
+
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+                       ret);
+               ep93xx_i2s_release();
        }
 
-       platform_set_drvdata(edb93xx_snd_device, &snd_soc_edb93xx);
-       ret = platform_device_add(edb93xx_snd_device);
-       if (ret)
-               goto device_put;
+       return ret;
+}
 
-       return 0;
+static int __devexit edb93xx_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
 
-device_put:
-       platform_device_put(edb93xx_snd_device);
-free_i2s:
+       snd_soc_unregister_card(card);
        ep93xx_i2s_release();
-       return ret;
+
+       return 0;
+}
+
+static struct platform_driver edb93xx_driver = {
+       .driver         = {
+               .name   = "edb93xx-audio",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = edb93xx_probe,
+       .remove         = __devexit_p(edb93xx_remove),
+};
+
+static int __init edb93xx_init(void)
+{
+       return platform_driver_register(&edb93xx_driver);
 }
 module_init(edb93xx_init);
 
 static void __exit edb93xx_exit(void)
 {
-       platform_device_unregister(edb93xx_snd_device);
-       ep93xx_i2s_release();
+       platform_driver_unregister(&edb93xx_driver);
 }
 module_exit(edb93xx_exit);
 
 MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
 MODULE_DESCRIPTION("ALSA SoC EDB93xx");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:edb93xx-audio");
index 8dfd3ad84b19c8f36a1350887659b9024cba7534..d00230a591b19efc8f4df849b7dbe07cb6cb665c 100644 (file)
@@ -355,3 +355,4 @@ module_exit(ep93xx_soc_platform_exit);
 MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ep93xx-pcm-audio");
index 286817946c5674c6a4536d4afda7507316e99883..968cb316d5115cf0d99bebf6d1fb1a47aef3a4e8 100644 (file)
@@ -39,53 +39,61 @@ static struct snd_soc_card snd_soc_simone = {
 };
 
 static struct platform_device *simone_snd_ac97_device;
-static struct platform_device *simone_snd_device;
 
-static int __init simone_init(void)
+static int __devinit simone_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = &snd_soc_simone;
        int ret;
 
-       if (!machine_is_sim_one())
-               return -ENODEV;
-
-       simone_snd_ac97_device = platform_device_alloc("ac97-codec", -1);
-       if (!simone_snd_ac97_device)
-               return -ENOMEM;
+       simone_snd_ac97_device = platform_device_register_simple("ac97-codec",
+                                                                -1, NULL, 0);
+       if (IS_ERR(simone_snd_ac97_device))
+               return PTR_ERR(simone_snd_ac97_device);
 
-       ret = platform_device_add(simone_snd_ac97_device);
-       if (ret)
-               goto fail1;
+       card->dev = &pdev->dev;
 
-       simone_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!simone_snd_device) {
-               ret = -ENOMEM;
-               goto fail2;
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+                       ret);
+               platform_device_unregister(simone_snd_ac97_device);
        }
 
-       platform_set_drvdata(simone_snd_device, &snd_soc_simone);
-       ret = platform_device_add(simone_snd_device);
-       if (ret)
-               goto fail3;
+       return ret;
+}
+
+static int __devexit simone_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
+       platform_device_unregister(simone_snd_ac97_device);
 
        return 0;
+}
 
-fail3:
-       platform_device_put(simone_snd_device);
-fail2:
-       platform_device_del(simone_snd_ac97_device);
-fail1:
-       platform_device_put(simone_snd_ac97_device);
-       return ret;
+static struct platform_driver simone_driver = {
+       .driver         = {
+               .name   = "simone-audio",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = simone_probe,
+       .remove         = __devexit_p(simone_remove),
+};
+
+static int __init simone_init(void)
+{
+       return platform_driver_register(&simone_driver);
 }
 module_init(simone_init);
 
 static void __exit simone_exit(void)
 {
-       platform_device_unregister(simone_snd_device);
-       platform_device_unregister(simone_snd_ac97_device);
+       platform_driver_unregister(&simone_driver);
 }
 module_exit(simone_exit);
 
 MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:simone-audio");
index c8aa8a5003ca62c84fb8909c9955e80eec765ded..f74ac54c285a8a2c7598c336b988f85612f83365 100644 (file)
@@ -104,37 +104,56 @@ static struct snd_soc_card snd_soc_snappercl15 = {
        .num_links      = 1,
 };
 
-static struct platform_device *snappercl15_snd_device;
-
-static int __init snappercl15_init(void)
+static int __devinit snappercl15_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = &snd_soc_snappercl15;
        int ret;
 
-       if (!machine_is_snapper_cl15())
-               return -ENODEV;
-
        ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
                                 EP93XX_SYSCON_I2SCLKDIV_ORIDE |
                                 EP93XX_SYSCON_I2SCLKDIV_SPOL);
        if (ret)
                return ret;
 
-       snappercl15_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!snappercl15_snd_device)
-               return -ENOMEM;
-       
-       platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15);
-       ret = platform_device_add(snappercl15_snd_device);
-       if (ret)
-               platform_device_put(snappercl15_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);
+               ep93xx_i2s_release();
+       }
 
        return ret;
 }
 
-static void __exit snappercl15_exit(void)
+static int __devexit snappercl15_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(snappercl15_snd_device);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
        ep93xx_i2s_release();
+
+       return 0;
+}
+
+static struct platform_driver snappercl15_driver = {
+       .driver         = {
+               .name   = "snappercl15-audio",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = snappercl15_probe,
+       .remove         = __devexit_p(snappercl15_remove),
+};
+
+static int __init snappercl15_init(void)
+{
+       return platform_driver_register(&snappercl15_driver);
+}
+
+static void __exit snappercl15_exit(void)
+{
+       platform_driver_unregister(&snappercl15_driver);
 }
 
 module_init(snappercl15_init);
@@ -143,4 +162,4 @@ module_exit(snappercl15_exit);
 MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("ALSA SoC Snapper CL15");
 MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:snappercl15-audio");
index cb50598338e92afd2d10997d220a274fd264d378..ef15402a3bc4948311c69b4b69da9ebd7055ee58 100644 (file)
@@ -297,7 +297,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
 static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
-       struct snd_soc_dai *dai = rtd->cpu_dai;
        struct snd_pcm *pcm = rtd->pcm;
        static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
        int ret;
index d48afea5d93d91c5b95d718768a239683c4f05d3..0268cf989736f303a224fbd26b0db2e8bf97f2ed 100644 (file)
@@ -78,7 +78,6 @@
  * @second_stream: pointer to second stream
  * @playback: the number of playback streams opened
  * @capture: the number of capture streams opened
- * @asynchronous: 0=synchronous mode, 1=asynchronous mode
  * @cpu_dai: the CPU DAI for this device
  * @dev_attr: the sysfs device attribute structure
  * @stats: SSI statistics
@@ -90,9 +89,6 @@ struct fsl_ssi_private {
        unsigned int irq;
        struct snd_pcm_substream *first_stream;
        struct snd_pcm_substream *second_stream;
-       unsigned int playback;
-       unsigned int capture;
-       int asynchronous;
        unsigned int fifo_depth;
        struct snd_soc_dai_driver cpu_dai_drv;
        struct device_attribute dev_attr;
@@ -281,24 +277,18 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+       struct fsl_ssi_private *ssi_private =
+               snd_soc_dai_get_drvdata(rtd->cpu_dai);
+       int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
 
        /*
         * If this is the first stream opened, then request the IRQ
         * and initialize the SSI registers.
         */
-       if (!ssi_private->playback && !ssi_private->capture) {
+       if (!ssi_private->first_stream) {
                struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-               int ret;
-
-               /* The 'name' should not have any slashes in it. */
-               ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0,
-                                 ssi_private->name, ssi_private);
-               if (ret < 0) {
-                       dev_err(substream->pcm->card->dev,
-                               "could not claim irq %u\n", ssi_private->irq);
-                       return ret;
-               }
+
+               ssi_private->first_stream = substream;
 
                /*
                 * Section 16.5 of the MPC8610 reference manual says that the
@@ -316,7 +306,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
                clrsetbits_be32(&ssi->scr,
                        CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
                        CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE
-                       | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN));
+                       | (synchronous ? CCSR_SSI_SCR_SYN : 0));
 
                out_be32(&ssi->stcr,
                         CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
@@ -333,7 +323,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
                 * master.
                 */
 
-               /* 4. Enable the interrupts and DMA requests */
+               /* Enable the interrupts and DMA requests */
                out_be32(&ssi->sier, SIER_FLAGS);
 
                /*
@@ -362,58 +352,47 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
                 * this is bad is because at this point, the PCM driver has not
                 * finished initializing the DMA controller.
                 */
-       }
+       } else {
+               if (synchronous) {
+                       struct snd_pcm_runtime *first_runtime =
+                               ssi_private->first_stream->runtime;
+                       /*
+                        * This is the second stream open, and we're in
+                        * synchronous mode, so we need to impose sample
+                        * sample size constraints. This is because STCCR is
+                        * used for playback and capture in synchronous mode,
+                        * so there's no way to specify different word
+                        * lengths.
+                        *
+                        * Note that this can cause a race condition if the
+                        * second stream is opened before the first stream is
+                        * fully initialized.  We provide some protection by
+                        * checking to make sure the first stream is
+                        * initialized, but it's not perfect.  ALSA sometimes
+                        * re-initializes the driver with a different sample
+                        * rate or size.  If the second stream is opened
+                        * before the first stream has received its final
+                        * parameters, then the second stream may be
+                        * constrained to the wrong sample rate or size.
+                        */
+                       if (!first_runtime->sample_bits) {
+                               dev_err(substream->pcm->card->dev,
+                                       "set sample size in %s stream first\n",
+                                       substream->stream ==
+                                       SNDRV_PCM_STREAM_PLAYBACK
+                                       ? "capture" : "playback");
+                               return -EAGAIN;
+                       }
 
-       if (!ssi_private->first_stream)
-               ssi_private->first_stream = substream;
-       else {
-               /* This is the second stream open, so we need to impose sample
-                * rate and maybe sample size constraints.  Note that this can
-                * cause a race condition if the second stream is opened before
-                * the first stream is fully initialized.
-                *
-                * We provide some protection by checking to make sure the first
-                * stream is initialized, but it's not perfect.  ALSA sometimes
-                * re-initializes the driver with a different sample rate or
-                * size.  If the second stream is opened before the first stream
-                * has received its final parameters, then the second stream may
-                * be constrained to the wrong sample rate or size.
-                *
-                * FIXME: This code does not handle opening and closing streams
-                * repeatedly.  If you open two streams and then close the first
-                * one, you may not be able to open another stream until you
-                * close the second one as well.
-                */
-               struct snd_pcm_runtime *first_runtime =
-                       ssi_private->first_stream->runtime;
-
-               if (!first_runtime->sample_bits) {
-                       dev_err(substream->pcm->card->dev,
-                               "set sample size in %s stream first\n",
-                               substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-                               ? "capture" : "playback");
-                       return -EAGAIN;
-               }
-
-               /* If we're in synchronous mode, then we need to constrain
-                * the sample size as well.  We don't support independent sample
-                * rates in asynchronous mode.
-                */
-               if (!ssi_private->asynchronous)
                        snd_pcm_hw_constraint_minmax(substream->runtime,
                                SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
                                first_runtime->sample_bits,
                                first_runtime->sample_bits);
+               }
 
                ssi_private->second_stream = substream;
        }
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               ssi_private->playback++;
-
-       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-               ssi_private->capture++;
-
        return 0;
 }
 
@@ -434,24 +413,35 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
 {
        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
+       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       unsigned int sample_size =
+               snd_pcm_format_width(params_format(hw_params));
+       u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
+       int enabled = in_be32(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
 
-       if (substream == ssi_private->first_stream) {
-               struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-               unsigned int sample_size =
-                       snd_pcm_format_width(params_format(hw_params));
-               u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
+       /*
+        * If we're in synchronous mode, and the SSI is already enabled,
+        * then STCCR is already set properly.
+        */
+       if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
+               return 0;
 
-               /* The SSI should always be disabled at this points (SSIEN=0) */
+       /*
+        * FIXME: The documentation says that SxCCR[WL] should not be
+        * modified while the SSI is enabled.  The only time this can
+        * happen is if we're trying to do simultaneous playback and
+        * capture in asynchronous mode.  Unfortunately, I have been enable
+        * to get that to work at all on the P1022DS.  Therefore, we don't
+        * bother to disable/enable the SSI when setting SxCCR[WL], because
+        * the SSI will stop anyway.  Maybe one day, this will get fixed.
+        */
 
-               /* In synchronous mode, the SSI uses STCCR for capture */
-               if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
-                   !ssi_private->asynchronous)
-                       clrsetbits_be32(&ssi->stccr,
-                                       CCSR_SSI_SxCCR_WL_MASK, wl);
-               else
-                       clrsetbits_be32(&ssi->srccr,
-                                       CCSR_SSI_SxCCR_WL_MASK, wl);
-       }
+       /* In synchronous mode, the SSI uses STCCR for capture */
+       if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
+           ssi_private->cpu_dai_drv.symmetric_rates)
+               clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
+       else
+               clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
 
        return 0;
 }
@@ -474,7 +464,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        setbits32(&ssi->scr,
@@ -510,27 +499,18 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               ssi_private->playback--;
-
-       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-               ssi_private->capture--;
-
        if (ssi_private->first_stream == substream)
                ssi_private->first_stream = ssi_private->second_stream;
 
        ssi_private->second_stream = NULL;
 
        /*
-        * If this is the last active substream, disable the SSI and release
-        * the IRQ.
+        * If this is the last active substream, disable the SSI.
         */
-       if (!ssi_private->playback && !ssi_private->capture) {
+       if (!ssi_private->first_stream) {
                struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
 
                clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
-
-               free_irq(ssi_private->irq, ssi_private);
        }
 }
 
@@ -675,22 +655,33 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
        ret = of_address_to_resource(np, 0, &res);
        if (ret) {
                dev_err(&pdev->dev, "could not determine device resources\n");
-               kfree(ssi_private);
-               return ret;
+               goto error_kmalloc;
        }
        ssi_private->ssi = of_iomap(np, 0);
        if (!ssi_private->ssi) {
                dev_err(&pdev->dev, "could not map device resources\n");
-               kfree(ssi_private);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto error_kmalloc;
        }
        ssi_private->ssi_phys = res.start;
+
        ssi_private->irq = irq_of_parse_and_map(np, 0);
+       if (ssi_private->irq == NO_IRQ) {
+               dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
+               ret = -ENXIO;
+               goto error_iomap;
+       }
+
+       /* The 'name' should not have any slashes in it. */
+       ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name,
+                         ssi_private);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq);
+               goto error_irqmap;
+       }
 
        /* Are the RX and the TX clocks locked? */
-       if (of_find_property(np, "fsl,ssi-asynchronous", NULL))
-               ssi_private->asynchronous = 1;
-       else
+       if (!of_find_property(np, "fsl,ssi-asynchronous", NULL))
                ssi_private->cpu_dai_drv.symmetric_rates = 1;
 
        /* Determine the FIFO depth. */
@@ -711,7 +702,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
        if (ret) {
                dev_err(&pdev->dev, "could not create sysfs %s file\n",
                        ssi_private->dev_attr.attr.name);
-               goto error;
+               goto error_irq;
        }
 
        /* Register with ASoC */
@@ -720,7 +711,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
        ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv);
        if (ret) {
                dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
-               goto error;
+               goto error_dev;
        }
 
        /* Trigger the machine driver's probe function.  The platform driver
@@ -741,18 +732,28 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
        if (IS_ERR(ssi_private->pdev)) {
                ret = PTR_ERR(ssi_private->pdev);
                dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
-               goto error;
+               goto error_dai;
        }
 
        return 0;
 
-error:
+error_dai:
        snd_soc_unregister_dai(&pdev->dev);
+
+error_dev:
        dev_set_drvdata(&pdev->dev, NULL);
-       if (dev_attr)
-               device_remove_file(&pdev->dev, dev_attr);
+       device_remove_file(&pdev->dev, dev_attr);
+
+error_irq:
+       free_irq(ssi_private->irq, ssi_private);
+
+error_irqmap:
        irq_dispose_mapping(ssi_private->irq);
+
+error_iomap:
        iounmap(ssi_private->ssi);
+
+error_kmalloc:
        kfree(ssi_private);
 
        return ret;
@@ -766,6 +767,9 @@ static int fsl_ssi_remove(struct platform_device *pdev)
        snd_soc_unregister_dai(&pdev->dev);
        device_remove_file(&pdev->dev, &ssi_private->dev_attr);
 
+       free_irq(ssi_private->irq, ssi_private);
+       irq_dispose_mapping(ssi_private->irq);
+
        kfree(ssi_private);
        dev_set_drvdata(&pdev->dev, NULL);
 
index 358f0baaf71b2df230295cda7ccf9f4df2fa901a..31af405bda843cc691e755cc6bb4a0afec78925f 100644 (file)
@@ -505,7 +505,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
        return 0;
 
 error_sound:
-       platform_device_unregister(sound_device);
+       platform_device_put(sound_device);
 error:
        kfree(machine_data);
 error_alloc:
index fcb862eb0c73420e1c3ecb65c240e8ed2a2569f2..2c064a9824adf84d345829be5d6d80544df5c7d8 100644 (file)
@@ -267,7 +267,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
        if (bus < 0)
                return bus;
 
-       snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
+       snprintf(buf, len, "%s.%u-%04x", temp, bus, addr);
 
        return 0;
 }
@@ -506,7 +506,7 @@ static int p1022_ds_probe(struct platform_device *pdev)
 
 error:
        if (sound_device)
-               platform_device_unregister(sound_device);
+               platform_device_put(sound_device);
 
        kfree(mdata);
 error_put:
index 7945625e0e087090d62948e0cacd14f2c792acea..c8527ead373626baf114e089f049169f3c23a06e 100644 (file)
@@ -242,23 +242,22 @@ static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_dai *dai = rtd->cpu_dai;
        struct snd_pcm *pcm = rtd->pcm;
+       struct snd_pcm_substream *substream;
        int ret;
 
        ret = imx_pcm_new(rtd);
        if (ret)
                return ret;
 
-       if (dai->driver->playback.channels_min) {
-               struct snd_pcm_substream *substream =
-                       pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+       substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+       if (substream) {
                struct snd_dma_buffer *buf = &substream->dma_buffer;
 
                imx_ssi_fiq_tx_buffer = (unsigned long)buf->area;
        }
 
-       if (dai->driver->capture.channels_min) {
-               struct snd_pcm_substream *substream =
-                       pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+       substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+       if (substream) {
                struct snd_dma_buffer *buf = &substream->dma_buffer;
 
                imx_ssi_fiq_rx_buffer = (unsigned long)buf->area;
index 10a8e2783751bee1f137d959d3931544f8862f12..4297cb6af42e8a4eaec9bc5136ec3ed0cceaca9a 100644 (file)
@@ -357,8 +357,8 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
        struct snd_pcm_runtime *runtime = substream->runtime;
        int ret;
 
-       ret = dma_mmap_coherent(NULL, vma, runtime->dma_area,
-                       runtime->dma_addr, runtime->dma_bytes);
+       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,
@@ -399,14 +399,14 @@ int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
                card->dev->dma_mask = &imx_pcm_dmamask;
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
-       if (dai->driver->playback.channels_min) {
+       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = imx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->driver->capture.channels_min) {
+       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
                ret = imx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
index a7c9578be983d431c44a6631a14e688a58ec9560..d1989cde9f14d0d442531066f96b2a6e9c4f3525 100644 (file)
@@ -299,7 +299,7 @@ static void jz4740_pcm_free(struct snd_pcm *pcm)
 
 static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
 
-int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
+static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_soc_dai *dai = rtd->cpu_dai;
index 429aa1be2cffa6ae8d73b3d3547373afb74fd2cd..1d818dc57973bae18d0670e9d40e2c4da54fd8d4 100644 (file)
@@ -54,9 +54,7 @@ static unsigned int   hs_switch;
 static unsigned int    lo_dac;
 
 struct mfld_mc_private {
-       struct platform_device *socdev;
        void __iomem *int_base;
-       struct snd_soc_codec *codec;
        u8 interrupt_status;
 };
 
index 3e7826058efe61375b1fa938e1569cea87d7a21e..7df8c58ba50ae3ae0015e3f7cb915049a71cfb5c 100644 (file)
@@ -63,7 +63,7 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
 };
 
 /* MFLD - MSIC */
-struct snd_soc_dai_driver sst_platform_dai[] = {
+static struct snd_soc_dai_driver sst_platform_dai[] = {
 {
        .name = "Headset-cpu-dai",
        .id = 0,
@@ -226,13 +226,18 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
 
 static int sst_platform_open(struct snd_pcm_substream *substream)
 {
-       struct snd_pcm_runtime *runtime;
+       struct snd_pcm_runtime *runtime = substream->runtime;
        struct sst_runtime_stream *stream;
        int ret_val = 0;
 
        pr_debug("sst_platform_open called\n");
-       runtime = substream->runtime;
-       runtime->hw = sst_platform_pcm_hw;
+
+       snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw);
+       ret_val = snd_pcm_hw_constraint_integer(runtime,
+                                               SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret_val < 0)
+               return ret_val;
+
        stream = kzalloc(sizeof(*stream), GFP_KERNEL);
        if (!stream)
                return -ENOMEM;
@@ -259,8 +264,8 @@ static int sst_platform_open(struct snd_pcm_substream *substream)
                return ret_val;
        }
        runtime->private_data = stream;
-       return snd_pcm_hw_constraint_integer(runtime,
-                        SNDRV_PCM_HW_PARAM_PERIODS);
+
+       return 0;
 }
 
 static int sst_platform_close(struct snd_pcm_substream *substream)
@@ -469,7 +474,7 @@ static struct platform_driver sst_platform_driver = {
 static int __init sst_soc_platform_init(void)
 {
        pr_debug("sst_soc_platform_init called\n");
-       return  platform_driver_register(&sst_platform_driver);
+       return platform_driver_register(&sst_platform_driver);
 }
 module_init(sst_soc_platform_init);
 
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
new file mode 100644 (file)
index 0000000..e4ba8d5
--- /dev/null
@@ -0,0 +1,20 @@
+menuconfig SND_MXS_SOC
+       tristate "SoC Audio for Freescale MXS CPUs"
+       depends on ARCH_MXS
+       select SND_PCM
+       help
+         Say Y or M if you want to add support for codecs attached to
+         the MXS SAIF interface.
+
+
+if SND_MXS_SOC
+
+config SND_SOC_MXS_SGTL5000
+       tristate "SoC Audio support for i.MX boards with sgtl5000"
+       depends on I2C
+       select SND_SOC_SGTL5000
+       help
+         Say Y if you want to add support for SoC audio on an MXS board with
+         a sgtl5000 codec.
+
+endif  # SND_MXS_SOC
diff --git a/sound/soc/mxs/Makefile b/sound/soc/mxs/Makefile
new file mode 100644 (file)
index 0000000..565b5b5
--- /dev/null
@@ -0,0 +1,10 @@
+# MXS Platform Support
+snd-soc-mxs-objs := mxs-saif.o
+snd-soc-mxs-pcm-objs := mxs-pcm.o
+
+obj-$(CONFIG_SND_MXS_SOC) += snd-soc-mxs.o snd-soc-mxs-pcm.o
+
+# i.MX Machine Support
+snd-soc-mxs-sgtl5000-objs := mxs-sgtl5000.o
+
+obj-$(CONFIG_SND_SOC_MXS_SGTL5000) += snd-soc-mxs-sgtl5000.o
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
new file mode 100644 (file)
index 0000000..dea5aa4
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Based on sound/soc/imx/imx-pcm-dma-mx2.c
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dmaengine.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <mach/dma.h>
+#include "mxs-pcm.h"
+
+static struct snd_pcm_hardware snd_mxs_hardware = {
+       .info                   = SNDRV_PCM_INFO_MMAP |
+                                 SNDRV_PCM_INFO_MMAP_VALID |
+                                 SNDRV_PCM_INFO_PAUSE |
+                                 SNDRV_PCM_INFO_RESUME |
+                                 SNDRV_PCM_INFO_INTERLEAVED,
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE |
+                                 SNDRV_PCM_FMTBIT_S20_3LE |
+                                 SNDRV_PCM_FMTBIT_S24_LE,
+       .channels_min           = 2,
+       .channels_max           = 2,
+       .period_bytes_min       = 32,
+       .period_bytes_max       = 8192,
+       .periods_min            = 1,
+       .periods_max            = 52,
+       .buffer_bytes_max       = 64 * 1024,
+       .fifo_size              = 32,
+
+};
+
+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;
+
+       if (!mxs_dma_is_apbx(chan))
+               return false;
+
+       if (chan->chan_id != dma_params->chan_num)
+               return false;
+
+       chan->private = &iprtd->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_TO_DEVICE : DMA_FROM_DEVICE);
+       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;
+       int ret;
+
+       iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
+       if (iprtd == 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);
+               return ret;
+       }
+
+       snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
+
+       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;
+
+       kfree(iprtd);
+
+       return 0;
+}
+
+static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
+               struct vm_area_struct *vma)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+                                       runtime->dma_area,
+                                       runtime->dma_addr,
+                                       runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops mxs_pcm_ops = {
+       .open           = snd_mxs_open,
+       .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,
+       .mmap           = snd_mxs_pcm_mmap,
+};
+
+static int mxs_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 = snd_mxs_hardware.buffer_bytes_max;
+
+       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 mxs_pcm_dmamask = DMA_BIT_MASK(32);
+static int mxs_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 = &mxs_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 = mxs_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_PLAYBACK);
+               if (ret)
+                       goto out;
+       }
+
+       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+               ret = mxs_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_CAPTURE);
+               if (ret)
+                       goto out;
+       }
+
+out:
+       return ret;
+}
+
+static void mxs_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;
+       }
+}
+
+static struct snd_soc_platform_driver mxs_soc_platform = {
+       .ops            = &mxs_pcm_ops,
+       .pcm_new        = mxs_pcm_new,
+       .pcm_free       = mxs_pcm_free,
+};
+
+static int __devinit mxs_soc_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_platform(&pdev->dev, &mxs_soc_platform);
+}
+
+static int __devexit mxs_soc_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+
+       return 0;
+}
+
+static struct platform_driver mxs_pcm_driver = {
+       .driver = {
+               .name = "mxs-pcm-audio",
+               .owner = THIS_MODULE,
+       },
+       .probe = mxs_soc_platform_probe,
+       .remove = __devexit_p(mxs_soc_platform_remove),
+};
+
+static int __init snd_mxs_pcm_init(void)
+{
+       return platform_driver_register(&mxs_pcm_driver);
+}
+module_init(snd_mxs_pcm_init);
+
+static void __exit snd_mxs_pcm_exit(void)
+{
+       platform_driver_unregister(&mxs_pcm_driver);
+}
+module_exit(snd_mxs_pcm_exit);
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
new file mode 100644 (file)
index 0000000..f55ac4f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#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
new file mode 100644 (file)
index 0000000..401944c
--- /dev/null
@@ -0,0 +1,797 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/saif.h>
+#include <mach/dma.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/mxs.h>
+
+#include "mxs-saif.h"
+
+static struct mxs_saif *mxs_saif[2];
+
+/*
+ * SAIF is a little different with other normal SOC DAIs on clock using.
+ *
+ * For MXS, two SAIF modules are instantiated on-chip.
+ * Each SAIF has a set of clock pins and can be operating in master
+ * mode simultaneously if they are connected to different off-chip codecs.
+ * Also, one of the two SAIFs can master or drive the clock pins while the
+ * other SAIF, in slave mode, receives clocking from the master SAIF.
+ * This also means that both SAIFs must operate at the same sample rate.
+ *
+ * We abstract this as each saif has a master, the master could be
+ * himself or other saifs. In the generic saif driver, saif does not need
+ * to know the different clkmux. Saif only needs to know who is his master
+ * and operating his master to generate the proper clock rate for him.
+ * The master id is provided in mach-specific layer according to different
+ * clkmux setting.
+ */
+
+static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+                       int clk_id, unsigned int freq, int dir)
+{
+       struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+
+       switch (clk_id) {
+       case MXS_SAIF_MCLK:
+               saif->mclk = freq;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK
+ * is provided by other SAIF, we provide a interface here to get its master
+ * from its master_id.
+ * Note that the master could be himself.
+ */
+static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif)
+{
+       return mxs_saif[saif->master_id];
+}
+
+/*
+ * Set SAIF clock and MCLK
+ */
+static int mxs_saif_set_clk(struct mxs_saif *saif,
+                                 unsigned int mclk,
+                                 unsigned int rate)
+{
+       u32 scr;
+       int ret;
+       struct mxs_saif *master_saif;
+
+       dev_dbg(saif->dev, "mclk %d rate %d\n", mclk, rate);
+
+       /* Set master saif to generate proper clock */
+       master_saif = mxs_saif_get_master(saif);
+       if (!master_saif)
+               return -EINVAL;
+
+       dev_dbg(saif->dev, "master saif%d\n", master_saif->id);
+
+       /* Checking if can playback and capture simutaneously */
+       if (master_saif->ongoing && rate != master_saif->cur_rate) {
+               dev_err(saif->dev,
+                       "can not change clock, master saif%d(rate %d) is ongoing\n",
+                       master_saif->id, master_saif->cur_rate);
+               return -EINVAL;
+       }
+
+       scr = __raw_readl(master_saif->base + SAIF_CTRL);
+       scr &= ~BM_SAIF_CTRL_BITCLK_MULT_RATE;
+       scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
+
+       /*
+        * Set SAIF clock
+        *
+        * The SAIF clock should be either 384*fs or 512*fs.
+        * If MCLK is used, the SAIF clk ratio need to match mclk ratio.
+        *  For 32x mclk, set saif clk as 512*fs.
+        *  For 48x mclk, set saif clk as 384*fs.
+        *
+        * If MCLK is not used, we just set saif clk to 512*fs.
+        */
+       if (master_saif->mclk_in_use) {
+               if (mclk % 32 == 0) {
+                       scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
+                       ret = clk_set_rate(master_saif->clk, 512 * rate);
+               } else if (mclk % 48 == 0) {
+                       scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE;
+                       ret = clk_set_rate(master_saif->clk, 384 * rate);
+               } else {
+                       /* SAIF MCLK should be either 32x or 48x */
+                       return -EINVAL;
+               }
+       } else {
+               ret = clk_set_rate(master_saif->clk, 512 * rate);
+               scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
+       }
+
+       if (ret)
+               return ret;
+
+       master_saif->cur_rate = rate;
+
+       if (!master_saif->mclk_in_use) {
+               __raw_writel(scr, master_saif->base + SAIF_CTRL);
+               return 0;
+       }
+
+       /*
+        * Program the over-sample rate for MCLK output
+        *
+        * The available MCLK range is 32x, 48x... 512x. The rate
+        * could be from 8kHz to 192kH.
+        */
+       switch (mclk / rate) {
+       case 32:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(4);
+               break;
+       case 64:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3);
+               break;
+       case 128:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2);
+               break;
+       case 256:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1);
+               break;
+       case 512:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0);
+               break;
+       case 48:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3);
+               break;
+       case 96:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2);
+               break;
+       case 192:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1);
+               break;
+       case 384:
+               scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       __raw_writel(scr, master_saif->base + SAIF_CTRL);
+
+       return 0;
+}
+
+/*
+ * Put and disable MCLK.
+ */
+int mxs_saif_put_mclk(unsigned int saif_id)
+{
+       struct mxs_saif *saif = mxs_saif[saif_id];
+       u32 stat;
+
+       if (!saif)
+               return -EINVAL;
+
+       stat = __raw_readl(saif->base + SAIF_STAT);
+       if (stat & BM_SAIF_STAT_BUSY) {
+               dev_err(saif->dev, "error: busy\n");
+               return -EBUSY;
+       }
+
+       clk_disable(saif->clk);
+
+       /* disable MCLK output */
+       __raw_writel(BM_SAIF_CTRL_CLKGATE,
+               saif->base + SAIF_CTRL + MXS_SET_ADDR);
+       __raw_writel(BM_SAIF_CTRL_RUN,
+               saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+       saif->mclk_in_use = 0;
+       return 0;
+}
+
+/*
+ * Get MCLK and set clock rate, then enable it
+ *
+ * This interface is used for codecs who are using MCLK provided
+ * by saif.
+ */
+int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
+                                       unsigned int rate)
+{
+       struct mxs_saif *saif = mxs_saif[saif_id];
+       u32 stat;
+       int ret;
+       struct mxs_saif *master_saif;
+
+       if (!saif)
+               return -EINVAL;
+
+       /* Clear Reset */
+       __raw_writel(BM_SAIF_CTRL_SFTRST,
+               saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+       /* FIXME: need clear clk gate for register r/w */
+       __raw_writel(BM_SAIF_CTRL_CLKGATE,
+               saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+       master_saif = mxs_saif_get_master(saif);
+       if (saif != master_saif) {
+               dev_err(saif->dev, "can not get mclk from a non-master saif\n");
+               return -EINVAL;
+       }
+
+       stat = __raw_readl(saif->base + SAIF_STAT);
+       if (stat & BM_SAIF_STAT_BUSY) {
+               dev_err(saif->dev, "error: busy\n");
+               return -EBUSY;
+       }
+
+       saif->mclk_in_use = 1;
+       ret = mxs_saif_set_clk(saif, mclk, rate);
+       if (ret)
+               return ret;
+
+       ret = clk_enable(saif->clk);
+       if (ret)
+               return ret;
+
+       /* enable MCLK output */
+       __raw_writel(BM_SAIF_CTRL_RUN,
+               saif->base + SAIF_CTRL + MXS_SET_ADDR);
+
+       return 0;
+}
+
+/*
+ * SAIF DAI format configuration.
+ * Should only be called when port is inactive.
+ */
+static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+       u32 scr, stat;
+       u32 scr0;
+       struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+
+       stat = __raw_readl(saif->base + SAIF_STAT);
+       if (stat & BM_SAIF_STAT_BUSY) {
+               dev_err(cpu_dai->dev, "error: busy\n");
+               return -EBUSY;
+       }
+
+       scr0 = __raw_readl(saif->base + SAIF_CTRL);
+       scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \
+               & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY;
+       scr = 0;
+
+       /* DAI mode */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               /* data frame low 1clk before data */
+               scr |= BM_SAIF_CTRL_DELAY;
+               scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               /* data frame high with data */
+               scr &= ~BM_SAIF_CTRL_DELAY;
+               scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
+               scr &= ~BM_SAIF_CTRL_JUSTIFY;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* DAI clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_IB_IF:
+               scr |= BM_SAIF_CTRL_BITCLK_EDGE;
+               scr |= BM_SAIF_CTRL_LRCLK_POLARITY;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               scr |= BM_SAIF_CTRL_BITCLK_EDGE;
+               scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               scr &= ~BM_SAIF_CTRL_BITCLK_EDGE;
+               scr |= BM_SAIF_CTRL_LRCLK_POLARITY;
+               break;
+       case SND_SOC_DAIFMT_NB_NF:
+               scr &= ~BM_SAIF_CTRL_BITCLK_EDGE;
+               scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
+               break;
+       }
+
+       /*
+        * Note: We simply just support master mode since SAIF TX can only
+        * work as master.
+        * Here the master is relative to codec side.
+        * Saif internally could be slave when working on EXTMASTER mode.
+        * We just hide this to machine driver.
+        */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               if (saif->id == saif->master_id)
+                       scr &= ~BM_SAIF_CTRL_SLAVE_MODE;
+               else
+                       scr |= BM_SAIF_CTRL_SLAVE_MODE;
+
+               __raw_writel(scr | scr0, saif->base + SAIF_CTRL);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mxs_saif_startup(struct snd_pcm_substream *substream,
+                          struct snd_soc_dai *cpu_dai)
+{
+       struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+       snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param);
+
+       /* clear error status to 0 for each re-open */
+       saif->fifo_underrun = 0;
+       saif->fifo_overrun = 0;
+
+       /* Clear Reset for normal operations */
+       __raw_writel(BM_SAIF_CTRL_SFTRST,
+               saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+       /* clear clock gate */
+       __raw_writel(BM_SAIF_CTRL_CLKGATE,
+               saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+       return 0;
+}
+
+/*
+ * Should only be called when port is inactive.
+ * although can be called multiple times by upper layers.
+ */
+static int mxs_saif_hw_params(struct snd_pcm_substream *substream,
+                            struct snd_pcm_hw_params *params,
+                            struct snd_soc_dai *cpu_dai)
+{
+       struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+       u32 scr, stat;
+       int ret;
+
+       /* mclk should already be set */
+       if (!saif->mclk && saif->mclk_in_use) {
+               dev_err(cpu_dai->dev, "set mclk first\n");
+               return -EINVAL;
+       }
+
+       stat = __raw_readl(saif->base + SAIF_STAT);
+       if (stat & BM_SAIF_STAT_BUSY) {
+               dev_err(cpu_dai->dev, "error: busy\n");
+               return -EBUSY;
+       }
+
+       /*
+        * Set saif clk based on sample rate.
+        * If mclk is used, we also set mclk, if not, saif->mclk is
+        * default 0, means not used.
+        */
+       ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params));
+       if (ret) {
+               dev_err(cpu_dai->dev, "unable to get proper clk\n");
+               return ret;
+       }
+
+       scr = __raw_readl(saif->base + SAIF_CTRL);
+
+       scr &= ~BM_SAIF_CTRL_WORD_LENGTH;
+       scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               scr |= BF_SAIF_CTRL_WORD_LENGTH(0);
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               scr |= BF_SAIF_CTRL_WORD_LENGTH(4);
+               scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               scr |= BF_SAIF_CTRL_WORD_LENGTH(8);
+               scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Tx/Rx config */
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               /* enable TX mode */
+               scr &= ~BM_SAIF_CTRL_READ_MODE;
+       } else {
+               /* enable RX mode */
+               scr |= BM_SAIF_CTRL_READ_MODE;
+       }
+
+       __raw_writel(scr, saif->base + SAIF_CTRL);
+       return 0;
+}
+
+static int mxs_saif_prepare(struct snd_pcm_substream *substream,
+                          struct snd_soc_dai *cpu_dai)
+{
+       struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+
+       /* enable FIFO error irqs */
+       __raw_writel(BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN,
+               saif->base + SAIF_CTRL + MXS_SET_ADDR);
+
+       return 0;
+}
+
+static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
+                               struct snd_soc_dai *cpu_dai)
+{
+       struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+       struct mxs_saif *master_saif;
+       u32 delay;
+
+       master_saif = mxs_saif_get_master(saif);
+       if (!master_saif)
+               return -EINVAL;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               dev_dbg(cpu_dai->dev, "start\n");
+
+               clk_enable(master_saif->clk);
+               if (!master_saif->mclk_in_use)
+                       __raw_writel(BM_SAIF_CTRL_RUN,
+                               master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
+
+               /*
+                * If the saif's master is not himself, we also need to enable
+                * itself clk for its internal basic logic to work.
+                */
+               if (saif != master_saif) {
+                       clk_enable(saif->clk);
+                       __raw_writel(BM_SAIF_CTRL_RUN,
+                               saif->base + SAIF_CTRL + MXS_SET_ADDR);
+               }
+
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       /*
+                        * write a data to saif data register to trigger
+                        * the transfer
+                        */
+                       __raw_writel(0, saif->base + SAIF_DATA);
+               } else {
+                       /*
+                        * read a data from saif data register to trigger
+                        * the receive
+                        */
+                       __raw_readl(saif->base + SAIF_DATA);
+               }
+
+               master_saif->ongoing = 1;
+
+               dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n",
+                       __raw_readl(saif->base + SAIF_CTRL),
+                       __raw_readl(saif->base + SAIF_STAT));
+
+               dev_dbg(master_saif->dev, "CTRL 0x%x STAT 0x%x\n",
+                       __raw_readl(master_saif->base + SAIF_CTRL),
+                       __raw_readl(master_saif->base + SAIF_STAT));
+               break;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               dev_dbg(cpu_dai->dev, "stop\n");
+
+               /* wait a while for the current sample to complete */
+               delay = USEC_PER_SEC / master_saif->cur_rate;
+
+               if (!master_saif->mclk_in_use) {
+                       __raw_writel(BM_SAIF_CTRL_RUN,
+                               master_saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+                       udelay(delay);
+               }
+               clk_disable(master_saif->clk);
+
+               if (saif != master_saif) {
+                       __raw_writel(BM_SAIF_CTRL_RUN,
+                               saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+                       udelay(delay);
+                       clk_disable(saif->clk);
+               }
+
+               master_saif->ongoing = 0;
+
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+#define MXS_SAIF_RATES         SNDRV_PCM_RATE_8000_192000
+#define MXS_SAIF_FORMATS \
+       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+       SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops mxs_saif_dai_ops = {
+       .startup = mxs_saif_startup,
+       .trigger = mxs_saif_trigger,
+       .prepare = mxs_saif_prepare,
+       .hw_params = mxs_saif_hw_params,
+       .set_sysclk = mxs_saif_set_dai_sysclk,
+       .set_fmt = mxs_saif_set_dai_fmt,
+};
+
+static int mxs_saif_dai_probe(struct snd_soc_dai *dai)
+{
+       struct mxs_saif *saif = dev_get_drvdata(dai->dev);
+
+       snd_soc_dai_set_drvdata(dai, saif);
+
+       return 0;
+}
+
+static struct snd_soc_dai_driver mxs_saif_dai = {
+       .name = "mxs-saif",
+       .probe = mxs_saif_dai_probe,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = MXS_SAIF_RATES,
+               .formats = MXS_SAIF_FORMATS,
+       },
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = MXS_SAIF_RATES,
+               .formats = MXS_SAIF_FORMATS,
+       },
+       .ops = &mxs_saif_dai_ops,
+};
+
+static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
+{
+       struct mxs_saif *saif = dev_id;
+       unsigned int stat;
+
+       stat = __raw_readl(saif->base + SAIF_STAT);
+       if (!(stat & (BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ |
+                       BM_SAIF_STAT_FIFO_OVERFLOW_IRQ)))
+               return IRQ_NONE;
+
+       if (stat & BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ) {
+               dev_dbg(saif->dev, "underrun!!! %d\n", ++saif->fifo_underrun);
+               __raw_writel(BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ,
+                               saif->base + SAIF_STAT + MXS_CLR_ADDR);
+       }
+
+       if (stat & BM_SAIF_STAT_FIFO_OVERFLOW_IRQ) {
+               dev_dbg(saif->dev, "overrun!!! %d\n", ++saif->fifo_overrun);
+               __raw_writel(BM_SAIF_STAT_FIFO_OVERFLOW_IRQ,
+                               saif->base + SAIF_STAT + MXS_CLR_ADDR);
+       }
+
+       dev_dbg(saif->dev, "SAIF_CTRL %x SAIF_STAT %x\n",
+              __raw_readl(saif->base + SAIF_CTRL),
+              __raw_readl(saif->base + SAIF_STAT));
+
+       return IRQ_HANDLED;
+}
+
+static int mxs_saif_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct mxs_saif *saif;
+       struct mxs_saif_platform_data *pdata;
+       int ret = 0;
+
+       if (pdev->id >= ARRAY_SIZE(mxs_saif))
+               return -EINVAL;
+
+       pdata = pdev->dev.platform_data;
+       if (pdata && pdata->init) {
+               ret = pdata->init();
+               if (ret)
+                       return ret;
+       }
+
+       saif = kzalloc(sizeof(*saif), GFP_KERNEL);
+       if (!saif)
+               return -ENOMEM;
+
+       mxs_saif[pdev->id] = saif;
+       saif->id = pdev->id;
+
+       saif->master_id = saif->id;
+       if (pdata && pdata->get_master_id) {
+               saif->master_id = pdata->get_master_id(saif->id);
+               if (saif->master_id < 0 ||
+                       saif->master_id >= ARRAY_SIZE(mxs_saif))
+                       return -EINVAL;
+       }
+
+       saif->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(saif->clk)) {
+               ret = PTR_ERR(saif->clk);
+               dev_err(&pdev->dev, "Cannot get the clock: %d\n",
+                       ret);
+               goto failed_clk;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               dev_err(&pdev->dev, "failed to get io resource: %d\n",
+                       ret);
+               goto failed_get_resource;
+       }
+
+       if (!request_mem_region(res->start, resource_size(res), "mxs-saif")) {
+               dev_err(&pdev->dev, "request_mem_region failed\n");
+               ret = -EBUSY;
+               goto failed_get_resource;
+       }
+
+       saif->base = ioremap(res->start, resource_size(res));
+       if (!saif->base) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               ret = -ENODEV;
+               goto failed_ioremap;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               ret = -ENODEV;
+               dev_err(&pdev->dev, "failed to get dma resource: %d\n",
+                       ret);
+               goto failed_ioremap;
+       }
+       saif->dma_param.chan_num = res->start;
+
+       saif->irq = platform_get_irq(pdev, 0);
+       if (saif->irq < 0) {
+               ret = saif->irq;
+               dev_err(&pdev->dev, "failed to get irq resource: %d\n",
+                       ret);
+               goto failed_get_irq1;
+       }
+
+       saif->dev = &pdev->dev;
+       ret = request_irq(saif->irq, mxs_saif_irq, 0, "mxs-saif", saif);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to request irq\n");
+               goto failed_get_irq1;
+       }
+
+       saif->dma_param.chan_irq = platform_get_irq(pdev, 1);
+       if (saif->dma_param.chan_irq < 0) {
+               ret = saif->dma_param.chan_irq;
+               dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
+                       ret);
+               goto failed_get_irq2;
+       }
+
+       platform_set_drvdata(pdev, saif);
+
+       ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai);
+       if (ret) {
+               dev_err(&pdev->dev, "register DAI failed\n");
+               goto failed_register;
+       }
+
+       saif->soc_platform_pdev = platform_device_alloc(
+                                       "mxs-pcm-audio", pdev->id);
+       if (!saif->soc_platform_pdev) {
+               ret = -ENOMEM;
+               goto failed_pdev_alloc;
+       }
+
+       platform_set_drvdata(saif->soc_platform_pdev, saif);
+       ret = platform_device_add(saif->soc_platform_pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to add soc platform device\n");
+               goto failed_pdev_add;
+       }
+
+       return 0;
+
+failed_pdev_add:
+       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(res->start, resource_size(res));
+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;
+}
+
+static struct platform_driver mxs_saif_driver = {
+       .probe = mxs_saif_probe,
+       .remove = __devexit_p(mxs_saif_remove),
+
+       .driver = {
+               .name = "mxs-saif",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init mxs_saif_init(void)
+{
+       return platform_driver_register(&mxs_saif_driver);
+}
+
+static void __exit mxs_saif_exit(void)
+{
+       platform_driver_unregister(&mxs_saif_driver);
+}
+
+module_init(mxs_saif_init);
+module_exit(mxs_saif_exit);
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXS ASoC SAIF driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h
new file mode 100644 (file)
index 0000000..12c91e4
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef _MXS_SAIF_H
+#define _MXS_SAIF_H
+
+#define SAIF_CTRL      0x0
+#define SAIF_STAT      0x10
+#define SAIF_DATA      0x20
+#define SAIF_VERSION   0X30
+
+/* SAIF_CTRL */
+#define BM_SAIF_CTRL_SFTRST            0x80000000
+#define BM_SAIF_CTRL_CLKGATE           0x40000000
+#define BP_SAIF_CTRL_BITCLK_MULT_RATE  27
+#define BM_SAIF_CTRL_BITCLK_MULT_RATE  0x38000000
+#define BF_SAIF_CTRL_BITCLK_MULT_RATE(v) \
+               (((v) << 27) & BM_SAIF_CTRL_BITCLK_MULT_RATE)
+#define BM_SAIF_CTRL_BITCLK_BASE_RATE  0x04000000
+#define BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN 0x02000000
+#define BM_SAIF_CTRL_FIFO_SERVICE_IRQ_EN       0x01000000
+#define BP_SAIF_CTRL_RSRVD2            21
+#define BM_SAIF_CTRL_RSRVD2            0x00E00000
+
+#define BP_SAIF_CTRL_DMAWAIT_COUNT     16
+#define BM_SAIF_CTRL_DMAWAIT_COUNT     0x001F0000
+#define BF_SAIF_CTRL_DMAWAIT_COUNT(v) \
+               (((v) << 16) & BM_SAIF_CTRL_DMAWAIT_COUNT)
+#define BP_SAIF_CTRL_CHANNEL_NUM_SELECT 14
+#define BM_SAIF_CTRL_CHANNEL_NUM_SELECT 0x0000C000
+#define BF_SAIF_CTRL_CHANNEL_NUM_SELECT(v) \
+               (((v) << 14) & BM_SAIF_CTRL_CHANNEL_NUM_SELECT)
+#define BM_SAIF_CTRL_LRCLK_PULSE       0x00002000
+#define BM_SAIF_CTRL_BIT_ORDER         0x00001000
+#define BM_SAIF_CTRL_DELAY             0x00000800
+#define BM_SAIF_CTRL_JUSTIFY           0x00000400
+#define BM_SAIF_CTRL_LRCLK_POLARITY    0x00000200
+#define BM_SAIF_CTRL_BITCLK_EDGE       0x00000100
+#define BP_SAIF_CTRL_WORD_LENGTH       4
+#define BM_SAIF_CTRL_WORD_LENGTH       0x000000F0
+#define BF_SAIF_CTRL_WORD_LENGTH(v) \
+               (((v) << 4) & BM_SAIF_CTRL_WORD_LENGTH)
+#define BM_SAIF_CTRL_BITCLK_48XFS_ENABLE       0x00000008
+#define BM_SAIF_CTRL_SLAVE_MODE                0x00000004
+#define BM_SAIF_CTRL_READ_MODE         0x00000002
+#define BM_SAIF_CTRL_RUN               0x00000001
+
+/* SAIF_STAT */
+#define BM_SAIF_STAT_PRESENT           0x80000000
+#define BP_SAIF_STAT_RSRVD2            17
+#define BM_SAIF_STAT_RSRVD2            0x7FFE0000
+#define BF_SAIF_STAT_RSRVD2(v) \
+               (((v) << 17) & BM_SAIF_STAT_RSRVD2)
+#define BM_SAIF_STAT_DMA_PREQ          0x00010000
+#define BP_SAIF_STAT_RSRVD1            7
+#define BM_SAIF_STAT_RSRVD1            0x0000FF80
+#define BF_SAIF_STAT_RSRVD1(v) \
+               (((v) << 7) & BM_SAIF_STAT_RSRVD1)
+
+#define BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ 0x00000040
+#define BM_SAIF_STAT_FIFO_OVERFLOW_IRQ 0x00000020
+#define BM_SAIF_STAT_FIFO_SERVICE_IRQ  0x00000010
+#define BP_SAIF_STAT_RSRVD0            1
+#define BM_SAIF_STAT_RSRVD0            0x0000000E
+#define BF_SAIF_STAT_RSRVD0(v) \
+               (((v) << 1) & BM_SAIF_STAT_RSRVD0)
+#define BM_SAIF_STAT_BUSY              0x00000001
+
+/* SAFI_DATA */
+#define BP_SAIF_DATA_PCM_RIGHT         16
+#define BM_SAIF_DATA_PCM_RIGHT         0xFFFF0000
+#define BF_SAIF_DATA_PCM_RIGHT(v) \
+               (((v) << 16) & BM_SAIF_DATA_PCM_RIGHT)
+#define BP_SAIF_DATA_PCM_LEFT          0
+#define BM_SAIF_DATA_PCM_LEFT          0x0000FFFF
+#define BF_SAIF_DATA_PCM_LEFT(v)       \
+               (((v) << 0) & BM_SAIF_DATA_PCM_LEFT)
+
+/* SAIF_VERSION */
+#define BP_SAIF_VERSION_MAJOR          24
+#define BM_SAIF_VERSION_MAJOR          0xFF000000
+#define BF_SAIF_VERSION_MAJOR(v) \
+               (((v) << 24) & BM_SAIF_VERSION_MAJOR)
+#define BP_SAIF_VERSION_MINOR          16
+#define BM_SAIF_VERSION_MINOR          0x00FF0000
+#define BF_SAIF_VERSION_MINOR(v) \
+               (((v) << 16) & BM_SAIF_VERSION_MINOR)
+#define BP_SAIF_VERSION_STEP           0
+#define BM_SAIF_VERSION_STEP           0x0000FFFF
+#define BF_SAIF_VERSION_STEP(v) \
+               (((v) << 0) & BM_SAIF_VERSION_STEP)
+
+#define MXS_SAIF_MCLK          0
+
+#include "mxs-pcm.h"
+
+struct mxs_saif {
+       struct device *dev;
+       struct clk *clk;
+       unsigned int mclk;
+       unsigned int mclk_in_use;
+       void __iomem *base;
+       int irq;
+       struct mxs_pcm_dma_params dma_param;
+       unsigned int id;
+       unsigned int master_id;
+       unsigned int cur_rate;
+       unsigned int ongoing;
+
+       struct platform_device *soc_platform_pdev;
+       u32 fifo_underrun;
+       u32 fifo_overrun;
+};
+
+extern int mxs_saif_put_mclk(unsigned int saif_id);
+extern int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
+                                       unsigned int rate);
+#endif
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
new file mode 100644 (file)
index 0000000..7fbeaec
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/soc-dapm.h>
+#include <asm/mach-types.h>
+
+#include "../codecs/sgtl5000.h"
+#include "mxs-saif.h"
+
+static int mxs_sgtl5000_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_dai *cpu_dai = rtd->cpu_dai;
+       unsigned int rate = params_rate(params);
+       u32 dai_format, mclk;
+       int ret;
+
+       /* sgtl5000 does not support 512*rate when in 96000 fs */
+       switch (rate) {
+       case 96000:
+               mclk = 256 * rate;
+               break;
+       default:
+               mclk = 512 * rate;
+               break;
+       }
+
+       /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */
+       if (mclk < 8000000 || mclk > 27000000)
+               return -EINVAL;
+
+       /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */
+       ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0);
+       if (ret)
+               return ret;
+
+       /* The SAIF MCLK should be the same as SGTL5000_SYSCLK */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0);
+       if (ret)
+               return ret;
+
+       /* set codec to slave mode */
+       dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS;
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
+       if (ret)
+               return ret;
+
+       /* set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_ops mxs_sgtl5000_hifi_ops = {
+       .hw_params = mxs_sgtl5000_hw_params,
+};
+
+static struct snd_soc_dai_link mxs_sgtl5000_dai[] = {
+       {
+               .name           = "HiFi Tx",
+               .stream_name    = "HiFi Playback",
+               .codec_dai_name = "sgtl5000",
+               .codec_name     = "sgtl5000.0-000a",
+               .cpu_dai_name   = "mxs-saif.0",
+               .platform_name  = "mxs-pcm-audio.0",
+               .ops            = &mxs_sgtl5000_hifi_ops,
+       }, {
+               .name           = "HiFi Rx",
+               .stream_name    = "HiFi Capture",
+               .codec_dai_name = "sgtl5000",
+               .codec_name     = "sgtl5000.0-000a",
+               .cpu_dai_name   = "mxs-saif.1",
+               .platform_name  = "mxs-pcm-audio.1",
+               .ops            = &mxs_sgtl5000_hifi_ops,
+       },
+};
+
+static struct snd_soc_card mxs_sgtl5000 = {
+       .name           = "mxs_sgtl5000",
+       .dai_link       = mxs_sgtl5000_dai,
+       .num_links      = ARRAY_SIZE(mxs_sgtl5000_dai),
+};
+
+static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &mxs_sgtl5000;
+       int ret;
+
+       /*
+        * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w).
+        * The Sgtl5000 sysclk is derived from saif0 mclk and it's range
+        * should be >= 8MHz and <= 27M.
+        */
+       ret = mxs_saif_get_mclk(0, 44100 * 256, 44100);
+       if (ret)
+               return ret;
+
+       card->dev = &pdev->dev;
+       platform_set_drvdata(pdev, card);
+
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       mxs_saif_put_mclk(0);
+
+       snd_soc_unregister_card(card);
+
+       return 0;
+}
+
+static struct platform_driver mxs_sgtl5000_audio_driver = {
+       .driver = {
+               .name = "mxs-sgtl5000",
+               .owner = THIS_MODULE,
+       },
+       .probe = mxs_sgtl5000_probe,
+       .remove = __devexit_p(mxs_sgtl5000_remove),
+};
+
+static int __init mxs_sgtl5000_init(void)
+{
+       return platform_driver_register(&mxs_sgtl5000_audio_driver);
+}
+module_init(mxs_sgtl5000_init);
+
+static void __exit mxs_sgtl5000_exit(void)
+{
+       platform_driver_unregister(&mxs_sgtl5000_audio_driver);
+}
+module_exit(mxs_sgtl5000_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXS ALSA SoC Machine driver");
+MODULE_LICENSE("GPL");
index d589ef14e917e95648b91daede2c53eae079e6a5..4e3626b9d8f9307df21c7327494bc9e1bc8ae840 100644 (file)
@@ -227,7 +227,7 @@ static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd)
        return ret;
 }
 
-int nuc900_dma_getposition(struct snd_pcm_substream *substream,
+static int nuc900_dma_getposition(struct snd_pcm_substream *substream,
                                        dma_addr_t *src, dma_addr_t *dst)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -318,7 +318,6 @@ static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32);
 static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
-       struct snd_soc_dai *dai = rtd->cpu_dai;
        struct snd_pcm *pcm = rtd->pcm;
 
        if (!card->dev->dma_mask)
index 59e2c8d1e38da13e334be2db1eb0143d0a501b63..052fd758722eb0cdc2db322476546228d5e534e8 100644 (file)
@@ -1,7 +1,7 @@
 # OMAP Platform Support
 snd-soc-omap-objs := omap-pcm.o
 snd-soc-omap-mcbsp-objs := omap-mcbsp.o
-snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o
+snd-soc-omap-mcpdm-objs := omap-mcpdm.o
 snd-soc-omap-hdmi-objs := omap-hdmi.o
 
 obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
index 73dde4a1adc34b9c0af6ea8a8dc617408f2ca207..48af0f87f84d9c8f34519e40fcfdb04e43d1ba7b 100644 (file)
@@ -43,26 +43,6 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0,
                        CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -140,6 +120,8 @@ static struct snd_soc_dai_link am3517evm_dai = {
        .codec_dai_name = "tlv320aic23-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "tlv320aic23-codec.2-001a",
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .init = am3517evm_aic23_init,
        .ops = &am3517evm_ops,
 };
index 0ae34702995ba6316cbe63defd1fd73d0948034f..84615a7de6adcd98ff7d808f73439a51a67df49d 100644 (file)
@@ -38,29 +38,8 @@ static int igep2_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                            SND_SOC_CLOCK_IN);
@@ -84,6 +63,8 @@ static struct snd_soc_dai_link igep2_dai = {
        .codec_dai_name = "twl4030-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "twl4030-codec",
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops = &igep2_ops,
 };
 
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
deleted file mode 100644 (file)
index 928f037..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * mcpdm.c  -- McPDM interface driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- * Copyright (C) 2009 - Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include "mcpdm.h"
-
-static struct omap_mcpdm *mcpdm;
-
-static inline void omap_mcpdm_write(u16 reg, u32 val)
-{
-       __raw_writel(val, mcpdm->io_base + reg);
-}
-
-static inline int omap_mcpdm_read(u16 reg)
-{
-       return __raw_readl(mcpdm->io_base + reg);
-}
-
-static void omap_mcpdm_reg_dump(void)
-{
-       dev_dbg(mcpdm->dev, "***********************\n");
-       dev_dbg(mcpdm->dev, "IRQSTATUS_RAW:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
-       dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQSTATUS));
-       dev_dbg(mcpdm->dev, "IRQENABLE_SET:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQENABLE_SET));
-       dev_dbg(mcpdm->dev, "IRQENABLE_CLR:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
-       dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQWAKE_EN));
-       dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DMAENABLE_SET));
-       dev_dbg(mcpdm->dev, "DMAENABLE_CLR:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
-       dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DMAWAKEEN));
-       dev_dbg(mcpdm->dev, "CTRL:      0x%04x\n",
-                       omap_mcpdm_read(MCPDM_CTRL));
-       dev_dbg(mcpdm->dev, "DN_DATA:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DN_DATA));
-       dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_UP_DATA));
-       dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
-       dev_dbg(mcpdm->dev, "FIFO_CTRL_UP:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
-       dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DN_OFFSET));
-       dev_dbg(mcpdm->dev, "***********************\n");
-}
-
-/*
- * Takes the McPDM module in and out of reset state.
- * Uplink and downlink can be reset individually.
- */
-static void omap_mcpdm_reset_capture(int reset)
-{
-       int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-       if (reset)
-               ctrl |= SW_UP_RST;
-       else
-               ctrl &= ~SW_UP_RST;
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-static void omap_mcpdm_reset_playback(int reset)
-{
-       int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-       if (reset)
-               ctrl |= SW_DN_RST;
-       else
-               ctrl &= ~SW_DN_RST;
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Enables the transfer through the PDM interface to/from the Phoenix
- * codec by enabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_start(int stream)
-{
-       int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-       if (stream)
-               ctrl |= mcpdm->up_channels;
-       else
-               ctrl |= mcpdm->dn_channels;
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Disables the transfer through the PDM interface to/from the Phoenix
- * codec by disabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_stop(int stream)
-{
-       int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-       if (stream)
-               ctrl &= ~mcpdm->up_channels;
-       else
-               ctrl &= ~mcpdm->dn_channels;
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Configures McPDM uplink for audio recording.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
-{
-       int irq_mask = 0;
-       int ctrl;
-
-       if (!uplink)
-               return -EINVAL;
-
-       mcpdm->uplink = uplink;
-
-       /* Enable irq request generation */
-       irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
-       omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
-       /* Configure uplink threshold */
-       if (uplink->threshold > UP_THRES_MAX)
-               uplink->threshold = UP_THRES_MAX;
-
-       omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
-
-       /* Configure DMA controller */
-       omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
-
-       /* Set pdm out format */
-       ctrl = omap_mcpdm_read(MCPDM_CTRL);
-       ctrl &= ~PDMOUTFORMAT;
-       ctrl |= uplink->format & PDMOUTFORMAT;
-
-       /* Uplink channels */
-       mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
-       return 0;
-}
-
-/*
- * Configures McPDM downlink for audio playback.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
-{
-       int irq_mask = 0;
-       int ctrl;
-
-       if (!downlink)
-               return -EINVAL;
-
-       mcpdm->downlink = downlink;
-
-       /* Enable irq request generation */
-       irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
-       omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
-       /* Configure uplink threshold */
-       if (downlink->threshold > DN_THRES_MAX)
-               downlink->threshold = DN_THRES_MAX;
-
-       omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
-
-       /* Enable DMA request generation */
-       omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
-
-       /* Set pdm out format */
-       ctrl = omap_mcpdm_read(MCPDM_CTRL);
-       ctrl &= ~PDMOUTFORMAT;
-       ctrl |= downlink->format & PDMOUTFORMAT;
-
-       /* Downlink channels */
-       mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
-       return 0;
-}
-
-/*
- * Cleans McPDM uplink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
-{
-       int irq_mask = 0;
-
-       if (!uplink)
-               return -EINVAL;
-
-       /* Disable irq request generation */
-       irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
-       omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
-       /* Disable DMA request generation */
-       omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
-
-       /* Clear Downlink channels */
-       mcpdm->up_channels = 0;
-
-       mcpdm->uplink = NULL;
-
-       return 0;
-}
-
-/*
- * Cleans McPDM downlink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink)
-{
-       int irq_mask = 0;
-
-       if (!downlink)
-               return -EINVAL;
-
-       /* Disable irq request generation */
-       irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
-       omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
-       /* Disable DMA request generation */
-       omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
-
-       /* clear Downlink channels */
-       mcpdm->dn_channels = 0;
-
-       mcpdm->downlink = NULL;
-
-       return 0;
-}
-
-static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
-{
-       struct omap_mcpdm *mcpdm_irq = dev_id;
-       int irq_status;
-
-       irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
-
-       /* Acknowledge irq event */
-       omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
-
-       if (irq & MCPDM_DN_IRQ_FULL) {
-               dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
-               omap_mcpdm_reset_playback(1);
-               omap_mcpdm_playback_open(mcpdm_irq->downlink);
-               omap_mcpdm_reset_playback(0);
-       }
-
-       if (irq & MCPDM_DN_IRQ_EMPTY) {
-               dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
-               omap_mcpdm_reset_playback(1);
-               omap_mcpdm_playback_open(mcpdm_irq->downlink);
-               omap_mcpdm_reset_playback(0);
-       }
-
-       if (irq & MCPDM_DN_IRQ) {
-               dev_dbg(mcpdm_irq->dev, "DN write request\n");
-       }
-
-       if (irq & MCPDM_UP_IRQ_FULL) {
-               dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
-               omap_mcpdm_reset_capture(1);
-               omap_mcpdm_capture_open(mcpdm_irq->uplink);
-               omap_mcpdm_reset_capture(0);
-       }
-
-       if (irq & MCPDM_UP_IRQ_EMPTY) {
-               dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
-               omap_mcpdm_reset_capture(1);
-               omap_mcpdm_capture_open(mcpdm_irq->uplink);
-               omap_mcpdm_reset_capture(0);
-       }
-
-       if (irq & MCPDM_UP_IRQ) {
-               dev_dbg(mcpdm_irq->dev, "UP write request\n");
-       }
-
-       return IRQ_HANDLED;
-}
-
-int omap_mcpdm_request(void)
-{
-       int ret;
-
-       clk_enable(mcpdm->clk);
-
-       spin_lock(&mcpdm->lock);
-
-       if (!mcpdm->free) {
-               dev_err(mcpdm->dev, "McPDM interface is in use\n");
-               spin_unlock(&mcpdm->lock);
-               ret = -EBUSY;
-               goto err;
-       }
-       mcpdm->free = 0;
-
-       spin_unlock(&mcpdm->lock);
-
-       /* Disable lines while request is ongoing */
-       omap_mcpdm_write(MCPDM_CTRL, 0x00);
-
-       ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
-                               0, "McPDM", (void *)mcpdm);
-       if (ret) {
-               dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
-               goto err;
-       }
-
-       return 0;
-
-err:
-       clk_disable(mcpdm->clk);
-       return ret;
-}
-
-void omap_mcpdm_free(void)
-{
-       spin_lock(&mcpdm->lock);
-       if (mcpdm->free) {
-               dev_err(mcpdm->dev, "McPDM interface is already free\n");
-               spin_unlock(&mcpdm->lock);
-               return;
-       }
-       mcpdm->free = 1;
-       spin_unlock(&mcpdm->lock);
-
-       clk_disable(mcpdm->clk);
-
-       free_irq(mcpdm->irq, (void *)mcpdm);
-}
-
-/* Enable/disable DC offset cancelation for the analog
- * headset path (PDM channels 1 and 2).
- */
-int omap_mcpdm_set_offset(int offset1, int offset2)
-{
-       int offset;
-
-       if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
-               return -EINVAL;
-
-       offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
-
-       /* offset cancellation for channel 1 */
-       if (offset1)
-               offset |= DN_OFST_RX1_EN;
-       else
-               offset &= ~DN_OFST_RX1_EN;
-
-       /* offset cancellation for channel 2 */
-       if (offset2)
-               offset |= DN_OFST_RX2_EN;
-       else
-               offset &= ~DN_OFST_RX2_EN;
-
-       omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
-
-       return 0;
-}
-
-int __devinit omap_mcpdm_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       int ret = 0;
-
-       mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
-       if (!mcpdm) {
-               ret = -ENOMEM;
-               goto exit;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "no resource\n");
-               goto err_resource;
-       }
-
-       spin_lock_init(&mcpdm->lock);
-       mcpdm->free = 1;
-       mcpdm->io_base = ioremap(res->start, resource_size(res));
-       if (!mcpdm->io_base) {
-               ret = -ENOMEM;
-               goto err_resource;
-       }
-
-       mcpdm->irq = platform_get_irq(pdev, 0);
-
-       mcpdm->clk = clk_get(&pdev->dev, "pdm_ck");
-       if (IS_ERR(mcpdm->clk)) {
-               ret = PTR_ERR(mcpdm->clk);
-               dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret);
-               goto err_clk;
-       }
-
-       mcpdm->dev = &pdev->dev;
-       platform_set_drvdata(pdev, mcpdm);
-
-       return 0;
-
-err_clk:
-       iounmap(mcpdm->io_base);
-err_resource:
-       kfree(mcpdm);
-exit:
-       return ret;
-}
-
-int __devexit omap_mcpdm_remove(struct platform_device *pdev)
-{
-       struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
-
-       platform_set_drvdata(pdev, NULL);
-
-       clk_put(mcpdm_ptr->clk);
-
-       iounmap(mcpdm_ptr->io_base);
-
-       mcpdm_ptr->clk = NULL;
-       mcpdm_ptr->free = 0;
-       mcpdm_ptr->dev = NULL;
-
-       kfree(mcpdm_ptr);
-
-       return 0;
-}
-
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h
deleted file mode 100644 (file)
index df3e16f..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * mcpdm.h -- Defines for McPDM driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-/* McPDM registers */
-
-#define MCPDM_REVISION         0x00
-#define MCPDM_SYSCONFIG                0x10
-#define MCPDM_IRQSTATUS_RAW    0x24
-#define MCPDM_IRQSTATUS                0x28
-#define MCPDM_IRQENABLE_SET    0x2C
-#define MCPDM_IRQENABLE_CLR    0x30
-#define MCPDM_IRQWAKE_EN       0x34
-#define MCPDM_DMAENABLE_SET    0x38
-#define MCPDM_DMAENABLE_CLR    0x3C
-#define MCPDM_DMAWAKEEN                0x40
-#define MCPDM_CTRL             0x44
-#define MCPDM_DN_DATA          0x48
-#define MCPDM_UP_DATA          0x4C
-#define MCPDM_FIFO_CTRL_DN     0x50
-#define MCPDM_FIFO_CTRL_UP     0x54
-#define MCPDM_DN_OFFSET                0x58
-
-/*
- * MCPDM_IRQ bit fields
- * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
- */
-
-#define MCPDM_DN_IRQ                   (1 << 0)
-#define MCPDM_DN_IRQ_EMPTY             (1 << 1)
-#define MCPDM_DN_IRQ_ALMST_EMPTY       (1 << 2)
-#define MCPDM_DN_IRQ_FULL              (1 << 3)
-
-#define MCPDM_UP_IRQ                   (1 << 8)
-#define MCPDM_UP_IRQ_EMPTY             (1 << 9)
-#define MCPDM_UP_IRQ_ALMST_FULL                (1 << 10)
-#define MCPDM_UP_IRQ_FULL              (1 << 11)
-
-#define MCPDM_DOWNLINK_IRQ_MASK                0x00F
-#define MCPDM_UPLINK_IRQ_MASK          0xF00
-
-/*
- * MCPDM_DMAENABLE bit fields
- */
-
-#define DMA_DN_ENABLE          0x1
-#define DMA_UP_ENABLE          0x2
-
-/*
- * MCPDM_CTRL bit fields
- */
-
-#define PDM_UP1_EN             0x0001
-#define PDM_UP2_EN             0x0002
-#define PDM_UP3_EN             0x0004
-#define PDM_DN1_EN             0x0008
-#define PDM_DN2_EN             0x0010
-#define PDM_DN3_EN             0x0020
-#define PDM_DN4_EN             0x0040
-#define PDM_DN5_EN             0x0080
-#define PDMOUTFORMAT           0x0100
-#define CMD_INT                        0x0200
-#define STATUS_INT             0x0400
-#define SW_UP_RST              0x0800
-#define SW_DN_RST              0x1000
-#define PDM_UP_MASK            0x007
-#define PDM_DN_MASK            0x0F8
-#define PDM_CMD_MASK           0x200
-#define PDM_STATUS_MASK                0x400
-
-
-#define PDMOUTFORMAT_LJUST     (0 << 8)
-#define PDMOUTFORMAT_RJUST     (1 << 8)
-
-/*
- * MCPDM_FIFO_CTRL bit fields
- */
-
-#define UP_THRES_MAX           0xF
-#define DN_THRES_MAX           0xF
-
-/*
- * MCPDM_DN_OFFSET bit fields
- */
-
-#define DN_OFST_RX1_EN         0x0001
-#define DN_OFST_RX2_EN         0x0100
-
-#define DN_OFST_RX1            1
-#define DN_OFST_RX2            9
-#define DN_OFST_MAX            0x1F
-
-#define MCPDM_UPLINK           1
-#define MCPDM_DOWNLINK         2
-
-struct omap_mcpdm_link {
-       int irq_mask;
-       int threshold;
-       int format;
-       int channels;
-};
-
-struct omap_mcpdm_platform_data {
-       unsigned long phys_base;
-       u16 irq;
-};
-
-struct omap_mcpdm {
-       struct device *dev;
-       unsigned long phys_base;
-       void __iomem *io_base;
-       u8 free;
-       int irq;
-
-       spinlock_t lock;
-       struct omap_mcpdm_platform_data *pdata;
-       struct clk *clk;
-       struct omap_mcpdm_link *downlink;
-       struct omap_mcpdm_link *uplink;
-       struct completion irq_completion;
-
-       int dn_channels;
-       int up_channels;
-};
-
-extern void omap_mcpdm_start(int stream);
-extern void omap_mcpdm_stop(int stream);
-extern int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_request(void);
-extern void omap_mcpdm_free(void);
-extern int omap_mcpdm_set_offset(int offset1, int offset2);
-int __devinit omap_mcpdm_probe(struct platform_device *pdev);
-int __devexit omap_mcpdm_remove(struct platform_device *pdev);
index 62e292f49313ce8645486949f6914b5912d9e6e5..c10d3566ab1fa6a8743bd78873924658cf8197c3 100644 (file)
@@ -115,25 +115,8 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
-       /* Set codec DAI configuration */
-       err = snd_soc_dai_set_fmt(codec_dai,
-                                        SND_SOC_DAIFMT_I2S |
-                                        SND_SOC_DAIFMT_NB_NF |
-                                        SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0)
-               return err;
-
-       /* Set cpu DAI configuration */
-       err = snd_soc_dai_set_fmt(cpu_dai,
-                                      SND_SOC_DAIFMT_I2S |
-                                      SND_SOC_DAIFMT_NB_NF |
-                                      SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0)
-               return err;
-
        /* Set the codec system clock for DAC and ADC */
        err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
                                            SND_SOC_CLOCK_IN);
@@ -312,6 +295,8 @@ static struct snd_soc_dai_link n810_dai = {
        .platform_name = "omap-pcm-audio",
        .codec_name = "tlv320aic3x-codec.2-0018",
        .codec_dai_name = "tlv320aic3x-hifi",
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .init = n810_aic33_init,
        .ops = &n810_ops,
 };
index 478d60778453632905dd7f8e3870dc289e9ca577..7f700610b3cbf761fca39f7db71ec1b140f170a9 100644 (file)
@@ -317,6 +317,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                return 0;
        }
 
+       regs->rcr2      &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7));
+       regs->xcr2      &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
+       regs->rcr1      &= ~(RFRLEN1(0x7f) | RWDLEN1(7));
+       regs->xcr1      &= ~(XFRLEN1(0x7f) | XWDLEN1(7));
        format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
        wpf = channels = params_channels(params);
        if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
@@ -369,6 +373,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                framesize = wlen * channels;
 
        /* Set FS period and length in terms of bit clock periods */
+       regs->srgr2     &= ~FPER(0xfff);
+       regs->srgr1     &= ~FWID(0xff);
        switch (format) {
        case SND_SOC_DAIFMT_I2S:
        case SND_SOC_DAIFMT_LEFT_J:
@@ -398,7 +404,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 {
        struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
-       unsigned int temp_fmt = fmt;
+       bool inv_fs = false;
 
        if (mcbsp_data->configured)
                return 0;
@@ -430,21 +436,21 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                regs->xcr2      |= XDATDLY(0);
                regs->spcr1     |= RJUST(2);
                /* Invert FS polarity configuration */
-               temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+               inv_fs = true;
                break;
        case SND_SOC_DAIFMT_DSP_A:
                /* 1-bit data delay */
                regs->rcr2      |= RDATDLY(1);
                regs->xcr2      |= XDATDLY(1);
                /* Invert FS polarity configuration */
-               temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+               inv_fs = true;
                break;
        case SND_SOC_DAIFMT_DSP_B:
                /* 0-bit data delay */
                regs->rcr2      |= RDATDLY(0);
                regs->xcr2      |= XDATDLY(0);
                /* Invert FS polarity configuration */
-               temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+               inv_fs = true;
                break;
        default:
                /* Unsupported data format */
@@ -468,7 +474,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        }
 
        /* Set bit clock (CLKX/CLKR) and FS polarities */
-       switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
                /*
                 * Normal BCLK + FS.
@@ -489,6 +495,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        default:
                return -EINVAL;
        }
+       if (inv_fs == true)
+               regs->pcr0 ^= FSXP | FSRP;
 
        return 0;
 }
@@ -503,6 +511,7 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
                return -ENODEV;
 
        mcbsp_data->clk_div = div;
+       regs->srgr1     &= ~CLKGDV(0xff);
        regs->srgr1     |= CLKGDV(div - 1);
 
        return 0;
@@ -516,11 +525,12 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        int err = 0;
 
-       if (mcbsp_data->active)
+       if (mcbsp_data->active) {
                if (freq == mcbsp_data->in_freq)
                        return 0;
                else
                        return -EBUSY;
+       }
 
        /* The McBSP signal muxing functions are only available on McBSP1 */
        if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
@@ -531,6 +541,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                        return -EINVAL;
 
        mcbsp_data->in_freq = freq;
+       regs->srgr2     &= ~CLKSM;
+       regs->pcr0      &= ~SCLKME;
 
        switch (clk_id) {
        case OMAP_MCBSP_SYSCLK_CLK:
index bed09c27e44cb9af6643f2e015d59405885b06bd..41d17067cc739a05ac085443cdbe1fd6e984593e 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * omap-mcpdm.c  --  OMAP ALSA SoC DAI driver using McPDM port
  *
- * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2009 - 2011 Texas Instruments
  *
- * Author: Misael Lopez Cruz <x0052729@ti.com>
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
  * Contact: Jorge Eduardo Candelaria <x0107209@ti.com>
  *          Margarita Olaya <magi.olaya@ti.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
-#include <sound/initval.h>
 #include <sound/soc.h>
 
 #include <plat/dma.h>
-#include <plat/mcbsp.h>
-#include "mcpdm.h"
+#include <plat/omap_hwmod.h>
+#include "omap-mcpdm.h"
 #include "omap-pcm.h"
 
-struct omap_mcpdm_data {
-       struct omap_mcpdm_link *links;
-       int active;
-};
+struct omap_mcpdm {
+       struct device *dev;
+       unsigned long phys_base;
+       void __iomem *io_base;
+       int irq;
 
-static struct omap_mcpdm_link omap_mcpdm_links[] = {
-       /* downlink */
-       {
-               .irq_mask = MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL,
-               .threshold = 1,
-               .format = PDMOUTFORMAT_LJUST,
-       },
-       /* uplink */
-       {
-               .irq_mask = MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL,
-               .threshold = 1,
-               .format = PDMOUTFORMAT_LJUST,
-       },
-};
+       struct mutex mutex;
+
+       /* channel data */
+       u32 dn_channels;
+       u32 up_channels;
+
+       /* McPDM FIFO thresholds */
+       u32 dn_threshold;
+       u32 up_threshold;
 
-static struct omap_mcpdm_data mcpdm_data = {
-       .links = omap_mcpdm_links,
-       .active = 0,
+       /* McPDM dn offsets for rx1, and 2 channels */
+       u32 dn_rx_offset;
 };
 
 /*
@@ -71,88 +73,259 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
                .dma_req = OMAP44XX_DMA_MCPDM_DL,
                .data_type = OMAP_DMA_DATA_TYPE_S32,
                .sync_mode = OMAP_DMA_SYNC_PACKET,
-               .packet_size = 16,
-               .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_DN_DATA,
+               .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA,
        },
        {
                .name = "Audio capture",
                .dma_req = OMAP44XX_DMA_MCPDM_UP,
                .data_type = OMAP_DMA_DATA_TYPE_S32,
                .sync_mode = OMAP_DMA_SYNC_PACKET,
-               .packet_size = 16,
-               .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_UP_DATA,
+               .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA,
        },
 };
 
-static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
-                                 struct snd_soc_dai *dai)
+static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
 {
-       int err = 0;
+       __raw_writel(val, mcpdm->io_base + reg);
+}
 
-       if (!dai->active)
-               err = omap_mcpdm_request();
+static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg)
+{
+       return __raw_readl(mcpdm->io_base + reg);
+}
 
-       return err;
+#ifdef DEBUG
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm)
+{
+       dev_dbg(mcpdm->dev, "***********************\n");
+       dev_dbg(mcpdm->dev, "IRQSTATUS_RAW:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS_RAW));
+       dev_dbg(mcpdm->dev, "IRQSTATUS:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS));
+       dev_dbg(mcpdm->dev, "IRQENABLE_SET:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_SET));
+       dev_dbg(mcpdm->dev, "IRQENABLE_CLR:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_CLR));
+       dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQWAKE_EN));
+       dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_SET));
+       dev_dbg(mcpdm->dev, "DMAENABLE_CLR:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_CLR));
+       dev_dbg(mcpdm->dev, "DMAWAKEEN:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_DMAWAKEEN));
+       dev_dbg(mcpdm->dev, "CTRL:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL));
+       dev_dbg(mcpdm->dev, "DN_DATA:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_DN_DATA));
+       dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_UP_DATA));
+       dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_DN));
+       dev_dbg(mcpdm->dev, "FIFO_CTRL_UP:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_UP));
+       dev_dbg(mcpdm->dev, "***********************\n");
 }
+#else
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
+#endif
 
-static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
-                                   struct snd_soc_dai *dai)
+/*
+ * Enables the transfer through the PDM interface to/from the Phoenix
+ * codec by enabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
+{
+       u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+       ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+       ctrl |= mcpdm->dn_channels | mcpdm->up_channels;
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+       ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+}
+
+/*
+ * Disables the transfer through the PDM interface to/from the Phoenix
+ * codec by disabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
+{
+       u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+       ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+       ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+       ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+}
+
+/*
+ * Is the physical McPDM interface active.
+ */
+static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
+{
+       return omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL) &
+                                       (MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK);
+}
+
+/*
+ * Configures McPDM uplink, and downlink for audio.
+ * This function should be called before omap_mcpdm_start.
+ */
+static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
+{
+       omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET,
+                       MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL |
+                       MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+       /* Enable DN RX1/2 offset cancellation feature, if configured */
+       if (mcpdm->dn_rx_offset) {
+               u32 dn_offset = mcpdm->dn_rx_offset;
+
+               omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+               dn_offset |= (MCPDM_DN_OFST_RX1_EN | MCPDM_DN_OFST_RX2_EN);
+               omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+       }
+
+       omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold);
+
+       omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET,
+                       MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE);
+}
+
+/*
+ * Cleans McPDM uplink, and downlink configuration.
+ * This function should be called when the stream is closed.
+ */
+static void omap_mcpdm_close_streams(struct omap_mcpdm *mcpdm)
+{
+       /* Disable irq request generation for downlink */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+                       MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL);
+
+       /* Disable DMA request generation for downlink */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_DN_ENABLE);
+
+       /* Disable irq request generation for uplink */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+                       MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+       /* Disable DMA request generation for uplink */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_UP_ENABLE);
+
+       /* Disable RX1/2 offset cancellation */
+       if (mcpdm->dn_rx_offset)
+               omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, 0);
+}
+
+static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
+{
+       struct omap_mcpdm *mcpdm = dev_id;
+       int irq_status;
+
+       irq_status = omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS);
+
+       /* Acknowledge irq event */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_IRQSTATUS, irq_status);
+
+       if (irq_status & MCPDM_DN_IRQ_FULL)
+               dev_dbg(mcpdm->dev, "DN (playback) FIFO Full\n");
+
+       if (irq_status & MCPDM_DN_IRQ_EMPTY)
+               dev_dbg(mcpdm->dev, "DN (playback) FIFO Empty\n");
+
+       if (irq_status & MCPDM_DN_IRQ)
+               dev_dbg(mcpdm->dev, "DN (playback) write request\n");
+
+       if (irq_status & MCPDM_UP_IRQ_FULL)
+               dev_dbg(mcpdm->dev, "UP (capture) FIFO Full\n");
+
+       if (irq_status & MCPDM_UP_IRQ_EMPTY)
+               dev_dbg(mcpdm->dev, "UP (capture) FIFO Empty\n");
+
+       if (irq_status & MCPDM_UP_IRQ)
+               dev_dbg(mcpdm->dev, "UP (capture) write request\n");
+
+       return IRQ_HANDLED;
+}
+
+static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
+                                 struct snd_soc_dai *dai)
 {
-       if (!dai->active)
-               omap_mcpdm_free();
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+       mutex_lock(&mcpdm->mutex);
+
+       if (!dai->active) {
+               pm_runtime_get_sync(mcpdm->dev);
+
+               /* Enable watch dog for ES above ES 1.0 to avoid saturation */
+               if (omap_rev() != OMAP4430_REV_ES1_0) {
+                       u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+                       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL,
+                                        ctrl | MCPDM_WD_EN);
+               }
+               omap_mcpdm_open_streams(mcpdm);
+       }
+
+       mutex_unlock(&mcpdm->mutex);
+
+       return 0;
 }
 
-static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
-       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-       int stream = substream->stream;
-       int err = 0;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               if (!mcpdm_priv->active++)
-                       omap_mcpdm_start(stream);
-               break;
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               if (!--mcpdm_priv->active)
-                       omap_mcpdm_stop(stream);
-               break;
-       default:
-               err = -EINVAL;
+       mutex_lock(&mcpdm->mutex);
+
+       if (!dai->active) {
+               if (omap_mcpdm_active(mcpdm)) {
+                       omap_mcpdm_stop(mcpdm);
+                       omap_mcpdm_close_streams(mcpdm);
+               }
+
+               if (!omap_mcpdm_active(mcpdm))
+                       pm_runtime_put_sync(mcpdm->dev);
        }
 
-       return err;
+       mutex_unlock(&mcpdm->mutex);
 }
 
 static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *params,
                                    struct snd_soc_dai *dai)
 {
-       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-       struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
        int stream = substream->stream;
-       int channels, err, link_mask = 0;
-
-       snd_soc_dai_set_dma_data(dai, substream,
-                                &omap_mcpdm_dai_dma_params[stream]);
+       struct omap_pcm_dma_data *dma_data;
+       int channels;
+       int link_mask = 0;
 
        channels = params_channels(params);
        switch (channels) {
+       case 5:
+               if (stream == SNDRV_PCM_STREAM_CAPTURE)
+                       /* up to 3 channels for capture */
+                       return -EINVAL;
+               link_mask |= 1 << 4;
        case 4:
                if (stream == SNDRV_PCM_STREAM_CAPTURE)
-                       /* up to 2 channels for capture */
+                       /* up to 3 channels for capture */
                        return -EINVAL;
                link_mask |= 1 << 3;
        case 3:
-               if (stream == SNDRV_PCM_STREAM_CAPTURE)
-                       /* up to 2 channels for capture */
-                       return -EINVAL;
                link_mask |= 1 << 2;
        case 2:
                link_mask |= 1 << 1;
@@ -164,95 +337,187 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
+       dma_data = &omap_mcpdm_dai_dma_params[stream];
+
+       /* Configure McPDM channels, and DMA packet size */
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               mcpdm_links[stream].channels = link_mask << 3;
-               err = omap_mcpdm_playback_open(&mcpdm_links[stream]);
+               mcpdm->dn_channels = link_mask << 3;
+               dma_data->packet_size =
+                       (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels;
        } else {
-               mcpdm_links[stream].channels = link_mask << 0;
-               err = omap_mcpdm_capture_open(&mcpdm_links[stream]);
+               mcpdm->up_channels = link_mask << 0;
+               dma_data->packet_size = mcpdm->up_threshold * channels;
        }
 
-       return err;
+       snd_soc_dai_set_dma_data(dai, substream, dma_data);
+
+       return 0;
 }
 
-static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream,
+static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
-       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-       struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
-       int stream = substream->stream;
-       int err;
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
-       if (substream->stream ==  SNDRV_PCM_STREAM_PLAYBACK)
-               err = omap_mcpdm_playback_close(&mcpdm_links[stream]);
-       else
-               err = omap_mcpdm_capture_close(&mcpdm_links[stream]);
+       if (!omap_mcpdm_active(mcpdm)) {
+               omap_mcpdm_start(mcpdm);
+               omap_mcpdm_reg_dump(mcpdm);
+       }
 
-       return err;
+       return 0;
 }
 
 static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
        .startup        = omap_mcpdm_dai_startup,
        .shutdown       = omap_mcpdm_dai_shutdown,
-       .trigger        = omap_mcpdm_dai_trigger,
        .hw_params      = omap_mcpdm_dai_hw_params,
-       .hw_free        = omap_mcpdm_dai_hw_free,
+       .prepare        = omap_mcpdm_prepare,
 };
 
-#define OMAP_MCPDM_RATES       (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-#define OMAP_MCPDM_FORMATS     (SNDRV_PCM_FMTBIT_S32_LE)
+static int omap_mcpdm_probe(struct snd_soc_dai *dai)
+{
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+       int ret;
 
-static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai)
+       pm_runtime_enable(mcpdm->dev);
+
+       /* Disable lines while request is ongoing */
+       pm_runtime_get_sync(mcpdm->dev);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
+
+       ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
+                               0, "McPDM", (void *)mcpdm);
+
+       pm_runtime_put_sync(mcpdm->dev);
+
+       if (ret) {
+               dev_err(mcpdm->dev, "Request for IRQ failed\n");
+               pm_runtime_disable(mcpdm->dev);
+       }
+
+       /* Configure McPDM threshold values */
+       mcpdm->dn_threshold = 2;
+       mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3;
+       return ret;
+}
+
+static int omap_mcpdm_remove(struct snd_soc_dai *dai)
 {
-       snd_soc_dai_set_drvdata(dai, &mcpdm_data);
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+       free_irq(mcpdm->irq, (void *)mcpdm);
+       pm_runtime_disable(mcpdm->dev);
+
        return 0;
 }
 
+#define OMAP_MCPDM_RATES       (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+#define OMAP_MCPDM_FORMATS     SNDRV_PCM_FMTBIT_S32_LE
+
 static struct snd_soc_dai_driver omap_mcpdm_dai = {
-       .probe = omap_mcpdm_dai_probe,
+       .probe = omap_mcpdm_probe,
+       .remove = omap_mcpdm_remove,
+       .probe_order = SND_SOC_COMP_ORDER_LATE,
+       .remove_order = SND_SOC_COMP_ORDER_EARLY,
        .playback = {
                .channels_min = 1,
-               .channels_max = 4,
+               .channels_max = 5,
                .rates = OMAP_MCPDM_RATES,
                .formats = OMAP_MCPDM_FORMATS,
        },
        .capture = {
                .channels_min = 1,
-               .channels_max = 2,
+               .channels_max = 3,
                .rates = OMAP_MCPDM_RATES,
                .formats = OMAP_MCPDM_FORMATS,
        },
        .ops = &omap_mcpdm_dai_ops,
 };
 
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+                                   u8 rx1, u8 rx2)
+{
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+       mcpdm->dn_rx_offset = MCPDM_DNOFST_RX1(rx1) | MCPDM_DNOFST_RX2(rx2);
+}
+EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets);
+
 static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
 {
-       int ret;
+       struct omap_mcpdm *mcpdm;
+       struct resource *res;
+       int ret = 0;
+
+       mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
+       if (!mcpdm)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mcpdm);
+
+       mutex_init(&mcpdm->mutex);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no resource\n");
+               goto err_res;
+       }
+
+       if (!request_mem_region(res->start, resource_size(res), "McPDM")) {
+               ret = -EBUSY;
+               goto err_res;
+       }
+
+       mcpdm->io_base = ioremap(res->start, resource_size(res));
+       if (!mcpdm->io_base) {
+               ret = -ENOMEM;
+               goto err_iomap;
+       }
+
+       mcpdm->irq = platform_get_irq(pdev, 0);
+       if (mcpdm->irq < 0) {
+               ret = mcpdm->irq;
+               goto err_irq;
+       }
+
+       mcpdm->dev = &pdev->dev;
 
-       ret = omap_mcpdm_probe(pdev);
-       if (ret < 0)
-               return ret;
        ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
-       if (ret < 0)
-               omap_mcpdm_remove(pdev);
+       if (!ret)
+               return 0;
+
+err_irq:
+       iounmap(mcpdm->io_base);
+err_iomap:
+       release_mem_region(res->start, resource_size(res));
+err_res:
+       kfree(mcpdm);
        return ret;
 }
 
 static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
 {
+       struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev);
+       struct resource *res;
+
        snd_soc_unregister_dai(&pdev->dev);
-       omap_mcpdm_remove(pdev);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       iounmap(mcpdm->io_base);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(mcpdm);
        return 0;
 }
 
 static struct platform_driver asoc_mcpdm_driver = {
        .driver = {
-                       .name = "omap-mcpdm-dai",
-                       .owner = THIS_MODULE,
+               .name   = "omap-mcpdm",
+               .owner  = THIS_MODULE,
        },
 
-       .probe = asoc_mcpdm_probe,
-       .remove = __devexit_p(asoc_mcpdm_remove),
+       .probe  = asoc_mcpdm_probe,
+       .remove = __devexit_p(asoc_mcpdm_remove),
 };
 
 static int __init snd_omap_mcpdm_init(void)
@@ -267,6 +532,6 @@ static void __exit snd_omap_mcpdm_exit(void)
 }
 module_exit(snd_omap_mcpdm_exit);
 
-MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
 MODULE_DESCRIPTION("OMAP PDM SoC Interface");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h
new file mode 100644 (file)
index 0000000..de8cf26
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * omap-mcpdm.h
+ *
+ * Copyright (C) 2009 - 2011 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_MCPDM_H__
+#define __OMAP_MCPDM_H__
+
+#define MCPDM_REG_REVISION             0x00
+#define MCPDM_REG_SYSCONFIG            0x10
+#define MCPDM_REG_IRQSTATUS_RAW                0x24
+#define MCPDM_REG_IRQSTATUS            0x28
+#define MCPDM_REG_IRQENABLE_SET                0x2C
+#define MCPDM_REG_IRQENABLE_CLR                0x30
+#define MCPDM_REG_IRQWAKE_EN           0x34
+#define MCPDM_REG_DMAENABLE_SET                0x38
+#define MCPDM_REG_DMAENABLE_CLR                0x3C
+#define MCPDM_REG_DMAWAKEEN            0x40
+#define MCPDM_REG_CTRL                 0x44
+#define MCPDM_REG_DN_DATA              0x48
+#define MCPDM_REG_UP_DATA              0x4C
+#define MCPDM_REG_FIFO_CTRL_DN         0x50
+#define MCPDM_REG_FIFO_CTRL_UP         0x54
+#define MCPDM_REG_DN_OFFSET            0x58
+
+/*
+ * MCPDM_IRQ bit fields
+ * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
+ */
+
+#define MCPDM_DN_IRQ                   (1 << 0)
+#define MCPDM_DN_IRQ_EMPTY             (1 << 1)
+#define MCPDM_DN_IRQ_ALMST_EMPTY       (1 << 2)
+#define MCPDM_DN_IRQ_FULL              (1 << 3)
+
+#define MCPDM_UP_IRQ                   (1 << 8)
+#define MCPDM_UP_IRQ_EMPTY             (1 << 9)
+#define MCPDM_UP_IRQ_ALMST_FULL                (1 << 10)
+#define MCPDM_UP_IRQ_FULL              (1 << 11)
+
+#define MCPDM_DOWNLINK_IRQ_MASK                0x00F
+#define MCPDM_UPLINK_IRQ_MASK          0xF00
+
+/*
+ * MCPDM_DMAENABLE bit fields
+ */
+
+#define MCPDM_DMA_DN_ENABLE            (1 << 0)
+#define MCPDM_DMA_UP_ENABLE            (1 << 1)
+
+/*
+ * MCPDM_CTRL bit fields
+ */
+
+#define MCPDM_PDM_UPLINK_EN(x)         (1 << (x - 1)) /* ch1 is at bit 0 */
+#define MCPDM_PDM_DOWNLINK_EN(x)       (1 << (x + 2)) /* ch1 is at bit 3 */
+#define MCPDM_PDMOUTFORMAT             (1 << 8)
+#define MCPDM_CMD_INT                  (1 << 9)
+#define MCPDM_STATUS_INT               (1 << 10)
+#define MCPDM_SW_UP_RST                        (1 << 11)
+#define MCPDM_SW_DN_RST                        (1 << 12)
+#define MCPDM_WD_EN                    (1 << 14)
+#define MCPDM_PDM_UP_MASK              0x7
+#define MCPDM_PDM_DN_MASK              (0x1f << 3)
+
+
+#define MCPDM_PDMOUTFORMAT_LJUST       (0 << 8)
+#define MCPDM_PDMOUTFORMAT_RJUST       (1 << 8)
+
+/*
+ * MCPDM_FIFO_CTRL bit fields
+ */
+
+#define MCPDM_UP_THRES_MAX             0xF
+#define MCPDM_DN_THRES_MAX             0xF
+
+/*
+ * MCPDM_DN_OFFSET bit fields
+ */
+
+#define MCPDM_DN_OFST_RX1_EN           (1 << 0)
+#define MCPDM_DNOFST_RX1(x)            ((x & 0x1f) << 1)
+#define MCPDM_DN_OFST_RX2_EN           (1 << 8)
+#define MCPDM_DNOFST_RX2(x)            ((x & 0x1f) << 9)
+
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+                                   u8 rx1, u8 rx2);
+
+#endif /* End of __OMAP_MCPDM_H__ */
index 0daa044698360fc0a125fc2776bccebc6288bf13..bf9ae2a6f90199bc1a8c02e245e98a7da7122097 100644 (file)
@@ -36,29 +36,8 @@ static int omap3evm_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "Can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "Can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                     SND_SOC_CLOCK_IN);
@@ -82,6 +61,8 @@ static struct snd_soc_dai_link omap3evm_dai = {
        .codec_dai_name = "twl4030-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "twl4030-codec",
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops            = &omap3evm_ops,
 };
 
index 8047c521e318d648405b4fcce75e1f0cca4ee54f..3ae87fd36612fdc2aefc0363538c830f0505a545 100644 (file)
@@ -48,24 +48,8 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-                 SND_SOC_DAIFMT_CBS_CFS;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, fmt);
-       if (ret < 0) {
-               pr_err(PREFIX "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
-       if (ret < 0) {
-               pr_err(PREFIX "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                            SND_SOC_CLOCK_IN);
@@ -231,6 +215,8 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
                .codec_dai_name = "twl4030-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBS_CFS,
                .ops = &omap3pandora_ops,
                .init = omap3pandora_out_init,
        }, {
@@ -240,6 +226,8 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
                .codec_dai_name = "twl4030-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBS_CFS,
                .ops = &omap3pandora_ops,
                .init = omap3pandora_in_init,
        }
index 7e75e775fb4a8943eea07911aa289ac98390b7d4..597833246e3ad7d8a4cc14b2806638c2142ad167 100644 (file)
@@ -55,29 +55,8 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
-       /* Set codec DAI configuration */
-       err = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return err;
-       }
-
-       /* Set cpu DAI configuration */
-       err = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return err;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        err =
            snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -141,6 +120,8 @@ static struct snd_soc_dai_link osk_dai = {
        .codec_dai_name = "tlv320aic23-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "tlv320aic23-codec",
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .init = osk_tlv320aic23_init,
        .ops = &osk_ops,
 };
index bbcf380bfb56309ce0e193e2312fe47eea8f9366..739efe9e327ad31ea194963caea116dd8b5a450e 100644 (file)
@@ -38,29 +38,8 @@ static int overo_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                            SND_SOC_CLOCK_IN);
@@ -84,6 +63,8 @@ static struct snd_soc_dai_link overo_dai = {
        .codec_dai_name = "twl4030-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "twl4030-codec",
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops = &overo_ops,
 };
 
index 893300a53bab5cc78ccd91aa331c4b114c91d090..7164db5fc38a0c69f08424c5e023c291f3fcbae1 100644 (file)
@@ -115,24 +115,6 @@ static int rx51_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int err;
-
-       /* Set codec DAI configuration */
-       err = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_DSP_A |
-                                 SND_SOC_DAIFMT_IB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0)
-               return err;
-
-       /* Set cpu DAI configuration */
-       err = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_DSP_A |
-                                 SND_SOC_DAIFMT_IB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0)
-               return err;
 
        /* Set the codec system clock for DAC and ADC */
        return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
@@ -377,6 +359,8 @@ static struct snd_soc_dai_link rx51_dai[] = {
                .codec_dai_name = "tlv320aic3x-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "tlv320aic3x-codec.2-0018",
+               .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = rx51_aic34_init,
                .ops = &rx51_ops,
        },
index 9f6a758029d16a63cbcd9b8930f64e2c9baceaef..269aded8a6becc38231abb3362086aa51a797bd2 100644 (file)
@@ -53,29 +53,8 @@ static int sdp3430_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                            SND_SOC_CLOCK_IN);
@@ -91,49 +70,6 @@ static struct snd_soc_ops sdp3430_ops = {
        .hw_params = sdp3430_hw_params,
 };
 
-static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int ret;
-
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                               SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM);
-       if (ret) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                               SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
-       /* Set the codec system clock for DAC and ADC */
-       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
-                                           SND_SOC_CLOCK_IN);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec system clock\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static struct snd_soc_ops sdp3430_voice_ops = {
-       .hw_params = sdp3430_hw_voice_params,
-};
-
 /* Headset jack */
 static struct snd_soc_jack hs_jack;
 
@@ -267,6 +203,8 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
                .codec_dai_name = "twl4030-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = sdp3430_twl4030_init,
                .ops = &sdp3430_ops,
        },
@@ -277,8 +215,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
                .codec_dai_name = "twl4030-voice",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = sdp3430_twl4030_voice_init,
-               .ops = &sdp3430_voice_ops,
+               .ops = &sdp3430_ops,
        },
 };
 
index b80efb02bfcae81ea365fce6c9f0be93a63dde28..79ec76d521e1f6719780b0ec4eff636e529fb30f 100644 (file)
@@ -32,7 +32,7 @@
 #include <plat/hardware.h>
 #include <plat/mux.h>
 
-#include "mcpdm.h"
+#include "omap-mcpdm.h"
 #include "omap-pcm.h"
 #include "../codecs/twl6040.h"
 
@@ -88,7 +88,7 @@ static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
        SND_SOC_DAPM_HP("Headset Stereophone", NULL),
        SND_SOC_DAPM_SPK("Earphone Spk", NULL),
-       SND_SOC_DAPM_INPUT("Aux/FM Stereo In"),
+       SND_SOC_DAPM_INPUT("FM Stereo In"),
 };
 
 static const struct snd_soc_dapm_route audio_map[] = {
@@ -113,15 +113,15 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Earphone Spk", NULL, "EP"},
 
        /* Aux/FM Stereo In: AFML, AFMR */
-       {"AFML", NULL, "Aux/FM Stereo In"},
-       {"AFMR", NULL, "Aux/FM Stereo In"},
+       {"AFML", NULL, "FM Stereo In"},
+       {"AFMR", NULL, "FM Stereo In"},
 };
 
 static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret;
+       int ret, hs_trim;
 
        /* Add SDP4430 specific widgets */
        ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
@@ -144,6 +144,14 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
        if (ret)
                return ret;
 
+       /*
+        * Configure McPDM offset cancellation based on the HSOTRIM value from
+        * twl6040.
+        */
+       hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
+       omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
+                                       TWL6040_HSF_TRIM_RIGHT(hs_trim));
+
        /* Headset jack detection */
        ret = snd_soc_jack_new(codec, "Headset Jack",
                                SND_JACK_HEADSET, &hs_jack);
@@ -165,8 +173,8 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link sdp4430_dai = {
        .name = "TWL6040",
        .stream_name = "TWL6040",
-       .cpu_dai_name ="omap-mcpdm-dai",
-       .codec_dai_name = "twl6040-hifi",
+       .cpu_dai_name = "omap-mcpdm",
+       .codec_dai_name = "twl6040-legacy",
        .platform_name = "omap-pcm-audio",
        .codec_name = "twl6040-codec",
        .init = sdp4430_twl6040_init,
index 9a2666ffc16c9b71b40ddf54cfc3464d217a1f62..8b1ebbce33aa36dc1a3f51282129cfecd1508b50 100644 (file)
@@ -44,29 +44,8 @@ static int zoom2_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                        SND_SOC_CLOCK_IN);
@@ -82,49 +61,6 @@ static struct snd_soc_ops zoom2_ops = {
        .hw_params = zoom2_hw_params,
 };
 
-static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int ret;
-
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                               SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM);
-       if (ret) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                               SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
-       /* Set the codec system clock for DAC and ADC */
-       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
-                                       SND_SOC_CLOCK_IN);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec system clock\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static struct snd_soc_ops zoom2_voice_ops = {
-       .hw_params = zoom2_hw_voice_params,
-};
-
 /* Zoom2 machine DAPM */
 static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
        SND_SOC_DAPM_MIC("Ext Mic", NULL),
@@ -217,6 +153,8 @@ static struct snd_soc_dai_link zoom2_dai[] = {
                .codec_dai_name = "twl4030-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = zoom2_twl4030_init,
                .ops = &zoom2_ops,
        },
@@ -227,8 +165,10 @@ static struct snd_soc_dai_link zoom2_dai[] = {
                .codec_dai_name = "twl4030-voice",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = zoom2_twl4030_voice_init,
-               .ops = &zoom2_voice_ops,
+               .ops = &zoom2_ops,
        },
 };
 
index 1a591f1ebfbd9431f89559be28421d8defde585c..b899a3bc8f42356cce6e9c6f1629bf0402f5706d 100644 (file)
@@ -306,8 +306,10 @@ static int __init raumfeld_audio_init(void)
                                     &snd_soc_raumfeld_connector);
 
        ret = platform_device_add(raumfeld_audio_device);
-       if (ret < 0)
+       if (ret < 0) {
+               platform_device_put(raumfeld_audio_device);
                return ret;
+       }
 
        raumfeld_enable_audio(true);
        return 0;
index b253d864868a558001dd9e6e90b0e33d739a254d..ce920e3cfea1ff58e825236da133250831239a25 100644 (file)
@@ -312,7 +312,7 @@ static struct snd_soc_dai_link spitz_dai = {
        .cpu_dai_name = "pxa2xx-i2s",
        .codec_dai_name = "wm8750-hifi",
        .platform_name = "pxa-pcm-audio",
-       .codec_name = "wm8750-codec.0-001b",
+       .codec_name = "wm8750.0-001b",
        .init = spitz_wm8750_init,
        .ops = &spitz_ops,
 };
index d69d9fc32233f0f8935920fc4fb68dcb4e03f9f2..4b81ffd87566eeda0cb6b4f7ed53b52b9050a936 100644 (file)
@@ -198,7 +198,7 @@ static struct snd_soc_dai_link z2_dai = {
        .cpu_dai_name   = "pxa2xx-i2s",
        .codec_dai_name = "wm8750-hifi",
        .platform_name = "pxa-pcm-audio",
-       .codec_name     = "wm8750-codec.0-001b",
+       .codec_name     = "wm8750.0-001b",
        .init           = z2_wm8750_init,
        .ops            = &z2_ops,
 };
index 80c85fd64e1aac4311502e2688f1f64da09fbf67..55efc2bdf0bd0a4fd73f938299764222601a5014 100644 (file)
@@ -446,7 +446,6 @@ static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32);
 static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
 {
        struct snd_card *card = runtime->card->snd_card;
-       struct snd_soc_dai *dai = runtime->cpu_dai;
        struct snd_pcm *pcm = runtime->pcm;
        struct s6000_pcm_dma_params *params;
        int res;
index 65f980ef28708689f7e554b514cbd54a8b18b3a2..dd3b3eac080565d7b55c4fe150b97b3f2fc79527 100644 (file)
@@ -63,7 +63,7 @@ config SND_SOC_SAMSUNG_SMDK_WM8580
 
 config SND_SOC_SAMSUNG_SMDK_WM8994
        tristate "SoC I2S Audio support for WM8994 on SMDK"
-       depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210)
+       depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210 || MACH_SMDK4212)
        select SND_SOC_WM8994
        select SND_SAMSUNG_I2S
        help
@@ -158,7 +158,7 @@ config SND_SOC_GONI_AQUILA_WM8994
 
 config SND_SOC_SAMSUNG_SMDK_SPDIF
        tristate "SoC S/PDIF Audio support for SMDK"
-       depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310)
+       depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310 || MACH_SMDK4212)
        select SND_SAMSUNG_SPDIF
        help
          Say Y if you want to add support for SoC S/PDIF audio on the SMDK.
@@ -173,7 +173,7 @@ config SND_SOC_SMDK_WM8580_PCM
 
 config SND_SOC_SMDK_WM8994_PCM
        tristate "SoC PCM Audio support for WM8994 on SMDK"
-       depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310)
+       depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310 || MACH_SMDK4212)
        select SND_SOC_WM8994
        select SND_SAMSUNG_PCM
        help
index 14eb6ea69e7c50f71791be271f17d5fd5c33f27f..ed8f13a29c859660afc4142ca1b945577f441506 100644 (file)
@@ -131,7 +131,7 @@ static struct snd_soc_dai_link jive_dai = {
        .cpu_dai_name   = "s3c2412-i2s",
        .codec_dai_name = "wm8750-hifi",
        .platform_name  = "samsung-audio",
-       .codec_name     = "wm8750-codec.0-001a",
+       .codec_name     = "wm8750.0-001a",
        .init           = jive_wm8750_init,
        .ops            = &jive_ops,
 };
index 841ab14c1100a9ca759fede04dae139402325d62..7ab8e2c292163c04a1e5c9c0579e6c8e274e2f12 100644 (file)
@@ -69,10 +69,10 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
        s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
 
        s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk");
-       if (s3c2412_i2s.iis_cclk == NULL) {
+       if (IS_ERR(s3c2412_i2s.iis_cclk)) {
                pr_err("failed to get i2sclk clock\n");
                iounmap(s3c2412_i2s.regs);
-               return -ENODEV;
+               return PTR_ERR(s3c2412_i2s.iis_cclk);
        }
 
        /* Set MPLL as the source for IIS CLK */
index 63d8849d80bdc738e667201af435f2ed838a9a9e..21c92e2e3007c00d6fa54cdab729d8741a3d1e51 100644 (file)
@@ -383,10 +383,10 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
                return -ENXIO;
 
        s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis");
-       if (s3c24xx_i2s.iis_clk == NULL) {
+       if (IS_ERR(s3c24xx_i2s.iis_clk)) {
                pr_err("failed to get iis_clock\n");
                iounmap(s3c24xx_i2s.regs);
-               return -ENODEV;
+               return PTR_ERR(s3c24xx_i2s.iis_clk);
        }
        clk_enable(s3c24xx_i2s.iis_clk);
 
index dc9d551f6788db05a420a0598494e947be4bcc51..65c1cfd47d8a73ae819403c3e24a5efccd5758ff 100644 (file)
@@ -66,17 +66,17 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
        pr_debug("%s %d\n", __func__, clk_users);
        if (clk_users == 0) {
                xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
-               if (!xtal) {
+               if (IS_ERR(xtal)) {
                        printk(KERN_ERR "%s cannot get xtal\n", __func__);
-                       ret = -EBUSY;
+                       ret = PTR_ERR(xtal);
                } else {
                        pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
                                       "pclk");
-                       if (!pclk) {
+                       if (IS_ERR(pclk)) {
                                printk(KERN_ERR "%s cannot get pclk\n",
                                       __func__);
                                clk_put(xtal);
-                               ret = -EBUSY;
+                               ret = PTR_ERR(pclk);
                        }
                }
                if (!ret) {
index 0a2c4f22303811b55921452f783ae485fefb3bdd..bbd14768ecd3dafc559ecee6ddfff34d855cf2c5 100644 (file)
@@ -207,7 +207,7 @@ static struct snd_soc_dai_link smartq_dai[] = {
                .cpu_dai_name   = "samsung-i2s.0",
                .codec_dai_name = "wm8750-hifi",
                .platform_name  = "samsung-audio",
-               .codec_name     = "wm8750-codec.0-0x1a",
+               .codec_name     = "wm8750.0-0x1a",
                .init           = smartq_wm8987_init,
                .ops            = &smartq_hifi_ops,
        },
index 3d26f6607aa47aa97cc6798ac0d10cb14276a0ae..20deecf3b243ad38a7f1b1c44512c59c33de5bb6 100644 (file)
@@ -210,7 +210,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm8580-hifi-playback",
                .platform_name = "samsung-audio",
-               .codec_name = "wm8580-codec.0-001b",
+               .codec_name = "wm8580.0-001b",
                .init = smdk_wm8580_init_paifrx,
                .ops = &smdk_ops,
        },
@@ -220,7 +220,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .cpu_dai_name = "samsung-i2s.0",
                .codec_dai_name = "wm8580-hifi-capture",
                .platform_name = "samsung-audio",
-               .codec_name = "wm8580-codec.0-001b",
+               .codec_name = "wm8580.0-001b",
                .init = smdk_wm8580_init_paiftx,
                .ops = &smdk_ops,
        },
@@ -230,7 +230,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .cpu_dai_name = "samsung-i2s.x",
                .codec_dai_name = "wm8580-hifi-playback",
                .platform_name = "samsung-audio",
-               .codec_name = "wm8580-codec.0-001b",
+               .codec_name = "wm8580.0-001b",
                .init = smdk_wm8580_init_paifrx,
                .ops = &smdk_ops,
        },
index 0d12092df164bde51c8d6f28ad6488c227c745d8..4b9c73477ce0d9e875256e4985ff78f70d5056ca 100644 (file)
@@ -127,7 +127,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .cpu_dai_name = "samsung-pcm.0",
                .codec_dai_name = "wm8580-hifi-playback",
                .platform_name = "samsung-audio",
-               .codec_name = "wm8580-codec.0-001b",
+               .codec_name = "wm8580.0-001b",
                .ops = &smdk_wm8580_pcm_ops,
        }, {
                .name = "WM8580 PAIF PCM TX",
@@ -135,7 +135,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .cpu_dai_name = "samsung-pcm.0",
                .codec_dai_name = "wm8580-hifi-capture",
                .platform_name = "samsung-audio",
-               .codec_name = "wm8580-codec.0-001b",
+               .codec_name = "wm8580.0-001b",
                .ops = &smdk_wm8580_pcm_ops,
        },
 };
index 590e9274b06285428f25a25104e524ccddb0d304..b9e213f6cc0630f179d9b811d6b382dac6c64777 100644 (file)
@@ -125,10 +125,6 @@ static struct snd_soc_jack_pin speyside_headset_pins[] = {
                .pin = "Headset Mic",
                .mask = SND_JACK_MICROPHONE,
        },
-       {
-               .pin = "Headphone",
-               .mask = SND_JACK_HEADPHONE,
-       },
 };
 
 /* Default the headphone selection to active high */
@@ -171,7 +167,8 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd)
        gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
 
        ret = snd_soc_jack_new(codec, "Headset",
-                              SND_JACK_HEADSET | SND_JACK_BTN_0,
+                              SND_JACK_LINEOUT | SND_JACK_HEADSET |
+                              SND_JACK_BTN_0,
                               &speyside_headset);
        if (ret)
                return ret;
@@ -227,7 +224,7 @@ static int speyside_wm9081_init(struct snd_soc_dapm_context *dapm)
        snd_soc_dapm_nc_pin(dapm, "LINEOUT");
 
        /* At any time the WM9081 is active it will have this clock */
-       return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK,
+       return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0,
                                        48000 * 256, 0);
 }
 
@@ -252,6 +249,7 @@ static const struct snd_kcontrol_new controls[] = {
        SOC_DAPM_PIN_SWITCH("Main AMIC"),
        SOC_DAPM_PIN_SWITCH("WM1250 Input"),
        SOC_DAPM_PIN_SWITCH("WM1250 Output"),
+       SOC_DAPM_PIN_SWITCH("Headphone"),
 };
 
 static struct snd_soc_dapm_widget widgets[] = {
index 72535f2daaf20612c28eef1fcadc577e96cd5ba2..8a082044436e4409461129d01bc94c710b7443b1 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "../codecs/wm8962.h"
 
+static int sample_rate = 44100;
+
 static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
                                          struct snd_soc_dapm_context *dapm,
                                          enum snd_soc_bias_level level)
@@ -31,13 +33,13 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
                if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
                        ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
                                                  WM8962_FLL_MCLK, 32768,
-                                                 44100 * 256);
+                                                 sample_rate * 512);
                        if (ret < 0)
                                pr_err("Failed to start FLL: %d\n", ret);
 
                        ret = snd_soc_dai_set_sysclk(codec_dai,
                                                     WM8962_SYSCLK_FLL,
-                                                    44100 * 256,
+                                                    sample_rate * 512,
                                                     SND_SOC_CLOCK_IN);
                        if (ret < 0) {
                                pr_err("Failed to set SYSCLK: %d\n", ret);
@@ -92,22 +94,7 @@ static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
 static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream,
                              struct snd_pcm_hw_params *params)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       int ret;
-
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
-                                        | SND_SOC_DAIFMT_NB_NF
-                                        | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
-                                        | SND_SOC_DAIFMT_NB_NF
-                                        | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
+       sample_rate = params_rate(params);
 
        return 0;
 }
@@ -124,12 +111,15 @@ static struct snd_soc_dai_link speyside_wm8962_dai[] = {
                .codec_dai_name = "wm8962",
                .platform_name = "samsung-audio",
                .codec_name = "wm8962.1-001a",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
                .ops = &speyside_wm8962_ops,
        },
 };
 
 static const struct snd_kcontrol_new controls[] = {
        SOC_DAPM_PIN_SWITCH("Main Speaker"),
+       SOC_DAPM_PIN_SWITCH("DMIC"),
 };
 
 static struct snd_soc_dapm_widget widgets[] = {
@@ -137,6 +127,7 @@ static struct snd_soc_dapm_widget widgets[] = {
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 
        SND_SOC_DAPM_MIC("DMIC", NULL),
+       SND_SOC_DAPM_MIC("AMIC", NULL),
 
        SND_SOC_DAPM_SPK("Main Speaker", NULL),
 };
@@ -148,12 +139,16 @@ static struct snd_soc_dapm_route audio_paths[] = {
        { "Main Speaker", NULL, "SPKOUTL" },
        { "Main Speaker", NULL, "SPKOUTR" },
 
-       { "MICBIAS", NULL, "Headset Mic" },
-       { "IN4L", NULL, "MICBIAS" },
-       { "IN4R", NULL, "MICBIAS" },
+       { "Headset Mic", NULL, "MICBIAS" },
+       { "IN4L", NULL, "Headset Mic" },
+       { "IN4R", NULL, "Headset Mic" },
+
+       { "AMIC", NULL, "MICBIAS" },
+       { "IN1L", NULL, "AMIC" },
+       { "IN1R", NULL, "AMIC" },
 
-       { "MICBIAS", NULL, "DMIC" },
-       { "DMICDAT", NULL, "MICBIAS" },
+       { "DMIC", NULL, "MICBIAS" },
+       { "DMICDAT", NULL, "DMIC" },
 };
 
 static struct snd_soc_jack speyside_wm8962_headset;
index 20b7f3b003a33d377991044fd4e2d71efba62353..143c705ac27b82fbefd61144be79089511c1bfd3 100644 (file)
@@ -548,9 +548,6 @@ static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
 
 static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
 {
-       const struct snd_soc_codec_driver *codec_drv;
-
-       codec_drv = codec->driver;
        return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
 }
 
@@ -868,10 +865,6 @@ static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
 
 static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
 {
-       const struct snd_soc_codec_driver *codec_drv;
-
-       codec_drv = codec->driver;
-
        if (codec->reg_def_copy)
                codec->reg_cache = kmemdup(codec->reg_def_copy,
                                           codec->reg_size, GFP_KERNEL);
index ef69f5a0270991e7990055b109282cd6e66afa08..a58c1fc966eb69d44762c83e0f5a6936082bf071 100644 (file)
@@ -106,7 +106,7 @@ static int format_register_str(struct snd_soc_codec *codec,
        if (wordsize + regsize + 2 + 1 != len)
                return -EINVAL;
 
-       ret = snd_soc_read(codec , reg);
+       ret = snd_soc_read(codec, reg);
        if (ret < 0) {
                memset(regbuf, 'X', regsize);
                regbuf[regsize] = '\0';
@@ -144,7 +144,7 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
                step = codec->driver->reg_cache_step;
 
        for (i = 0; i < codec->driver->reg_cache_size; i += step) {
-               if (codec->readable_register && !codec->readable_register(codec, i))
+               if (!snd_soc_codec_readable_register(codec, i))
                        continue;
                if (codec->driver->display_register) {
                        count += codec->driver->display_register(codec, buf + count,
@@ -245,7 +245,6 @@ static ssize_t codec_reg_write_file(struct file *file,
        size_t buf_size;
        char *start = buf;
        unsigned long reg, value;
-       int step = 1;
        struct snd_soc_codec *codec = file->private_data;
 
        buf_size = min(count, (sizeof(buf)-1));
@@ -253,9 +252,6 @@ static ssize_t codec_reg_write_file(struct file *file,
                return -EFAULT;
        buf[buf_size] = 0;
 
-       if (codec->driver->reg_cache_step)
-               step = codec->driver->reg_cache_step;
-
        while (*start == ' ')
                start++;
        reg = simple_strtoul(start, &start, 16);
@@ -957,6 +953,8 @@ static int soc_probe_codec(struct snd_soc_card *card,
                snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
                                          driver->num_dapm_widgets);
 
+       codec->dapm.idle_bias_off = driver->idle_bias_off;
+
        if (driver->probe) {
                ret = driver->probe(codec);
                if (ret < 0) {
@@ -1319,6 +1317,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
        struct snd_soc_codec *codec;
        struct snd_soc_codec_conf *codec_conf;
        enum snd_soc_compress_type compress_type;
+       struct snd_soc_dai_link *dai_link;
        int ret, i, order;
 
        mutex_lock(&card->mutex);
@@ -1431,6 +1430,26 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
                                        card->num_dapm_routes);
 
+       for (i = 0; i < card->num_links; i++) {
+               dai_link = &card->dai_link[i];
+
+               if (dai_link->dai_fmt) {
+                       ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
+                                                 dai_link->dai_fmt);
+                       if (ret != 0)
+                               dev_warn(card->rtd[i].codec_dai->dev,
+                                        "Failed to set DAI format: %d\n",
+                                        ret);
+
+                       ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
+                                                 dai_link->dai_fmt);
+                       if (ret != 0)
+                               dev_warn(card->rtd[i].cpu_dai->dev,
+                                        "Failed to set DAI format: %d\n",
+                                        ret);
+               }
+       }
+
        snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
                 "%s", card->name);
        snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
@@ -2680,7 +2699,7 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
        if (dai->driver && dai->driver->ops->set_sysclk)
                return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
        else if (dai->codec && dai->codec->driver->set_sysclk)
-               return dai->codec->driver->set_sysclk(dai->codec, clk_id,
+               return dai->codec->driver->set_sysclk(dai->codec, clk_id, 0,
                                                      freq, dir);
        else
                return -EINVAL;
@@ -2691,16 +2710,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
  * snd_soc_codec_set_sysclk - configure CODEC system or master clock.
  * @codec: CODEC
  * @clk_id: DAI specific clock ID
+ * @source: Source for the clock
  * @freq: new clock frequency in Hz
  * @dir: new clock direction - input/output.
  *
  * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
  */
 int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
-       unsigned int freq, int dir)
+                            int source, unsigned int freq, int dir)
 {
        if (codec->driver->set_sysclk)
-               return codec->driver->set_sysclk(codec, clk_id, freq, dir);
+               return codec->driver->set_sysclk(codec, clk_id, source,
+                                                freq, dir);
        else
                return -EINVAL;
 }
@@ -3153,6 +3174,7 @@ int snd_soc_register_platform(struct device *dev,
        platform->driver = platform_drv;
        platform->dapm.dev = dev;
        platform->dapm.platform = platform;
+       platform->dapm.stream_event = platform_drv->stream_event;
 
        mutex_lock(&client_mutex);
        list_add(&platform->list, &platform_list);
@@ -3265,6 +3287,7 @@ int snd_soc_register_codec(struct device *dev,
        codec->dapm.dev = dev;
        codec->dapm.codec = codec;
        codec->dapm.seq_notifier = codec_drv->seq_notifier;
+       codec->dapm.stream_event = codec_drv->stream_event;
        codec->dev = dev;
        codec->driver = codec_drv;
        codec->num_dai = num_dai;
index d67c637557a784a2832676b814e71c0b1b7f1fc3..c277228ec967e3fc665abda1ea85c93a9353c9d7 100644 (file)
@@ -48,6 +48,8 @@
 
 #include <trace/events/asoc.h>
 
+#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
+
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
        [snd_soc_dapm_pre] = 0,
@@ -443,6 +445,11 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
                        if (path->name != (char *)w->kcontrol_news[i].name)
                                continue;
 
+                       if (w->kcontrols[i]) {
+                               path->kcontrol = w->kcontrols[i];
+                               continue;
+                       }
+
                        wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
                                    sizeof(struct snd_soc_dapm_widget *),
                        wlist = kzalloc(wlistsize, GFP_KERNEL);
@@ -579,8 +586,8 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
                                        name + prefix_len, prefix);
                ret = snd_ctl_add(card, kcontrol);
                if (ret < 0) {
-                       dev_err(dapm->dev,
-                               "asoc: failed to add kcontrol %s\n", w->name);
+                       dev_err(dapm->dev, "failed to add kcontrol %s: %d\n",
+                               w->name, ret);
                        kfree(wlist);
                        return ret;
                }
@@ -644,6 +651,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
        struct snd_soc_dapm_path *path;
        int con = 0;
 
+       DAPM_UPDATE_STAT(widget, path_checks);
+
        if (widget->id == snd_soc_dapm_supply)
                return 0;
 
@@ -668,6 +677,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
        }
 
        list_for_each_entry(path, &widget->sinks, list_source) {
+               DAPM_UPDATE_STAT(widget, neighbour_checks);
+
                if (path->weak)
                        continue;
 
@@ -692,6 +703,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
        struct snd_soc_dapm_path *path;
        int con = 0;
 
+       DAPM_UPDATE_STAT(widget, path_checks);
+
        if (widget->id == snd_soc_dapm_supply)
                return 0;
 
@@ -721,6 +734,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
        }
 
        list_for_each_entry(path, &widget->sources, list_sink) {
+               DAPM_UPDATE_STAT(widget, neighbour_checks);
+
                if (path->weak)
                        continue;
 
@@ -762,6 +777,8 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
 {
        int in, out;
 
+       DAPM_UPDATE_STAT(w, power_checks);
+
        in = is_connected_input_ep(w);
        dapm_clear_walk(w->dapm);
        out = is_connected_output_ep(w);
@@ -774,6 +791,8 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
 {
        int in;
 
+       DAPM_UPDATE_STAT(w, power_checks);
+
        if (w->active) {
                in = is_connected_input_ep(w);
                dapm_clear_walk(w->dapm);
@@ -788,6 +807,8 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
 {
        int out;
 
+       DAPM_UPDATE_STAT(w, power_checks);
+
        if (w->active) {
                out = is_connected_output_ep(w);
                dapm_clear_walk(w->dapm);
@@ -803,8 +824,12 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
        struct snd_soc_dapm_path *path;
        int power = 0;
 
+       DAPM_UPDATE_STAT(w, power_checks);
+
        /* Check if one of our outputs is connected */
        list_for_each_entry(path, &w->sinks, list_source) {
+               DAPM_UPDATE_STAT(w, neighbour_checks);
+
                if (path->weak)
                        continue;
 
@@ -1172,6 +1197,65 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
        }
 }
 
+static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
+                                 struct list_head *up_list,
+                                 struct list_head *down_list)
+{
+       struct snd_soc_dapm_context *d;
+       int power;
+
+       switch (w->id) {
+       case snd_soc_dapm_pre:
+               dapm_seq_insert(w, down_list, false);
+               break;
+       case snd_soc_dapm_post:
+               dapm_seq_insert(w, up_list, true);
+               break;
+
+       default:
+               if (!w->power_check)
+                       break;
+
+               if (!w->force)
+                       power = w->power_check(w);
+               else
+                       power = 1;
+
+               if (power) {
+                       d = w->dapm;
+
+                       /* Supplies and micbiases only bring the
+                        * context up to STANDBY as unless something
+                        * else is active and passing audio they
+                        * generally don't require full power.
+                        */
+                       switch (w->id) {
+                       case snd_soc_dapm_supply:
+                       case snd_soc_dapm_micbias:
+                               if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
+                                       d->target_bias_level = SND_SOC_BIAS_STANDBY;
+                               break;
+                       default:
+                               d->target_bias_level = SND_SOC_BIAS_ON;
+                               break;
+                       }
+               }
+
+               if (w->power == power)
+                       break;
+
+               trace_snd_soc_dapm_widget_power(w, power);
+
+               if (power)
+                       dapm_seq_insert(w, up_list, true);
+               else
+                       dapm_seq_insert(w, down_list, false);
+
+               w->power = power;
+               break;
+       }
+}
+
 /*
  * Scan each dapm widget for complete audio path.
  * A complete path is a route that has valid endpoints i.e.:-
@@ -1190,7 +1274,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
        LIST_HEAD(down_list);
        LIST_HEAD(async_domain);
        enum snd_soc_bias_level bias;
-       int power;
 
        trace_snd_soc_dapm_start(card);
 
@@ -1203,61 +1286,13 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                }
        }
 
+       memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
+
        /* Check which widgets we need to power and store them in
         * lists indicating if they should be powered up or down.
         */
        list_for_each_entry(w, &card->widgets, list) {
-               switch (w->id) {
-               case snd_soc_dapm_pre:
-                       dapm_seq_insert(w, &down_list, false);
-                       break;
-               case snd_soc_dapm_post:
-                       dapm_seq_insert(w, &up_list, true);
-                       break;
-
-               default:
-                       if (!w->power_check)
-                               continue;
-
-                       if (!w->force)
-                               power = w->power_check(w);
-                       else
-                               power = 1;
-
-                       if (power) {
-                               d = w->dapm;
-
-                               /* Supplies and micbiases only bring
-                                * the context up to STANDBY as unless
-                                * something else is active and
-                                * passing audio they generally don't
-                                * require full power.
-                                */
-                               switch (w->id) {
-                               case snd_soc_dapm_supply:
-                               case snd_soc_dapm_micbias:
-                                       if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
-                                               d->target_bias_level = SND_SOC_BIAS_STANDBY;
-                                       break;
-                               default:
-                                       d->target_bias_level = SND_SOC_BIAS_ON;
-                                       break;
-                               }
-                       }
-
-                       if (w->power == power)
-                               continue;
-
-                       trace_snd_soc_dapm_widget_power(w, power);
-
-                       if (power)
-                               dapm_seq_insert(w, &up_list, true);
-                       else
-                               dapm_seq_insert(w, &down_list, false);
-
-                       w->power = power;
-                       break;
-               }
+               dapm_power_one_widget(w, &up_list, &down_list);
        }
 
        /* If there are no DAPM widgets then try to figure out power from the
@@ -1286,14 +1321,18 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                }
        }
 
-       /* Force all contexts in the card to the same bias state */
+       /* Force all contexts in the card to the same bias state if
+        * they're not ground referenced.
+        */
        bias = SND_SOC_BIAS_OFF;
        list_for_each_entry(d, &card->dapm_list, list)
                if (d->target_bias_level > bias)
                        bias = d->target_bias_level;
        list_for_each_entry(d, &card->dapm_list, list)
-               d->target_bias_level = bias;
+               if (!d->idle_bias_off)
+                       d->target_bias_level = bias;
 
+       trace_snd_soc_dapm_walk_done(card);
 
        /* Run all the bias changes in parallel */
        list_for_each_entry(d, &dapm->card->dapm_list, list)
@@ -1556,7 +1595,6 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
                /* found, now check type */
                found = 1;
                path->connect = connect;
-               break;
        }
 
        if (found)
@@ -2584,7 +2622,7 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
        {
                if (!w->sname || w->dapm != dapm)
                        continue;
-               dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
+               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)) {
                        switch(event) {
@@ -2604,6 +2642,10 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
        }
 
        dapm_power_widgets(dapm, event);
+
+       /* do we need to notify any clients that DAPM stream is complete */
+       if (dapm->stream_event)
+               dapm->stream_event(dapm, event);
 }
 
 /**
index a62f7dd4ba96bcd266cd98e468d3248fe87ee096..66fcccd79efe9a2cbc8aa591d491f0f15fbc378f 100644 (file)
 
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <sound/soc.h>
 
 #include <trace/events/asoc.h>
 
-#ifdef CONFIG_SPI_MASTER
-static int do_spi_write(void *control, const char *data, int len)
-{
-       struct spi_device *spi = control;
-       int ret;
-
-       ret = spi_write(spi, data, len);
-       if (ret < 0)
-               return ret;
-
-       return len;
-}
-#endif
-
-static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
-                      unsigned int value, const void *data, int len)
+#ifdef CONFIG_REGMAP
+static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
+                   unsigned int value)
 {
        int ret;
 
@@ -49,13 +37,7 @@ static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
                return 0;
        }
 
-       ret = codec->hw_write(codec->control_data, data, len);
-       if (ret == len)
-               return 0;
-       if (ret < 0)
-               return ret;
-       else
-               return -EIO;
+       return regmap_write(codec->control_data, reg, value);
 }
 
 static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
@@ -69,8 +51,11 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
                if (codec->cache_only)
                        return -1;
 
-               BUG_ON(!codec->hw_read);
-               return codec->hw_read(codec, reg);
+               ret = regmap_read(codec->control_data, reg, &val);
+               if (ret == 0)
+                       return val;
+               else
+                       return ret;
        }
 
        ret = snd_soc_cache_read(codec, reg, &val);
@@ -79,202 +64,18 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
        return val;
 }
 
-static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
-                             unsigned int value)
-{
-       u16 data;
-
-       data = cpu_to_be16((reg << 12) | (value & 0xffffff));
-
-       return do_hw_write(codec, reg, value, &data, 2);
-}
-
-static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
-                            unsigned int value)
-{
-       u16 data;
-
-       data = cpu_to_be16((reg << 9) | (value & 0x1ff));
-
-       return do_hw_write(codec, reg, value, &data, 2);
-}
-
-static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
-                            unsigned int value)
-{
-       u8 data[2];
-
-       reg &= 0xff;
-       data[0] = reg;
-       data[1] = value & 0xff;
-
-       return do_hw_write(codec, reg, value, data, 2);
-}
-
-static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
-                             unsigned int value)
-{
-       u8 data[3];
-       u16 val = cpu_to_be16(value);
-
-       data[0] = reg;
-       memcpy(&data[1], &val, sizeof(val));
-
-       return do_hw_write(codec, reg, value, data, 3);
-}
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int do_i2c_read(struct snd_soc_codec *codec,
-                               void *reg, int reglen,
-                               void *data, int datalen)
-{
-       struct i2c_msg xfer[2];
-       int ret;
-       struct i2c_client *client = codec->control_data;
-
-       /* Write register */
-       xfer[0].addr = client->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = reglen;
-       xfer[0].buf = reg;
-
-       /* Read data */
-       xfer[1].addr = client->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = datalen;
-       xfer[1].buf = data;
-
-       ret = i2c_transfer(client->adapter, xfer, 2);
-       if (ret == 2)
-               return 0;
-       else if (ret < 0)
-               return ret;
-       else
-               return -EIO;
-}
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
-                                        unsigned int r)
-{
-       u8 reg = r;
-       u8 data;
-       int ret;
-
-       ret = do_i2c_read(codec, &reg, 1, &data, 1);
-       if (ret < 0)
-               return 0;
-       return data;
-}
-#else
-#define snd_soc_8_8_read_i2c NULL
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
-                                         unsigned int r)
-{
-       u8 reg = r;
-       u16 data;
-       int ret;
-
-       ret = do_i2c_read(codec, &reg, 1, &data, 2);
-       if (ret < 0)
-               return 0;
-       return (data >> 8) | ((data & 0xff) << 8);
-}
-#else
-#define snd_soc_8_16_read_i2c NULL
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
-                                         unsigned int r)
-{
-       u16 reg = r;
-       u8 data;
-       int ret;
-
-       ret = do_i2c_read(codec, &reg, 2, &data, 1);
-       if (ret < 0)
-               return 0;
-       return data;
-}
-#else
-#define snd_soc_16_8_read_i2c NULL
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static unsigned int snd_soc_16_8_read_spi(struct snd_soc_codec *codec,
-                                         unsigned int r)
-{
-       struct spi_device *spi = codec->control_data;
-
-       const u16 reg = cpu_to_be16(r | 0x100);
-       u8 data;
-       int ret;
-
-       ret = spi_write_then_read(spi, &reg, 2, &data, 1);
-       if (ret < 0)
-               return 0;
-       return data;
-}
-#else
-#define snd_soc_16_8_read_spi NULL
-#endif
-
-static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
-                             unsigned int value)
-{
-       u8 data[3];
-       u16 rval = cpu_to_be16(reg);
-
-       memcpy(data, &rval, sizeof(rval));
-       data[2] = value;
-
-       return do_hw_write(codec, reg, value, data, 3);
-}
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
-                                          unsigned int r)
-{
-       u16 reg = cpu_to_be16(r);
-       u16 data;
-       int ret;
-
-       ret = do_i2c_read(codec, &reg, 2, &data, 2);
-       if (ret < 0)
-               return 0;
-       return be16_to_cpu(data);
-}
-#else
-#define snd_soc_16_16_read_i2c NULL
-#endif
-
-static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
-                              unsigned int value)
-{
-       u16 data[2];
-
-       data[0] = cpu_to_be16(reg);
-       data[1] = cpu_to_be16(value);
-
-       return do_hw_write(codec, reg, value, data, sizeof(data));
-}
-
 /* Primitive bulk write support for soc-cache.  The data pointed to by
- * `data' needs to already be in the form the hardware expects
- * including any leading register specific data.  Any data written
- * through this function will not go through the cache as it only
- * handles writing to volatile or out of bounds registers.
+ * `data' needs to already be in the form the hardware expects.  Any
+ * data written through this function will not go through the cache as
+ * it only handles writing to volatile or out of bounds registers.
+ *
+ * This is currently only supported for devices using the regmap API
+ * wrappers.
  */
-static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg,
+static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
+                                    unsigned int reg,
                                     const void *data, size_t len)
 {
-       int ret;
-
        /* To ensure that we don't get out of sync with the cache, check
         * whether the base register is volatile or if we've directly asked
         * to bypass the cache.  Out of bounds registers are considered
@@ -285,68 +86,9 @@ static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int r
            && reg < codec->driver->reg_cache_size)
                return -EINVAL;
 
-       switch (codec->control_type) {
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-       case SND_SOC_I2C:
-               ret = i2c_master_send(to_i2c_client(codec->dev), data, len);
-               break;
-#endif
-#if defined(CONFIG_SPI_MASTER)
-       case SND_SOC_SPI:
-               ret = spi_write(to_spi_device(codec->dev), data, len);
-               break;
-#endif
-       default:
-               BUG();
-       }
-
-       if (ret == len)
-               return 0;
-       if (ret < 0)
-               return ret;
-       else
-               return -EIO;
+       return regmap_raw_write(codec->control_data, reg, data, len);
 }
 
-static struct {
-       int addr_bits;
-       int data_bits;
-       int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
-       unsigned int (*read)(struct snd_soc_codec *, unsigned int);
-       unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
-       unsigned int (*spi_read)(struct snd_soc_codec *, unsigned int);
-} io_types[] = {
-       {
-               .addr_bits = 4, .data_bits = 12,
-               .write = snd_soc_4_12_write,
-       },
-       {
-               .addr_bits = 7, .data_bits = 9,
-               .write = snd_soc_7_9_write,
-       },
-       {
-               .addr_bits = 8, .data_bits = 8,
-               .write = snd_soc_8_8_write,
-               .i2c_read = snd_soc_8_8_read_i2c,
-       },
-       {
-               .addr_bits = 8, .data_bits = 16,
-               .write = snd_soc_8_16_write,
-               .i2c_read = snd_soc_8_16_read_i2c,
-       },
-       {
-               .addr_bits = 16, .data_bits = 8,
-               .write = snd_soc_16_8_write,
-               .i2c_read = snd_soc_16_8_read_i2c,
-               .spi_read = snd_soc_16_8_read_spi,
-       },
-       {
-               .addr_bits = 16, .data_bits = 16,
-               .write = snd_soc_16_16_write,
-               .i2c_read = snd_soc_16_16_read_i2c,
-       },
-};
-
 /**
  * snd_soc_codec_set_cache_io: Set up standard I/O functions.
  *
@@ -370,50 +112,51 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
                               int addr_bits, int data_bits,
                               enum snd_soc_control_type control)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(io_types); i++)
-               if (io_types[i].addr_bits == addr_bits &&
-                   io_types[i].data_bits == data_bits)
-                       break;
-       if (i == ARRAY_SIZE(io_types)) {
-               printk(KERN_ERR
-                      "No I/O functions for %d bit address %d bit data\n",
-                      addr_bits, data_bits);
-               return -EINVAL;
-       }
+       struct regmap_config config;
 
-       codec->write = io_types[i].write;
+       memset(&config, 0, sizeof(config));
+       codec->write = hw_write;
        codec->read = hw_read;
        codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
 
+       config.reg_bits = addr_bits;
+       config.val_bits = data_bits;
+
        switch (control) {
+#if defined(CONFIG_REGMAP_I2C) || defined(CONFIG_REGMAP_I2C_MODULE)
        case SND_SOC_I2C:
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-               codec->hw_write = (hw_write_t)i2c_master_send;
-#endif
-               if (io_types[i].i2c_read)
-                       codec->hw_read = io_types[i].i2c_read;
-
-               codec->control_data = container_of(codec->dev,
-                                                  struct i2c_client,
-                                                  dev);
+               codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
+                                                     &config);
                break;
+#endif
 
+#if defined(CONFIG_REGMAP_SPI) || defined(CONFIG_REGMAP_SPI_MODULE)
        case SND_SOC_SPI:
-#ifdef CONFIG_SPI_MASTER
-               codec->hw_write = do_spi_write;
+               codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
+                                                     &config);
+               break;
 #endif
-               if (io_types[i].spi_read)
-                       codec->hw_read = io_types[i].spi_read;
 
-               codec->control_data = container_of(codec->dev,
-                                                  struct spi_device,
-                                                  dev);
+       case SND_SOC_REGMAP:
+               /* Device has made its own regmap arrangements */
                break;
+
+       default:
+               return -EINVAL;
        }
 
+       if (IS_ERR(codec->control_data))
+               return PTR_ERR(codec->control_data);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
-
+#else
+int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
+                              int addr_bits, int data_bits,
+                              enum snd_soc_control_type control)
+{
+       return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
+#endif
index 2879c883eebc2161d0c1ff3fdc14e764cde9ac33..8eb0f0711f8c161d809983149b9f9739bbcdca08 100644 (file)
 #include <sound/soc.h>
 #include <sound/initval.h>
 
-static DEFINE_MUTEX(pcm_mutex);
-
-static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
+static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
+                                       struct snd_soc_dai *soc_dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
-       if (!codec_dai->driver->symmetric_rates &&
-           !cpu_dai->driver->symmetric_rates &&
+       if (!soc_dai->driver->symmetric_rates &&
            !rtd->dai_link->symmetric_rates)
                return 0;
 
@@ -45,19 +41,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
         * the second can need to get its constraints before the first has
         * picked a rate.  Complain and allow the application to carry on.
         */
-       if (!rtd->rate) {
-               dev_warn(&rtd->dev,
+       if (!soc_dai->rate) {
+               dev_warn(soc_dai->dev,
                         "Not enforcing symmetric_rates due to race\n");
                return 0;
        }
 
-       dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
+       dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
 
        ret = snd_pcm_hw_constraint_minmax(substream->runtime,
                                           SNDRV_PCM_HW_PARAM_RATE,
-                                          rtd->rate, rtd->rate);
+                                          soc_dai->rate, soc_dai->rate);
        if (ret < 0) {
-               dev_err(&rtd->dev,
+               dev_err(soc_dai->dev,
                        "Unable to apply rate symmetry constraint: %d\n", ret);
                return ret;
        }
@@ -187,8 +183,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        }
 
        /* Symmetry only applies if we've already got an active stream. */
-       if (cpu_dai->active || codec_dai->active) {
-               ret = soc_pcm_apply_symmetry(substream);
+       if (cpu_dai->active) {
+               ret = soc_pcm_apply_symmetry(substream, cpu_dai);
+               if (ret != 0)
+                       goto config_err;
+       }
+
+       if (codec_dai->active) {
+               ret = soc_pcm_apply_symmetry(substream, codec_dai);
                if (ret != 0)
                        goto config_err;
        }
@@ -290,8 +292,12 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        codec_dai->active--;
        codec->active--;
 
-       if (!cpu_dai->active && !codec_dai->active)
-               rtd->rate = 0;
+       /* clear the corresponding DAIs rate when inactive */
+       if (!cpu_dai->active)
+               cpu_dai->rate = 0;
+
+       if (!codec_dai->active)
+               codec_dai->rate = 0;
 
        /* Muting the DAC suppresses artifacts caused during digital
         * shutdown, for example from stopping clocks.
@@ -449,7 +455,9 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       rtd->rate = params_rate(params);
+       /* store the rate for each DAIs */
+       cpu_dai->rate = params_rate(params);
+       codec_dai->rate = params_rate(params);
 
 out:
        mutex_unlock(&rtd->pcm_mutex);